summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/Target/TargetInstrPredicate.td34
-rw-r--r--llvm/lib/Target/X86/X86SchedPredicates.td17
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp10
-rw-r--r--llvm/utils/TableGen/PredicateExpander.cpp66
-rw-r--r--llvm/utils/TableGen/PredicateExpander.h5
5 files changed, 119 insertions, 13 deletions
diff --git a/llvm/include/llvm/Target/TargetInstrPredicate.td b/llvm/include/llvm/Target/TargetInstrPredicate.td
index 8d57cae02d2..8925e4b0b39 100644
--- a/llvm/include/llvm/Target/TargetInstrPredicate.td
+++ b/llvm/include/llvm/Target/TargetInstrPredicate.td
@@ -169,6 +169,35 @@ class CheckAll<list<MCInstPredicate> Sequence>
class CheckAny<list<MCInstPredicate> Sequence>
: CheckPredicateSequence<Sequence>;
+
+// Used to expand the body of a function predicate. See the definition of
+// TIIPredicate below.
+class MCStatement;
+
+// Expands to a return statement. The return expression is a boolean expression
+// described by a MCInstPredicate.
+class MCReturnStatement<MCInstPredicate predicate> : MCStatement {
+ MCInstPredicate Pred = predicate;
+}
+
+// Used to automatically construct cases of a switch statement where the switch
+// variable is an instruction opcode. There is a 'case' for every opcode in the
+// `opcodes` list, and each case is associated with MCStatement `caseStmt`.
+class MCOpcodeSwitchCase<list<Instruction> opcodes, MCStatement caseStmt> {
+ list<Instruction> Opcodes = opcodes;
+ MCStatement CaseStmt = caseStmt;
+}
+
+// Expands to a switch statement. The switch variable is an instruction opcode.
+// The auto-generated switch is populated by a number of cases based on the
+// `cases` list in input. A default case is automatically generated, and it
+// evaluates to `default`.
+class MCOpcodeSwitchStatement<list<MCOpcodeSwitchCase> cases,
+ MCStatement default> : MCStatement {
+ list<MCOpcodeSwitchCase> Cases = cases;
+ MCStatement DefaultCase = default;
+}
+
// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is
// the `Target` name) returns true.
//
@@ -176,10 +205,11 @@ class CheckAny<list<MCInstPredicate> Sequence>
// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter
// tablegen backend, which will use it to automatically generate a definition in
// the target specific `GenInstrInfo` class.
-class TIIPredicate<string Target, string Name, MCInstPredicate P> : MCInstPredicate {
+class TIIPredicate<string Target, string Name, MCStatement body>
+ : MCInstPredicate {
string TargetName = Target;
string FunctionName = Name;
- MCInstPredicate Pred = P;
+ MCStatement Body = body;
}
// A function predicate that takes as input a machine instruction, and returns
diff --git a/llvm/lib/Target/X86/X86SchedPredicates.td b/llvm/lib/Target/X86/X86SchedPredicates.td
index 27aaeb19358..abb86119d45 100644
--- a/llvm/lib/Target/X86/X86SchedPredicates.td
+++ b/llvm/lib/Target/X86/X86SchedPredicates.td
@@ -19,11 +19,9 @@
// different zero-idioms.
def ZeroIdiomPredicate : CheckSameRegOperand<1, 2>;
-// A predicate used to check if an instruction is a LEA, and if it uses all
-// three source operands: base, index, and offset.
+// A predicate used to check if a LEA instruction uses all three source
+// operands: base, index, and offset.
def IsThreeOperandsLEAPredicate: CheckAll<[
- CheckOpcode<[LEA32r, LEA64r, LEA64_32r, LEA16r]>,
-
// isRegOperand(Base)
CheckIsRegOperand<1>,
CheckNot<CheckInvalidRegOperand<1>>,
@@ -42,8 +40,17 @@ def IsThreeOperandsLEAPredicate: CheckAll<[
]>
]>;
+def LEACases : MCOpcodeSwitchCase<
+ [LEA32r, LEA64r, LEA64_32r, LEA16r],
+ MCReturnStatement<IsThreeOperandsLEAPredicate>
+>;
+
+// Used to generate the body of a TII member function.
+def IsThreeOperandsLEABody :
+ MCOpcodeSwitchStatement<[LEACases], MCReturnStatement<FalsePred>>;
+
// This predicate evaluates to true only if the input machine instruction is a
// 3-operands LEA. Tablegen automatically generates a new method for it in
// X86GenInstrInfo.
def IsThreeOperandsLEAFn :
- TIIPredicate<"X86", "isThreeOperandsLEA", IsThreeOperandsLEAPredicate>;
+ TIIPredicate<"X86", "isThreeOperandsLEA", IsThreeOperandsLEABody>;
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index a492daac0d0..ca9d5ed262d 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -389,9 +389,8 @@ void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS) {
for (const Record *Rec : TIIPredicates) {
FOS << "bool " << Rec->getValueAsString("FunctionName");
FOS << "(const MCInst &MI) {\n";
- FOS << " return ";
- PE.expandPredicate(FOS, Rec->getValueAsDef("Pred"));
- FOS << ";\n}\n";
+ PE.expandStatement(FOS, Rec->getValueAsDef("Body"));
+ FOS << "\n}\n";
}
FOS << "\n} // end " << TargetName << "_MC namespace\n";
@@ -413,9 +412,8 @@ void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS) {
for (const Record *Rec : TIIPredicates) {
FOS << "\n static bool " << Rec->getValueAsString("FunctionName");
FOS << "(const MachineInstr &MI) {\n";
- FOS << " return ";
- PE.expandPredicate(FOS, Rec->getValueAsDef("Pred"));
- FOS << ";\n }\n";
+ PE.expandStatement(FOS, Rec->getValueAsDef("Body"));
+ FOS << "\n }\n";
}
}
diff --git a/llvm/utils/TableGen/PredicateExpander.cpp b/llvm/utils/TableGen/PredicateExpander.cpp
index 68eb32794a0..6f611737a43 100644
--- a/llvm/utils/TableGen/PredicateExpander.cpp
+++ b/llvm/utils/TableGen/PredicateExpander.cpp
@@ -176,6 +176,72 @@ void PredicateExpander::expandCheckNonPortable(formatted_raw_ostream &OS,
OS << '(' << Code << ')';
}
+void PredicateExpander::expandReturnStatement(formatted_raw_ostream &OS,
+ const Record *Rec) {
+ OS << "return ";
+ expandPredicate(OS, Rec);
+ OS << ";";
+}
+
+void PredicateExpander::expandOpcodeSwitchCase(formatted_raw_ostream &OS,
+ const Record *Rec) {
+ const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
+ for (const Record *Opcode : Opcodes) {
+ OS.PadToColumn(getIndentLevel() * 2);
+ OS << "case " << Opcode->getValueAsString("Namespace")
+ << "::" << Opcode->getName() << " :\n";
+ }
+
+ increaseIndentLevel();
+ expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
+ decreaseIndentLevel();
+}
+
+void PredicateExpander::expandOpcodeSwitchStatement(formatted_raw_ostream &OS,
+ const RecVec &Cases,
+ const Record *Default) {
+ OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
+
+ for (const Record *Rec : Cases) {
+ expandOpcodeSwitchCase(OS, Rec);
+ OS << '\n';
+ }
+
+ unsigned ColNum = getIndentLevel() * 2;
+ OS.PadToColumn(ColNum);
+
+ // Expand the default case.
+ OS << "default :\n";
+ increaseIndentLevel();
+ expandStatement(OS, Default);
+ decreaseIndentLevel();
+ OS << '\n';
+
+ OS.PadToColumn(ColNum);
+ OS << "} // end of switch-stmt";
+}
+
+void PredicateExpander::expandStatement(formatted_raw_ostream &OS,
+ const Record *Rec) {
+ OS.flush();
+ unsigned ColNum = getIndentLevel() * 2;
+ if (OS.getColumn() < ColNum)
+ OS.PadToColumn(ColNum);
+
+ if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
+ expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
+ Rec->getValueAsDef("DefaultCase"));
+ return;
+ }
+
+ if (Rec->isSubClassOf("MCReturnStatement")) {
+ expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
+ return;
+ }
+
+ llvm_unreachable("No known rules to expand this MCStatement");
+}
+
void PredicateExpander::expandPredicate(formatted_raw_ostream &OS,
const Record *Rec) {
OS.flush();
diff --git a/llvm/utils/TableGen/PredicateExpander.h b/llvm/utils/TableGen/PredicateExpander.h
index 398b376f7a8..31952dc690e 100644
--- a/llvm/utils/TableGen/PredicateExpander.h
+++ b/llvm/utils/TableGen/PredicateExpander.h
@@ -79,6 +79,11 @@ public:
StringRef MachineInstrFn);
void expandCheckNonPortable(formatted_raw_ostream &OS, StringRef CodeBlock);
void expandPredicate(formatted_raw_ostream &OS, const Record *Rec);
+ void expandReturnStatement(formatted_raw_ostream &OS, const Record *Rec);
+ void expandOpcodeSwitchCase(formatted_raw_ostream &OS, const Record *Rec);
+ void expandOpcodeSwitchStatement(formatted_raw_ostream &OS,
+ const RecVec &Cases, const Record *Default);
+ void expandStatement(formatted_raw_ostream &OS, const Record *Rec);
};
} // namespace llvm
OpenPOWER on IntegriCloud