[llvm] [RISCV] Use addi rather than addiw for immediates materialised by lui+addi(w) pairs when possible (PR #141663)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue May 27 22:00:16 PDT 2025


topperc wrote:

> Here's a test case where the sext.w isn't neutral in instruction count:
> 
> ```
> target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
> target triple = "riscv64-unknown-linux-gnu"
> 
> define i32 @Perm(i32 %0) {
> entry:
>   %cmp1.not = icmp eq i32 %0, 43300
>   br i1 %cmp1.not, label %if.end, label %if.then
> 
> if.then:                                          ; preds = %entry
>   %.pre = load i32, ptr null, align 4
>   br label %if.end
> 
> if.end:                                           ; preds = %if.then, %entry
>   %1 = phi i32 [ %.pre, %if.then ], [ 43300, %entry ]
>   %call2 = tail call i32 (ptr, ...) null(ptr null, i32 signext %1)
>   ret i32 %call2
> }
> ```
> 
> It does indeed look like RISCVOptWInstrs needs to be a little bit smarter. Thanks for pointing that out.

I think something like this should work.

```
diff --git a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp
index 3b601bb43bf2..899c8068a971 100644
--- a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp
+++ b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp
@@ -591,6 +591,27 @@ static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST,
         return false;
       break;
 
+    case RISCV::ADDI: {
+      if (MI->getOperand(1).isReg() && MI->getOperand(1).getReg().isVirtual()) {
+        if (MachineInstr *SrcMI = MRI.getVRegDef(MI->getOperand(1).getReg())) {
+          if (SrcMI->getOpcode() == RISCV::LUI &&
+              SrcMI->getOperand(1).isImm()) {
+            uint64_t Imm = SrcMI->getOperand(1).getImm();
+            Imm = SignExtend64<32>(Imm << 12);
+            Imm += (uint64_t)MI->getOperand(2).getImm();
+            if (isInt<32>(Imm))
+              return true;
+          }
+        }
+      }
+
+      if (hasAllWUsers(*MI, ST, MRI)) {
+        FixableDef.insert(MI);
+        break;
+      }
+      return false;
+    }
+
     // With these opcode, we can "fix" them with the W-version
     // if we know all users of the result only rely on bits 31:0
     case RISCV::SLLI:
@@ -598,7 +619,6 @@ static bool isSignExtendedW(Register SrcReg, const RISCVSubtarget &ST,
       if (MI->getOperand(2).getImm() >= 32)
         return false;
       [[fallthrough]];
-    case RISCV::ADDI:
     case RISCV::ADD:
     case RISCV::LD:
     case RISCV::LWU
```

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


More information about the llvm-commits mailing list