mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 991153: Add machinery necessary for both register allocators to deal with aliased registers (r=bbouvier)
This commit is contained in:
parent
9479a316d2
commit
d0c5858924
@ -379,6 +379,14 @@ LDefinition::toString() const
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool
|
||||
LAllocation::aliases(const LAllocation &other) const
|
||||
{
|
||||
if (isFloatReg() && other.isFloatReg())
|
||||
return toFloatReg()->reg().aliases(other.toFloatReg()->reg());
|
||||
return *this == other;
|
||||
}
|
||||
|
||||
static void
|
||||
PrintUse(char *buf, size_t size, const LUse *use)
|
||||
{
|
||||
|
@ -195,8 +195,9 @@ class LAllocation : public TempObject
|
||||
#else
|
||||
const char *toString() const { return "???"; }
|
||||
#endif
|
||||
|
||||
bool aliases(const LAllocation &other) const;
|
||||
void dump() const;
|
||||
|
||||
};
|
||||
|
||||
class LUse : public LAllocation
|
||||
@ -481,6 +482,28 @@ class LDefinition
|
||||
Type type() const {
|
||||
return (Type)((bits_ >> TYPE_SHIFT) & TYPE_MASK);
|
||||
}
|
||||
bool isCompatibleReg(const AnyRegister &r) const {
|
||||
if (isFloatReg() && r.isFloat()) {
|
||||
#if defined(JS_CODEGEN_ARM) && defined(EVERYONE_KNOWS_ABOUT_ALIASING)
|
||||
if (type() == FLOAT32)
|
||||
return r.fpu().isSingle();
|
||||
return r.fpu().isDouble();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return !isFloatReg() && !r.isFloat();
|
||||
}
|
||||
bool isCompatibleDef(const LDefinition &other) const {
|
||||
#ifdef JS_CODEGEN_ARM
|
||||
if (isFloatReg() && other.isFloatReg())
|
||||
return type() == other.type();
|
||||
return !isFloatReg() && !other.isFloatReg();
|
||||
#else
|
||||
return isFloatReg() == other.isFloatReg();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isFloatReg() const {
|
||||
return type() == FLOAT32 || type() == DOUBLE;
|
||||
}
|
||||
|
@ -647,7 +647,7 @@ LiveRangeAllocator<VREG, forLSRA>::buildLivenessInfo()
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < ins->numDefs(); i++) {
|
||||
if (ins->getDef(i)->isFixed() &&
|
||||
*ins->getDef(i)->output() == LAllocation(*iter)) {
|
||||
ins->getDef(i)->output()->aliases(LAllocation(*iter))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -494,6 +494,12 @@ class VirtualRegister
|
||||
bool isFloatReg() const {
|
||||
return def_->isFloatReg();
|
||||
}
|
||||
bool isCompatibleReg(const AnyRegister &r) const {
|
||||
return def_->isCompatibleReg(r);
|
||||
}
|
||||
bool isCompatibleVReg(const VirtualRegister &vr) const {
|
||||
return def_->isCompatibleDef(*vr.def_);
|
||||
}
|
||||
|
||||
LiveInterval *intervalFor(CodePosition pos);
|
||||
LiveInterval *getFirstInterval();
|
||||
|
@ -66,6 +66,41 @@ struct AnyRegister {
|
||||
bool volatile_() const {
|
||||
return isFloat() ? fpu().volatile_() : gpr().volatile_();
|
||||
}
|
||||
AnyRegister aliased(uint32_t aliasIdx) const {
|
||||
AnyRegister ret;
|
||||
if (isFloat()) {
|
||||
FloatRegister fret;
|
||||
fpu().aliased(aliasIdx, &fret);
|
||||
ret = AnyRegister(fret);
|
||||
} else {
|
||||
Register gret;
|
||||
gpr().aliased(aliasIdx, &gret);
|
||||
ret = AnyRegister(gret);
|
||||
}
|
||||
JS_ASSERT_IF(aliasIdx == 0, ret == *this);
|
||||
return ret;
|
||||
}
|
||||
uint32_t numAliased() const {
|
||||
if (isFloat())
|
||||
return fpu().numAliased();
|
||||
return gpr().numAliased();
|
||||
}
|
||||
bool aliases(const AnyRegister &other) const {
|
||||
if (isFloat() && other.isFloat())
|
||||
return fpu().aliases(other.fpu());
|
||||
if (!isFloat() && !other.isFloat())
|
||||
return gpr().aliases(other.gpr());
|
||||
return false;
|
||||
}
|
||||
// do the two registers hold the same type of data (e.g. both float32, both gpr)
|
||||
bool isCompatibleReg (const AnyRegister other) const {
|
||||
if (isFloat() && other.isFloat())
|
||||
return fpu().equiv(other.fpu());
|
||||
if (!isFloat() && !other.isFloat())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Registers to hold a boxed value. Uses one register on 64 bit
|
||||
|
@ -62,9 +62,9 @@ struct Register {
|
||||
uint32_t numAliased() const {
|
||||
return 1;
|
||||
}
|
||||
Register aliased(int a) const {
|
||||
JS_ASSERT(a == 0);
|
||||
return *this;
|
||||
void aliased(uint32_t aliasIdx, Register *ret) const {
|
||||
JS_ASSERT(aliasIdx == 0);
|
||||
*ret = *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -345,23 +345,29 @@ class VFPRegister
|
||||
}
|
||||
static const int NumAliasedDoubles = 16;
|
||||
uint32_t numAliased() const {
|
||||
return 1;
|
||||
#ifdef EVERYONE_KNOWS_ABOUT_ALIASING
|
||||
if (isDouble()) {
|
||||
if (code_ < NumAliasedDoubles)
|
||||
return 3;
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
VFPRegister aliased(uint32_t a) {
|
||||
if (a == 0)
|
||||
return *this;
|
||||
void aliased(uint32_t aliasIdx, VFPRegister *ret) {
|
||||
if (aliasIdx == 0) {
|
||||
*ret = *this;
|
||||
return;
|
||||
}
|
||||
if (isDouble()) {
|
||||
JS_ASSERT(code_ < NumAliasedDoubles);
|
||||
JS_ASSERT(a <= 2);
|
||||
return singleOverlay(a - 1);
|
||||
JS_ASSERT(aliasIdx <= 2);
|
||||
*ret = singleOverlay(aliasIdx - 1);
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(a == 1);
|
||||
return doubleOverlay(a - 1);
|
||||
JS_ASSERT(aliasIdx == 1);
|
||||
*ret = doubleOverlay(aliasIdx - 1);
|
||||
}
|
||||
uint32_t numAlignedAliased() const {
|
||||
if (isDouble()) {
|
||||
@ -369,21 +375,25 @@ class VFPRegister
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
// s1 has 0 other aligned aliases
|
||||
// s0 has 1 other aligned aliases
|
||||
// s1 has 0 other aligned aliases, 1 total.
|
||||
// s0 has 1 other aligned aliase, 2 total.
|
||||
return 2 - (code_ & 1);
|
||||
}
|
||||
VFPRegister alignedAliased(uint32_t a) {
|
||||
if (a == 0)
|
||||
return *this;
|
||||
void alignedAliased(uint32_t aliasIdx, VFPRegister *ret) {
|
||||
if (aliasIdx == 0) {
|
||||
*ret = *this;
|
||||
return;
|
||||
}
|
||||
if (isDouble()) {
|
||||
JS_ASSERT(code_ < NumAliasedDoubles);
|
||||
JS_ASSERT(a <= 1);
|
||||
return singleOverlay(a - 1);
|
||||
JS_ASSERT(aliasIdx <= 1);
|
||||
*ret = singleOverlay(aliasIdx - 1);
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(a == 1);
|
||||
JS_ASSERT(aliasIdx == 1);
|
||||
JS_ASSERT((code_ & 1) == 0);
|
||||
return doubleOverlay(a - 1);
|
||||
*ret = doubleOverlay(aliasIdx - 1);
|
||||
return;
|
||||
}
|
||||
static Code FromName(const char *name) {
|
||||
return FloatRegisters::FromName(name);
|
||||
|
@ -188,7 +188,33 @@ struct FloatRegister {
|
||||
bool operator ==(FloatRegister other) const {
|
||||
return other.code_ == code_;
|
||||
}
|
||||
bool aliases(FloatRegister const &other) const;
|
||||
bool aliases(FloatRegister const &other) const {
|
||||
return other.code_ == code_;
|
||||
}
|
||||
uint32_t numAliased() {
|
||||
return 1;
|
||||
}
|
||||
void aliased(uint32_t aliasIdx, FloatRegister *ret) {
|
||||
JS_ASSERT(aliasIdx == 0);
|
||||
*ret = *this;
|
||||
}
|
||||
// This function mostly exists for the ARM backend. It is to ensure that two
|
||||
// floating point registers are equivalent. e.g. S0 is not equivalent to D16.
|
||||
// Since all floating point registers on x86 and x64 are equivalent, it is
|
||||
// reasonable for this function to do the same.
|
||||
bool equiv(FloatRegister other) const {
|
||||
return true;
|
||||
}
|
||||
uint32_t size() {
|
||||
return sizeof(double);
|
||||
}
|
||||
uint32_t numAlignedAliased() {
|
||||
return 1;
|
||||
}
|
||||
void alignedAliased(uint32_t aliasIdx, FloatRegister *ret) {
|
||||
JS_ASSERT(aliasIdx == 0);
|
||||
*ret = *this;
|
||||
}
|
||||
};
|
||||
|
||||
// Arm/D32 has double registers that can NOT be treated as float32
|
||||
|
@ -160,13 +160,40 @@ struct FloatRegister {
|
||||
bool volatile_() const {
|
||||
return !!((1 << code()) & FloatRegisters::VolatileMask);
|
||||
}
|
||||
bool operator != (const FloatRegister &other) const {
|
||||
bool operator != (FloatRegister other) const {
|
||||
return other.code_ != code_;
|
||||
}
|
||||
bool operator == (const FloatRegister &other) const {
|
||||
bool operator == (FloatRegister other) const {
|
||||
return other.code_ == code_;
|
||||
}
|
||||
bool aliases(FloatRegister const &other) const;
|
||||
bool aliases(FloatRegister other) const {
|
||||
return other.code_ == code_;
|
||||
}
|
||||
uint32_t numAliased() {
|
||||
return 1;
|
||||
}
|
||||
void aliased(uint32_t aliasIdx, FloatRegister *ret) {
|
||||
JS_ASSERT(aliasIdx == 0);
|
||||
*ret = *this;
|
||||
}
|
||||
// This function mostly exists for the ARM backend. It is to ensure that two
|
||||
// floating point registers are equivalent. e.g. S0 is not equivalent to D16.
|
||||
// Since all floating point registers on x86 and x64 are equivalent, it is
|
||||
// reasonable for this function to do the same.
|
||||
bool equiv(FloatRegister other) const {
|
||||
return true;
|
||||
}
|
||||
uint32_t size() {
|
||||
return sizeof(double);
|
||||
}
|
||||
uint32_t numAlignedAliased() {
|
||||
return 1;
|
||||
}
|
||||
void alignedAliased(uint32_t aliasIdx, FloatRegister *ret) {
|
||||
JS_ASSERT(aliasIdx == 0);
|
||||
*ret = *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Arm/D32 has double registers that can NOT be treated as float32
|
||||
|
Loading…
Reference in New Issue
Block a user