void VisitLogicNot(Comp inst, ILInstruction arg) { ILInstruction lhs, rhs; if (arg is Comp comp) { if ((comp.InputType != StackType.F && !comp.IsLifted) || comp.Kind.IsEqualityOrInequality()) { context.Step("push negation into comparison", inst); comp.Kind = comp.Kind.Negate(); comp.AddILRange(inst.ILRange); inst.ReplaceWith(comp); } comp.AcceptVisitor(this); } else if (arg.MatchLogicAnd(out lhs, out rhs)) { // logic.not(if (lhs) rhs else ldc.i4 0) // ==> if (logic.not(lhs)) ldc.i4 1 else logic.not(rhs) context.Step("push negation into logic.and", inst); IfInstruction ifInst = (IfInstruction)arg; var ldc0 = ifInst.FalseInst; Debug.Assert(ldc0.MatchLdcI4(0)); ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange); ifInst.TrueInst = new LdcI4(1) { ILRange = ldc0.ILRange }; ifInst.FalseInst = Comp.LogicNot(rhs, inst.ILRange); inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else if (arg.MatchLogicOr(out lhs, out rhs)) { // logic.not(if (lhs) ldc.i4 1 else rhs) // ==> if (logic.not(lhs)) logic.not(rhs) else ldc.i4 0) context.Step("push negation into logic.or", inst); IfInstruction ifInst = (IfInstruction)arg; var ldc1 = ifInst.TrueInst; Debug.Assert(ldc1.MatchLdcI4(1)); ifInst.Condition = Comp.LogicNot(lhs, inst.ILRange); ifInst.TrueInst = Comp.LogicNot(rhs, inst.ILRange); ifInst.FalseInst = new LdcI4(0) { ILRange = ldc1.ILRange }; inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else { arg.AcceptVisitor(this); } }