[llvm] [RISCV] Implement codegen for XAndesPerf lea instructions (PR #137925)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 29 22:38:43 PDT 2025


https://github.com/tclin914 created https://github.com/llvm/llvm-project/pull/137925

This patch add the patterns for generating XAndesPerf lea instructions.

The operation of LEA family instructions is:

  rd = rs1 + rs2 * (the number of bytes)

The variants with *.ze suffix are RV64 only and its operation is:

  rd = rs1 + ZE32(rs2[31:0]) * (the number of bytes)

>From 253317e0c265ec77929ecedf503bbc1cf183205b Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Thu, 17 Apr 2025 16:55:00 +0800
Subject: [PATCH] [RISCV] Implement codegen for XAndesPerf lea instructions

This patch add the patterns for generating XAndesPerf lea instructions.

The operation of LEA family instructions is:

  rd = rs1 + rs2 * (the number of bytes)

The variants with *.ze suffix are RV64 only and its operation is:

  rd = rs1 + ZE32(rs2[31:0]) * (the number of bytes)
---
 llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 25 ++++++++++
 llvm/test/CodeGen/RISCV/rv32xandesperf.ll     | 33 +++++++++++++
 llvm/test/CodeGen/RISCV/rv64xandesperf.ll     | 46 +++++++++++++++++++
 3 files changed, 104 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/rv32xandesperf.ll
 create mode 100644 llvm/test/CodeGen/RISCV/rv64xandesperf.ll

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 2ec768435259c..e59a7c9353b8a 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -356,3 +356,28 @@ def NDS_LDGP  : NDSRVInstLDGP<0b011, "nds.ldgp">;
 def NDS_SDGP  : NDSRVInstSDGP<0b111, "nds.sdgp">;
 } // Predicates = [HasVendorXAndesPerf, IsRV64]
 } // DecoderNamespace = "XAndes"
+
+// Patterns
+
+let Predicates = [HasVendorXAndesPerf] in {
+class NDS_LEAPat<int shamt, RVInstR Inst>
+    : Pat<(add (XLenVT GPR:$rs1), (shl GPR:$rs2, (XLenVT shamt))),
+          (Inst GPR:$rs1, GPR:$rs2)>;
+
+def : NDS_LEAPat<1, NDS_LEA_H>;
+def : NDS_LEAPat<2, NDS_LEA_W>;
+def : NDS_LEAPat<3, NDS_LEA_D>;
+} // Predicates = [HasVendorXAndesPerf]
+
+let Predicates = [HasVendorXAndesPerf, IsRV64] in {
+def : Pat<(add (XLenVT GPR:$rs1), (zexti32 (i64 GPR:$rs2))),
+          (NDS_LEA_B_ZE GPR:$rs1, GPR:$rs2)>;
+
+class NDS_LEA_ZEPat<int shamt, RVInstR Inst>
+    : Pat<(add GPR:$rs1, (shl (zexti32 (XLenVT GPR:$rs2)), (XLenVT shamt))),
+          (Inst GPR:$rs1, GPR:$rs2)>;
+
+def : NDS_LEA_ZEPat<1, NDS_LEA_H_ZE>;
+def : NDS_LEA_ZEPat<2, NDS_LEA_W_ZE>;
+def : NDS_LEA_ZEPat<3, NDS_LEA_D_ZE>;
+} // Predicates = [HasVendorXAndesPerf, IsRV64]
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
new file mode 100644
index 0000000000000..e99c9ee5af587
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -mtriple=riscv32 -mattr=+xandesperf -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define i32 @lea_h(i32 %a, i32 %b) {
+; CHECK-LABEL: lea_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.h a0, a0, a1
+; CHECK-NEXT:    ret
+  %shl = shl i32 %b, 1
+  %ret = add i32 %a, %shl
+  ret i32 %ret
+}
+
+define i32 @lea_w(i32 %a, i32 %b) {
+; CHECK-LABEL: lea_w:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.w a0, a0, a1
+; CHECK-NEXT:    ret
+  %shl = shl i32 %b, 2
+  %ret = add i32 %a, %shl
+  ret i32 %ret
+}
+
+define i32 @lea_d(i32 %a, i32 %b) {
+; CHECK-LABEL: lea_d:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.d a0, a0, a1
+; CHECK-NEXT:    ret
+  %shl = shl i32 %b, 3
+  %ret = add i32 %a, %shl
+  ret i32 %ret
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
new file mode 100644
index 0000000000000..6349272847a4a
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -0,0 +1,46 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv64 -mattr=+xandesperf -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define i64 @lea_b_ze(i32 %a, i64 %b) {
+; CHECK-LABEL: lea_b_ze:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.b.ze a0, a1, a0
+; CHECK-NEXT:    ret
+  %conv = zext i32 %a to i64
+  %add = add i64 %conv, %b
+  ret i64 %add
+}
+
+define i64 @lea_h_ze(i32 %a, i64 %b) {
+; CHECK-LABEL: lea_h_ze:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.h.ze a0, a1, a0
+; CHECK-NEXT:    ret
+  %conv = zext i32 %a to i64
+  %shl = shl nuw nsw i64 %conv, 1
+  %add = add i64 %shl, %b
+  ret i64 %add
+}
+
+define i64 @lea_w_ze(i32 %a, i64 %b) {
+; CHECK-LABEL: lea_w_ze:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.w.ze a0, a1, a0
+; CHECK-NEXT:    ret
+  %conv = zext i32 %a to i64
+  %shl = shl nuw nsw i64 %conv, 2
+  %add = add i64 %shl, %b
+  ret i64 %add
+}
+
+define i64 @lea_d_ze(i32 %a, i64 %b) {
+; CHECK-LABEL: lea_d_ze:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.lea.d.ze a0, a1, a0
+; CHECK-NEXT:    ret
+  %conv = zext i32 %a to i64
+  %shl = shl nuw nsw i64 %conv, 3
+  %add = add i64 %shl, %b
+  ret i64 %add
+}



More information about the llvm-commits mailing list