[llvm] 06d7585 - [TableGen][Decoder] Remove special case of single sub-op dag (#156175)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 31 00:07:48 PDT 2025


Author: Sergei Barannikov
Date: 2025-08-31T10:07:44+03:00
New Revision: 06d758537d4c6db8857deeb0de53786767233492

URL: https://github.com/llvm/llvm-project/commit/06d758537d4c6db8857deeb0de53786767233492
DIFF: https://github.com/llvm/llvm-project/commit/06d758537d4c6db8857deeb0de53786767233492.diff

LOG: [TableGen][Decoder] Remove special case of single sub-op dag (#156175)

If a custom operand has MIOperandInfo with >= 2 sub-operands, it is
required that either the operand or its sub-operands have a decoder
method (depending on usage). Require this for single sub-operand
operands as well, since there is no good reason not to.

There are no changes in the generated files.

Added: 
    

Modified: 
    llvm/lib/Target/ARC/ARCInstrFormats.td
    llvm/lib/Target/ARC/ARCInstrInfo.td
    llvm/lib/Target/ARM/ARMInstrInfo.td
    llvm/lib/Target/Lanai/LanaiInstrInfo.td
    llvm/lib/Target/PowerPC/PPCInstrFuture.td
    llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td
    llvm/utils/TableGen/DecoderEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARC/ARCInstrFormats.td b/llvm/lib/Target/ARC/ARCInstrFormats.td
index bd2ed00576177..0560bb1dc9661 100644
--- a/llvm/lib/Target/ARC/ARCInstrFormats.td
+++ b/llvm/lib/Target/ARC/ARCInstrFormats.td
@@ -964,12 +964,10 @@ class F16_OP_U7<bit i, string asmstr> :
 
 // Special types for 
diff erent instruction operands.
 def ccond : Operand<i32> {
-  let MIOperandInfo = (ops i32imm);
   let PrintMethod = "printPredicateOperand";
 }
 
 def brccond : Operand<i32> {
-  let MIOperandInfo = (ops i32imm);
   let PrintMethod = "printBRCCPredicateOperand";
 }
 

diff  --git a/llvm/lib/Target/ARC/ARCInstrInfo.td b/llvm/lib/Target/ARC/ARCInstrInfo.td
index f26b49119caba..8ff5f4a39ca7f 100644
--- a/llvm/lib/Target/ARC/ARCInstrInfo.td
+++ b/llvm/lib/Target/ARC/ARCInstrInfo.td
@@ -18,7 +18,7 @@ include "ARCInstrFormats.td"
 
 // Operand for printing out a condition code.
 let PrintMethod = "printCCOperand" in
-  def CCOp : PredicateOperand<i32, (ops i32imm), (ops)>;
+  def CCOp : PredicateOperand<i32, (ops), (ops)>;
 
 // The "u6" operand of a RRU6-type instruction
 let PrintMethod = "printU6" in {

diff  --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 80a9e3b0b4802..bdb16d7d39266 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -765,7 +765,6 @@ class MVEVectorIndexOperand<int NumLanes> : AsmOperandClass {
 class MVEVectorIndex<int NumLanes> : Operand<i32> {
   let PrintMethod = "printVectorIndex";
   let ParserMatchClass = MVEVectorIndexOperand<NumLanes>;
-  let MIOperandInfo = (ops i32imm);
 }
 
 // shift_imm: An integer that encodes a shift amount and the type of shift
@@ -1181,7 +1180,6 @@ def PostIdxImm8AsmOperand : AsmOperandClass { let Name = "PostIdxImm8"; }
 def postidx_imm8 : MemOperand {
   let PrintMethod = "printPostIdxImm8Operand";
   let ParserMatchClass = PostIdxImm8AsmOperand;
-  let MIOperandInfo = (ops i32imm);
 }
 
 // postidx_imm8s4 := +/- [0,1020]

diff  --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.td b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
index bb142fe26fdff..e0cd79ca22ff4 100644
--- a/llvm/lib/Target/Lanai/LanaiInstrInfo.td
+++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
@@ -212,7 +212,6 @@ def MemImmAsmOperand : AsmOperandClass {
   let ParserMethod  = "parseMemoryOperand";
 }
 def MEMi : Operand<i32> {
-  let MIOperandInfo = (ops i32lo21:$offset);
   let ParserMatchClass = MemImmAsmOperand;
   let PrintMethod   = "printMemImmOperand";
 }

diff  --git a/llvm/lib/Target/PowerPC/PPCInstrFuture.td b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
index 80fac18d5737f..9eef7332f573b 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFuture.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
@@ -54,31 +54,31 @@ let Predicates = [IsISAFuture] in {
 let Predicates = [HasVSX, IsISAFuture] in {
   let mayLoad = 1 in {
     def LXVRL
-        : XX1Form_memOp<31, 525, (outs vsrc:$XT), (ins memr:$RA, g8rc:$RB),
-                        "lxvrl $XT, $RA, $RB", IIC_LdStLoad, []>;
+        : XX1Form_memOp<31, 525, (outs vsrc:$XT), (ins (memr $RA):$addr, g8rc:$RB),
+                        "lxvrl $XT, $addr, $RB", IIC_LdStLoad, []>;
     def LXVRLL
-        : XX1Form_memOp<31, 557, (outs vsrc:$XT), (ins memr:$RA, g8rc:$RB),
-                        "lxvrll $XT, $RA, $RB", IIC_LdStLoad, []>;
+        : XX1Form_memOp<31, 557, (outs vsrc:$XT), (ins (memr $RA):$addr, g8rc:$RB),
+                        "lxvrll $XT, $addr, $RB", IIC_LdStLoad, []>;
     def LXVPRL
-        : XForm_XTp5_XAB5<31, 589, (outs vsrprc:$XTp), (ins memr:$RA, g8rc:$RB),
-                          "lxvprl $XTp, $RA, $RB", IIC_LdStLFD, []>;
+        : XForm_XTp5_XAB5<31, 589, (outs vsrprc:$XTp), (ins (memr $RA):$addr, g8rc:$RB),
+                          "lxvprl $XTp, $addr, $RB", IIC_LdStLFD, []>;
     def LXVPRLL
-        : XForm_XTp5_XAB5<31, 621, (outs vsrprc:$XTp), (ins memr:$RA, g8rc:$RB),
-                          "lxvprll $XTp, $RA, $RB", IIC_LdStLFD, []>;
+        : XForm_XTp5_XAB5<31, 621, (outs vsrprc:$XTp), (ins (memr $RA):$addr, g8rc:$RB),
+                          "lxvprll $XTp, $addr, $RB", IIC_LdStLFD, []>;
   }
 
   let mayStore = 1 in {
     def STXVRL
-        : XX1Form_memOp<31, 653, (outs), (ins vsrc:$XT, memr:$RA, g8rc:$RB),
-                        "stxvrl $XT, $RA, $RB", IIC_LdStLoad, []>;
+        : XX1Form_memOp<31, 653, (outs), (ins vsrc:$XT, (memr $RA):$addr, g8rc:$RB),
+                        "stxvrl $XT, $addr, $RB", IIC_LdStLoad, []>;
     def STXVRLL
-        : XX1Form_memOp<31, 685, (outs), (ins vsrc:$XT, memr:$RA, g8rc:$RB),
-                        "stxvrll $XT, $RA, $RB", IIC_LdStLoad, []>;
+        : XX1Form_memOp<31, 685, (outs), (ins vsrc:$XT, (memr $RA):$addr, g8rc:$RB),
+                        "stxvrll $XT, $addr, $RB", IIC_LdStLoad, []>;
     def STXVPRL : XForm_XTp5_XAB5<31, 717, (outs),
-                                  (ins vsrprc:$XTp, memr:$RA, g8rc:$RB),
-                                  "stxvprl $XTp, $RA, $RB", IIC_LdStLFD, []>;
+                                  (ins vsrprc:$XTp, (memr $RA):$addr, g8rc:$RB),
+                                  "stxvprl $XTp, $addr, $RB", IIC_LdStLFD, []>;
     def STXVPRLL : XForm_XTp5_XAB5<31, 749, (outs),
-                                   (ins vsrprc:$XTp, memr:$RA, g8rc:$RB),
-                                   "stxvprll $XTp, $RA, $RB", IIC_LdStLFD, []>;
+                                   (ins vsrprc:$XTp, (memr $RA):$addr, g8rc:$RB),
+                                   "stxvprll $XTp, $addr, $RB", IIC_LdStLFD, []>;
   }
 }

diff  --git a/llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td b/llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td
index d7263b69dd8f4..ef15b6b9a9001 100644
--- a/llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td
+++ b/llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td
@@ -12,39 +12,56 @@ def Reg : Register<"reg">;
 
 def Regs : RegisterClass<"foo", [i32], 0, (add Reg)>;
 
-def complex_nodec : Operand<i32> {
+def complex_nodec1 : Operand<i32> {
+  let MIOperandInfo = (ops Regs);
+}
+
+def complex_nodec2 : Operand<i32> {
   let MIOperandInfo = (ops Regs, Regs);
 }
 
-def complex_withdec : Operand<i32> {
+def complex_withdec1 : Operand<i32> {
+  let MIOperandInfo = (ops Regs);
+  let DecoderMethod = "DecodeComplex";
+}
+
+def complex_withdec2 : Operand<i32> {
   let MIOperandInfo = (ops Regs, Regs);
   let DecoderMethod = "DecodeComplex";
 }
 
 class ArchInstr : Instruction {
-  let Size = 1;
-  bits<8> Inst;
+  let Size = 2;
+  bits<16> Inst;
 }
 
 // This definition is broken in both directions:
 // 1. Uses a complex operand without a decoder, and without named sub-ops.
 // 2. Uses a complex operand with named sub-ops, but with a decoder as well.
 
-// CHECK: error: DecoderEmitter: operand "r1c" uses MIOperandInfo with multiple ops, but doesn't have a custom decoder!
+// CHECK: error: DecoderEmitter: operand "r1c" has non-empty MIOperandInfo, but doesn't have a custom decoder!
 // CHECK: note: Dumping record for previous error:
-// CHECK: error: DecoderEmitter: operand "r1ab" has type "complex_withdec" with a custom DecoderMethod, but also named sub-operands.
+// CHECK: error: DecoderEmitter: operand "r2b" has non-empty MIOperandInfo, but doesn't have a custom decoder!
+// CHECK: note: Dumping record for previous error:
+// CHECK: error: DecoderEmitter: operand "r1" has type "complex_withdec2" with a custom DecoderMethod, but also named sub-operands.
+// CHECK: error: DecoderEmitter: operand "r2" has type "complex_withdec1" with a custom DecoderMethod, but also named sub-operands.
 def foo1 : ArchInstr {
   bits<2> r1a;
   bits<2> r1b;
   bits<2> r1c;
+  bits<2> r2a;
+  bits<2> r2b;
 
   let Inst{1-0} = r1a;
   let Inst{3-2} = r1b;
   let Inst{5-4} = r1c;
-  let Inst{7-6} = 0b00;
+  let Inst{7-6} = r2a;
+  let Inst{9-8} = r2b;
+  let Inst{11-10} = 0b00;
 
-  let OutOperandList = (outs complex_nodec:$r1c);
-  let InOperandList = (ins (complex_withdec $r1a, $r1b):$r1ab);
+  let OutOperandList = (outs complex_nodec2:$r1c, complex_nodec1:$r2b);
+  let InOperandList = (ins (complex_withdec2 $r1a, $r1b):$r1,
+                           (complex_withdec1 $r2a):$r2);
 }
 
 // This definition has no errors.
@@ -52,12 +69,17 @@ def foo2 : ArchInstr {
   bits<2> r2a;
   bits<2> r2b;
   bits<2> r2c;
+  bits<2> r1a;
+  bits<2> r1b;
 
   let Inst{1-0} = r2a;
   let Inst{3-2} = r2b;
   let Inst{5-4} = r2c;
-  let Inst{7-6} = 0b01;
+  let Inst{7-6} = r1a;
+  let Inst{9-8} = r1b;
+  let Inst{11-10} = 0b01;
 
-  let OutOperandList = (outs complex_withdec:$r2c);
-  let InOperandList = (ins (complex_nodec $r2a, $r2b):$r2ab);
+  let OutOperandList = (outs complex_withdec2:$r2c, complex_withdec1:$r1b);
+  let InOperandList = (ins (complex_nodec2 $r2a, $r2b):$r2,
+                           (complex_nodec1 $r1a):$r1);
 }

diff  --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 98569abfbb1a4..ea295b33ce8c9 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -1990,18 +1990,12 @@ void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) {
     // Otherwise, if we have an operand with sub-operands, but they aren't
     // named...
     if (Op.MIOperandInfo && OpInfo.Decoder.empty()) {
-      // If it's a single sub-operand, and no custom decoder, use the decoder
-      // from the one sub-operand.
-      if (Op.MIOperandInfo->getNumArgs() == 1)
-        OpInfo =
-            getOpInfo(cast<DefInit>(Op.MIOperandInfo->getArg(0))->getDef());
-
-      // If we have multiple sub-ops, there'd better have a custom
-      // decoder. (Otherwise we don't know how to populate them properly...)
-      if (Op.MIOperandInfo->getNumArgs() > 1) {
+      // If we have sub-ops, we'd better have a custom decoder.
+      // (Otherwise we don't know how to populate them properly...)
+      if (Op.MIOperandInfo->getNumArgs()) {
         PrintError(EncodingDef,
                    "DecoderEmitter: operand \"" + Op.Name +
-                       "\" uses MIOperandInfo with multiple ops, but doesn't "
+                       "\" has non-empty MIOperandInfo, but doesn't "
                        "have a custom decoder!");
         debugDumpRecord(*EncodingDef);
         continue;


        


More information about the llvm-commits mailing list