diff --git a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs index e8d593ec393d4b58b8e8d36fe36c17a11b47a63d..bae012123fc3226fe7c20a983c81a53d0098f97b 100644 --- a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs +++ b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs @@ -524,13 +524,7 @@ DagState uniqifyState(DagState state) } else { - BoundDagDecision selectDecision(DagState s) - { - // Our simple heuristic is to perform the first test of the first possible matched case - return s.Cases[0].Decisions[0]; - } - - switch (state.SelectedDecision = selectDecision(state)) + switch (state.SelectedDecision = state.ComputeSelectedDecision()) { case BoundDagEvaluation e: state.TrueBranch = uniqifyState(RemoveEvaluation(state.Cases, e)); @@ -643,6 +637,7 @@ BoundDecisionDag finalState(SyntaxNode syntax, LabelSymbol label, ImmutableArray finalStates.Free(); Debug.Assert(initialState.Dag != null); + // Note: It is useful for debugging the dag state table construction to view `initialState.Dump()` here. return initialState.Dag; } @@ -775,6 +770,10 @@ BoundDecisionDag finalState(SyntaxNode syntax, LabelSymbol label, ImmutableArray trueDecisionPermitsTrueOther = false; // if v!=null is true, then v==null cannot succeed falseDecisionImpliesTrueOther = true; // if v!=null is false, then v==null has been proven true break; + case BoundNonNullDecision n2: + trueDecisionImpliesTrueOther = true; + falseDecisionPermitsTrueOther = false; + break; default: // Once v!=null fails, it must fail a type test falseDecisionPermitsTrueOther = false; @@ -885,6 +884,10 @@ private static PartialCaseDecision RemoveEvaluation(PartialCaseDecision c, Bound Bindings: c.Bindings, WhenClause: c.WhenClause, CaseLabel: c.CaseLabel); } + /// + /// The state at a given node of the decision acyclic graph. This is used during computation of the state machine, + /// and contains a representation of the meaning of the state. + /// private class DagState { public readonly ImmutableArray Cases; @@ -904,7 +907,134 @@ public DagState(ImmutableArray cases) // After the entire graph of DagState objects is complete, we translate each into its Dag. public BoundDecisionDag Dag; + + // Compute a decision to use at the root of the generated decision tree. + internal BoundDagDecision ComputeSelectedDecision() + { + // Our simple heuristic is to perform the first test of the first possible matched case + var choice = Cases[0].Decisions[0]; + + // But if that test is a null check, it would be redundant with a following + // type test. We apply this refinement only when there is exactly one case, because + // when there are multiple cases the null check is likely to be shared. + if (choice.Kind == BoundKind.NonNullDecision && + Cases.Length == 1 && + Cases[0].Decisions.Length > 1) + { + var choice2 = Cases[0].Decisions[1]; + if (choice2.Kind == BoundKind.TypeDecision) + { + return choice2; + } + } + + return choice; + } + +#if DEBUG + /// + /// Starting with `this` state, produce a human-readable description of the state tables. + /// This is very useful for debugging and optimizing the dag state construction. + /// + internal string Dump() + { + var printed = PooledHashSet.GetInstance(); + + int nextStateNumber = 0; + var workQueue = ArrayBuilder.GetInstance(); + var stateIdentifierMap = PooledDictionary.GetInstance(); + int stateIdentifier(DagState state) + { + if (stateIdentifierMap.TryGetValue(state, out int value)) + { + return value; + } + else + { + value = stateIdentifierMap[state] = ++nextStateNumber; + workQueue.Push(state); + } + + return value; + } + + int nextTempNumber = 0; + var tempIdentifierMap = PooledDictionary.GetInstance(); + int tempIdentifier(BoundDagEvaluation e) + { + return (e == null) ? 0 : tempIdentifierMap.TryGetValue(e, out int value) ? value : tempIdentifierMap[e] = ++nextTempNumber; + } + + string tempName(BoundDagTemp t) + { + return $"t{tempIdentifier(t.Source)}{(t.Index != 0 ? $".{t.Index.ToString()}" : "")}"; + } + + var resultBuilder = PooledStringBuilder.GetInstance(); + var result = resultBuilder.Builder; + stateIdentifier(this); // push the start node onto the work queue + + while (workQueue.Count != 0) + { + var state = workQueue.Pop(); + if (!printed.Add(state)) + { + continue; + } + + result.AppendLine($"State " + stateIdentifier(state)); + foreach (PartialCaseDecision cd in state.Cases) + { + result.Append($" [{cd.Syntax}]"); + foreach (BoundDagDecision d in cd.Decisions) + { + result.Append($" {dump(d)}"); + } + + result.AppendLine(); + } + + if (state.SelectedDecision != null) + { + result.AppendLine($" Decision: {dump(state.SelectedDecision)}"); + } + + if (state.TrueBranch != null) + { + result.AppendLine($" TrueBranch: {stateIdentifier(state.TrueBranch)}"); + } + + if (state.FalseBranch != null) + { + result.AppendLine($" FalseBranch: {stateIdentifier(state.FalseBranch)}"); + } + } + + workQueue.Free(); + printed.Free(); + stateIdentifierMap.Free(); + tempIdentifierMap.Free(); + return resultBuilder.ToStringAndFree(); + + string dump(BoundDagDecision d) + { + switch (d) + { + case BoundDagTypeEvaluation a: + return $"t{tempIdentifier(a)}={a.Kind}({a.Type.ToString()})"; + case BoundDagEvaluation e: + return $"t{tempIdentifier(e)}={e.Kind}"; + case BoundTypeDecision b: + return $"?{d.Kind}({b.Type.ToString()}, {tempName(d.Input)})"; + case BoundNonNullValueDecision v: + return $"?{d.Kind}({v.Value.ToString()}, {tempName(d.Input)})"; + default: + return $"?{d.Kind}({tempName(d.Input)})"; + } + } + } } +#endif /// /// An equivalence relation between dag states used to dedup the states during dag construction. diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs index ef89f04698e35f43892c4ff438851df390465696..3d87b1742f7b023b426760fdee66fa59a3f96c8c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs @@ -149,6 +149,7 @@ private void LowerDecisionDag(ImmutableArray sortedNodes) /// /// Translate the decision tree for node, given that it will be followed by the translation for nextNode. + /// This knowledge allows us to fall through to nextNode instead of producing a goto statement to get there. /// private void LowerDecisionDagNode(BoundDecisionDag node, BoundDecisionDag nextNode) { diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs index 8fec2fa33c62f22fd5141bc2b3328a43155270f9..99a663d78c42cd255e301072c076eb5ba4c201c8 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs @@ -203,7 +203,6 @@ protected BoundExpression LowerDecision(BoundDagDecision decision) } else { - // PROTOTYPE(patterns2): combine null test and type test when possible for improved code return _localRewriter.MakeNullCheck(d.Syntax, input, input.Type.IsNullableType() ? BinaryOperatorKind.NullableNullNotEqual : BinaryOperatorKind.NotEqual); } @@ -211,6 +210,7 @@ protected BoundExpression LowerDecision(BoundDagDecision decision) case BoundTypeDecision d: { + // Note that this tests for non-null as a side-effect. We depend on that to sometimes avoid the null check. return _factory.Is(input, d.Type); } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs index 63256a687b2a8eb0eb713636033dfa95f61451b4..00fcdfa1190199d672d245ff1aa6852f57011a15 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/PatternTests.cs @@ -142,7 +142,6 @@ static void M1(int? x) ); } - // PROTOTYPE(patterns2): code quality has regressed for this test because the lowering strategy reifies the boolean result of the if expression. [Fact, WorkItem(17266, "https://github.com/dotnet/roslyn/issues/17266")] public void DoubleEvaluation01() { @@ -200,6 +199,28 @@ .maxstack 1 IL_002a: nop IL_002b: ret }"); + + compilation = CreateCompilation(source, options: TestOptions.ReleaseExe); + compilation.VerifyDiagnostics(); + compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput); + compVerifier.VerifyIL("C.Main", +@"{ + // Code size 30 (0x1e) + .maxstack 1 + .locals init (int V_0, //index + int? V_1) + IL_0000: call ""int? C.TryGet()"" + IL_0005: stloc.1 + IL_0006: ldloca.s V_1 + IL_0008: call ""bool int?.HasValue.get"" + IL_000d: brfalse.s IL_001d + IL_000f: ldloca.s V_1 + IL_0011: call ""int int?.GetValueOrDefault()"" + IL_0016: stloc.0 + IL_0017: ldloc.0 + IL_0018: call ""void System.Console.WriteLine(int)"" + IL_001d: ret +}"); } [Fact, WorkItem(19122, "https://github.com/dotnet/roslyn/issues/19122")] @@ -248,7 +269,7 @@ public Guid GetId(T t) var compVerifier = CompileAndVerify(compilation); compVerifier.VerifyIL("X.Y", @"{ - // Code size 71 (0x47) + // Code size 63 (0x3f) .maxstack 3 .locals init (U V_0, //u bool V_1, @@ -264,26 +285,23 @@ .maxstack 3 IL_0018: stloc.2 IL_0019: ldloc.2 IL_001a: box ""T"" - IL_001f: brfalse.s IL_003f - IL_0021: ldloc.2 - IL_0022: box ""T"" - IL_0027: isinst ""U"" - IL_002c: brfalse.s IL_003f - IL_002e: ldloc.2 - IL_002f: box ""T"" - IL_0034: unbox.any ""U"" - IL_0039: stloc.3 - IL_003a: ldloc.3 - IL_003b: stloc.0 - IL_003c: ldc.i4.1 - IL_003d: br.s IL_0040 - IL_003f: ldc.i4.0 - IL_0040: stloc.1 - IL_0041: ldloc.1 - IL_0042: brfalse.s IL_0046 - IL_0044: nop - IL_0045: nop - IL_0046: ret + IL_001f: isinst ""U"" + IL_0024: brfalse.s IL_0037 + IL_0026: ldloc.2 + IL_0027: box ""T"" + IL_002c: unbox.any ""U"" + IL_0031: stloc.3 + IL_0032: ldloc.3 + IL_0033: stloc.0 + IL_0034: ldc.i4.1 + IL_0035: br.s IL_0038 + IL_0037: ldc.i4.0 + IL_0038: stloc.1 + IL_0039: ldloc.1 + IL_003a: brfalse.s IL_003e + IL_003c: nop + IL_003d: nop + IL_003e: ret }"); } @@ -327,7 +345,7 @@ static void Main(string[] args) var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput); compVerifier.VerifyIL("Program.Main", @"{ - // Code size 113 (0x71) + // Code size 106 (0x6a) .maxstack 2 .locals init (Base V_0, //x Derived V_1, //y @@ -346,47 +364,43 @@ .maxstack 2 IL_0010: call ""void System.Console.WriteLine(bool)"" IL_0015: nop IL_0016: ldloc.0 - IL_0017: brfalse.s IL_002d - IL_0019: ldloc.0 - IL_001a: isinst ""Derived"" - IL_001f: brfalse.s IL_002d - IL_0021: ldloc.0 - IL_0022: castclass ""Derived"" - IL_0027: stloc.2 - IL_0028: ldloc.2 - IL_0029: stloc.1 - IL_002a: ldc.i4.1 - IL_002b: br.s IL_002e - IL_002d: ldc.i4.0 - IL_002e: call ""void System.Console.WriteLine(bool)"" - IL_0033: nop - IL_0034: ldloc.0 - IL_0035: stloc.s V_6 - IL_0037: ldloc.s V_6 - IL_0039: stloc.s V_4 - IL_003b: ldloc.s V_4 - IL_003d: brfalse.s IL_0061 - IL_003f: ldloc.s V_4 - IL_0041: isinst ""Derived"" - IL_0046: brfalse.s IL_0061 - IL_0048: ldloc.s V_4 - IL_004a: castclass ""Derived"" - IL_004f: stloc.s V_5 - IL_0051: br.s IL_0053 - IL_0053: ldloc.s V_5 - IL_0055: stloc.3 - IL_0056: br.s IL_0058 - IL_0058: ldc.i4.1 - IL_0059: call ""void System.Console.WriteLine(bool)"" - IL_005e: nop - IL_005f: br.s IL_0061 - IL_0061: ldloc.0 - IL_0062: isinst ""Derived"" - IL_0067: ldnull - IL_0068: cgt.un - IL_006a: call ""void System.Console.WriteLine(bool)"" - IL_006f: nop - IL_0070: ret + IL_0017: isinst ""Derived"" + IL_001c: brfalse.s IL_002a + IL_001e: ldloc.0 + IL_001f: castclass ""Derived"" + IL_0024: stloc.2 + IL_0025: ldloc.2 + IL_0026: stloc.1 + IL_0027: ldc.i4.1 + IL_0028: br.s IL_002b + IL_002a: ldc.i4.0 + IL_002b: call ""void System.Console.WriteLine(bool)"" + IL_0030: nop + IL_0031: ldloc.0 + IL_0032: stloc.s V_6 + IL_0034: ldloc.s V_6 + IL_0036: stloc.s V_4 + IL_0038: ldloc.s V_4 + IL_003a: isinst ""Derived"" + IL_003f: brfalse.s IL_005a + IL_0041: ldloc.s V_4 + IL_0043: castclass ""Derived"" + IL_0048: stloc.s V_5 + IL_004a: br.s IL_004c + IL_004c: ldloc.s V_5 + IL_004e: stloc.3 + IL_004f: br.s IL_0051 + IL_0051: ldc.i4.1 + IL_0052: call ""void System.Console.WriteLine(bool)"" + IL_0057: nop + IL_0058: br.s IL_005a + IL_005a: ldloc.0 + IL_005b: isinst ""Derived"" + IL_0060: ldnull + IL_0061: cgt.un + IL_0063: call ""void System.Console.WriteLine(bool)"" + IL_0068: nop + IL_0069: ret }"); } @@ -472,7 +486,7 @@ .maxstack 2 }"); compVerifier.VerifyIL("Program.P5", @"{ - // Code size 125 (0x7d) + // Code size 122 (0x7a) .maxstack 2 .locals init (object V_0, double V_1, @@ -485,7 +499,7 @@ .maxstack 2 IL_0003: ldloc.3 IL_0004: stloc.0 IL_0005: ldloc.0 - IL_0006: brfalse.s IL_0075 + IL_0006: brfalse.s IL_0072 IL_0008: ldloc.0 IL_0009: isinst ""double"" IL_000e: brfalse.s IL_0035 @@ -494,49 +508,47 @@ .maxstack 2 IL_0016: stloc.1 IL_0017: ldloc.1 IL_0018: call ""bool double.IsNaN(double)"" - IL_001d: brtrue.s IL_0061 + IL_001d: brtrue.s IL_005e IL_001f: ldloc.0 IL_0020: isinst ""double"" - IL_0025: brfalse.s IL_0075 + IL_0025: brfalse.s IL_0072 IL_0027: ldc.r8 3.14 IL_0030: ldloc.1 - IL_0031: beq.s IL_006b - IL_0033: br.s IL_0075 + IL_0031: beq.s IL_0068 + IL_0033: br.s IL_0072 IL_0035: ldloc.0 - IL_0036: brfalse.s IL_0075 - IL_0038: ldloc.0 - IL_0039: isinst ""float"" - IL_003e: brfalse.s IL_0075 - IL_0040: ldloc.0 - IL_0041: unbox.any ""float"" - IL_0046: stloc.2 - IL_0047: ldloc.2 - IL_0048: call ""bool float.IsNaN(float)"" - IL_004d: brtrue.s IL_0066 - IL_004f: ldloc.0 - IL_0050: isinst ""float"" - IL_0055: brfalse.s IL_0075 - IL_0057: ldc.r4 3.14 - IL_005c: ldloc.2 - IL_005d: beq.s IL_0070 - IL_005f: br.s IL_0075 - IL_0061: ldc.i4.1 - IL_0062: stloc.s V_4 - IL_0064: br.s IL_007a - IL_0066: ldc.i4.1 - IL_0067: stloc.s V_4 - IL_0069: br.s IL_007a - IL_006b: ldc.i4.1 - IL_006c: stloc.s V_4 - IL_006e: br.s IL_007a - IL_0070: ldc.i4.1 - IL_0071: stloc.s V_4 - IL_0073: br.s IL_007a - IL_0075: ldc.i4.0 - IL_0076: stloc.s V_4 - IL_0078: br.s IL_007a - IL_007a: ldloc.s V_4 - IL_007c: ret + IL_0036: isinst ""float"" + IL_003b: brfalse.s IL_0072 + IL_003d: ldloc.0 + IL_003e: unbox.any ""float"" + IL_0043: stloc.2 + IL_0044: ldloc.2 + IL_0045: call ""bool float.IsNaN(float)"" + IL_004a: brtrue.s IL_0063 + IL_004c: ldloc.0 + IL_004d: isinst ""float"" + IL_0052: brfalse.s IL_0072 + IL_0054: ldc.r4 3.14 + IL_0059: ldloc.2 + IL_005a: beq.s IL_006d + IL_005c: br.s IL_0072 + IL_005e: ldc.i4.1 + IL_005f: stloc.s V_4 + IL_0061: br.s IL_0077 + IL_0063: ldc.i4.1 + IL_0064: stloc.s V_4 + IL_0066: br.s IL_0077 + IL_0068: ldc.i4.1 + IL_0069: stloc.s V_4 + IL_006b: br.s IL_0077 + IL_006d: ldc.i4.1 + IL_006e: stloc.s V_4 + IL_0070: br.s IL_0077 + IL_0072: ldc.i4.0 + IL_0073: stloc.s V_4 + IL_0075: br.s IL_0077 + IL_0077: ldloc.s V_4 + IL_0079: ret }"); } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs index 931c21544e394cbd18322929598d3070e34d0d42..40a5d0c3c330bdd5cc77e8f53248065e1153a41f 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/SwitchTests.cs @@ -7933,23 +7933,20 @@ public static void M(object x) var compVerifier = CompileAndVerify(source, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: "1"); - // PROTOTYPE(patterns2): Need to restore code quality compVerifier.VerifyIL("Program.M", @"{ - // Code size 25 (0x19) + // Code size 22 (0x16) .maxstack 1 .locals init (object V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: brfalse.s IL_0018 - IL_0005: ldloc.0 - IL_0006: isinst ""int"" - IL_000b: brfalse.s IL_0018 - IL_000d: ldloc.0 - IL_000e: unbox.any ""int"" - IL_0013: call ""void System.Console.Write(int)"" - IL_0018: ret + IL_0003: isinst ""int"" + IL_0008: brfalse.s IL_0015 + IL_000a: ldloc.0 + IL_000b: unbox.any ""int"" + IL_0010: call ""void System.Console.Write(int)"" + IL_0015: ret }" ); compVerifier = CompileAndVerify(source, @@ -7957,7 +7954,7 @@ .locals init (object V_0) expectedOutput: "1"); compVerifier.VerifyIL("Program.M", @"{ - // Code size 39 (0x27) + // Code size 36 (0x24) .maxstack 1 .locals init (int V_0, //i object V_1, @@ -7969,22 +7966,20 @@ .maxstack 1 IL_0003: ldloc.3 IL_0004: stloc.1 IL_0005: ldloc.1 - IL_0006: brfalse.s IL_0026 - IL_0008: ldloc.1 - IL_0009: isinst ""int"" - IL_000e: brfalse.s IL_0026 - IL_0010: ldloc.1 - IL_0011: unbox.any ""int"" - IL_0016: stloc.2 - IL_0017: br.s IL_0019 - IL_0019: ldloc.2 - IL_001a: stloc.0 - IL_001b: br.s IL_001d - IL_001d: ldloc.0 - IL_001e: call ""void System.Console.Write(int)"" - IL_0023: nop - IL_0024: br.s IL_0026 - IL_0026: ret + IL_0006: isinst ""int"" + IL_000b: brfalse.s IL_0023 + IL_000d: ldloc.1 + IL_000e: unbox.any ""int"" + IL_0013: stloc.2 + IL_0014: br.s IL_0016 + IL_0016: ldloc.2 + IL_0017: stloc.0 + IL_0018: br.s IL_001a + IL_001a: ldloc.0 + IL_001b: call ""void System.Console.Write(int)"" + IL_0020: nop + IL_0021: br.s IL_0023 + IL_0023: ret }" ); } @@ -8017,24 +8012,21 @@ public static void M(object x) var compVerifier = CompileAndVerify(source, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: "1"); - // PROTOTYPE(patterns2): Need to restore code quality for this compVerifier.VerifyIL("Program.M", @"{ - // Code size 30 (0x1e) + // Code size 27 (0x1b) .maxstack 1 .locals init (object V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: brfalse.s IL_001d - IL_0005: ldloc.0 - IL_0006: isinst ""T"" - IL_000b: brfalse.s IL_001d - IL_000d: ldloc.0 - IL_000e: unbox.any ""T"" - IL_0013: box ""T"" - IL_0018: call ""void System.Console.Write(object)"" - IL_001d: ret + IL_0003: isinst ""T"" + IL_0008: brfalse.s IL_001a + IL_000a: ldloc.0 + IL_000b: unbox.any ""T"" + IL_0010: box ""T"" + IL_0015: call ""void System.Console.Write(object)"" + IL_001a: ret }" ); compVerifier = CompileAndVerify(source, @@ -8042,7 +8034,7 @@ .locals init (object V_0) expectedOutput: "1"); compVerifier.VerifyIL("Program.M", @"{ - // Code size 44 (0x2c) + // Code size 41 (0x29) .maxstack 1 .locals init (T V_0, //i object V_1, @@ -8054,23 +8046,21 @@ .maxstack 1 IL_0003: ldloc.3 IL_0004: stloc.1 IL_0005: ldloc.1 - IL_0006: brfalse.s IL_002b - IL_0008: ldloc.1 - IL_0009: isinst ""T"" - IL_000e: brfalse.s IL_002b - IL_0010: ldloc.1 - IL_0011: unbox.any ""T"" - IL_0016: stloc.2 - IL_0017: br.s IL_0019 - IL_0019: ldloc.2 - IL_001a: stloc.0 - IL_001b: br.s IL_001d - IL_001d: ldloc.0 - IL_001e: box ""T"" - IL_0023: call ""void System.Console.Write(object)"" - IL_0028: nop - IL_0029: br.s IL_002b - IL_002b: ret + IL_0006: isinst ""T"" + IL_000b: brfalse.s IL_0028 + IL_000d: ldloc.1 + IL_000e: unbox.any ""T"" + IL_0013: stloc.2 + IL_0014: br.s IL_0016 + IL_0016: ldloc.2 + IL_0017: stloc.0 + IL_0018: br.s IL_001a + IL_001a: ldloc.0 + IL_001b: box ""T"" + IL_0020: call ""void System.Console.Write(object)"" + IL_0025: nop + IL_0026: br.s IL_0028 + IL_0028: ret }" ); } @@ -8103,33 +8093,29 @@ public static void M(IComparable x) var compVerifier = CompileAndVerify(source, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: "1"); - // PROTOTYPE(patterns2): Need to restore code quality compVerifier.VerifyIL("Program.M", @"{ - // Code size 30 (0x1e) + // Code size 27 (0x1b) .maxstack 1 .locals init (System.IComparable V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: brfalse.s IL_001d - IL_0005: ldloc.0 - IL_0006: isinst ""T"" - IL_000b: brfalse.s IL_001d - IL_000d: ldloc.0 - IL_000e: unbox.any ""T"" - IL_0013: box ""T"" - IL_0018: call ""void System.Console.Write(object)"" - IL_001d: ret + IL_0003: isinst ""T"" + IL_0008: brfalse.s IL_001a + IL_000a: ldloc.0 + IL_000b: unbox.any ""T"" + IL_0010: box ""T"" + IL_0015: call ""void System.Console.Write(object)"" + IL_001a: ret }" ); compVerifier = CompileAndVerify(source, options: TestOptions.DebugDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: "1"); - // PROTOTYPE(patterns2): Need to restore code quality. compVerifier.VerifyIL("Program.M", @"{ - // Code size 44 (0x2c) + // Code size 41 (0x29) .maxstack 1 .locals init (T V_0, //i System.IComparable V_1, @@ -8141,29 +8127,26 @@ .maxstack 1 IL_0003: ldloc.3 IL_0004: stloc.1 IL_0005: ldloc.1 - IL_0006: brfalse.s IL_002b - IL_0008: ldloc.1 - IL_0009: isinst ""T"" - IL_000e: brfalse.s IL_002b - IL_0010: ldloc.1 - IL_0011: unbox.any ""T"" - IL_0016: stloc.2 - IL_0017: br.s IL_0019 - IL_0019: ldloc.2 - IL_001a: stloc.0 - IL_001b: br.s IL_001d - IL_001d: ldloc.0 - IL_001e: box ""T"" - IL_0023: call ""void System.Console.Write(object)"" - IL_0028: nop - IL_0029: br.s IL_002b - IL_002b: ret + IL_0006: isinst ""T"" + IL_000b: brfalse.s IL_0028 + IL_000d: ldloc.1 + IL_000e: unbox.any ""T"" + IL_0013: stloc.2 + IL_0014: br.s IL_0016 + IL_0016: ldloc.2 + IL_0017: stloc.0 + IL_0018: br.s IL_001a + IL_001a: ldloc.0 + IL_001b: box ""T"" + IL_0020: call ""void System.Console.Write(object)"" + IL_0025: nop + IL_0026: br.s IL_0028 + IL_0028: ret }" ); } - [Fact(Skip = "PROTOTYPE(patterns2): This test is sensitive to the precise code generated, which is currently in flux.")] - [WorkItem(18859, "https://github.com/dotnet/roslyn/issues/18859")] + [Fact, WorkItem(18859, "https://github.com/dotnet/roslyn/issues/18859")] public void UnoxInPatternSwitch_09() { var source = @"using System; @@ -8193,96 +8176,62 @@ public static void Main() expectedOutput: "1"); compVerifier.VerifyIL("Program.M", @"{ - // Code size 61 (0x3d) - .maxstack 2 - .locals init (U V_0, - T V_1, - object V_2, - T V_3) + // Code size 37 (0x25) + .maxstack 1 + .locals init (U V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: box ""U"" - IL_0008: brfalse.s IL_003c - IL_000a: ldloc.0 - IL_000b: box ""U"" - IL_0010: stloc.2 - IL_0011: ldloc.2 - IL_0012: isinst ""T"" - IL_0017: ldnull - IL_0018: cgt.un - IL_001a: dup - IL_001b: brtrue.s IL_0028 - IL_001d: ldloca.s V_3 - IL_001f: initobj ""T"" - IL_0025: ldloc.3 - IL_0026: br.s IL_002e - IL_0028: ldloc.2 - IL_0029: unbox.any ""T"" - IL_002e: stloc.1 - IL_002f: brfalse.s IL_003c - IL_0031: ldloc.1 - IL_0032: box ""T"" - IL_0037: call ""void System.Console.Write(object)"" - IL_003c: ret + IL_0008: isinst ""T"" + IL_000d: brfalse.s IL_0024 + IL_000f: ldloc.0 + IL_0010: box ""U"" + IL_0015: unbox.any ""T"" + IL_001a: box ""T"" + IL_001f: call ""void System.Console.Write(object)"" + IL_0024: ret }" ); compVerifier = CompileAndVerify(source, options: TestOptions.DebugDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: "1"); - // PROTOTYPE(patterns2): Need to restore code quality compVerifier.VerifyIL("Program.M", @"{ - // Code size 81 (0x51) - .maxstack 2 - .locals init (U V_0, - T V_1, - T V_2, //i - U V_3, - object V_4, - T V_5) + // Code size 51 (0x33) + .maxstack 1 + .locals init (T V_0, //i + U V_1, + T V_2, + U V_3) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.3 IL_0003: ldloc.3 - IL_0004: stloc.0 - IL_0005: ldloc.0 + IL_0004: stloc.1 + IL_0005: ldloc.1 IL_0006: box ""U"" - IL_000b: brtrue.s IL_000f - IL_000d: br.s IL_003c - IL_000f: ldloc.0 - IL_0010: box ""U"" - IL_0015: stloc.s V_4 - IL_0017: ldloc.s V_4 - IL_0019: isinst ""T"" - IL_001e: ldnull - IL_001f: cgt.un - IL_0021: dup - IL_0022: brtrue.s IL_0030 - IL_0024: ldloca.s V_5 - IL_0026: initobj ""T"" - IL_002c: ldloc.s V_5 - IL_002e: br.s IL_0037 - IL_0030: ldloc.s V_4 - IL_0032: unbox.any ""T"" - IL_0037: stloc.1 - IL_0038: brfalse.s IL_003c - IL_003a: br.s IL_003e - IL_003c: br.s IL_0050 - IL_003e: ldloc.1 - IL_003f: stloc.2 - IL_0040: br.s IL_0042 - IL_0042: ldloc.2 - IL_0043: box ""T"" - IL_0048: call ""void System.Console.Write(object)"" - IL_004d: nop - IL_004e: br.s IL_0050 - IL_0050: ret + IL_000b: isinst ""T"" + IL_0010: brfalse.s IL_0032 + IL_0012: ldloc.1 + IL_0013: box ""U"" + IL_0018: unbox.any ""T"" + IL_001d: stloc.2 + IL_001e: br.s IL_0020 + IL_0020: ldloc.2 + IL_0021: stloc.0 + IL_0022: br.s IL_0024 + IL_0024: ldloc.0 + IL_0025: box ""T"" + IL_002a: call ""void System.Console.Write(object)"" + IL_002f: nop + IL_0030: br.s IL_0032 + IL_0032: ret }" ); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality"), WorkItem(18859, "https://github.com/dotnet/roslyn/issues/18859")] + [Fact, WorkItem(18859, "https://github.com/dotnet/roslyn/issues/18859")] public void BoxInPatternIf_02() { var source = @"using System; @@ -8318,29 +8267,32 @@ .maxstack 1 expectedOutput: "RemoveEmptyEntries"); compVerifier.VerifyIL("Program.Main", @"{ - // Code size 23 (0x17) + // Code size 25 (0x19) .maxstack 1 .locals init (object V_0, //o - bool V_1) + bool V_1, + object V_2) IL_0000: nop IL_0001: ldc.i4.1 IL_0002: box ""System.StringSplitOptions"" - IL_0007: stloc.0 - IL_0008: ldc.i4.1 - IL_0009: stloc.1 - IL_000a: ldloc.1 - IL_000b: brfalse.s IL_0016 - IL_000d: nop - IL_000e: ldloc.0 - IL_000f: call ""void System.Console.WriteLine(object)"" - IL_0014: nop - IL_0015: nop - IL_0016: ret + IL_0007: stloc.2 + IL_0008: ldloc.2 + IL_0009: stloc.0 + IL_000a: ldc.i4.1 + IL_000b: stloc.1 + IL_000c: ldloc.1 + IL_000d: brfalse.s IL_0018 + IL_000f: nop + IL_0010: ldloc.0 + IL_0011: call ""void System.Console.WriteLine(object)"" + IL_0016: nop + IL_0017: nop + IL_0018: ret }" ); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality"), WorkItem(16195, "https://github.com/dotnet/roslyn/issues/16195")] + [Fact, WorkItem(16195, "https://github.com/dotnet/roslyn/issues/16195")] public void TestMatchWithTypeParameter_01() { var source = @@ -8383,54 +8335,24 @@ public static T M2(ValueType o) parseOptions: TestOptions.Regular7_1, expectedOutput: "2300"); compVerifier.VerifyIL("Program.M1", -@"{ - // Code size 31 (0x1f) - .maxstack 2 - .locals init (T V_0, //t - System.ValueType V_1, - T V_2) - IL_0000: ldarg.0 - IL_0001: dup - IL_0002: stloc.1 - IL_0003: isinst ""T"" - IL_0008: brfalse.s IL_0013 - IL_000a: ldloc.1 - IL_000b: unbox.any ""T"" - IL_0010: stloc.0 - IL_0011: br.s IL_001d - IL_0013: ldloca.s V_2 - IL_0015: initobj ""T"" - IL_001b: ldloc.2 - IL_001c: ret - IL_001d: ldloc.0 - IL_001e: ret -}" - ); - compVerifier.VerifyIL("Program.M2", @"{ // Code size 34 (0x22) - .maxstack 2 - .locals init (System.ValueType V_0, - T V_1, - System.ValueType V_2, - T V_3) + .maxstack 1 + .locals init (T V_0, //t + T V_1) IL_0000: ldarg.0 - IL_0001: stloc.0 - IL_0002: ldloc.0 - IL_0003: brfalse.s IL_0018 - IL_0005: ldloc.0 - IL_0006: dup - IL_0007: stloc.2 - IL_0008: isinst ""T"" - IL_000d: brfalse.s IL_0018 - IL_000f: ldloc.2 - IL_0010: unbox.any ""T"" - IL_0015: stloc.1 - IL_0016: ldloc.1 - IL_0017: ret - IL_0018: ldloca.s V_3 - IL_001a: initobj ""T"" - IL_0020: ldloc.3 + IL_0001: isinst ""T"" + IL_0006: brfalse.s IL_0016 + IL_0008: ldarg.0 + IL_0009: isinst ""T"" + IL_000e: unbox.any ""T"" + IL_0013: stloc.0 + IL_0014: br.s IL_0020 + IL_0016: ldloca.s V_1 + IL_0018: initobj ""T"" + IL_001e: ldloc.1 + IL_001f: ret + IL_0020: ldloc.0 IL_0021: ret }" ); @@ -8440,80 +8362,75 @@ .maxstack 2 expectedOutput: "2300"); compVerifier.VerifyIL("Program.M1", @"{ - // Code size 37 (0x25) - .maxstack 2 + // Code size 42 (0x2a) + .maxstack 1 .locals init (T V_0, //t - System.ValueType V_1, + T V_1, T V_2, T V_3) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.1 - IL_0004: isinst ""T"" - IL_0009: brfalse.s IL_0014 - IL_000b: ldloc.1 - IL_000c: unbox.any ""T"" - IL_0011: stloc.0 - IL_0012: br.s IL_001f - IL_0014: ldloca.s V_2 - IL_0016: initobj ""T"" - IL_001c: ldloc.2 - IL_001d: br.s IL_0020 - IL_001f: ldloc.0 - IL_0020: stloc.3 - IL_0021: br.s IL_0023 - IL_0023: ldloc.3 - IL_0024: ret + IL_0002: isinst ""T"" + IL_0007: brfalse.s IL_0019 + IL_0009: ldarg.0 + IL_000a: isinst ""T"" + IL_000f: unbox.any ""T"" + IL_0014: stloc.1 + IL_0015: ldloc.1 + IL_0016: stloc.0 + IL_0017: br.s IL_0024 + IL_0019: ldloca.s V_2 + IL_001b: initobj ""T"" + IL_0021: ldloc.2 + IL_0022: br.s IL_0025 + IL_0024: ldloc.0 + IL_0025: stloc.3 + IL_0026: br.s IL_0028 + IL_0028: ldloc.3 + IL_0029: ret }" ); compVerifier.VerifyIL("Program.M2", @"{ - // Code size 59 (0x3b) - .maxstack 2 - .locals init (System.ValueType V_0, - T V_1, - T V_2, //t + // Code size 53 (0x35) + .maxstack 1 + .locals init (T V_0, //t + System.ValueType V_1, + T V_2, System.ValueType V_3, - System.ValueType V_4, - T V_5, - T V_6) + T V_4, + T V_5) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.3 IL_0003: ldloc.3 - IL_0004: stloc.0 - IL_0005: ldloc.0 - IL_0006: brtrue.s IL_000a - IL_0008: br.s IL_001f - IL_000a: ldloc.0 - IL_000b: dup - IL_000c: stloc.s V_4 + IL_0004: stloc.1 + IL_0005: ldloc.1 + IL_0006: isinst ""T"" + IL_000b: brfalse.s IL_0024 + IL_000d: ldloc.1 IL_000e: isinst ""T"" - IL_0013: brfalse.s IL_001f - IL_0015: ldloc.s V_4 - IL_0017: unbox.any ""T"" - IL_001c: stloc.1 - IL_001d: br.s IL_0021 - IL_001f: br.s IL_002a - IL_0021: ldloc.1 - IL_0022: stloc.2 - IL_0023: br.s IL_0025 - IL_0025: ldloc.2 - IL_0026: stloc.s V_5 - IL_0028: br.s IL_0038 - IL_002a: ldloca.s V_6 - IL_002c: initobj ""T"" - IL_0032: ldloc.s V_6 - IL_0034: stloc.s V_5 - IL_0036: br.s IL_0038 - IL_0038: ldloc.s V_5 - IL_003a: ret + IL_0013: unbox.any ""T"" + IL_0018: stloc.2 + IL_0019: br.s IL_001b + IL_001b: ldloc.2 + IL_001c: stloc.0 + IL_001d: br.s IL_001f + IL_001f: ldloc.0 + IL_0020: stloc.s V_4 + IL_0022: br.s IL_0032 + IL_0024: ldloca.s V_5 + IL_0026: initobj ""T"" + IL_002c: ldloc.s V_5 + IL_002e: stloc.s V_4 + IL_0030: br.s IL_0032 + IL_0032: ldloc.s V_4 + IL_0034: ret }" ); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality"), WorkItem(16195, "https://github.com/dotnet/roslyn/issues/16195")] + [Fact, WorkItem(16195, "https://github.com/dotnet/roslyn/issues/16195")] public void TestMatchWithTypeParameter_02() { var source = @@ -8556,53 +8473,43 @@ public static int M2(T o) expectedOutput: "2300"); compVerifier.VerifyIL("Program.M1", @"{ - // Code size 33 (0x21) - .maxstack 2 - .locals init (int V_0, //t - T V_1) + // Code size 36 (0x24) + .maxstack 1 + .locals init (int V_0) //t IL_0000: ldarg.0 - IL_0001: dup - IL_0002: stloc.1 - IL_0003: box ""T"" - IL_0008: isinst ""int"" - IL_000d: brfalse.s IL_001d - IL_000f: ldloc.1 - IL_0010: box ""T"" - IL_0015: unbox.any ""int"" - IL_001a: stloc.0 - IL_001b: br.s IL_001f - IL_001d: ldc.i4.0 - IL_001e: ret - IL_001f: ldloc.0 - IL_0020: ret + IL_0001: box ""T"" + IL_0006: isinst ""int"" + IL_000b: brfalse.s IL_0020 + IL_000d: ldarg.0 + IL_000e: box ""T"" + IL_0013: isinst ""int"" + IL_0018: unbox.any ""int"" + IL_001d: stloc.0 + IL_001e: br.s IL_0022 + IL_0020: ldc.i4.0 + IL_0021: ret + IL_0022: ldloc.0 + IL_0023: ret }" ); compVerifier.VerifyIL("Program.M2", @"{ - // Code size 41 (0x29) - .maxstack 2 - .locals init (T V_0, - int V_1, - T V_2) + // Code size 34 (0x22) + .maxstack 1 + .locals init (T V_0) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 IL_0003: box ""T"" - IL_0008: brfalse.s IL_0027 - IL_000a: ldloc.0 - IL_000b: dup - IL_000c: stloc.2 - IL_000d: box ""T"" - IL_0012: isinst ""int"" - IL_0017: brfalse.s IL_0027 - IL_0019: ldloc.2 - IL_001a: box ""T"" - IL_001f: unbox.any ""int"" - IL_0024: stloc.1 - IL_0025: ldloc.1 - IL_0026: ret - IL_0027: ldc.i4.0 - IL_0028: ret + IL_0008: isinst ""int"" + IL_000d: brfalse.s IL_0020 + IL_000f: ldloc.0 + IL_0010: box ""T"" + IL_0015: isinst ""int"" + IL_001a: unbox.any ""int"" + IL_001f: ret + IL_0020: ldc.i4.0 + IL_0021: ret }" ); compVerifier = CompileAndVerify(source, @@ -8611,74 +8518,68 @@ .maxstack 2 expectedOutput: "2300"); compVerifier.VerifyIL("Program.M1", @"{ - // Code size 39 (0x27) - .maxstack 2 + // Code size 44 (0x2c) + .maxstack 1 .locals init (int V_0, //t - T V_1, + int V_1, int V_2) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.1 - IL_0004: box ""T"" - IL_0009: isinst ""int"" - IL_000e: brfalse.s IL_001e - IL_0010: ldloc.1 - IL_0011: box ""T"" - IL_0016: unbox.any ""int"" - IL_001b: stloc.0 - IL_001c: br.s IL_0021 - IL_001e: ldc.i4.0 - IL_001f: br.s IL_0022 - IL_0021: ldloc.0 - IL_0022: stloc.2 - IL_0023: br.s IL_0025 - IL_0025: ldloc.2 - IL_0026: ret + IL_0002: box ""T"" + IL_0007: isinst ""int"" + IL_000c: brfalse.s IL_0023 + IL_000e: ldarg.0 + IL_000f: box ""T"" + IL_0014: isinst ""int"" + IL_0019: unbox.any ""int"" + IL_001e: stloc.1 + IL_001f: ldloc.1 + IL_0020: stloc.0 + IL_0021: br.s IL_0026 + IL_0023: ldc.i4.0 + IL_0024: br.s IL_0027 + IL_0026: ldloc.0 + IL_0027: stloc.2 + IL_0028: br.s IL_002a + IL_002a: ldloc.2 + IL_002b: ret }" ); compVerifier.VerifyIL("Program.M2", @"{ - // Code size 65 (0x41) - .maxstack 2 - .locals init (T V_0, - int V_1, - int V_2, //t + // Code size 54 (0x36) + .maxstack 1 + .locals init (int V_0, //t + T V_1, + int V_2, T V_3, - T V_4, - int V_5) + int V_4) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.3 IL_0003: ldloc.3 - IL_0004: stloc.0 - IL_0005: ldloc.0 + IL_0004: stloc.1 + IL_0005: ldloc.1 IL_0006: box ""T"" - IL_000b: brtrue.s IL_000f - IL_000d: br.s IL_002e - IL_000f: ldloc.0 - IL_0010: dup - IL_0011: stloc.s V_4 + IL_000b: isinst ""int"" + IL_0010: brfalse.s IL_002e + IL_0012: ldloc.1 IL_0013: box ""T"" IL_0018: isinst ""int"" - IL_001d: brfalse.s IL_002e - IL_001f: ldloc.s V_4 - IL_0021: box ""T"" - IL_0026: unbox.any ""int"" - IL_002b: stloc.1 - IL_002c: br.s IL_0030 - IL_002e: br.s IL_0039 - IL_0030: ldloc.1 - IL_0031: stloc.2 - IL_0032: br.s IL_0034 - IL_0034: ldloc.2 - IL_0035: stloc.s V_5 - IL_0037: br.s IL_003e - IL_0039: ldc.i4.0 - IL_003a: stloc.s V_5 - IL_003c: br.s IL_003e - IL_003e: ldloc.s V_5 - IL_0040: ret + IL_001d: unbox.any ""int"" + IL_0022: stloc.2 + IL_0023: br.s IL_0025 + IL_0025: ldloc.2 + IL_0026: stloc.0 + IL_0027: br.s IL_0029 + IL_0029: ldloc.0 + IL_002a: stloc.s V_4 + IL_002c: br.s IL_0033 + IL_002e: ldc.i4.0 + IL_002f: stloc.s V_4 + IL_0031: br.s IL_0033 + IL_0033: ldloc.s V_4 + IL_0035: ret }" ); } @@ -9115,7 +9016,7 @@ public static string M2(object o) // ); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality"), WorkItem(16129, "https://github.com/dotnet/roslyn/issues/16129")] + [Fact, WorkItem(16129, "https://github.com/dotnet/roslyn/issues/16129")] public void ExactPatternMatch() { var source = @@ -9161,7 +9062,7 @@ .maxstack 2 ); } - [Fact(Skip = "PROTOTYPE(patterns2): PDB for new pattern switch not yet fully supported"), WorkItem(19280, "https://github.com/dotnet/roslyn/issues/19280")] + [Fact, WorkItem(19280, "https://github.com/dotnet/roslyn/issues/19280")] public void ShareLikeKindedTemps_01() { var source = @"using System; @@ -9189,246 +9090,164 @@ public static void M(object o) var compVerifier = CompileAndVerify(source, options: TestOptions.ReleaseDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: ""); - // PROTOTYPE(patterns2): Need to restore code quality. compVerifier.VerifyIL("Program.M", @"{ - // Code size 191 (0xbf) - .maxstack 2 + // Code size 141 (0x8d) + .maxstack 1 .locals init (object V_0, - int V_1, - object V_2) + int V_1) IL_0000: ldarg.0 IL_0001: stloc.0 IL_0002: ldloc.0 - IL_0003: brfalse IL_0088 - IL_0008: ldloc.0 - IL_0009: stloc.2 - IL_000a: ldloc.2 - IL_000b: isinst ""int"" - IL_0010: ldnull - IL_0011: cgt.un - IL_0013: dup - IL_0014: brtrue.s IL_0019 - IL_0016: ldc.i4.0 - IL_0017: br.s IL_001f - IL_0019: ldloc.2 - IL_001a: unbox.any ""int"" - IL_001f: stloc.1 - IL_0020: brfalse.s IL_0088 - IL_0022: br.s IL_0081 - IL_0024: ldloc.0 - IL_0025: brfalse.s IL_0098 - IL_0027: ldloc.0 - IL_0028: stloc.2 - IL_0029: ldloc.2 - IL_002a: isinst ""int"" - IL_002f: ldnull - IL_0030: cgt.un - IL_0032: dup - IL_0033: brtrue.s IL_0038 - IL_0035: ldc.i4.0 - IL_0036: br.s IL_003e - IL_0038: ldloc.2 - IL_0039: unbox.any ""int"" - IL_003e: stloc.1 - IL_003f: brfalse.s IL_0098 - IL_0041: br.s IL_0091 - IL_0043: ldloc.0 - IL_0044: brfalse.s IL_00a8 - IL_0046: ldloc.0 - IL_0047: stloc.2 - IL_0048: ldloc.2 - IL_0049: isinst ""int"" - IL_004e: ldnull - IL_004f: cgt.un - IL_0051: dup - IL_0052: brtrue.s IL_0057 - IL_0054: ldc.i4.0 - IL_0055: br.s IL_005d - IL_0057: ldloc.2 - IL_0058: unbox.any ""int"" - IL_005d: stloc.1 - IL_005e: brfalse.s IL_00a8 - IL_0060: br.s IL_00a1 - IL_0062: ldloc.0 - IL_0063: brfalse.s IL_00b8 - IL_0065: ldloc.0 - IL_0066: stloc.2 - IL_0067: ldloc.2 - IL_0068: isinst ""int"" - IL_006d: ldnull - IL_006e: cgt.un - IL_0070: dup - IL_0071: brtrue.s IL_0076 - IL_0073: ldc.i4.0 - IL_0074: br.s IL_007c - IL_0076: ldloc.2 - IL_0077: unbox.any ""int"" - IL_007c: stloc.1 - IL_007d: brfalse.s IL_00b8 - IL_007f: br.s IL_00b1 - IL_0081: ldsfld ""bool Program.b"" - IL_0086: brtrue.s IL_00be - IL_0088: ldsfld ""bool Program.b"" - IL_008d: brtrue.s IL_00be - IL_008f: br.s IL_0024 - IL_0091: ldsfld ""bool Program.b"" - IL_0096: brtrue.s IL_00be - IL_0098: ldsfld ""bool Program.b"" - IL_009d: brtrue.s IL_00be - IL_009f: br.s IL_0043 - IL_00a1: ldsfld ""bool Program.b"" - IL_00a6: brtrue.s IL_00be - IL_00a8: ldsfld ""bool Program.b"" - IL_00ad: brtrue.s IL_00be - IL_00af: br.s IL_0062 - IL_00b1: ldsfld ""bool Program.b"" - IL_00b6: brtrue.s IL_00be - IL_00b8: ldsfld ""bool Program.b"" - IL_00bd: pop - IL_00be: ret + IL_0003: brfalse.s IL_0044 + IL_0005: ldloc.0 + IL_0006: isinst ""int"" + IL_000b: brfalse.s IL_0044 + IL_000d: ldloc.0 + IL_000e: unbox.any ""int"" + IL_0013: stloc.1 + IL_0014: br.s IL_0034 + IL_0016: ldloc.0 + IL_0017: isinst ""int"" + IL_001c: brfalse.s IL_005d + IL_001e: br.s IL_004d + IL_0020: ldloc.0 + IL_0021: isinst ""int"" + IL_0026: brfalse.s IL_0076 + IL_0028: br.s IL_0066 + IL_002a: ldloc.0 + IL_002b: isinst ""int"" + IL_0030: brfalse.s IL_0086 + IL_0032: br.s IL_007f + IL_0034: ldsfld ""bool Program.b"" + IL_0039: brtrue.s IL_008c + IL_003b: ldsfld ""bool Program.b"" + IL_0040: brtrue.s IL_008c + IL_0042: br.s IL_0016 + IL_0044: ldsfld ""bool Program.b"" + IL_0049: brtrue.s IL_008c + IL_004b: br.s IL_005d + IL_004d: ldsfld ""bool Program.b"" + IL_0052: brtrue.s IL_008c + IL_0054: ldsfld ""bool Program.b"" + IL_0059: brtrue.s IL_008c + IL_005b: br.s IL_0020 + IL_005d: ldsfld ""bool Program.b"" + IL_0062: brtrue.s IL_008c + IL_0064: br.s IL_0076 + IL_0066: ldsfld ""bool Program.b"" + IL_006b: brtrue.s IL_008c + IL_006d: ldsfld ""bool Program.b"" + IL_0072: brtrue.s IL_008c + IL_0074: br.s IL_002a + IL_0076: ldsfld ""bool Program.b"" + IL_007b: brtrue.s IL_008c + IL_007d: br.s IL_0086 + IL_007f: ldsfld ""bool Program.b"" + IL_0084: brtrue.s IL_008c + IL_0086: ldsfld ""bool Program.b"" + IL_008b: pop + IL_008c: ret }" ); compVerifier = CompileAndVerify(source, options: TestOptions.DebugDll.WithOutputKind(OutputKind.ConsoleApplication), expectedOutput: ""); - // PROTOTYPE(patterns2): Need to restore code quality compVerifier.VerifyIL("Program.M", @"{ - // Code size 272 (0x110) - .maxstack 2 - .locals init (object V_0, - int V_1, + // Code size 207 (0xcf) + .maxstack 1 + .locals init (int V_0, //i + int V_1, //i int V_2, //i int V_3, //i - int V_4, //i - int V_5, //i - object V_6, - object V_7) + object V_4, + int V_5, + object V_6) IL_0000: nop IL_0001: ldarg.0 IL_0002: stloc.s V_6 IL_0004: ldloc.s V_6 - IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: brtrue.s IL_000c - IL_000a: br.s IL_002b - IL_000c: ldloc.0 - IL_000d: stloc.s V_7 - IL_000f: ldloc.s V_7 - IL_0011: isinst ""int"" - IL_0016: ldnull - IL_0017: cgt.un - IL_0019: dup - IL_001a: brtrue.s IL_001f - IL_001c: ldc.i4.0 - IL_001d: br.s IL_0026 - IL_001f: ldloc.s V_7 - IL_0021: unbox.any ""int"" - IL_0026: stloc.1 - IL_0027: brfalse.s IL_002b - IL_0029: br.s IL_00a4 - IL_002b: br IL_00b4 - IL_0030: ldloc.0 - IL_0031: brtrue.s IL_0035 - IL_0033: br.s IL_0054 - IL_0035: ldloc.0 - IL_0036: stloc.s V_7 - IL_0038: ldloc.s V_7 - IL_003a: isinst ""int"" - IL_003f: ldnull - IL_0040: cgt.un - IL_0042: dup - IL_0043: brtrue.s IL_0048 - IL_0045: ldc.i4.0 - IL_0046: br.s IL_004f - IL_0048: ldloc.s V_7 - IL_004a: unbox.any ""int"" - IL_004f: stloc.1 - IL_0050: brfalse.s IL_0054 - IL_0052: br.s IL_00c2 - IL_0054: br.s IL_00cf - IL_0056: ldloc.0 + IL_0006: stloc.s V_4 + IL_0008: ldloc.s V_4 + IL_000a: brfalse.s IL_0047 + IL_000c: ldloc.s V_4 + IL_000e: isinst ""int"" + IL_0013: brfalse.s IL_0047 + IL_0015: ldloc.s V_4 + IL_0017: unbox.any ""int"" + IL_001c: stloc.s V_5 + IL_001e: br.s IL_004f + IL_0020: br.s IL_005d + IL_0022: ldloc.s V_4 + IL_0024: isinst ""int"" + IL_0029: brfalse.s IL_0049 + IL_002b: br.s IL_0071 + IL_002d: br.s IL_007f + IL_002f: ldloc.s V_4 + IL_0031: isinst ""int"" + IL_0036: brfalse.s IL_004b + IL_0038: br.s IL_0093 + IL_003a: br.s IL_00a1 + IL_003c: ldloc.s V_4 + IL_003e: isinst ""int"" + IL_0043: brfalse.s IL_004d + IL_0045: br.s IL_00b5 + IL_0047: br.s IL_0066 + IL_0049: br.s IL_0088 + IL_004b: br.s IL_00aa + IL_004d: br.s IL_00c3 + IL_004f: ldloc.s V_5 + IL_0051: stloc.0 + IL_0052: ldsfld ""bool Program.b"" IL_0057: brtrue.s IL_005b - IL_0059: br.s IL_007a - IL_005b: ldloc.0 - IL_005c: stloc.s V_7 - IL_005e: ldloc.s V_7 - IL_0060: isinst ""int"" - IL_0065: ldnull - IL_0066: cgt.un - IL_0068: dup - IL_0069: brtrue.s IL_006e - IL_006b: ldc.i4.0 - IL_006c: br.s IL_0075 - IL_006e: ldloc.s V_7 - IL_0070: unbox.any ""int"" - IL_0075: stloc.1 - IL_0076: brfalse.s IL_007a - IL_0078: br.s IL_00dd - IL_007a: br.s IL_00eb - IL_007c: ldloc.0 - IL_007d: brtrue.s IL_0081 - IL_007f: br.s IL_00a0 - IL_0081: ldloc.0 - IL_0082: stloc.s V_7 - IL_0084: ldloc.s V_7 - IL_0086: isinst ""int"" - IL_008b: ldnull - IL_008c: cgt.un - IL_008e: dup - IL_008f: brtrue.s IL_0094 - IL_0091: ldc.i4.0 - IL_0092: br.s IL_009b - IL_0094: ldloc.s V_7 - IL_0096: unbox.any ""int"" - IL_009b: stloc.1 - IL_009c: brfalse.s IL_00a0 - IL_009e: br.s IL_00f6 - IL_00a0: br.s IL_0104 - IL_00a2: br.s IL_010f - IL_00a4: ldloc.1 - IL_00a5: stloc.2 - IL_00a6: ldsfld ""bool Program.b"" - IL_00ab: brtrue.s IL_00b2 - IL_00ad: br IL_002b - IL_00b2: br.s IL_010f - IL_00b4: ldsfld ""bool Program.b"" - IL_00b9: brtrue.s IL_00c0 - IL_00bb: br IL_0030 - IL_00c0: br.s IL_010f - IL_00c2: ldloc.1 - IL_00c3: stloc.3 - IL_00c4: ldsfld ""bool Program.b"" - IL_00c9: brtrue.s IL_00cd - IL_00cb: br.s IL_0054 - IL_00cd: br.s IL_010f - IL_00cf: ldsfld ""bool Program.b"" - IL_00d4: brtrue.s IL_00db - IL_00d6: br IL_0056 - IL_00db: br.s IL_010f - IL_00dd: ldloc.1 - IL_00de: stloc.s V_4 - IL_00e0: ldsfld ""bool Program.b"" - IL_00e5: brtrue.s IL_00e9 - IL_00e7: br.s IL_007a - IL_00e9: br.s IL_010f - IL_00eb: ldsfld ""bool Program.b"" - IL_00f0: brtrue.s IL_00f4 - IL_00f2: br.s IL_007c - IL_00f4: br.s IL_010f - IL_00f6: ldloc.1 - IL_00f7: stloc.s V_5 - IL_00f9: ldsfld ""bool Program.b"" - IL_00fe: brtrue.s IL_0102 - IL_0100: br.s IL_00a0 - IL_0102: br.s IL_010f - IL_0104: ldsfld ""bool Program.b"" - IL_0109: brtrue.s IL_010d - IL_010b: br.s IL_00a2 - IL_010d: br.s IL_010f - IL_010f: ret + IL_0059: br.s IL_0020 + IL_005b: br.s IL_00ce + IL_005d: ldsfld ""bool Program.b"" + IL_0062: brtrue.s IL_006f + IL_0064: br.s IL_0022 + IL_0066: ldsfld ""bool Program.b"" + IL_006b: brtrue.s IL_006f + IL_006d: br.s IL_0049 + IL_006f: br.s IL_00ce + IL_0071: ldloc.s V_5 + IL_0073: stloc.1 + IL_0074: ldsfld ""bool Program.b"" + IL_0079: brtrue.s IL_007d + IL_007b: br.s IL_002d + IL_007d: br.s IL_00ce + IL_007f: ldsfld ""bool Program.b"" + IL_0084: brtrue.s IL_0091 + IL_0086: br.s IL_002f + IL_0088: ldsfld ""bool Program.b"" + IL_008d: brtrue.s IL_0091 + IL_008f: br.s IL_004b + IL_0091: br.s IL_00ce + IL_0093: ldloc.s V_5 + IL_0095: stloc.2 + IL_0096: ldsfld ""bool Program.b"" + IL_009b: brtrue.s IL_009f + IL_009d: br.s IL_003a + IL_009f: br.s IL_00ce + IL_00a1: ldsfld ""bool Program.b"" + IL_00a6: brtrue.s IL_00b3 + IL_00a8: br.s IL_003c + IL_00aa: ldsfld ""bool Program.b"" + IL_00af: brtrue.s IL_00b3 + IL_00b1: br.s IL_004d + IL_00b3: br.s IL_00ce + IL_00b5: ldloc.s V_5 + IL_00b7: stloc.3 + IL_00b8: ldsfld ""bool Program.b"" + IL_00bd: brtrue.s IL_00c1 + IL_00bf: br.s IL_004d + IL_00c1: br.s IL_00ce + IL_00c3: ldsfld ""bool Program.b"" + IL_00c8: brtrue.s IL_00cc + IL_00ca: br.s IL_00ce + IL_00cc: br.s IL_00ce + IL_00ce: ret }" ); compVerifier.VerifyPdb( @@ -9456,54 +9275,41 @@ .maxstack 2 - - + + - - - - + + + - - + + - - + + - - + + @@ -9516,7 +9322,8 @@ .maxstack 2 -"); + +"); } [Fact(Skip = "PROTOTYPE(patterns2): This test is sensitive to the precise code generated, which is currently in flux.")] diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs index 79c635f8a532bfb007c99d844c1bff72bfdd1d20..1113b72715a96c8766e199b1695d7289276886bb 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/EditAndContinueTests.cs @@ -7585,7 +7585,7 @@ .maxstack 2 "); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality")] + [Fact] public void PatternVariable_TypeChange() { var source0 = MarkedSource(@" @@ -7617,19 +7617,19 @@ class C v0.VerifyIL("C.F", @" { // Code size 37 (0x25) - .maxstack 2 + .maxstack 1 .locals init (int V_0, //i bool V_1, - object V_2, + int V_2, int V_3) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.2 - IL_0004: isinst ""int"" - IL_0009: brfalse.s IL_0015 - IL_000b: ldloc.2 - IL_000c: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0015 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.2 + IL_0010: ldloc.2 IL_0011: stloc.0 IL_0012: ldc.i4.1 IL_0013: br.s IL_0016 @@ -7659,23 +7659,23 @@ .maxstack 2 diff1.VerifyIL("C.F", @" { // Code size 52 (0x34) - .maxstack 2 + .maxstack 1 .locals init ([int] V_0, [bool] V_1, - [object] V_2, + [int] V_2, [int] V_3, bool V_4, //i bool V_5, - object V_6, + bool V_6, int V_7) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.s V_6 - IL_0005: isinst ""bool"" - IL_000a: brfalse.s IL_0018 - IL_000c: ldloc.s V_6 - IL_000e: unbox.any ""bool"" + IL_0002: isinst ""bool"" + IL_0007: brfalse.s IL_0018 + IL_0009: ldarg.0 + IL_000a: unbox.any ""bool"" + IL_000f: stloc.s V_6 + IL_0011: ldloc.s V_6 IL_0013: stloc.s V_4 IL_0015: ldc.i4.1 IL_0016: br.s IL_0019 @@ -7706,27 +7706,27 @@ .maxstack 2 diff2.VerifyIL("C.F", @" { // Code size 46 (0x2e) - .maxstack 2 + .maxstack 1 .locals init ([int] V_0, [bool] V_1, - [object] V_2, + [int] V_2, [int] V_3, [bool] V_4, [bool] V_5, - [object] V_6, + [bool] V_6, [int] V_7, int V_8, //j bool V_9, - object V_10, + int V_10, int V_11) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.s V_10 - IL_0005: isinst ""int"" - IL_000a: brfalse.s IL_0018 - IL_000c: ldloc.s V_10 - IL_000e: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0018 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.s V_10 + IL_0011: ldloc.s V_10 IL_0013: stloc.s V_8 IL_0015: ldc.i4.1 IL_0016: br.s IL_0019 @@ -7746,7 +7746,7 @@ .maxstack 2 }"); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality")] + [Fact] public void PatternVariable_DeleteInsert() { var source0 = MarkedSource(@" @@ -7778,19 +7778,19 @@ class C v0.VerifyIL("C.F", @" { // Code size 37 (0x25) - .maxstack 2 + .maxstack 1 .locals init (int V_0, //i bool V_1, - object V_2, + int V_2, int V_3) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.2 - IL_0004: isinst ""int"" - IL_0009: brfalse.s IL_0015 - IL_000b: ldloc.2 - IL_000c: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0015 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.2 + IL_0010: ldloc.2 IL_0011: stloc.0 IL_0012: ldc.i4.1 IL_0013: br.s IL_0016 @@ -7823,7 +7823,7 @@ .maxstack 2 .maxstack 2 .locals init ([int] V_0, [bool] V_1, - [object] V_2, + [int] V_2, [int] V_3, bool V_4, int V_5) @@ -7855,25 +7855,25 @@ .maxstack 2 diff2.VerifyIL("C.F", @" { // Code size 46 (0x2e) - .maxstack 2 + .maxstack 1 .locals init ([int] V_0, [bool] V_1, - [object] V_2, + [int] V_2, [int] V_3, [bool] V_4, [int] V_5, int V_6, //i bool V_7, - object V_8, + int V_8, int V_9) IL_0000: nop IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.s V_8 - IL_0005: isinst ""int"" - IL_000a: brfalse.s IL_0018 - IL_000c: ldloc.s V_8 - IL_000e: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0018 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.s V_8 + IL_0011: ldloc.s V_8 IL_0013: stloc.s V_6 IL_0015: ldc.i4.1 IL_0016: br.s IL_0019 diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs index a6751cef79512c057276639a72af6310d488c692..4332aec449d3bf1faddb3ecdde50762afbf01ff6 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs @@ -2364,7 +2364,7 @@ .locals init (int V_0) }"); } - [Fact(Skip = "PROTOTYPE(patterns2): local slot mapping is not yet supported for new pattern switch")] + [Fact] public void Switch_Patterns() { var source = @" @@ -2402,15 +2402,14 @@ static void M() - - - + + + - @@ -2419,107 +2418,95 @@ static void M() v0.VerifyIL("C.M", @" { - // Code size 200 (0xc8) + // Code size 197 (0xc5) .maxstack 2 - .locals init (object V_0, - int V_1, - byte V_2, - byte V_3, //b - int V_4, //i - int V_5, //j - object V_6, //o - object V_7, - object V_8) + .locals init (byte V_0, //b + int V_1, //i + int V_2, //j + object V_3, //o + object V_4, + int V_5, + byte V_6, + object V_7) IL_0000: nop IL_0001: call ""object C.F()"" IL_0006: stloc.s V_7 IL_0008: ldloc.s V_7 - IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: brtrue.s IL_0010 - IL_000e: br.s IL_0063 - IL_0010: ldloc.0 - IL_0011: dup - IL_0012: stloc.s V_8 - IL_0014: isinst ""int"" - IL_0019: brfalse.s IL_002b - IL_001b: ldloc.s V_8 - IL_001d: unbox.any ""int"" - IL_0022: stloc.1 - IL_0023: ldloc.1 - IL_0024: ldc.i4.1 - IL_0025: beq.s IL_0029 - IL_0027: br.s IL_002b - IL_0029: br.s IL_0065 - IL_002b: ldloc.0 - IL_002c: dup - IL_002d: stloc.s V_8 - IL_002f: isinst ""byte"" - IL_0034: brfalse.s IL_0048 - IL_0036: ldloc.s V_8 - IL_0038: unbox.any ""byte"" - IL_003d: stloc.2 - IL_003e: br.s IL_0072 - IL_0040: ldloc.2 - IL_0041: ldc.i4.1 - IL_0042: beq.s IL_0046 - IL_0044: br.s IL_0048 - IL_0046: br.s IL_009c - IL_0048: ldloc.0 - IL_0049: dup - IL_004a: stloc.s V_8 - IL_004c: isinst ""int"" - IL_0051: brfalse.s IL_005f - IL_0053: ldloc.s V_8 - IL_0055: unbox.any ""int"" - IL_005a: stloc.1 - IL_005b: br.s IL_0086 - IL_005d: br.s IL_00a9 - IL_005f: ldloc.0 - IL_0060: stloc.0 - IL_0061: br.s IL_00b8 - IL_0063: br.s IL_00c7 - IL_0065: ldstr ""int 1"" - IL_006a: call ""void System.Console.WriteLine(string)"" - IL_006f: nop - IL_0070: br.s IL_00c7 - IL_0072: ldloc.2 - IL_0073: stloc.3 + IL_000a: stloc.s V_4 + IL_000c: ldloc.s V_4 + IL_000e: brfalse IL_00c4 + IL_0013: ldloc.s V_4 + IL_0015: isinst ""int"" + IL_001a: brfalse.s IL_0040 + IL_001c: ldloc.s V_4 + IL_001e: unbox.any ""int"" + IL_0023: stloc.s V_5 + IL_0025: ldc.i4.1 + IL_0026: ldloc.s V_5 + IL_0028: beq.s IL_0064 + IL_002a: ldloc.s V_4 + IL_002c: isinst ""int"" + IL_0031: brfalse.s IL_0062 + IL_0033: br.s IL_0086 + IL_0035: ldloc.s V_4 + IL_0037: isinst ""int"" + IL_003c: brfalse.s IL_0062 + IL_003e: br.s IL_00a8 + IL_0040: ldloc.s V_4 + IL_0042: isinst ""byte"" + IL_0047: brfalse.s IL_0062 + IL_0049: ldloc.s V_4 + IL_004b: unbox.any ""byte"" + IL_0050: stloc.s V_6 + IL_0052: br.s IL_0071 + IL_0054: ldloc.s V_4 + IL_0056: isinst ""byte"" + IL_005b: brfalse.s IL_0062 + IL_005d: ldc.i4.1 + IL_005e: ldloc.s V_6 + IL_0060: beq.s IL_009b + IL_0062: br.s IL_00b6 + IL_0064: ldstr ""int 1"" + IL_0069: call ""void System.Console.WriteLine(string)"" + IL_006e: nop + IL_006f: br.s IL_00c4 + IL_0071: ldloc.s V_6 + IL_0073: stloc.0 IL_0074: call ""bool C.P()"" IL_0079: brtrue.s IL_007d - IL_007b: br.s IL_0040 - IL_007d: ldloc.3 + IL_007b: br.s IL_0054 + IL_007d: ldloc.0 IL_007e: call ""void System.Console.WriteLine(int)"" IL_0083: nop - IL_0084: br.s IL_00c7 - IL_0086: ldloc.1 - IL_0087: stloc.s V_4 + IL_0084: br.s IL_00c4 + IL_0086: ldloc.s V_5 + IL_0088: stloc.1 IL_0089: call ""bool C.P()"" IL_008e: brtrue.s IL_0092 - IL_0090: br.s IL_005d - IL_0092: ldloc.s V_4 - IL_0094: call ""void System.Console.WriteLine(int)"" - IL_0099: nop - IL_009a: br.s IL_00c7 - IL_009c: ldstr ""byte 1"" - IL_00a1: call ""void System.Console.WriteLine(string)"" - IL_00a6: nop - IL_00a7: br.s IL_00c7 - IL_00a9: ldloc.1 - IL_00aa: stloc.s V_5 - IL_00ac: br.s IL_00ae - IL_00ae: ldloc.s V_5 - IL_00b0: call ""void System.Console.WriteLine(int)"" - IL_00b5: nop - IL_00b6: br.s IL_00c7 - IL_00b8: ldloc.0 - IL_00b9: stloc.s V_6 - IL_00bb: br.s IL_00bd - IL_00bd: ldloc.s V_6 - IL_00bf: call ""void System.Console.WriteLine(object)"" - IL_00c4: nop - IL_00c5: br.s IL_00c7 - IL_00c7: ret + IL_0090: br.s IL_0035 + IL_0092: ldloc.1 + IL_0093: call ""void System.Console.WriteLine(int)"" + IL_0098: nop + IL_0099: br.s IL_00c4 + IL_009b: ldstr ""byte 1"" + IL_00a0: call ""void System.Console.WriteLine(string)"" + IL_00a5: nop + IL_00a6: br.s IL_00c4 + IL_00a8: ldloc.s V_5 + IL_00aa: stloc.2 + IL_00ab: br.s IL_00ad + IL_00ad: ldloc.2 + IL_00ae: call ""void System.Console.WriteLine(int)"" + IL_00b3: nop + IL_00b4: br.s IL_00c4 + IL_00b6: ldloc.s V_4 + IL_00b8: stloc.3 + IL_00b9: br.s IL_00bb + IL_00bb: ldloc.3 + IL_00bc: call ""void System.Console.WriteLine(object)"" + IL_00c1: nop + IL_00c2: br.s IL_00c4 + IL_00c4: ret }"); var methodData0 = v0.TestData.GetMethodData("C.M"); var method0 = compilation0.GetMember("C.M"); @@ -2532,108 +2519,98 @@ .maxstack 2 diff1.VerifyIL("C.M", @" { - // Code size 200 (0xc8) + // Code size 197 (0xc5) .maxstack 2 - .locals init (object V_0, - int V_1, - byte V_2, - byte V_3, //b - int V_4, //i - int V_5, //j - object V_6, //o + .locals init (byte V_0, //b + int V_1, //i + int V_2, //j + object V_3, //o + [object] V_4, + [int] V_5, + [unchanged] V_6, object V_7, - [object] V_8, - object V_9) + object V_8, + int V_9, + byte V_10) IL_0000: nop IL_0001: call ""object C.F()"" IL_0006: stloc.s V_7 IL_0008: ldloc.s V_7 - IL_000a: stloc.0 - IL_000b: ldloc.0 - IL_000c: brtrue.s IL_0010 - IL_000e: br.s IL_0063 - IL_0010: ldloc.0 - IL_0011: dup - IL_0012: stloc.s V_9 - IL_0014: isinst ""int"" - IL_0019: brfalse.s IL_002b - IL_001b: ldloc.s V_9 - IL_001d: unbox.any ""int"" - IL_0022: stloc.1 - IL_0023: ldloc.1 - IL_0024: ldc.i4.1 - IL_0025: beq.s IL_0029 - IL_0027: br.s IL_002b - IL_0029: br.s IL_0065 - IL_002b: ldloc.0 - IL_002c: dup - IL_002d: stloc.s V_9 - IL_002f: isinst ""byte"" - IL_0034: brfalse.s IL_0048 - IL_0036: ldloc.s V_9 - IL_0038: unbox.any ""byte"" - IL_003d: stloc.2 - IL_003e: br.s IL_0072 - IL_0040: ldloc.2 - IL_0041: ldc.i4.1 - IL_0042: beq.s IL_0046 - IL_0044: br.s IL_0048 - IL_0046: br.s IL_009c - IL_0048: ldloc.0 - IL_0049: dup - IL_004a: stloc.s V_9 - IL_004c: isinst ""int"" - IL_0051: brfalse.s IL_005f - IL_0053: ldloc.s V_9 - IL_0055: unbox.any ""int"" - IL_005a: stloc.1 - IL_005b: br.s IL_0086 - IL_005d: br.s IL_00a9 - IL_005f: ldloc.0 - IL_0060: stloc.0 - IL_0061: br.s IL_00b8 - IL_0063: br.s IL_00c7 - IL_0065: ldstr ""int 1"" - IL_006a: call ""void System.Console.WriteLine(string)"" - IL_006f: nop - IL_0070: br.s IL_00c7 - IL_0072: ldloc.2 - IL_0073: stloc.3 + IL_000a: stloc.s V_8 + IL_000c: ldloc.s V_8 + IL_000e: brfalse IL_00c4 + IL_0013: ldloc.s V_8 + IL_0015: isinst ""int"" + IL_001a: brfalse.s IL_0040 + IL_001c: ldloc.s V_8 + IL_001e: unbox.any ""int"" + IL_0023: stloc.s V_9 + IL_0025: ldc.i4.1 + IL_0026: ldloc.s V_9 + IL_0028: beq.s IL_0064 + IL_002a: ldloc.s V_8 + IL_002c: isinst ""int"" + IL_0031: brfalse.s IL_0062 + IL_0033: br.s IL_0086 + IL_0035: ldloc.s V_8 + IL_0037: isinst ""int"" + IL_003c: brfalse.s IL_0062 + IL_003e: br.s IL_00a8 + IL_0040: ldloc.s V_8 + IL_0042: isinst ""byte"" + IL_0047: brfalse.s IL_0062 + IL_0049: ldloc.s V_8 + IL_004b: unbox.any ""byte"" + IL_0050: stloc.s V_10 + IL_0052: br.s IL_0071 + IL_0054: ldloc.s V_8 + IL_0056: isinst ""byte"" + IL_005b: brfalse.s IL_0062 + IL_005d: ldc.i4.1 + IL_005e: ldloc.s V_10 + IL_0060: beq.s IL_009b + IL_0062: br.s IL_00b6 + IL_0064: ldstr ""int 1"" + IL_0069: call ""void System.Console.WriteLine(string)"" + IL_006e: nop + IL_006f: br.s IL_00c4 + IL_0071: ldloc.s V_10 + IL_0073: stloc.0 IL_0074: call ""bool C.P()"" IL_0079: brtrue.s IL_007d - IL_007b: br.s IL_0040 - IL_007d: ldloc.3 + IL_007b: br.s IL_0054 + IL_007d: ldloc.0 IL_007e: call ""void System.Console.WriteLine(int)"" IL_0083: nop - IL_0084: br.s IL_00c7 - IL_0086: ldloc.1 - IL_0087: stloc.s V_4 + IL_0084: br.s IL_00c4 + IL_0086: ldloc.s V_9 + IL_0088: stloc.1 IL_0089: call ""bool C.P()"" IL_008e: brtrue.s IL_0092 - IL_0090: br.s IL_005d - IL_0092: ldloc.s V_4 - IL_0094: call ""void System.Console.WriteLine(int)"" - IL_0099: nop - IL_009a: br.s IL_00c7 - IL_009c: ldstr ""byte 1"" - IL_00a1: call ""void System.Console.WriteLine(string)"" - IL_00a6: nop - IL_00a7: br.s IL_00c7 - IL_00a9: ldloc.1 - IL_00aa: stloc.s V_5 - IL_00ac: br.s IL_00ae - IL_00ae: ldloc.s V_5 - IL_00b0: call ""void System.Console.WriteLine(int)"" - IL_00b5: nop - IL_00b6: br.s IL_00c7 - IL_00b8: ldloc.0 - IL_00b9: stloc.s V_6 - IL_00bb: br.s IL_00bd - IL_00bd: ldloc.s V_6 - IL_00bf: call ""void System.Console.WriteLine(object)"" - IL_00c4: nop - IL_00c5: br.s IL_00c7 - IL_00c7: ret + IL_0090: br.s IL_0035 + IL_0092: ldloc.1 + IL_0093: call ""void System.Console.WriteLine(int)"" + IL_0098: nop + IL_0099: br.s IL_00c4 + IL_009b: ldstr ""byte 1"" + IL_00a0: call ""void System.Console.WriteLine(string)"" + IL_00a5: nop + IL_00a6: br.s IL_00c4 + IL_00a8: ldloc.s V_9 + IL_00aa: stloc.2 + IL_00ab: br.s IL_00ad + IL_00ad: ldloc.2 + IL_00ae: call ""void System.Console.WriteLine(int)"" + IL_00b3: nop + IL_00b4: br.s IL_00c4 + IL_00b6: ldloc.s V_8 + IL_00b8: stloc.3 + IL_00b9: br.s IL_00bb + IL_00bb: ldloc.3 + IL_00bc: call ""void System.Console.WriteLine(object)"" + IL_00c1: nop + IL_00c2: br.s IL_00c4 + IL_00c4: ret }"); } @@ -3606,7 +3583,7 @@ .maxstack 2 ", methodToken: diff1.UpdatedMethods.Single()); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality")] + [Fact] public void PatternVariable() { var source = @" @@ -3632,21 +3609,21 @@ class C diff1.VerifyIL("C.F", @" { // Code size 42 (0x2a) - .maxstack 2 + .maxstack 1 .locals init (int V_0, //i bool V_1, - [object] V_2, + [int] V_2, [int] V_3, - object V_4, + int V_4, int V_5) -IL_0000: nop -IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.s V_4 - IL_0005: isinst ""int"" - IL_000a: brfalse.s IL_0017 - IL_000c: ldloc.s V_4 - IL_000e: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0017 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.s V_4 + IL_0011: ldloc.s V_4 IL_0013: stloc.0 IL_0014: ldc.i4.1 IL_0015: br.s IL_0018 @@ -3773,7 +3750,7 @@ .maxstack 2 ", methodToken: diff1.UpdatedMethods.Single()); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality")] + [Fact] public void PatternMatching_Variable() { var source = @" @@ -3799,21 +3776,21 @@ class C diff1.VerifyIL("C.F", @" { // Code size 42 (0x2a) - .maxstack 2 + .maxstack 1 .locals init (int V_0, //i bool V_1, - [object] V_2, + [int] V_2, [int] V_3, - object V_4, + int V_4, int V_5) -IL_0000: nop -IL_0001: ldarg.0 - IL_0002: dup - IL_0003: stloc.s V_4 - IL_0005: isinst ""int"" - IL_000a: brfalse.s IL_0017 - IL_000c: ldloc.s V_4 - IL_000e: unbox.any ""int"" + IL_0002: isinst ""int"" + IL_0007: brfalse.s IL_0017 + IL_0009: ldarg.0 + IL_000a: unbox.any ""int"" + IL_000f: stloc.s V_4 + IL_0011: ldloc.s V_4 IL_0013: stloc.0 IL_0014: ldc.i4.1 IL_0015: br.s IL_0018 @@ -3833,7 +3810,7 @@ .maxstack 2 }", methodToken: diff1.UpdatedMethods.Single()); } - [Fact(Skip = "PROTOTYPE(patterns2): code quality")] + [Fact] public void PatternMatching_NoVariable() { var source = @" @@ -3858,33 +3835,42 @@ class C diff1.VerifyIL("C.F", @" { - // Code size 39 (0x27) + // Code size 52 (0x34) .maxstack 2 .locals init (bool V_0, [int] V_1, - int V_2) + [int] V_2, + int V_3, + int V_4) -IL_0000: nop -IL_0001: ldarg.0 IL_0002: isinst ""bool"" - IL_0007: brtrue.s IL_0017 - IL_0009: ldc.i4.0 - IL_000a: box ""int"" - IL_000f: ldarg.0 - IL_0010: call ""bool object.Equals(object, object)"" - IL_0015: br.s IL_0018 - IL_0017: ldc.i4.1 - IL_0018: stloc.0 - ~IL_0019: ldloc.0 - IL_001a: brfalse.s IL_0021 - -IL_001c: nop - -IL_001d: ldc.i4.0 - IL_001e: stloc.2 - IL_001f: br.s IL_0025 - -IL_0021: ldc.i4.1 - IL_0022: stloc.2 - IL_0023: br.s IL_0025 - -IL_0025: ldloc.2 - IL_0026: ret + IL_0007: brtrue.s IL_0021 + IL_0009: ldarg.0 + IL_000a: isinst ""int"" + IL_000f: brfalse.s IL_001e + IL_0011: ldarg.0 + IL_0012: unbox.any ""int"" + IL_0017: stloc.3 + IL_0018: ldloc.3 + IL_0019: ldc.i4.0 + IL_001a: ceq + IL_001c: br.s IL_001f + IL_001e: ldc.i4.0 + IL_001f: br.s IL_0022 + IL_0021: ldc.i4.1 + IL_0022: stloc.0 + ~IL_0023: ldloc.0 + IL_0024: brfalse.s IL_002c + -IL_0026: nop + -IL_0027: ldc.i4.0 + IL_0028: stloc.s V_4 + IL_002a: br.s IL_0031 + -IL_002c: ldc.i4.1 + IL_002d: stloc.s V_4 + IL_002f: br.s IL_0031 + -IL_0031: ldloc.s V_4 + IL_0033: ret } ", methodToken: diff1.UpdatedMethods.Single()); } diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index d0629eb93f11be7c8cfe237142a91216d0a56440..5f14662cc07cf1025578135b44d7ddc52727c8e9 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -3358,7 +3358,7 @@ .maxstack 1 }"); } - [Fact(Skip = "PROTOTYPE(patterns2): This test is sensitive to the precise code generated, which is currently in flux.")] + [Fact] [WorkItem(19734, "https://github.com/dotnet/roslyn/issues/19734")] public void SwitchWithConstantGenericPattern_01() { @@ -3408,125 +3408,99 @@ static void M2() c.VerifyDiagnostics(); var verifier = CompileAndVerify(c, expectedOutput: "1234"); - // PROTOTYPE(patterns2): Need to restore code quality verifier.VerifyIL(qualifiedMethodName: "Program.M1", sequencePoints: "Program.M1", source: source, expectedIL: @"{ - // Code size 80 (0x50) - .maxstack 2 - .locals init (T V_0, - int V_1, - T V_2, //t - int V_3, //i - int V_4, - object V_5, - T V_6) + // Code size 67 (0x43) + .maxstack 1 + .locals init (T V_0, //t + int V_1, //i + int V_2, + T V_3, + int V_4) // sequence point: { IL_0000: nop // sequence point: switch (1) IL_0001: ldc.i4.1 IL_0002: stloc.s V_4 IL_0004: ldc.i4.1 - IL_0005: box ""int"" - IL_000a: stloc.s V_5 - IL_000c: ldloc.s V_5 - IL_000e: isinst ""T"" - IL_0013: ldnull - IL_0014: cgt.un - IL_0016: dup - IL_0017: brtrue.s IL_0025 - IL_0019: ldloca.s V_6 - IL_001b: initobj ""T"" - IL_0021: ldloc.s V_6 - IL_0023: br.s IL_002c - IL_0025: ldloc.s V_5 - IL_0027: unbox.any ""T"" - IL_002c: stloc.0 - IL_002d: brfalse.s IL_0031 - IL_002f: br.s IL_0035 - IL_0031: ldc.i4.1 - IL_0032: stloc.1 + IL_0005: stloc.2 + IL_0006: ldloc.2 + IL_0007: box ""int"" + IL_000c: isinst ""T"" + IL_0011: brfalse.s IL_0026 + IL_0013: ldloc.2 + IL_0014: box ""int"" + IL_0019: isinst ""T"" + IL_001e: unbox.any ""T"" + IL_0023: stloc.3 + IL_0024: br.s IL_0028 + IL_0026: br.s IL_0035 + IL_0028: ldloc.3 + IL_0029: stloc.0 + IL_002a: br.s IL_002c + // sequence point: Console.Write(1); + IL_002c: ldc.i4.1 + IL_002d: call ""void System.Console.Write(int)"" + IL_0032: nop + // sequence point: break; IL_0033: br.s IL_0042 - // sequence point: - IL_0035: ldloc.0 - IL_0036: stloc.2 + IL_0035: ldloc.2 + IL_0036: stloc.1 IL_0037: br.s IL_0039 - // sequence point: Console.Write(1); - IL_0039: ldc.i4.1 + // sequence point: Console.Write(2); + IL_0039: ldc.i4.2 IL_003a: call ""void System.Console.Write(int)"" IL_003f: nop // sequence point: break; - IL_0040: br.s IL_004f - // sequence point: - IL_0042: ldloc.1 - IL_0043: stloc.3 - IL_0044: br.s IL_0046 - // sequence point: Console.Write(2); - IL_0046: ldc.i4.2 - IL_0047: call ""void System.Console.Write(int)"" - IL_004c: nop - // sequence point: break; - IL_004d: br.s IL_004f + IL_0040: br.s IL_0042 // sequence point: } - IL_004f: ret + IL_0042: ret }"); verifier.VerifyIL(qualifiedMethodName: "Program.M2", sequencePoints: "Program.M2", source: source, expectedIL: @"{ - // Code size 87 (0x57) - .maxstack 2 - .locals init (T V_0, - string V_1, - T V_2, //t - string V_3, //s - string V_4, - object V_5, - T V_6) + // Code size 65 (0x41) + .maxstack 1 + .locals init (T V_0, //t + string V_1, //s + string V_2, + T V_3, + string V_4) // sequence point: { IL_0000: nop // sequence point: switch (nameof(M2)) IL_0001: ldstr ""M2"" IL_0006: stloc.s V_4 IL_0008: ldstr ""M2"" - IL_000d: stloc.s V_5 - IL_000f: ldloc.s V_5 - IL_0011: isinst ""T"" - IL_0016: ldnull - IL_0017: cgt.un - IL_0019: dup - IL_001a: brtrue.s IL_0028 - IL_001c: ldloca.s V_6 - IL_001e: initobj ""T"" - IL_0024: ldloc.s V_6 - IL_0026: br.s IL_002f - IL_0028: ldloc.s V_5 - IL_002a: unbox.any ""T"" - IL_002f: stloc.0 - IL_0030: brfalse.s IL_0034 - IL_0032: br.s IL_003c - IL_0034: ldstr ""M2"" - IL_0039: stloc.1 - IL_003a: br.s IL_0049 - // sequence point: - IL_003c: ldloc.0 - IL_003d: stloc.2 - IL_003e: br.s IL_0040 + IL_000d: stloc.2 + IL_000e: ldloc.2 + IL_000f: isinst ""T"" + IL_0014: brfalse.s IL_0024 + IL_0016: ldloc.2 + IL_0017: isinst ""T"" + IL_001c: unbox.any ""T"" + IL_0021: stloc.3 + IL_0022: br.s IL_0026 + IL_0024: br.s IL_0033 + IL_0026: ldloc.3 + IL_0027: stloc.0 + IL_0028: br.s IL_002a // sequence point: Console.Write(3); - IL_0040: ldc.i4.3 - IL_0041: call ""void System.Console.Write(int)"" - IL_0046: nop + IL_002a: ldc.i4.3 + IL_002b: call ""void System.Console.Write(int)"" + IL_0030: nop // sequence point: break; - IL_0047: br.s IL_0056 - // sequence point: - IL_0049: ldloc.1 - IL_004a: stloc.3 - IL_004b: br.s IL_004d + IL_0031: br.s IL_0040 + IL_0033: ldloc.2 + IL_0034: stloc.1 + IL_0035: br.s IL_0037 // sequence point: Console.Write(4); - IL_004d: ldc.i4.4 - IL_004e: call ""void System.Console.Write(int)"" - IL_0053: nop + IL_0037: ldc.i4.4 + IL_0038: call ""void System.Console.Write(int)"" + IL_003d: nop // sequence point: break; - IL_0054: br.s IL_0056 + IL_003e: br.s IL_0040 // sequence point: } - IL_0056: ret + IL_0040: ret }"); // Check the release code generation too. @@ -3536,72 +3510,49 @@ .maxstack 2 verifier.VerifyIL("Program.M1", @"{ - // Code size 57 (0x39) - .maxstack 2 - .locals init (T V_0, - int V_1, - object V_2, - T V_3) + // Code size 46 (0x2e) + .maxstack 1 + .locals init (int V_0, + T V_1) IL_0000: ldc.i4.1 - IL_0001: box ""int"" - IL_0006: stloc.2 - IL_0007: ldloc.2 + IL_0001: stloc.0 + IL_0002: ldloc.0 + IL_0003: box ""int"" IL_0008: isinst ""T"" - IL_000d: ldnull - IL_000e: cgt.un - IL_0010: dup - IL_0011: brtrue.s IL_001e - IL_0013: ldloca.s V_3 - IL_0015: initobj ""T"" - IL_001b: ldloc.3 - IL_001c: br.s IL_0024 - IL_001e: ldloc.2 - IL_001f: unbox.any ""T"" - IL_0024: stloc.0 - IL_0025: brtrue.s IL_002b - IL_0027: ldc.i4.1 - IL_0028: stloc.1 - IL_0029: br.s IL_0032 - IL_002b: ldc.i4.1 - IL_002c: call ""void System.Console.Write(int)"" - IL_0031: ret - IL_0032: ldc.i4.2 - IL_0033: call ""void System.Console.Write(int)"" - IL_0038: ret + IL_000d: brfalse.s IL_0027 + IL_000f: ldloc.0 + IL_0010: box ""int"" + IL_0015: isinst ""T"" + IL_001a: unbox.any ""T"" + IL_001f: stloc.1 + IL_0020: ldc.i4.1 + IL_0021: call ""void System.Console.Write(int)"" + IL_0026: ret + IL_0027: ldc.i4.2 + IL_0028: call ""void System.Console.Write(int)"" + IL_002d: ret }"); verifier.VerifyIL("Program.M2", @"{ - // Code size 60 (0x3c) - .maxstack 2 - .locals init (T V_0, - string V_1, - object V_2, - T V_3) + // Code size 40 (0x28) + .maxstack 1 + .locals init (string V_0, + T V_1) IL_0000: ldstr ""M2"" - IL_0005: stloc.2 - IL_0006: ldloc.2 + IL_0005: stloc.0 + IL_0006: ldloc.0 IL_0007: isinst ""T"" - IL_000c: ldnull - IL_000d: cgt.un - IL_000f: dup - IL_0010: brtrue.s IL_001d - IL_0012: ldloca.s V_3 - IL_0014: initobj ""T"" - IL_001a: ldloc.3 - IL_001b: br.s IL_0023 - IL_001d: ldloc.2 - IL_001e: unbox.any ""T"" - IL_0023: stloc.0 - IL_0024: brtrue.s IL_002e - IL_0026: ldstr ""M2"" - IL_002b: stloc.1 - IL_002c: br.s IL_0035 - IL_002e: ldc.i4.3 - IL_002f: call ""void System.Console.Write(int)"" - IL_0034: ret - IL_0035: ldc.i4.4 - IL_0036: call ""void System.Console.Write(int)"" - IL_003b: ret + IL_000c: brfalse.s IL_0021 + IL_000e: ldloc.0 + IL_000f: isinst ""T"" + IL_0014: unbox.any ""T"" + IL_0019: stloc.1 + IL_001a: ldc.i4.3 + IL_001b: call ""void System.Console.Write(int)"" + IL_0020: ret + IL_0021: ldc.i4.4 + IL_0022: call ""void System.Console.Write(int)"" + IL_0027: ret }"); }