-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[RISCV] Add Qualcomm uC Xqcilb (Long Branch) extension #131996
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
Conversation
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. Change-Id: I262d59edc8c7266800badc82d6496619ce2aeabf
Change-Id: I0afb1b8f8ab442a83477e09917634db0b3ac6093
Change-Id: I969bb0f122a467c8b36308f6ce016d9f7e53a88b
Change-Id: Ia36de6564e8961039aa53ce8b6aaf242f6c335b1
Change-Id: I15118e0e3b96c380e44e07c6c344ec8ac20e2eeb
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: quic_hchandel (hchandel) ChangesThis extension adds two long branch instructions. The current spec can be found at: This patch adds assembler only support. Co-authored-by: Sudharsan Veeravalli <[email protected]> Full diff: https://github.com/llvm/llvm-project/pull/131996.diff 12 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 019106abfabc3..6ddb118004134 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -203,6 +203,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 cf7be8b2c5c96..2966c887caae2 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -459,6 +459,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 b191a840d9803..8fb24cc850a55 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 433e95d2bca19..a71594de4e8ca 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1132,6 +1132,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
@@ -1765,6 +1776,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 e3c4cc36ee822..d5ca56c7e46e3 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -651,10 +651,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 74224b2e150e4..905662b8869bd 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1359,6 +1359,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 d10c334330a14..8ebae8f70a652 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 a5cbc7f0cf882..6fab99b19426b 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
@@ -416,6 +417,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 04082a89124ee..de30757ace822 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -658,7 +658,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'"));
@@ -1143,6 +1144,7 @@ Experimental extensions
xqcics 0.2
xqcicsr 0.2
xqciint 0.4
+ xqcilb 0.2
xqcili 0.2
xqcilia 0.2
xqcilo 0.2
|
@llvm/pr-subscribers-backend-risc-v Author: quic_hchandel (hchandel) ChangesThis extension adds two long branch instructions. The current spec can be found at: This patch adds assembler only support. Co-authored-by: Sudharsan Veeravalli <[email protected]> Full diff: https://github.com/llvm/llvm-project/pull/131996.diff 12 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 019106abfabc3..6ddb118004134 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -203,6 +203,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 cf7be8b2c5c96..2966c887caae2 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -459,6 +459,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 b191a840d9803..8fb24cc850a55 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 433e95d2bca19..a71594de4e8ca 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1132,6 +1132,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
@@ -1765,6 +1776,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 e3c4cc36ee822..d5ca56c7e46e3 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -651,10 +651,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 74224b2e150e4..905662b8869bd 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1359,6 +1359,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 d10c334330a14..8ebae8f70a652 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 a5cbc7f0cf882..6fab99b19426b 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
@@ -416,6 +417,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 04082a89124ee..de30757ace822 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -658,7 +658,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'"));
@@ -1143,6 +1144,7 @@ Experimental extensions
xqcics 0.2
xqcicsr 0.2
xqciint 0.4
+ xqcilb 0.2
xqcili 0.2
xqcilia 0.2
xqcilo 0.2
|
int64_t Imm; | ||
if (!MCOp.evaluateAsConstantImm(Imm)) | ||
return false; | ||
return isShiftedInt<31, 1>(Imm); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why doesn't this check for MCOp.isBareSymbolRef()
like simm13_lsb0 and simm21_lsb0_jal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR adds only support for using explicit immediates in these instructions. We do intend to add support for symbols, but deeper changes are required to how LLVM emits relocations, so we'll do all that support in a follow-up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are explicit immediates useful? binutils and llvm disagree on how those are treated for the existing branches/jumps. llvm treats them as relative addresses. binutils treats them as absolute addresses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well that's a fun assembler difference I didn't know about :(
We've found it useful to write them for testing our assembler/disassembler, but agree that most users will use the symbol versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but Craig may have more comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Windows build has passed but linux build failed. The failed linux build seems unrelated. I am going ahead and merging the PR. |
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/30/builds/18020 Here is the relevant piece of the build log for the reference
|
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 [email protected]