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); } }
protected internal override void VisitLogicNot(LogicNot inst) { ILInstruction arg, lhs, rhs; if (inst.Argument.MatchLogicNot(out arg)) { context.Step("logic.not(logic.not(arg)) => arg", inst); Debug.Assert(arg.ResultType == StackType.I4); arg.AddILRange(inst.ILRange); arg.AddILRange(inst.Argument.ILRange); inst.ReplaceWith(arg); arg.AcceptVisitor(this); } else if (inst.Argument 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 (inst.Argument.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)inst.Argument; var ldc0 = ifInst.FalseInst; Debug.Assert(ldc0.MatchLdcI4(0)); ifInst.Condition = new LogicNot(lhs) { ILRange = inst.ILRange }; ifInst.TrueInst = new LdcI4(1) { ILRange = ldc0.ILRange }; ifInst.FalseInst = new LogicNot(rhs) { ILRange = inst.ILRange }; inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else if (inst.Argument.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)inst.Argument; var ldc1 = ifInst.TrueInst; Debug.Assert(ldc1.MatchLdcI4(1)); ifInst.Condition = new LogicNot(lhs) { ILRange = inst.ILRange }; ifInst.TrueInst = new LogicNot(rhs) { ILRange = inst.ILRange }; ifInst.FalseInst = new LdcI4(0) { ILRange = ldc1.ILRange }; inst.ReplaceWith(ifInst); ifInst.AcceptVisitor(this); } else { inst.Argument.AcceptVisitor(this); } }