aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-04-15 15:34:03 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-30 15:01:31 +0200
commit5f66ce2d962b5cf6720303173747e15ad6df0788 (patch)
tree02e5b8cf648e745b2a828ae63e2c0221fcd4454f
parenta719ccf476273f17bf72dbf0909a7663fe64f2b0 (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>
-rw-r--r--src/qml/compiler/qv4ssa_p.h2
-rw-r--r--src/qml/jit/qv4regalloc.cpp73
2 files changed, 42 insertions, 33 deletions
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index e53573fdd5..40ca44dc55 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -77,7 +77,7 @@ private:
public:
enum { Invalid = -1 };
- LifeTimeInterval(int rangeCapacity = 2)
+ explicit LifeTimeInterval(int rangeCapacity = 2)
: _end(Invalid)
, _reg(Invalid)
, _isFixedInterval(0)
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 &current, 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