Browse Source

Add IL ordering based hint to UseCSharpSwitch

pull/1258/head
Chicken-Bones 7 years ago
parent
commit
cb4fa90545
  1. 59
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  2. 272
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il
  3. 126
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il
  4. 126
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il
  5. 258
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il
  6. 12
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

59
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs

@ -608,6 +608,65 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -608,6 +608,65 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine();
}
public static bool SwitchlikeIf(int i, int j)
{
if (i != 0 && j != 0) {
if (i == -1 && j == -1) {
Console.WriteLine("-1, -1");
}
if (i == -1 && j == 1) {
Console.WriteLine("-1, 1");
}
if (i == 1 && j == -1) {
Console.WriteLine("1, -1");
}
if (i == 1 && j == 1) {
Console.WriteLine("1, 1");
}
return false;
}
if (i != 0) {
if (i == -1) {
Console.WriteLine("-1, 0");
}
if (i == 1) {
Console.WriteLine("1, 0");
}
return false;
}
if (j != 0) {
if (j == -1) {
Console.WriteLine("0, -1");
}
if (j == 1) {
Console.WriteLine("0, 1");
}
return false;
}
return true;
}
public static bool SwitchlikeIf2(int i)
{
if (i != 0) {
// note that using else-if in this chain creates a nice-looking switch here (as expected)
if (i == 1) {
Console.WriteLine(1);
}
if (i == 2) {
Console.WriteLine(2);
}
if (i == 3) {
Console.WriteLine(3);
}
return false;
}
return false;
}
#endregion
// Ensure correctness of SwitchDetection.FindBreakTarget

272
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il

@ -2196,6 +2196,278 @@ @@ -2196,6 +2196,278 @@
IL_00a8: ret
} // end of method Switch::IfChainWithCondition
.method public hidebysig static bool SwitchlikeIf(int32 i,
int32 j) cil managed
{
// Code size 280 (0x118)
.maxstack 2
.locals init (bool V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: brfalse.s IL_000a
IL_0004: ldarg.1
IL_0005: ldc.i4.0
IL_0006: ceq
IL_0008: br.s IL_000b
IL_000a: ldc.i4.1
IL_000b: nop
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: brtrue IL_0098
IL_0013: nop
IL_0014: ldarg.0
IL_0015: ldc.i4.m1
IL_0016: bne.un.s IL_0021
IL_0018: ldarg.1
IL_0019: ldc.i4.m1
IL_001a: ceq
IL_001c: ldc.i4.0
IL_001d: ceq
IL_001f: br.s IL_0022
IL_0021: ldc.i4.1
IL_0022: nop
IL_0023: stloc.1
IL_0024: ldloc.1
IL_0025: brtrue.s IL_0034
IL_0027: nop
IL_0028: ldstr "-1, -1"
IL_002d: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: nop
IL_0033: nop
IL_0034: ldarg.0
IL_0035: ldc.i4.m1
IL_0036: bne.un.s IL_0041
IL_0038: ldarg.1
IL_0039: ldc.i4.1
IL_003a: ceq
IL_003c: ldc.i4.0
IL_003d: ceq
IL_003f: br.s IL_0042
IL_0041: ldc.i4.1
IL_0042: nop
IL_0043: stloc.1
IL_0044: ldloc.1
IL_0045: brtrue.s IL_0054
IL_0047: nop
IL_0048: ldstr "-1, 1"
IL_004d: call void [mscorlib]System.Console::WriteLine(string)
IL_0052: nop
IL_0053: nop
IL_0054: ldarg.0
IL_0055: ldc.i4.1
IL_0056: bne.un.s IL_0061
IL_0058: ldarg.1
IL_0059: ldc.i4.m1
IL_005a: ceq
IL_005c: ldc.i4.0
IL_005d: ceq
IL_005f: br.s IL_0062
IL_0061: ldc.i4.1
IL_0062: nop
IL_0063: stloc.1
IL_0064: ldloc.1
IL_0065: brtrue.s IL_0074
IL_0067: nop
IL_0068: ldstr "1, -1"
IL_006d: call void [mscorlib]System.Console::WriteLine(string)
IL_0072: nop
IL_0073: nop
IL_0074: ldarg.0
IL_0075: ldc.i4.1
IL_0076: bne.un.s IL_0081
IL_0078: ldarg.1
IL_0079: ldc.i4.1
IL_007a: ceq
IL_007c: ldc.i4.0
IL_007d: ceq
IL_007f: br.s IL_0082
IL_0081: ldc.i4.1
IL_0082: nop
IL_0083: stloc.1
IL_0084: ldloc.1
IL_0085: brtrue.s IL_0094
IL_0087: nop
IL_0088: ldstr "1, 1"
IL_008d: call void [mscorlib]System.Console::WriteLine(string)
IL_0092: nop
IL_0093: nop
IL_0094: ldc.i4.0
IL_0095: stloc.0
IL_0096: br.s IL_0116
IL_0098: ldarg.0
IL_0099: ldc.i4.0
IL_009a: ceq
IL_009c: stloc.1
IL_009d: ldloc.1
IL_009e: brtrue.s IL_00d5
IL_00a0: nop
IL_00a1: ldarg.0
IL_00a2: ldc.i4.m1
IL_00a3: ceq
IL_00a5: ldc.i4.0
IL_00a6: ceq
IL_00a8: stloc.1
IL_00a9: ldloc.1
IL_00aa: brtrue.s IL_00b9
IL_00ac: nop
IL_00ad: ldstr "-1, 0"
IL_00b2: call void [mscorlib]System.Console::WriteLine(string)
IL_00b7: nop
IL_00b8: nop
IL_00b9: ldarg.0
IL_00ba: ldc.i4.1
IL_00bb: ceq
IL_00bd: ldc.i4.0
IL_00be: ceq
IL_00c0: stloc.1
IL_00c1: ldloc.1
IL_00c2: brtrue.s IL_00d1
IL_00c4: nop
IL_00c5: ldstr "1, 0"
IL_00ca: call void [mscorlib]System.Console::WriteLine(string)
IL_00cf: nop
IL_00d0: nop
IL_00d1: ldc.i4.0
IL_00d2: stloc.0
IL_00d3: br.s IL_0116
IL_00d5: ldarg.1
IL_00d6: ldc.i4.0
IL_00d7: ceq
IL_00d9: stloc.1
IL_00da: ldloc.1
IL_00db: brtrue.s IL_0112
IL_00dd: nop
IL_00de: ldarg.1
IL_00df: ldc.i4.m1
IL_00e0: ceq
IL_00e2: ldc.i4.0
IL_00e3: ceq
IL_00e5: stloc.1
IL_00e6: ldloc.1
IL_00e7: brtrue.s IL_00f6
IL_00e9: nop
IL_00ea: ldstr "0, -1"
IL_00ef: call void [mscorlib]System.Console::WriteLine(string)
IL_00f4: nop
IL_00f5: nop
IL_00f6: ldarg.1
IL_00f7: ldc.i4.1
IL_00f8: ceq
IL_00fa: ldc.i4.0
IL_00fb: ceq
IL_00fd: stloc.1
IL_00fe: ldloc.1
IL_00ff: brtrue.s IL_010e
IL_0101: nop
IL_0102: ldstr "0, 1"
IL_0107: call void [mscorlib]System.Console::WriteLine(string)
IL_010c: nop
IL_010d: nop
IL_010e: ldc.i4.0
IL_010f: stloc.0
IL_0110: br.s IL_0116
IL_0112: ldc.i4.1
IL_0113: stloc.0
IL_0114: br.s IL_0116
IL_0116: ldloc.0
IL_0117: ret
} // end of method Switch::SwitchlikeIf
.method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed
{
// Code size 80 (0x50)
.maxstack 2
.locals init (bool V_0,
bool V_1)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: ceq
IL_0005: stloc.1
IL_0006: ldloc.1
IL_0007: brtrue.s IL_004a
IL_0009: nop
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: ceq
IL_000e: ldc.i4.0
IL_000f: ceq
IL_0011: stloc.1
IL_0012: ldloc.1
IL_0013: brtrue.s IL_001e
IL_0015: nop
IL_0016: ldc.i4.1
IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
IL_001c: nop
IL_001d: nop
IL_001e: ldarg.0
IL_001f: ldc.i4.2
IL_0020: ceq
IL_0022: ldc.i4.0
IL_0023: ceq
IL_0025: stloc.1
IL_0026: ldloc.1
IL_0027: brtrue.s IL_0032
IL_0029: nop
IL_002a: ldc.i4.2
IL_002b: call void [mscorlib]System.Console::WriteLine(int32)
IL_0030: nop
IL_0031: nop
IL_0032: ldarg.0
IL_0033: ldc.i4.3
IL_0034: ceq
IL_0036: ldc.i4.0
IL_0037: ceq
IL_0039: stloc.1
IL_003a: ldloc.1
IL_003b: brtrue.s IL_0046
IL_003d: nop
IL_003e: ldc.i4.3
IL_003f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0044: nop
IL_0045: nop
IL_0046: ldc.i4.0
IL_0047: stloc.0
IL_0048: br.s IL_004e
IL_004a: ldc.i4.0
IL_004b: stloc.0
IL_004c: br.s IL_004e
IL_004e: ldloc.0
IL_004f: ret
} // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SwitchWithReturnAndBreak(int32 i,
bool b) cil managed
{

126
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il

@ -1818,6 +1818,132 @@ @@ -1818,6 +1818,132 @@
IL_0061: ret
} // end of method Switch::IfChainWithCondition
.method public hidebysig static bool SwitchlikeIf(int32 i,
int32 j) cil managed
{
// Code size 148 (0x94)
.maxstack 2
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0050
IL_0003: ldarg.1
IL_0004: brfalse.s IL_0050
IL_0006: ldarg.0
IL_0007: ldc.i4.m1
IL_0008: bne.un.s IL_0018
IL_000a: ldarg.1
IL_000b: ldc.i4.m1
IL_000c: bne.un.s IL_0018
IL_000e: ldstr "-1, -1"
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: ldarg.0
IL_0019: ldc.i4.m1
IL_001a: bne.un.s IL_002a
IL_001c: ldarg.1
IL_001d: ldc.i4.1
IL_001e: bne.un.s IL_002a
IL_0020: ldstr "-1, 1"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: ldarg.0
IL_002b: ldc.i4.1
IL_002c: bne.un.s IL_003c
IL_002e: ldarg.1
IL_002f: ldc.i4.m1
IL_0030: bne.un.s IL_003c
IL_0032: ldstr "1, -1"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ldarg.0
IL_003d: ldc.i4.1
IL_003e: bne.un.s IL_004e
IL_0040: ldarg.1
IL_0041: ldc.i4.1
IL_0042: bne.un.s IL_004e
IL_0044: ldstr "1, 1"
IL_0049: call void [mscorlib]System.Console::WriteLine(string)
IL_004e: ldc.i4.0
IL_004f: ret
IL_0050: ldarg.0
IL_0051: brfalse.s IL_0071
IL_0053: ldarg.0
IL_0054: ldc.i4.m1
IL_0055: bne.un.s IL_0061
IL_0057: ldstr "-1, 0"
IL_005c: call void [mscorlib]System.Console::WriteLine(string)
IL_0061: ldarg.0
IL_0062: ldc.i4.1
IL_0063: bne.un.s IL_006f
IL_0065: ldstr "1, 0"
IL_006a: call void [mscorlib]System.Console::WriteLine(string)
IL_006f: ldc.i4.0
IL_0070: ret
IL_0071: ldarg.1
IL_0072: brfalse.s IL_0092
IL_0074: ldarg.1
IL_0075: ldc.i4.m1
IL_0076: bne.un.s IL_0082
IL_0078: ldstr "0, -1"
IL_007d: call void [mscorlib]System.Console::WriteLine(string)
IL_0082: ldarg.1
IL_0083: ldc.i4.1
IL_0084: bne.un.s IL_0090
IL_0086: ldstr "0, 1"
IL_008b: call void [mscorlib]System.Console::WriteLine(string)
IL_0090: ldc.i4.0
IL_0091: ret
IL_0092: ldc.i4.1
IL_0093: ret
} // end of method Switch::SwitchlikeIf
.method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed
{
// Code size 37 (0x25)
.maxstack 8
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0023
IL_0003: ldarg.0
IL_0004: ldc.i4.1
IL_0005: bne.un.s IL_000d
IL_0007: ldc.i4.1
IL_0008: call void [mscorlib]System.Console::WriteLine(int32)
IL_000d: ldarg.0
IL_000e: ldc.i4.2
IL_000f: bne.un.s IL_0017
IL_0011: ldc.i4.2
IL_0012: call void [mscorlib]System.Console::WriteLine(int32)
IL_0017: ldarg.0
IL_0018: ldc.i4.3
IL_0019: bne.un.s IL_0021
IL_001b: ldc.i4.3
IL_001c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0021: ldc.i4.0
IL_0022: ret
IL_0023: ldc.i4.0
IL_0024: ret
} // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SwitchWithReturnAndBreak(int32 i,
bool b) cil managed
{

126
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il

@ -1952,6 +1952,132 @@ @@ -1952,6 +1952,132 @@
IL_0061: ret
} // end of method Switch::IfChainWithCondition
.method public hidebysig static bool SwitchlikeIf(int32 i,
int32 j) cil managed
{
// Code size 148 (0x94)
.maxstack 2
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0050
IL_0003: ldarg.1
IL_0004: brfalse.s IL_0050
IL_0006: ldarg.0
IL_0007: ldc.i4.m1
IL_0008: bne.un.s IL_0018
IL_000a: ldarg.1
IL_000b: ldc.i4.m1
IL_000c: bne.un.s IL_0018
IL_000e: ldstr "-1, -1"
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: ldarg.0
IL_0019: ldc.i4.m1
IL_001a: bne.un.s IL_002a
IL_001c: ldarg.1
IL_001d: ldc.i4.1
IL_001e: bne.un.s IL_002a
IL_0020: ldstr "-1, 1"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: ldarg.0
IL_002b: ldc.i4.1
IL_002c: bne.un.s IL_003c
IL_002e: ldarg.1
IL_002f: ldc.i4.m1
IL_0030: bne.un.s IL_003c
IL_0032: ldstr "1, -1"
IL_0037: call void [mscorlib]System.Console::WriteLine(string)
IL_003c: ldarg.0
IL_003d: ldc.i4.1
IL_003e: bne.un.s IL_004e
IL_0040: ldarg.1
IL_0041: ldc.i4.1
IL_0042: bne.un.s IL_004e
IL_0044: ldstr "1, 1"
IL_0049: call void [mscorlib]System.Console::WriteLine(string)
IL_004e: ldc.i4.0
IL_004f: ret
IL_0050: ldarg.0
IL_0051: brfalse.s IL_0071
IL_0053: ldarg.0
IL_0054: ldc.i4.m1
IL_0055: bne.un.s IL_0061
IL_0057: ldstr "-1, 0"
IL_005c: call void [mscorlib]System.Console::WriteLine(string)
IL_0061: ldarg.0
IL_0062: ldc.i4.1
IL_0063: bne.un.s IL_006f
IL_0065: ldstr "1, 0"
IL_006a: call void [mscorlib]System.Console::WriteLine(string)
IL_006f: ldc.i4.0
IL_0070: ret
IL_0071: ldarg.1
IL_0072: brfalse.s IL_0092
IL_0074: ldarg.1
IL_0075: ldc.i4.m1
IL_0076: bne.un.s IL_0082
IL_0078: ldstr "0, -1"
IL_007d: call void [mscorlib]System.Console::WriteLine(string)
IL_0082: ldarg.1
IL_0083: ldc.i4.1
IL_0084: bne.un.s IL_0090
IL_0086: ldstr "0, 1"
IL_008b: call void [mscorlib]System.Console::WriteLine(string)
IL_0090: ldc.i4.0
IL_0091: ret
IL_0092: ldc.i4.1
IL_0093: ret
} // end of method Switch::SwitchlikeIf
.method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed
{
// Code size 37 (0x25)
.maxstack 8
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0023
IL_0003: ldarg.0
IL_0004: ldc.i4.1
IL_0005: bne.un.s IL_000d
IL_0007: ldc.i4.1
IL_0008: call void [mscorlib]System.Console::WriteLine(int32)
IL_000d: ldarg.0
IL_000e: ldc.i4.2
IL_000f: bne.un.s IL_0017
IL_0011: ldc.i4.2
IL_0012: call void [mscorlib]System.Console::WriteLine(int32)
IL_0017: ldarg.0
IL_0018: ldc.i4.3
IL_0019: bne.un.s IL_0021
IL_001b: ldc.i4.3
IL_001c: call void [mscorlib]System.Console::WriteLine(int32)
IL_0021: ldc.i4.0
IL_0022: ret
IL_0023: ldc.i4.0
IL_0024: ret
} // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SwitchWithReturnAndBreak(int32 i,
bool b) cil managed
{

258
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il

@ -2492,6 +2492,264 @@ @@ -2492,6 +2492,264 @@
IL_0096: ret
} // end of method Switch::IfChainWithCondition
.method public hidebysig static bool SwitchlikeIf(int32 i,
int32 j) cil managed
{
// Code size 270 (0x10e)
.maxstack 2
.locals init (bool V_0,
bool V_1,
bool V_2,
bool V_3,
bool V_4,
bool V_5,
bool V_6,
bool V_7,
bool V_8,
bool V_9,
bool V_10,
bool V_11)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: brfalse.s IL_000a
IL_0004: ldarg.1
IL_0005: ldc.i4.0
IL_0006: cgt.un
IL_0008: br.s IL_000b
IL_000a: ldc.i4.0
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_008a
IL_000f: nop
IL_0010: ldarg.0
IL_0011: ldc.i4.m1
IL_0012: bne.un.s IL_001a
IL_0014: ldarg.1
IL_0015: ldc.i4.m1
IL_0016: ceq
IL_0018: br.s IL_001b
IL_001a: ldc.i4.0
IL_001b: stloc.1
IL_001c: ldloc.1
IL_001d: brfalse.s IL_002c
IL_001f: nop
IL_0020: ldstr "-1, -1"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: nop
IL_002c: ldarg.0
IL_002d: ldc.i4.m1
IL_002e: bne.un.s IL_0036
IL_0030: ldarg.1
IL_0031: ldc.i4.1
IL_0032: ceq
IL_0034: br.s IL_0037
IL_0036: ldc.i4.0
IL_0037: stloc.2
IL_0038: ldloc.2
IL_0039: brfalse.s IL_0048
IL_003b: nop
IL_003c: ldstr "-1, 1"
IL_0041: call void [mscorlib]System.Console::WriteLine(string)
IL_0046: nop
IL_0047: nop
IL_0048: ldarg.0
IL_0049: ldc.i4.1
IL_004a: bne.un.s IL_0052
IL_004c: ldarg.1
IL_004d: ldc.i4.m1
IL_004e: ceq
IL_0050: br.s IL_0053
IL_0052: ldc.i4.0
IL_0053: stloc.3
IL_0054: ldloc.3
IL_0055: brfalse.s IL_0064
IL_0057: nop
IL_0058: ldstr "1, -1"
IL_005d: call void [mscorlib]System.Console::WriteLine(string)
IL_0062: nop
IL_0063: nop
IL_0064: ldarg.0
IL_0065: ldc.i4.1
IL_0066: bne.un.s IL_006e
IL_0068: ldarg.1
IL_0069: ldc.i4.1
IL_006a: ceq
IL_006c: br.s IL_006f
IL_006e: ldc.i4.0
IL_006f: stloc.s V_4
IL_0071: ldloc.s V_4
IL_0073: brfalse.s IL_0082
IL_0075: nop
IL_0076: ldstr "1, 1"
IL_007b: call void [mscorlib]System.Console::WriteLine(string)
IL_0080: nop
IL_0081: nop
IL_0082: ldc.i4.0
IL_0083: stloc.s V_5
IL_0085: br IL_010b
IL_008a: ldarg.0
IL_008b: ldc.i4.0
IL_008c: cgt.un
IL_008e: stloc.s V_6
IL_0090: ldloc.s V_6
IL_0092: brfalse.s IL_00c8
IL_0094: nop
IL_0095: ldarg.0
IL_0096: ldc.i4.m1
IL_0097: ceq
IL_0099: stloc.s V_7
IL_009b: ldloc.s V_7
IL_009d: brfalse.s IL_00ac
IL_009f: nop
IL_00a0: ldstr "-1, 0"
IL_00a5: call void [mscorlib]System.Console::WriteLine(string)
IL_00aa: nop
IL_00ab: nop
IL_00ac: ldarg.0
IL_00ad: ldc.i4.1
IL_00ae: ceq
IL_00b0: stloc.s V_8
IL_00b2: ldloc.s V_8
IL_00b4: brfalse.s IL_00c3
IL_00b6: nop
IL_00b7: ldstr "1, 0"
IL_00bc: call void [mscorlib]System.Console::WriteLine(string)
IL_00c1: nop
IL_00c2: nop
IL_00c3: ldc.i4.0
IL_00c4: stloc.s V_5
IL_00c6: br.s IL_010b
IL_00c8: ldarg.1
IL_00c9: ldc.i4.0
IL_00ca: cgt.un
IL_00cc: stloc.s V_9
IL_00ce: ldloc.s V_9
IL_00d0: brfalse.s IL_0106
IL_00d2: nop
IL_00d3: ldarg.1
IL_00d4: ldc.i4.m1
IL_00d5: ceq
IL_00d7: stloc.s V_10
IL_00d9: ldloc.s V_10
IL_00db: brfalse.s IL_00ea
IL_00dd: nop
IL_00de: ldstr "0, -1"
IL_00e3: call void [mscorlib]System.Console::WriteLine(string)
IL_00e8: nop
IL_00e9: nop
IL_00ea: ldarg.1
IL_00eb: ldc.i4.1
IL_00ec: ceq
IL_00ee: stloc.s V_11
IL_00f0: ldloc.s V_11
IL_00f2: brfalse.s IL_0101
IL_00f4: nop
IL_00f5: ldstr "0, 1"
IL_00fa: call void [mscorlib]System.Console::WriteLine(string)
IL_00ff: nop
IL_0100: nop
IL_0101: ldc.i4.0
IL_0102: stloc.s V_5
IL_0104: br.s IL_010b
IL_0106: ldc.i4.1
IL_0107: stloc.s V_5
IL_0109: br.s IL_010b
IL_010b: ldloc.s V_5
IL_010d: ret
} // end of method Switch::SwitchlikeIf
.method public hidebysig static bool SwitchlikeIf2(int32 i) cil managed
{
// Code size 74 (0x4a)
.maxstack 2
.locals init (bool V_0,
bool V_1,
bool V_2,
bool V_3,
bool V_4)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.0
IL_0003: cgt.un
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0042
IL_0009: nop
IL_000a: ldarg.0
IL_000b: ldc.i4.1
IL_000c: ceq
IL_000e: stloc.1
IL_000f: ldloc.1
IL_0010: brfalse.s IL_001b
IL_0012: nop
IL_0013: ldc.i4.1
IL_0014: call void [mscorlib]System.Console::WriteLine(int32)
IL_0019: nop
IL_001a: nop
IL_001b: ldarg.0
IL_001c: ldc.i4.2
IL_001d: ceq
IL_001f: stloc.2
IL_0020: ldloc.2
IL_0021: brfalse.s IL_002c
IL_0023: nop
IL_0024: ldc.i4.2
IL_0025: call void [mscorlib]System.Console::WriteLine(int32)
IL_002a: nop
IL_002b: nop
IL_002c: ldarg.0
IL_002d: ldc.i4.3
IL_002e: ceq
IL_0030: stloc.3
IL_0031: ldloc.3
IL_0032: brfalse.s IL_003d
IL_0034: nop
IL_0035: ldc.i4.3
IL_0036: call void [mscorlib]System.Console::WriteLine(int32)
IL_003b: nop
IL_003c: nop
IL_003d: ldc.i4.0
IL_003e: stloc.s V_4
IL_0040: br.s IL_0047
IL_0042: ldc.i4.0
IL_0043: stloc.s V_4
IL_0045: br.s IL_0047
IL_0047: ldloc.s V_4
IL_0049: ret
} // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SwitchWithReturnAndBreak(int32 i,
bool b) cil managed
{

12
ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

@ -206,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -206,7 +206,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// These goto statements may be "goto case x" or "goto default", but these are a hint that the original code was not a switch,
// and that the switch statement may be very poor quality.
// Thus the rule of thumb is no goto statements if the original code didn't include them
return !SwitchRequiresGoto();
return !SwitchUsesGoto();
}
/// <summary>
@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary>
/// Determines if the analysed switch can be constructed without any gotos
/// </summary>
private bool SwitchRequiresGoto()
private bool SwitchUsesGoto()
{
if (controlFlowGraph == null)
controlFlowGraph = new ControlFlowGraph(currentContainer, context.CancellationToken);
@ -253,8 +253,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -253,8 +253,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (caseNode.Predecessors.Any(n => !flowBlocks.Contains(n.UserData)))
return true;
// determine if the switch would have a single exit point (break target)
return !FindBreakTarget(caseNodes, defaultNode, out var _);
if (!FindBreakTarget(caseNodes, defaultNode, out var breakTarget))
return true; // more than one exit point, requires goto statements
// if the switch has a single break target there is one more hint
// The break target cannot be inlined, and should have a higher IL offset than anything in the switch body
return breakTarget?.UserIndex < caseNodes.Select(c => c.UserIndex).Max();
}
/// <summary>

Loading…
Cancel
Save