/// <summary> /// For an if statement with an unreachable end point and no else block, /// inverts to match IL order of the first statement of each branch /// </summary> private void ImproveILOrdering(Block block, IfInstruction ifInst, Block continueTarget) { if (!block.HasFlag(InstructionFlags.EndPointUnreachable) || !ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable) || !ifInst.FalseInst.MatchNop()) { return; } Debug.Assert(ifInst != block.Instructions.Last()); var trueRangeStart = ConditionDetection.GetStartILOffset(ifInst.TrueInst, out bool trueRangeIsEmpty); var falseRangeStart = ConditionDetection.GetStartILOffset(block.Instructions[block.Instructions.IndexOf(ifInst) + 1], out bool falseRangeIsEmpty); if (trueRangeIsEmpty || falseRangeIsEmpty || falseRangeStart >= trueRangeStart) { return; } if (block.Instructions.Last() is Leave leave && !leave.IsLeavingFunction && leave.TargetContainer.Kind == ContainerKind.Normal) { // non-keyword leave. Can't move out of the last position in the block (fall-through) without introducing goto, unless it can be replaced with a keyword (return/continue) if (!CanDuplicateExit(block.Instructions.Last(), continueTarget, out var keywordExit)) { return; } context.Step("Replace leave with keyword exit", ifInst.TrueInst); block.Instructions.Last().ReplaceWith(keywordExit.Clone()); } ConditionDetection.InvertIf(block, ifInst, context); }
/// <summary> /// For an if statement with an unreachable end point and no else block, /// inverts to match IL order of the first statement of each branch /// </summary> private void ImproveILOrdering(Block block, IfInstruction ifInst) { if (!block.HasFlag(InstructionFlags.EndPointUnreachable) || !ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable) || !ifInst.FalseInst.MatchNop()) { return; } Debug.Assert(ifInst != block.Instructions.Last()); var trueRangeStart = ConditionDetection.GetStartILOffset(ifInst.TrueInst, out bool trueRangeIsEmpty); var falseRangeStart = ConditionDetection.GetStartILOffset(block.Instructions[block.Instructions.IndexOf(ifInst) + 1], out bool falseRangeIsEmpty); if (!trueRangeIsEmpty && !falseRangeIsEmpty && falseRangeStart < trueRangeStart) { ConditionDetection.InvertIf(block, ifInst, context); } }