Skip to content

Conversation

@topperc
Copy link
Collaborator

@topperc topperc commented Dec 22, 2025

These instructions can be used for fshl and fshr respectively.

These instructions can be used for fshl and fshr respectively.
@llvmbot
Copy link
Member

llvmbot commented Dec 22, 2025

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

Author: Craig Topper (topperc)

Changes

These instructions can be used for fshl and fshr respectively.


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

4 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoP.td (+6-1)
  • (modified) llvm/test/CodeGen/RISCV/rv32p.ll (+49)
  • (modified) llvm/test/CodeGen/RISCV/rv64p.ll (+49)
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 c9111a1a24f98..6be18e25086e8 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -60,3 +60,52 @@ 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 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
+  ret i64 %b
+}
+
+define i64 @slxi_i64(i64 %x) {
+; CHECK-LABEL: slxi_i64:
+; CHECK:       # %bb.0:
+; 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
+  ret i64 %a
+}
+
+define i64 @srx_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: srx_i64:
+; CHECK:       # %bb.0:
+; 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:    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 22dba6501f68c..39902dec66e64 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -99,3 +99,52 @@ 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 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
+  ret i128 %b
+}
+
+define i128 @slxi_i128(i128 %x) {
+; CHECK-LABEL: slxi_i128:
+; CHECK:       # %bb.0:
+; 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
+  ret i128 %a
+}
+
+define i128 @srx_i128(i128 %x, i128 %y) {
+; CHECK-LABEL: srx_i128:
+; CHECK:       # %bb.0:
+; 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:    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
+}

Copy link
Member

@4vtomat 4vtomat left a comment

Choose a reason for hiding this comment

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

LGTM~

@topperc topperc merged commit f4ded95 into llvm:main Dec 23, 2025
10 checks passed
valadaptive pushed a commit to valadaptive/llvm-project that referenced this pull request Dec 24, 2025
These instructions can be used for fshl and fshr respectively.
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.

3 participants