Skip to content

Commit 036c6cb

Browse files
hchandelsvs-quic
andauthored
[RISCV] Add Qualcomm uC Xqcibi (Branch Immediate) extension (#130779)
This extension adds twelve conditional branch instructions that use an immediate operand for the source. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.7.0 This patch adds assembler only support. Co-authored-by: Sudharsan Veeravalli <[email protected]>
1 parent 194ecef commit 036c6cb

File tree

13 files changed

+423
-11
lines changed

13 files changed

+423
-11
lines changed

clang/test/Driver/print-supported-extensions-riscv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@
196196
// CHECK-NEXT: xqccmp 0.1 'Xqccmp' (Qualcomm 16-bit Push/Pop and Double Moves)
197197
// CHECK-NEXT: xqcia 0.4 'Xqcia' (Qualcomm uC Arithmetic Extension)
198198
// CHECK-NEXT: xqciac 0.3 'Xqciac' (Qualcomm uC Load-Store Address Calculation Extension)
199+
// CHECK-NEXT: xqcibi 0.2 'Xqcibi' (Qualcomm uC Branch Immediate Extension)
199200
// CHECK-NEXT: xqcibm 0.4 'Xqcibm' (Qualcomm uC Bit Manipulation Extension)
200201
// CHECK-NEXT: xqcicli 0.2 'Xqcicli' (Qualcomm uC Conditional Load Immediate Extension)
201202
// CHECK-NEXT: xqcicm 0.2 'Xqcicm' (Qualcomm uC Conditional Move Extension)

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ The current vendor extensions supported are:
438438
``experimental-Xqciac``
439439
LLVM implements `version 0.3 of the Qualcomm uC Load-Store Address Calculation extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
440440

441+
``experimental-Xqcibi``
442+
LLVM implements `version 0.2 of the Qualcomm uC Branch Immediate extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
443+
441444
``experimental-Xqcibm``
442445
LLVM implements `version 0.4 of the Qualcomm uC Bit Manipulation extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
443446

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ Changes to the RISC-V Backend
120120
extension.
121121
* Adds experimental assembler support for the Qualcomm uC 'Xqcibm` (Bit Manipulation)
122122
extension.
123+
* Adds experimental assembler support for the Qualcomm uC 'Xqcibi` (Branch Immediate)
124+
extension.
123125
* Adds experimental assembler and code generation support for the Qualcomm
124126
'Xqccmp' extension, which is a frame-pointer convention compatible version of
125127
Zcmp.

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
820820
VK == RISCVMCExpr::VK_None;
821821
}
822822

823+
bool isSImm5NonZero() const {
824+
if (!isImm())
825+
return false;
826+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
827+
int64_t Imm;
828+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
829+
return IsConstantImm && Imm != 0 &&
830+
isInt<5>(fixImmediateForRV32(Imm, isRV64Imm())) &&
831+
VK == RISCVMCExpr::VK_RISCV_None;
832+
}
833+
823834
bool isSImm6() const {
824835
if (!isImm())
825836
return false;
@@ -1007,6 +1018,27 @@ struct RISCVOperand final : public MCParsedAsmOperand {
10071018
VK == RISCVMCExpr::VK_None;
10081019
}
10091020

1021+
bool isSImm16NonZero() const {
1022+
if (!isImm())
1023+
return false;
1024+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1025+
int64_t Imm;
1026+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1027+
return IsConstantImm && Imm != 0 &&
1028+
isInt<16>(fixImmediateForRV32(Imm, isRV64Imm())) &&
1029+
VK == RISCVMCExpr::VK_RISCV_None;
1030+
}
1031+
1032+
bool isUImm16NonZero() const {
1033+
if (!isImm())
1034+
return false;
1035+
int64_t Imm;
1036+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1037+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1038+
return IsConstantImm && isUInt<16>(Imm) && (Imm != 0) &&
1039+
VK == RISCVMCExpr::VK_RISCV_None;
1040+
}
1041+
10101042
bool isUImm20LUI() const {
10111043
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_None;
10121044
int64_t Imm;
@@ -1611,6 +1643,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16111643
case Match_InvalidSImm5:
16121644
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
16131645
(1 << 4) - 1);
1646+
case Match_InvalidSImm5NonZero:
1647+
return generateImmOutOfRangeError(
1648+
Operands, ErrorInfo, -(1 << 4), (1 << 4) - 1,
1649+
"immediate must be non-zero in the range");
16141650
case Match_InvalidSImm6:
16151651
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 5),
16161652
(1 << 5) - 1);
@@ -1665,6 +1701,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16651701
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 10) - 1);
16661702
case Match_InvalidUImm11:
16671703
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);
1704+
case Match_InvalidUImm16NonZero:
1705+
return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16) - 1);
16681706
case Match_InvalidSImm12:
16691707
return generateImmOutOfRangeError(
16701708
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
@@ -1682,6 +1720,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16821720
return generateImmOutOfRangeError(
16831721
Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
16841722
"immediate must be a multiple of 2 bytes in the range");
1723+
case Match_InvalidSImm16NonZero:
1724+
return generateImmOutOfRangeError(
1725+
Operands, ErrorInfo, -(1 << 15), (1 << 15) - 1,
1726+
"immediate must be non-zero in the range");
16851727
case Match_InvalidUImm20LUI:
16861728
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
16871729
"operand must be a symbol with "

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -648,12 +648,12 @@ static constexpr FeatureBitset XRivosFeatureGroup = {
648648

649649
static constexpr FeatureBitset XqciFeatureGroup = {
650650
RISCV::FeatureVendorXqcia, RISCV::FeatureVendorXqciac,
651-
RISCV::FeatureVendorXqcibm, RISCV::FeatureVendorXqcicli,
652-
RISCV::FeatureVendorXqcicm, RISCV::FeatureVendorXqcics,
653-
RISCV::FeatureVendorXqcicsr, RISCV::FeatureVendorXqciint,
654-
RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilia,
655-
RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
656-
RISCV::FeatureVendorXqcisls,
651+
RISCV::FeatureVendorXqcibi, RISCV::FeatureVendorXqcibm,
652+
RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
653+
RISCV::FeatureVendorXqcics, RISCV::FeatureVendorXqcicsr,
654+
RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcili,
655+
RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
656+
RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisls,
657657
};
658658

659659
static constexpr FeatureBitset XSfVectorGroup = {

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ enum OperandType : unsigned {
314314
OPERAND_UIMM11,
315315
OPERAND_UIMM12,
316316
OPERAND_UIMM16,
317+
OPERAND_UIMM16_NONZERO,
317318
OPERAND_UIMM20,
318319
OPERAND_UIMMLOG2XLEN,
319320
OPERAND_UIMMLOG2XLEN_NONZERO,
@@ -322,13 +323,15 @@ enum OperandType : unsigned {
322323
OPERAND_UIMM64,
323324
OPERAND_ZERO,
324325
OPERAND_SIMM5,
326+
OPERAND_SIMM5_NONZERO,
325327
OPERAND_SIMM5_PLUS1,
326328
OPERAND_SIMM6,
327329
OPERAND_SIMM6_NONZERO,
328330
OPERAND_SIMM10_LSB0000_NONZERO,
329331
OPERAND_SIMM11,
330332
OPERAND_SIMM12,
331333
OPERAND_SIMM12_LSB00000,
334+
OPERAND_SIMM16_NONZERO,
332335
OPERAND_SIMM20,
333336
OPERAND_SIMM26,
334337
OPERAND_SIMM32,

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,14 @@ def HasVendorXqcibm
13831383
AssemblerPredicate<(all_of FeatureVendorXqcibm),
13841384
"'Xqcibm' (Qualcomm uC Bit Manipulation Extension)">;
13851385

1386+
def FeatureVendorXqcibi
1387+
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Branch Immediate Extension",
1388+
[FeatureStdExtZca]>;
1389+
def HasVendorXqcibi
1390+
: Predicate<"Subtarget->hasVendorXqcibi()">,
1391+
AssemblerPredicate<(all_of FeatureVendorXqcibi),
1392+
"'Xqcibi' (Qualcomm uC Branch Immediate Extension)">;
1393+
13861394
def FeatureVendorXqcilo
13871395
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
13881396
[FeatureStdExtZca]>;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,29 @@ def uimm10 : RISCVUImmLeafOp<10>;
5454

5555
def uimm11 : RISCVUImmLeafOp<11>;
5656

57+
def uimm16nonzero : RISCVOp<XLenVT>,
58+
ImmLeaf<XLenVT, [{return (Imm != 0) && isUInt<16>(Imm);}]> {
59+
let ParserMatchClass = UImmAsmOperand<16, "NonZero">;
60+
let DecoderMethod = "decodeUImmNonZeroOperand<16>";
61+
let OperandType = "OPERAND_UIMM16_NONZERO";
62+
}
63+
64+
def simm5nonzero : RISCVOp<XLenVT>,
65+
ImmLeaf<XLenVT, [{return (Imm != 0) && isInt<5>(Imm);}]> {
66+
let ParserMatchClass = SImmAsmOperand<5, "NonZero">;
67+
let DecoderMethod = "decodeSImmNonZeroOperand<5>";
68+
let OperandType = "OPERAND_SIMM5_NONZERO";
69+
}
70+
5771
def simm11 : RISCVSImmLeafOp<11>;
5872

73+
def simm16nonzero : RISCVOp<XLenVT>,
74+
ImmLeaf<XLenVT, [{return (Imm != 0) && isInt<16>(Imm);}]> {
75+
let ParserMatchClass = SImmAsmOperand<16, "NonZero">;
76+
let DecoderMethod = "decodeSImmNonZeroOperand<16>";
77+
let OperandType = "OPERAND_SIMM16_NONZERO";
78+
}
79+
5980
def simm20 : RISCVSImmLeafOp<20>;
6081

6182
def simm26 : RISCVSImmLeafOp<26>;
@@ -261,6 +282,40 @@ class QCIRVInst16CI_RS1<bits<5> funct5, string OpcodeStr>
261282
let Inst{6-2} = funct5{4-0};
262283
}
263284

285+
class QCIBranchInst_rii<bits<3> funct3, DAGOperand InTyImm5, string opcodestr>
286+
: RVInstB<funct3, OPC_CUSTOM_3, (outs),
287+
(ins GPRNoX0:$rs1, InTyImm5:$rs2, simm13_lsb0:$imm12),
288+
opcodestr, "$rs1, $rs2, $imm12"> {
289+
let isBranch = 1;
290+
let isTerminator = 1;
291+
let hasSideEffects = 0;
292+
let mayLoad = 0;
293+
let mayStore = 0;
294+
}
295+
296+
class QCIBranchInst48_rii<bits<5> funct5, DAGOperand InTyImm16, string opcodestr>
297+
: RVInst48<(outs), (ins GPRNoX0:$rs1, InTyImm16:$imm16, simm13_lsb0:$imm12),
298+
opcodestr, "$rs1, $imm16, $imm12", [], InstFormatOther> {
299+
bits<5> rs1;
300+
bits<16> imm16;
301+
bits<12> imm12;
302+
303+
let Inst{47-32} = imm16;
304+
let Inst{31} = imm12{11};
305+
let Inst{30-25} = imm12{9-4};
306+
let Inst{24-20} = funct5;
307+
let Inst{19-15} = rs1;
308+
let Inst{14-12} = 0b100;
309+
let Inst{11-8} = imm12{3-0};
310+
let Inst{7} = imm12{10};
311+
let Inst{6-0} = 0b0011111;
312+
let isBranch = 1;
313+
let isTerminator = 1;
314+
let hasSideEffects = 0;
315+
let mayLoad = 0;
316+
let mayStore = 0;
317+
}
318+
264319
let hasSideEffects = 1 in
265320
class QCIRVInst16CI_NONE<bits<5> funct5, string OpcodeStr>
266321
: RVInst16CI<0b000, 0b10, (outs), (ins), OpcodeStr, ""> {
@@ -399,6 +454,22 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
399454
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
400455
} // Predicates = [HasVendorXqcia, IsRV32]
401456

457+
let Predicates = [HasVendorXqcibi, IsRV32] in {
458+
def QC_BEQI : QCIBranchInst_rii<0b000, simm5nonzero, "qc.beqi">;
459+
def QC_BNEI : QCIBranchInst_rii<0b001, simm5nonzero, "qc.bnei">;
460+
def QC_BLTI : QCIBranchInst_rii<0b100, simm5nonzero, "qc.blti">;
461+
def QC_BGEI : QCIBranchInst_rii<0b101, simm5nonzero, "qc.bgei">;
462+
def QC_BLTUI : QCIBranchInst_rii<0b110, uimm5nonzero, "qc.bltui">;
463+
def QC_BGEUI : QCIBranchInst_rii<0b111, uimm5nonzero, "qc.bgeui">;
464+
465+
def QC_E_BEQI : QCIBranchInst48_rii<0b11000, simm16nonzero, "qc.e.beqi">;
466+
def QC_E_BNEI : QCIBranchInst48_rii<0b11001, simm16nonzero, "qc.e.bnei">;
467+
def QC_E_BLTI : QCIBranchInst48_rii<0b11100, simm16nonzero, "qc.e.blti">;
468+
def QC_E_BGEI : QCIBranchInst48_rii<0b11101, simm16nonzero, "qc.e.bgei">;
469+
def QC_E_BLTUI : QCIBranchInst48_rii<0b11110, uimm16nonzero, "qc.e.bltui">;
470+
def QC_E_BGEUI : QCIBranchInst48_rii<0b11111, uimm16nonzero, "qc.e.bgeui">;
471+
} // Predicates = [HasVendorXqcibi, IsRV32]
472+
402473
let Predicates = [HasVendorXqcibm, IsRV32] in {
403474
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
404475
def QC_INSBRI : QCIRVInstRI<0b1, simm11, "qc.insbri">;

llvm/lib/TargetParser/RISCVISAInfo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,9 @@ Error RISCVISAInfo::checkDependency() {
744744
bool HasXqccmp = Exts.count("xqccmp") != 0;
745745

746746
static constexpr StringLiteral XqciExts[] = {
747-
{"xqcia"}, {"xqciac"}, {"xqcibm"}, {"xqcicli"}, {"xqcicm"},
748-
{"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcili"}, {"xqcilia"},
749-
{"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
747+
{"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"}, {"xqcicli"},
748+
{"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcili"},
749+
{"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
750750
static constexpr StringLiteral ZcdOverlaps[] = {
751751
{"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
752752

llvm/test/CodeGen/RISCV/attributes.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqccmp %s -o - | FileCheck --check-prefix=RV32XQCCMP %s
8585
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia %s -o - | FileCheck --check-prefix=RV32XQCIA %s
8686
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciac %s -o - | FileCheck --check-prefix=RV32XQCIAC %s
87+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibi %s -o - | FileCheck --check-prefix=RV32XQCIBI %s
8788
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcibm %s -o - | FileCheck --check-prefix=RV32XQCIBM %s
8889
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicli %s -o - | FileCheck --check-prefix=RV32XQCICLI %s
8990
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm %s -o - | FileCheck --check-prefix=RV32XQCICM %s
@@ -407,6 +408,7 @@
407408
; RV32XQCCMP: .attribute 5, "rv32i2p1_zca1p0_xqccmp0p1"
408409
; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p4"
409410
; RV32XQCIAC: .attribute 5, "rv32i2p1_zca1p0_xqciac0p3"
411+
; RV32XQCIBI: .attribute 5, "rv32i2p1_zca1p0_xqcibi0p2"
410412
; RV32XQCIBM: .attribute 5, "rv32i2p1_zca1p0_xqcibm0p4"
411413
; RV32XQCICLI: .attribute 5, "rv32i2p1_xqcicli0p2"
412414
; RV32XQCICM: .attribute 5, "rv32i2p1_zca1p0_xqcicm0p2"

0 commit comments

Comments
 (0)