[llvm] [RISCV] Support srx/slx for P extension. (PR #173225)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 22 00:06:24 PST 2025
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/173225
These instructions can be used for fshl and fshr respectively.
>From 7ebea8abba565bc26a861e1c22d8dd99408f4346 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Sun, 21 Dec 2025 23:40:05 -0800
Subject: [PATCH 1/2] Pre-commit tests
---
llvm/test/CodeGen/RISCV/rv32p.ll | 56 ++++++++++++++++++++++++++++++++
llvm/test/CodeGen/RISCV/rv64p.ll | 56 ++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+)
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index c9111a1a24f98..b942b6ea87970 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -60,3 +60,59 @@ define void @pli_b_store_i32(ptr %p) {
store i32 u0x41414141, ptr %p
ret void
}
+
+define i64 @slx_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: slx_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: sll a1, a1, a2
+; CHECK-NEXT: srli a3, a0, 1
+; CHECK-NEXT: andi a4, a2, 31
+; CHECK-NEXT: xori a4, a4, 31
+; CHECK-NEXT: srl a3, a3, a4
+; CHECK-NEXT: or a1, a1, a3
+; CHECK-NEXT: sll a0, a0, a2
+; CHECK-NEXT: ret
+ %a = and i64 %y, 31
+ %b = shl i64 %x, %a
+ ret i64 %b
+}
+
+define i64 @slxi_i64(i64 %x) {
+; CHECK-LABEL: slxi_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a2, a0, 7
+; CHECK-NEXT: slli a1, a1, 25
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: slli a0, a0, 25
+; CHECK-NEXT: ret
+ %a = shl i64 %x, 25
+ ret i64 %a
+}
+
+define i64 @srx_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: srx_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srl a0, a0, a2
+; CHECK-NEXT: slli a3, a1, 1
+; CHECK-NEXT: andi a4, a2, 31
+; CHECK-NEXT: xori a4, a4, 31
+; CHECK-NEXT: sll a3, a3, a4
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: srl a1, a1, a2
+; CHECK-NEXT: ret
+ %a = and i64 %y, 31
+ %b = lshr i64 %x, %a
+ ret i64 %b
+}
+
+define i64 @srxi_i64(i64 %x) {
+; CHECK-LABEL: srxi_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slli a2, a1, 7
+; CHECK-NEXT: srli a0, a0, 25
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: srli a1, a1, 25
+; CHECK-NEXT: ret
+ %a = lshr i64 %x, 25
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index 22dba6501f68c..269821d152c96 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -99,3 +99,59 @@ define void @pli_b_store_i32(ptr %p) {
store i32 u0x41414141, ptr %p
ret void
}
+
+define i128 @slx_i128(i128 %x, i128 %y) {
+; CHECK-LABEL: slx_i128:
+; CHECK: # %bb.0:
+; CHECK-NEXT: sll a1, a1, a2
+; CHECK-NEXT: srli a3, a0, 1
+; CHECK-NEXT: andi a4, a2, 63
+; CHECK-NEXT: xori a4, a4, 63
+; CHECK-NEXT: srl a3, a3, a4
+; CHECK-NEXT: or a1, a1, a3
+; CHECK-NEXT: sll a0, a0, a2
+; CHECK-NEXT: ret
+ %a = and i128 %y, 63
+ %b = shl i128 %x, %a
+ ret i128 %b
+}
+
+define i128 @slxi_i128(i128 %x) {
+; CHECK-LABEL: slxi_i128:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srli a2, a0, 15
+; CHECK-NEXT: slli a1, a1, 49
+; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: slli a0, a0, 49
+; CHECK-NEXT: ret
+ %a = shl i128 %x, 49
+ ret i128 %a
+}
+
+define i128 @srx_i128(i128 %x, i128 %y) {
+; CHECK-LABEL: srx_i128:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srl a0, a0, a2
+; CHECK-NEXT: slli a3, a1, 1
+; CHECK-NEXT: andi a4, a2, 63
+; CHECK-NEXT: xori a4, a4, 63
+; CHECK-NEXT: sll a3, a3, a4
+; CHECK-NEXT: or a0, a0, a3
+; CHECK-NEXT: srl a1, a1, a2
+; CHECK-NEXT: ret
+ %a = and i128 %y, 63
+ %b = lshr i128 %x, %a
+ ret i128 %b
+}
+
+define i128 @srxi_i128(i128 %x) {
+; CHECK-LABEL: srxi_i128:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slli a2, a1, 15
+; CHECK-NEXT: srli a0, a0, 49
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: srli a1, a1, 49
+; CHECK-NEXT: ret
+ %a = lshr i128 %x, 49
+ ret i128 %a
+}
>From 5e0d6aaa924c0a474a72e82d257641eaff5888cc Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 22 Dec 2025 00:03:27 -0800
Subject: [PATCH 2/2] [RISCV] Support srx/slx for P extension.
These instructions can be used for fshl and fshr respectively.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 3 ++
llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 7 ++++-
llvm/test/CodeGen/RISCV/rv32p.ll | 33 ++++++++-------------
llvm/test/CodeGen/RISCV/rv64p.ll | 33 ++++++++-------------
4 files changed, 35 insertions(+), 41 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7dfb5cd0a9e6c..23a24d184e508 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -398,6 +398,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction({ISD::ROTL, ISD::ROTR}, XLenVT, Expand);
}
+ if (Subtarget.hasStdExtP())
+ setOperationAction({ISD::FSHL, ISD::FSHR}, XLenVT, Legal);
+
setOperationAction(ISD::BSWAP, XLenVT,
Subtarget.hasREV8Like() ? Legal : Expand);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 060161f3a8fa0..92a9c06fc534b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -690,7 +690,7 @@ let Predicates = [HasStdExtP, IsRV64] in {
} // Predicates = [HasStdExtP, IsRV64]
let Predicates = [HasStdExtP] in {
- def SLX : RVPBinary_rr<0b0001, 0b11, 0b001, "slx">;
+ def SLX : RVPTernary_rrr<0b0001, 0b11, 0b001, "slx">;
def PMUL_H_B01 : RVPBinary_rr<0b0010, 0b00, 0b001, "pmul.h.b01">;
@@ -1474,6 +1474,11 @@ def riscv_pmulhsu : RVSDNode<"PMULHSU", SDT_RISCVPBinOp>;
let Predicates = [HasStdExtP] in {
def : PatGpr<abs, ABS>;
+ def : Pat<(XLenVT (fshl GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)),
+ (SLX GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)>;
+ def : Pat<(XLenVT (fshr GPR:$rs1, GPR:$rd, shiftMaskXLen:$rs2)),
+ (SRX GPR:$rd, GPR:$rs1, shiftMaskXLen:$rs2)>;
+
// Basic 8-bit arithmetic patterns
def: Pat<(XLenVecI8VT (add GPR:$rs1, GPR:$rs2)), (PADD_B GPR:$rs1, GPR:$rs2)>;
def: Pat<(XLenVecI8VT (sub GPR:$rs1, GPR:$rs2)), (PSUB_B GPR:$rs1, GPR:$rs2)>;
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index b942b6ea87970..6be18e25086e8 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -64,13 +64,9 @@ define void @pli_b_store_i32(ptr %p) {
define i64 @slx_i64(i64 %x, i64 %y) {
; CHECK-LABEL: slx_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: sll a1, a1, a2
-; CHECK-NEXT: srli a3, a0, 1
-; CHECK-NEXT: andi a4, a2, 31
-; CHECK-NEXT: xori a4, a4, 31
-; CHECK-NEXT: srl a3, a3, a4
-; CHECK-NEXT: or a1, a1, a3
-; CHECK-NEXT: sll a0, a0, a2
+; CHECK-NEXT: sll a3, a0, a2
+; CHECK-NEXT: slx a1, a0, a2
+; CHECK-NEXT: mv a0, a3
; CHECK-NEXT: ret
%a = and i64 %y, 31
%b = shl i64 %x, %a
@@ -80,9 +76,8 @@ define i64 @slx_i64(i64 %x, i64 %y) {
define i64 @slxi_i64(i64 %x) {
; CHECK-LABEL: slxi_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a2, a0, 7
-; CHECK-NEXT: slli a1, a1, 25
-; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: li a2, 25
+; CHECK-NEXT: slx a1, a0, a2
; CHECK-NEXT: slli a0, a0, 25
; CHECK-NEXT: ret
%a = shl i64 %x, 25
@@ -92,26 +87,24 @@ define i64 @slxi_i64(i64 %x) {
define i64 @srx_i64(i64 %x, i64 %y) {
; CHECK-LABEL: srx_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: srl a0, a0, a2
-; CHECK-NEXT: slli a3, a1, 1
-; CHECK-NEXT: andi a4, a2, 31
-; CHECK-NEXT: xori a4, a4, 31
-; CHECK-NEXT: sll a3, a3, a4
-; CHECK-NEXT: or a0, a0, a3
-; CHECK-NEXT: srl a1, a1, a2
+; CHECK-NEXT: srl a3, a1, a2
+; CHECK-NEXT: srx a0, a1, a2
+; CHECK-NEXT: mv a1, a3
; CHECK-NEXT: ret
%a = and i64 %y, 31
%b = lshr i64 %x, %a
ret i64 %b
}
+; FIXME: Using srx instead of slx would avoid the mv.
define i64 @srxi_i64(i64 %x) {
; CHECK-LABEL: srxi_i64:
; CHECK: # %bb.0:
-; CHECK-NEXT: slli a2, a1, 7
-; CHECK-NEXT: srli a0, a0, 25
-; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: mv a2, a1
+; CHECK-NEXT: li a3, 7
; CHECK-NEXT: srli a1, a1, 25
+; CHECK-NEXT: slx a2, a0, a3
+; CHECK-NEXT: mv a0, a2
; CHECK-NEXT: ret
%a = lshr i64 %x, 25
ret i64 %a
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index 269821d152c96..39902dec66e64 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -103,13 +103,9 @@ define void @pli_b_store_i32(ptr %p) {
define i128 @slx_i128(i128 %x, i128 %y) {
; CHECK-LABEL: slx_i128:
; CHECK: # %bb.0:
-; CHECK-NEXT: sll a1, a1, a2
-; CHECK-NEXT: srli a3, a0, 1
-; CHECK-NEXT: andi a4, a2, 63
-; CHECK-NEXT: xori a4, a4, 63
-; CHECK-NEXT: srl a3, a3, a4
-; CHECK-NEXT: or a1, a1, a3
-; CHECK-NEXT: sll a0, a0, a2
+; CHECK-NEXT: sll a3, a0, a2
+; CHECK-NEXT: slx a1, a0, a2
+; CHECK-NEXT: mv a0, a3
; CHECK-NEXT: ret
%a = and i128 %y, 63
%b = shl i128 %x, %a
@@ -119,9 +115,8 @@ define i128 @slx_i128(i128 %x, i128 %y) {
define i128 @slxi_i128(i128 %x) {
; CHECK-LABEL: slxi_i128:
; CHECK: # %bb.0:
-; CHECK-NEXT: srli a2, a0, 15
-; CHECK-NEXT: slli a1, a1, 49
-; CHECK-NEXT: or a1, a1, a2
+; CHECK-NEXT: li a2, 49
+; CHECK-NEXT: slx a1, a0, a2
; CHECK-NEXT: slli a0, a0, 49
; CHECK-NEXT: ret
%a = shl i128 %x, 49
@@ -131,26 +126,24 @@ define i128 @slxi_i128(i128 %x) {
define i128 @srx_i128(i128 %x, i128 %y) {
; CHECK-LABEL: srx_i128:
; CHECK: # %bb.0:
-; CHECK-NEXT: srl a0, a0, a2
-; CHECK-NEXT: slli a3, a1, 1
-; CHECK-NEXT: andi a4, a2, 63
-; CHECK-NEXT: xori a4, a4, 63
-; CHECK-NEXT: sll a3, a3, a4
-; CHECK-NEXT: or a0, a0, a3
-; CHECK-NEXT: srl a1, a1, a2
+; CHECK-NEXT: srl a3, a1, a2
+; CHECK-NEXT: srx a0, a1, a2
+; CHECK-NEXT: mv a1, a3
; CHECK-NEXT: ret
%a = and i128 %y, 63
%b = lshr i128 %x, %a
ret i128 %b
}
+; FIXME: Using srx instead of slx would avoid the mv.
define i128 @srxi_i128(i128 %x) {
; CHECK-LABEL: srxi_i128:
; CHECK: # %bb.0:
-; CHECK-NEXT: slli a2, a1, 15
-; CHECK-NEXT: srli a0, a0, 49
-; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: mv a2, a1
+; CHECK-NEXT: li a3, 15
; CHECK-NEXT: srli a1, a1, 49
+; CHECK-NEXT: slx a2, a0, a3
+; CHECK-NEXT: mv a0, a2
; CHECK-NEXT: ret
%a = lshr i128 %x, 49
ret i128 %a
More information about the llvm-commits
mailing list