Exemplo n.º 1
0
        private void Spill(RegisterClass @class)
        {
            var m = _willSpill.Get(@class);
            var i = -1;

            if (m == 0)
            {
                return;
            }

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

            // Available registers for decision if move has any benefit over spill.
            var availableRegs = VariableContext.GaRegs[@class] & ~(state.Occupied.Get(@class) | m | _willAlloc.Get(@class));

            do
            {
                // We always advance one more to destroy the bit that we have found.
                var bitIndex = m.FindFirstBit() + 1;

                i  += bitIndex;
                m >>= bitIndex;

                var vd = sVars[i];
                if (!(vd != null))
                {
                    throw new ArgumentException();
                }
                if (!(vd.Attributes == null))
                {
                    throw new ArgumentException();
                }

                if (vd.IsModified && availableRegs != 0)
                {
                    var available = GuessSpill(@class, vd, availableRegs);
                    if (available != 0)
                    {
                        var regIndex = available.FindFirstBit();
                        var regMask  = Utils.Mask(regIndex);

                        Translator.Move(vd, @class, regIndex);
                        availableRegs ^= regMask;
                        continue;
                    }
                }

                Translator.Spill(vd, @class);
            } while (m != 0);
        }
Exemplo n.º 2
0
        private void Spill(RegisterClass @class)
        {
            var m = _willSpill.Get(@class);
            var i = -1;

            if (m == 0)
            {
                return;
            }

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

            var availableRegs = VariableContext.GaRegs[@class] & ~(state.Occupied.Get(@class) | m | _willAlloc.Get(@class));

            do
            {
                var bitIndex = m.FindFirstBit() + 1;

                i  += bitIndex;
                m >>= bitIndex;

                var vd = sVars[i];
                var va = vd.Attributes;

                if (!(va == null || !va.Flags.IsSet(VariableFlags.XReg)))
                {
                    throw new ArgumentException();
                }

                if (vd.IsModified && availableRegs != 0)
                {
                    if (va == null || !va.Flags.IsSet(VariableFlags.Spill))
                    {
                        var altRegs = GuessSpill(vd, availableRegs, @class);

                        if (altRegs != 0)
                        {
                            var regIndex = altRegs.FindFirstBit();
                            var regMask  = Utils.Mask(regIndex);

                            Translator.Move(vd, @class, regIndex);
                            availableRegs ^= regMask;
                        }
                    }
                }
                Translator.Spill(vd, @class);
            } while (m != 0);
        }
Exemplo n.º 3
0
        private void Plan(RegisterClass @class)
        {
            int i;
            var clobbered = Map.ClobberedRegs.Get(@class);

            var willAlloc = _willAlloc.Get(@class);
            var willFree  = clobbered & ~willAlloc;

            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.IsSet(VariableFlags.RReg))
                {
                    // Planning register allocation. First check whether the variable is
                    // already allocated in register and if it can stay there. Function
                    // arguments are passed either in a specific register or in stack so
                    // we care mostly of mandatory registers.
                    var inRegs = va.InRegs;

                    if (inRegs == 0)
                    {
                        inRegs = va.AllocableRegs;
                    }

                    // Optimize situation where the variable has to be allocated in a
                    // mandatory register, but it's already allocated in register that
                    // is not clobbered (i.e. it will survive function call).
                    if ((regMask & inRegs) != 0 || ((regMask & ~clobbered) != 0 && !vaFlags.IsSet(VariableFlags.Unuse)))
                    {
                        va.InRegIndex = regIndex;
                        va.Flags     |= VariableFlags.AllocRDone;
                        Done.Add(@class);
                    }
                    else
                    {
                        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. Only
            // useful for Gp registers used as call operand.
            for (i = 0; i < count; i++)
            {
                var va = list[i];
                var vd = va.VariableData;

                var vaFlags = va.Flags;
                if (vaFlags.IsSet(VariableFlags.AllocRDone) || !vaFlags.IsSet(VariableFlags.RReg))
                {
                    continue;
                }

                // All registers except Gp used by call itself must have inRegIndex.
                var m = va.InRegs;
                if (@class != RegisterClass.Gp || m != 0)
                {
                    if (!(m != 0))
                    {
                        throw new ArgumentException();
                    }
                    va.InRegIndex = m.FindFirstBit();
                    willSpill    |= occupied & m;
                    continue;
                }

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

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

                if (!vaFlags.IsSet(VariableFlags.WReg) && !vaFlags.IsSet(VariableFlags.Unuse) && candidateRegs.IsSet(~clobbered))
                {
                    candidateRegs &= ~clobbered;
                }

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

                va.InRegIndex = regIndex;
                va.InRegs     = regMask;

                willAlloc |= regMask;
                willSpill |= regMask & occupied;
                willFree  &= ~regMask;

                occupied |= regMask;
            }

            // Set calculated masks back to the allocator; needed by spill() and alloc().
            _willSpill.Set(@class, willSpill);
            _willAlloc.Set(@class, willAlloc);
        }
Exemplo n.º 4
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);
        }