public AllocationResult RunPass(ControlFlowGraph cfg, StackAllocator stackAlloc, RegisterMasks regMasks) { int intUsedRegisters = 0; int vecUsedRegisters = 0; int intFreeRegisters = regMasks.IntAvailableRegisters; int vecFreeRegisters = regMasks.VecAvailableRegisters; var blockInfo = new BlockInfo[cfg.Blocks.Count]; var localInfo = new LocalInfo[cfg.Blocks.Count * 3]; int localInfoCount = 0; // The "visited" state is stored in the MSB of the local's value. const ulong VisitedMask = 1ul << 63; bool IsVisited(Operand local) { return((local.GetValueUnsafe() & VisitedMask) != 0); } void SetVisited(Operand local) { local.GetValueUnsafe() |= VisitedMask | (uint)++localInfoCount; } ref LocalInfo GetLocalInfo(Operand local) { Debug.Assert(local.Kind == OperandKind.LocalVariable); if (!IsVisited(local)) { throw new InvalidOperationException("Local was not visisted yet. Used before defined?"); } return(ref localInfo[(uint)local.GetValueUnsafe() - 1]);
public AllocationContext(StackAllocator stackAlloc, RegisterMasks masks, int intervalsCount) { StackAlloc = stackAlloc; Masks = masks; Active = new BitMap(intervalsCount); Inactive = new BitMap(intervalsCount); }
public AllocationResult RunPass( ControlFlowGraph cfg, StackAllocator stackAlloc, RegisterMasks regMasks) { NumberLocals(cfg); AllocationContext context = new AllocationContext(stackAlloc, regMasks, _intervals.Count); BuildIntervals(cfg, context); for (int index = 0; index < _intervals.Count; index++) { LiveInterval current = _intervals[index]; if (current.IsEmpty) { continue; } if (current.IsFixed) { context.Active.Set(index); if (current.Register.Type == RegisterType.Integer) { context.IntUsedRegisters |= 1 << current.Register.Index; } else /* if (interval.Register.Type == RegisterType.Vector) */ { context.VecUsedRegisters |= 1 << current.Register.Index; } continue; } AllocateInterval(context, current, index); } for (int index = RegistersCount * 2; index < _intervals.Count; index++) { if (!_intervals[index].IsSpilled) { ReplaceLocalWithRegister(_intervals[index]); } } InsertSplitCopies(); InsertSplitCopiesAtEdges(cfg); return(new AllocationResult( context.IntUsedRegisters, context.VecUsedRegisters, context.StackAlloc.TotalSize)); }
public AllocationResult RunPass( ControlFlowGraph cfg, StackAllocator stackAlloc, RegisterMasks regMasks) { int intUsedRegisters = 0; int vecUsedRegisters = 0; int intFreeRegisters = regMasks.IntAvailableRegisters; int vecFreeRegisters = regMasks.VecAvailableRegisters; BlockInfo[] blockInfo = new BlockInfo[cfg.Blocks.Count]; List <LocalInfo> locInfo = new List <LocalInfo>(); for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--) { BasicBlock block = cfg.PostOrderBlocks[index]; int intFixedRegisters = 0; int vecFixedRegisters = 0; bool hasCall = false; foreach (Node node in block.Operations) { if (node is Operation operation && operation.Instruction == Instruction.Call) { hasCall = true; } for (int srcIndex = 0; srcIndex < node.SourcesCount; srcIndex++) { Operand source = node.GetSource(srcIndex); if (source.Kind == OperandKind.LocalVariable) { locInfo[source.AsInt32() - 1].SetBlockIndex(block.Index); } } for (int dstIndex = 0; dstIndex < node.DestinationsCount; dstIndex++) { Operand dest = node.GetDestination(dstIndex); if (dest.Kind == OperandKind.LocalVariable) { LocalInfo info; if (dest.Value != 0) { info = locInfo[dest.AsInt32() - 1]; } else { dest.NumberLocal(locInfo.Count + 1); info = new LocalInfo(dest.Type, UsesCount(dest)); locInfo.Add(info); } info.SetBlockIndex(block.Index); } else if (dest.Kind == OperandKind.Register) { if (dest.Type.IsInteger()) { intFixedRegisters |= 1 << dest.GetRegister().Index; } else { vecFixedRegisters |= 1 << dest.GetRegister().Index; } } } } blockInfo[block.Index] = new BlockInfo(hasCall, intFixedRegisters, vecFixedRegisters); } int sequence = 0; for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--) { BasicBlock block = cfg.PostOrderBlocks[index]; BlockInfo blkInfo = blockInfo[block.Index]; int intLocalFreeRegisters = intFreeRegisters & ~blkInfo.IntFixedRegisters; int vecLocalFreeRegisters = vecFreeRegisters & ~blkInfo.VecFixedRegisters; int intCallerSavedRegisters = blkInfo.HasCall ? regMasks.IntCallerSavedRegisters : 0; int vecCallerSavedRegisters = blkInfo.HasCall ? regMasks.VecCallerSavedRegisters : 0; int intSpillTempRegisters = SelectSpillTemps( intCallerSavedRegisters & ~blkInfo.IntFixedRegisters, intLocalFreeRegisters); int vecSpillTempRegisters = SelectSpillTemps( vecCallerSavedRegisters & ~blkInfo.VecFixedRegisters, vecLocalFreeRegisters); intLocalFreeRegisters &= ~(intSpillTempRegisters | intCallerSavedRegisters); vecLocalFreeRegisters &= ~(vecSpillTempRegisters | vecCallerSavedRegisters); for (LinkedListNode <Node> llNode = block.Operations.First; llNode != null; llNode = llNode.Next) { Node node = llNode.Value; int intLocalUse = 0; int vecLocalUse = 0; for (int srcIndex = 0; srcIndex < node.SourcesCount; srcIndex++) { Operand source = node.GetSource(srcIndex); if (source.Kind != OperandKind.LocalVariable) { continue; } LocalInfo info = locInfo[source.AsInt32() - 1]; info.UseCount++; Debug.Assert(info.UseCount <= info.Uses); if (info.Register != -1) { node.SetSource(srcIndex, Register(info.Register, source.Type.ToRegisterType(), source.Type)); if (info.UseCount == info.Uses && !info.PreAllocated) { if (source.Type.IsInteger()) { intLocalFreeRegisters |= 1 << info.Register; } else { vecLocalFreeRegisters |= 1 << info.Register; } } } else { Operand temp = info.Temp; if (temp == null || info.Sequence != sequence) { temp = source.Type.IsInteger() ? GetSpillTemp(source, intSpillTempRegisters, ref intLocalUse) : GetSpillTemp(source, vecSpillTempRegisters, ref vecLocalUse); info.Sequence = sequence; info.Temp = temp; } node.SetSource(srcIndex, temp); Operation fillOp = new Operation(Instruction.Fill, temp, Const(info.SpillOffset)); block.Operations.AddBefore(llNode, fillOp); } } int intLocalAsg = 0; int vecLocalAsg = 0; for (int dstIndex = 0; dstIndex < node.DestinationsCount; dstIndex++) { Operand dest = node.GetDestination(dstIndex); if (dest.Kind != OperandKind.LocalVariable) { continue; } LocalInfo info = locInfo[dest.AsInt32() - 1]; if (info.UseCount == 0 && !info.PreAllocated) { int mask = dest.Type.IsInteger() ? intLocalFreeRegisters : vecLocalFreeRegisters; if (info.IsBlockLocal && mask != 0) { int selectedReg = BitUtils.LowestBitSet(mask); info.Register = selectedReg; if (dest.Type.IsInteger()) { intLocalFreeRegisters &= ~(1 << selectedReg); intUsedRegisters |= 1 << selectedReg; } else { vecLocalFreeRegisters &= ~(1 << selectedReg); vecUsedRegisters |= 1 << selectedReg; } } else { info.Register = -1; info.SpillOffset = stackAlloc.Allocate(dest.Type.GetSizeInBytes()); } } info.UseCount++; Debug.Assert(info.UseCount <= info.Uses); if (info.Register != -1) { node.SetDestination(dstIndex, Register(info.Register, dest.Type.ToRegisterType(), dest.Type)); } else { Operand temp = info.Temp; if (temp == null || info.Sequence != sequence) { temp = dest.Type.IsInteger() ? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg) : GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg); info.Sequence = sequence; info.Temp = temp; } node.SetDestination(dstIndex, temp); Operation spillOp = new Operation(Instruction.Spill, null, Const(info.SpillOffset), temp); llNode = block.Operations.AddAfter(llNode, spillOp); } } sequence++; intUsedRegisters |= intLocalAsg | intLocalUse; vecUsedRegisters |= vecLocalAsg | vecLocalUse; } } return(new AllocationResult(intUsedRegisters, vecUsedRegisters, stackAlloc.TotalSize)); }
public AllocationResult RunPass( ControlFlowGraph cfg, StackAllocator stackAlloc, RegisterMasks regMasks) { int intUsedRegisters = 0; int vecUsedRegisters = 0; int intFreeRegisters = regMasks.IntAvailableRegisters; int vecFreeRegisters = regMasks.VecAvailableRegisters; var blockInfo = new BlockInfo[cfg.Blocks.Count]; var locInfo = new List <LocalInfo>(); var locVisited = new HashSet <Operand>(); for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--) { BasicBlock block = cfg.PostOrderBlocks[index]; int intFixedRegisters = 0; int vecFixedRegisters = 0; bool hasCall = false; for (Node node = block.Operations.First; node != null; node = node.ListNext) { if (node is Operation operation && operation.Instruction == Instruction.Call) { hasCall = true; } for (int srcIndex = 0; srcIndex < node.SourcesCount; srcIndex++) { Operand source = node.GetSource(srcIndex); if (source.Kind == OperandKind.LocalVariable) { locInfo[source.GetLocalNumber() - 1].SetBlockIndex(block.Index); } else if (source.Kind == OperandKind.Memory) { MemoryOperand memOp = (MemoryOperand)source; if (memOp.BaseAddress != null) { locInfo[memOp.BaseAddress.GetLocalNumber() - 1].SetBlockIndex(block.Index); } if (memOp.Index != null) { locInfo[memOp.Index.GetLocalNumber() - 1].SetBlockIndex(block.Index); } } } for (int dstIndex = 0; dstIndex < node.DestinationsCount; dstIndex++) { Operand dest = node.GetDestination(dstIndex); if (dest.Kind == OperandKind.LocalVariable) { LocalInfo info; if (!locVisited.Add(dest)) { info = locInfo[dest.GetLocalNumber() - 1]; } else { dest.NumberLocal(locInfo.Count + 1); info = new LocalInfo(dest.Type, UsesCount(dest)); locInfo.Add(info); } info.SetBlockIndex(block.Index); } else if (dest.Kind == OperandKind.Register) { if (dest.Type.IsInteger()) { intFixedRegisters |= 1 << dest.GetRegister().Index; } else { vecFixedRegisters |= 1 << dest.GetRegister().Index; } } } } blockInfo[block.Index] = new BlockInfo(hasCall, intFixedRegisters, vecFixedRegisters); } int sequence = 0; for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--) { BasicBlock block = cfg.PostOrderBlocks[index]; BlockInfo blkInfo = blockInfo[block.Index]; int intLocalFreeRegisters = intFreeRegisters & ~blkInfo.IntFixedRegisters; int vecLocalFreeRegisters = vecFreeRegisters & ~blkInfo.VecFixedRegisters; int intCallerSavedRegisters = blkInfo.HasCall ? regMasks.IntCallerSavedRegisters : 0; int vecCallerSavedRegisters = blkInfo.HasCall ? regMasks.VecCallerSavedRegisters : 0; int intSpillTempRegisters = SelectSpillTemps( intCallerSavedRegisters & ~blkInfo.IntFixedRegisters, intLocalFreeRegisters); int vecSpillTempRegisters = SelectSpillTemps( vecCallerSavedRegisters & ~blkInfo.VecFixedRegisters, vecLocalFreeRegisters); intLocalFreeRegisters &= ~(intSpillTempRegisters | intCallerSavedRegisters); vecLocalFreeRegisters &= ~(vecSpillTempRegisters | vecCallerSavedRegisters); for (Node node = block.Operations.First; node != null; node = node.ListNext) { int intLocalUse = 0; int vecLocalUse = 0; void AllocateRegister(Operand source, MemoryOperand memOp, int srcIndex) { LocalInfo info = locInfo[source.GetLocalNumber() - 1]; info.UseCount++; Debug.Assert(info.UseCount <= info.Uses); if (info.Register != -1) { Operand reg = Register(info.Register, source.Type.ToRegisterType(), source.Type); if (memOp != null) { if (srcIndex == 0) { memOp.BaseAddress = reg; } else /* if (srcIndex == 1) */ { memOp.Index = reg; } } else { node.SetSource(srcIndex, reg); } if (info.UseCount == info.Uses && !info.PreAllocated) { if (source.Type.IsInteger()) { intLocalFreeRegisters |= 1 << info.Register; } else { vecLocalFreeRegisters |= 1 << info.Register; } } } else if (node is Operation operation && operation.Instruction == Instruction.Copy) { Operation fillOp = Operation(Instruction.Fill, node.Destination, Const(info.SpillOffset)); block.Operations.AddBefore(node, fillOp); block.Operations.Remove(node); node = fillOp; }