[llvm] 0744d49 - [RISCV] Add Qualcomm uC Xqcilb (Long Branch) extension (#131996)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 19 22:44:57 PDT 2025
Author: quic_hchandel
Date: 2025-03-20T11:14:53+05:30
New Revision: 0744d4926a0c567b0f10d19f0478b7a4bf960a19
URL: https://github.com/llvm/llvm-project/commit/0744d4926a0c567b0f10d19f0478b7a4bf960a19
DIFF: https://github.com/llvm/llvm-project/commit/0744d4926a0c567b0f10d19f0478b7a4bf960a19.diff
LOG: [RISCV] Add Qualcomm uC Xqcilb (Long Branch) extension (#131996)
This extension adds two long branch instructions.
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 <quic_svs at quicinc.com>
Added:
llvm/test/MC/RISCV/xqcilb-invalid.s
llvm/test/MC/RISCV/xqcilb-valid.s
Modified:
clang/test/Driver/print-supported-extensions-riscv.c
llvm/docs/RISCVUsage.rst
llvm/docs/ReleaseNotes.md
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
llvm/lib/Target/RISCV/RISCVFeatures.td
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
llvm/lib/TargetParser/RISCVISAInfo.cpp
llvm/test/CodeGen/RISCV/attributes.ll
llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
Removed:
################################################################################
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 35de2820ef84f..40b8eb6217240 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -205,6 +205,7 @@
// CHECK-NEXT: xqcics 0.2 'Xqcics' (Qualcomm uC Conditional Select Extension)
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
// CHECK-NEXT: xqciint 0.4 'Xqciint' (Qualcomm uC Interrupts Extension)
+// CHECK-NEXT: xqcilb 0.2 'Xqcilb' (Qualcomm uC Long Branch Extension)
// CHECK-NEXT: xqcili 0.2 'Xqcili' (Qualcomm uC Load Large Immediate Extension)
// CHECK-NEXT: xqcilia 0.2 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
// CHECK-NEXT: xqcilo 0.2 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index d6ac226dad5e6..28d09cffa95c0 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -461,6 +461,9 @@ The current vendor extensions supported are:
``experimental-Xqciint``
LLVM implements `version 0.4 of the Qualcomm uC Interrupts 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.
+``experimental-Xqcilb``
+ LLVM implements `version 0.2 of the Qualcomm uC Long Branch 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.
+
``experimental-Xqcili``
LLVM implements `version 0.2 of the Qualcomm uC Load Large 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.
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 30d66b4a77a71..205c2ad25f23e 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -114,6 +114,8 @@ Changes to the PowerPC Backend
Changes to the RISC-V Backend
-----------------------------
+* Adds experimental assembler support for the Qualcomm uC 'Xqcilb` (Long Branch)
+ extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcili` (Load Large Immediate)
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcilia` (Large Immediate Arithmetic)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index ce25380cbdda2..d3500e3e44c50 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1144,6 +1144,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_None;
}
+ bool isSImm32Lsb0() const {
+ if (!isImm())
+ return false;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_None;
+ int64_t Imm;
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+ return IsConstantImm &&
+ isShiftedInt<31, 1>(fixImmediateForRV32(Imm, isRV64Imm())) &&
+ VK == RISCVMCExpr::VK_None;
+ }
+
/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
@@ -1777,6 +1788,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(Operands, ErrorInfo,
std::numeric_limits<int32_t>::min(),
std::numeric_limits<uint32_t>::max());
+ case Match_InvalidSImm32Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
+ std::numeric_limits<int32_t>::max() - 1,
+ "operand must be a multiple of 2 bytes in the range ");
case Match_InvalidRnumArg: {
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
}
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 05bb6d30cc9a7..5abf15a404dfb 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -667,10 +667,10 @@ static constexpr FeatureBitset XqciFeatureGroup = {
RISCV::FeatureVendorXqcibi, RISCV::FeatureVendorXqcibm,
RISCV::FeatureVendorXqcicli, RISCV::FeatureVendorXqcicm,
RISCV::FeatureVendorXqcics, RISCV::FeatureVendorXqcicsr,
- RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcili,
- RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
- RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisim,
- RISCV::FeatureVendorXqcisls,
+ RISCV::FeatureVendorXqciint, RISCV::FeatureVendorXqcilb,
+ RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilia,
+ RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
+ RISCV::FeatureVendorXqcisim, RISCV::FeatureVendorXqcisls,
};
static constexpr FeatureBitset XSfVectorGroup = {
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index f23a855e7049f..761cfbea76734 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1374,6 +1374,14 @@ def HasVendorXqciint
AssemblerPredicate<(all_of FeatureVendorXqciint),
"'Xqciint' (Qualcomm uC Interrupts Extension)">;
+def FeatureVendorXqcilb
+ : RISCVExperimentalExtension<0, 2, "Qualcomm uC Long Branch Extension",
+ [FeatureStdExtZca]>;
+
+def HasVendorXqcilb : Predicate<"Subtarget->hasVendorXqcilb()">,
+ AssemblerPredicate<(all_of FeatureVendorXqcilb),
+ "'Xqcilb' (Qualcomm uC Long Branch Extension)">;
+
def FeatureVendorXqcili
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Load Large Immediate Extension",
[FeatureStdExtZca]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 59fd13c6d683a..c009bd3b24682 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -96,6 +96,21 @@ def simm32 : RISCVOp<XLenVT> {
}];
}
+// A 32-bit signed immediate where the least significant bit is zero.
+def simm32_lsb0 : Operand<OtherVT> {
+ let ParserMatchClass = SImmAsmOperand<32, "Lsb0">;
+ let PrintMethod = "printBranchOperand";
+ let EncoderMethod = "getImmOpValueAsr1";
+ let DecoderMethod = "decodeSImmOperandAndLsl1<32>";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return isShiftedInt<31, 1>(Imm);
+ }];
+ let OperandType = "OPERAND_PCREL";
+}
+
//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
@@ -413,6 +428,24 @@ class QCIRVInstEI<bits<3> funct3, bits<2> funct2, string opcodestr>
(ins GPRNoX0:$rs1, simm26:$imm), opcodestr,
"$rd, $rs1, $imm">;
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class QCIRVInst48EJ<bits<2> func2, string opcodestr>
+ : RVInst48<(outs), (ins simm32_lsb0:$imm31),
+ opcodestr, "$imm31", [], InstFormatOther> {
+ bits<31> imm31;
+
+ let Inst{47-32} = imm31{30-15};
+ let Inst{31} = imm31{11};
+ let Inst{30-25} = imm31{9-4};
+ let Inst{24-20} = 0b00000;
+ let Inst{19-17} = imm31{14-12};
+ let Inst{16-15} = func2;
+ let Inst{14-12} = 0b100;
+ let Inst{11-8} = imm31{3-0};
+ let Inst{7} = imm31{10};
+ let Inst{6-0} = 0b0011111;
+}
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -677,6 +710,13 @@ let Predicates = [HasVendorXqcilo, IsRV32] in {
def QC_E_SW : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
} // Predicates = [HasVendorXqcilo, IsRV32]
+let Predicates = [HasVendorXqcilb, IsRV32] in {
+ let isCall = 1, Defs = [X1] in
+ def QC_E_JAL : QCIRVInst48EJ<0b01, "qc.e.jal">;
+ let isBranch = 1, isTerminator = 1, isBarrier = 1 in
+ def QC_E_J : QCIRVInst48EJ<0b00, "qc.e.j">;
+} // Predicates = [HasVendorXqcilb, IsRV32]
+
let Predicates = [HasVendorXqcili, IsRV32] in {
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
def QC_LI : RVInstU<OPC_OP_IMM_32, (outs GPRNoX0:$rd), (ins simm20:$imm20),
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 11d4b3746e94d..4cb263b028625 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -744,9 +744,10 @@ Error RISCVISAInfo::checkDependency() {
bool HasXqccmp = Exts.count("xqccmp") != 0;
static constexpr StringLiteral XqciExts[] = {
- {"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"}, {"xqcicli"},
- {"xqcicm"}, {"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcili"},
- {"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
+ {"xqcia"}, {"xqciac"}, {"xqcibi"}, {"xqcibm"},
+ {"xqcicli"}, {"xqcicm"}, {"xqcics"}, {"xqcicsr"},
+ {"xqciint"}, {"xqcilb"}, {"xqcili"}, {"xqcilia"},
+ {"xqcilo"}, {"xqcilsm"}, {"xqcisim"}, {"xqcisls"}};
static constexpr StringLiteral ZcdOverlaps[] = {
{"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 344438e554ce6..82b2b25add735 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -91,6 +91,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciint %s -o - | FileCheck --check-prefix=RV32XQCIINT %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilb %s -o - | FileCheck --check-prefix=RV32XQCILB %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcili %s -o - | FileCheck --check-prefix=RV32XQCILI %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilia %s -o - | FileCheck --check-prefix=RV32XQCILIA %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
@@ -418,6 +419,7 @@
; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p4"
+; RV32XQCILB: .attribute 5, "rv32i2p1_zca1p0_xqcilb0p2"
; RV32XQCILI: .attribute 5, "rv32i2p1_zca1p0_xqcili0p2"
; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
diff --git a/llvm/test/MC/RISCV/xqcilb-invalid.s b/llvm/test/MC/RISCV/xqcilb-invalid.s
new file mode 100644
index 0000000000000..1a9009b26b691
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilb-invalid.s
@@ -0,0 +1,24 @@
+# Xqcilb - Qualcomm uC Long Branch Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcilb < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcilb < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.j
+
+# CHECK-PLUS: :[[@LINE+1]]:9: error: operand must be a multiple of 2 bytes in the range [-2147483648, 2147483646]
+qc.e.j -2147483649
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilb' (Qualcomm uC Long Branch Extension)
+qc.e.j -2147483648
+
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.jal
+
+# CHECK-PLUS: :[[@LINE+1]]:10: error: operand must be a multiple of 2 bytes in the range [-2147483648, 2147483646]
+qc.e.jal 2147483649
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilb' (Qualcomm uC Long Branch Extension)
+qc.e.jal 2147483640
diff --git a/llvm/test/MC/RISCV/xqcilb-valid.s b/llvm/test/MC/RISCV/xqcilb-valid.s
new file mode 100644
index 0000000000000..1c722e3b3173e
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilb-valid.s
@@ -0,0 +1,26 @@
+# Xqcilb - Qualcomm uC Long Branch Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilb -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilb < %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcilb -M no-aliases --no-print-imm-hex -d - \
+# RUN: | FileCheck -check-prefix=CHECK-OBJ %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilb -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilb < %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcilb --no-print-imm-hex -d - \
+# RUN: | FileCheck -check-prefix=CHECK-OBJ %s
+
+# CHECK-INST: qc.e.j -2147483648
+# CHECK-OBJ: qc.e.j 0x80000000
+# CHECK-ENC: encoding: [0x1f,0x40,0x00,0x00,0x00,0x80]
+qc.e.j -2147483648
+
+# CHECK-INST: qc.e.jal 2147483640
+# CHECK-OBJ: qc.e.jal 0x7ffffffe
+# CHECK-ENC: encoding: [0x9f,0xcc,0x0e,0xfe,0xff,0x7f]
+qc.e.jal 2147483640
+
+# CHECK-INST: qc.e.jal -116
+# CHECK-OBJ: qc.e.jal 0xffffff98
+# CHECK-ENC: encoding: [0x9f,0xc6,0x0e,0xf8,0xff,0xff]
+qc.e.jal 0xffffff8c
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index c734f8a66d289..e609189b086e9 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -663,7 +663,8 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
"rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
"rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p4",
"rv64i_xqcilo0p2", "rv64i_xqcilia0p2", "rv64i_xqcibm0p4",
- "rv64i_xqcibi0p2", "rv64i_xqcili0p2", "rv64i_xqcisim0p2"}) {
+ "rv64i_xqcibi0p2", "rv64i_xqcili0p2", "rv64i_xqcisim0p2",
+ "rv64i_xqcilb0p2"}) {
EXPECT_THAT(
toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
::testing::EndsWith(" is only supported for 'rv32'"));
@@ -1150,6 +1151,7 @@ Experimental extensions
xqcics 0.2
xqcicsr 0.2
xqciint 0.4
+ xqcilb 0.2
xqcili 0.2
xqcilia 0.2
xqcilo 0.2
More information about the llvm-commits
mailing list