Skip to content

[RISCV] Add compress patterns for Xqcibi branch instructions #143095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 9, 2025

Conversation

svs-quic
Copy link
Contributor

@svs-quic svs-quic commented Jun 6, 2025

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32 bit qc.bxxi branch instructions.

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32 bit qc.bxxi branch instructions.
@llvmbot llvmbot added backend:RISC-V mc Machine (object) code labels Jun 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 6, 2025

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

Author: Sudharsan Veeravalli (svs-quic)

Changes

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32 bit qc.bxxi branch instructions.


Full diff: https://github.com/llvm/llvm-project/pull/143095.diff

5 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+20-8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td (+2-2)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+29-2)
  • (modified) llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s (+18-18)
  • (modified) llvm/test/MC/RISCV/xqcibi-valid.s (+49-11)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index de424b3be852b..e5eaa5d478387 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -341,21 +341,33 @@ def simm12 : RISCVSImmLeafOp<12> {
 def simm12_no6 : ImmLeaf<XLenVT, [{
   return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>;
 
-// A 13-bit signed immediate where the least significant bit is zero.
-def bare_simm13_lsb0 : Operand<OtherVT> {
-  let ParserMatchClass = BareSImmNLsb0AsmOperand<13>;
-  let PrintMethod = "printBranchOperand";
-  let EncoderMethod = "getImmOpValueAsrN<1>";
-  let DecoderMethod = "decodeSImmOperandAndLslN<13, 1>";
+class BareSImm13Lsb0MaybeSym : Operand<OtherVT> {
   let MCOperandPredicate = [{
     int64_t Imm;
     if (MCOp.evaluateAsConstantImm(Imm))
       return isShiftedInt<12, 1>(Imm);
     return MCOp.isBareSymbolRef();
   }];
+}
+
+// A 13-bit signed immediate where the least significant bit is zero. The ImmLeaf
+// is needed so that the CompressInstEmitter can correctly add checks for the
+// compress patterns that involve instructions that use this operand. Similar to
+// bare_simm9_lsb0 in RISCVInstrINfoC.td.
+def bare_simm13_lsb0 : BareSImm13Lsb0MaybeSym,
+                       ImmLeaf<XLenVT, [{return isShiftedInt<12, 1>(Imm);}]> {
+  let ParserMatchClass = BareSImmNLsb0AsmOperand<13>;
+  let PrintMethod = "printBranchOperand";
+  let EncoderMethod = "getImmOpValueAsrN<1>";
+  let DecoderMethod = "decodeSImmOperandAndLslN<13, 1>";
   let OperandType = "OPERAND_PCREL";
 }
 
+// We need this (sort of) duplicate defintion since adding ImmLeaf to
+// bare_simm13_lsb0 above makes it not sit well with patterns where it is used to
+// match with a basic block (eg. BccPat<>).
+def bare_simm13_lsb0_bb: BareSImm13Lsb0MaybeSym;
+
 class UImm20OperandMaybeSym : RISCVUImmOp<20> {
   let MCOperandPredicate = [{
     int64_t Imm;
@@ -1660,10 +1672,10 @@ multiclass SelectCC_GPR_riirr<DAGOperand valty, DAGOperand imm> {
 // Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
 multiclass BccPat<CondCode Cond, RVInstB Inst> {
   def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12),
-            (Inst GPR:$rs1, GPR:$rs2, bare_simm13_lsb0:$imm12)>;
+            (Inst GPR:$rs1, GPR:$rs2, bare_simm13_lsb0_bb:$imm12)>;
   // Explicitly select 0 to X0. The register coalescer doesn't always do it.
   def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12),
-            (Inst GPR:$rs1, (XLenVT X0), bare_simm13_lsb0:$imm12)>;
+            (Inst GPR:$rs1, (XLenVT X0), bare_simm13_lsb0_bb:$imm12)>;
 }
 
 class BrccCompressOpt<CondCode Cond, RVInstB Inst>
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index 5d7dad458cf5d..942dde4bab31d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -798,9 +798,9 @@ def IntCCtoRISCVCCCV : SDNodeXForm<riscv_selectcc, [{
 
 let Predicates = [HasVendorXCVbi, IsRV32], AddedComplexity = 2 in {
   def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETEQ, bb:$imm12),
-            (CV_BEQIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0:$imm12)>;
+            (CV_BEQIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0_bb:$imm12)>;
   def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETNE, bb:$imm12),
-            (CV_BNEIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0:$imm12)>;
+            (CV_BNEIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0_bb:$imm12)>;
 
   defm CC_SImm5_CV : SelectCC_GPR_riirr<GPR, simm5>;
 
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index f292c93765744..dba035bab928c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -19,6 +19,12 @@ def uimm5nonzero : RISCVOp<XLenVT>,
   let ParserMatchClass = UImmAsmOperand<5, "NonZero">;
   let DecoderMethod = "decodeUImmNonZeroOperand<5>";
   let OperandType = "OPERAND_UIMM5_NONZERO";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return (Imm != 0) && isUInt<5>(Imm);;
+  }];
 }
 
 def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
@@ -111,6 +117,12 @@ def simm5nonzero : RISCVOp<XLenVT>,
   let ParserMatchClass = SImmAsmOperand<5, "NonZero">;
   let DecoderMethod = "decodeSImmNonZeroOperand<5>";
   let OperandType = "OPERAND_SIMM5_NONZERO";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return (Imm != 0) && isInt<5>(Imm);
+  }];
 }
 
 def simm11 : RISCVSImmLeafOp<11>;
@@ -1322,11 +1334,11 @@ class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
 // Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
 class BcciPat<CondCode Cond, QCIBranchInst_rii Inst, DAGOperand InTyImm>
     : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
-          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0_bb:$imm12)>;
 
 class Bcci48Pat<CondCode Cond, QCIBranchInst48_rii Inst, DAGOperand InTyImm>
     : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
-          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0_bb:$imm12)>;
 
 defm CC_SImm5NonZero_QC  : SelectCC_GPR_riirr<GPRNoX0, simm5nonzero>;
 defm CC_UImm5NonZero_QC  : SelectCC_GPR_riirr<GPRNoX0, uimm5nonzero>;
@@ -1543,3 +1555,18 @@ def : CompressPat<(QC_E_ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, 0),
 def : CompressPat<(QC_E_ADDI X2, X2, simm10_lsb0000nonzero:$imm),
                   (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
 } // let isCompressOnly = true, Predicates = [HasVendorXqcilia, IsRV32]
+
+let isCompressOnly = true, Predicates = [HasVendorXqcibi, IsRV32] in {
+def : CompressPat<(QC_E_BEQI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BEQI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BNEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BNEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BGEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BGEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BLTI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BLTI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BGEUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BGEUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+} // let isCompressOnly = true, Predicates = [HasVendorXqcibi, IsRV32]
diff --git a/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
index aab664f2a75fd..577a35b68dd0b 100644
--- a/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
+++ b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
@@ -64,56 +64,56 @@ test:
 .L6:
    ret
 
-# CHECK-INST:         qc.e.beqi    a0, 0x1, 0x7a26
+# CHECK-INST:         qc.e.beqi    a0, 0x51, 0x7a26
 # CHECK-INST-NEXT:    jal     zero, 0x8e76
-# CHECK-INST-RELAX:         qc.e.beqi    a0, 0x1, 0x7a26
+# CHECK-INST-RELAX:         qc.e.beqi    a0, 0x51, 0x7a26
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bnei a0, 1, .L7
+   qc.e.bnei a0, 81, .L7
 .fill 1300, 4, 0
 .L7:
    ret
 
-# CHECK-INST:         qc.e.bnei    a0, 0x2, 0x8e82
+# CHECK-INST:         qc.e.bnei    a0, 0x3e, 0x8e82
 # CHECK-INST-NEXT:    jal     zero, 0xa2d2
-# CHECK-INST-RELAX:         qc.e.bnei    a0, 0x2, 0x8e82
+# CHECK-INST-RELAX:         qc.e.bnei    a0, 0x3e, 0x8e82
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.beqi a0, 2, .L8
+   qc.e.beqi a0, 62, .L8
 .fill 1300, 4, 0
 .L8:
    ret
 
-# CHECK-INST:         qc.e.bgei    a0, 0x3, 0xa2de
+# CHECK-INST:         qc.e.bgei    a0, 0x5d, 0xa2de
 # CHECK-INST-NEXT:    jal     zero, 0xb72e
-# CHECK-INST-RELAX:         qc.e.bgei    a0, 0x3, 0xa2de
+# CHECK-INST-RELAX:         qc.e.bgei    a0, 0x5d, 0xa2de
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.blti a0, 3, .L9
+   qc.e.blti a0, 93, .L9
 .fill 1300, 4, 0
 .L9:
    ret
 
-# CHECK-INST:         qc.e.blti    a0, 0x4, 0xb73a
+# CHECK-INST:         qc.e.blti    a0, 0x2c, 0xb73a
 # CHECK-INST-NEXT:    jal     zero, 0xcb8a
-# CHECK-INST-RELAX:         qc.e.blti    a0, 0x4, 0xb73a
+# CHECK-INST-RELAX:         qc.e.blti    a0, 0x2c, 0xb73a
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bgei a0, 4, .L10
+   qc.e.bgei a0, 44, .L10
 .fill 1300, 4, 0
 .L10:
    ret
 
-# CHECK-INST:         qc.e.bgeui    a0, 0x5, 0xcb96
+# CHECK-INST:         qc.e.bgeui    a0, 0x37, 0xcb96
 # CHECK-INST-NEXT:    jal     zero, 0xdfe6
-# CHECK-INST-RELAX:         qc.e.bgeui    a0, 0x5, 0xcb96
+# CHECK-INST-RELAX:         qc.e.bgeui    a0, 0x37, 0xcb96
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bltui a0, 5, .L11
+   qc.e.bltui a0, 55, .L11
 .fill 1300, 4, 0
 .L11:
    ret
 
-# CHECK-INST:         qc.e.bltui    a0, 0x6, 0xdff2
+# CHECK-INST:         qc.e.bltui    a0, 0x24, 0xdff2
 # CHECK-INST-NEXT:    jal     zero, 0xf442
-# CHECK-INST-RELAX:         qc.e.bltui    a0, 0x6, 0xdff2
+# CHECK-INST-RELAX:         qc.e.bltui    a0, 0x24, 0xdff2
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bgeui a0, 6, .L12
+   qc.e.bgeui a0, 36, .L12
 .fill 1300, 4, 0
 .L12:
    ret
diff --git a/llvm/test/MC/RISCV/xqcibi-valid.s b/llvm/test/MC/RISCV/xqcibi-valid.s
index 63d35f3cafb80..88f7813d50915 100644
--- a/llvm/test/MC/RISCV/xqcibi-valid.s
+++ b/llvm/test/MC/RISCV/xqcibi-valid.s
@@ -1,11 +1,11 @@
 # Xqcibi - Qualcomm uC Branch Immediate Extension
 # RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -M no-aliases -show-encoding \
-# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST,CHECK-NOALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
 # RUN:     | llvm-objdump --mattr=+experimental-xqcibi -M no-aliases -d - \
-# RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ %s
 # RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -show-encoding \
-# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST,CHECK-ALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
 # RUN:     | llvm-objdump --mattr=+experimental-xqcibi -d - \
 # RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
@@ -40,10 +40,10 @@ qc.bgeui x12, 11, 128
 # CHECK-ENC: encoding: [0x7b,0x6d,0x71,0x28]
 qc.bltui x2, 7, 666
 
-# CHECK-INST:  qc.e.beqi   ra, 1, 2
-# CHECK-OBJ:  qc.e.beqi   ra, 0x1, 0x1a
-# CHECK-ENC: encoding: [0x1f,0xc1,0x80,0x01,0x01,0x00]
-qc.e.beqi x1, 1, 2
+# CHECK-INST:  qc.e.beqi   ra, 111, 2
+# CHECK-OBJ:  qc.e.beqi   ra, 0x6f, 0x1a
+# CHECK-ENC: encoding: [0x1f,0xc1,0x80,0x01,0x6f,0x00]
+qc.e.beqi x1, 111, 2
 
 # CHECK-INST: qc.e.bnei   tp, 115, 4094
 # CHECK-OBJ: qc.e.bnei   tp, 0x73, 0x101c
@@ -65,7 +65,45 @@ qc.e.blti x1, 32767, 2000
 # CHECK-ENC: encoding: [0x1f,0x40,0xf6,0x09,0xc7,0x02]
 qc.e.bgeui x12, 711, 128
 
-# CHECK-INST: qc.e.bltui  sp, 7, 666
-# CHECK-OBJ: qc.e.bltui  sp, 0x7, 0x2d0
-# CHECK-ENC: encoding: [0x1f,0x4d,0xe1,0x29,0x07,0x00]
-qc.e.bltui x2, 7, 666
+# CHECK-INST: qc.e.bltui  sp, 77, 666
+# CHECK-OBJ: qc.e.bltui  sp, 0x4d, 0x2d0
+# CHECK-ENC: encoding: [0x1f,0x4d,0xe1,0x29,0x4d,0x00]
+qc.e.bltui x2, 77, 666
+
+# Check that compress patterns work as expected
+
+# CHECK-NOALIAS:  beqi   ra, 11, 2
+# CHECK-ALIAS: qc.beqi   ra, 11, 2
+# CHECK-OBJ:  qc.beqi   ra, 0xb, 0x3e
+# CHECK-ENC: encoding: [0x7b,0x81,0xb0,0x00]
+qc.e.beqi x1, 11, 2
+
+# CHECK-NOALIAS:  bnei   ra, 11, 2
+# CHECK-ALIAS: qc.bnei   ra, 11, 2
+# CHECK-OBJ:  qc.bnei   ra, 0xb, 0x42
+# CHECK-ENC: encoding: [0x7b,0x91,0xb0,0x00]
+qc.e.bnei x1, 11, 2
+
+# CHECK-NOALIAS:  bgei   ra, 11, 2
+# CHECK-ALIAS: qc.bgei   ra, 11, 2
+# CHECK-OBJ:  qc.bgei   ra, 0xb, 0x46
+# CHECK-ENC: encoding: [0x7b,0xd1,0xb0,0x00]
+qc.e.bgei x1, 11, 2
+
+# CHECK-NOALIAS:  blti   ra, 11, 2
+# CHECK-ALIAS: qc.blti   ra, 11, 2
+# CHECK-OBJ:  qc.blti   ra, 0xb, 0x4a
+# CHECK-ENC: encoding: [0x7b,0xc1,0xb0,0x00]
+qc.e.blti x1, 11, 2
+
+# CHECK-NOALIAS:  bgeui   ra, 11, 2
+# CHECK-ALIAS: qc.bgeui   ra, 11, 2
+# CHECK-OBJ:  qc.bgeui   ra, 0xb, 0x4e
+# CHECK-ENC: encoding: [0x7b,0xf1,0xb0,0x00]
+qc.e.bgeui x1, 11, 2
+
+# CHECK-NOALIAS:  bltui   ra, 11, 2
+# CHECK-ALIAS: qc.bltui   ra, 11, 2
+# CHECK-OBJ:  qc.bltui   ra, 0xb, 0x52
+# CHECK-ENC: encoding: [0x7b,0xe1,0xb0,0x00]
+qc.e.bltui x1, 11, 2

@llvmbot
Copy link
Member

llvmbot commented Jun 6, 2025

@llvm/pr-subscribers-mc

Author: Sudharsan Veeravalli (svs-quic)

Changes

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32 bit qc.bxxi branch instructions.


Full diff: https://github.com/llvm/llvm-project/pull/143095.diff

5 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+20-8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td (+2-2)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+29-2)
  • (modified) llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s (+18-18)
  • (modified) llvm/test/MC/RISCV/xqcibi-valid.s (+49-11)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index de424b3be852b..e5eaa5d478387 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -341,21 +341,33 @@ def simm12 : RISCVSImmLeafOp<12> {
 def simm12_no6 : ImmLeaf<XLenVT, [{
   return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>;
 
-// A 13-bit signed immediate where the least significant bit is zero.
-def bare_simm13_lsb0 : Operand<OtherVT> {
-  let ParserMatchClass = BareSImmNLsb0AsmOperand<13>;
-  let PrintMethod = "printBranchOperand";
-  let EncoderMethod = "getImmOpValueAsrN<1>";
-  let DecoderMethod = "decodeSImmOperandAndLslN<13, 1>";
+class BareSImm13Lsb0MaybeSym : Operand<OtherVT> {
   let MCOperandPredicate = [{
     int64_t Imm;
     if (MCOp.evaluateAsConstantImm(Imm))
       return isShiftedInt<12, 1>(Imm);
     return MCOp.isBareSymbolRef();
   }];
+}
+
+// A 13-bit signed immediate where the least significant bit is zero. The ImmLeaf
+// is needed so that the CompressInstEmitter can correctly add checks for the
+// compress patterns that involve instructions that use this operand. Similar to
+// bare_simm9_lsb0 in RISCVInstrINfoC.td.
+def bare_simm13_lsb0 : BareSImm13Lsb0MaybeSym,
+                       ImmLeaf<XLenVT, [{return isShiftedInt<12, 1>(Imm);}]> {
+  let ParserMatchClass = BareSImmNLsb0AsmOperand<13>;
+  let PrintMethod = "printBranchOperand";
+  let EncoderMethod = "getImmOpValueAsrN<1>";
+  let DecoderMethod = "decodeSImmOperandAndLslN<13, 1>";
   let OperandType = "OPERAND_PCREL";
 }
 
+// We need this (sort of) duplicate defintion since adding ImmLeaf to
+// bare_simm13_lsb0 above makes it not sit well with patterns where it is used to
+// match with a basic block (eg. BccPat<>).
+def bare_simm13_lsb0_bb: BareSImm13Lsb0MaybeSym;
+
 class UImm20OperandMaybeSym : RISCVUImmOp<20> {
   let MCOperandPredicate = [{
     int64_t Imm;
@@ -1660,10 +1672,10 @@ multiclass SelectCC_GPR_riirr<DAGOperand valty, DAGOperand imm> {
 // Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
 multiclass BccPat<CondCode Cond, RVInstB Inst> {
   def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12),
-            (Inst GPR:$rs1, GPR:$rs2, bare_simm13_lsb0:$imm12)>;
+            (Inst GPR:$rs1, GPR:$rs2, bare_simm13_lsb0_bb:$imm12)>;
   // Explicitly select 0 to X0. The register coalescer doesn't always do it.
   def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12),
-            (Inst GPR:$rs1, (XLenVT X0), bare_simm13_lsb0:$imm12)>;
+            (Inst GPR:$rs1, (XLenVT X0), bare_simm13_lsb0_bb:$imm12)>;
 }
 
 class BrccCompressOpt<CondCode Cond, RVInstB Inst>
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index 5d7dad458cf5d..942dde4bab31d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -798,9 +798,9 @@ def IntCCtoRISCVCCCV : SDNodeXForm<riscv_selectcc, [{
 
 let Predicates = [HasVendorXCVbi, IsRV32], AddedComplexity = 2 in {
   def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETEQ, bb:$imm12),
-            (CV_BEQIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0:$imm12)>;
+            (CV_BEQIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0_bb:$imm12)>;
   def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETNE, bb:$imm12),
-            (CV_BNEIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0:$imm12)>;
+            (CV_BNEIMM GPR:$rs1, simm5:$imm5, bare_simm13_lsb0_bb:$imm12)>;
 
   defm CC_SImm5_CV : SelectCC_GPR_riirr<GPR, simm5>;
 
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index f292c93765744..dba035bab928c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -19,6 +19,12 @@ def uimm5nonzero : RISCVOp<XLenVT>,
   let ParserMatchClass = UImmAsmOperand<5, "NonZero">;
   let DecoderMethod = "decodeUImmNonZeroOperand<5>";
   let OperandType = "OPERAND_UIMM5_NONZERO";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return (Imm != 0) && isUInt<5>(Imm);;
+  }];
 }
 
 def uimm5gt3 : RISCVOp<XLenVT>, ImmLeaf<XLenVT,
@@ -111,6 +117,12 @@ def simm5nonzero : RISCVOp<XLenVT>,
   let ParserMatchClass = SImmAsmOperand<5, "NonZero">;
   let DecoderMethod = "decodeSImmNonZeroOperand<5>";
   let OperandType = "OPERAND_SIMM5_NONZERO";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (!MCOp.evaluateAsConstantImm(Imm))
+      return false;
+    return (Imm != 0) && isInt<5>(Imm);
+  }];
 }
 
 def simm11 : RISCVSImmLeafOp<11>;
@@ -1322,11 +1334,11 @@ class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
 // Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
 class BcciPat<CondCode Cond, QCIBranchInst_rii Inst, DAGOperand InTyImm>
     : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
-          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0_bb:$imm12)>;
 
 class Bcci48Pat<CondCode Cond, QCIBranchInst48_rii Inst, DAGOperand InTyImm>
     : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
-          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0:$imm12)>;
+          (Inst GPRNoX0:$rs1, InTyImm:$rs2, bare_simm13_lsb0_bb:$imm12)>;
 
 defm CC_SImm5NonZero_QC  : SelectCC_GPR_riirr<GPRNoX0, simm5nonzero>;
 defm CC_UImm5NonZero_QC  : SelectCC_GPR_riirr<GPRNoX0, uimm5nonzero>;
@@ -1543,3 +1555,18 @@ def : CompressPat<(QC_E_ADDI GPRNoX0:$rs1, GPRNoX0:$rs2, 0),
 def : CompressPat<(QC_E_ADDI X2, X2, simm10_lsb0000nonzero:$imm),
                   (C_ADDI16SP X2, simm10_lsb0000nonzero:$imm)>;
 } // let isCompressOnly = true, Predicates = [HasVendorXqcilia, IsRV32]
+
+let isCompressOnly = true, Predicates = [HasVendorXqcibi, IsRV32] in {
+def : CompressPat<(QC_E_BEQI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BEQI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BNEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BNEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BGEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BGEI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BLTI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BLTI GPRNoX0:$rs1, simm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BGEUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BGEUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+def : CompressPat<(QC_E_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12),
+                  (QC_BLTUI GPRNoX0:$rs1, uimm5nonzero:$imm5, bare_simm13_lsb0:$imm12)>;
+} // let isCompressOnly = true, Predicates = [HasVendorXqcibi, IsRV32]
diff --git a/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
index aab664f2a75fd..577a35b68dd0b 100644
--- a/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
+++ b/llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
@@ -64,56 +64,56 @@ test:
 .L6:
    ret
 
-# CHECK-INST:         qc.e.beqi    a0, 0x1, 0x7a26
+# CHECK-INST:         qc.e.beqi    a0, 0x51, 0x7a26
 # CHECK-INST-NEXT:    jal     zero, 0x8e76
-# CHECK-INST-RELAX:         qc.e.beqi    a0, 0x1, 0x7a26
+# CHECK-INST-RELAX:         qc.e.beqi    a0, 0x51, 0x7a26
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bnei a0, 1, .L7
+   qc.e.bnei a0, 81, .L7
 .fill 1300, 4, 0
 .L7:
    ret
 
-# CHECK-INST:         qc.e.bnei    a0, 0x2, 0x8e82
+# CHECK-INST:         qc.e.bnei    a0, 0x3e, 0x8e82
 # CHECK-INST-NEXT:    jal     zero, 0xa2d2
-# CHECK-INST-RELAX:         qc.e.bnei    a0, 0x2, 0x8e82
+# CHECK-INST-RELAX:         qc.e.bnei    a0, 0x3e, 0x8e82
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.beqi a0, 2, .L8
+   qc.e.beqi a0, 62, .L8
 .fill 1300, 4, 0
 .L8:
    ret
 
-# CHECK-INST:         qc.e.bgei    a0, 0x3, 0xa2de
+# CHECK-INST:         qc.e.bgei    a0, 0x5d, 0xa2de
 # CHECK-INST-NEXT:    jal     zero, 0xb72e
-# CHECK-INST-RELAX:         qc.e.bgei    a0, 0x3, 0xa2de
+# CHECK-INST-RELAX:         qc.e.bgei    a0, 0x5d, 0xa2de
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.blti a0, 3, .L9
+   qc.e.blti a0, 93, .L9
 .fill 1300, 4, 0
 .L9:
    ret
 
-# CHECK-INST:         qc.e.blti    a0, 0x4, 0xb73a
+# CHECK-INST:         qc.e.blti    a0, 0x2c, 0xb73a
 # CHECK-INST-NEXT:    jal     zero, 0xcb8a
-# CHECK-INST-RELAX:         qc.e.blti    a0, 0x4, 0xb73a
+# CHECK-INST-RELAX:         qc.e.blti    a0, 0x2c, 0xb73a
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bgei a0, 4, .L10
+   qc.e.bgei a0, 44, .L10
 .fill 1300, 4, 0
 .L10:
    ret
 
-# CHECK-INST:         qc.e.bgeui    a0, 0x5, 0xcb96
+# CHECK-INST:         qc.e.bgeui    a0, 0x37, 0xcb96
 # CHECK-INST-NEXT:    jal     zero, 0xdfe6
-# CHECK-INST-RELAX:         qc.e.bgeui    a0, 0x5, 0xcb96
+# CHECK-INST-RELAX:         qc.e.bgeui    a0, 0x37, 0xcb96
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bltui a0, 5, .L11
+   qc.e.bltui a0, 55, .L11
 .fill 1300, 4, 0
 .L11:
    ret
 
-# CHECK-INST:         qc.e.bltui    a0, 0x6, 0xdff2
+# CHECK-INST:         qc.e.bltui    a0, 0x24, 0xdff2
 # CHECK-INST-NEXT:    jal     zero, 0xf442
-# CHECK-INST-RELAX:         qc.e.bltui    a0, 0x6, 0xdff2
+# CHECK-INST-RELAX:         qc.e.bltui    a0, 0x24, 0xdff2
 # CHECK-INST-RELAX-NEXT:    jal     zero, {{.*}}
-   qc.e.bgeui a0, 6, .L12
+   qc.e.bgeui a0, 36, .L12
 .fill 1300, 4, 0
 .L12:
    ret
diff --git a/llvm/test/MC/RISCV/xqcibi-valid.s b/llvm/test/MC/RISCV/xqcibi-valid.s
index 63d35f3cafb80..88f7813d50915 100644
--- a/llvm/test/MC/RISCV/xqcibi-valid.s
+++ b/llvm/test/MC/RISCV/xqcibi-valid.s
@@ -1,11 +1,11 @@
 # Xqcibi - Qualcomm uC Branch Immediate Extension
 # RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -M no-aliases -show-encoding \
-# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST,CHECK-NOALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
 # RUN:     | llvm-objdump --mattr=+experimental-xqcibi -M no-aliases -d - \
-# RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
+# RUN:     | FileCheck -check-prefixes=CHECK-OBJ %s
 # RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcibi -show-encoding \
-# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST,CHECK-ALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcibi < %s \
 # RUN:     | llvm-objdump --mattr=+experimental-xqcibi -d - \
 # RUN:     | FileCheck -check-prefix=CHECK-OBJ %s
@@ -40,10 +40,10 @@ qc.bgeui x12, 11, 128
 # CHECK-ENC: encoding: [0x7b,0x6d,0x71,0x28]
 qc.bltui x2, 7, 666
 
-# CHECK-INST:  qc.e.beqi   ra, 1, 2
-# CHECK-OBJ:  qc.e.beqi   ra, 0x1, 0x1a
-# CHECK-ENC: encoding: [0x1f,0xc1,0x80,0x01,0x01,0x00]
-qc.e.beqi x1, 1, 2
+# CHECK-INST:  qc.e.beqi   ra, 111, 2
+# CHECK-OBJ:  qc.e.beqi   ra, 0x6f, 0x1a
+# CHECK-ENC: encoding: [0x1f,0xc1,0x80,0x01,0x6f,0x00]
+qc.e.beqi x1, 111, 2
 
 # CHECK-INST: qc.e.bnei   tp, 115, 4094
 # CHECK-OBJ: qc.e.bnei   tp, 0x73, 0x101c
@@ -65,7 +65,45 @@ qc.e.blti x1, 32767, 2000
 # CHECK-ENC: encoding: [0x1f,0x40,0xf6,0x09,0xc7,0x02]
 qc.e.bgeui x12, 711, 128
 
-# CHECK-INST: qc.e.bltui  sp, 7, 666
-# CHECK-OBJ: qc.e.bltui  sp, 0x7, 0x2d0
-# CHECK-ENC: encoding: [0x1f,0x4d,0xe1,0x29,0x07,0x00]
-qc.e.bltui x2, 7, 666
+# CHECK-INST: qc.e.bltui  sp, 77, 666
+# CHECK-OBJ: qc.e.bltui  sp, 0x4d, 0x2d0
+# CHECK-ENC: encoding: [0x1f,0x4d,0xe1,0x29,0x4d,0x00]
+qc.e.bltui x2, 77, 666
+
+# Check that compress patterns work as expected
+
+# CHECK-NOALIAS:  beqi   ra, 11, 2
+# CHECK-ALIAS: qc.beqi   ra, 11, 2
+# CHECK-OBJ:  qc.beqi   ra, 0xb, 0x3e
+# CHECK-ENC: encoding: [0x7b,0x81,0xb0,0x00]
+qc.e.beqi x1, 11, 2
+
+# CHECK-NOALIAS:  bnei   ra, 11, 2
+# CHECK-ALIAS: qc.bnei   ra, 11, 2
+# CHECK-OBJ:  qc.bnei   ra, 0xb, 0x42
+# CHECK-ENC: encoding: [0x7b,0x91,0xb0,0x00]
+qc.e.bnei x1, 11, 2
+
+# CHECK-NOALIAS:  bgei   ra, 11, 2
+# CHECK-ALIAS: qc.bgei   ra, 11, 2
+# CHECK-OBJ:  qc.bgei   ra, 0xb, 0x46
+# CHECK-ENC: encoding: [0x7b,0xd1,0xb0,0x00]
+qc.e.bgei x1, 11, 2
+
+# CHECK-NOALIAS:  blti   ra, 11, 2
+# CHECK-ALIAS: qc.blti   ra, 11, 2
+# CHECK-OBJ:  qc.blti   ra, 0xb, 0x4a
+# CHECK-ENC: encoding: [0x7b,0xc1,0xb0,0x00]
+qc.e.blti x1, 11, 2
+
+# CHECK-NOALIAS:  bgeui   ra, 11, 2
+# CHECK-ALIAS: qc.bgeui   ra, 11, 2
+# CHECK-OBJ:  qc.bgeui   ra, 0xb, 0x4e
+# CHECK-ENC: encoding: [0x7b,0xf1,0xb0,0x00]
+qc.e.bgeui x1, 11, 2
+
+# CHECK-NOALIAS:  bltui   ra, 11, 2
+# CHECK-ALIAS: qc.bltui   ra, 11, 2
+# CHECK-OBJ:  qc.bltui   ra, 0xb, 0x52
+# CHECK-ENC: encoding: [0x7b,0xe1,0xb0,0x00]
+qc.e.bltui x1, 11, 2

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

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

Please can you add some more tests for the long branch relaxation done in the assembler?

The comment changes are nits, a typo and trying to be specific about which patterns we mean, because there are two kinds of patterns interacting oddly here.

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

Copy link
Contributor

@tclin914 tclin914 left a comment

Choose a reason for hiding this comment

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

A few nits. LTGM

@svs-quic svs-quic merged commit e27876a into llvm:main Jun 9, 2025
7 checks passed
@svs-quic svs-quic deleted the xqcibicompress branch June 9, 2025 03:59
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
…3095)

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32
bit qc.bxxi branch instructions.
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
…3095)

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32
bit qc.bxxi branch instructions.
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
…3095)

This patch adds patterns to compress from the 48-bit qc.e.bxxi to the 32
bit qc.bxxi branch instructions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants