Commit bb0a5fe3 by John Porto

Subzero. Changes the Register Allocator so that it is aware of register

aliases. BUG= R=jvoung@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1319203005.
parent 8f98cdd2
...@@ -79,7 +79,7 @@ void dumpLiveRange(const Variable *Var, const Cfg *Func) { ...@@ -79,7 +79,7 @@ void dumpLiveRange(const Variable *Var, const Cfg *Func) {
} // end of anonymous namespace } // end of anonymous namespace
LinearScan::LinearScan(Cfg *Func) LinearScan::LinearScan(Cfg *Func)
: Func(Func), Ctx(Func->getContext()), : Func(Func), Ctx(Func->getContext()), Target(Func->getTarget()),
Verbose(BuildDefs::dump() && Func->isVerbose(IceV_LinearScan)) {} Verbose(BuildDefs::dump() && Func->isVerbose(IceV_LinearScan)) {}
// Prepare for full register allocation of all variables. We depend on // Prepare for full register allocation of all variables. We depend on
...@@ -225,6 +225,12 @@ void LinearScan::init(RegAllocKind Kind) { ...@@ -225,6 +225,12 @@ void LinearScan::init(RegAllocKind Kind) {
Inactive.clear(); Inactive.clear();
Active.clear(); Active.clear();
SizeT NumRegs = Target->getNumRegisters();
RegAliases.resize(NumRegs);
for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
RegAliases[Reg] = &Target->getAliasesForRegister(Reg);
}
switch (Kind) { switch (Kind) {
case RAK_Unknown: case RAK_Unknown:
llvm::report_fatal_error("Invalid RAK_Unknown"); llvm::report_fatal_error("Invalid RAK_Unknown");
...@@ -295,8 +301,13 @@ void LinearScan::addSpillFill(IterationState &Iter) { ...@@ -295,8 +301,13 @@ void LinearScan::addSpillFill(IterationState &Iter) {
// range. Start looking after SpillPoint gets set, i.e. once Cur's live // range. Start looking after SpillPoint gets set, i.e. once Cur's live
// range begins. // range begins.
FOREACH_VAR_IN_INST(Var, *I) { FOREACH_VAR_IN_INST(Var, *I) {
if (Var->hasRegTmp()) if (!Var->hasRegTmp())
Iter.RegMask[Var->getRegNumTmp()] = false; continue;
const llvm::SmallBitVector &Aliases = *RegAliases[Var->getRegNumTmp()];
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
Iter.RegMask[RegAlias] = false;
}
} }
} }
} }
...@@ -307,7 +318,6 @@ void LinearScan::addSpillFill(IterationState &Iter) { ...@@ -307,7 +318,6 @@ void LinearScan::addSpillFill(IterationState &Iter) {
int32_t RegNum = Iter.RegMask.find_first(); int32_t RegNum = Iter.RegMask.find_first();
assert(RegNum != -1); assert(RegNum != -1);
Iter.Cur->setRegNumTmp(RegNum); Iter.Cur->setRegNumTmp(RegNum);
TargetLowering *Target = Func->getTarget();
Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType()); Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType());
// TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc
// is correctly identified as !isMultiBlock(), reducing stack frame size. // is correctly identified as !isMultiBlock(), reducing stack frame size.
...@@ -340,9 +350,12 @@ void LinearScan::handleActiveRangeExpiredOrInactive(const Variable *Cur) { ...@@ -340,9 +350,12 @@ void LinearScan::handleActiveRangeExpiredOrInactive(const Variable *Cur) {
if (Moved) { if (Moved) {
// Decrement Item from RegUses[]. // Decrement Item from RegUses[].
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
int32_t RegNum = Item->getRegNumTmp(); const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
--RegUses[RegNum]; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
assert(RegUses[RegNum] >= 0); RegAlias = Aliases.find_next(RegAlias)) {
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
} }
} }
} }
...@@ -362,9 +375,12 @@ void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) { ...@@ -362,9 +375,12 @@ void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
moveItem(Inactive, Index, Active); moveItem(Inactive, Index, Active);
// Increment Item in RegUses[]. // Increment Item in RegUses[].
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
int32_t RegNum = Item->getRegNumTmp(); const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
assert(RegUses[RegNum] >= 0); for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
++RegUses[RegNum]; RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
} }
} }
} }
...@@ -430,17 +446,20 @@ void LinearScan::findRegisterPreference(IterationState &Iter) { ...@@ -430,17 +446,20 @@ void LinearScan::findRegisterPreference(IterationState &Iter) {
// the current range. // the current range.
void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) { void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) {
for (const Variable *Item : Inactive) { for (const Variable *Item : Inactive) {
if (Item->rangeOverlaps(Iter.Cur)) { if (!Item->rangeOverlaps(Iter.Cur))
int32_t RegNum = Item->getRegNumTmp(); continue;
const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
// Don't assert(Free[RegNum]) because in theory (though probably never in // Don't assert(Free[RegNum]) because in theory (though probably never in
// practice) there could be two inactive variables that were marked with // practice) there could be two inactive variables that were marked with
// AllowOverlap. // AllowOverlap.
Iter.Free[RegNum] = false; Iter.Free[RegAlias] = false;
// Disable AllowOverlap if an Inactive variable, which is not Prefer, // Disable AllowOverlap if an Inactive variable, which is not Prefer,
// shares Prefer's register, and has a definition within Cur's live // shares Prefer's register, and has a definition within Cur's live
// range. // range.
if (Iter.AllowOverlap && Item != Iter.Prefer && if (Iter.AllowOverlap && Item != Iter.Prefer &&
RegNum == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) { RegAlias == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) {
Iter.AllowOverlap = false; Iter.AllowOverlap = false;
dumpDisableOverlap(Func, Item, "Inactive"); dumpDisableOverlap(Func, Item, "Inactive");
} }
...@@ -459,18 +478,22 @@ void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) { ...@@ -459,18 +478,22 @@ void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) {
if (Iter.Cur->rangeEndsBefore(Item)) if (Iter.Cur->rangeEndsBefore(Item))
break; break;
if (Item->rangeOverlaps(Iter.Cur)) { if (Item->rangeOverlaps(Iter.Cur)) {
int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp() const llvm::SmallBitVector &Aliases =
Iter.Weights[ItemReg].setWeight(RegWeight::Inf); *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
Iter.Free[ItemReg] = false; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
Iter.PrecoloredUnhandledMask[ItemReg] = true; RegAlias = Aliases.find_next(RegAlias)) {
Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
Iter.Free[RegAlias] = false;
Iter.PrecoloredUnhandledMask[RegAlias] = true;
// Disable Iter.AllowOverlap if the preferred register is one of these // Disable Iter.AllowOverlap if the preferred register is one of these
// pre-colored unhandled overlapping ranges. // pre-colored unhandled overlapping ranges.
if (Iter.AllowOverlap && ItemReg == Iter.PreferReg) { if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) {
Iter.AllowOverlap = false; Iter.AllowOverlap = false;
dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
} }
} }
} }
}
} }
void LinearScan::allocatePrecoloredRegister(Variable *Cur) { void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
...@@ -479,8 +502,12 @@ void LinearScan::allocatePrecoloredRegister(Variable *Cur) { ...@@ -479,8 +502,12 @@ void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
assert(Cur->getRegNumTmp() == RegNum); assert(Cur->getRegNumTmp() == RegNum);
dumpLiveRangeTrace("Precoloring ", Cur); dumpLiveRangeTrace("Precoloring ", Cur);
Active.push_back(Cur); Active.push_back(Cur);
assert(RegUses[RegNum] >= 0); const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
++RegUses[RegNum]; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
assert(!UnhandledPrecolored.empty()); assert(!UnhandledPrecolored.empty());
assert(UnhandledPrecolored.back() == Cur); assert(UnhandledPrecolored.back() == Cur);
UnhandledPrecolored.pop_back(); UnhandledPrecolored.pop_back();
...@@ -489,8 +516,12 @@ void LinearScan::allocatePrecoloredRegister(Variable *Cur) { ...@@ -489,8 +516,12 @@ void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
void LinearScan::allocatePreferredRegister(IterationState &Iter) { void LinearScan::allocatePreferredRegister(IterationState &Iter) {
Iter.Cur->setRegNumTmp(Iter.PreferReg); Iter.Cur->setRegNumTmp(Iter.PreferReg);
dumpLiveRangeTrace("Preferring ", Iter.Cur); dumpLiveRangeTrace("Preferring ", Iter.Cur);
assert(RegUses[Iter.PreferReg] >= 0); const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
++RegUses[Iter.PreferReg]; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
Active.push_back(Iter.Cur); Active.push_back(Iter.Cur);
} }
...@@ -498,8 +529,12 @@ void LinearScan::allocateFreeRegister(IterationState &Iter) { ...@@ -498,8 +529,12 @@ void LinearScan::allocateFreeRegister(IterationState &Iter) {
int32_t RegNum = Iter.Free.find_first(); int32_t RegNum = Iter.Free.find_first();
Iter.Cur->setRegNumTmp(RegNum); Iter.Cur->setRegNumTmp(RegNum);
dumpLiveRangeTrace("Allocating ", Iter.Cur); dumpLiveRangeTrace("Allocating ", Iter.Cur);
assert(RegUses[RegNum] >= 0); const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
++RegUses[RegNum]; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
Active.push_back(Iter.Cur); Active.push_back(Iter.Cur);
} }
...@@ -507,16 +542,28 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -507,16 +542,28 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
// Check Active ranges. // Check Active ranges.
for (const Variable *Item : Active) { for (const Variable *Item : Active) {
assert(Item->rangeOverlaps(Iter.Cur)); assert(Item->rangeOverlaps(Iter.Cur));
int32_t RegNum = Item->getRegNumTmp();
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
Iter.Weights[RegNum].addWeight(Item->getWeight(Func)); const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
// We add the Item's weight to each alias/subregister to represent that,
// should we decide to pick any of them, then we would incur that many
// memory accesses.
RegWeight W = Item->getWeight(Func);
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
Iter.Weights[RegAlias].addWeight(W);
}
} }
// Same as above, but check Inactive ranges instead of Active. // Same as above, but check Inactive ranges instead of Active.
for (const Variable *Item : Inactive) { for (const Variable *Item : Inactive) {
int32_t RegNum = Item->getRegNumTmp(); if (!Item->rangeOverlaps(Iter.Cur))
continue;
assert(Item->hasRegTmp()); assert(Item->hasRegTmp());
if (Item->rangeOverlaps(Iter.Cur)) const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
Iter.Weights[RegNum].addWeight(Item->getWeight(Func)); RegWeight W = Item->getWeight(Func);
for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
Iter.Weights[RegAlias].addWeight(W);
}
} }
// All the weights are now calculated. Find the register with smallest // All the weights are now calculated. Find the register with smallest
...@@ -548,8 +595,12 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -548,8 +595,12 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
Variable *Item = Active[Index]; Variable *Item = Active[Index];
if (Item->getRegNumTmp() == MinWeightIndex) { if (Item->getRegNumTmp() == MinWeightIndex) {
dumpLiveRangeTrace("Evicting ", Item); dumpLiveRangeTrace("Evicting ", Item);
--RegUses[MinWeightIndex]; const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
assert(RegUses[MinWeightIndex] >= 0); for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
--RegUses[RegAlias];
assert(RegUses[RegAlias] >= 0);
}
Item->setRegNumTmp(Variable::NoRegister); Item->setRegNumTmp(Variable::NoRegister);
moveItem(Active, Index, Handled); moveItem(Active, Index, Handled);
} }
...@@ -574,8 +625,12 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) { ...@@ -574,8 +625,12 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
} }
// Assign the register to Cur. // Assign the register to Cur.
Iter.Cur->setRegNumTmp(MinWeightIndex); Iter.Cur->setRegNumTmp(MinWeightIndex);
assert(RegUses[MinWeightIndex] >= 0); const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
++RegUses[MinWeightIndex]; for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
RegAlias = Aliases.find_next(RegAlias)) {
assert(RegUses[RegAlias] >= 0);
++RegUses[RegAlias];
}
Active.push_back(Iter.Cur); Active.push_back(Iter.Cur);
dumpLiveRangeTrace("Allocating ", Iter.Cur); dumpLiveRangeTrace("Allocating ", Iter.Cur);
} }
...@@ -594,7 +649,7 @@ void LinearScan::assignFinalRegisters( ...@@ -594,7 +649,7 @@ void LinearScan::assignFinalRegisters(
// is different. // is different.
uint64_t Salt = uint64_t Salt =
(Func->getSequenceNumber() << 1) ^ (Kind == RAK_Phi ? 0u : 1u); (Func->getSequenceNumber() << 1) ^ (Kind == RAK_Phi ? 0u : 1u);
Func->getTarget()->makeRandomRegisterPermutation( Target->makeRandomRegisterPermutation(
Permutation, PreDefinedRegisters | ~RegMaskFull, Salt); Permutation, PreDefinedRegisters | ~RegMaskFull, Salt);
} }
...@@ -616,8 +671,8 @@ void LinearScan::assignFinalRegisters( ...@@ -616,8 +671,8 @@ void LinearScan::assignFinalRegisters(
} else { } else {
Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning " Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning "
: "Assigning ") : "Assigning ")
<< Func->getTarget()->getRegName(AssignedRegNum, IceType_i32) << Target->getRegName(AssignedRegNum, IceType_i32) << "(r"
<< "(r" << AssignedRegNum << ") to "; << AssignedRegNum << ") to ";
Item->dump(Func); Item->dump(Func);
Str << "\n"; Str << "\n";
} }
...@@ -667,7 +722,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, ...@@ -667,7 +722,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
TargetLowering::RegSet_CallerSave; TargetLowering::RegSet_CallerSave;
const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None;
const llvm::SmallBitVector KillsMask = const llvm::SmallBitVector KillsMask =
Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); Target->getRegisterSet(RegsInclude, RegsExclude);
// Allocate memory once outside the loop // Allocate memory once outside the loop
IterationState Iter; IterationState Iter;
...@@ -679,8 +734,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, ...@@ -679,8 +734,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
Unhandled.pop_back(); Unhandled.pop_back();
dumpLiveRangeTrace("\nConsidering ", Iter.Cur); dumpLiveRangeTrace("\nConsidering ", Iter.Cur);
Iter.RegMask = Iter.RegMask =
RegMaskFull & RegMaskFull & Target->getRegisterSetForType(Iter.Cur->getType());
Func->getTarget()->getRegisterSetForType(Iter.Cur->getType());
KillsRange.trim(Iter.Cur->getLiveRange().getStart()); KillsRange.trim(Iter.Cur->getLiveRange().getStart());
// Check for pre-colored ranges. If Cur is pre-colored, it definitely gets // Check for pre-colored ranges. If Cur is pre-colored, it definitely gets
...@@ -744,8 +798,8 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, ...@@ -744,8 +798,8 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
Ostream &Str = Ctx->getStrDump(); Ostream &Str = Ctx->getStrDump();
for (SizeT i = 0; i < Iter.RegMask.size(); ++i) { for (SizeT i = 0; i < Iter.RegMask.size(); ++i) {
if (Iter.RegMask[i]) { if (Iter.RegMask[i]) {
Str << Func->getTarget()->getRegName(i, IceType_i32) Str << Target->getRegName(i, IceType_i32) << "(U=" << RegUses[i]
<< "(U=" << RegUses[i] << ",F=" << Iter.Free[i] << ",F=" << Iter.Free[i]
<< ",P=" << Iter.PrecoloredUnhandledMask[i] << ") "; << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") ";
} }
} }
......
...@@ -96,6 +96,7 @@ private: ...@@ -96,6 +96,7 @@ private:
Cfg *const Func; Cfg *const Func;
GlobalContext *const Ctx; GlobalContext *const Ctx;
TargetLowering *const Target;
OrderedRanges Unhandled; OrderedRanges Unhandled;
/// UnhandledPrecolored is a subset of Unhandled, specially collected for /// UnhandledPrecolored is a subset of Unhandled, specially collected for
...@@ -108,6 +109,9 @@ private: ...@@ -108,6 +109,9 @@ private:
/// currently assigned to. It can be greater than 1 as a result of /// currently assigned to. It can be greater than 1 as a result of
/// AllowOverlap inference. /// AllowOverlap inference.
llvm::SmallVector<int32_t, REGS_SIZE> RegUses; llvm::SmallVector<int32_t, REGS_SIZE> RegUses;
// TODO(jpp): for some architectures a SmallBitVector might not be big enough.
// Evaluate what the performance impact on those architectures is.
llvm::SmallVector<const llvm::SmallBitVector *, REGS_SIZE> RegAliases;
bool FindPreference = false; bool FindPreference = false;
bool FindOverlap = false; bool FindOverlap = false;
......
...@@ -211,6 +211,8 @@ public: ...@@ -211,6 +211,8 @@ public:
virtual llvm::SmallBitVector getRegisterSet(RegSetMask Include, virtual llvm::SmallBitVector getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const = 0; RegSetMask Exclude) const = 0;
virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0; virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0;
virtual const llvm::SmallBitVector &getAliasesForRegister(SizeT) const = 0;
void regAlloc(RegAllocKind Kind); void regAlloc(RegAllocKind Kind);
virtual void virtual void
......
...@@ -187,6 +187,8 @@ TargetARM32::TargetARM32(Cfg *Func) ...@@ -187,6 +187,8 @@ TargetARM32::TargetARM32(Cfg *Func)
Float32Registers[RegARM32::val] = isFP32; \ Float32Registers[RegARM32::val] = isFP32; \
Float64Registers[RegARM32::val] = isFP64; \ Float64Registers[RegARM32::val] = isFP64; \
VectorRegisters[RegARM32::val] = isVec128; \ VectorRegisters[RegARM32::val] = isVec128; \
RegisterAliases[RegARM32::val].resize(RegARM32::Reg_NUM); \
RegisterAliases[RegARM32::val].set(RegARM32::val); \
ScratchRegs[RegARM32::val] = scratch; ScratchRegs[RegARM32::val] = scratch;
REGARM32_TABLE; REGARM32_TABLE;
#undef X #undef X
......
...@@ -68,6 +68,9 @@ public: ...@@ -68,6 +68,9 @@ public:
const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
return TypeToRegisterSet[Ty]; return TypeToRegisterSet[Ty];
} }
const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return UsesFramePointer; } bool hasFramePointer() const override { return UsesFramePointer; }
SizeT getFrameOrStackReg() const override { SizeT getFrameOrStackReg() const override {
return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp; return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp;
...@@ -434,7 +437,9 @@ protected: ...@@ -434,7 +437,9 @@ protected:
bool NeedsStackAlignment = false; bool NeedsStackAlignment = false;
bool MaybeLeafFunc = true; bool MaybeLeafFunc = true;
size_t SpillAreaSizeBytes = 0; size_t SpillAreaSizeBytes = 0;
// TODO(jpp): std::array instead of array.
llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
llvm::SmallBitVector RegisterAliases[RegARM32::Reg_NUM];
llvm::SmallBitVector ScratchRegs; llvm::SmallBitVector ScratchRegs;
llvm::SmallBitVector RegsUsed; llvm::SmallBitVector RegsUsed;
VarList PhysicalRegisters[IceType_NUM]; VarList PhysicalRegisters[IceType_NUM];
......
...@@ -56,6 +56,8 @@ TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) { ...@@ -56,6 +56,8 @@ TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {
IntegerRegisters[RegMIPS32::val] = isInt; \ IntegerRegisters[RegMIPS32::val] = isInt; \
FloatRegisters[RegMIPS32::val] = isFP; \ FloatRegisters[RegMIPS32::val] = isFP; \
VectorRegisters[RegMIPS32::val] = isFP; \ VectorRegisters[RegMIPS32::val] = isFP; \
RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \
RegisterAliases[RegMIPS32::val].set(RegMIPS32::val); \
ScratchRegs[RegMIPS32::val] = scratch; ScratchRegs[RegMIPS32::val] = scratch;
REGMIPS32_TABLE; REGMIPS32_TABLE;
#undef X #undef X
......
...@@ -44,6 +44,9 @@ public: ...@@ -44,6 +44,9 @@ public:
const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
return TypeToRegisterSet[Ty]; return TypeToRegisterSet[Ty];
} }
const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return UsesFramePointer; } bool hasFramePointer() const override { return UsesFramePointer; }
SizeT getFrameOrStackReg() const override { SizeT getFrameOrStackReg() const override {
return UsesFramePointer ? RegMIPS32::Reg_FP : RegMIPS32::Reg_SP; return UsesFramePointer ? RegMIPS32::Reg_FP : RegMIPS32::Reg_SP;
...@@ -128,6 +131,7 @@ protected: ...@@ -128,6 +131,7 @@ protected:
bool UsesFramePointer = false; bool UsesFramePointer = false;
bool NeedsStackAlignment = false; bool NeedsStackAlignment = false;
llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
llvm::SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
llvm::SmallBitVector ScratchRegs; llvm::SmallBitVector ScratchRegs;
llvm::SmallBitVector RegsUsed; llvm::SmallBitVector RegsUsed;
VarList PhysicalRegisters[IceType_NUM]; VarList PhysicalRegisters[IceType_NUM];
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "IceTargetLoweringX8632.def" #include "IceTargetLoweringX8632.def"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include <array>
namespace Ice { namespace Ice {
class TargetX8632; class TargetX8632;
...@@ -312,20 +314,43 @@ template <> struct MachineTraits<TargetX8632> { ...@@ -312,20 +314,43 @@ template <> struct MachineTraits<TargetX8632> {
} }
} }
static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters, static void initRegisterSet(
llvm::SmallBitVector *IntegerRegistersI8, std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet,
llvm::SmallBitVector *FloatRegisters, std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases,
llvm::SmallBitVector *VectorRegisters,
llvm::SmallBitVector *ScratchRegs) { llvm::SmallBitVector *ScratchRegs) {
llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
ScratchRegs->resize(RegisterSet::Reg_NUM);
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
frameptr, isI8, isInt, isFP) \ frameptr, isI8, isInt, isFP) \
(*IntegerRegisters)[RegisterSet::val] = isInt; \ (IntegerRegisters)[RegisterSet::val] = isInt; \
(*IntegerRegistersI8)[RegisterSet::val] = isI8; \ (IntegerRegistersI8)[RegisterSet::val] = isI8; \
(*FloatRegisters)[RegisterSet::val] = isFP; \ (FloatRegisters)[RegisterSet::val] = isFP; \
(*VectorRegisters)[RegisterSet::val] = isFP; \ (VectorRegisters)[RegisterSet::val] = isFP; \
(*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM); \
(*RegisterAliases)[RegisterSet::val].set(RegisterSet::val); \
(*ScratchRegs)[RegisterSet::val] = scratch; (*ScratchRegs)[RegisterSet::val] = scratch;
REGX8632_TABLE; REGX8632_TABLE;
#undef X #undef X
(*TypeToRegisterSet)[IceType_void] = InvalidRegisters;
(*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8;
(*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8;
(*TypeToRegisterSet)[IceType_i16] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_i32] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_i64] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_f32] = FloatRegisters;
(*TypeToRegisterSet)[IceType_f64] = FloatRegisters;
(*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters;
} }
static llvm::SmallBitVector static llvm::SmallBitVector
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "IceTargetLoweringX8664.def" #include "IceTargetLoweringX8664.def"
#include <array>
namespace Ice { namespace Ice {
class TargetX8664; class TargetX8664;
...@@ -325,20 +327,44 @@ template <> struct MachineTraits<TargetX8664> { ...@@ -325,20 +327,44 @@ template <> struct MachineTraits<TargetX8664> {
} }
} }
static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters, static void initRegisterSet(
llvm::SmallBitVector *IntegerRegistersI8, std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet,
llvm::SmallBitVector *FloatRegisters, std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases,
llvm::SmallBitVector *VectorRegisters,
llvm::SmallBitVector *ScratchRegs) { llvm::SmallBitVector *ScratchRegs) {
llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
ScratchRegs->resize(RegisterSet::Reg_NUM);
#define X(val, encode, name64, name32, name16, name8, scratch, preserved, \ #define X(val, encode, name64, name32, name16, name8, scratch, preserved, \
stackptr, frameptr, isInt, isFP) \ stackptr, frameptr, isInt, isFP) \
(*IntegerRegisters)[RegisterSet::val] = isInt; \ (IntegerRegisters)[RegisterSet::val] = isInt; \
(*IntegerRegistersI8)[RegisterSet::val] = isInt; \ (IntegerRegistersI8)[RegisterSet::val] = isInt; \
(*FloatRegisters)[RegisterSet::val] = isFP; \ (FloatRegisters)[RegisterSet::val] = isFP; \
(*VectorRegisters)[RegisterSet::val] = isFP; \ (VectorRegisters)[RegisterSet::val] = isFP; \
(*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM); \
(*RegisterAliases)[RegisterSet::val].set(RegisterSet::val); \
(*ScratchRegs)[RegisterSet::val] = scratch; (*ScratchRegs)[RegisterSet::val] = scratch;
REGX8664_TABLE; REGX8664_TABLE;
#undef X #undef X
(*TypeToRegisterSet)[IceType_void] = InvalidRegisters;
(*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8;
(*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8;
(*TypeToRegisterSet)[IceType_i16] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_i32] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_i64] = IntegerRegisters;
(*TypeToRegisterSet)[IceType_f32] = FloatRegisters;
(*TypeToRegisterSet)[IceType_f64] = FloatRegisters;
(*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters;
(*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters;
} }
static llvm::SmallBitVector static llvm::SmallBitVector
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "IceUtils.h" #include "IceUtils.h"
#include <array>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
...@@ -75,6 +76,12 @@ public: ...@@ -75,6 +76,12 @@ public:
const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
return TypeToRegisterSet[Ty]; return TypeToRegisterSet[Ty];
} }
const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
assert(Reg < Traits::RegisterSet::Reg_NUM);
return RegisterAliases[Reg];
}
bool hasFramePointer() const override { return IsEbpBasedFrame; } bool hasFramePointer() const override { return IsEbpBasedFrame; }
SizeT getFrameOrStackReg() const override { SizeT getFrameOrStackReg() const override {
return IsEbpBasedFrame ? Traits::RegisterSet::Reg_ebp return IsEbpBasedFrame ? Traits::RegisterSet::Reg_ebp
...@@ -680,10 +687,12 @@ protected: ...@@ -680,10 +687,12 @@ protected:
bool IsEbpBasedFrame = false; bool IsEbpBasedFrame = false;
bool NeedsStackAlignment = false; bool NeedsStackAlignment = false;
size_t SpillAreaSizeBytes = 0; size_t SpillAreaSizeBytes = 0;
llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; std::array<llvm::SmallBitVector, IceType_NUM> TypeToRegisterSet;
std::array<llvm::SmallBitVector, Traits::RegisterSet::Reg_NUM>
RegisterAliases;
llvm::SmallBitVector ScratchRegs; llvm::SmallBitVector ScratchRegs;
llvm::SmallBitVector RegsUsed; llvm::SmallBitVector RegsUsed;
VarList PhysicalRegisters[IceType_NUM]; std::array<VarList, IceType_NUM> PhysicalRegisters;
/// Randomize a given immediate operand /// Randomize a given immediate operand
Operand *randomizeOrPoolImmediate(Constant *Immediate, Operand *randomizeOrPoolImmediate(Constant *Immediate,
......
...@@ -281,31 +281,7 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func) ...@@ -281,31 +281,7 @@ TargetX86Base<Machine>::TargetX86Base(Cfg *Func)
} }
// TODO: Don't initialize IntegerRegisters and friends every time. Instead, // TODO: Don't initialize IntegerRegisters and friends every time. Instead,
// initialize in some sort of static initializer for the class. // initialize in some sort of static initializer for the class.
llvm::SmallBitVector IntegerRegisters(Traits::RegisterSet::Reg_NUM); Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs);
llvm::SmallBitVector IntegerRegistersI8(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector FloatRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector VectorRegisters(Traits::RegisterSet::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(Traits::RegisterSet::Reg_NUM);
ScratchRegs.resize(Traits::RegisterSet::Reg_NUM);
Traits::initRegisterSet(&IntegerRegisters, &IntegerRegistersI8,
&FloatRegisters, &VectorRegisters, &ScratchRegs);
TypeToRegisterSet[IceType_void] = InvalidRegisters;
TypeToRegisterSet[IceType_i1] = IntegerRegistersI8;
TypeToRegisterSet[IceType_i8] = IntegerRegistersI8;
TypeToRegisterSet[IceType_i16] = IntegerRegisters;
TypeToRegisterSet[IceType_i32] = IntegerRegisters;
TypeToRegisterSet[IceType_i64] = IntegerRegisters;
TypeToRegisterSet[IceType_f32] = FloatRegisters;
TypeToRegisterSet[IceType_f64] = FloatRegisters;
TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
} }
template <class Machine> void TargetX86Base<Machine>::translateO2() { template <class Machine> void TargetX86Base<Machine>::translateO2() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment