Skip to content

Conversation

@svs-quic
Copy link
Contributor

This patch adds basic instruction selection patterns for generating the 48 bit load/store instructions that are a part of the Qualcomm uC Xqcilo vendor extension.

This patch adds instruction selection patterns for generating the 48 bit load/store instructions
that are a part of the Qualcomm uC Xqcilo vendor extension.
@llvmbot
Copy link
Member

llvmbot commented Apr 16, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Sudharsan Veeravalli (svs-quic)

Changes

This patch adds basic instruction selection patterns for generating the 48 bit load/store instructions that are a part of the Qualcomm uC Xqcilo vendor extension.


Full diff: https://github.com/llvm/llvm-project/pull/135901.diff

2 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+27)
  • (added) llvm/test/CodeGen/RISCV/qc-xqcilo.ll (+143)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 2458bda80b1d6..6736b0f1d0328 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -159,6 +159,11 @@ def bare_simm32_lsb0 : Operand<OtherVT> {
   let OperandType = "OPERAND_PCREL";
 }
 
+def AddLike: PatFrags<(ops node:$A, node:$B),
+                      [(add node:$A, node:$B), (or node:$A, node:$B)], [{
+    return CurDAG->isBaseWithConstantOffset(SDValue(N, 0));
+}]>;
+
 //===----------------------------------------------------------------------===//
 // Instruction Formats
 //===----------------------------------------------------------------------===//
@@ -1239,6 +1244,14 @@ class PatGprNoX0Simm32NoSimm26<SDPatternOperator OpNode, RVInst48 Inst>
     : Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), simm32_nosimm26:$imm)),
           (Inst GPRNoX0:$rs1, simm32_nosimm26:$imm)>;
 
+class QC48LdPat<PatFrag LoadOp, RVInst48 Inst>
+    : Pat<(i32 (LoadOp (AddLike (i32 GPR:$rs1), simm26_nosimm12:$imm26))),
+          (Inst GPR:$rs1, simm26_nosimm12:$imm26)>;
+
+class QC48StPat<PatFrag StoreOp, RVInst48 Inst>
+    : Pat<(StoreOp (i32 GPR:$rs2), (AddLike (i32 GPR:$rs1), simm26_nosimm12:$imm26)),
+          (Inst GPR:$rs2, GPR:$rs1, simm26_nosimm12:$imm26)>;
+
 /// Simple arithmetic operations
 
 let Predicates = [HasVendorXqcilia, IsRV32] in {
@@ -1253,5 +1266,19 @@ def : PatGprNoX0Simm26NoSimm12<or, QC_E_ORI>;
 def : PatGprNoX0Simm26NoSimm12<xor, QC_E_XORI>;
 } // Predicates = [HasVendorXqcilia, IsRV32]
 
+let Predicates = [HasVendorXqcilo, IsRV32], AddedComplexity = 2 in {
+  def : QC48LdPat<sextloadi8, QC_E_LB>;
+  def : QC48LdPat<extloadi8, QC_E_LBU>; // Prefer unsigned due to no c.lb in Zcb.
+  def : QC48LdPat<sextloadi16, QC_E_LH>;
+  def : QC48LdPat<extloadi16, QC_E_LH>;
+  def : QC48LdPat<load, QC_E_LW>;
+  def : QC48LdPat<zextloadi8, QC_E_LBU>;
+  def : QC48LdPat<zextloadi16, QC_E_LHU>;
+
+  def : QC48StPat<truncstorei8, QC_E_SB>;
+  def : QC48StPat<truncstorei16, QC_E_SH>;
+  def : QC48StPat<store, QC_E_SW>;
+} // Predicates = [HasVendorXqcilo, IsRV32], AddedComplexity = 2
+
 let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
diff --git a/llvm/test/CodeGen/RISCV/qc-xqcilo.ll b/llvm/test/CodeGen/RISCV/qc-xqcilo.ll
new file mode 100644
index 0000000000000..fb06f21b3ab98
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/qc-xqcilo.ll
@@ -0,0 +1,143 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefixes=RV32I
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefixes=RV32IXQCILO
+
+define i32 @lb_ri(i8* %a) {
+; RV32I-LABEL: lb_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 2
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    lb a0, 1808(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: lb_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.lb a0, 10000(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i8, i8* %a, i32 10000
+  %2 = load i8, i8* %1
+  %3 = sext i8 %2 to i32
+  ret i32 %3
+}
+
+define i32 @lbu_ri(i8* %a) {
+; RV32I-LABEL: lbu_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 1048574
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    lbu a0, 192(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: lbu_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.lbu a0, -8000(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i8, i8* %a, i32 -8000
+  %2 = load i8, i8* %1
+  %3 = zext i8 %2 to i32
+  ret i32 %3
+}
+
+define i32 @lh_ri(i16* %a) {
+; RV32I-LABEL: lh_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 11
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    lhu a0, -612(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: lh_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.lhu a0, 44444(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i16, i16* %a, i32 22222
+  %2 = load i16, i16* %1
+  %3 = zext i16 %2 to i32
+  ret i32 %3
+}
+
+define i32 @lhu_ri(i16* %a) {
+; RV32I-LABEL: lhu_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a1, 1048570
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    lhu a0, 120(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: lhu_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.lhu a0, -24456(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i16, i16* %a, i32 -12228
+  %2 = load i16, i16* %1
+  %3 = zext i16 %2 to i32
+  ret i32 %3
+}
+
+define i32 @lw_ri(i32* %a) {
+; RV32I-LABEL: lw_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a0, a0, 2047
+; RV32I-NEXT:    lw a0, 1953(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: lw_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.lw a0, 4000(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i32, i32* %a, i32 1000
+  %2 = load i32, i32* %1
+  ret i32 %2
+}
+
+define void @sb_ri(i8* %a, i8 %b) {
+; RV32I-LABEL: sb_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 2
+; RV32I-NEXT:    add a0, a0, a2
+; RV32I-NEXT:    sb a1, 1808(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: sb_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.sb a1, 10000(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i8, i8* %a, i32 10000
+  store i8 %b, i8* %1
+  ret void
+}
+
+define void @sh_ri(i16* %a, i16 %b) {
+; RV32I-LABEL: sh_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 11
+; RV32I-NEXT:    add a0, a0, a2
+; RV32I-NEXT:    sh a1, -612(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: sh_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.sh a1, 44444(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i16, i16* %a, i32 22222
+  store i16 %b, i16* %1
+  ret void
+}
+
+define void @sw_ri(i32* %a, i32 %b) {
+; RV32I-LABEL: sw_ri:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi a0, a0, 2047
+; RV32I-NEXT:    sw a1, 1953(a0)
+; RV32I-NEXT:    ret
+;
+; RV32IXQCILO-LABEL: sw_ri:
+; RV32IXQCILO:       # %bb.0:
+; RV32IXQCILO-NEXT:    qc.e.sw a1, 4000(a0)
+; RV32IXQCILO-NEXT:    ret
+  %1 = getelementptr i32, i32* %a, i32 1000
+  store i32 %b, i32* %1
+  ret void
+}

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@hchandel hchandel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@svs-quic
Copy link
Contributor Author

The linux build failures seem unrelated. Going ahead and merging this.

@svs-quic svs-quic merged commit 40460a5 into llvm:main Apr 16, 2025
9 of 11 checks passed
@svs-quic svs-quic deleted the xqcilopat branch April 16, 2025 05:49
@llvm-ci
Copy link
Collaborator

llvm-ci commented Apr 16, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/20310

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: functionalities/thread/num_threads/TestNumThreads.py (115 of 2827)
PASS: lldb-api :: lang/cpp/virtual-functions/TestCppVirtualFunctions.py (116 of 2827)
PASS: lldb-api :: functionalities/step-avoids-no-debug/TestStepNoDebug.py (117 of 2827)
PASS: lldb-api :: functionalities/thread/exit_during_break/TestExitDuringBreak.py (118 of 2827)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/unordered/TestDataFormatterGenericUnordered.py (119 of 2827)
PASS: lldb-shell :: Commands/command-thread-siginfo.test (120 of 2827)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py (121 of 2827)
PASS: lldb-api :: tools/lldb-server/libraries-svr4/TestGdbRemoteLibrariesSvr4Support.py (122 of 2827)
PASS: lldb-api :: functionalities/postmortem/mach-core/TestMachCore.py (123 of 2827)
UNRESOLVED: lldb-api :: tools/lldb-dap/memory/TestDAP_memory.py (124 of 2827)
******************** TEST 'lldb-api :: tools/lldb-dap/memory/TestDAP_memory.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/memory -p TestDAP_memory.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 40460a5cf76c973a783fb2f5229e1076398df96e)
  clang revision 40460a5cf76c973a783fb2f5229e1076398df96e
  llvm revision 40460a5cf76c973a783fb2f5229e1076398df96e
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/memory
runCmd: settings clear -all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 

runCmd: settings set target.auto-apply-fixits false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants