/// <summary> /// Performs stage specific processing on the compiler context. /// </summary> public void Run() { bool remove = false; foreach (BasicBlock block in BasicBlocks) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { if (ctx.Instruction is IR.MoveInstruction || ctx.Instruction is CIL.StlocInstruction) { if (ctx.Operand1 is ConstantOperand) { // HACK: We can't track a constant through a register, so we keep those moves if (ctx.Result is StackOperand) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(ctx.Operand1, InstructionSet); remove = true; } } } else if (ctx.Instruction is IR.PhiInstruction) { IR.PhiInstruction phi = (IR.PhiInstruction)ctx.Instruction; ConstantOperand co = ctx.Operand2 as ConstantOperand; List <BasicBlock> blocks = ctx.Other as List <BasicBlock>; // FIXME PG / ctx has moved if (co != null && blocks.Count == 1) { // We can remove the phi, as it is only defined once // HACK: We can't track a constant through a register, so we keep those moves if (!ctx.Result.IsRegister) { Debug.Assert(ctx.Result.Definitions.Count == 1, @"Operand defined multiple times. Instruction stream not in SSA form!"); ctx.Result.Replace(co, InstructionSet); remove = true; } } } // Shall we remove this instruction? if (remove) { ctx.Remove(); remove = false; } } } }
private void MergePhiInstructions(BasicBlock block, BasicBlock caller, IDictionary <StackOperand, StackOperand> liveIn) { for (Context ctx = new Context(InstructionSet, block); !ctx.EndOfInstruction; ctx.GotoNext()) { IR.PhiInstruction phi = ctx.Instruction as IR.PhiInstruction; if (phi != null && liveIn.ContainsKey(ctx.Result as StackOperand)) { StackOperand value = liveIn[ctx.Result as StackOperand]; if (!IR.PhiInstruction.Contains(ctx, value) && (ctx.Result as StackOperand).Version != value.Version) { IR.PhiInstruction.AddValue(ctx, caller, value); } } } }