diff options
Diffstat (limited to 'src/qml/jit/qv4regalloc_p.h')
-rw-r--r-- | src/qml/jit/qv4regalloc_p.h | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/src/qml/jit/qv4regalloc_p.h b/src/qml/jit/qv4regalloc_p.h index 030fb4bf50..34ae19dfec 100644 --- a/src/qml/jit/qv4regalloc_p.h +++ b/src/qml/jit/qv4regalloc_p.h @@ -44,6 +44,7 @@ #include "qv4global_p.h" #include "qv4isel_p.h" #include "qv4ssa_p.h" +#include "qv4registerinfo_p.h" #include <config.h> @@ -54,46 +55,68 @@ namespace JIT { class RegAllocInfo; +// This class implements a linear-scan register allocator, with a couple of tweaks: +// - Second-chance allocation is used when an interval becomes active after a spill, which results +// in fewer differences between edges, and hence fewer moves before jumps. +// - Use positions are flagged with either "must have" register or "could have" register. This is +// used to decide whether a register is really needed when a temporary is used after a spill +// occurred. +// - Fixed intervals are used to denotate IR positions where certain registers are needed in order +// to implement the operation, and cannot be used by a temporary on that position. An example is +// caller saved registers, where the call will use/clobber those registers. +// - Hints are used to indicate which registers could be used to generate more compact code. An +// example is an addition, where one (or both) operands' life-time ends at that instruction. In +// this case, re-using an operand register for the result will result in an in-place add. +// - SSA form properties are used: +// - to simplify life-times (two temporaries will never interfere as long as their intervals +// are not split), resulting in a slightly faster algorithm; +// - when a temporary needs to be spilled, it is done directly after calculating it, so that +// 1 store is generated even if multiple spills/splits happen. +// - phi-node elimination (SSA form deconstruction) is done when resolving differences between +// CFG edges class RegisterAllocator { typedef IR::LifeTimeInterval LifeTimeInterval; - QVector<int> _normalRegisters; - QVector<int> _fpRegisters; + const RegisterInformation &_registerInformation; + QVector<const RegisterInfo *> _normalRegisters; + QVector<const RegisterInfo *> _fpRegisters; QScopedPointer<RegAllocInfo> _info; - QVector<LifeTimeInterval> _fixedRegisterRanges, _fixedFPRegisterRanges; + QVector<LifeTimeInterval *> _fixedRegisterRanges, _fixedFPRegisterRanges; - QVector<LifeTimeInterval> _unhandled, _active, _inactive, _handled; + IR::LifeTimeIntervals::Ptr _lifeTimeIntervals; + typedef QVector<LifeTimeInterval *> Intervals; + Intervals _unhandled, _active, _inactive, _handled; - QHash<IR::Temp, int> _lastAssignedRegister; - QHash<IR::Temp, int> _assignedSpillSlots; + std::vector<int> _lastAssignedRegister; + std::vector<int> _assignedSpillSlots; QVector<int> _activeSpillSlots; Q_DISABLE_COPY(RegisterAllocator) public: - RegisterAllocator(const QVector<int> &normalRegisters, const QVector<int> &fpRegisters); + enum { InvalidSpillSlot = -1 }; + + RegisterAllocator(const RegisterInformation ®isterInformation); ~RegisterAllocator(); void run(IR::Function *function, const IR::Optimizer &opt); private: + LifeTimeInterval *cloneFixedInterval(int reg, bool isFP, const LifeTimeInterval &original); void prepareRanges(); void linearScan(); - void tryAllocateFreeReg(LifeTimeInterval ¤t, const int position); - void allocateBlockedReg(LifeTimeInterval ¤t, const int position); - void longestAvailableReg(const QVector<int> &nextUses, int ®, int &nextUsePos_reg, - int lastUse) const; - int nextIntersection(const LifeTimeInterval ¤t, const LifeTimeInterval &another, - const int position) const; + void tryAllocateFreeReg(LifeTimeInterval ¤t); + void allocateBlockedReg(LifeTimeInterval ¤t); + int nextIntersection(const LifeTimeInterval ¤t, const LifeTimeInterval &another) const; int nextUse(const IR::Temp &t, int startPosition) const; void split(LifeTimeInterval ¤t, int beforePosition, bool skipOptionalRegisterUses =false); void splitInactiveAtEndOfLifetimeHole(int reg, bool isFPReg, int position); void assignSpillSlot(const IR::Temp &t, int startPos, int endPos); void resolve(IR::Function *function, const IR::Optimizer &opt); - void dump() const; + void dump(IR::Function *function) const; }; } // end of namespace JIT |