[llvm] [RISCV][P-ext] Use pli.b when only the lower 2 bytes are used. (PR #192400)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 15 23:27:06 PDT 2026
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/192400
If the lower 2 bytes are the same and are the only bytes used we
can use pli.b instead of lui+addi.
>From 7028e118bc30212fa8678d89d7a5e814e0d0b1d9 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 15 Apr 2026 23:20:57 -0700
Subject: [PATCH 1/2] Pre-commit tests
---
llvm/test/CodeGen/RISCV/rv32p.ll | 23 +++++++++++++++++------
llvm/test/CodeGen/RISCV/rv64p.ll | 11 +++++++++++
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/rv32p.ll b/llvm/test/CodeGen/RISCV/rv32p.ll
index 154319f221d2a..0e25b5822e2da 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -58,6 +58,17 @@ 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: lui a1, 8
+; CHECK-NEXT: addi a1, a1, 385
+; 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 +201,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 +228,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 +236,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..5eb682a41130a 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -173,6 +173,17 @@ 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: lui a1, 8
+; CHECK-NEXT: addi a1, a1, 385
+; 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:
>From efcd4d8bcfccbe344e97a9209bea9af943c6eb65 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 15 Apr 2026 23:24:25 -0700
Subject: [PATCH 2/2] [RISCV][P-ext] Use pli.b when only the lower 2 bytes are
used.
If the lower 2 bytes are the same and are the only bytes used we
can use pli.b instead of lui+addi.
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 36 ++++++++++++++-------
llvm/test/CodeGen/RISCV/rv32p.ll | 3 +-
llvm/test/CodeGen/RISCV/rv64p.ll | 3 +-
3 files changed, 27 insertions(+), 15 deletions(-)
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 0e25b5822e2da..ebec3f57cae5c 100644
--- a/llvm/test/CodeGen/RISCV/rv32p.ll
+++ b/llvm/test/CodeGen/RISCV/rv32p.ll
@@ -61,8 +61,7 @@ define void @pli_b_store_i32(ptr %p) {
define void @pli_b_store_i16(ptr %p) {
; CHECK-LABEL: pli_b_store_i16:
; CHECK: # %bb.0:
-; CHECK-NEXT: lui a1, 8
-; CHECK-NEXT: addi a1, a1, 385
+; CHECK-NEXT: pli.b a1, -127
; CHECK-NEXT: sh a1, 0(a0)
; CHECK-NEXT: ret
store i16 u0x8181, ptr %p
diff --git a/llvm/test/CodeGen/RISCV/rv64p.ll b/llvm/test/CodeGen/RISCV/rv64p.ll
index 5eb682a41130a..21630c8dbb37f 100644
--- a/llvm/test/CodeGen/RISCV/rv64p.ll
+++ b/llvm/test/CodeGen/RISCV/rv64p.ll
@@ -176,8 +176,7 @@ define void @pli_b_store_i32(ptr %p) {
define void @pli_b_store_i16(ptr %p) {
; CHECK-LABEL: pli_b_store_i16:
; CHECK: # %bb.0:
-; CHECK-NEXT: lui a1, 8
-; CHECK-NEXT: addi a1, a1, 385
+; CHECK-NEXT: pli.b a1, -127
; CHECK-NEXT: sh a1, 0(a0)
; CHECK-NEXT: ret
store i16 u0x8181, ptr %p
More information about the llvm-commits
mailing list