|
|
@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
public bool Run(IfInstruction ifInst) |
|
|
|
public bool Run(IfInstruction ifInst) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var lifted = Lift(ifInst, ifInst.TrueInst, ifInst.FalseInst); |
|
|
|
var lifted = Lift(ifInst, ifInst.Condition, ifInst.TrueInst, ifInst.FalseInst); |
|
|
|
if (lifted != null) { |
|
|
|
if (lifted != null) { |
|
|
|
ifInst.ReplaceWith(lifted); |
|
|
|
ifInst.ReplaceWith(lifted); |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -64,6 +64,25 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
|
|
/// VS2017.8 / Roslyn 2.9 started optimizing some cases of
|
|
|
|
|
|
|
|
/// "a.GetValueOrDefault() == b.GetValueOrDefault() && (a.HasValue & b.HasValue)"
|
|
|
|
|
|
|
|
/// to
|
|
|
|
|
|
|
|
/// "(a.GetValueOrDefault() == b.GetValueOrDefault()) & (a.HasValue & b.HasValue)"
|
|
|
|
|
|
|
|
/// so this secondary entry point analyses logic.and as-if it was a short-circuting &&.
|
|
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
|
|
public bool Run(BinaryNumericInstruction bni) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Debug.Assert(!bni.IsLifted && bni.Operator == BinaryNumericOperator.BitAnd); |
|
|
|
|
|
|
|
// caller ensures that bni.Left/bni.Right are booleans
|
|
|
|
|
|
|
|
var lifted = Lift(bni, bni.Left, bni.Right, new LdcI4(0)); |
|
|
|
|
|
|
|
if (lifted != null) { |
|
|
|
|
|
|
|
bni.ReplaceWith(lifted); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public bool RunStatements(Block block, int pos) |
|
|
|
public bool RunStatements(Block block, int pos) |
|
|
|
{ |
|
|
|
{ |
|
|
|
/// e.g.:
|
|
|
|
/// e.g.:
|
|
|
@ -85,7 +104,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
if (elseLeave.TargetContainer != thenLeave.TargetContainer) |
|
|
|
if (elseLeave.TargetContainer != thenLeave.TargetContainer) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
var lifted = Lift(ifInst, thenLeave.Value, elseLeave.Value); |
|
|
|
var lifted = Lift(ifInst, ifInst.Condition, thenLeave.Value, elseLeave.Value); |
|
|
|
if (lifted != null) { |
|
|
|
if (lifted != null) { |
|
|
|
thenLeave.Value = lifted; |
|
|
|
thenLeave.Value = lifted; |
|
|
|
ifInst.ReplaceWith(thenLeave); |
|
|
|
ifInst.ReplaceWith(thenLeave); |
|
|
@ -118,14 +137,15 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
/// Main entry point for lifting; called by both the expression-transform
|
|
|
|
/// Main entry point for lifting; called by both the expression-transform
|
|
|
|
/// and the block transform.
|
|
|
|
/// and the block transform.
|
|
|
|
/// </summary>
|
|
|
|
/// </summary>
|
|
|
|
ILInstruction Lift(IfInstruction ifInst, ILInstruction trueInst, ILInstruction falseInst) |
|
|
|
ILInstruction Lift(ILInstruction ifInst, ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ILInstruction condition = ifInst.Condition; |
|
|
|
// ifInst is usually the IfInstruction to which condition belongs;
|
|
|
|
|
|
|
|
// but can also be a BinaryNumericInstruction.
|
|
|
|
while (condition.MatchLogicNot(out var arg)) { |
|
|
|
while (condition.MatchLogicNot(out var arg)) { |
|
|
|
condition = arg; |
|
|
|
condition = arg; |
|
|
|
ExtensionMethods.Swap(ref trueInst, ref falseInst); |
|
|
|
ExtensionMethods.Swap(ref trueInst, ref falseInst); |
|
|
|
} |
|
|
|
} |
|
|
|
if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst)) { |
|
|
|
if (context.Settings.NullPropagation && !NullPropagationTransform.IsProtectedIfInst(ifInst as IfInstruction)) { |
|
|
|
var nullPropagated = new NullPropagationTransform(context) |
|
|
|
var nullPropagated = new NullPropagationTransform(context) |
|
|
|
.Run(condition, trueInst, falseInst, ifInst.ILRange); |
|
|
|
.Run(condition, trueInst, falseInst, ifInst.ILRange); |
|
|
|
if (nullPropagated != null) |
|
|
|
if (nullPropagated != null) |
|
|
|