[llvm] Feature tablegen hwmode bitset access (PR #88377)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 11 03:29:08 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: None (superZWT123)

<details>
<summary>Changes</summary>



---

Patch is 32.26 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/88377.diff


14 Files Affected:

- (modified) llvm/include/llvm/MC/MCSubtargetInfo.h (+17-1) 
- (modified) llvm/lib/Target/RISCV/CMakeLists.txt (+1-1) 
- (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+6) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZcmop.td (+38) 
- (modified) llvm/lib/Target/RISCV/RISCVProcessors.td (+1-1) 
- (modified) llvm/lib/Target/RISCV/RISCVSubtarget.cpp (+2-2) 
- (modified) llvm/lib/Target/RISCV/RISCVSubtarget.h (+1) 
- (modified) llvm/test/MC/RISCV/rvzcmop-valid.s (+11-3) 
- (added) llvm/test/TableGen/HwModeBitSet.td (+162) 
- (modified) llvm/test/TableGen/HwModeEncodeDecode3.td (+60-18) 
- (modified) llvm/utils/TableGen/CodeEmitterGen.cpp (+70-23) 
- (modified) llvm/utils/TableGen/Common/CodeGenHwModes.cpp (+2) 
- (modified) llvm/utils/TableGen/SubtargetEmitter.cpp (+69-8) 


``````````diff
diff --git a/llvm/include/llvm/MC/MCSubtargetInfo.h b/llvm/include/llvm/MC/MCSubtargetInfo.h
index f172a799aa3331..70b14665ea9ebd 100644
--- a/llvm/include/llvm/MC/MCSubtargetInfo.h
+++ b/llvm/include/llvm/MC/MCSubtargetInfo.h
@@ -240,7 +240,23 @@ class MCSubtargetInfo {
     return ProcFeatures;
   }
 
-  virtual unsigned getHwMode() const { return 0; }
+  /// HwMode ID will be stored as bits, allowing users to pull the specific
+  /// HwMode ID (like RegInfo HwMode ID) from the bits as needed. This enables
+  /// users to control multiple features with one hwmode (as previously) or use
+  /// different hwmodes to control different features.
+  enum HwModeType {
+    HwMode_Default,   // Return the smallest HwMode ID of current subtarget.
+    HwMode_ValueType, // Return the HwMode ID that controls the ValueType.
+    HwMode_RegInfo,   // Return the HwMode ID that controls the RegSizeInfo and
+                      // SubRegRange.
+    HwMode_EncodingInfo // Return the HwMode ID that controls the EncodingInfo.
+  };
+
+  virtual unsigned getHwModeSet() const { return 0; }
+
+  virtual unsigned getHwMode(enum HwModeType type = HwMode_Default) const {
+    return 0;
+  }
 
   /// Return the cache size in bytes for the given level of cache.
   /// Level is zero-based, so a value of zero means the first level of
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 8715403f3839a6..0d5205f5351ecd 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -7,7 +7,7 @@ tablegen(LLVM RISCVGenAsmWriter.inc -gen-asm-writer)
 tablegen(LLVM RISCVGenCompressInstEmitter.inc -gen-compress-inst-emitter)
 tablegen(LLVM RISCVGenMacroFusion.inc -gen-macro-fusion-pred)
 tablegen(LLVM RISCVGenDAGISel.inc -gen-dag-isel)
-tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler)
+tablegen(LLVM RISCVGenDisassemblerTables.inc -gen-disassembler --suppress-per-hwmode-duplicates=O1)
 tablegen(LLVM RISCVGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM RISCVGenMCCodeEmitter.inc -gen-emitter)
 tablegen(LLVM RISCVGenMCPseudoLowering.inc -gen-pseudo-lowering)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 6aadabdf1bc61a..7298526bb36f93 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -640,6 +640,8 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
   TRY_TO_DECODE_FEATURE(
       RISCV::FeatureStdExtZcmp, DecoderTableRVZcmp16,
       "Zcmp table (16-bit Push/Pop & Double Move Instructions)");
+  TRY_TO_DECODE_AND_ADD_SP(STI.hasFeature(RISCV::FeatureEncodingTmp), DecoderTable_EncodingTmp16,
+                           "For HwMode check");
   TRY_TO_DECODE_AND_ADD_SP(true, DecoderTable16,
                            "RISCV_C table (16-bit Instruction)");
 
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 794455aa730400..072649f4610f8d 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1150,15 +1150,21 @@ def Feature32Bit
     : SubtargetFeature<"32bit", "IsRV32", "true", "Implements RV32">;
 def Feature64Bit
     : SubtargetFeature<"64bit", "IsRV64", "true", "Implements RV64">;
+def FeatureEncodingTmp
+    : SubtargetFeature<"TmpE", "IsTmpE", "true", "Implements encoding tmp">;
 def IsRV64 : Predicate<"Subtarget->is64Bit()">,
              AssemblerPredicate<(all_of Feature64Bit),
                                 "RV64I Base Instruction Set">;
 def IsRV32 : Predicate<"!Subtarget->is64Bit()">,
              AssemblerPredicate<(all_of (not Feature64Bit)),
                                 "RV32I Base Instruction Set">;
+def IsTmpE : Predicate<"Subtarget->isETmp()">,
+             AssemblerPredicate<(all_of FeatureEncodingTmp),
+                                "RV32I Encoding tmp">;
 
 defvar RV32 = DefaultMode;
 def RV64           : HwMode<"+64bit", [IsRV64]>;
+def EncodingTmp    : HwMode<"+TmpE", [IsRV64]>;
 
 def FeatureRVE
     : SubtargetFeature<"e", "IsRVE", "true",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZcmop.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZcmop.td
index dd13a07d606d04..23a0a6fb31f00e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZcmop.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZcmop.td
@@ -11,6 +11,38 @@
 //
 //===----------------------------------------------------------------------===//
 
+multiclass tmpEclass<bits<3> imm3> {
+def NAME#commonE : InstructionEncoding {
+  field bits<16> Inst;
+  field bits<16> SoftFail = 0;
+  let Size = 2;
+  bit mayLoad      = 0;
+  bit mayStore     = 0;
+  bit hasSideEffects = 0;
+  let Inst{1-0} = 0b01;
+  let Inst{6-2} = 0;
+  let Inst{7} = 0b1; //differ
+  let Inst{10-8} = imm3;
+  let Inst{12-11} = 0;
+  let Inst{15-13} = 0b011;
+}
+
+def NAME#specialE : InstructionEncoding {
+  field bits<16> Inst;
+  field bits<16> SoftFail = 0;
+  let Size = 2;
+  bit mayLoad      = 0;
+  bit mayStore     = 0;
+  bit hasSideEffects = 0;
+  let Inst{1-0} = 0b01;
+  let Inst{6-2} = 0;
+  let Inst{7} = 0b0; //differ
+  let Inst{10-8} = imm3;
+  let Inst{12-11} = 0;
+  let Inst{15-13} = 0b011;
+}
+}
+
 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
 class CMOPInst<bits<3> imm3, string opcodestr>
     : RVInst16CI<0b011, 0b01, (outs), (ins), opcodestr, ""> {
@@ -18,15 +50,21 @@ class CMOPInst<bits<3> imm3, string opcodestr>
   let Inst{7} = 1;
   let Inst{10-8} = imm3;
   let Inst{12-11} = 0;
+  let EncodingInfos = EncodingByHwMode<[DefaultMode, EncodingTmp],
+                                       [!cast<InstructionEncoding>(NAME#commonE),
+                                        !cast<InstructionEncoding>(NAME#specialE)]>;
 }
 
 // CMOP1, CMOP5 is used by Zicfiss.
 let Predicates = [HasStdExtZcmop, NoHasStdExtZicfiss] in {
+  defm CMOP1 : tmpEclass<0>;
+  defm CMOP5 : tmpEclass<2>;
   def CMOP1 : CMOPInst<0, "cmop.1">, Sched<[]>;
   def CMOP5 : CMOPInst<2, "cmop.5">, Sched<[]>;
 }
 
 foreach n = [3, 7, 9, 11, 13, 15] in {
   let Predicates = [HasStdExtZcmop] in
+  defm CMOP # n : tmpEclass<!srl(n, 1)>;
   def CMOP # n : CMOPInst<!srl(n, 1), "cmop." # n>, Sched<[]>;
 }
diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td
index fd6d6078ec238b..cbb199ffb76585 100644
--- a/llvm/lib/Target/RISCV/RISCVProcessors.td
+++ b/llvm/lib/Target/RISCV/RISCVProcessors.td
@@ -60,7 +60,7 @@ def GENERIC_RV32 : RISCVProcessorModel<"generic-rv32",
                    GenericTuneInfo;
 def GENERIC_RV64 : RISCVProcessorModel<"generic-rv64",
                                        NoSchedModel,
-                                       [Feature64Bit]>,
+                                       [Feature64Bit, FeatureEncodingTmp]>,
                    GenericTuneInfo;
 // Support generic for compatibility with other targets. The triple will be used
 // to change to the appropriate rv32/rv64 version.
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index d3236bb07d56d5..b4156df907ee97 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -100,11 +100,11 @@ RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
       RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax),
       FrameLowering(
           initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
-      InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
+      InstrInfo(*this), RegInfo(getHwMode(HwMode_RegInfo)), TLInfo(TM, *this) {
   CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
   Legalizer.reset(new RISCVLegalizerInfo(*this));
 
-  auto *RBI = new RISCVRegisterBankInfo(getHwMode());
+  auto *RBI = new RISCVRegisterBankInfo(getHwMode(HwMode_RegInfo));
   RegBankInfo.reset(RBI);
   InstSelector.reset(createRISCVInstructionSelector(
       *static_cast<const RISCVTargetMachine *>(&TM), *this, *RBI));
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 85f8f5f654fe7c..28e9ff4c07f436 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -165,6 +165,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   }
 
   bool is64Bit() const { return IsRV64; }
+  bool isETmp() const { return IsTmpE; }
   MVT getXLenVT() const {
     return is64Bit() ? MVT::i64 : MVT::i32;
   }
diff --git a/llvm/test/MC/RISCV/rvzcmop-valid.s b/llvm/test/MC/RISCV/rvzcmop-valid.s
index c6bb4a15808258..4e0ce25f73efa3 100644
--- a/llvm/test/MC/RISCV/rvzcmop-valid.s
+++ b/llvm/test/MC/RISCV/rvzcmop-valid.s
@@ -1,42 +1,50 @@
 # RUN: llvm-mc %s -triple=riscv32 -mattr=+zcmop -show-encoding \
 # RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
 # RUN: llvm-mc %s -triple=riscv64 -mattr=+zcmop -show-encoding \
-# RUN:     | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
+# RUN:     | FileCheck -check-prefixes=CHECK-ASM-64,CHECK-ASM-AND-OBJ %s
 # RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zcmop < %s \
-# RUN:     | llvm-objdump --mattr=+zcmop -d -r - \
+# RUN:     | llvm-objdump --triple=riscv32 --mattr=+zcmop -d -r - \
 # RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
 # RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zcmop < %s \
-# RUN:     | llvm-objdump --mattr=+zcmop -d -r - \
+# RUN:     | llvm-objdump --triple=riscv64 --mattr=+zcmop -d -r - \
 # RUN:     | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
 
 # CHECK-ASM-AND-OBJ: cmop.1
 # CHECK-ASM: encoding: [0x81,0x60]
+# CHECK-ASM-64: encoding: [0x01,0x60]
 cmop.1
 
 # CHECK-ASM-AND-OBJ: cmop.3
 # CHECK-ASM: encoding: [0x81,0x61]
+# CHECK-ASM-64: encoding: [0x01,0x61]
 cmop.3
 
 # CHECK-ASM-AND-OBJ: cmop.5
 # CHECK-ASM: encoding: [0x81,0x62]
+# CHECK-ASM-64: encoding: [0x01,0x62]
 cmop.5
 
 # CHECK-ASM-AND-OBJ: cmop.7
 # CHECK-ASM: encoding: [0x81,0x63]
+# CHECK-ASM-64: encoding: [0x01,0x63]
 cmop.7
 
 # CHECK-ASM-AND-OBJ: cmop.9
 # CHECK-ASM: encoding: [0x81,0x64]
+# CHECK-ASM-64: encoding: [0x01,0x64]
 cmop.9
 
 # CHECK-ASM-AND-OBJ: cmop.11
 # CHECK-ASM: encoding: [0x81,0x65]
+# CHECK-ASM-64: encoding: [0x01,0x65]
 cmop.11
 
 # CHECK-ASM-AND-OBJ: cmop.13
 # CHECK-ASM: encoding: [0x81,0x66]
+# CHECK-ASM-64: encoding: [0x01,0x66]
 cmop.13
 
 # CHECK-ASM-AND-OBJ: cmop.15
 # CHECK-ASM: encoding: [0x81,0x67]
+# CHECK-ASM-64: encoding: [0x01,0x67]
 cmop.15
diff --git a/llvm/test/TableGen/HwModeBitSet.td b/llvm/test/TableGen/HwModeBitSet.td
new file mode 100644
index 00000000000000..c642906f6f4a88
--- /dev/null
+++ b/llvm/test/TableGen/HwModeBitSet.td
@@ -0,0 +1,162 @@
+// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-REG
+// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SUBTARGET
+
+include "llvm/Target/Target.td"
+
+def TestTargetInstrInfo : InstrInfo;
+
+def TestTarget : Target {
+  let InstructionSet = TestTargetInstrInfo;
+}
+
+def TestMode : HwMode<"+feat", []>;
+def TestMode1 : HwMode<"+feat1", []>;
+def TestMode2 : HwMode<"+feat2", []>;
+
+class MyReg<string n>
+  : Register<n> {
+  let Namespace = "Test";
+}
+
+class MyClass<int size, list<ValueType> types, dag registers>
+  : RegisterClass<"Test", types, size, registers> {
+  let Size = size;
+}
+
+def X0 : MyReg<"x0">;
+def X1 : MyReg<"x1">;
+def X2 : MyReg<"x2">;
+def X3 : MyReg<"x3">;
+def X4 : MyReg<"x4">;
+def X5 : MyReg<"x5">;
+def X6 : MyReg<"x6">;
+def X7 : MyReg<"x7">;
+def X8 : MyReg<"x8">;
+def X9 : MyReg<"x9">;
+def X10 : MyReg<"x10">;
+def X11 : MyReg<"x11">;
+def X12 : MyReg<"x12">;
+def X13 : MyReg<"x13">;
+def X14 : MyReg<"x14">;
+def X15 : MyReg<"x15">;
+
+def ValueModeVT : ValueTypeByHwMode<[DefaultMode, TestMode, TestMode1],
+                                    [i32,  i64, f32]>;
+
+let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
+                               [RegInfo<32,32,32>, RegInfo<64,64,64>]> in
+def XRegs : MyClass<32, [ValueModeVT], (sequence "X%u", 0, 15)>;
+
+def sub_even : SubRegIndex<32> {
+  let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
+                                         [SubRegRange<32>, SubRegRange<64>]>;
+}
+def sub_odd  : SubRegIndex<32, 32> {
+  let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode],
+                                         [SubRegRange<32, 32>, SubRegRange<64, 64>]>;
+}
+
+def XPairs : RegisterTuples<[sub_even, sub_odd],
+                            [(decimate (rotl XRegs, 0), 2),
+                             (decimate (rotl XRegs, 1), 2)]>;
+
+let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode],
+                               [RegInfo<64,64,32>, RegInfo<128,128,64>]> in
+def XPairsClass : MyClass<64, [untyped], (add XPairs)>;
+
+// Modes who are not controlling Register related features will be manipulated
+// the same as DefaultMode.
+// CHECK-REG-LABEL: RegisterClass XRegs:
+// CHECK-REG: SpillSize: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+// CHECK-REG: SpillAlignment: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+// CHECK-REG: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15
+
+// CHECK-REG-LABEL: RegisterClass XPairsClass:
+// CHECK-REG: SpillSize: { Default:64 TestMode:128 TestMode1:64 TestMode2:64 }
+// CHECK-REG: SpillAlignment: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+// CHECK-REG: CoveredBySubRegs: 1
+// CHECK-REG: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15
+
+// CHECK-REG-LABEL: SubRegIndex sub_even:
+// CHECK-REG: Offset: { Default:0 TestMode:0 TestMode1:0 TestMode2:0 }
+// CHECK-REG: Size: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+// CHECK-REG-LABEL: SubRegIndex sub_odd:
+// CHECK-REG: Offset: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+// CHECK-REG: Size: { Default:32 TestMode:64 TestMode1:32 TestMode2:32 }
+
+//============================================================================//
+//--------------------- Encoding/Decoding parts ------------------------------//
+//============================================================================//
+def fooTypeEncDefault : InstructionEncoding {
+  let Size = 8;
+  field bits<64> SoftFail = 0;
+  bits<64> Inst;
+  bits<8> factor;
+  let Inst{7...0} = factor;
+  let Inst{3...2} = 0b10;
+  let Inst{1...0} = 0b00;
+}
+
+def fooTypeEncA : InstructionEncoding {
+  let Size = 4;
+  field bits<32> SoftFail = 0;
+  bits<32> Inst;
+  bits<8> factor;
+  let Inst{7...0} = factor;
+  let Inst{3...2} = 0b11;
+  let Inst{1...0} = 0b00;
+}
+
+
+def foo : Instruction {
+  let OutOperandList = (outs);
+  let InOperandList = (ins i32imm:$factor);
+  let EncodingInfos = EncodingByHwMode<
+    [TestMode2, DefaultMode], [fooTypeEncA, fooTypeEncDefault]
+  >;
+  let AsmString = "foo  $factor";
+}
+
+// CHECK-SUBTARGET-LABEL: unsigned TestTargetGenSubtargetInfo::getHwModeSet() const {
+// CHECK-SUBTARGET:         unsigned Modes = 0;
+// CHECK-SUBTARGET:         if (checkFeatures("+feat")) Modes |= (1 << 0);
+// CHECK-SUBTARGET:         if (checkFeatures("+feat1")) Modes |= (1 << 1);
+// CHECK-SUBTARGET:         if (checkFeatures("+feat2")) Modes |= (1 << 2);
+// CHECK-SUBTARGET:         return Modes;
+// CHECK-SUBTARGET:       }
+// CHECK-SUBTARGET-LABEL: unsigned TestTargetGenSubtargetInfo::getHwMode(enum HwModeType type) const {
+// CHECK-SUBTARGET:         unsigned Modes = getHwModeSet();
+// CHECK-SUBTARGET:         if(!Modes)
+// CHECK-SUBTARGET:           return Modes;
+// CHECK-SUBTARGET:         switch (type) {
+// CHECK-SUBTARGET:         case HwMode_Default:
+// CHECK-SUBTARGET:           return llvm::countr_zero(Modes) + 1;
+// CHECK-SUBTARGET:           break;
+// CHECK-SUBTARGET:         case HwMode_ValueType: {
+// CHECK-SUBTARGET:           Modes &= 3;
+// CHECK-SUBTARGET:           if (!Modes)
+// CHECK-SUBTARGET:             return Modes;
+// CHECK-SUBTARGET:           if (!llvm::has_single_bit<unsigned>(Modes))
+// CHECK-SUBTARGET:             llvm_unreachable("Two or more HwModes for ValueType were found!");
+// CHECK-SUBTARGET:           return llvm::countr_zero(Modes) + 1;
+// CHECK-SUBTARGET:         }
+// CHECK-SUBTARGET:         case HwMode_RegInfo: {
+// CHECK-SUBTARGET:           Modes &= 1;
+// CHECK-SUBTARGET:           if (!Modes)
+// CHECK-SUBTARGET:             return Modes;
+// CHECK-SUBTARGET:           if (!llvm::has_single_bit<unsigned>(Modes))
+// CHECK-SUBTARGET:             llvm_unreachable("Two or more HwModes for RegInfo were found!");
+// CHECK-SUBTARGET:           return llvm::countr_zero(Modes) + 1;
+// CHECK-SUBTARGET:         }
+// CHECK-SUBTARGET:         case HwMode_EncodingInfo: {
+// CHECK-SUBTARGET:           Modes &= 4;
+// CHECK-SUBTARGET:           if (!Modes)
+// CHECK-SUBTARGET:             return Modes;
+// CHECK-SUBTARGET:           if (!llvm::has_single_bit<unsigned>(Modes))
+// CHECK-SUBTARGET:             llvm_unreachable("Two or more HwModes for Encoding were found!");
+// CHECK-SUBTARGET:           return llvm::countr_zero(Modes) + 1;
+// CHECK-SUBTARGET:         }
+// CHECK-SUBTARGET:         }
+// CHECK-SUBTARGET:         return 0; // should not get here
+// CHECK-SUBTARGET:       }
+
diff --git a/llvm/test/TableGen/HwModeEncodeDecode3.td b/llvm/test/TableGen/HwModeEncodeDecode3.td
index 8e0266b2c55af9..bc65d4a1d40d3b 100644
--- a/llvm/test/TableGen/HwModeEncodeDecode3.td
+++ b/llvm/test/TableGen/HwModeEncodeDecode3.td
@@ -160,15 +160,22 @@ def unrelated: Instruction {
 // DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncA:baz
 // DECODER-SUPPRESS-O2-NOT: Opcode: bar
 
-// ENCODER-LABEL:   static const uint64_t InstBits_DefaultMode[] = {
+// For 'bar' and 'unrelated', we didn't assign any hwmodes for them,
+// they should keep the same in the following three tables.
+// For 'foo' we assigned three hwmodes(includes 'DefaultMode')
+// it's encodings should be different in the following three tables.
+// For 'baz' we only assigned ModeB for it, to avoid empty encoding
+// we assigned the encoding of ModeB to ModeA and DefaultMode(Even though
+// they will not be used).
+// ENCODER-LABEL:   static const uint64_t InstBits[] = {
 // ENCODER:         UINT64_C(2),        // bar
-// ENCODER:         UINT64_C(0),        // baz
+// ENCODER:         UINT64_C(12),       // baz
 // ENCODER:         UINT64_C(8),        // foo
 // ENCODER:         UINT64_C(2),        // unrelated
 
 // ENCODER-LABEL:   static const uint64_t InstBits_ModeA[] = {
 // ENCODER:         UINT64_C(2),        // bar
-// ENCODER:         UINT64_C(0),        // baz
+// ENCODER:         UINT64_C(12),       // baz
 // ENCODER:         UINT64_C(12),       // foo
 // ENCODER:         UINT64_C(2),        // unrelated
 
@@ -178,18 +185,53 @@ def unrelated: Instruction {
 // ENCODER:         UINT64_C(3),        // foo
 // ENCODER:         UINT64_C(2),        // unrelated
 
-// ENCODER:  unsigned HwMode = STI.getHwMode();
-// ENCODER:  switch (HwMode) {
-// ENCODER:  default: llvm_unreachable("Unknown hardware mode!"); break;
-// ENCODER:  case 0: InstBits = InstBits_DefaultMode; break;
-// ENCODER:  case 1: InstBits = InstBits_ModeA; break;
-// ENCODER:  case 2: InstBits = InstBits_ModeB; break;
-// ENCODER:  };
-
-// ENCODER:     case ::foo: {
-// ENCODER:      switch (HwMode) {
-// ENCODER:      default: llvm_unreachable("Unhandled HwMode");
-// ENCODER:      case 0: {
-// ENCODER:      case 1: {
-// ENCODER:      case 2: {
-
+// ENCODER-LABEL: case ::bar:
+// ENCODER-LABEL: case ::unrelated:
+// ENCODER-NOT: getHwMode
+// ENCODER-LABEL: case ::baz: {
+// ENCODER: unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMode_EncodingInfo);
+// ENCODER: HwMode &= 2;
+// ENCODER: switch (HwMode) {
+// ENCODER: default: llvm_unreachable("Unknown hardware mode!"); break;
+// ENCODER: case 2: InstBitsByHw = InstBits_ModeB; break;
+// ENCODER: };
+// ENCODER: Value = InstBitsByHw[opcode];
+// ENCODER: switch (HwMode) {
+// ENCODER: default: llvm_unreachable("Unhandled HwMode");
+// ENCODER: case 2: {
+// ENCODER: op = getMachineOpValue(MI, MI.getOperand(0), Fixups, STI);
+// ENCODER: op &= UINT64_C(240);
+// ENCODER: Value |= op;
+// ENCODER: break;
+// ENCODER: }
+// ENCODER-LABEL: case ::foo: {
+// ENCODER: unsigned HwMode = STI.getHwMode(MCSubtargetInfo::HwMod...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/88377


More information about the llvm-commits mailing list