aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-08-12 14:30:42 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-08-14 15:27:55 +0200
commita503efe0df31742bac7d5af6ed4a53ee79a4c2a7 (patch)
tree3b3e67c5e4249354daf033932f855245fe07ce1a /src
parentd9f33ccdef985badc56fd8940373748626beffc7 (diff)
V4 JIT: calculate used registers and only save those.
Instead of saving all possibly used ones. Note that floating point registers are not saved yet, as we don't support callee-saved FP registers yet. Change-Id: I1db2ba2513f7b466c64ec103eda0c464269247b0 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jit/qv4isel_masm.cpp5
-rw-r--r--src/qml/jit/qv4regalloc.cpp30
-rw-r--r--src/qml/jit/qv4regalloc_p.h4
3 files changed, 37 insertions, 2 deletions
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 5547190303..39e7c0fbc2 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -225,8 +225,9 @@ void InstructionSelection::run(int functionIndex)
static const bool withRegisterAllocator = qgetenv("QV4_NO_REGALLOC").isEmpty();
if (Assembler::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
- RegisterAllocator(Assembler::getRegisterInfo()).run(_function, opt);
- calculateRegistersToSave(Assembler::getRegisterInfo());
+ RegisterAllocator regalloc(Assembler::getRegisterInfo());
+ regalloc.run(_function, opt);
+ calculateRegistersToSave(regalloc.usedRegisters());
} else {
if (opt.isInSSA())
// No register allocator available for this platform, or env. var was set, so:
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index 0639c5361f..15a92770ca 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -1241,6 +1241,9 @@ RegisterAllocator::RegisterAllocator(const QV4::JIT::RegisterInformation &regist
Q_ASSERT(_fpRegisters.size() >= 2);
_active.reserve((_normalRegisters.size() + _fpRegisters.size()) * 2);
_inactive.reserve(_active.size());
+
+ _regularRegsInUse.resize(_normalRegisters.size());
+ _fpRegsInUse.resize(_fpRegisters.size());
}
RegisterAllocator::~RegisterAllocator()
@@ -1303,6 +1306,31 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
}
}
+RegisterInformation RegisterAllocator::usedRegisters() const
+{
+ RegisterInformation regInfo;
+
+ for (int i = 0, ei = _normalRegisters.size(); i != ei; ++i) {
+ if (_regularRegsInUse.testBit(i))
+ regInfo.append(*_normalRegisters.at(i));
+ }
+
+ for (int i = 0, ei = _fpRegisters.size(); i != ei; ++i) {
+ if (_fpRegsInUse.testBit(i))
+ regInfo.append(*_fpRegisters.at(i));
+ }
+
+ return regInfo;
+}
+
+void RegisterAllocator::markInUse(int reg, bool isFPReg)
+{
+ if (isFPReg)
+ _fpRegsInUse.setBit(reg);
+ else
+ _regularRegsInUse.setBit(reg);
+}
+
static inline LifeTimeInterval createFixedInterval(int rangeCount)
{
LifeTimeInterval i(rangeCount);
@@ -1565,6 +1593,7 @@ void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current)
qDebug() << "*** allocating register" << reg << "for the whole interval of %" << current.temp().index;
current.setReg(reg);
_lastAssignedRegister[current.temp().index] = reg;
+ markInUse(reg, needsFPReg);
} else {
// register available for the first part of the interval
@@ -1580,6 +1609,7 @@ void RegisterAllocator::tryAllocateFreeReg(LifeTimeInterval &current)
if (DebugRegAlloc)
qDebug() << "*** allocating register" << reg << "for the first part of interval of %" << current.temp().index;
split(current, freeUntilPos_reg, true);
+ markInUse(reg, needsFPReg);
}
}
diff --git a/src/qml/jit/qv4regalloc_p.h b/src/qml/jit/qv4regalloc_p.h
index 34ae19dfec..e1f075cb07 100644
--- a/src/qml/jit/qv4regalloc_p.h
+++ b/src/qml/jit/qv4regalloc_p.h
@@ -93,6 +93,8 @@ class RegisterAllocator
std::vector<int> _assignedSpillSlots;
QVector<int> _activeSpillSlots;
+ QBitArray _regularRegsInUse, _fpRegsInUse;
+
Q_DISABLE_COPY(RegisterAllocator)
public:
@@ -102,8 +104,10 @@ public:
~RegisterAllocator();
void run(IR::Function *function, const IR::Optimizer &opt);
+ RegisterInformation usedRegisters() const;
private:
+ void markInUse(int reg, bool isFPReg);
LifeTimeInterval *cloneFixedInterval(int reg, bool isFP, const LifeTimeInterval &original);
void prepareRanges();
void linearScan();