Emit the LLVM<->DWARF register mapping as a sorted table and use binary search to do the lookup.

This also avoids emitting the information twice, which led to code bloat. On i386-linux-Release+Asserts
with all targets built this change shaves a whopping 1.3 MB off clang. The number is probably exaggerated
by recent inliner changes but the methods were already enormous with the old inline cost computation.

The DWARF reg -> LLVM reg mapping doesn't seem to have holes in it, so it could be a simple lookup table.
I didn't implement that optimization yet to avoid potentially changing functionality.

There is still some duplication both in tablegen and the generated code that should be cleaned up eventually.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153837 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Benjamin Kramer 2012-04-01 14:23:58 +00:00
parent dafe48e230
commit 243018ffcf
3 changed files with 201 additions and 72 deletions

View File

@ -127,6 +127,16 @@ struct MCRegisterDesc {
class MCRegisterInfo { class MCRegisterInfo {
public: public:
typedef const MCRegisterClass *regclass_iterator; typedef const MCRegisterClass *regclass_iterator;
/// DwarfLLVMRegPair - Emitted by tablegen so Dwarf<->LLVM reg mappings can be
/// performed with a binary search.
struct DwarfLLVMRegPair {
unsigned FromReg;
unsigned ToReg;
bool operator==(unsigned Reg) const { return FromReg == Reg; }
bool operator<(unsigned Reg) const { return FromReg < Reg; }
};
private: private:
const MCRegisterDesc *Desc; // Pointer to the descriptor array const MCRegisterDesc *Desc; // Pointer to the descriptor array
unsigned NumRegs; // Number of entries in the array unsigned NumRegs; // Number of entries in the array
@ -137,10 +147,15 @@ private:
const uint16_t *SubRegIndices; // Pointer to the subreg lookup const uint16_t *SubRegIndices; // Pointer to the subreg lookup
// array. // array.
unsigned NumSubRegIndices; // Number of subreg indices. unsigned NumSubRegIndices; // Number of subreg indices.
DenseMap<unsigned, int> L2DwarfRegs; // LLVM to Dwarf regs mapping
DenseMap<unsigned, int> EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH unsigned L2DwarfRegsSize;
DenseMap<unsigned, unsigned> Dwarf2LRegs; // Dwarf to LLVM regs mapping unsigned EHL2DwarfRegsSize;
DenseMap<unsigned, unsigned> EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH unsigned Dwarf2LRegsSize;
unsigned EHDwarf2LRegsSize;
const DwarfLLVMRegPair *L2DwarfRegs; // LLVM to Dwarf regs mapping
const DwarfLLVMRegPair *EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH
const DwarfLLVMRegPair *Dwarf2LRegs; // Dwarf to LLVM regs mapping
const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH
DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping
public: public:
@ -161,24 +176,32 @@ public:
NumSubRegIndices = NumIndices; NumSubRegIndices = NumIndices;
} }
/// mapLLVMRegToDwarfReg - Used to initialize LLVM register to Dwarf /// mapLLVMRegsToDwarfRegs - Used to initialize LLVM register to Dwarf
/// register number mapping. Called by TableGen auto-generated routines. /// register number mapping. Called by TableGen auto-generated routines.
/// *DO NOT USE*. /// *DO NOT USE*.
void mapLLVMRegToDwarfReg(unsigned LLVMReg, int DwarfReg, bool isEH) { void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size,
if (isEH) bool isEH) {
EHL2DwarfRegs[LLVMReg] = DwarfReg; if (isEH) {
else EHL2DwarfRegs = Map;
L2DwarfRegs[LLVMReg] = DwarfReg; EHL2DwarfRegsSize = Size;
} else {
L2DwarfRegs = Map;
L2DwarfRegsSize = Size;
}
} }
/// mapDwarfRegToLLVMReg - Used to initialize Dwarf register to LLVM /// mapDwarfRegsToLLVMRegs - Used to initialize Dwarf register to LLVM
/// register number mapping. Called by TableGen auto-generated routines. /// register number mapping. Called by TableGen auto-generated routines.
/// *DO NOT USE*. /// *DO NOT USE*.
void mapDwarfRegToLLVMReg(unsigned DwarfReg, unsigned LLVMReg, bool isEH) { void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size,
if (isEH) bool isEH) {
EHDwarf2LRegs[DwarfReg] = LLVMReg; if (isEH) {
else EHDwarf2LRegs = Map;
Dwarf2LRegs[DwarfReg] = LLVMReg; EHDwarf2LRegsSize = Size;
} else {
Dwarf2LRegs = Map;
Dwarf2LRegsSize = Size;
}
} }
/// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register /// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register
@ -289,21 +312,24 @@ public:
/// parameter allows targets to use different numberings for EH info and /// parameter allows targets to use different numberings for EH info and
/// debugging info. /// debugging info.
int getDwarfRegNum(unsigned RegNum, bool isEH) const { int getDwarfRegNum(unsigned RegNum, bool isEH) const {
const DenseMap<unsigned, int> &M = isEH ? EHL2DwarfRegs : L2DwarfRegs; const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs;
const DenseMap<unsigned, int>::const_iterator I = M.find(RegNum); unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize;
if (I == M.end()) return -1;
return I->second; const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, RegNum);
if (I == M+Size || I->FromReg != RegNum)
return -1;
return I->ToReg;
} }
/// getLLVMRegNum - Map a dwarf register back to a target register. /// getLLVMRegNum - Map a dwarf register back to a target register.
/// ///
int getLLVMRegNum(unsigned RegNum, bool isEH) const { int getLLVMRegNum(unsigned RegNum, bool isEH) const {
const DenseMap<unsigned, unsigned> &M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs;
const DenseMap<unsigned, unsigned>::const_iterator I = M.find(RegNum); unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize;
if (I == M.end()) {
llvm_unreachable("Invalid RegNum"); const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, RegNum);
} assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum");
return I->second; return I->ToReg;
} }
/// getSEHRegNum - Map a target register to an equivalent SEH register /// getSEHRegNum - Map a target register to an equivalent SEH register

View File

@ -118,11 +118,11 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "#endif // GET_REGINFO_ENUM\n\n"; OS << "#endif // GET_REGINFO_ENUM\n\n";
} }
void
RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
const std::vector<CodeGenRegister*> &Regs,
bool isCtor) {
void
RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
const std::vector<CodeGenRegister*> &Regs,
bool isCtor) {
// Collect all information about dwarf register numbers // Collect all information about dwarf register numbers
typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
DwarfRegNumsMapTy DwarfRegNums; DwarfRegNumsMapTy DwarfRegNums;
@ -148,38 +148,52 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
I->second.push_back(-1); I->second.push_back(-1);
std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace");
OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n";
// Emit reverse information about the dwarf register numbers. // Emit reverse information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) { for (unsigned j = 0; j < 2; ++j) {
OS << " switch (";
if (j == 0)
OS << "DwarfFlavour";
else
OS << "EHFlavour";
OS << ") {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown DWARF flavour\");\n";
for (unsigned i = 0, e = maxLength; i != e; ++i) { for (unsigned i = 0, e = maxLength; i != e; ++i) {
OS << " case " << i << ":\n"; OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace;
for (DwarfRegNumsMapTy::iterator OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { OS << i << "Dwarf2L[]";
int DwarfRegNo = I->second[i];
if (DwarfRegNo < 0) if (!isCtor) {
continue; OS << " = {\n";
OS << " ";
if (!isCtor) // Store the mapping sorted by the LLVM reg num so lookup can be done
OS << "RI->"; // with a binary search.
OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", " std::map<uint64_t, Record*> Dwarf2LMap;
<< getQualifiedName(I->first) << ", "; for (DwarfRegNumsMapTy::iterator
if (j == 0) I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
OS << "false"; int DwarfRegNo = I->second[i];
else if (DwarfRegNo < 0)
OS << "true"; continue;
OS << " );\n"; Dwarf2LMap[DwarfRegNo] = I->first;
}
for (std::map<uint64_t, Record*>::iterator
I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I)
OS << " { " << I->first << "U, " << getQualifiedName(I->second)
<< " },\n";
OS << "};\n";
} else {
OS << ";\n";
} }
OS << " break;\n";
// We have to store the size in a const global, it's used in multiple
// places.
OS << "extern const unsigned " << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize";
if (!isCtor)
OS << " = sizeof(" << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n";
else
OS << ";\n\n";
} }
OS << " }\n";
} }
for (unsigned i = 0, e = Regs.size(); i != e; ++i) { for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
@ -193,6 +207,93 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
DwarfRegNums[Reg] = DwarfRegNums[Alias]; DwarfRegNums[Reg] = DwarfRegNums[Alias];
} }
// Emit information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) {
for (unsigned i = 0, e = maxLength; i != e; ++i) {
OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace;
OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
OS << i << "L2Dwarf[]";
if (!isCtor) {
OS << " = {\n";
// Store the mapping sorted by the Dwarf reg num so lookup can be done
// with a binary search.
for (DwarfRegNumsMapTy::iterator
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
int RegNo = I->second[i];
if (RegNo == -1) // -1 is the default value, don't emit a mapping.
continue;
OS << " { " << getQualifiedName(I->first) << ", " << RegNo
<< "U },\n";
}
OS << "};\n";
} else {
OS << ";\n";
}
// We have to store the size in a const global, it's used in multiple
// places.
OS << "extern const unsigned " << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize";
if (!isCtor)
OS << " = sizeof(" << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n";
else
OS << ";\n\n";
}
}
}
void
RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
const std::vector<CodeGenRegister*> &Regs,
bool isCtor) {
// Emit the initializer so the tables from EmitRegMappingTables get wired up
// to the MCRegisterInfo object.
unsigned maxLength = 0;
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
Record *Reg = Regs[i]->TheDef;
maxLength = std::max((size_t)maxLength,
Reg->getValueAsListOfInts("DwarfNumbers").size());
}
if (!maxLength)
return;
std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace");
// Emit reverse information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) {
OS << " switch (";
if (j == 0)
OS << "DwarfFlavour";
else
OS << "EHFlavour";
OS << ") {\n"
<< " default:\n"
<< " llvm_unreachable(\"Unknown DWARF flavour\");\n";
for (unsigned i = 0, e = maxLength; i != e; ++i) {
OS << " case " << i << ":\n";
OS << " ";
if (!isCtor)
OS << "RI->";
std::string Tmp;
raw_string_ostream(Tmp) << Namespace
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "Dwarf2L";
OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, ";
if (j == 0)
OS << "false";
else
OS << "true";
OS << ");\n";
OS << " break;\n";
}
OS << " }\n";
}
// Emit information about the dwarf register numbers. // Emit information about the dwarf register numbers.
for (unsigned j = 0; j < 2; ++j) { for (unsigned j = 0; j < 2; ++j) {
OS << " switch ("; OS << " switch (";
@ -206,24 +307,19 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
for (unsigned i = 0, e = maxLength; i != e; ++i) { for (unsigned i = 0, e = maxLength; i != e; ++i) {
OS << " case " << i << ":\n"; OS << " case " << i << ":\n";
// Sort by name to get a stable order. OS << " ";
for (DwarfRegNumsMapTy::iterator if (!isCtor)
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { OS << "RI->";
int RegNo = I->second[i]; std::string Tmp;
if (RegNo == -1) // -1 is the default value, don't emit a mapping. raw_string_ostream(Tmp) << Namespace
continue; << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
<< "L2Dwarf";
OS << " "; OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, ";
if (!isCtor) if (j == 0)
OS << "RI->";
OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", "
<< RegNo << ", ";
if (j == 0)
OS << "false"; OS << "false";
else else
OS << "true"; OS << "true";
OS << " );\n"; OS << ");\n";
}
OS << " break;\n"; OS << " break;\n";
} }
OS << " }\n"; OS << " }\n";
@ -448,6 +544,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "SubRegTable;\n}\n\n"; << "SubRegTable;\n}\n\n";
} }
EmitRegMappingTables(OS, Regs, false);
// MCRegisterInfo initialization routine. // MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName OS << "static inline void Init" << TargetName
<< "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
@ -872,6 +970,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "extern const uint16_t *get" << TargetName OS << "extern const uint16_t *get" << TargetName
<< "SubRegTable();\n"; << "SubRegTable();\n";
EmitRegMappingTables(OS, Regs, true);
OS << ClassName << "::\n" << ClassName OS << ClassName << "::\n" << ClassName
<< "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n"
<< " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"

View File

@ -50,6 +50,9 @@ public:
private: private:
void EmitRegMapping(raw_ostream &o, void EmitRegMapping(raw_ostream &o,
const std::vector<CodeGenRegister*> &Regs, bool isCtor); const std::vector<CodeGenRegister*> &Regs, bool isCtor);
void EmitRegMappingTables(raw_ostream &o,
const std::vector<CodeGenRegister*> &Regs,
bool isCtor);
void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target); void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
}; };