diff --git a/llvm/include/llvm/Target/TargetInstrPredicate.td b/llvm/include/llvm/Target/TargetInstrPredicate.td index d25309a45bac..e70da0097904 100644 --- a/llvm/include/llvm/Target/TargetInstrPredicate.td +++ b/llvm/include/llvm/Target/TargetInstrPredicate.td @@ -106,28 +106,50 @@ class CheckSameRegOperand : MCInstPredicate { int SecondIndex = Second; } +// Base class for checks on register/immediate operands. +// It allows users to define checks like: +// MyFunction(MI->getOperand(Index).getImm()) == Val; +// +// In the example above, `MyFunction` is a function that takes as input an +// immediate operand value, and returns another value. Field `FunctionMapper` is +// the name of the function to call on the operand value. +class CheckOperandBase : MCOperandPredicate { + string FunctionMapper = Fn; +} + // Check that the machine register operand at position `Index` references // register R. This predicate assumes that we already checked that the machine // operand at position `Index` is a register operand. -class CheckRegOperand : MCOperandPredicate { +class CheckRegOperand : CheckOperandBase { Register Reg = R; } // Check if register operand at index `Index` is the invalid register. -class CheckInvalidRegOperand : MCOperandPredicate; +class CheckInvalidRegOperand : CheckOperandBase; // Check that the operand at position `Index` is immediate `Imm`. -class CheckImmOperand : MCOperandPredicate { +// If field `FunctionMapper` is a non-empty string, then function +// `FunctionMapper` is applied to the operand value, and the return value is then +// compared against `Imm`. +class CheckImmOperand : CheckOperandBase { int ImmVal = Imm; } // Similar to CheckImmOperand, however the immediate is not a literal number. // This is useful when we want to compare the value of an operand against an // enum value, and we know the actual integer value of that enum. -class CheckImmOperand_s : MCOperandPredicate { +class CheckImmOperand_s : CheckOperandBase { string ImmVal = Value; } +// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. +// Otherwise, it expands to a CheckNot>. +class CheckRegOperandSimple : CheckOperandBase; + +// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. +// Otherwise, it simply evaluates to TruePred. +class CheckImmOperandSimple : CheckOperandBase; + // Check that the operand at position `Index` is immediate value zero. class CheckZeroOperand : CheckImmOperand; @@ -206,13 +228,13 @@ class FunctionPredicateBase { MCStatement Body = body; } -// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is +// Check that a call to method `Name` in class "XXXInstrInfo" (where XXX is // the name of a target) returns true. // // TIIPredicate definitions are used to model calls to the target-specific // 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. +// the target specific `InstrInfo` class. // // There cannot be multiple TIIPredicate definitions with the same name for the // same target. diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index db0cb63ae695..88f2f0fffd68 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -7844,3 +7844,6 @@ X86InstrInfo::insertOutlinedCall(Module &M, MachineBasicBlock &MBB, return It; } + +#define GET_TII_HELPERS +#include "X86GenInstrInfo.inc" diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h index 85afcf8904a1..f3965db4fe7c 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -558,6 +558,9 @@ public: MachineBasicBlock::iterator &It, MachineFunction &MF, const outliner::Candidate &C) const override; +#define GET_TII_HELPER_DECLS +#include "X86GenInstrInfo.inc" + protected: /// Commutes the operands in the given instruction by changing the operands /// order and/or changing the instruction's opcode and/or the immediate value diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index ef8c849e25f4..55b6f192c2f0 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -66,7 +66,8 @@ private: /// This method is used to custom expand TIIPredicate definitions. /// See file llvm/Target/TargetInstPredicates.td for a description of what is /// a TIIPredicate and how to use it. - void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName); + void emitTIIHelperMethods(raw_ostream &OS, StringRef TargetName, + bool ExpandDefinition = true); /// Expand TIIPredicate definitions to functions that accept a const MCInst /// reference. @@ -400,7 +401,8 @@ void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS, } void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS, - StringRef TargetName) { + StringRef TargetName, + bool ExpandDefinition) { RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate"); if (TIIPredicates.empty()) return; @@ -410,8 +412,17 @@ void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS, PE.setIndentLevel(2); for (const Record *Rec : TIIPredicates) { - OS << "\n static bool " << Rec->getValueAsString("FunctionName"); - OS << "(const MachineInstr &MI) {\n"; + OS << "\n " << (ExpandDefinition ? "" : "static ") << "bool "; + if (ExpandDefinition) + OS << TargetName << "InstrInfo::"; + OS << Rec->getValueAsString("FunctionName"); + OS << "(const MachineInstr &MI)"; + if (!ExpandDefinition) { + OS << ";\n"; + continue; + } + + OS << " {\n"; OS.indent(PE.getIndentLevel() * 2); PE.expandStatement(OS, Rec->getValueAsDef("Body")); @@ -517,12 +528,21 @@ void InstrInfoEmitter::run(raw_ostream &OS) { << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n" << " ~" << ClassName << "() override = default;\n"; - emitTIIHelperMethods(OS, TargetName); OS << "\n};\n} // end llvm namespace\n"; OS << "#endif // GET_INSTRINFO_HEADER\n\n"; + OS << "#ifdef GET_TII_HELPER_DECLS\n"; + OS << "#undef GET_TII_HELPER_DECLS\n"; + emitTIIHelperMethods(OS, TargetName, /* ExpandDefintion = */false); + OS << "#endif // GET_TII_HELPER_DECLS\n\n"; + + OS << "#ifdef GET_TII_HELPERS\n"; + OS << "#undef GET_TII_HELPERS\n"; + emitTIIHelperMethods(OS, TargetName, /* ExpandDefintion = */true); + OS << "#endif // GET_TTI_HELPERS\n\n"; + OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n"; OS << "#undef GET_INSTRINFO_CTOR_DTOR\n"; diff --git a/llvm/utils/TableGen/PredicateExpander.cpp b/llvm/utils/TableGen/PredicateExpander.cpp index 83f67c023e51..ad7bf60caab9 100644 --- a/llvm/utils/TableGen/PredicateExpander.cpp +++ b/llvm/utils/TableGen/PredicateExpander.cpp @@ -20,23 +20,43 @@ void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; } void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; } void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex, - int ImmVal) { + int ImmVal, + StringRef FunctionMapper) { + if (!FunctionMapper.empty()) + OS << FunctionMapper << "("; OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex - << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal; + << ").getImm()"; + OS << (FunctionMapper.empty() ? " " : ") "); + OS << (shouldNegate() ? "!= " : "== ") << ImmVal; } void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex, - StringRef ImmVal) { + StringRef ImmVal, + StringRef FunctionMapper) { + if (!FunctionMapper.empty()) + OS << FunctionMapper << "("; OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex - << ").getImm() " << (shouldNegate() ? "!= " : "== ") << ImmVal; + << ").getImm()"; + + OS << (FunctionMapper.empty() ? "" : ")"); + if (ImmVal.empty()) + return; + OS << (shouldNegate() ? " != " : " == ") << ImmVal; } void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex, - const Record *Reg) { + const Record *Reg, + StringRef FunctionMapper) { assert(Reg->isSubClassOf("Register") && "Expected a register Record!"); + if (!FunctionMapper.empty()) + OS << FunctionMapper << "("; OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex - << ").getReg() " << (shouldNegate() ? "!= " : "== "); + << ").getReg()"; + OS << (FunctionMapper.empty() ? "" : ")"); + if (!Reg) + return; + OS << (shouldNegate() ? " != " : " == "); const StringRef Str = Reg->getValueAsString("Namespace"); if (!Str.empty()) OS << Str << "::"; @@ -137,7 +157,7 @@ void PredicateExpander::expandPredicateSequence(raw_ostream &OS, void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS, StringRef MethodName) { OS << (shouldNegate() ? "!" : ""); - OS << TargetName << (shouldExpandForMC() ? "_MC::" : "GenInstrInfo::"); + OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::"); OS << MethodName << (isByRef() ? "(MI)" : "(*MI)"); } @@ -266,18 +286,30 @@ void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) { if (Rec->isSubClassOf("CheckRegOperand")) return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"), - Rec->getValueAsDef("Reg")); + Rec->getValueAsDef("Reg"), + Rec->getValueAsString("FunctionMapper")); + + if (Rec->isSubClassOf("CheckRegOperandSimple")) + return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"), + nullptr, + Rec->getValueAsString("FunctionMapper")); if (Rec->isSubClassOf("CheckInvalidRegOperand")) return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex")); if (Rec->isSubClassOf("CheckImmOperand")) return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"), - Rec->getValueAsInt("ImmVal")); + Rec->getValueAsInt("ImmVal"), + Rec->getValueAsString("FunctionMapper")); if (Rec->isSubClassOf("CheckImmOperand_s")) return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"), - Rec->getValueAsString("ImmVal")); + Rec->getValueAsString("ImmVal"), + Rec->getValueAsString("FunctionMapper")); + + if (Rec->isSubClassOf("CheckImmOperandSimple")) + return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"), "", + Rec->getValueAsString("FunctionMapper")); if (Rec->isSubClassOf("CheckSameRegOperand")) return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"), diff --git a/llvm/utils/TableGen/PredicateExpander.h b/llvm/utils/TableGen/PredicateExpander.h index 255e40c49988..0f3ee6867e65 100644 --- a/llvm/utils/TableGen/PredicateExpander.h +++ b/llvm/utils/TableGen/PredicateExpander.h @@ -56,9 +56,16 @@ public: using RecVec = std::vector; void expandTrue(raw_ostream &OS); void expandFalse(raw_ostream &OS); - void expandCheckImmOperand(raw_ostream &OS, int OpIndex, int ImmVal); - void expandCheckImmOperand(raw_ostream &OS, int OpIndex, StringRef ImmVal); - void expandCheckRegOperand(raw_ostream &OS, int OpIndex, const Record *Reg); + void expandCheckImmOperand(raw_ostream &OS, int OpIndex, int ImmVal, + StringRef FunctionMapper); + void expandCheckImmOperand(raw_ostream &OS, int OpIndex, StringRef ImmVal, + StringRef FunctionMapperer); + void expandCheckImmOperandSimple(raw_ostream &OS, int OpIndex, + StringRef FunctionMapper); + void expandCheckRegOperand(raw_ostream &OS, int OpIndex, const Record *Reg, + StringRef FunctionMapper); + void expandCheckRegOperandSimple(raw_ostream &OS, int OpIndex, + StringRef FunctionMapper); void expandCheckSameRegOperand(raw_ostream &OS, int First, int Second); void expandCheckNumOperands(raw_ostream &OS, int NumOps); void expandCheckOpcode(raw_ostream &OS, const Record *Inst);