Skip to content

Conversation

@lenary
Copy link
Member

@lenary lenary commented Apr 8, 2025

This adds qc.e.l<type> <reg>, <symbol> and qc.e.s<type> <reg>, <symbol>, <reg> pseudos for the corresponding Xqcilo instructions.

These emit as an AUIPC + (Standard) Load/Store pair, because this sequence is shorter and can be relaxed back into the equivalent Xqcilo load/store instruction in the right circumstances.

This adds `qc.e.l<type> <reg>, <symbol>` and `qc.e.s<type> <reg>,
<symbol>, <reg>` pseudos for the corresponding Xqcilo instructions.

These emit as an AUIPC + (Standard) Load/Store pair, because this
sequence is shorter and can be relaxed back into the equivalent Xqcilo
load/store instruction in the right circumstances.
@lenary lenary requested review from hchandel and svs-quic April 8, 2025 21:12
@llvmbot llvmbot added backend:RISC-V llvm:mc Machine (object) code labels Apr 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 8, 2025

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

@llvm/pr-subscribers-mc

Author: Sam Elliott (lenary)

Changes

This adds qc.e.l&lt;type&gt; &lt;reg&gt;, &lt;symbol&gt; and qc.e.s&lt;type&gt; &lt;reg&gt;, &lt;symbol&gt;, &lt;reg&gt; pseudos for the corresponding Xqcilo instructions.

These emit as an AUIPC + (Standard) Load/Store pair, because this sequence is shorter and can be relaxed back into the equivalent Xqcilo load/store instruction in the right circumstances.


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

4 Files Affected:

  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+17)
  • (added) llvm/test/MC/RISCV/xqcilo-pseudos-invalid.s (+70)
  • (added) llvm/test/MC/RISCV/xqcilo-pseudos-valid.s (+43)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index dba78fef0bad8..ac3f88f2c867b 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -3746,18 +3746,23 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
     emitLoadTLSGDAddress(Inst, IDLoc, Out);
     return false;
   case RISCV::PseudoLB:
+  case RISCV::PseudoQC_E_LB:
     emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
     return false;
   case RISCV::PseudoLBU:
+  case RISCV::PseudoQC_E_LBU:
     emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
     return false;
   case RISCV::PseudoLH:
+  case RISCV::PseudoQC_E_LH:
     emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
     return false;
   case RISCV::PseudoLHU:
+  case RISCV::PseudoQC_E_LHU:
     emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
     return false;
   case RISCV::PseudoLW:
+  case RISCV::PseudoQC_E_LW:
     emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
     return false;
   case RISCV::PseudoLWU:
@@ -3776,12 +3781,15 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
     emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
     return false;
   case RISCV::PseudoSB:
+  case RISCV::PseudoQC_E_SB:
     emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
     return false;
   case RISCV::PseudoSH:
+  case RISCV::PseudoQC_E_SH:
     emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
     return false;
   case RISCV::PseudoSW:
+  case RISCV::PseudoQC_E_SW:
     emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
     return false;
   case RISCV::PseudoSD:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index f762c4943f630..97d0d2d028ff1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1186,6 +1186,23 @@ def PseudoLongQC_E_BGEI : LongBcciPseudo<simm16nonzero, 10>;
 def PseudoLongQC_E_BLTUI : LongBcciPseudo<uimm16nonzero, 10>;
 def PseudoLongQC_E_BGEUI : LongBcciPseudo<uimm16nonzero, 10>;
 
+// Load/Store predicates with QC.E.* Mnemonics. These expand to an AUIPC +
+// (Standard) Load/Store pairs, as this sequence can materialize all 32-bit
+// addresses, and is shorter than e.g. an AUIPC + Xqcilo Load/Store pair.
+// These pairs can be turned back into Xqcilo instructions using linker
+// relaxation.
+let Predicates = [HasVendorXqcilo, IsRV32] in {
+def PseudoQC_E_LB : PseudoLoad<"qc.e.lb">;
+def PseudoQC_E_LBU : PseudoLoad<"qc.e.lbu">;
+def PseudoQC_E_LH : PseudoLoad<"qc.e.lh">;
+def PseudoQC_E_LHU : PseudoLoad<"qc.e.lhu">;
+def PseudoQC_E_LW : PseudoLoad<"qc.e.lw">;
+
+def PseudoQC_E_SB : PseudoStore<"qc.e.sb">;
+def PseudoQC_E_SH : PseudoStore<"qc.e.sh">;
+def PseudoQC_E_SW : PseudoStore<"qc.e.sw">;
+} // Predicates = [HasVendorXqcilo, IsRV32]
+
 //===----------------------------------------------------------------------===//
 // Code Gen Patterns
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/MC/RISCV/xqcilo-pseudos-invalid.s b/llvm/test/MC/RISCV/xqcilo-pseudos-invalid.s
new file mode 100644
index 0000000000000..b6da8e487152c
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilo-pseudos-invalid.s
@@ -0,0 +1,70 @@
+# Xqcilo - Qualcomm uC Large Offset Load Store extension
+# RUN: not llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo \
+# RUN:     2>&1 | FileCheck -check-prefixes=CHECK-ENABLED %s
+# RUN: not llvm-mc %s -triple=riscv32 -mattr=-experimental-xqcilo \
+# RUN:     2>&1 | FileCheck -check-prefixes=CHECK-DISABLED %s
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lb a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lb a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lbu a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lh a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lhu a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.lw a0, 0xf000
+
+# CHECK-ENABLED: [[@LINE+2]]:21: error: invalid operand for instruction
+# CHECK-DISABLED: [[@LINE+1]]:21: error: invalid operand for instruction
+qc.e.sb a0, 0xf000, t0
+
+# CHECK-ENABLED: [[@LINE+2]]:21: error: invalid operand for instruction
+# CHECK-DISABLED: [[@LINE+1]]:21: error: invalid operand for instruction
+qc.e.sh a0, 0xf000, t0
+
+# CHECK-ENABLED: [[@LINE+2]]:21: error: invalid operand for instruction
+# CHECK-DISABLED: [[@LINE+1]]:21: error: invalid operand for instruction
+qc.e.sw a0, 0xf000, t0
+
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.lb a0, undefined
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.lbu a0, undefined
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.lh a0, undefined
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.lhu a0, undefined
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.lw a0, undefined
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.sb a0, undefined, t0
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.sh a0, undefined, t0
+# CHECK-DISABLED: [[@LINE+1]]:1: error: instruction requires the following: 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
+qc.e.sw a0, undefined, t0
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.sb a0, undefined
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.sh a0, undefined
+
+# CHECK-ENABLED: [[@LINE+2]]:1: error: too few operands for instruction
+# CHECK-DISABLED: [[@LINE+1]]:1: error: too few operands for instruction
+qc.e.sw a0, undefined
diff --git a/llvm/test/MC/RISCV/xqcilo-pseudos-valid.s b/llvm/test/MC/RISCV/xqcilo-pseudos-valid.s
new file mode 100644
index 0000000000000..b8fc33dc9deb3
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilo-pseudos-valid.s
@@ -0,0 +1,43 @@
+# Xqcilo - Qualcomm uC Large Offset Load Store extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo \
+# RUN:     | FileCheck -check-prefixes=CHECK %s
+
+# CHECK-LABEL: .Lpcrel_hi0
+# CHECK-NEXT: auipc a0, %pcrel_hi(undefined)
+# CHECK-NEXT: lb a0, %pcrel_lo(.Lpcrel_hi0)(a0)
+qc.e.lb a0, undefined
+
+# CHECK-LABEL: .Lpcrel_hi1
+# CHECK-NEXT: auipc a0, %pcrel_hi(undefined)
+# CHECK-NEXT: lbu a0, %pcrel_lo(.Lpcrel_hi1)(a0)
+qc.e.lbu a0, undefined
+
+# CHECK-LABEL: .Lpcrel_hi2
+# CHECK-NEXT: auipc a0, %pcrel_hi(undefined)
+# CHECK-NEXT: lh a0, %pcrel_lo(.Lpcrel_hi2)(a0)
+qc.e.lh a0, undefined
+
+# CHECK-LABEL: .Lpcrel_hi3
+# CHECK-NEXT: auipc a0, %pcrel_hi(undefined)
+# CHECK-NEXT: lhu a0, %pcrel_lo(.Lpcrel_hi3)(a0)
+qc.e.lhu a0, undefined
+
+# CHECK-LABEL: .Lpcrel_hi4
+# CHECK-NEXT: auipc a0, %pcrel_hi(undefined)
+# CHECK-NEXT: lw a0, %pcrel_lo(.Lpcrel_hi4)(a0)
+qc.e.lw a0, undefined
+
+# CHECK-LABEL: .Lpcrel_hi5
+# CHECK-NEXT: auipc t0, %pcrel_hi(undefined)
+# CHECK-NEXT: sb a0, %pcrel_lo(.Lpcrel_hi5)(t0)
+qc.e.sb a0, undefined, t0
+
+# CHECK-LABEL: .Lpcrel_hi6
+# CHECK-NEXT: auipc t0, %pcrel_hi(undefined)
+# CHECK-NEXT: sh a0, %pcrel_lo(.Lpcrel_hi6)(t0)
+qc.e.sh a0, undefined, t0
+
+# CHECK-LABEL: .Lpcrel_hi7
+# CHECK-NEXT: auipc t0, %pcrel_hi(undefined)
+# CHECK-NEXT: sw a0, %pcrel_lo(.Lpcrel_hi7)(t0)
+qc.e.sw a0, undefined, t0

// (Standard) Load/Store pairs, as this sequence can materialize all 32-bit
// addresses, and is shorter than e.g. an AUIPC + Xqcilo Load/Store pair.
// These pairs can be turned back into Xqcilo instructions using linker
// Load/Store psuedos with QC.E.* Mnemonics. These expand to an AUIPC +
Copy link
Collaborator

Choose a reason for hiding this comment

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

pseudo*

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

@lenary lenary merged commit ad01e0a into llvm:main Apr 9, 2025
11 checks passed
@lenary lenary deleted the pr/riscv-xqcilo-psuedos branch June 16, 2025 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V llvm:mc Machine (object) code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants