diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -14,11 +14,13 @@ // Include all information about LLVM intrinsics. include "llvm/IR/Intrinsics.td" +class Predicate; // Forward def + //===----------------------------------------------------------------------===// // Register file description - These classes are used to fill in the target // description classes. -class HwMode { +class HwMode Ps> { // A string representing subtarget features that turn on this HW mode. // For example, "+feat1,-feat2" will indicate that the mode is active // when "feat1" is enabled and "feat2" is disabled at the same time. @@ -26,12 +28,15 @@ // When multiple modes are used, they should be mutually exclusive, // otherwise the results are unpredictable. string Features = FS; + + // A list of predicates that turn on this HW mode. + list Predicates = Ps; } // A special mode recognized by tablegen. This mode is considered active // when no other mode is active. For targets that do not use specific hw // modes, this is the only mode. -def DefaultMode : HwMode<"">; +def DefaultMode : HwMode<"", []>; // A class used to associate objects with HW modes. It is only intended to // be used as a base class, where the derived class should contain a member @@ -446,8 +451,6 @@ // include "llvm/Target/TargetSchedule.td" -class Predicate; // Forward def - class InstructionEncoding { // Size of encoded instruction. int Size; diff --git a/llvm/lib/Target/Hexagon/Hexagon.td b/llvm/lib/Target/Hexagon/Hexagon.td --- a/llvm/lib/Target/Hexagon/Hexagon.td +++ b/llvm/lib/Target/Hexagon/Hexagon.td @@ -160,8 +160,8 @@ def UseCabac : Predicate<"HST->useCabac()">, AssemblerPredicate<(any_of FeatureCabac)>; -def Hvx64: HwMode<"+hvx-length64b">; -def Hvx128: HwMode<"+hvx-length128b">; +def Hvx64: HwMode<"+hvx-length64b", [UseHVX64B]>; +def Hvx128: HwMode<"+hvx-length128b", [UseHVX128B]>; //===----------------------------------------------------------------------===// // Classes used for relation maps. diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td --- a/llvm/lib/Target/LoongArch/LoongArch.td +++ b/llvm/lib/Target/LoongArch/LoongArch.td @@ -30,7 +30,7 @@ "LA32 Basic Integer and Privilege Instruction Set">; defvar LA32 = DefaultMode; -def LA64 : HwMode<"+64bit">; +def LA64 : HwMode<"+64bit", [IsLA64]>; // Single Precision floating point def FeatureBasicF diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -587,7 +587,7 @@ "RV32I Base Instruction Set">; defvar RV32 = DefaultMode; -def RV64 : HwMode<"+64bit">; +def RV64 : HwMode<"+64bit", [IsRV64]>; def FeatureRV32E : SubtargetFeature<"e", "IsRV32E", "true", diff --git a/llvm/test/TableGen/HwModeEncodeDecode.td b/llvm/test/TableGen/HwModeEncodeDecode.td --- a/llvm/test/TableGen/HwModeEncodeDecode.td +++ b/llvm/test/TableGen/HwModeEncodeDecode.td @@ -13,8 +13,11 @@ let DecoderMethod = "DecodeMyi32"; } -def ModeA : HwMode<"+a">; -def ModeB : HwMode<"+b">; +def HasA : Predicate<"Subtarget->hasA()">; +def HasB : Predicate<"Subtarget->hasB()">; + +def ModeA : HwMode<"+a", [HasA]>; +def ModeB : HwMode<"+b", [HasB]>; def fooTypeEncA : InstructionEncoding { diff --git a/llvm/test/TableGen/HwModeSelect.td b/llvm/test/TableGen/HwModeSelect.td --- a/llvm/test/TableGen/HwModeSelect.td +++ b/llvm/test/TableGen/HwModeSelect.td @@ -18,8 +18,11 @@ def TestReg : Register<"testreg">; def TestClass : RegisterClass<"TestTarget", [i32], 32, (add TestReg)>; -def TestMode1 : HwMode<"+feat1">; -def TestMode2 : HwMode<"+feat2">; +def HasFeat1 : Predicate<"Subtarget->hasFeat1()">; +def HasFeat2 : Predicate<"Subtarget->hasFeat2()">; + +def TestMode1 : HwMode<"+feat1", [HasFeat1]>; +def TestMode2 : HwMode<"+feat2", [HasFeat2]>; def BadDef : ValueTypeByHwMode<[TestMode1, TestMode2, DefaultMode], [i8, i16, i32, i64]>; diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -4451,14 +4451,14 @@ // Fill the map entry for this mode. const HwMode &HM = CGH.getMode(M); - AppendPattern(P, M, "(MF->getSubtarget().checkFeatures(\"" + HM.Features + "\"))"); + AppendPattern(P, M, HM.Predicates); // Add negations of the HM's predicates to the default predicate. if (!DefaultCheck.empty()) DefaultCheck += " && "; - DefaultCheck += "(!(MF->getSubtarget().checkFeatures(\""; - DefaultCheck += HM.Features; - DefaultCheck += "\")))"; + DefaultCheck += "!("; + DefaultCheck += HM.Predicates; + DefaultCheck += ")"; } bool HasDefault = Modes.count(DefaultMode); diff --git a/llvm/utils/TableGen/CodeGenHwModes.h b/llvm/utils/TableGen/CodeGenHwModes.h --- a/llvm/utils/TableGen/CodeGenHwModes.h +++ b/llvm/utils/TableGen/CodeGenHwModes.h @@ -31,6 +31,7 @@ HwMode(Record *R); StringRef Name; std::string Features; + std::string Predicates; void dump() const; }; diff --git a/llvm/utils/TableGen/CodeGenHwModes.cpp b/llvm/utils/TableGen/CodeGenHwModes.cpp --- a/llvm/utils/TableGen/CodeGenHwModes.cpp +++ b/llvm/utils/TableGen/CodeGenHwModes.cpp @@ -21,6 +21,19 @@ HwMode::HwMode(Record *R) { Name = R->getName(); Features = std::string(R->getValueAsString("Features")); + + std::vector PredicateRecs = R->getValueAsListOfDefs("Predicates"); + SmallString<128> PredicateCheck; + raw_svector_ostream OS(PredicateCheck); + ListSeparator LS(" && "); + for (Record *Pred : PredicateRecs) { + StringRef CondString = Pred->getValueAsString("CondString"); + if (CondString.empty()) + continue; + OS << LS << '(' << CondString << ')'; + } + + Predicates = std::string(PredicateCheck); } LLVM_DUMP_METHOD