[llvm] [TableGen][Decoder] Remove special case of single sub-op dag (PR #156175)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 30 05:21:49 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-arm
Author: Sergei Barannikov (s-barannikov)
<details>
<summary>Changes</summary>
If a custom operand has MIOperandInfo with >= 2 sub-operands, it is
required that either the operand or its sub-operands have a custom
decoder method (depending on usage). Require this for single sub-operand
operands as well, since there is no good reason not to.
---
Full diff: https://github.com/llvm/llvm-project/pull/156175.diff
8 Files Affected:
- (modified) llvm/lib/Target/ARC/ARCInstrFormats.td (-2)
- (modified) llvm/lib/Target/ARC/ARCInstrInfo.td (+1-1)
- (modified) llvm/lib/Target/ARM/ARMInstrInfo.td (-2)
- (modified) llvm/lib/Target/ARM/ARMInstrNEON.td (-4)
- (modified) llvm/lib/Target/Lanai/LanaiInstrInfo.td (+8-8)
- (modified) llvm/lib/Target/PowerPC/PPCInstrFuture.td (+16-16)
- (modified) llvm/test/TableGen/FixedLenDecoderEmitter/MultiOps.td (+34-12)
- (modified) llvm/utils/TableGen/DecoderEmitter.cpp (+4-9)
``````````diff
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 different 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 4345f7a4a0ebc..a4d7a20305624 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/ARM/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td
index 7485ef569445a..37f0103363b9a 100644
--- a/llvm/lib/Target/ARM/ARMInstrNEON.td
+++ b/llvm/lib/Target/ARM/ARMInstrNEON.td
@@ -95,28 +95,24 @@ def VectorIndex8 : Operand<i32>, ImmLeaf<i32, [{
}]> {
let ParserMatchClass = VectorIndex8Operand;
let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i32imm);
}
def VectorIndex16 : Operand<i32>, ImmLeaf<i32, [{
return ((uint64_t)Imm) < 4;
}]> {
let ParserMatchClass = VectorIndex16Operand;
let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i32imm);
}
def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{
return ((uint64_t)Imm) < 2;
}]> {
let ParserMatchClass = VectorIndex32Operand;
let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i32imm);
}
def VectorIndex64 : Operand<i32>, ImmLeaf<i32, [{
return ((uint64_t)Imm) < 1;
}]> {
let ParserMatchClass = VectorIndex64Operand;
let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i32imm);
}
// Register list of one D register.
diff --git a/llvm/lib/Target/Lanai/LanaiInstrInfo.td b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
index 1d968fa391c2a..5129de047f953 100644
--- a/llvm/lib/Target/Lanai/LanaiInstrInfo.td
+++ b/llvm/lib/Target/Lanai/LanaiInstrInfo.td
@@ -540,15 +540,15 @@ let E = 0 in {
def LDBs_RR : LoadRR<"ld.b", sextloadi8, i32>;
}
-def LDADDR : InstSLS<0x0, (outs GPR:$Rd), (ins MEMi:$src),
+def LDADDR : InstSLS<0x0, (outs GPR:$Rd), (ins (MEMi $offset):$src),
"ld\t$src, $Rd",
[(set (i32 GPR:$Rd), (load ADDRsls:$src))]>,
Sched<[WriteLD]> {
- bits<21> src;
+ bits<21> offset;
let Itinerary = IIC_LD;
- let msb = src{20-16};
- let lsb = src{15-0};
+ let msb = offset{20-16};
+ let lsb = offset{15-0};
let isReMaterializable = 1;
let mayLoad = 1;
}
@@ -639,15 +639,15 @@ let E = 0 in {
def STB_RR : StoreRR<"st.b", truncstorei8, i32>;
}
-def STADDR : InstSLS<0x1, (outs), (ins GPR:$Rd, MEMi:$dst),
+def STADDR : InstSLS<0x1, (outs), (ins GPR:$Rd, (MEMi $offset):$dst),
"st\t$Rd, $dst",
[(store (i32 GPR:$Rd), ADDRsls:$dst)]>,
Sched<[WriteST]> {
- bits<21> dst;
+ bits<21> offset;
let Itinerary = IIC_ST;
- let msb = dst{20-16};
- let lsb = dst{15-0};
+ let msb = offset{20-16};
+ let lsb = offset{15-0};
let mayStore = 1;
}
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 f1db0368d0988..451e831d2dd5f 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -2023,17 +2023,12 @@ void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) {
// Otherwise, if we have an operand with sub-operands, but they aren't
// named...
if (SubOps && OpInfo.Decoder.empty()) {
- // If it's a single sub-operand, and no custom decoder, use the decoder
- // from the one sub-operand.
- if (SubOps->getNumArgs() == 1)
- OpInfo = getOpInfo(cast<DefInit>(SubOps->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 (SubOps->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 (SubOps->getNumArgs()) {
PrintError(EncodingDef,
"DecoderEmitter: operand \"" + OpName +
- "\" uses MIOperandInfo with multiple ops, but doesn't "
+ "\" has non-empty MIOperandInfo, but doesn't "
"have a custom decoder!");
debugDumpRecord(*EncodingDef);
continue;
``````````
</details>
https://github.com/llvm/llvm-project/pull/156175
More information about the llvm-commits
mailing list