Commit 149999e5 by John Porto

Subzero. ARM32. Materializes the register table.

This CL modifies the ARM32 backend so that the REGARM32_TABLE is only expanded once (to initialize a constexpr array.) This change decreased the backend size in roughly ~80k. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=kschimpf@google.com Review URL: https://codereview.chromium.org/1554263002 .
parent dff7dbdb
......@@ -480,7 +480,7 @@ void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags,
return;
if (SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
llvm::report_fatal_error(std::string(InstName) + ": " +
RegARM32::RegNames[Reg] +
RegARM32::getRegName(Reg) +
"=pc not allowed when CC=1");
}
......@@ -497,7 +497,7 @@ size_t MoveRelocatableFixup::emit(GlobalContext *Ctx,
IValueT Inst = Asm.load<IValueT>(position());
Str << "\t"
"mov" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "w" : "t") << "\t"
<< RegARM32::RegNames[(Inst >> kRdShift) & 0xF]
<< RegARM32::getRegName((Inst >> kRdShift) & 0xF)
<< ", #:" << (kind() == llvm::ELF::R_ARM_MOVW_ABS_NC ? "lower" : "upper")
<< "16:" << symbol(Ctx) << "\t@ .word "
<< llvm::format_hex_no_prefix(Inst, 8) << "\n";
......
......@@ -23,7 +23,39 @@
namespace Ice {
namespace ARM32 {
/// SizeOf is used to obtain the size of an initializer list as a constexpr
/// expression. This is only needed until our C++ library is updated to
/// C++ 14 -- which defines constexpr members to std::initializer_list.
class SizeOf {
SizeOf(const SizeOf &) = delete;
SizeOf &operator=(const SizeOf &) = delete;
public:
constexpr SizeOf() : Size(0) {}
template <typename... T>
explicit constexpr SizeOf(T...)
: Size(__length<T...>::value) {}
constexpr SizeT size() const { return Size; }
private:
template <typename T, typename... U> struct __length {
static constexpr std::size_t value = 1 + __length<U...>::value;
};
template <typename T> struct __length<T> {
static constexpr std::size_t value = 1;
};
const std::size_t Size;
};
class RegARM32 {
private:
RegARM32() = delete;
RegARM32(const RegARM32 &) = delete;
RegARM32 &operator=(const RegARM32 &) = delete;
~RegARM32() = delete;
public:
/// An enum of every register. The enum value may not match the encoding used
/// to binary encode register operands in instructions.
......@@ -83,30 +115,61 @@ public:
Encoded_Not_QReg = -1
};
static constexpr struct TableType {
const char *Name;
int32_t Encoding : 10;
int32_t CCArg : 6;
int32_t Scratch : 1;
int32_t Preserved : 1;
int32_t StackPtr : 1;
int32_t FramePtr : 1;
int32_t IsGPR : 1;
int32_t IsInt : 1;
int32_t IsI64Pair : 1;
int32_t IsFP32 : 1;
int32_t IsFP64 : 1;
int32_t IsVec128 : 1;
#define NUM_ALIASES_BITS 3
SizeT NumAliases : (NUM_ALIASES_BITS + 1);
uint16_t Aliases[1 << NUM_ALIASES_BITS];
#undef NUM_ALIASES_BITS
} Table[Reg_NUM] = {
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
{ \
name, encode, cc_arg, scratch, preserved, stackptr, frameptr, isGPR, \
isInt, isI64Pair, isFP32, isFP64, isVec128, \
(SizeOf alias_init).size(), alias_init \
} \
,
REGARM32_TABLE
#undef X
};
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum);
assert(RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
return GPRRegister(Table[RegNum].Encoding);
}
static inline GPRRegister getI64PairFirstGPRNum(int32_t RegNum) {
assert(Reg_I64PAIR_First <= RegNum);
assert(RegNum <= Reg_I64PAIR_Last);
return GPRRegister(2 * (RegNum - Reg_I64PAIR_First + Reg_GPR_First));
return GPRRegister(Table[RegNum].Encoding);
}
static inline GPRRegister getI64PairSecondGPRNum(int32_t RegNum) {
assert(Reg_I64PAIR_First <= RegNum);
assert(RegNum <= Reg_I64PAIR_Last);
return GPRRegister(2 * (RegNum - Reg_I64PAIR_First + Reg_GPR_First) + 1);
return GPRRegister(Table[RegNum].Encoding + 1);
}
static inline bool isI64RegisterPair(int32_t RegNum) {
return Reg_I64PAIR_First <= RegNum && RegNum <= Reg_I64PAIR_Last;
return Table[RegNum].IsI64Pair;
}
static inline bool isEncodedSReg(int32_t RegNum) {
return Reg_SREG_First <= RegNum && RegNum <= Reg_SREG_Last;
return Table[RegNum].IsFP32;
}
static inline SizeT getNumSRegs() {
......@@ -116,22 +179,25 @@ public:
static inline SRegister getEncodedSReg(int32_t RegNum) {
assert(Reg_SREG_First <= RegNum);
assert(RegNum <= Reg_SREG_Last);
return SRegister(RegNum - Reg_SREG_First);
return SRegister(Table[RegNum].Encoding);
}
static inline DRegister getEncodedDReg(int32_t RegNum) {
assert(Reg_DREG_First <= RegNum);
assert(RegNum <= Reg_DREG_Last);
return DRegister(RegNum - Reg_DREG_First);
return DRegister(Table[RegNum].Encoding);
}
static inline QRegister getEncodedQReg(int32_t RegNum) {
assert(Reg_QREG_First <= RegNum);
assert(RegNum <= Reg_QREG_Last);
return QRegister(RegNum - Reg_QREG_First);
return QRegister(Table[RegNum].Encoding);
}
static const char *RegNames[];
static inline IceString getRegName(SizeT RegNum) {
assert(RegNum < Reg_NUM);
return Table[RegNum].Name;
}
};
// Extend enum RegClass with ARM32-specific register classes (if any).
......
......@@ -56,6 +56,9 @@ void staticInit() { ::Ice::ARM32::TargetARM32::staticInit(); }
namespace Ice {
namespace ARM32 {
// Defines the RegARM32::Table table with register information.
constexpr RegARM32::TableType RegARM32::Table[];
namespace {
// The following table summarizes the logic for lowering the icmp instruction
......@@ -239,35 +242,35 @@ void TargetARM32::staticInit() {
llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM);
llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM);
ScratchRegs.resize(RegARM32::Reg_NUM);
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
IntegerRegisters[RegARM32::val] = isInt; \
I64PairRegisters[RegARM32::val] = isI64Pair; \
Float32Registers[RegARM32::val] = isFP32; \
Float64Registers[RegARM32::val] = isFP64; \
VectorRegisters[RegARM32::val] = isVec128; \
RegisterAliases[RegARM32::val].resize(RegARM32::Reg_NUM); \
for (SizeT RegAlias : alias_init) { \
assert((!RegisterAliases[RegARM32::val][RegAlias] || \
RegAlias != RegARM32::val) && \
"Duplicate alias for " #val); \
RegisterAliases[RegARM32::val].set(RegAlias); \
} \
RegisterAliases[RegARM32::val].set(RegARM32::val); \
ScratchRegs[RegARM32::val] = scratch; \
if ((isInt) && (cc_arg) > 0) { \
GPRArgInitializer[(cc_arg)-1] = RegARM32::val; \
} else if ((isI64Pair) && (cc_arg) > 0) { \
I64ArgInitializer[(cc_arg)-1] = RegARM32::val; \
} else if ((isFP32) && (cc_arg) > 0) { \
FP32ArgInitializer[(cc_arg)-1] = RegARM32::val; \
} else if ((isFP64) && (cc_arg) > 0) { \
FP64ArgInitializer[(cc_arg)-1] = RegARM32::val; \
} else if ((isVec128) && (cc_arg) > 0) { \
Vec128ArgInitializer[(cc_arg)-1] = RegARM32::val; \
}
REGARM32_TABLE;
#undef X
for (int i = 0; i < RegARM32::Reg_NUM; ++i) {
const auto &Entry = RegARM32::Table[i];
IntegerRegisters[i] = Entry.IsInt;
I64PairRegisters[i] = Entry.IsI64Pair;
Float32Registers[i] = Entry.IsFP32;
Float64Registers[i] = Entry.IsFP64;
VectorRegisters[i] = Entry.IsVec128;
ScratchRegs[i] = Entry.Scratch;
RegisterAliases[i].resize(RegARM32::Reg_NUM);
for (int j = 0; j < Entry.NumAliases; ++j) {
assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]);
RegisterAliases[i].set(Entry.Aliases[j]);
}
assert(RegisterAliases[i][i]);
if (Entry.CCArg <= 0) {
continue;
}
if (Entry.IsGPR) {
GPRArgInitializer[Entry.CCArg - 1] = i;
} else if (Entry.IsI64Pair) {
I64ArgInitializer[Entry.CCArg - 1] = i;
} else if (Entry.IsFP32) {
FP32ArgInitializer[Entry.CCArg - 1] = i;
} else if (Entry.IsFP64) {
FP64ArgInitializer[Entry.CCArg - 1] = i;
} else if (Entry.IsVec128) {
Vec128ArgInitializer[Entry.CCArg - 1] = i;
}
}
TypeToRegisterSet[IceType_void] = InvalidRegisters;
TypeToRegisterSet[IceType_i1] = IntegerRegisters;
TypeToRegisterSet[IceType_i8] = IntegerRegisters;
......@@ -827,18 +830,10 @@ bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) {
return false;
}
const char *RegARM32::RegNames[] = {
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
name,
REGARM32_TABLE
#undef X
};
IceString TargetARM32::getRegName(SizeT RegNum, Type Ty) const {
assert(RegNum < RegARM32::Reg_NUM);
(void)Ty;
return RegARM32::RegNames[RegNum];
return RegARM32::getRegName(RegNum);
}
Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) {
......@@ -1834,28 +1829,25 @@ llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include,
RegSetMask Exclude) const {
llvm::SmallBitVector Registers(RegARM32::Reg_NUM);
#define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \
isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \
if (scratch && (Include & RegSet_CallerSave)) \
Registers[RegARM32::val] = true; \
if (preserved && (Include & RegSet_CalleeSave)) \
Registers[RegARM32::val] = true; \
if (stackptr && (Include & RegSet_StackPointer)) \
Registers[RegARM32::val] = true; \
if (frameptr && (Include & RegSet_FramePointer)) \
Registers[RegARM32::val] = true; \
if (scratch && (Exclude & RegSet_CallerSave)) \
Registers[RegARM32::val] = false; \
if (preserved && (Exclude & RegSet_CalleeSave)) \
Registers[RegARM32::val] = false; \
if (stackptr && (Exclude & RegSet_StackPointer)) \
Registers[RegARM32::val] = false; \
if (frameptr && (Exclude & RegSet_FramePointer)) \
Registers[RegARM32::val] = false;
REGARM32_TABLE
#undef X
for (int i = 0; i < RegARM32::Reg_NUM; ++i) {
const auto &Entry = RegARM32::Table[i];
if (Entry.Scratch && (Include & RegSet_CallerSave))
Registers[i] = true;
if (Entry.Preserved && (Include & RegSet_CalleeSave))
Registers[i] = true;
if (Entry.StackPtr && (Include & RegSet_StackPointer))
Registers[i] = true;
if (Entry.FramePtr && (Include & RegSet_FramePointer))
Registers[i] = true;
if (Entry.Scratch && (Exclude & RegSet_CallerSave))
Registers[i] = false;
if (Entry.Preserved && (Exclude & RegSet_CalleeSave))
Registers[i] = false;
if (Entry.StackPtr && (Exclude & RegSet_StackPointer))
Registers[i] = false;
if (Entry.FramePtr && (Exclude & RegSet_FramePointer))
Registers[i] = false;
}
return Registers;
}
......
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