// 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
}
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) {
Allocatable = R->getValueAsBit("isAllocatable");
MethodBodies = R->getValueAsCode("MethodBodies");
MethodProtos = R->getValueAsCode("MethodProtos");
+ AltOrderSelect = R->getValueAsCode("AltOrderSelect");
}
bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
class CodeGenRegisterClass {
CodeGenRegister::Set Members;
const std::vector<Record*> *Elements;
+ std::vector<SmallVector<Record*, 16> > AltOrders;
public:
Record *TheDef;
std::string Namespace;
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;}
// 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);
};
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";
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";
<< 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";