diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/CodeGenRegisters.cpp | 19 | ||||
-rw-r--r-- | utils/TableGen/CodeGenRegisters.h | 14 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 33 |
3 files changed, 59 insertions, 7 deletions
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 37952fc..6b87782 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -172,10 +172,28 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); + // Default allocation order always contains all registers. Elements = RegBank.getSets().expand(R); for (unsigned i = 0, e = Elements->size(); i != e; ++i) Members.insert(RegBank.getReg((*Elements)[i])); + // Alternative allocation orders may be subsets. + ListInit *Alts = R->getValueAsListInit("AltOrders"); + AltOrders.resize(Alts->size()); + SetTheory::RecSet Order; + for (unsigned i = 0, e = Alts->size(); i != e; ++i) { + RegBank.getSets().evaluate(Alts->getElement(i), Order); + AltOrders[i].append(Order.begin(), Order.end()); + // Verify that all altorder members are regclass members. + while (!Order.empty()) { + CodeGenRegister *Reg = RegBank.getReg(Order.back()); + Order.pop_back(); + if (!contains(Reg)) + throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + + " is not a class member"); + } + } + // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. ListInit *SRC = R->getValueAsListInit("SubRegClasses"); for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { @@ -209,6 +227,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) Allocatable = R->getValueAsBit("isAllocatable"); MethodBodies = R->getValueAsCode("MethodBodies"); MethodProtos = R->getValueAsCode("MethodProtos"); + AltOrderSelect = R->getValueAsCode("AltOrderSelect"); } bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 55f0b9b..5e3d5e5 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -86,6 +86,7 @@ namespace llvm { class CodeGenRegisterClass { CodeGenRegister::Set Members; const std::vector<Record*> *Elements; + std::vector<SmallVector<Record*, 16> > AltOrders; public: Record *TheDef; std::string Namespace; @@ -96,7 +97,7 @@ namespace llvm { bool Allocatable; // Map SubRegIndex -> RegisterClass DenseMap<Record*,Record*> SubRegClasses; - std::string MethodProtos, MethodBodies; + std::string MethodProtos, MethodBodies, AltOrderSelect; const std::string &getName() const; const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;} @@ -125,10 +126,17 @@ namespace llvm { // Returns an ordered list of class members. // The order of registers is the same as in the .td file. - ArrayRef<Record*> getOrder() const { - return *Elements; + // No = 0 is the default allocation order, No = 1 is the first alternative. + ArrayRef<Record*> getOrder(unsigned No = 0) const { + if (No == 0) + return *Elements; + else + return AltOrders[No - 1]; } + // Return the total number of allocation orders available. + unsigned getNumOrders() const { return 1 + AltOrders.size(); } + CodeGenRegisterClass(CodeGenRegBank&, Record *R); }; diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 9ffb66a..bcdde34 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -108,12 +108,16 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "\n };\n\n"; for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const std::string &Name = RegisterClasses[i].getName(); + const CodeGenRegisterClass &RC = RegisterClasses[i]; + const std::string &Name = RC.getName(); // Output the register class definition. OS << " struct " << Name << "Class : public TargetRegisterClass {\n" - << " " << Name << "Class();\n" - << RegisterClasses[i].MethodProtos << " };\n"; + << " " << Name << "Class();\n"; + if (!RC.AltOrderSelect.empty()) + OS << " ArrayRef<unsigned> " + "getRawAllocationOrder(const MachineFunction&) const;\n"; + OS << RC.MethodProtos << " };\n"; // Output the extern for the instance. OS << " extern " << Name << "Class\t" << Name << "RegClass;\n"; @@ -349,7 +353,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "\n };\n\n"; } - + // Emit methods. for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RegisterClasses[i]; OS << RC.MethodBodies << "\n"; @@ -371,6 +375,27 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << RC.getName() << ", " << RC.getName() << " + " << RC.getOrder().size() << ") {}\n"; + if (!RC.AltOrderSelect.empty()) { + OS << "\nstatic inline unsigned " << RC.getName() + << "AltOrderSelect(const MachineFunction &MF) {" + << RC.AltOrderSelect << "}\n\nArrayRef<unsigned> " + << RC.getName() << "Class::" + << "getRawAllocationOrder(const MachineFunction &MF) const {\n"; + for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { + ArrayRef<Record*> Elems = RC.getOrder(oi); + OS << " static const unsigned AltOrder" << oi << "[] = {"; + for (unsigned elem = 0; elem != Elems.size(); ++elem) + OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); + OS << " };\n"; + } + OS << " static const ArrayRef<unsigned> Order[] = {\n" + << " ArrayRef<unsigned>(" << RC.getName(); + for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) + OS << "),\n ArrayRef<unsigned>(AltOrder" << oi; + OS << ")\n };\n const unsigned Select = " << RC.getName() + << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() + << ");\n return Order[Select];\n}\n"; + } } OS << "}\n"; |