[llvm] [RISCV][P-ext] Use pli.b when only the lower 2 bytes are used. (PR #192400)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 23:27:38 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Craig Topper (topperc)

<details>
<summary>Changes</summary>

If the lower 2 bytes are the same and are the only bytes used we
can use pli.b instead of lui+addi.

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


3 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp (+25-11) 
- (modified) llvm/test/CodeGen/RISCV/rv32p.ll (+16-6) 
- (modified) llvm/test/CodeGen/RISCV/rv64p.ll (+10) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index e7be2938c2256..acdb05ae546c0 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1133,17 +1133,31 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     else if (!isInt<16>(Imm) && isUInt<16>(Imm) &&
              isInt<12>(SignExtend64<16>(Imm)) && hasAllHUsers(Node))
       Imm = SignExtend64<16>(Imm);
-    // If the upper 32-bits are not used try to convert this into a simm32 by
-    // sign extending bit 32.
-    else if (!isInt<32>(Imm) && isUInt<32>(Imm) && hasAllWUsers(Node))
-      Imm = SignExtend64<32>(Imm);
-
-    if (VT == MVT::i64 && Subtarget->hasStdExtP() && isApplicableToPLI(Imm) &&
-        hasAllWUsers(Node)) {
-      // If it's 4 packed 8-bit integers or 2 packed signed 16-bit integers, we
-      // can simply copy lower 32 bits to higher 32 bits to make it able to
-      // rematerialize to PLI_B or PLI_H
-      Imm = ((uint64_t)Imm << 32) | (Imm & 0xFFFFFFFF);
+
+    // If the upper XLen-16 bits are not used, the lower 2 bytes are the same,
+    // and we can't use li, convert to an xlen splat so we can use pli.b.
+    if (Subtarget->hasStdExtP() && !isInt<12>(Imm) &&
+        (Imm & 0xff) == ((Imm >> 8) & 0xff) && hasAllHUsers(Node)) {
+      // Splat the lower 16 bits to XLen. Sign extend for RV32.
+      uint64_t Splat = Imm & 0xffff;
+      Splat = (Splat << 16) | Splat;
+      if (VT == MVT::i64)
+        Imm = Splat << 32 | Splat;
+      else
+        Imm = SignExtend64<32>(Splat);
+    } else {
+      // If the upper 32-bits are not used try to convert this into a simm32 by
+      // sign extending bit 32.
+      if (!isInt<32>(Imm) && isUInt<32>(Imm) && hasAllWUsers(Node))
+        Imm = SignExtend64<32>(Imm);
+
+      if (VT == MVT::i64 && Subtarget->hasStdExtP() && isApplicableToPLI(Imm) &&
+          hasAllWUsers(Node)) {
+        // If it's 4 packed 8-bit integers or 2 packed signed 16-bit integers, we
+        // can simply copy lower 32 bits to higher 32 bits to make it able to
+        // rematerialize to PLI_B or PLI_H
+        Imm = ((uint64_t)Imm << 32) | (Imm & 0xFFFFFFFF);
+      }
     }
 
     ReplaceNode(Node, selectImm(CurDAG, DL, VT, Imm, *Subtarget).getNode());
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index 154319f221d2a..ebec3f57cae5c 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -58,6 +58,16 @@ define void @pli_b_store_i32(ptr %p) {
   ret void
 }
 
+define void @pli_b_store_i16(ptr %p) {
+; CHECK-LABEL: pli_b_store_i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pli.b a1, -127
+; CHECK-NEXT:    sh a1, 0(a0)
+; CHECK-NEXT:    ret
+  store i16 u0x8181, ptr %p
+  ret void
+}
+
 define i32 @plui_h_i32(ptr %p) {
 ; CHECK-LABEL: plui_h_i32:
 ; CHECK:       # %bb.0:
@@ -190,16 +200,16 @@ define i64 @cls_i64(i64 %x) {
 ; CHECK-LABEL: cls_i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    srai a2, a1, 31
-; CHECK-NEXT:    bne a1, a2, .LBB16_2
+; CHECK-NEXT:    bne a1, a2, .LBB17_2
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    xor a0, a0, a2
 ; CHECK-NEXT:    clz a0, a0
 ; CHECK-NEXT:    addi a0, a0, 32
-; CHECK-NEXT:    j .LBB16_3
-; CHECK-NEXT:  .LBB16_2:
+; CHECK-NEXT:    j .LBB17_3
+; CHECK-NEXT:  .LBB17_2:
 ; CHECK-NEXT:    xor a1, a1, a2
 ; CHECK-NEXT:    clz a0, a1
-; CHECK-NEXT:  .LBB16_3:
+; CHECK-NEXT:  .LBB17_3:
 ; CHECK-NEXT:    li a1, 1
 ; CHECK-NEXT:    wsubu a0, a0, a1
 ; CHECK-NEXT:    ret
@@ -217,7 +227,7 @@ define i64 @cls_i64_2(i64 %x) {
 ; CHECK-NEXT:    xor a1, a1, a2
 ; CHECK-NEXT:    xor a0, a0, a2
 ; CHECK-NEXT:    nsrli a1, a0, 31
-; CHECK-NEXT:    bnez a1, .LBB17_2
+; CHECK-NEXT:    bnez a1, .LBB18_2
 ; CHECK-NEXT:  # %bb.1:
 ; CHECK-NEXT:    slli a0, a0, 1
 ; CHECK-NEXT:    addi a0, a0, 1
@@ -225,7 +235,7 @@ define i64 @cls_i64_2(i64 %x) {
 ; CHECK-NEXT:    addi a0, a0, 32
 ; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    ret
-; CHECK-NEXT:  .LBB17_2:
+; CHECK-NEXT:  .LBB18_2:
 ; CHECK-NEXT:    clz a0, a1
 ; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index d4a5e054d312d..21630c8dbb37f 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -173,6 +173,16 @@ define void @pli_b_store_i32(ptr %p) {
   ret void
 }
 
+define void @pli_b_store_i16(ptr %p) {
+; CHECK-LABEL: pli_b_store_i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    pli.b a1, -127
+; CHECK-NEXT:    sh a1, 0(a0)
+; CHECK-NEXT:    ret
+  store i16 u0x8181, ptr %p
+  ret void
+}
+
 define i64 @plui_h_i64() {
 ; CHECK-LABEL: plui_h_i64:
 ; CHECK:       # %bb.0:

``````````

</details>


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


More information about the llvm-commits mailing list