Browse Source

Prefer simple if statements over switch with single case block

pull/1258/head
Chicken-Bones 7 years ago
parent
commit
d86f4b4132
  1. 8
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs
  2. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.il
  3. 19
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.il
  4. 19
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.opt.roslyn.il
  5. 33
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.roslyn.il
  6. 4
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

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

@ -987,6 +987,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
} }
return false; return false;
} }
public static void SingleIntervalIf(char c)
{
if (c >= 'A' && c <= 'Z') {
Console.WriteLine("alphabet");
}
Console.WriteLine("end");
}
public static bool Loop8(char c, bool b, Func<char> getChar) public static bool Loop8(char c, bool b, Func<char> getChar)
{ {

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

@ -3345,6 +3345,38 @@
IL_004f: ret IL_004f: ret
} // end of method Switch::SwitchlikeIf2 } // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SingleIntervalIf(char c) cil managed
{
// Code size 44 (0x2c)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 65
IL_0004: blt.s IL_000d
IL_0006: ldarg.0
IL_0007: ldc.i4.s 90
IL_0009: cgt
IL_000b: br.s IL_000e
IL_000d: ldc.i4.1
IL_000e: nop
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: brtrue.s IL_0020
IL_0013: nop
IL_0014: ldstr "alphabet"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: nop
IL_001f: nop
IL_0020: ldstr "end"
IL_0025: call void [mscorlib]System.Console::WriteLine(string)
IL_002a: nop
IL_002b: ret
} // end of method Switch::SingleIntervalIf
.method public hidebysig static bool Loop8(char c, .method public hidebysig static bool Loop8(char c,
bool b, bool b,
class [mscorlib]System.Func`1<char> getChar) cil managed class [mscorlib]System.Func`1<char> getChar) cil managed

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

@ -2530,6 +2530,25 @@
IL_0024: ret IL_0024: ret
} // end of method Switch::SwitchlikeIf2 } // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SingleIntervalIf(char c) cil managed
{
// Code size 31 (0x1f)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 65
IL_0003: blt.s IL_0014
IL_0005: ldarg.0
IL_0006: ldc.i4.s 90
IL_0008: bgt.s IL_0014
IL_000a: ldstr "alphabet"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: ldstr "end"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: ret
} // end of method Switch::SingleIntervalIf
.method public hidebysig static bool Loop8(char c, .method public hidebysig static bool Loop8(char c,
bool b, bool b,
class [mscorlib]System.Func`1<char> getChar) cil managed class [mscorlib]System.Func`1<char> getChar) cil managed

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

@ -2691,6 +2691,25 @@
IL_0024: ret IL_0024: ret
} // end of method Switch::SwitchlikeIf2 } // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SingleIntervalIf(char c) cil managed
{
// Code size 31 (0x1f)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 65
IL_0003: blt.s IL_0014
IL_0005: ldarg.0
IL_0006: ldc.i4.s 90
IL_0008: bgt.s IL_0014
IL_000a: ldstr "alphabet"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: ldstr "end"
IL_0019: call void [mscorlib]System.Console::WriteLine(string)
IL_001e: ret
} // end of method Switch::SingleIntervalIf
.method public hidebysig static bool Loop8(char c, .method public hidebysig static bool Loop8(char c,
bool b, bool b,
class [mscorlib]System.Func`1<char> getChar) cil managed class [mscorlib]System.Func`1<char> getChar) cil managed

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

@ -3694,6 +3694,39 @@
IL_0049: ret IL_0049: ret
} // end of method Switch::SwitchlikeIf2 } // end of method Switch::SwitchlikeIf2
.method public hidebysig static void SingleIntervalIf(char c) cil managed
{
// Code size 46 (0x2e)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 65
IL_0004: blt.s IL_0010
IL_0006: ldarg.0
IL_0007: ldc.i4.s 90
IL_0009: cgt
IL_000b: ldc.i4.0
IL_000c: ceq
IL_000e: br.s IL_0011
IL_0010: ldc.i4.0
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: brfalse.s IL_0022
IL_0015: nop
IL_0016: ldstr "alphabet"
IL_001b: call void [mscorlib]System.Console::WriteLine(string)
IL_0020: nop
IL_0021: nop
IL_0022: ldstr "end"
IL_0027: call void [mscorlib]System.Console::WriteLine(string)
IL_002c: nop
IL_002d: ret
} // end of method Switch::SingleIntervalIf
.method public hidebysig static bool Loop8(char c, .method public hidebysig static bool Loop8(char c,
bool b, bool b,
class [mscorlib]System.Func`1<char> getChar) cil managed class [mscorlib]System.Func`1<char> getChar) cil managed

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

@ -197,6 +197,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// heuristic to determine if a block would be better represented as an if statement rather than a case statement // heuristic to determine if a block would be better represented as an if statement rather than a case statement
if (ifCount < labelCount) if (ifCount < labelCount)
return false; return false;
// don't create switch statements with only one non-default label (provided the if option is short enough)
if (analysis.Sections.Count == 2 && ifCount <= 2)
return false;
// if there is no ILSwitch, there's still many control flow patterns that // if there is no ILSwitch, there's still many control flow patterns that
// match a switch statement but were originally just regular if statements, // match a switch statement but were originally just regular if statements,

Loading…
Cancel
Save