Index: include/llvm/Target/TargetInstrPredicate.td =================================================================== --- include/llvm/Target/TargetInstrPredicate.td +++ include/llvm/Target/TargetInstrPredicate.td @@ -169,6 +169,35 @@ class CheckAny Sequence> : CheckPredicateSequence; + +// 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 : 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 opcodes, MCStatement caseStmt> { + list 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 cases, + MCStatement default> : MCStatement { + list 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 @@ // 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 : MCInstPredicate { +class TIIPredicate + : 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 Index: lib/Target/X86/X86SchedPredicates.td =================================================================== --- lib/Target/X86/X86SchedPredicates.td +++ 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>, @@ -42,8 +40,17 @@ ]> ]>; +def LEACases : MCOpcodeSwitchCase< + [LEA32r, LEA64r, LEA64_32r, LEA16r], + MCReturnStatement +>; + +// Used to generate the body of a TII member function. +def IsThreeOperandsLEABody : + MCOpcodeSwitchStatement<[LEACases], MCReturnStatement>; + // 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>; Index: utils/TableGen/InstrInfoEmitter.cpp =================================================================== --- utils/TableGen/InstrInfoEmitter.cpp +++ utils/TableGen/InstrInfoEmitter.cpp @@ -389,9 +389,8 @@ 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 @@ 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"; } } Index: utils/TableGen/PredicateExpander.h =================================================================== --- utils/TableGen/PredicateExpander.h +++ utils/TableGen/PredicateExpander.h @@ -79,6 +79,12 @@ 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 Index: utils/TableGen/PredicateExpander.cpp =================================================================== --- utils/TableGen/PredicateExpander.cpp +++ utils/TableGen/PredicateExpander.cpp @@ -176,6 +176,72 @@ 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();