private void RemoveBlock(BasicBlock block, CompilerTrace trace) { Debug.Assert(block.NextBlocks.Count == 1); BasicBlock target = block.NextBlocks[0]; if (trace.Active) { trace.Log("====== Removing: " + block.ToString() + " # " + block.Sequence); trace.Log(" New Target: " + target.ToString()); foreach (var from in block.PreviousBlocks) { trace.Log("Previous Blocks: " + from.ToString()); } } target.PreviousBlocks.Remove(block); foreach (var from in block.PreviousBlocks) { from.NextBlocks.Remove(block); from.NextBlocks.AddIfNew(target); if (trace.Active) { trace.Log(" Add target to NextBlock of " + from.ToString()); } target.PreviousBlocks.AddIfNew(from); if (trace.Active) { trace.Log(" Add " + from.ToString() + " to PreviousBlock of " + target.ToString()); } ReplaceBranchTargets(from, block, target); } block.NextBlocks.Clear(); block.PreviousBlocks.Clear(); EmptyBlockOfAllInstructions(block); }
private void NumberInstructions() { var number = new CompilerTrace(trace, "InstructionNumber"); int index = SlotIncrement; foreach (BasicBlock block in basicBlocks) { for (Context context = new Context(instructionSet, block); ; context.GotoNext()) { if (!context.IsEmpty) { context.SlotNumber = index; index = index + SlotIncrement; if (number.Active) { if (context.IsBlockStartInstruction) { number.Log(context.SlotNumber.ToString() + " = " + context.ToString() + " # " + block.ToString()); } else { number.Log(context.SlotNumber.ToString() + " = " + context.ToString()); } } } if (context.IsBlockEndInstruction) break; } SlotIndex start = new SlotIndex(instructionSet, block.StartIndex); SlotIndex end = new SlotIndex(instructionSet, block.EndIndex); extendedBlocks[block.Sequence].Interval = new Interval(start, end); } }
private void InsertRegisterMoves() { var insertTrace = new CompilerTrace(trace, "InsertRegisterMoves"); // collect edge slot indexes Dictionary<SlotIndex, ExtendedBlock> blockEdges = new Dictionary<SlotIndex, ExtendedBlock>(); foreach (var block in extendedBlocks) { blockEdges.Add(block.Start, block); blockEdges.Add(block.End, block); } foreach (var virtualRegister in virtualRegisters) { if (virtualRegister.IsPhysicalRegister) continue; if (virtualRegister.LiveIntervals.Count <= 1) continue; foreach (var currentInterval in virtualRegister.LiveIntervals) { if (blockEdges.ContainsKey(currentInterval.End)) continue; // List is not sorted, so scan thru each one foreach (var nextInterval in virtualRegister.LiveIntervals) { if (nextInterval.Start == currentInterval.End) { // next interval is stack - stores to stack are done elsewhere if (nextInterval.AssignedPhysicalOperand == null) break; // check if source and destination operands of the move are the same if (nextInterval.AssignedOperand == currentInterval.AssignedOperand || nextInterval.AssignedOperand.Register == currentInterval.AssignedOperand.Register) break; Context context = new Context(instructionSet, currentInterval.End.Index); context.GotoPrevious(); while (context.IsEmpty || context.Instruction.FlowControl == FlowControl.UnconditionalBranch || context.Instruction.FlowControl == FlowControl.ConditionalBranch || context.Instruction.FlowControl == FlowControl.Return) { context.GotoPrevious(); } architecture.InsertMoveInstruction(context, nextInterval.AssignedOperand, currentInterval.AssignedOperand ); context.Marked = true; if (insertTrace.Active) { insertTrace.Log("REGISTER: " + virtualRegister.ToString()); insertTrace.Log("POSITION: " + currentInterval.End.ToString()); insertTrace.Log(" FROM: " + currentInterval.AssignedOperand.ToString()); insertTrace.Log(" TO: " + nextInterval.AssignedOperand.ToString()); insertTrace.Log(""); } break; } } } } }
private void ComputeLocalLiveSets() { var liveSetTrace = new CompilerTrace(trace, "ComputeLocalLiveSets"); foreach (var block in extendedBlocks) { if (liveSetTrace.Active) liveSetTrace.Log("Block # " + block.BasicBlock.Sequence.ToString()); BitArray liveGen = new BitArray(registerCount, false); BitArray liveKill = new BitArray(registerCount, false); liveGen.Set(stackFrameRegister.Index, true); liveGen.Set(stackPointerRegister.Index, true); if (programCounter != null) liveGen.Set(programCounter.Index, true); for (Context context = new Context(instructionSet, block.BasicBlock); !context.IsBlockEndInstruction; context.GotoNext()) { if (context.IsEmpty) continue; if (liveSetTrace.Active) liveSetTrace.Log(context.ToString()); OperandVisitor visitor = new OperandVisitor(context); foreach (var ops in visitor.Input) { if (liveSetTrace.Active) liveSetTrace.Log("INPUT: " + ops.ToString()); int index = GetIndex(ops); if (!liveKill.Get(index)) { liveGen.Set(index, true); if (liveSetTrace.Active) liveSetTrace.Log("GEN: " + index.ToString() + " " + ops.ToString()); } } if (context.Instruction.FlowControl == FlowControl.Call) { for (int s = 0; s < physicalRegisterCount; s++) { liveKill.Set(s, true); } if (liveSetTrace.Active) liveSetTrace.Log("KILL ALL PHYSICAL"); } foreach (var ops in visitor.Output) { if (liveSetTrace.Active) liveSetTrace.Log("OUTPUT: " + ops.ToString()); int index = GetIndex(ops); liveKill.Set(index, true); if (liveSetTrace.Active) liveSetTrace.Log("KILL: " + index.ToString() + " " + ops.ToString()); } } block.LiveGen = liveGen; block.LiveKill = liveKill; block.LiveKillNot = ((BitArray)liveKill.Clone()).Not(); if (liveSetTrace.Active) { liveSetTrace.Log("GEN: " + ToString(block.LiveGen)); liveSetTrace.Log("KILL: " + ToString(block.LiveKill)); liveSetTrace.Log("KILLNOT: " + ToString(block.LiveKillNot)); liveSetTrace.Log(string.Empty); } } }
private void BuildLiveIntervals() { var intervalTrace = new CompilerTrace(trace, "BuildLiveIntervals"); for (int b = basicBlocks.Count - 1; b >= 0; b--) { var block = extendedBlocks[b]; for (int r = 0; r < registerCount; r++) { if (!block.LiveOut.Get(r)) continue; var register = virtualRegisters[r]; if (b + 1 != basicBlocks.Count && extendedBlocks[b + 1].LiveIn.Get(r)) { if (intervalTrace.Active) intervalTrace.Log("Add (LiveOut) " + register.ToString() + " : " + block.Start + " to " + extendedBlocks[b + 1].Start); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Start, extendedBlocks[b + 1].Start); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } else { if (intervalTrace.Active) intervalTrace.Log("Add (!LiveOut) " + register.ToString() + " : " + block.Interval.Start + " to " + block.Interval.End); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Interval); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } Context context = new Context(instructionSet, block.BasicBlock, block.BasicBlock.EndIndex); while (!context.IsBlockStartInstruction) { if (!context.IsEmpty) { SlotIndex slotIndex = new SlotIndex(context); OperandVisitor visitor = new OperandVisitor(context); if (context.Instruction.FlowControl == FlowControl.Call) { SlotIndex nextSlotIndex = slotIndex.Next; for (int s = 0; s < physicalRegisterCount; s++) { var register = virtualRegisters[s]; if (intervalTrace.Active) intervalTrace.Log("Add (Call) " + register.ToString() + " : " + slotIndex + " to " + nextSlotIndex); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(slotIndex, nextSlotIndex); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } callSlots.Add(slotIndex); } foreach (var result in visitor.Output) { var register = virtualRegisters[GetIndex(result)]; if (register.IsReserved) continue; var first = register.FirstRange; if (!register.IsPhysicalRegister) { register.AddDefPosition(slotIndex); } if (first != null) { if (intervalTrace.Active) intervalTrace.Log("Replace First " + register.ToString() + " : " + slotIndex + " to " + first.End); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.FirstRange = new LiveInterval(register, slotIndex, first.End); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } else { // This is necesary to handled a result that is never used! // Common with instructions which more than one result if (intervalTrace.Active) intervalTrace.Log("Add (Unused) " + register.ToString() + " : " + slotIndex + " to " + slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(slotIndex, slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } foreach (var result in visitor.Input) { var register = virtualRegisters[GetIndex(result)]; if (register.IsReserved) continue; if (!register.IsPhysicalRegister) { register.AddUsePosition(slotIndex); } if (intervalTrace.Active) intervalTrace.Log("Add (normal) " + register.ToString() + " : " + block.Start + " to " + slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" Before: " + LiveIntervalsToString(register.LiveIntervals)); register.AddLiveInterval(block.Start, slotIndex.Next); if (intervalTrace.Active) intervalTrace.Log(" After: " + LiveIntervalsToString(register.LiveIntervals)); } } context.GotoPrevious(); } } }
private void TraceMoveHints() { if (!trace.Active) return; var moveHintTrace = new CompilerTrace(trace, "Move Hints"); foreach (var moveHint in moveHints) { moveHintTrace.Log(moveHint.Value.ToString()); } }
private void TraceLiveIntervals(string stage, bool operand) { if (!trace.Active) return; var registerTrace = new CompilerTrace(trace, stage); foreach (var virtualRegister in virtualRegisters) { if (virtualRegister.IsPhysicalRegister) { registerTrace.Log("Physical Register # " + virtualRegister.PhysicalRegister.ToString()); } else { registerTrace.Log("Virtual Register # " + virtualRegister.VirtualRegisterOperand.Index.ToString()); } registerTrace.Log("Live Intervals (" + virtualRegister.LiveIntervals.Count.ToString() + "): " + LiveIntervalsToString(virtualRegister.LiveIntervals, operand)); registerTrace.Log("Def Positions (" + virtualRegister.DefPositions.Count.ToString() + "): " + SlotsToString(virtualRegister.DefPositions)); registerTrace.Log("Use Positions (" + virtualRegister.UsePositions.Count.ToString() + "): " + SlotsToString(virtualRegister.UsePositions)); } }
private void TraceBlocks() { if (!trace.Active) return; var sectionTrace = new CompilerTrace(trace, "Extended Blocks"); foreach (var block in extendedBlocks) { sectionTrace.Log("Block # " + block.BasicBlock.Sequence.ToString() + " (" + block.Start + " to " + block.End + ")"); sectionTrace.Log(" LiveIn: " + ToString(block.LiveIn)); sectionTrace.Log(" LiveGen: " + ToString(block.LiveGen)); sectionTrace.Log(" LiveKill: " + ToString(block.LiveKill)); sectionTrace.Log(" LiveOut: " + ToString(block.LiveOut)); } }
private void ResolveDataFlow() { var resolverTrace = new CompilerTrace(trace, "ResolveDataFlow"); MoveResolver[,] moveResolvers = new MoveResolver[2, basicBlocks.Count]; foreach (var from in extendedBlocks) { foreach (var nextBlock in from.BasicBlock.NextBlocks) { var to = extendedBlocks[nextBlock.Sequence]; // determine where to insert resolving moves bool fromAnchorFlag = (from.BasicBlock.NextBlocks.Count == 1); ExtendedBlock anchor = fromAnchorFlag ? from : to; MoveResolver moveResolver = moveResolvers[fromAnchorFlag ? 0 : 1, anchor.Sequence]; if (moveResolver == null) { moveResolver = new MoveResolver(anchor.BasicBlock, from.BasicBlock, to.BasicBlock); moveResolvers[fromAnchorFlag ? 0 : 1, anchor.Sequence] = moveResolver; } foreach (var virtualRegister in GetVirtualRegisters(to.LiveIn)) { //if (virtualRegister.IsPhysicalRegister) //continue; var fromLiveInterval = virtualRegister.GetIntervalAtOrEndsAt(from.End); var toLiveInterval = virtualRegister.GetIntervalAt(to.Start); Debug.Assert(fromLiveInterval != null); Debug.Assert(toLiveInterval != null); if (fromLiveInterval.AssignedPhysicalRegister != toLiveInterval.AssignedPhysicalRegister) { if (resolverTrace.Active) { resolverTrace.Log("REGISTER: " + fromLiveInterval.VirtualRegister.ToString()); resolverTrace.Log(" FROM: " + from.ToString().PadRight(7) + " " + fromLiveInterval.AssignedOperand.ToString()); resolverTrace.Log(" TO: " + to.ToString().PadRight(7) + " " + toLiveInterval.AssignedOperand.ToString()); resolverTrace.Log(" INSERT: " + (fromAnchorFlag ? "FROM (bottom)" : "TO (top)") + ((toLiveInterval.AssignedPhysicalOperand == null) ? " ****SKIPPED***" : string.Empty)); resolverTrace.Log(""); } // interval was spilled (spill moves are inserted elsewhere) if (toLiveInterval.AssignedPhysicalOperand == null) continue; Debug.Assert(from.BasicBlock.NextBlocks.Count == 1 || to.BasicBlock.PreviousBlocks.Count == 1); moveResolver.AddMove(fromLiveInterval.AssignedOperand, toLiveInterval.AssignedOperand); } } } } for (int b = 0; b < basicBlocks.Count; b++) { for (int fromTag = 0; fromTag < 2; fromTag++) { MoveResolver moveResolver = moveResolvers[fromTag, b]; if (moveResolver == null) continue; moveResolver.InsertResolvingMoves(architecture, instructionSet); } } }