[llvm] [RISCV] Use proper LLA operand for constant from load (PR #142292)
Carl Nettelblad via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 2 15:27:21 PDT 2025
cnettel wrote:
It took some work. This isn's quite minimal, but you need to fool LLVM a bit to store constants without inlining all the math, even at -O0.
The premise is that ori can be replaced by addi if the compiler can prove that the low bits are zero. This is done late during instruction selection.
The following IR:
```
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-unknown"
; Function Attrs: mustprogress noinline nounwind optnone
define dso_local noundef i64 @_Z4sum2j(i32 noundef signext %c, i32 noundef signext %d) #0 {
entry:
%or1 = or i64 -9191740941672644608, 4096
%or2 = or i64 -9191740941672644608, 8192
%or3 = or i64 -9191740941672644608, 16384
%conv = zext i32 %c to i64
%donv = zext i32 %d to i64
%3 = mul i64 %or1, %conv
%4 = mul i64 %or2, %donv
%5 = mul i64 %or3, %conv
%6 = add i64 %3, %4
%7 = add i64 %6, %5
%8 = or i64 %5, 127
%9 = mul i64 %3, %8
%add = add i64 -9191740941672644608, %9
%add2 = add i64 %add, %conv
ret i64 %add2
}
```
generates the following assembler if run through `llc -mcpu=mips-p8700 -O0 -relocation-model=pic` in the patched version:
```
.attribute 4, 16
.attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zba1p0_zbb1p0"
.file "testbug.ll"
.section .rodata.cst8,"aM", at progbits,8
.p2align 3, 0x0 # -- Begin function _Z4sum2j
.LCPI0_0:
.quad -9191740941672628224 # 0x8070605040304000
.LCPI0_1:
.quad -9191740941672640512 # 0x8070605040301000
.text
.globl _Z4sum2j
.p2align 1
.type _Z4sum2j, at function
_Z4sum2j: # @_Z4sum2j
.L_Z4sum2j$local:
.type .L_Z4sum2j$local, at function
.cfi_startproc
# %bb.0: # %entry
# kill: def $x11 killed $x10
zext.w a1, a0
.Lpcrel_hi0:
auipc a2, %pcrel_hi(.LCPI0_0)
addi a2, a2, %pcrel_lo(.Lpcrel_hi0)
ld a2, 0(a2)
mul a2, a1, a2
addi a2, a2, 127
mul a1, a1, a2
.Lpcrel_hi1:
auipc a2, %pcrel_hi(.LCPI0_1)
addi a2, a2, %pcrel_lo(.Lpcrel_hi1)
ld a2, 0(a2)
mul a1, a1, a2
add.uw a0, a0, a1
lui a1, 1015920
addiw a1, a1, 1541
slli a1, a1, 16
addi a1, a1, 1027
slli a1, a1, 20
add a0, a0, a1
ret
.Lfunc_end0:
.size _Z4sum2j, .Lfunc_end0-_Z4sum2j
.size .L_Z4sum2j$local, .Lfunc_end0-_Z4sum2j
.cfi_endproc
# -- End function
.section ".note.GNU-stack","", at progbits
```
This is correct. The same command, on the current main branch, generates the ori instruction instead, showing that or_is_add in RISCVInstrInfo isn't able to see the known bits:
`
.attribute 4, 16
.attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zba1p0_zbb1p0"
.file "testbug.ll"
.section .rodata.cst8,"aM", at progbits,8
.p2align 3, 0x0 # -- Begin function _Z4sum2j
.LCPI0_0:
.quad -9191740941672628224 # 0x8070605040304000
.LCPI0_1:
.quad -9191740941672640512 # 0x8070605040301000
.text
.globl _Z4sum2j
.p2align 1
.type _Z4sum2j, at function
_Z4sum2j: # @_Z4sum2j
.L_Z4sum2j$local:
.type .L_Z4sum2j$local, at function
.cfi_startproc
# %bb.0: # %entry
# kill: def $x11 killed $x10
zext.w a1, a0
.Lpcrel_hi0:
auipc a2, %pcrel_hi(.LCPI0_0)
addi a2, a2, %pcrel_lo(.Lpcrel_hi0)
ld a2, 0(a2)
mul a2, a1, a2
ori a2, a2, 127
mul a1, a1, a2
.Lpcrel_hi1:
auipc a2, %pcrel_hi(.LCPI0_1)
addi a2, a2, %pcrel_lo(.Lpcrel_hi1)
ld a2, 0(a2)
mul a1, a1, a2
add.uw a0, a0, a1
lui a1, 1015920
addiw a1, a1, 1541
slli a1, a1, 16
addi a1, a1, 1027
slli a1, a1, 20
add a0, a0, a1
ret
.Lfunc_end0:
.size _Z4sum2j, .Lfunc_end0-_Z4sum2j
.size .L_Z4sum2j$local, .Lfunc_end0-_Z4sum2j
.cfi_endproc
# -- End function
.section ".note.GNU-stack","", at progbits
```
https://github.com/llvm/llvm-project/pull/142292
More information about the llvm-commits
mailing list