summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/Target.td16
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp19
-rw-r--r--utils/TableGen/CodeGenRegisters.h14
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp33
4 files changed, 75 insertions, 7 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 616087cd14..915879202c 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -138,6 +138,22 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
// overload virtual methods.
code MethodProtos = [{}];
code MethodBodies = [{}];
+
+ // AltOrders - List of alternative allocation orders. The default order is
+ // MemberList itself, and that is good enough for most targets since the
+ // register allocators automatically remove reserved registers and move
+ // callee-saved registers to the end.
+ list<dag> AltOrders = [];
+
+ // AltOrderSelect - The body of a function that selects the allocation order
+ // to use in a given machine function. The code will be inserted in a
+ // function like this:
+ //
+ // static inline unsigned f(const MachineFunction &MF) { ... }
+ //
+ // The function should return 0 to select the default order defined by
+ // MemberList, 1 to select the first AltOrders entry and so on.
+ code AltOrderSelect = [{}];
}
// The memberList in a RegisterClass is a dag of set operations. TableGen
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 37952fc36a..6b877826f4 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 55f0b9b3aa..5e3d5e59c1 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 9ffb66a452..bcdde342c0 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";