mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 13:11:39 +01:00
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. llvm-svn: 153837
This commit is contained in:
parent
8b30ff4d0f
commit
84a17ab494
@ -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
|
||||||
|
@ -118,11 +118,11 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
|||||||
OS << "#endif // GET_REGINFO_ENUM\n\n";
|
OS << "#endif // GET_REGINFO_ENUM\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
|
RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS,
|
||||||
const std::vector<CodeGenRegister*> &Regs,
|
const std::vector<CodeGenRegister*> &Regs,
|
||||||
bool isCtor) {
|
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;
|
||||||
|
OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
|
||||||
|
OS << i << "Dwarf2L[]";
|
||||||
|
|
||||||
|
if (!isCtor) {
|
||||||
|
OS << " = {\n";
|
||||||
|
|
||||||
|
// Store the mapping sorted by the LLVM reg num so lookup can be done
|
||||||
|
// with a binary search.
|
||||||
|
std::map<uint64_t, Record*> Dwarf2LMap;
|
||||||
for (DwarfRegNumsMapTy::iterator
|
for (DwarfRegNumsMapTy::iterator
|
||||||
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
|
I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
|
||||||
int DwarfRegNo = I->second[i];
|
int DwarfRegNo = I->second[i];
|
||||||
if (DwarfRegNo < 0)
|
if (DwarfRegNo < 0)
|
||||||
continue;
|
continue;
|
||||||
OS << " ";
|
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";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
if (!isCtor)
|
||||||
OS << "RI->";
|
OS << " = sizeof(" << Namespace
|
||||||
OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", "
|
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
|
||||||
<< getQualifiedName(I->first) << ", ";
|
<< "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n";
|
||||||
if (j == 0)
|
|
||||||
OS << "false";
|
|
||||||
else
|
else
|
||||||
OS << "true";
|
OS << ";\n\n";
|
||||||
OS << " );\n";
|
|
||||||
}
|
}
|
||||||
OS << " break;\n";
|
|
||||||
}
|
|
||||||
OS << " }\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
||||||
@ -194,6 +208,62 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit information about the dwarf register numbers.
|
// 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) {
|
for (unsigned j = 0; j < 2; ++j) {
|
||||||
OS << " switch (";
|
OS << " switch (";
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
@ -206,24 +276,50 @@ 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.
|
|
||||||
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 << " ";
|
OS << " ";
|
||||||
if (!isCtor)
|
if (!isCtor)
|
||||||
OS << "RI->";
|
OS << "RI->";
|
||||||
OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", "
|
std::string Tmp;
|
||||||
<< RegNo << ", ";
|
raw_string_ostream(Tmp) << Namespace
|
||||||
|
<< (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
|
||||||
|
<< "Dwarf2L";
|
||||||
|
OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, ";
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
OS << "false";
|
OS << "false";
|
||||||
else
|
else
|
||||||
OS << "true";
|
OS << "true";
|
||||||
OS << " );\n";
|
OS << ");\n";
|
||||||
|
OS << " break;\n";
|
||||||
}
|
}
|
||||||
|
OS << " }\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit 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
|
||||||
|
<< "L2Dwarf";
|
||||||
|
OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, ";
|
||||||
|
if (j == 0)
|
||||||
|
OS << "false";
|
||||||
|
else
|
||||||
|
OS << "true";
|
||||||
|
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"
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user