-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Don't fold a pcrel addi into ld/st instructions with multiple uses #80240
Conversation
… uses When folding the low part of the address into the load/store instruction offsets, as added in https://reviews.llvm.org/D123265, we need to make sure that we only fold the pcrel address into a single instruction. Folding it into multiple instructions will result in different addresses, since the pcrel offset will be different.
@llvm/pr-subscribers-backend-risc-v Author: Visoiu Mistrih Francis (francisvm) ChangesWhen folding the low part of the address into the load/store instruction offsets, as added in https://reviews.llvm.org/D123265, we need to make sure that we only fold the pcrel address into a single instruction. Folding it into multiple instructions will result in different addresses, since the pcrel offset will be different. Full diff: https://github.com/llvm/llvm-project/pull/80240.diff 3 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
index 410989177a8b9..fd3001818267b 100644
--- a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
@@ -116,6 +116,11 @@ bool RISCVMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi,
if (LoOp2.getTargetFlags() != RISCVII::MO_PCREL_LO ||
LoOp2.getType() != MachineOperand::MO_MCSymbol)
return false;
+ // Only fold pcrel offsets into a single instruction, otherwise the offset
+ // will be different at each use.
+ if (LoOp2.getTargetFlags() == RISCVII::MO_PCREL_LO &&
+ !MRI->hasOneUse(Lo->getOperand(0).getReg()))
+ return false;
}
if (HiOp1.isGlobal()) {
diff --git a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
index 91e73992bdfa3..883b56cb1ac5b 100644
--- a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
+++ b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
@@ -316,9 +316,10 @@ define dso_local void @inc_g_i32() nounwind {
; RV32I-MEDIUM: # %bb.0: # %entry
; RV32I-MEDIUM-NEXT: .Lpcrel_hi8:
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32)
-; RV32I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8)
+; RV32I-MEDIUM-NEXT: lw a1, 0(a0)
; RV32I-MEDIUM-NEXT: addi a1, a1, 1
-; RV32I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
+; RV32I-MEDIUM-NEXT: sw a1, 0(a0)
; RV32I-MEDIUM-NEXT: ret
;
; RV64I-LABEL: inc_g_i32:
@@ -333,9 +334,10 @@ define dso_local void @inc_g_i32() nounwind {
; RV64I-MEDIUM: # %bb.0: # %entry
; RV64I-MEDIUM-NEXT: .Lpcrel_hi8:
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(g_4_i32)
-; RV64I-MEDIUM-NEXT: lw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi8)
+; RV64I-MEDIUM-NEXT: lw a1, 0(a0)
; RV64I-MEDIUM-NEXT: addi a1, a1, 1
-; RV64I-MEDIUM-NEXT: sw a1, %pcrel_lo(.Lpcrel_hi8)(a0)
+; RV64I-MEDIUM-NEXT: sw a1, 0(a0)
; RV64I-MEDIUM-NEXT: ret
entry:
%0 = load i32, ptr @g_4_i32
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
index 52d0dabf18839..363eca71aa9d7 100644
--- a/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
+++ b/llvm/test/CodeGen/RISCV/inline-asm-mem-constraint.ll
@@ -515,8 +515,9 @@ define void @constraint_m_with_multi_operands() nounwind {
; RV32I-MEDIUM: # %bb.0:
; RV32I-MEDIUM-NEXT: .Lpcrel_hi9:
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi9)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0); sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
@@ -524,8 +525,9 @@ define void @constraint_m_with_multi_operands() nounwind {
; RV64I-MEDIUM: # %bb.0:
; RV64I-MEDIUM-NEXT: .Lpcrel_hi9:
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi9)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi9)(a0); sw zero, %pcrel_lo(.Lpcrel_hi9)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0); sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: ret
call void asm "sw zero, $0; sw zero, $1", "=*m,=*m"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg)
@@ -559,11 +561,12 @@ define void @constraint_m_with_multi_asm() nounwind {
; RV32I-MEDIUM: # %bb.0:
; RV32I-MEDIUM-NEXT: .Lpcrel_hi10:
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi10)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
@@ -571,11 +574,12 @@ define void @constraint_m_with_multi_asm() nounwind {
; RV64I-MEDIUM: # %bb.0:
; RV64I-MEDIUM-NEXT: .Lpcrel_hi10:
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi10)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi10)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: ret
call void asm "sw zero, $0", "=*m"(ptr elementtype(i32) @eg)
@@ -618,8 +622,9 @@ define i32 @constraint_m_with_callbr_multi_operands(i32 %a) {
; RV32I-MEDIUM: # %bb.0: # %entry
; RV32I-MEDIUM-NEXT: .Lpcrel_hi11:
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi11)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB14_2
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.1: # %normal
; RV32I-MEDIUM-NEXT: li a0, 0
@@ -634,8 +639,9 @@ define i32 @constraint_m_with_callbr_multi_operands(i32 %a) {
; RV64I-MEDIUM: # %bb.0: # %entry
; RV64I-MEDIUM-NEXT: .Lpcrel_hi11:
; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi11)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); sw zero, %pcrel_lo(.Lpcrel_hi11)(a1); beqz a0, .LBB14_2
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB14_2
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.1: # %normal
; RV64I-MEDIUM-NEXT: li a0, 0
@@ -698,12 +704,13 @@ define i32 @constraint_m_with_multi_callbr_asm(i32 %a) {
; RV32I-MEDIUM: # %bb.0: # %entry
; RV32I-MEDIUM-NEXT: .Lpcrel_hi12:
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi12)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(a1); beqz a0, .LBB15_3
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB15_3
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.1: # %normal0
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(a1); beqz a0, .LBB15_3
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB15_3
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.2: # %normal1
; RV32I-MEDIUM-NEXT: li a0, 0
@@ -718,12 +725,13 @@ define i32 @constraint_m_with_multi_callbr_asm(i32 %a) {
; RV64I-MEDIUM: # %bb.0: # %entry
; RV64I-MEDIUM-NEXT: .Lpcrel_hi12:
; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi12)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(a1); beqz a0, .LBB15_3
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB15_3
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.1: # %normal0
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi12)(a1); beqz a0, .LBB15_3
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB15_3
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.2: # %normal1
; RV64I-MEDIUM-NEXT: li a0, 0
@@ -1100,8 +1108,9 @@ define void @constraint_o_with_multi_operands() nounwind {
; RV32I-MEDIUM: # %bb.0:
; RV32I-MEDIUM-NEXT: .Lpcrel_hi19:
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi19)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi19)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi19)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0) \n sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
@@ -1109,8 +1118,9 @@ define void @constraint_o_with_multi_operands() nounwind {
; RV64I-MEDIUM: # %bb.0:
; RV64I-MEDIUM-NEXT: .Lpcrel_hi19:
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi19)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi19)(a0) \n sw zero, %pcrel_lo(.Lpcrel_hi19)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0) \n sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: ret
call void asm "sw zero, $0 \n sw zero, $1", "=*o,=*o"(ptr elementtype(i32) @eg, ptr elementtype(i32) @eg)
@@ -1144,11 +1154,12 @@ define void @constraint_o_with_multi_asm() nounwind {
; RV32I-MEDIUM: # %bb.0:
; RV32I-MEDIUM-NEXT: .Lpcrel_hi20:
; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi20)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi20)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi20)(a0)
+; RV32I-MEDIUM-NEXT: sw zero, 0(a0)
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: ret
;
@@ -1156,11 +1167,12 @@ define void @constraint_o_with_multi_asm() nounwind {
; RV64I-MEDIUM: # %bb.0:
; RV64I-MEDIUM-NEXT: .Lpcrel_hi20:
; RV64I-MEDIUM-NEXT: auipc a0, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.Lpcrel_hi20)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi20)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi20)(a0)
+; RV64I-MEDIUM-NEXT: sw zero, 0(a0)
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: ret
call void asm "sw zero, $0", "=*o"(ptr elementtype(i32) @eg)
@@ -1203,8 +1215,9 @@ define i32 @constraint_o_with_callbr_multi_operands(i32 %a) {
; RV32I-MEDIUM: # %bb.0: # %entry
; RV32I-MEDIUM-NEXT: .Lpcrel_hi21:
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi21)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi21)(a1); sw zero, %pcrel_lo(.Lpcrel_hi21)(a1); beqz a0, .LBB27_2
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB27_2
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.1: # %normal
; RV32I-MEDIUM-NEXT: li a0, 0
@@ -1219,8 +1232,9 @@ define i32 @constraint_o_with_callbr_multi_operands(i32 %a) {
; RV64I-MEDIUM: # %bb.0: # %entry
; RV64I-MEDIUM-NEXT: .Lpcrel_hi21:
; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi21)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi21)(a1); sw zero, %pcrel_lo(.Lpcrel_hi21)(a1); beqz a0, .LBB27_2
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); sw zero, 0(a1); beqz a0, .LBB27_2
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.1: # %normal
; RV64I-MEDIUM-NEXT: li a0, 0
@@ -1283,12 +1297,13 @@ define i32 @constraint_o_with_multi_callbr_asm(i32 %a) {
; RV32I-MEDIUM: # %bb.0: # %entry
; RV32I-MEDIUM-NEXT: .Lpcrel_hi22:
; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi22)
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi22)(a1); beqz a0, .LBB28_3
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB28_3
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.1: # %normal0
; RV32I-MEDIUM-NEXT: #APP
-; RV32I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi22)(a1); beqz a0, .LBB28_3
+; RV32I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB28_3
; RV32I-MEDIUM-NEXT: #NO_APP
; RV32I-MEDIUM-NEXT: # %bb.2: # %normal1
; RV32I-MEDIUM-NEXT: li a0, 0
@@ -1303,12 +1318,13 @@ define i32 @constraint_o_with_multi_callbr_asm(i32 %a) {
; RV64I-MEDIUM: # %bb.0: # %entry
; RV64I-MEDIUM-NEXT: .Lpcrel_hi22:
; RV64I-MEDIUM-NEXT: auipc a1, %pcrel_hi(eg)
+; RV64I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.Lpcrel_hi22)
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi22)(a1); beqz a0, .LBB28_3
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB28_3
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.1: # %normal0
; RV64I-MEDIUM-NEXT: #APP
-; RV64I-MEDIUM-NEXT: sw zero, %pcrel_lo(.Lpcrel_hi22)(a1); beqz a0, .LBB28_3
+; RV64I-MEDIUM-NEXT: sw zero, 0(a1); beqz a0, .LBB28_3
; RV64I-MEDIUM-NEXT: #NO_APP
; RV64I-MEDIUM-NEXT: # %bb.2: # %normal1
; RV64I-MEDIUM-NEXT: li a0, 0
|
Isn't it pc-relative to the location of the auipc? The load/store relocations point to a label that is above the auipc. |
Yes. There's no bug in the currently-generated code. |
Got it, so it's the low 12 bits of the symbol in |
It's the low 12 bits of the distance between the address of auipc and the address of the symbol. |
When folding the low part of the address into the load/store instruction offsets, as added in https://reviews.llvm.org/D123265, we need to make sure that we only fold the pcrel address into a single instruction. Folding it into multiple instructions will result in different addresses, since the pcrel offset will be different.