-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[RISCV] Add Qualcomm uC Xqcisls (Scaled Load Store) extension #117987
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 8 load/store instructions with a scaled index addressing mode. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/latest This patch adds assembler only support.
@llvm/pr-subscribers-backend-risc-v @llvm/pr-subscribers-clang-driver Author: Sudharsan Veeravalli (svs-quic) ChangesThis extension adds 8 load/store instructions with a scaled index addressing mode. The current spec can be found at: This patch adds assembler only support. Full diff: https://github.com/llvm/llvm-project/pull/117987.diff 11 Files Affected:
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index 02edfc03e59cac..70b7a96daf1daf 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -189,6 +189,7 @@
// CHECK-NEXT: ssctr 1.0 'Ssctr' (Control Transfer Records Supervisor Level)
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
+// CHECK-NEXT: xqcisls 0.2 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
// CHECK-EMPTY:
// CHECK-NEXT: Supported Profiles
// CHECK-NEXT: rva20s64
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index a7000baa69d806..230bf66fcf461b 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -429,6 +429,9 @@ The current vendor extensions supported are:
``experimental-Xqcicsr``
LLVM implements `version 0.2 of the Qualcomm uC CSR 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-Xqcisls``
+ LLVM implements `version 0.2 of the Qualcomm uC Scaled Load Store 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 C Intrinsics
=========================
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 8b155d77bbb397..6d50839d68953e 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -213,6 +213,8 @@ Changes to the RISC-V Backend
between e.g. F and Zfinx code.
* Adds experimental assembler support for the Qualcomm uC 'Xqcicsr` (CSR)
extension.
+* Adds experimental assembler support for the Qualcomm uC 'Xqcisls` (Scaled Load Store)
+ extension.
Changes to the WebAssembly Backend
----------------------------------
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index e4f7ee323cf20b..95658f24f79e1c 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -684,6 +684,8 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
"CORE-V Immediate Branching custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcicsr, DecoderTableXqcicsr32,
"Qualcomm uC CSR custom opcode table");
+ TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcisls, DecoderTableXqcisls32,
+ "Qualcomm uC Scaled Load Store custom opcode table");
TRY_TO_DECODE(true, DecoderTable32, "RISCV32 table");
return MCDisassembler::Fail;
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 48ae378c0e67ef..95a37a76836729 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1351,6 +1351,14 @@ def HasVendorXqcicsr
AssemblerPredicate<(all_of FeatureVendorXqcicsr),
"'Xqcicsr' (Qualcomm uC CSR Extension)">;
+def FeatureVendorXqcisls
+ : RISCVExperimentalExtension<"xqcisls", 0, 2,
+ "'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;
+def HasVendorXqcisls
+ : Predicate<"Subtarget->hasVendorXqcisls()">,
+ AssemblerPredicate<(all_of FeatureVendorXqcisls),
+ "'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;
+
//===----------------------------------------------------------------------===//
// LLVM specific features and extensions
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 570fe23d744e14..5cdf07ee513a3d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -22,6 +22,28 @@
// Instruction Class Templates
//===----------------------------------------------------------------------===//
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+class QCILoad_ScaleIdx<bits<4> func4, string opcodestr>
+ : RVInstRBase<0b111, OPC_CUSTOM_0,
+ (outs GPR:$rd), (ins GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt),
+ opcodestr, "$rd, $rs1, $rs2, $shamt"> {
+ bits<3> shamt;
+ let Inst{31-28} = func4;
+ let Inst{27-25} = shamt;
+}
+}
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+class QCIStore_ScaleIdx<bits<4> func4, string opcodestr>
+ : RVInstRBase<0b110, OPC_CUSTOM_1, (outs),
+ (ins GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt),
+ opcodestr, "$rd, $rs1, $rs2, $shamt"> {
+ bits<3> shamt;
+ let Inst{31-28} = func4;
+ let Inst{27-25} = shamt;
+}
+}
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -37,3 +59,15 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
"$rd, $rs1, $rs2">;
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
} // Predicates = [HasVendorXqcicsr, IsRV32], DecoderNamespace = "Xqcicsr"
+
+let Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls" in {
+ def QC_LRB : QCILoad_ScaleIdx<0b1000, "qc.lrb">;
+ def QC_LRH : QCILoad_ScaleIdx<0b1001, "qc.lrh">;
+ def QC_LRW : QCILoad_ScaleIdx<0b1010, "qc.lrw">;
+ def QC_LRBU : QCILoad_ScaleIdx<0b1011, "qc.lrbu">;
+ def QC_LRHU : QCILoad_ScaleIdx<0b1100, "qc.lrhu">;
+
+ def QC_SRB : QCIStore_ScaleIdx<0b1101, "qc.srb">;
+ def QC_SRH : QCIStore_ScaleIdx<0b1110, "qc.srh">;
+ def QC_SRW : QCIStore_ScaleIdx<0b1111, "qc.srw">;
+} // Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls"
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index cc5be59572e040..08d2774e50a458 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -741,6 +741,7 @@ Error RISCVISAInfo::checkDependency() {
bool HasVector = Exts.count("zve32x") != 0;
bool HasZvl = MinVLen != 0;
bool HasZcmt = Exts.count("zcmt") != 0;
+ static constexpr StringLiteral XqciExts[] = {{"xqcicsr"}, {"xqcisls"}};
if (HasI && HasE)
return getIncompatibleError("i", "e");
@@ -771,9 +772,11 @@ Error RISCVISAInfo::checkDependency() {
return getIncompatibleError("xwchc", "zcb");
}
- if (Exts.count("xqcicsr") != 0 && (XLen != 32)) {
- return getError("'xqcicsr' is only supported for 'rv32'");
- }
+ for (auto Ext : XqciExts)
+ if (Exts.count(Ext.str()) && (XLen != 32))
+ return createStringError(errc::invalid_argument,
+ "'" + Twine(Ext) + "'" +
+ " is only supported for 'rv32'");
return Error::success();
}
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 554ae89357f72c..8a3d5e5cfe6216 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -82,6 +82,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV32XTHEADSYNC %s
; RUN: llc -mtriple=riscv32 -mattr=+xwchc %s -o - | FileCheck --check-prefix=RV32XWCHC %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
; RUN: llc -mtriple=riscv32 -mattr=+zalrsc %s -o - | FileCheck --check-prefix=RV32ZALRSC %s
; RUN: llc -mtriple=riscv32 -mattr=+zca %s -o - | FileCheck --check-prefixes=CHECK,RV32ZCA %s
@@ -387,6 +388,7 @@
; RV32XTHEADSYNC: .attribute 5, "rv32i2p1_xtheadsync1p0"
; RV32XWCHC: .attribute 5, "rv32i2p1_xwchc2p2"
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
+; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
; RV32ZALRSC: .attribute 5, "rv32i2p1_zalrsc1p0"
; RV32ZCA: .attribute 5, "rv32i2p1_zca1p0"
diff --git a/llvm/test/MC/RISCV/xqcisls-invalid.s b/llvm/test/MC/RISCV/xqcisls-invalid.s
new file mode 100644
index 00000000000000..4cd2a14975a946
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisls-invalid.s
@@ -0,0 +1,132 @@
+# Xqcisls - Qualcomm uC Scaled Load Store Extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcisls < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcisls < %s 2>&1 \
+# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.lrb x5, x2, x0, 4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrb x5, x2, x4
+
+# CHECK-PLUS: :[[@LINE+1]]:20: error: immediate must be an integer in the range [0, 7]
+qc.lrb x5, x2, x4, 12
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.lrb x5, 2, x4, 4
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrb x5, x2, x4, 4
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.lrh x1, x12, x0, 2
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrh x1, x12, x6
+
+# CHECK-PLUS: :[[@LINE+1]]:21: error: immediate must be an integer in the range [0, 7]
+qc.lrh x1, x12, x6, 22
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.lrh x1, 12, x6, 2
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrh x1, x12, x6, 2
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.lrw x15, x7, x0, 1
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrw x15, x7, x14
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.lrw x15, x7, x14, 11
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.lrw x15, 7, x14, 1
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrw x15, x7, x14, 1
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.lrbu x9, x11, x0, 7
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrbu x9, x11, x4
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.lrbu x9, x11, x4, 37
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.lrbu x9, 11, x4, 7
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrbu x9, x11, x4, 7
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.lrhu x16, x6, x0, 4
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.lrhu x16, x6, x10
+
+# CHECK-PLUS: :[[@LINE+1]]:23: error: immediate must be an integer in the range [0, 7]
+qc.lrhu x16, x6, x10, 44
+
+# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
+qc.lrhu x16, 6, x10, 4
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.lrhu x16, x6, x10, 4
+
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.srb x0, x2, x0, 3
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srb x0, x2, x8
+
+# CHECK-PLUS: :[[@LINE+1]]:20: error: immediate must be an integer in the range [0, 7]
+qc.srb x0, x2, x8, 93
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.srb x0, 2, x8, 3
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srb x0, x2, x8, 3
+
+
+# CHECK: :[[@LINE+1]]:17: error: invalid operand for instruction
+qc.srh x13, x0, x0, 6
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srh x13, x0, x20
+
+# CHECK-PLUS: :[[@LINE+1]]:22: error: immediate must be an integer in the range [0, 7]
+qc.srh x13, x0, x20, 76
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.srh x13, 0, x20, 6
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srh x13, x0, x20, 6
+
+
+# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
+qc.srw x17, x18, x0, 0
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.srw x17, x18, x19
+
+# CHECK-PLUS: :[[@LINE+1]]:23: error: immediate must be an integer in the range [0, 7]
+qc.srw x17, x18, x19, 10
+
+# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
+qc.srw x17, 18, x19, 0
+
+# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
+qc.srw x17, x18, x19, 0
diff --git a/llvm/test/MC/RISCV/xqcisls-valid.s b/llvm/test/MC/RISCV/xqcisls-valid.s
new file mode 100644
index 00000000000000..ae8370afc6c6e2
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcisls-valid.s
@@ -0,0 +1,43 @@
+# Xqcisls - Qualcomm uC Scaled Load Store Extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisls -riscv-no-aliases -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisls < %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcisls -M no-aliases --no-print-imm-hex -d - \
+# RUN: | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcisls -show-encoding \
+# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcisls < %s \
+# RUN: | llvm-objdump --mattr=+experimental-xqcisls --no-print-imm-hex -d - \
+# RUN: | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.lrb t0, sp, tp, 4
+# CHECK-ENC: encoding: [0x8b,0x72,0x41,0x88]
+qc.lrb x5, x2, x4, 4
+
+# CHECK-INST: qc.lrh ra, a2, t1, 2
+# CHECK-ENC: encoding: [0x8b,0x70,0x66,0x94]
+qc.lrh x1, x12, x6, 2
+
+# CHECK-INST: qc.lrw a5, t2, a4, 1
+# CHECK-ENC: encoding: [0x8b,0xf7,0xe3,0xa2]
+qc.lrw x15, x7, x14, 1
+
+# CHECK-INST: qc.lrbu s1, a1, tp, 7
+# CHECK-ENC: encoding: [0x8b,0xf4,0x45,0xbe]
+qc.lrbu x9, x11, x4, 7
+
+# CHECK-INST: qc.lrhu a6, t1, a0, 4
+# CHECK-ENC: encoding: [0x0b,0x78,0xa3,0xc8]
+qc.lrhu x16, x6, x10, 4
+
+# CHECK-INST: qc.srb zero, sp, s0, 3
+# CHECK-ENC: encoding: [0x2b,0x60,0x81,0xd6]
+qc.srb x0, x2, x8, 3
+
+# CHECK-INST: qc.srh a3, zero, s4, 6
+# CHECK-ENC: encoding: [0xab,0x66,0x40,0xed]
+qc.srh x13, x0, x20, 6
+
+# CHECK-INST: qc.srw a7, s2, s3, 0
+# CHECK-ENC: encoding: [0xab,0x68,0x39,0xf1]
+qc.srw x17, x18, x19, 0
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 4b450e23627168..554568280a1b40 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -1105,6 +1105,7 @@ Experimental extensions
ssctr 1.0
svukte 0.3
xqcicsr 0.2
+ xqcisls 0.2
Supported Profiles
rva20s64
|
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.
The encodings and functionality here are correct, but we're missing a test and it would be good to add a comment to the scaled store tablegen class.
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
} | ||
for (auto Ext : XqciExts) | ||
if (Exts.count(Ext.str()) && (XLen != 32)) | ||
return createStringError(errc::invalid_argument, |
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.
Can we use getError instead of createStringError?
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.
Thanks, I've made the change.
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
This extension adds 8 load/store instructions with a scaled index addressing mode.
The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/latest
This patch adds assembler only support.