diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2014-04-15 15:34:03 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-04-30 15:01:31 +0200 |
commit | 5f66ce2d962b5cf6720303173747e15ad6df0788 (patch) | |
tree | 02e5b8cf648e745b2a828ae63e2c0221fcd4454f /src/qml/jit/qv4regalloc.cpp | |
parent | a719ccf476273f17bf72dbf0909a7663fe64f2b0 (diff) |
V4 regalloc: optimize fixed interval creation.
Instead of creating ranges for all caller saved registers one at a time,
create a single template for all of them. Then change the template for
a (all) specific registers. So, instead of building the ranges every
time for all registers, do it once, and re-use the array. We currently
treat all registers as caller saved, so the ranges can actually be
shared.
Change-Id: I39111ba88be5c49bbab8fe4f2f8c5ad1c89ef282
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jit/qv4regalloc.cpp')
-rw-r--r-- | src/qml/jit/qv4regalloc.cpp | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index c1b39a4ff4..a06d3710e7 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -1077,6 +1077,8 @@ RegisterAllocator::RegisterAllocator(const QVector<int> &normalRegisters, const { Q_ASSERT(normalRegisters.size() >= 2); Q_ASSERT(fpRegisters.size() >= 2); + _active.reserve((normalRegisters.size() + fpRegisters.size()) * 2); + _inactive.reserve(_active.size()); } RegisterAllocator::~RegisterAllocator() @@ -1094,6 +1096,7 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt) #endif // DEBUG_REGALLOC _unhandled = opt.lifeTimeIntervals(); + _handled.reserve(_unhandled.size()); _info.reset(new RegAllocInfo); _info->collect(function); @@ -1114,10 +1117,6 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt) prepareRanges(); - _handled.reserve(_unhandled.size()); - _active.reserve(32); - _inactive.reserve(16); - Optimizer::showMeTheCode(function); linearScan(); @@ -1138,45 +1137,55 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt) #endif // DEBUG_REGALLOC } -static inline LifeTimeInterval createFixedInterval(int reg, bool isFP, int rangeCount) +static inline LifeTimeInterval createFixedInterval(int rangeCount) { - Temp t; - t.init(Temp::PhysicalRegister, reg, 0); - t.type = isFP ? IR::DoubleType : IR::SInt32Type; LifeTimeInterval i(rangeCount); + i.setReg(0); + + Temp t; + t.init(Temp::PhysicalRegister, 0, 0); + t.type = IR::SInt32Type; i.setTemp(t); - i.setReg(reg); - i.setFixedInterval(true); + return i; } +static inline LifeTimeInterval cloneFixedInterval(int reg, bool isFP, LifeTimeInterval lti) +{ + lti.setReg(reg); + lti.setFixedInterval(true); + + Temp t; + t.init(Temp::PhysicalRegister, reg, 0); + t.type = isFP ? IR::DoubleType : IR::SInt32Type; + lti.setTemp(t); + + return lti; +} + void RegisterAllocator::prepareRanges() { + LifeTimeInterval ltiWithCalls = createFixedInterval(_info->calls().size()); + foreach (int callPosition, _info->calls()) + ltiWithCalls.addRange(callPosition, callPosition); + const int regCount = _normalRegisters.size(); - _fixedRegisterRanges.resize(regCount); - for (int reg = 0; reg < regCount; ++reg) - _fixedRegisterRanges[reg] = createFixedInterval(reg, false, _info->calls().size()); + _fixedRegisterRanges.reserve(regCount); + for (int reg = 0; reg < regCount; ++reg) { + LifeTimeInterval lti = cloneFixedInterval(reg, false, ltiWithCalls); + _fixedRegisterRanges.append(lti); + if (lti.isValid()) + _active.append(lti); + } const int fpRegCount = _fpRegisters.size(); - _fixedFPRegisterRanges.resize(fpRegCount); + _fixedFPRegisterRanges.reserve(fpRegCount); for (int fpReg = 0; fpReg < fpRegCount; ++fpReg) { - _fixedFPRegisterRanges[fpReg] = createFixedInterval(fpReg, true, _info->calls().size()); + LifeTimeInterval lti = cloneFixedInterval(fpReg, true, ltiWithCalls); + _fixedFPRegisterRanges.append(lti); + if (lti.isValid()) + _active.append(lti); } - - foreach (int callPosition, _info->calls()) { - for (int reg = 0; reg < regCount; ++reg) - _fixedRegisterRanges[reg].addRange(callPosition, callPosition); - for (int fpReg = 0; fpReg < fpRegCount; ++fpReg) - _fixedFPRegisterRanges[fpReg].addRange(callPosition, callPosition); - } - for (int reg = 0; reg < regCount; ++reg) - if (_fixedRegisterRanges[reg].isValid()) - _active.append(_fixedRegisterRanges[reg]); - for (int fpReg = 0; fpReg < fpRegCount; ++fpReg) - if (_fixedFPRegisterRanges[fpReg].isValid()) - _active.append(_fixedFPRegisterRanges[fpReg]); - - std::sort(_active.begin(), _active.end(), LifeTimeInterval::lessThan); } void RegisterAllocator::linearScan() @@ -1442,8 +1451,8 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval ¤t, const int splitInactiveAtEndOfLifetimeHole(reg, needsFPReg, position); // make sure that current does not intersect with the fixed interval for reg - const LifeTimeInterval &fixedRegRange = needsFPReg ? _fixedFPRegisterRanges[reg] - : _fixedRegisterRanges[reg]; + const LifeTimeInterval &fixedRegRange = needsFPReg ? _fixedFPRegisterRanges.at(reg) + : _fixedRegisterRanges.at(reg); int ni = nextIntersection(current, fixedRegRange, position); if (ni != -1) { #ifdef DEBUG_REGALLOC |