Browse Source

Simplify logic.not in patterns

pull/4091/head
Daniel Grunwald 3 days ago
parent
commit
6fcb387ffb
  1. 34
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

34
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -92,7 +92,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// "logic.not(arg)" is sugar for "comp(arg != ldc.i4 0)" // "logic.not(arg)" is sugar for "comp(arg != ldc.i4 0)"
if (inst.MatchLogicNot(out var arg)) if (inst.MatchLogicNot(out var arg))
{ {
VisitLogicNot(inst, arg); var toVisit = HandleLogicNot(inst, arg, context);
(toVisit ?? arg).AcceptVisitor(this);
return; return;
} }
else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None else if (inst.Kind == ComparisonKind.Inequality && inst.LiftingKind == ComparisonLiftingKind.None
@ -238,9 +239,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
void VisitLogicNot(Comp inst, ILInstruction arg) /// <summary>
/// Handles combining negations with comparisons and logical operations.
/// Returns the instruction that `inst` was replaced with; or null is no transformation was made.
/// </summary>
static ILInstruction HandleLogicNot(Comp inst, ILInstruction arg, ILTransformContext context)
{ {
ILInstruction lhs, rhs;
if (arg is Comp comp) if (arg is Comp comp)
{ {
if ((!comp.InputType.IsFloatType() && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality()) if ((!comp.InputType.IsFloatType() && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality())
@ -250,10 +254,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
comp.AddILRange(inst); comp.AddILRange(inst);
inst.ReplaceWith(comp); inst.ReplaceWith(comp);
context.EndStep(comp); context.EndStep(comp);
return comp;
} }
comp.AcceptVisitor(this);
} }
else if (arg.MatchLogicAnd(out lhs, out rhs)) else if (arg.MatchLogicAnd(out var lhs, out var rhs))
{ {
// logic.not(if (lhs) rhs else ldc.i4 0) // logic.not(if (lhs) rhs else ldc.i4 0)
// ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs) // ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs)
@ -266,7 +270,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInst.FalseInst = Comp.LogicNot(rhs).WithILRange(inst); ifInst.FalseInst = Comp.LogicNot(rhs).WithILRange(inst);
inst.ReplaceWith(ifInst); inst.ReplaceWith(ifInst);
context.EndStep(ifInst); context.EndStep(ifInst);
ifInst.AcceptVisitor(this); return ifInst;
} }
else if (arg.MatchLogicOr(out lhs, out rhs)) else if (arg.MatchLogicOr(out lhs, out rhs))
{ {
@ -281,12 +285,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInst.FalseInst = new LdcI4(0).WithILRange(ldc1); ifInst.FalseInst = new LdcI4(0).WithILRange(ldc1);
inst.ReplaceWith(ifInst); inst.ReplaceWith(ifInst);
context.EndStep(ifInst); context.EndStep(ifInst);
ifInst.AcceptVisitor(this); return ifInst;
}
else
{
arg.AcceptVisitor(this);
} }
return null;
} }
protected internal override void VisitCall(Call inst) protected internal override void VisitCall(Call inst)
@ -1027,6 +1028,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.TestedOperand.AcceptVisitor(this); inst.TestedOperand.AcceptVisitor(this);
// Do not recurse into the sub-patterns: patterns are restricted to use only certain ILInstructions, // Do not recurse into the sub-patterns: patterns are restricted to use only certain ILInstructions,
// and arbitrary transforms might not stay within that allowed set of instructions. // and arbitrary transforms might not stay within that allowed set of instructions.
foreach (var subPattern in inst.SubPatterns)
{
// However, we still need to simplify negations:
foreach (var potentialNegation in subPattern.Descendants.OfType<Comp>())
{
if (potentialNegation.MatchLogicNot(out var arg))
{
HandleLogicNot(potentialNegation, arg, context);
}
}
}
} }
} }
} }

Loading…
Cancel
Save