summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-06-18 00:50:49 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-06-18 00:50:49 +0000
commitb4c704877d1600852a55ab7bef2918a7c0af5e0d (patch)
tree797c8330b51e92939fa6b20a2b45674a8e02d32a /utils
parentedb15d6872c4475f45f3182960bd138acda6799e (diff)
downloadllvm-b4c704877d1600852a55ab7bef2918a7c0af5e0d.tar.gz
llvm-b4c704877d1600852a55ab7bef2918a7c0af5e0d.tar.bz2
llvm-b4c704877d1600852a55ab7bef2918a7c0af5e0d.tar.xz
Provide AltOrders for specifying alternative allocation orders.
A register class can define AltOrders and AltOrderSelect instead of defining method protos and bodies. The AltOrders lists can be defined with set operations, and TableGen can verify that the alternative allocation orders only contain valid registers. This is currently an opt-in feature, and it is still possible to override allocation_order_begin/end. That will not be true for long. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133320 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp19
-rw-r--r--utils/TableGen/CodeGenRegisters.h14
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp33
3 files changed, 59 insertions, 7 deletions
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";