[llvm] [RISCV] Support emitting plui.h for i32 constants on RV64. (PR #192534)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 14:04:09 PDT 2026


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/192534

If the constant was originally i32, it will be sign or zero
extended to i64 during type legalization. If we can prove the
upper bits aren't used we can duplicate the lower bits to allow
RISCVMatInt to select plui.h.

>From 472f224c8f6311120fd0b55b6d2fc3df76333009 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 16 Apr 2026 12:52:54 -0700
Subject: [PATCH 1/2] [RISCV] Don't check isApplicableToPLI for simm12
 constants.

It won't match except when the constant is -1, which we should
use li for. This avoids an unecessary call for hasAllWUsers in that
case.
---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index e428769818727..5f459f016faa4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1151,8 +1151,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
       if (!isInt<32>(Imm) && isUInt<32>(Imm) && hasAllWUsers(Node))
         Imm = SignExtend64<32>(Imm);
 
-      if (VT == MVT::i64 && Subtarget->hasStdExtP() && isApplicableToPLI(Imm) &&
-          hasAllWUsers(Node)) {
+      if (VT == MVT::i64 && !isInt<12>(Imm) && 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

>From e0effc0c6716e1dbc5b970a175474a3fa463fe21 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 16 Apr 2026 13:54:03 -0700
Subject: [PATCH 2/2] [RISCV] Support emitting plui.h for i32 constants on
 RV64.

If the constant was originally i32, it will be sign or zero
extended to i64 during type legalization. If we can prove the
upper bits aren't used we can duplicate the lower bits to allow
RISCVMatInt to select plui.h.
---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 5f459f016faa4..359ba913589a6 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1082,7 +1082,7 @@ static unsigned getSegInstNF(unsigned Intrinsic) {
   }
 }
 
-static bool isApplicableToPLI(int Val) {
+static bool isApplicableToPLIOrPLUI(int Val) {
   // Check if the immediate is packed i8 or i10
   int16_t Bit31To16 = Val >> 16;
   int16_t Bit15To0 = Val;
@@ -1091,7 +1091,8 @@ static bool isApplicableToPLI(int Val) {
   if (Bit31To16 != Bit15To0)
     return false;
 
-  return isInt<10>(Bit31To16) || Bit15To8 == Bit7To0;
+  return isInt<10>(Bit15To0) || isShiftedInt<10, 6>(Bit15To0) ||
+         Bit15To8 == Bit7To0;
 }
 
 void RISCVDAGToDAGISel::Select(SDNode *Node) {
@@ -1151,8 +1152,9 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
       if (!isInt<32>(Imm) && isUInt<32>(Imm) && hasAllWUsers(Node))
         Imm = SignExtend64<32>(Imm);
 
-      if (VT == MVT::i64 && !isInt<12>(Imm) && Subtarget->hasStdExtP() &&
-          isApplicableToPLI(Imm) && hasAllWUsers(Node)) {
+      if (VT == MVT::i64 && !isInt<12>(Imm) && !isShiftedInt<20, 12>(Imm) &&
+          Subtarget->hasStdExtP() && isApplicableToPLIOrPLUI(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



More information about the llvm-commits mailing list