private void CollectObjectAssignmentsAndUses() { foreach (var block in BasicBlocks) { for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.ResultCount == 0 && node.OperandCount == 0) { continue; } var visitor = new OperandVisitor(node); foreach (var input in visitor.Input) { if (input.Type.IsReferenceType || input.Type.IsManagedPointer) { if (input.IsRegister) { registerRangeData[input.Register.Index].UseList.Add(node.Offset); } else if (input.IsStackLocal) { stackLocalRangeData[stack[input]].UseList.Add(node.Offset); } } else { if (input.IsRegister) { registerRangeData[input.Register.Index].KillList.Add(node.Offset); } else if (input.IsStackLocal) { stackLocalRangeData[stack[input]].KillList.Add(node.Offset); } } } foreach (var output in visitor.Output) { if (output.Type.IsReferenceType || output.Type.IsManagedPointer) { if (output.IsRegister) { registerRangeData[output.Register.Index].GenList.Add(node.Offset); } else if (output.IsStackLocal) { stackLocalRangeData[stack[output]].GenList.Add(node.Offset); } } } } } }
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 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 CollectObjectAssignmentsAndUses() { foreach (var block in BasicBlocks) { for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) continue; if (node.ResultCount == 0 && node.OperandCount == 0) continue; var visitor = new OperandVisitor(node); foreach (var input in visitor.Input) { if (input.Type.IsReferenceType || input.Type.IsManagedPointer) { if (input.IsCPURegister) registerRangeData[input.Register.Index].UseList.Add(node.Offset); else if (input.IsStackLocal) stackLocalRangeData[stack[input]].UseList.Add(node.Offset); } else { if (input.IsCPURegister) registerRangeData[input.Register.Index].KillList.Add(node.Offset); else if (input.IsStackLocal) stackLocalRangeData[stack[input]].KillList.Add(node.Offset); } } foreach (var output in visitor.Output) { if (output.Type.IsReferenceType || output.Type.IsManagedPointer) { if (output.IsCPURegister) registerRangeData[output.Register.Index].GenList.Add(node.Offset); else if (output.IsStackLocal) stackLocalRangeData[stack[output]].GenList.Add(node.Offset); } } } } }