[llvm] [RISCV] Add ISel patterns for Xqcilia instructions (PR #135724)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 14 18:37:08 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Sudharsan Veeravalli (svs-quic)

<details>
<summary>Changes</summary>

This patch adds instruction selection patterns for generating the long immediate arithmetic instructions.

We prefer generating instructions that have a 26 bit immediate to a 32 bit immediate given that both are of the same size but the former might be easier to register allocate for. Base RISC-V arithmetic instructions will be preferred, when applicable.

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


2 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+40-1) 
- (added) llvm/test/CodeGen/RISCV/xqcilia.ll (+108) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 4ac17c8283866..d915177278828 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -125,7 +125,8 @@ class BareSImmNAsmOperand<int width>
 
 // 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
 // sign-/zero-extension. This is represented internally as a signed 32-bit value.
-def bare_simm32 : RISCVOp<XLenVT> {
+def bare_simm32 : RISCVOp<XLenVT>,
+                  ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]> {
   let ParserMatchClass = BareSImmNAsmOperand<32>;
   let EncoderMethod = "getImmOpValue";
   let DecoderMethod = "decodeSImmOperand<32>";
@@ -1245,5 +1246,43 @@ def PseudoQC_E_JAL: Pseudo<(outs), (ins pseudo_qc_jump_symbol:$func), [],
 // Code Gen Patterns
 //===----------------------------------------------------------------------===//
 
+/// Generic pattern classes
+
+class PatGprNoX0Simm26<SDPatternOperator OpNode, RVInst48 Inst>
+    : Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), simm26:$imm)),
+          (Inst GPRNoX0:$rs1, simm26:$imm)>;
+
+class PatGprNoX0Imm32<SDPatternOperator OpNode, RVInst48 Inst>
+    : Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), bare_simm32:$imm)),
+          (Inst GPRNoX0:$rs1, bare_simm32:$imm)>;
+
+/// Simple arithmetic operations
+
+let Predicates = [HasVendorXqcilia, IsRV32] in {
+//
+// LLVM sorts by number of covered nodes plus AddedComplexity,
+// highest first. All these patterns cover the same number of
+// nodes (but the immediate leafs are different sizes), so we use
+// AddedComplexity to deprioritise the longer immediate encodings,
+// and achieve the following order for pattern matching:
+// 1. Base RISC-V arithmetic instructions
+// 2. Xqcilia instructions with 26 bit immediate
+// 3. Xqcilia instructions with 32 bit immediate
+//
+let AddedComplexity = -2 in {
+def : PatGprNoX0Imm32<add, QC_E_ADDAI>;
+def : PatGprNoX0Imm32<and, QC_E_ANDAI>;
+def : PatGprNoX0Imm32<or, QC_E_ORAI>;
+def : PatGprNoX0Imm32<xor, QC_E_XORAI>;
+} // AddedComplexity = -2
+
+let AddedComplexity = -1 in {
+def : PatGprNoX0Simm26<add, QC_E_ADDI>;
+def : PatGprNoX0Simm26<and, QC_E_ANDI>;
+def : PatGprNoX0Simm26<or, QC_E_ORI>;
+def : PatGprNoX0Simm26<xor, QC_E_XORI>;
+} // AddedComplexity = -1
+} // Predicates = [HasVendorXqcilia, IsRV32]
+
 let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
diff --git a/llvm/test/CodeGen/RISCV/xqcilia.ll b/llvm/test/CodeGen/RISCV/xqcilia.ll
new file mode 100644
index 0000000000000..0f14044d62dc8
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xqcilia.ll
@@ -0,0 +1,108 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test that we are able to generate the Xqcilia instructions
+; RUN: llc < %s -mtriple=riscv32 | FileCheck %s -check-prefix=RV32I
+; RUN: llc < %s -mtriple=riscv32 -mattr=+experimental-xqcilia | FileCheck %s -check-prefix=RV32XQCILIA
+
+define i32 @add(i32 %a, i32 %b) {
+; RV32I-LABEL: add:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 65536
+; RV32I-NEXT:    add a0, a0, a2
+; RV32I-NEXT:    lui a2, 573
+; RV32I-NEXT:    addi a2, a2, -1330
+; RV32I-NEXT:    add a1, a1, a2
+; RV32I-NEXT:    and a0, a1, a0
+; RV32I-NEXT:    addi a0, a0, 13
+; RV32I-NEXT:    ret
+;
+; RV32XQCILIA-LABEL: add:
+; RV32XQCILIA:       # %bb.0:
+; RV32XQCILIA-NEXT:    qc.e.addi a1, a1, 2345678
+; RV32XQCILIA-NEXT:    qc.e.addai a0, 268435456
+; RV32XQCILIA-NEXT:    and a0, a0, a1
+; RV32XQCILIA-NEXT:    addi a0, a0, 13
+; RV32XQCILIA-NEXT:    ret
+ %addai = add i32 %a, 268435456
+ %add = add i32 %b, 2345678
+ %and = and i32 %add, %addai
+ %res = add i32 %and, 13
+ ret i32 %res
+}
+
+define i32 @and(i32 %a, i32 %b) {
+; RV32I-LABEL: and:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 65536
+; RV32I-NEXT:    and a0, a0, a2
+; RV32I-NEXT:    lui a2, 573
+; RV32I-NEXT:    addi a2, a2, -1330
+; RV32I-NEXT:    and a1, a1, a2
+; RV32I-NEXT:    srl a0, a1, a0
+; RV32I-NEXT:    andi a0, a0, 10
+; RV32I-NEXT:    ret
+;
+; RV32XQCILIA-LABEL: and:
+; RV32XQCILIA:       # %bb.0:
+; RV32XQCILIA-NEXT:    qc.e.andi a1, a1, 2345678
+; RV32XQCILIA-NEXT:    qc.e.andai a0, 268435456
+; RV32XQCILIA-NEXT:    srl a0, a1, a0
+; RV32XQCILIA-NEXT:    andi a0, a0, 10
+; RV32XQCILIA-NEXT:    ret
+ %andai = and i32 %a, 268435456
+ %and = and i32 %b, 2345678
+ %srl = lshr i32 %and, %andai
+ %res = and i32 %srl, 10
+ ret i32 %res
+}
+
+define i32 @or(i32 %a, i32 %b) {
+; RV32I-LABEL: or:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 65536
+; RV32I-NEXT:    or a0, a0, a2
+; RV32I-NEXT:    lui a2, 573
+; RV32I-NEXT:    addi a2, a2, -1330
+; RV32I-NEXT:    or a1, a1, a2
+; RV32I-NEXT:    add a0, a1, a0
+; RV32I-NEXT:    ori a0, a0, 13
+; RV32I-NEXT:    ret
+;
+; RV32XQCILIA-LABEL: or:
+; RV32XQCILIA:       # %bb.0:
+; RV32XQCILIA-NEXT:    qc.e.ori a1, a1, 2345678
+; RV32XQCILIA-NEXT:    qc.e.orai a0, 268435456
+; RV32XQCILIA-NEXT:    add a0, a0, a1
+; RV32XQCILIA-NEXT:    ori a0, a0, 13
+; RV32XQCILIA-NEXT:    ret
+ %orai = or i32 %a, 268435456
+ %or = or i32 %b, 2345678
+ %add = add i32 %or, %orai
+ %res = or i32 %add, 13
+ ret i32 %res
+}
+
+define i32 @xor(i32 %a, i32 %b) {
+; RV32I-LABEL: xor:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    lui a2, 65536
+; RV32I-NEXT:    xor a0, a0, a2
+; RV32I-NEXT:    lui a2, 573
+; RV32I-NEXT:    addi a2, a2, -1330
+; RV32I-NEXT:    xor a1, a1, a2
+; RV32I-NEXT:    add a0, a1, a0
+; RV32I-NEXT:    xori a0, a0, 13
+; RV32I-NEXT:    ret
+;
+; RV32XQCILIA-LABEL: xor:
+; RV32XQCILIA:       # %bb.0:
+; RV32XQCILIA-NEXT:    qc.e.xori a1, a1, 2345678
+; RV32XQCILIA-NEXT:    qc.e.xorai a0, 268435456
+; RV32XQCILIA-NEXT:    add a0, a0, a1
+; RV32XQCILIA-NEXT:    xori a0, a0, 13
+; RV32XQCILIA-NEXT:    ret
+ %xorai = xor i32 %a, 268435456
+ %xor = xor i32 %b, 2345678
+ %add = add i32 %xor, %xorai
+ %res = xor i32 %add, 13
+ ret i32 %res
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/135724


More information about the llvm-commits mailing list