Skip to content

Conversation

@s-barannikov
Copy link
Contributor

@s-barannikov s-barannikov commented Sep 2, 2025

Most predicable Thumb instructions do not encode the predicate operand, but rather take it from an enclosing IT block.
Add bits<0> p to the encoding of these instructions to make the predicate operand decodable by the generated code.

The previous approach was to analyze an instruction after it has been decoded and add missing predicate operand if necessary. The post-decoding pass is still required to check predicate applicability and advance IT block state, but it no longer modifies a decoded instruction.

Some of the custom decoder methods have become redundant and can be removed in the future, delegating the decoding task to TableGen-erated decoder.

Copy link
Contributor Author

s-barannikov commented Sep 2, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 8b97be9 to 8e6e8dd Compare September 2, 2025 21:49
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-6-aarch64-rest branch from 46fc93b to ee67c36 Compare September 3, 2025 19:51
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 8e6e8dd to a4b0131 Compare September 3, 2025 19:51
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-6-aarch64-rest branch from ee67c36 to 9709854 Compare September 3, 2025 20:17
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from a4b0131 to 611d87c Compare September 3, 2025 20:17
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-6-aarch64-rest branch from 9709854 to aa97c88 Compare September 4, 2025 13:37
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 611d87c to 6029b96 Compare September 4, 2025 13:37
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-6-aarch64-rest branch from aa97c88 to f31a7b8 Compare September 4, 2025 14:14
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch 2 times, most recently from 408cfbc to b06dce1 Compare September 4, 2025 14:59
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-6-aarch64-rest branch from f31a7b8 to 5f3f11d Compare September 4, 2025 14:59
@s-barannikov s-barannikov changed the base branch from users/s.barannikov/decoder-operands-6-aarch64-rest to main September 4, 2025 15:36
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from b06dce1 to b45bd86 Compare September 4, 2025 15:36
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from b45bd86 to 204f13a Compare September 9, 2025 16:18
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 204f13a to 67bdfe0 Compare September 19, 2025 17:01
s-barannikov added a commit that referenced this pull request Sep 19, 2025
This change adds basic `MCInst` verification (checks the number of
operands) and fixes detected bugs.

* `RFE*` instructions have only one operand, but `DecodeRFEInstruction`
added two.
* `DecodeMVEModImmInstruction` and `DecodeMVEVCMP` added a `vpred`
operand, but this is what `AddThumbPredicate` normally does. This
resulted in an extra `vpred` operand.
* `DecodeMVEVADCInstruction` added an extra immediate operand.
* `getARMInstruction` added a `pred` operand to instructions that don't
have one (via `DecodePredicateOperand`).
* `AddThumb1SBit` appended an extra register operand to instructions
that don't modify CPSR (such as `tBL`).
* Instructions in `NEONDup` namespace have `pred` operand that the
generated code successfully decodes. The operand was added once again by
`getARMInstruction`/`getThumbInstruction` via `AddThumbPredicate`.

Functional changes extracted from #156540.
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch 2 times, most recently from ea21c47 to 23f77e4 Compare September 21, 2025 05:08
@github-actions
Copy link

github-actions bot commented Sep 21, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch 2 times, most recently from 0aa1f38 to 9853907 Compare September 21, 2025 19:54
s-barannikov added a commit that referenced this pull request Sep 23, 2025
The operand can be decoded automatically, without the need for
post-decoding instruction modification.
Part of #156540.
s-barannikov added a commit that referenced this pull request Oct 4, 2025
Make the operands auto-decodable by adding `bits<0>` fields to
instructions.

Now we try to decode a vpred_n/vpred_r operand only if the instruction
being decoded has one.
We still need post-decoding pass to check/advance VPT state.

Part of #156540.
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch 2 times, most recently from c32bc56 to 91d92fe Compare October 4, 2025 21:23
aokblast pushed a commit to aokblast/llvm-project that referenced this pull request Oct 6, 2025
Make the operands auto-decodable by adding `bits<0>` fields to
instructions.

Now we try to decode a vpred_n/vpred_r operand only if the instruction
being decoded has one.
We still need post-decoding pass to check/advance VPT state.

Part of llvm#156540.
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 91d92fe to 9114707 Compare November 10, 2025 09:43
@s-barannikov s-barannikov changed the title [ARM] Remove most post-decoding instruction adjustments [ARM] Auto-decode pred operands Nov 10, 2025
@s-barannikov s-barannikov changed the title [ARM] Auto-decode pred operands [ARM] Auto-decode pred operands of Thumb instructions Nov 10, 2025
@s-barannikov s-barannikov force-pushed the users/s.barannikov/decoder-operands-7-arm branch from 9114707 to bb5577b Compare November 10, 2025 09:58
ARMDisassembler::checkThumbPredicate(MCInst &MI) const {
MCDisassembler::DecodeStatus S = Success;

const FeatureBitset &FeatureBits = getSubtargetInfo().getFeatureBits();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The switch a little down below could probably be moved to DecodePredicateOperand. Not sure if that would be a better place for it. Let me know what you think.

@s-barannikov s-barannikov marked this pull request as ready for review November 10, 2025 10:04
@llvmbot llvmbot added backend:ARM bazel "Peripheral" support tier build system: utils/bazel labels Nov 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 10, 2025

@llvm/pr-subscribers-backend-arm

Author: Sergei Barannikov (s-barannikov)

Changes

Most predicable Thumb instructions do not encode the predicate operand, but rather take it from an enclosing IT block.
Add bits&lt;0&gt; p to the encoding of these instructions to make the predicate operand decodable by the generated code.

The previous approach was to analyze an instruction after it has been decoded and add missing predicate operand if necessary. The post-decoding pass is still required to check predicate applicability and advance IT block state, but it no longer modifies a decoded instruction.

Some of the custom decoder methods have become redundant and can be removed in the future, delegating the decoding task to TableGen-erated decoder.


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

8 Files Affected:

  • (modified) llvm/lib/Target/ARM/ARMInstrCDE.td (+3)
  • (modified) llvm/lib/Target/ARM/ARMInstrFormats.td (+6)
  • (modified) llvm/lib/Target/ARM/ARMInstrThumb.td (+10)
  • (modified) llvm/lib/Target/ARM/ARMInstrThumb2.td (+20-3)
  • (modified) llvm/lib/Target/ARM/CMakeLists.txt (+1-2)
  • (modified) llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (+125-61)
  • (modified) llvm/utils/gn/secondary/llvm/lib/Target/ARM/Disassembler/BUILD.gn (+1-4)
  • (modified) utils/bazel/llvm-project-overlay/llvm/BUILD.bazel (+1-4)
diff --git a/llvm/lib/Target/ARM/ARMInstrCDE.td b/llvm/lib/Target/ARM/ARMInstrCDE.td
index f4326de5ed667..5d4e3acf5b581 100644
--- a/llvm/lib/Target/ARM/ARMInstrCDE.td
+++ b/llvm/lib/Target/ARM/ARMInstrCDE.td
@@ -115,6 +115,7 @@ class CDE_CX1_Instr<string iname, CX_Params params>
                   !con(params.Iops1, (ins imm_13b:$imm), params.PredOp),
                   !strconcat(iname, params.PAsm, "\t$coproc, $Rd, $imm"),
                   params.Cstr> {
+  bits<0> p;
   bits<13> imm;
   bits<4> Rd;
 
@@ -131,6 +132,7 @@ class CDE_CX2_Instr<string iname, CX_Params params>
                   !con(params.Iops2, (ins imm_9b:$imm), params.PredOp),
                   !strconcat(iname, params.PAsm, "\t$coproc, $Rd, $Rn, $imm"),
                   params.Cstr> {
+  bits<0> p;
   bits<9> imm;
   bits<4> Rd;
   bits<4> Rn;
@@ -149,6 +151,7 @@ class CDE_CX3_Instr<string iname, CX_Params params>
                   !con(params.Iops3, (ins imm_6b:$imm), params.PredOp),
                   !strconcat(iname, params.PAsm, "\t$coproc, $Rd, $Rn, $Rm, $imm"),
                   params.Cstr> {
+  bits<0> p;
   bits<6> imm;
   bits<4> Rd;
   bits<4> Rn;
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index 1ad2485dce17f..1cd1a9a0f7331 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -1220,6 +1220,7 @@ class Thumb1sI<dag oops, dag iops, AddrMode am, int sz,
                string opc, string asm, string cstr, list<dag> pattern>
   : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
   bits<0> s;
+  bits<0> p;
   let OutOperandList = !con(oops, (outs s_cc_out:$s));
   let InOperandList = !con(iops, (ins pred:$p));
   let AsmString = !strconcat(opc, "${s}${p}", asm);
@@ -1244,6 +1245,7 @@ class Thumb1pI<dag oops, dag iops, AddrMode am, int sz,
                InstrItinClass itin,
                string opc, string asm, string cstr, list<dag> pattern>
   : InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+  bits<0> p;
   let OutOperandList = oops;
   let InOperandList = !con(iops, (ins pred:$p));
   let AsmString = !strconcat(opc, "${p}", asm);
@@ -1343,6 +1345,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, int sz,
               InstrItinClass itin,
               string opc, string asm, string cstr, list<dag> pattern>
   : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+  bits<0> p;
   let OutOperandList = oops;
   let InOperandList = !con(iops, (ins pred:$p));
   let AsmString = !strconcat(opc, "${p}", asm);
@@ -1361,6 +1364,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, int sz,
                InstrItinClass itin,
                string opc, string asm, string cstr, list<dag> pattern>
   : InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+  bits<0> p;
   bits<1> s; // condition-code set flag ('1' if the insn should set the flags)
   let Inst{20} = s;
 
@@ -2221,6 +2225,7 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
             InstrItinClass itin, string opc, string dt, string asm, string cstr,
             list<dag> pattern>
   : InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
+  bits<0> p;
   let OutOperandList = oops;
   let InOperandList = !con(iops, (ins pred:$p));
   let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
@@ -2234,6 +2239,7 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
              InstrItinClass itin, string opc, string asm, string cstr,
              list<dag> pattern>
   : InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
+  bits<0> p;
   let OutOperandList = oops;
   let InOperandList = !con(iops, (ins pred:$p));
   let AsmString = !strconcat(opc, "${p}", "\t", asm);
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index 0c5ea3e0fa8d5..bc1b34c691e39 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -483,6 +483,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
   def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>,
             T1Special<{1,1,0,?}>, Sched<[WriteBr]> {
     // A6.2.3 & A8.6.25
+    bits<0> p;
     bits<4> Rm;
     let Inst{6-3} = Rm;
     let Inst{2-0} = 0b000;
@@ -491,6 +492,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
   def tBXNS : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bxns${p}\t$Rm", []>,
               Requires<[IsThumb, Has8MSecExt]>,
               T1Special<{1,1,0,?}>, Sched<[WriteBr]> {
+    bits<0> p;
     bits<4> Rm;
     let Inst{6-3} = Rm;
     let Inst{2-0} = 0b100;
@@ -523,6 +525,7 @@ let isCall = 1,
                   "bl${p}\t$func",
                   [(ARMcall tglobaladdr:$func)]>,
              Requires<[IsThumb]>, Sched<[WriteBrL]> {
+    bits<0> p;
     bits<24> func;
     let Inst{26} = func{23};
     let Inst{25-16} = func{20-11};
@@ -536,6 +539,7 @@ let isCall = 1,
                  (outs), (ins pred:$p, thumb_blx_target:$func), IIC_Br,
                    "blx${p}\t$func", []>,
               Requires<[IsThumb, HasV5T, IsNotMClass]>, Sched<[WriteBrL]> {
+    bits<0> p;
     bits<24> func;
     let Inst{26} = func{23};
     let Inst{25-16} = func{20-11};
@@ -550,6 +554,7 @@ let isCall = 1,
                   "blx${p}\t$func", []>,
               Requires<[IsThumb, HasV5T]>,
               T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24;
+    bits<0> p;
     bits<4> func;
     let Inst{6-3} = func;
     let Inst{2-0} = 0b000;
@@ -565,6 +570,7 @@ let isCall = 1,
                    "blxns${p}\t$func", []>,
                 Requires<[IsThumb, Has8MSecExt]>,
                 T1Special<{1,1,1,?}>, Sched<[WriteBrL]> {
+    bits<0> p;
     bits<4> func;
     let Inst{6-3} = func;
     let Inst{2-0} = 0b100;
@@ -824,6 +830,7 @@ let hasSideEffects = 0 in {
 let mayLoad = 1, hasExtraDefRegAllocReq = 1, variadicOpsAreDefs = 1 in
 def tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
         IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> {
+  bits<0> p;
   bits<3> Rn;
   bits<8> regs;
   let Inst{10-8} = Rn;
@@ -854,6 +861,7 @@ def tSTMIA_UPD : Thumb1I<(outs tGPR:$wb),
                          AddrModeNone, 2, IIC_iStore_mu,
                          "stm${p}\t$Rn!, $regs", "$Rn = $wb", []>,
                      T1Encoding<{1,1,0,0,0,?}> {
+  bits<0> p;
   bits<3> Rn;
   bits<8> regs;
   let Inst{10-8} = Rn;
@@ -872,6 +880,7 @@ def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
                IIC_iPop,
                "pop${p}\t$regs", []>,
            T1Misc<{1,1,0,?,?,?,?}>, Sched<[WriteLd]> {
+  bits<0> p;
   bits<16> regs;
   let Inst{8}   = regs{15};
   let Inst{7-0} = regs{7-0};
@@ -882,6 +891,7 @@ def tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
                 IIC_iStore_m,
                 "push${p}\t$regs", []>,
             T1Misc<{0,1,0,?,?,?,?}>, Sched<[WriteST]> {
+  bits<0> p;
   bits<16> regs;
   let Inst{8}   = regs{14};
   let Inst{7-0} = regs{7-0};
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index c229c8e4491df..290dd05fc84cb 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -2059,6 +2059,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
   def IA :
     T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
          itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2074,6 +2075,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
   def IA_UPD :
     T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
           itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2089,6 +2091,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
   def DB :
     T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
          itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2104,6 +2107,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
   def DB_UPD :
     T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
           itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2128,6 +2132,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
   def IA :
     T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
          itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2146,6 +2151,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
   def IA_UPD :
     T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
           itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2164,6 +2170,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
   def DB :
     T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
          itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -2182,6 +2189,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
   def DB_UPD :
     T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
           itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+    bits<0>  p;
     bits<4>  Rn;
     bits<16> regs;
 
@@ -4030,9 +4038,11 @@ def t2TBH : T2I<(outs), (ins (addrmode_tbh $Rn, $Rm):$addr), IIC_Br,
 // FIXME: should be able to write a pattern for ARMBrcond, but can't use
 // a two-value operand where a dag node expects ", "two operands. :(
 let isBranch = 1, isTerminator = 1 in
-def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
-                "b", ".w\t$target",
-                [/*(ARMbrcond bb:$target, imm:$cc)*/]>, Sched<[WriteBr]> {
+def t2Bcc : Thumb2XI<(outs), (ins brtarget:$target, pred:$p),
+                     AddrModeNone, 4, IIC_Br,
+                     "b${p}.w\t$target", "",
+                     [/*(ARMbrcond bb:$target, imm:$cc)*/]>,
+            Sched<[WriteBr]> {
   let Inst{31-27} = 0b11110;
   let Inst{15-14} = 0b10;
   let Inst{12} = 0;
@@ -5481,6 +5491,7 @@ class V8_1MI<dag oops, dag iops, AddrMode am, InstrItinClass itin, string asm,
 def t2CLRM : V8_1MI<(outs),
                     (ins pred:$p, reglist_with_apsr:$regs, variable_ops),
                     AddrModeNone, NoItinerary, "clrm${p}", "$regs", "", []> {
+  bits<0> p;
   bits<16> regs;
 
   let Inst{31-16} = 0b1110100010011111;
@@ -5509,6 +5520,7 @@ def t2BF_LabelPseudo
 
 def t2BFi : t2BF<(ins bflabel_u4:$b_label, bflabel_s16:$label, pred:$p),
                  !strconcat("bf", "${p}"), "$b_label, $label"> {
+  bits<0> p;
   bits<4> b_label;
   bits<16> label;
 
@@ -5540,6 +5552,7 @@ def t2BFic : t2BF<(ins bflabel_u4:$b_label, bflabel_s12:$label,
 
 def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
                  !strconcat("bfx", "${p}"), "$b_label, $Rn"> {
+  bits<0> p;
   bits<4> b_label;
   bits<4> Rn;
 
@@ -5551,6 +5564,7 @@ def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
 
 def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p),
                   !strconcat("bfl", "${p}"), "$b_label, $label"> {
+  bits<0> p;
   bits<4> b_label;
   bits<18> label;
 
@@ -5563,6 +5577,7 @@ def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p),
 
 def t2BFLr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
                   !strconcat("bflx", "${p}"), "$b_label, $Rn"> {
+  bits<0> p;
   bits<4> b_label;
   bits<4> Rn;
 
@@ -5803,6 +5818,7 @@ let Predicates = [IsThumb2, HasV8_1MMainline, HasPACBTI] in {
 def t2PACG : V8_1MI<(outs rGPR:$Rd),
                     (ins pred:$p, GPRnopc:$Rn, GPRnopc:$Rm),
                     AddrModeNone, NoItinerary, "pacg${p}", "$Rd, $Rn, $Rm", "", []> {
+  bits<0> p;
   bits<4> Rd;
   bits<4> Rn;
   bits<4> Rm;
@@ -5818,6 +5834,7 @@ let hasSideEffects = 1 in {
 class PACBTIAut<dag iops, string asm, bit b>
   : V8_1MI<(outs), iops,
            AddrModeNone, NoItinerary, asm, "$Ra, $Rn, $Rm", "", []> {
+  bits<0> p;
   bits<4> Ra;
   bits<4> Rn;
   bits<4> Rm;
diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt
index fa778cad4af8e..a39629bd8aeb0 100644
--- a/llvm/lib/Target/ARM/CMakeLists.txt
+++ b/llvm/lib/Target/ARM/CMakeLists.txt
@@ -6,8 +6,7 @@ tablegen(LLVM ARMGenAsmMatcher.inc -gen-asm-matcher)
 tablegen(LLVM ARMGenAsmWriter.inc -gen-asm-writer)
 tablegen(LLVM ARMGenCallingConv.inc -gen-callingconv)
 tablegen(LLVM ARMGenDAGISel.inc -gen-dag-isel)
-tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler
-              -ignore-non-decodable-operands)
+tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler)
 tablegen(LLVM ARMGenFastISel.inc -gen-fast-isel)
 tablegen(LLVM ARMGenGlobalISel.inc -gen-global-isel)
 tablegen(LLVM ARMGenInstrInfo.inc -gen-instr-info)
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index b119146576569..0a3e6d2f89e1c 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -149,7 +149,7 @@ class ARMDisassembler : public MCDisassembler {
                                    raw_ostream &CStream) const;
 
   bool isVectorPredicable(const MCInst &MI) const;
-  DecodeStatus AddThumbPredicate(MCInst&) const;
+  DecodeStatus checkThumbPredicate(MCInst &) const;
   void UpdateThumbPredicate(DecodeStatus &S, MCInst &MI) const;
 
   llvm::endianness InstructionEndianness;
@@ -618,6 +618,23 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
   return S;
 }
 
+// This overload is used to decode a `pred` operand that is not encoded into
+// instruction. This is the case for almost all predicable Thumb instructions
+// (exceptions are tBcc and t2Bcc). Some predicable Thumb instructions have ARM
+// equivalents where they are not predicable (always executed). This function
+// is used to decode `pred` operand of these ARM instructions, too.
+static DecodeStatus DecodePredicateOperand(MCInst &Inst,
+                                           const MCDisassembler *Decoder) {
+  const auto *D = static_cast<const ARMDisassembler *>(Decoder);
+  unsigned CC = ARMCC::AL;
+  if (D->getSubtargetInfo().hasFeature(ARM::ModeThumb))
+    CC = D->ITBlock.getITCC();
+  MCRegister CondReg = CC == ARMCC::AL ? ARM::NoRegister : ARM::CPSR;
+  Inst.addOperand(MCOperand::createImm(CC));
+  Inst.addOperand(MCOperand::createReg(CondReg));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,
                                        uint64_t Address,
                                        const MCDisassembler *Decoder) {
@@ -1050,6 +1067,40 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
       if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
         return MCDisassembler::Fail;
       break;
+    case ARM::t2LDC2L_OFFSET:
+    case ARM::t2LDC2L_OPTION:
+    case ARM::t2LDC2L_POST:
+    case ARM::t2LDC2L_PRE:
+    case ARM::t2LDC2_OFFSET:
+    case ARM::t2LDC2_OPTION:
+    case ARM::t2LDC2_POST:
+    case ARM::t2LDC2_PRE:
+    case ARM::t2LDCL_OFFSET:
+    case ARM::t2LDCL_OPTION:
+    case ARM::t2LDCL_POST:
+    case ARM::t2LDCL_PRE:
+    case ARM::t2LDC_OFFSET:
+    case ARM::t2LDC_OPTION:
+    case ARM::t2LDC_POST:
+    case ARM::t2LDC_PRE:
+    case ARM::t2STC2L_OFFSET:
+    case ARM::t2STC2L_OPTION:
+    case ARM::t2STC2L_POST:
+    case ARM::t2STC2L_PRE:
+    case ARM::t2STC2_OFFSET:
+    case ARM::t2STC2_OPTION:
+    case ARM::t2STC2_POST:
+    case ARM::t2STC2_PRE:
+    case ARM::t2STCL_OFFSET:
+    case ARM::t2STCL_OPTION:
+    case ARM::t2STCL_POST:
+    case ARM::t2STCL_PRE:
+    case ARM::t2STC_OFFSET:
+    case ARM::t2STC_OPTION:
+    case ARM::t2STC_POST:
+    case ARM::t2STC_PRE:
+      DecodePredicateOperand(Inst, Decoder);
+      break;
     default:
       break;
   }
@@ -1217,6 +1268,8 @@ static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn,
   // the only available operand), but LLVM expects the instruction to have one
   // operand, so we need to add the csync when decoding.
   Inst.addOperand(MCOperand::createImm(ARM_TSB::CSYNC));
+  if (Inst.getOpcode() == ARM::t2TSB)
+    DecodePredicateOperand(Inst, Decoder);
   return MCDisassembler::Success;
 }
 
@@ -1650,6 +1703,7 @@ static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
     if(imm > 4) return MCDisassembler::Fail;
     Inst.setOpcode(ARM::t2HINT);
     Inst.addOperand(MCOperand::createImm(imm));
+    DecodePredicateOperand(Inst, Decoder);
   }
 
   return S;
@@ -1675,6 +1729,7 @@ DecodeT2HintSpaceInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
   Inst.setOpcode(Opcode);
   if (Opcode == ARM::t2HINT) {
     Inst.addOperand(MCOperand::createImm(imm));
+    DecodePredicateOperand(Inst, Decoder);
   }
 
   return MCDisassembler::Success;
@@ -1702,6 +1757,7 @@ static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn,
   if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
     Inst.addOperand(MCOperand::createImm(imm));
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -1906,6 +1962,7 @@ static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
                                 true, 4, Inst, Decoder))
     Inst.addOperand(MCOperand::createImm(imm32));
 
+  DecodePredicateOperand(Inst, Decoder);
   return Status;
 }
 
@@ -2231,6 +2288,7 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn,
     break;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2502,6 +2560,7 @@ static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn,
       break;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2605,6 +2664,7 @@ static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn,
       !Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
     return MCDisassembler::Fail;
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2654,6 +2714,7 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
       return MCDisassembler::Fail;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2690,6 +2751,7 @@ static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn,
       return MCDisassembler::Fail;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2743,6 +2805,7 @@ static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn,
       return MCDisassembler::Fail;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2789,6 +2852,7 @@ static DecodeStatus DecodeVMOVModImmInstruction(MCInst &Inst, unsigned Insn,
       break;
   }
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2861,6 +2925,7 @@ static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn,
     return MCDisassembler::Fail;
   Inst.addOperand(MCOperand::createImm(8 << size));
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2926,6 +2991,7 @@ static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn,
   if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
     return MCDisassembler::Fail;
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -2951,6 +3017,7 @@ static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
   }
 
   Inst.addOperand(MCOperand::createImm(imm));
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -3113,6 +3180,7 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
   }
   Inst.addOperand(MCOperand::createImm(imm));
 
+  DecodePredicateOperand(Inst, Decoder);
   return S;
 }
 
@@ -3197,6 +3265,7 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
   if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder)))
     return MCDisassemb...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:ARM bazel "Peripheral" support tier build system: utils/bazel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants