[llvm-branch-commits] [llvm] [AArch64][llvm] Fix constant expressions in CMPBR immediate aliases (PR #230050)

Jonathan Thackray via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 9 03:13:17 PDT 2026


https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/230050

>From acb5ed3a2c7168d5e5ce8b29462f504bdad7671f Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Fri, 2 Oct 2026 11:52:02 +0100
Subject: [PATCH 1/2] [AArch64][llvm] Fix constant expressions in CMPBR
 immediate aliases

Use the standard immediate parser for CMPBR aliases so that parenthesized
expressions and explicit unary plus are accepted. This also simplifies
the amount of code required, since we can remove `tryParseAdjImm0_63`,
and reuse code in `AdjImmAsmOperand` which does the same job.

Check immediates in their original ranges and apply the adjustment
when rendering MC operands. Add coverage for constant expressions in
`cbge`, `cbhs`, `cble` and `cbls`.
---
 .../lib/Target/AArch64/AArch64InstrFormats.td | 38 +++++++------------
 .../AArch64/AsmParser/AArch64AsmParser.cpp    | 35 -----------------
 llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s    | 13 +++++++
 3 files changed, 27 insertions(+), 59 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 2e2f4b7fc2ba9b..567ef4cdb156cc 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -470,6 +470,16 @@ def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
+// TODO: Use AdjImmAsmOperand for the uimm6m1 and uimm6p1 operands too.
+class AdjImmAsmOperand<string name, string diagnostic, int adjustment,
+                       int low, int high> : AsmOperandClass {
+  let Name = name;
+  let DiagnosticType = diagnostic;
+  let RenderMethod = "addAdjImmOperands<" # adjustment # ">";
+  let PredicateMethod = "isImmInRange<" # !sub(low, adjustment) # "," #
+                        !sub(high, adjustment) # ">";
+}
+
 def CmpBranchUImm6Operand_32b
     : ComplexPattern<i32, 1, "SelectCmpBranchUImm6Operand", [imm]> {
   let WantsParent = true;
@@ -486,21 +496,11 @@ def CmpBranchBExtOperand
 def CmpBranchHExtOperand
     : ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<false>", []> {}
 
-def UImm6Plus1Operand : AsmOperandClass {
-  let Name = "UImm6P1";
-  let DiagnosticType = "InvalidImm1_64";
-  let RenderMethod = "addImmOperands";
-  let ParserMethod = "tryParseAdjImm0_63<-1>";
-  let PredicateMethod = "isImmInRange<0,63>";
-}
+def UImm6Plus1Operand
+    : AdjImmAsmOperand<"UImm6P1", "InvalidImm1_64", -1, 0, 63>;
 
-def UImm6Minus1Operand : AsmOperandClass {
-  let Name = "UImm6M1";
-  let DiagnosticType = "InvalidImmM1_62";
-  let RenderMethod = "addImmOperands";
-  let ParserMethod = "tryParseAdjImm0_63<1>";
-  let PredicateMethod = "isImmInRange<0,63>";
-}
+def UImm6Minus1Operand
+    : AdjImmAsmOperand<"UImm6M1", "InvalidImmM1_62", 1, 0, 63>;
 
 def uimm6p1_32b : Operand<i32> {
   let ParserMatchClass = UImm6Plus1Operand;
@@ -527,16 +527,6 @@ def uimm9 : Operand<i64> {
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-// TODO: Use AdjImmAsmOperand for the uimm6m1 and uimm6p1 operands too.
-class AdjImmAsmOperand<string name, string diagnostic, int adjustment,
-                       int low, int high> : AsmOperandClass {
-  let Name = name;
-  let DiagnosticType = diagnostic;
-  let RenderMethod = "addAdjImmOperands<" # adjustment # ">";
-  let PredicateMethod = "isImmInRange<" # !sub(low, adjustment) # "," #
-                        !sub(high, adjustment) # ">";
-}
-
 def uimm9p1 : Operand<i64> {
   let ParserMatchClass =
       AdjImmAsmOperand<"UImm9P1", "InvalidImm1_512", -1, 0, 511>;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 3fe6d140974851..79e39424097e07 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -296,7 +296,6 @@ class AArch64AsmParser : public MCTargetAsmParser {
   ParseStatus tryParseSVEVecLenSpecifier(OperandVector &Operands);
   ParseStatus tryParseGPR64x8(OperandVector &Operands);
   ParseStatus tryParseImmRange(OperandVector &Operands);
-  template <int> ParseStatus tryParseAdjImm0_63(OperandVector &Operands);
 
 public:
   enum AArch64MatchResultTy {
@@ -8797,37 +8796,3 @@ ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
       AArch64Operand::CreateImmRange(ImmFVal, ImmLVal, S, E, getContext()));
   return ParseStatus::Success;
 }
-
-template <int Adj>
-ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
-  SMLoc S = getLoc();
-
-  parseOptionalToken(AsmToken::Hash);
-  bool IsNegative = parseOptionalToken(AsmToken::Minus);
-
-  if (getTok().isNot(AsmToken::Integer))
-    return ParseStatus::NoMatch;
-
-  const MCExpr *Ex;
-  if (getParser().parseExpression(Ex))
-    return ParseStatus::NoMatch;
-
-  int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
-  if (IsNegative)
-    Imm = -Imm;
-
-  // We want an adjusted immediate in the range [0, 63]. If we don't have one,
-  // return a value, which is certain to trigger a error message about invalid
-  // immediate range instead of a non-descriptive invalid operand error.
-  static_assert(Adj == 1 || Adj == -1, "Unsafe immediate adjustment");
-  if (Imm == INT64_MIN || Imm == INT64_MAX || Imm + Adj < 0 || Imm + Adj > 63)
-    Imm = -2;
-  else
-    Imm += Adj;
-
-  SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
-  Operands.push_back(AArch64Operand::CreateImm(
-      MCConstantExpr::create(Imm, getContext()), S, E, getContext()));
-
-  return ParseStatus::Success;
-}
diff --git a/llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s b/llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s
index b7ec31d51a4263..8985a574ace80b 100644
--- a/llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s
+++ b/llvm/test/MC/AArch64/CMPBR/cmpbr_aliases.s
@@ -72,3 +72,16 @@
 
 // CHECK: cbgt x5, x3, #-1024                  // encoding: [0x05,0x20,0x03,0xf4]
     cblt x3, x5, #-1024
+// Constant expressions in adjusted immediate aliases.
+
+// CHECK: cbgt w5, #0, #-1024                  // encoding: [0x05,0x20,0x00,0x75]
+    cbge w5, #(2 - 1), #-1024
+
+// CHECK: cbhi x5, #63, #-1024                 // encoding: [0x05,0xa0,0x5f,0xf5]
+    cbhs x5, #+64, #-1024
+
+// CHECK: cblt w5, #0, #-1024                  // encoding: [0x05,0x20,0x20,0x75]
+    cble w5, #(-1), #-1024
+
+// CHECK: cblo x5, #63, #-1024                 // encoding: [0x05,0xa0,0x7f,0xf5]
+    cbls x5, #+62, #-1024

>From 9ccd8cb1274aee704a08545ba72a36aa708c0838 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 8 Oct 2026 22:37:37 +0100
Subject: [PATCH 2/2] fixup! Remove UImm6Plus1Operand and UImm6Minus1Operand

---
 .../lib/Target/AArch64/AArch64InstrFormats.td | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 567ef4cdb156cc..3dbe36a8c6850e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -470,7 +470,6 @@ def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
-// TODO: Use AdjImmAsmOperand for the uimm6m1 and uimm6p1 operands too.
 class AdjImmAsmOperand<string name, string diagnostic, int adjustment,
                        int low, int high> : AsmOperandClass {
   let Name = name;
@@ -496,29 +495,27 @@ def CmpBranchBExtOperand
 def CmpBranchHExtOperand
     : ComplexPattern<i32, 2, "SelectCmpBranchExtOperand<false>", []> {}
 
-def UImm6Plus1Operand
-    : AdjImmAsmOperand<"UImm6P1", "InvalidImm1_64", -1, 0, 63>;
-
-def UImm6Minus1Operand
-    : AdjImmAsmOperand<"UImm6M1", "InvalidImmM1_62", 1, 0, 63>;
-
 def uimm6p1_32b : Operand<i32> {
-  let ParserMatchClass = UImm6Plus1Operand;
+  let ParserMatchClass =
+      AdjImmAsmOperand<"UImm6P1", "InvalidImm1_64", -1, 0, 63>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
 def uimm6p1_64b : Operand<i64> {
-  let ParserMatchClass = UImm6Plus1Operand;
+  let ParserMatchClass =
+      AdjImmAsmOperand<"UImm6P1", "InvalidImm1_64", -1, 0, 63>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
 def uimm6m1_32b : Operand<i32> {
-  let ParserMatchClass = UImm6Minus1Operand;
+  let ParserMatchClass =
+      AdjImmAsmOperand<"UImm6M1", "InvalidImmM1_62", 1, 0, 63>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 
 def uimm6m1_64b : Operand<i64> {
-  let ParserMatchClass = UImm6Minus1Operand;
+  let ParserMatchClass =
+      AdjImmAsmOperand<"UImm6M1", "InvalidImmM1_62", 1, 0, 63>;
   let OperandType = "OPERAND_IMMEDIATE";
 }
 



More information about the llvm-branch-commits mailing list