Ejemplo n.º 1
0
        private void Alloc(RegisterClass @class)
        {
            if (Done.Get(@class) == Count.Get(@class))
            {
                return;
            }
            var list  = VaList[(int)@class];
            var count = Count.Get(@class);

            var state = VariableContext.State;
            //			var sVars = state.GetListByClass(@class);

            bool didWork;

            do
            {
                didWork = false;
                int i;
                for (i = 0; i < count; i++)
                {
                    var aVa = list[i];
                    var aVd = aVa.VariableData;

                    if ((aVa.Flags & (VariableFlags.RReg | VariableFlags.AllocRDone)) != VariableFlags.RReg)
                    {
                        continue;
                    }

                    var aIndex = aVd.RegisterIndex;
                    var bIndex = aVa.InRegIndex;

                    // Shouldn't be the same.
                    if (aIndex == bIndex)
                    {
                        throw new ArgumentException();
                    }

                    var bVd = state.GetListByClass(@class)[bIndex];
                    if (bVd != null)
                    {
                        var bVa = bVd.Attributes;

                        // Gp registers only - Swap two registers if we can solve two
                        // allocation tasks by a single 'xchg' instruction, swapping
                        // two registers required by the instruction/node or one register
                        // required with another non-required.
                        if (@class != RegisterClass.Gp)
                        {
                            continue;
                        }
                        Translator.SwapGp(aVd, bVd);

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        // Doublehit, two registers allocated by a single swap.
                        if (bVa != null && bVa.InRegIndex == aIndex)
                        {
                            bVa.Flags |= VariableFlags.AllocRDone;
                            Done.Add(@class);
                        }

                        didWork = true;
                    }
                    else if (aIndex != RegisterIndex.Invalid)
                    {
                        Translator.Move(aVd, @class, bIndex);
                        VariableContext.ClobberedRegs.Or(@class, Utils.Mask(bIndex));

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        didWork = true;
                    }
                    else
                    {
                        Translator.Alloc(aVd, @class, bIndex);
                        VariableContext.ClobberedRegs.Or(@class, Utils.Mask(bIndex));

                        aVa.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);

                        didWork = true;
                    }
                }
            }while (didWork);
        }
Ejemplo n.º 2
0
        private void Plan(RegisterClass @class)
        {
            if (Done.Get(@class) == Count.Get(@class))
            {
                return;
            }

            int i;
            int willAlloc = _willAlloc.Get(@class);
            int willFree  = 0;

            var list  = VaList[(int)@class];
            var count = Count.Get(@class);

            var state = VariableContext.State;

            // Calculate 'willAlloc' and 'willFree' masks based on mandatory masks.
            for (i = 0; i < count; i++)
            {
                var va = list[i];
                var vd = va.VariableData;

                var vaFlags  = va.Flags;
                var regIndex = vd.RegisterIndex;
                var regMask  = (regIndex != RegisterIndex.Invalid) ? Utils.Mask(regIndex) : 0;

                if ((vaFlags & VariableFlags.XReg) != 0)
                {
                    // Planning register allocation. First check whether the variable is
                    // already allocated in register and if it can stay allocated there.
                    //
                    // The following conditions may happen:
                    //
                    // a) Allocated register is one of the mandatoryRegs.
                    // b) Allocated register is one of the allocableRegs.
                    var mandatoryRegs = va.InRegs;
                    var allocableRegs = va.AllocableRegs;

                    if (regMask != 0)
                    {
                        // Special path for planning output-only registers.
                        if ((vaFlags & VariableFlags.XReg) == VariableFlags.WReg)
                        {
                            var outRegIndex = va.OutRegIndex;
                            mandatoryRegs = (outRegIndex != RegisterIndex.Invalid) ? Utils.Mask(outRegIndex) : 0;

                            if ((mandatoryRegs | allocableRegs).IsSet(regMask))
                            {
                                va.OutRegIndex = regIndex;
                                va.Flags      |= VariableFlags.AllocWDone;

                                if (mandatoryRegs.IsSet(regMask))
                                {
                                    // Case 'a' - 'willAlloc' contains initially all inRegs from all VarAttr's.
                                    if (!((willAlloc & regMask) != 0))
                                    {
                                        throw new ArgumentException();
                                    }
                                }
                                else
                                {
                                    // Case 'b'.
                                    va.OutRegIndex = regIndex;
                                    willAlloc     |= regMask;
                                }

                                Done.Add(@class);
                                continue;
                            }
                        }
                        else
                        {
                            if ((mandatoryRegs | allocableRegs).IsSet(regMask))
                            {
                                va.InRegIndex = regIndex;
                                va.Flags     |= VariableFlags.AllocRDone;

                                if (mandatoryRegs.IsSet(regMask))
                                {
                                    // Case 'a' - 'willAlloc' contains initially all inRegs from all VarAttr's.
                                    if (!((willAlloc & regMask) != 0))
                                    {
                                        throw new ArgumentException();
                                    }
                                }
                                else
                                {
                                    // Case 'b'.
                                    va.InRegs |= regMask;
                                    willAlloc |= regMask;
                                }

                                Done.Add(@class);
                                continue;
                            }
                        }
                    }

                    // Variable is not allocated or allocated in register that doesn't
                    // match inRegs or allocableRegs. The next step is to pick the best
                    // register for this variable. If `inRegs` contains any register the
                    // decision is simple - we have to follow, in other case will use
                    // the advantage of `guessAlloc()` to find a register (or registers)
                    // by looking ahead. But the best way to find a good register is not
                    // here since now we have no information about the registers that
                    // will be freed. So instead of finding register here, we just mark
                    // the current register (if variable is allocated) as `willFree` so
                    // the planner can use this information in the second step to plan the
                    // allocation as a whole.
                    willFree |= regMask;
                }
                else
                {
                    // Memory access - if variable is allocated it has to be freed.
                    if (regMask != 0)
                    {
                        willFree |= regMask;
                    }
                    else
                    {
                        va.Flags |= VariableFlags.AllocRDone;
                        Done.Add(@class);
                    }
                }
            }

            // Occupied registers without 'willFree' registers; contains basically
            // all the registers we can use to allocate variables without inRegs
            // speficied.
            var occupied  = state.Occupied.Get(@class) & ~willFree;
            var willSpill = 0;

            // Find the best registers for variables that are not allocated yet.
            for (i = 0; i < count; i++)
            {
                var va = list[i];
                var vd = va.VariableData;

                var vaFlags = va.Flags;

                if ((vaFlags & VariableFlags.XReg) != 0)
                {
                    if ((vaFlags & VariableFlags.XReg) == VariableFlags.WReg)
                    {
                        if (vaFlags.IsSet(VariableFlags.AllocWDone))
                        {
                            continue;
                        }

                        // Skip all registers that have assigned outRegIndex. Spill if occupied.
                        if (va.OutRegIndex != RegisterIndex.Invalid)
                        {
                            var outRegs = Utils.Mask(va.OutRegIndex);
                            willSpill |= occupied & outRegs;
                            continue;
                        }
                    }
                    else
                    {
                        if (vaFlags.IsSet(VariableFlags.AllocRDone))
                        {
                            continue;
                        }

                        // We skip all registers that have assigned inRegIndex, indicates that
                        // the register to allocate in is known.
                        if (va.InRegIndex != RegisterIndex.Invalid)
                        {
                            var inRegs = va.InRegs;
                            willSpill |= occupied & inRegs;
                            continue;
                        }
                    }

                    var m = va.InRegs;
                    if (va.OutRegIndex != RegisterIndex.Invalid)
                    {
                        m |= Utils.Mask(va.OutRegIndex);
                    }

                    m = va.AllocableRegs & ~(willAlloc ^ m);
                    m = GuessAlloc(vd, m, @class);
                    if (!(m != 0))
                    {
                        throw new ArgumentException();
                    }

                    var candidateRegs = m & ~occupied;
                    var homeMask      = vd.HomeMask;

                    if (candidateRegs == 0)
                    {
                        candidateRegs = m & occupied & ~state.Modified.Get(@class);
                        if (candidateRegs == 0)
                        {
                            candidateRegs = m;
                        }
                    }

                    // printf("CANDIDATE: %s %08X\n", vd->getName(), homeMask);
                    if (candidateRegs.IsSet(homeMask))
                    {
                        candidateRegs &= homeMask;
                    }

                    var regIndex = candidateRegs.FindFirstBit();
                    var regMask  = Utils.Mask(regIndex);

                    if ((vaFlags & VariableFlags.XReg) == VariableFlags.WReg)
                    {
                        va.OutRegIndex = regIndex;
                    }
                    else
                    {
                        va.InRegIndex = regIndex;
                        va.InRegs     = regMask;
                    }

                    willAlloc |= regMask;
                    willSpill |= regMask & occupied;
                    willFree  &= ~regMask;
                    occupied  |= regMask;
                }
                else if ((vaFlags & VariableFlags.XMem) != 0)
                {
                    var regIndex = vd.RegisterIndex;
                    if (regIndex != RegisterIndex.Invalid && (vaFlags & VariableFlags.XMem) != VariableFlags.WMem)
                    {
                        willSpill |= Utils.Mask(regIndex);
                    }
                }
            }

            _willSpill.Set(@class, willSpill);
            _willAlloc.Set(@class, willAlloc);
        }