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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 definition since adding ImmLeaf to
// bare_simm13_lsb0 above makes it not sit well with codegen 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;
Expand Down Expand Up @@ -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>
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;

Expand Down
31 changes: 29 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -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]
92 changes: 74 additions & 18 deletions llvm/test/MC/RISCV/xqcibi-long-conditional-jump.s
Original file line number Diff line number Diff line change
Expand Up @@ -64,59 +64,115 @@ 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

# Check that instructions are first compressed and then relaxed

# CHECK-INST: qc.beqi a0, 0xa, 0xf44c
# CHECK-INST-NEXT: jal zero, 0x1089c
# CHECK-INST-RELAX: qc.beqi a0, 0xa, 0xf44c
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.bnei a0, 10, .L13
.fill 1300, 4, 0
.L13:
ret

# CHECK-INST: qc.bnei a0, 0xa, 0x108a6
# CHECK-INST-NEXT: jal zero, 0x11cf6
# CHECK-INST-RELAX: qc.bnei a0, 0xa, 0x108a6
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.beqi a0, 10, .L14
.fill 1300, 4, 0
.L14:
ret

# CHECK-INST: qc.bgei a0, 0xa, 0x11d00
# CHECK-INST-NEXT: jal zero, 0x13150
# CHECK-INST-RELAX: qc.bgei a0, 0xa, 0x11d00
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.blti a0, 10, .L15
.fill 1300, 4, 0
.L15:
ret

# CHECK-INST: qc.blti a0, 0xa, 0x1315a
# CHECK-INST-NEXT: jal zero, 0x145aa
# CHECK-INST-RELAX: qc.blti a0, 0xa, 0x1315a
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.bgei a0, 10, .L16
.fill 1300, 4, 0
.L16:
ret

# CHECK-INST: qc.bgeui a0, 0xa, 0x145b4
# CHECK-INST-NEXT: jal zero, 0x15a04
# CHECK-INST-RELAX: qc.bgeui a0, 0xa, 0x145b4
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.bltui a0, 10, .L17
.fill 1300, 4, 0
.L17:
ret

# CHECK-INST: qc.bltui a0, 0xa, 0x15a0e
# CHECK-INST-NEXT: jal zero, 0x16e5e
# CHECK-INST-RELAX: qc.bltui a0, 0xa, 0x15a0e
# CHECK-INST-RELAX-NEXT: jal zero, {{.*}}
qc.e.bgeui a0, 10, .L18
.fill 1300, 4, 0
.L18:
ret

.Lfunc_end0:
.size test, .Lfunc_end0-test
60 changes: 49 additions & 11 deletions llvm/test/MC/RISCV/xqcibi-valid.s
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Loading