// TODO: // 1. If first branch is to the next basic block, // then swap branch condition, replace branch target with jump target, and remove jump instruction. // part of code: ConditionCode = GetOppositeConditionCode(ConditionCode); // 2. If the basic block contains only a single jump instruction, rewrite all jumps to avoid it. protected override void Run() { var trace = CreateTrace(); for (int f = 0; f < BasicBlocks.Count - 1; f++) { var from = BasicBlocks[f]; var next = BasicBlocks[f + 1]; Context context = new Context(InstructionSet, from, from.EndIndex); context.GotoPrevious(); while (context.IsEmpty) { context.GotoPrevious(); } if (context.Instruction.FlowControl != FlowControl.UnconditionalBranch) continue; Debug.Assert(context.Instruction.FlowControl == FlowControl.UnconditionalBranch); Debug.Assert(context.BranchTargets.Length == 1); var target = context.BranchTargets[0]; if (next.Label != target) continue; context.Remove(); } }
public static Context CreateNewBlock(this InstructionSet instructionSet, BasicBlocks basicBlocks) { Context ctx = new Context(instructionSet); ctx.AppendInstruction(IRInstruction.BlockStart); int start = ctx.Index; ctx.AppendInstruction(IRInstruction.BlockEnd); int last = ctx.Index; BasicBlock block = basicBlocks.CreateBlockWithAutoLabel(start, last); ctx.BasicBlock = block; ctx.GotoPrevious(); return ctx; }
/// <summary> /// Replaces the branch targets. /// </summary> /// <param name="block">The current from block.</param> /// <param name="oldTarget">The current destination block.</param> /// <param name="newTarget">The new target block.</param> protected void ReplaceBranchTargets(BasicBlock block, BasicBlock oldTarget, BasicBlock newTarget) { // Replace any jump/branch target in block (from) with js var ctx = new Context(InstructionSet, block, block.EndIndex); Debug.Assert(ctx.IsBlockEndInstruction); do { ctx.GotoPrevious(); } while (ctx.IsEmpty); // Find branch or jump to (to) and replace it with js while (!ctx.IsBlockStartInstruction) { if (ctx.BranchTargets != null) { var targets = ctx.BranchTargets; for (int index = 0; index < targets.Length; index++) { if (targets[index] == oldTarget.Label) targets[index] = newTarget.Label; } } do { ctx.GotoPrevious(); } while (ctx.IsEmpty); } }