[llvm] [RISCV] Use ADDD for GPR Pair Move with P (PR #180671)

via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 9 19:50:06 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Sam Elliott (lenary)

<details>
<summary>Changes</summary>



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


2 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+17-7) 
- (modified) llvm/test/CodeGen/RISCV/make-compressible-zilsd.mir (+51-33) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 2156d1919ddbe..14e85d9dbd0da 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -531,13 +531,23 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
   }
 
   if (RISCV::GPRPairRegClass.contains(DstReg, SrcReg)) {
-    if (STI.isRV32() && STI.hasStdExtZdinx()) {
-      // On RV32_Zdinx, FMV.D will move a pair of registers to another pair of
-      // registers, in one instruction.
-      BuildMI(MBB, MBBI, DL, get(RISCV::FSGNJ_D_IN32X), DstReg)
-          .addReg(SrcReg, getRenamableRegState(RenamableSrc))
-          .addReg(SrcReg, KillFlag | getRenamableRegState(RenamableSrc));
-      return;
+    if (STI.isRV32()) {
+      if (STI.hasStdExtZdinx()) {
+        // On RV32_Zdinx, FMV.D will move a pair of registers to another pair of
+        // registers, in one instruction.
+        BuildMI(MBB, MBBI, DL, get(RISCV::FSGNJ_D_IN32X), DstReg)
+            .addReg(SrcReg, getRenamableRegState(RenamableSrc))
+            .addReg(SrcReg, KillFlag | getRenamableRegState(RenamableSrc));
+        return;
+      }
+
+      if (STI.hasStdExtP()) {
+        // On RV32P, `addd` is a GPR Pair Add
+        BuildMI(MBB, MBBI, DL, get(RISCV::ADDD), DstReg)
+          .addReg(SrcReg, KillFlag | getRenamableRegState(RenamableSrc))
+          .addReg(RISCV::X0_Pair);
+        return;
+      }
     }
 
     MCRegister EvenReg = TRI->getSubReg(SrcReg, RISCV::sub_gpr_even);
diff --git a/llvm/test/CodeGen/RISCV/make-compressible-zilsd.mir b/llvm/test/CodeGen/RISCV/make-compressible-zilsd.mir
index 6dc6cf7d1393e..897f215cee525 100644
--- a/llvm/test/CodeGen/RISCV/make-compressible-zilsd.mir
+++ b/llvm/test/CodeGen/RISCV/make-compressible-zilsd.mir
@@ -1,8 +1,10 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 # RUN: llc -o - %s -mtriple=riscv32 -mattr=+zilsd,+zclsd,+zdinx -simplify-mir \
-# RUN:   -run-pass=riscv-make-compressible | FileCheck --check-prefixes=RV32 %s
+# RUN:   -run-pass=riscv-make-compressible | FileCheck --check-prefixes=RV32,RV32_NOP %s
+# RUN: llc -o - %s -mtriple=riscv32 -mattr=+zilsd,+zclsd,+experimental-p -simplify-mir \
+# RUN:   -run-pass=riscv-make-compressible | FileCheck --check-prefixes=RV32,RV32_P %s
 --- |
-  define void @store_common_value_double(ptr %a, ptr %b, ptr %c, i32 %d, double %e, double %f) #0 {
+  define void @store_common_value_double(ptr %a, ptr %b, ptr %c, i32 %d, double %e, double %f) minsize {
   entry:
     store double %f, ptr %a, align 8
     store double %f, ptr %b, align 8
@@ -10,7 +12,7 @@
     ret void
   }
 
-  define void @store_common_value_double_zero(ptr %a, ptr %b, ptr %c) #0 {
+  define void @store_common_value_double_zero(ptr %a, ptr %b, ptr %c) minsize {
   entry:
     store double 0.0, ptr %a, align 8
     store double 0.0, ptr %b, align 8
@@ -18,7 +20,7 @@
     ret void
   }
 
-  define void @store_common_ptr_double(double %a, double %b, double %d, ptr %p) #0 {
+  define void @store_common_ptr_double(double %a, double %b, double %d, ptr %p) minsize {
   entry:
     store volatile double %a, ptr %p, align 8
     store volatile double %b, ptr %p, align 8
@@ -26,7 +28,7 @@
     ret void
   }
 
-  define void @load_common_ptr_double(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, ptr %g) #0 {
+  define void @load_common_ptr_double(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, ptr %g) minsize {
   entry:
     %0 = load double, ptr %g, align 8
     %arrayidx1 = getelementptr inbounds { double, double, i32 }, ptr %g, i32 0, i32 1
@@ -37,9 +39,9 @@
     ret void
   }
 
-  declare void @load_common_ptr_double_1(double, double, double) #0
+  declare void @load_common_ptr_double_1(double, double, double) minsize
 
-  define void @store_large_offset_double(ptr %p, i32 %dummy, double %a, double %b, double %c) #0 {
+  define void @store_large_offset_double(ptr %p, i32 %dummy, double %a, double %b, double %c) minsize {
   entry:
     %0 = getelementptr inbounds double, ptr %p, i32 100
     store volatile double %a, ptr %0, align 8
@@ -50,7 +52,7 @@
     ret void
   }
 
-  define void @load_large_offset_double(i32 %a, i32 %b, i32 %c, i32 %d, ptr %p) #0 {
+  define void @load_large_offset_double(i32 %a, i32 %b, i32 %c, i32 %d, ptr %p) minsize {
   entry:
     %arrayidx = getelementptr inbounds { [102 x double], i32 }, ptr %p, i32 0, i32 0, i32 100
     %0 = load double, ptr %arrayidx, align 8
@@ -62,34 +64,34 @@
     ret void
   }
 
-  declare void @load_large_offset_double_1(double, double) #0
+  declare void @load_large_offset_double_1(double, double) minsize
 
-  define void @store_common_value_double_no_opt(ptr %a, i32 %b, double %c, double %d, double %e) #0 {
+  define void @store_common_value_double_no_opt(ptr %a, i32 %b, double %c, double %d, double %e) minsize {
   entry:
     store double %e, ptr %a, align 8
     ret void
   }
 
-  define void @store_common_value_double_no_opt2(ptr %a, i32 %b, double %c, double %d, double %e) #0 {
+  define void @store_common_value_double_no_opt2(ptr %a, i32 %b, double %c, double %d, double %e) minsize {
   entry:
     store volatile double %e, ptr %a, align 8
     store volatile double %e, ptr %a, align 8
     ret void
   }
 
-  define void @store_common_ptr_double_no_opt(double %a, i32 %b, i32 %c, i32 %d, i32 %e, ptr %p) #0 {
+  define void @store_common_ptr_double_no_opt(double %a, i32 %b, i32 %c, i32 %d, i32 %e, ptr %p) minsize {
   entry:
     store volatile double %a, ptr %p, align 8
     ret void
   }
 
-  define double @load_common_ptr_double_no_opt(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, ptr %g) #0 {
+  define double @load_common_ptr_double_no_opt(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, ptr %g) minsize {
   entry:
     %0 = load double, ptr %g, align 8
     ret double %0
   }
 
-  define void @store_large_offset_double_no_opt(ptr %p, double %a, double %b) #0 {
+  define void @store_large_offset_double_no_opt(ptr %p, double %a, double %b) minsize {
   entry:
     %0 = getelementptr inbounds double, ptr %p, i32 100
     store volatile double %a, ptr %0, align 8
@@ -98,7 +100,7 @@
     ret void
   }
 
-  define { double, double } @load_large_offset_double_no_opt(ptr %p) #0 {
+  define { double, double } @load_large_offset_double_no_opt(ptr %p) minsize {
   entry:
     %arrayidx = getelementptr inbounds double, ptr %p, i32 100
     %0 = load double, ptr %arrayidx, align 8
@@ -108,8 +110,6 @@
     %3 = insertvalue { double, double } %2, double %1, 1
     ret { double, double } %3
   }
-
-  attributes #0 = { minsize "target-features"="+zilsd,+zdinx" }
 ...
 ---
 name:            store_common_value_double
@@ -118,14 +118,23 @@ body:             |
   bb.0.entry:
     liveins: $x10, $x11, $x12, $x16, $x17
 
-    ; RV32-LABEL: name: store_common_value_double
-    ; RV32: liveins: $x10, $x11, $x12, $x16, $x17
-    ; RV32-NEXT: {{  $}}
-    ; RV32-NEXT: $x14_x15 = FSGNJ_D_IN32X $x16_x17, $x16_x17
-    ; RV32-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
-    ; RV32-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
-    ; RV32-NEXT: SD_RV32 killed $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
-    ; RV32-NEXT: PseudoRET
+    ; RV32_NOP-LABEL: name: store_common_value_double
+    ; RV32_NOP: liveins: $x10, $x11, $x12, $x16, $x17
+    ; RV32_NOP-NEXT: {{  $}}
+    ; RV32_NOP-NEXT: $x14_x15 = FSGNJ_D_IN32X $x16_x17, $x16_x17
+    ; RV32_NOP-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
+    ; RV32_NOP-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
+    ; RV32_NOP-NEXT: SD_RV32 killed $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
+    ; RV32_NOP-NEXT: PseudoRET
+    ;
+    ; RV32_P-LABEL: name: store_common_value_double
+    ; RV32_P: liveins: $x10, $x11, $x12, $x16, $x17
+    ; RV32_P-NEXT: {{  $}}
+    ; RV32_P-NEXT: $x14_x15 = ADDD $x16_x17, $x0_pair
+    ; RV32_P-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
+    ; RV32_P-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
+    ; RV32_P-NEXT: SD_RV32 killed $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
+    ; RV32_P-NEXT: PseudoRET
     SD_RV32 renamable $x16_x17, killed renamable $x10, 0 :: (store (s64) into %ir.a)
     SD_RV32 renamable $x16_x17, killed renamable $x11, 0 :: (store (s64) into %ir.b)
     SD_RV32 killed renamable $x16_x17, killed renamable $x12, 0 :: (store (s64) into %ir.c)
@@ -139,14 +148,23 @@ body:             |
   bb.0.entry:
     liveins: $x10, $x11, $x12
 
-    ; RV32-LABEL: name: store_common_value_double_zero
-    ; RV32: liveins: $x10, $x11, $x12
-    ; RV32-NEXT: {{  $}}
-    ; RV32-NEXT: $x14_x15 = FSGNJ_D_IN32X $x0_pair, $x0_pair
-    ; RV32-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
-    ; RV32-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
-    ; RV32-NEXT: SD_RV32 $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
-    ; RV32-NEXT: PseudoRET
+    ; RV32_NOP-LABEL: name: store_common_value_double_zero
+    ; RV32_NOP: liveins: $x10, $x11, $x12
+    ; RV32_NOP-NEXT: {{  $}}
+    ; RV32_NOP-NEXT: $x14_x15 = FSGNJ_D_IN32X $x0_pair, $x0_pair
+    ; RV32_NOP-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
+    ; RV32_NOP-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
+    ; RV32_NOP-NEXT: SD_RV32 $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
+    ; RV32_NOP-NEXT: PseudoRET
+    ;
+    ; RV32_P-LABEL: name: store_common_value_double_zero
+    ; RV32_P: liveins: $x10, $x11, $x12
+    ; RV32_P-NEXT: {{  $}}
+    ; RV32_P-NEXT: $x14_x15 = ADDD $x0_pair, $x0_pair
+    ; RV32_P-NEXT: SD_RV32 $x14_x15, killed renamable $x10, 0 :: (store (s64) into %ir.a)
+    ; RV32_P-NEXT: SD_RV32 $x14_x15, killed renamable $x11, 0 :: (store (s64) into %ir.b)
+    ; RV32_P-NEXT: SD_RV32 $x14_x15, killed renamable $x12, 0 :: (store (s64) into %ir.c)
+    ; RV32_P-NEXT: PseudoRET
     SD_RV32 $x0_pair, killed renamable $x10, 0 :: (store (s64) into %ir.a)
     SD_RV32 $x0_pair, killed renamable $x11, 0 :: (store (s64) into %ir.b)
     SD_RV32 $x0_pair, killed renamable $x12, 0 :: (store (s64) into %ir.c)

``````````

</details>


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


More information about the llvm-commits mailing list