[llvm] [ReplaceConstant] Don't create instructions for the same constant multiple times in the same basic block (PR #169141)
Shilei Tian via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 21 18:13:49 PST 2025
https://github.com/shiltian created https://github.com/llvm/llvm-project/pull/169141
Fixes #167500.
>From 4ff4d682a3703ef404cddf79613c4b73375b986d Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Fri, 21 Nov 2025 21:13:14 -0500
Subject: [PATCH] [ReplaceConstant] Don't create instructions for the same
constant multiple times in the same basic block
Fixes #167500.
---
llvm/lib/IR/ReplaceConstant.cpp | 10 +++-
...s-variable-multiple-use-in-one-phi-node.ll | 51 +++++++++++++++++++
2 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/same-lds-variable-multiple-use-in-one-phi-node.ll
diff --git a/llvm/lib/IR/ReplaceConstant.cpp b/llvm/lib/IR/ReplaceConstant.cpp
index b3586b45a23f2..f3d1914a8dc82 100644
--- a/llvm/lib/IR/ReplaceConstant.cpp
+++ b/llvm/lib/IR/ReplaceConstant.cpp
@@ -91,6 +91,11 @@ bool llvm::convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts,
// Replace those expandable operands with instructions
bool Changed = false;
+ // We need to cache the instructions we've already expanded to avoid expanding
+ // the same constant multiple times in the same basic block, which is
+ // problematic when the same constant is used in a phi node multiple times.
+ DenseMap<std::pair<Constant *, BasicBlock *>, SmallVector<Instruction *, 4>>
+ ConstantToInstructionMap;
while (!InstructionWorklist.empty()) {
Instruction *I = InstructionWorklist.pop_back_val();
DebugLoc Loc = I->getDebugLoc();
@@ -105,7 +110,10 @@ bool llvm::convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts,
if (auto *C = dyn_cast<Constant>(U.get())) {
if (ExpandableUsers.contains(C)) {
Changed = true;
- auto NewInsts = expandUser(BI, C);
+ SmallVector<Instruction *, 4> &NewInsts =
+ ConstantToInstructionMap[std::make_pair(C, BI->getParent())];
+ if (NewInsts.empty())
+ NewInsts = expandUser(BI, C);
for (auto *NI : NewInsts)
NI->setDebugLoc(Loc);
InstructionWorklist.insert_range(NewInsts);
diff --git a/llvm/test/CodeGen/AMDGPU/same-lds-variable-multiple-use-in-one-phi-node.ll b/llvm/test/CodeGen/AMDGPU/same-lds-variable-multiple-use-in-one-phi-node.ll
new file mode 100644
index 0000000000000..35a9bee03411f
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/same-lds-variable-multiple-use-in-one-phi-node.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -amdgpu-lower-module-lds %s -o - | FileCheck %s
+; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-lower-module-lds %s -o - | FileCheck %s
+
+ at lds = internal unnamed_addr addrspace(3) global [6144 x half] poison, align 2
+
+define amdgpu_kernel void @test(ptr addrspace(1) %out) {
+; CHECK-LABEL: define amdgpu_kernel void @test(
+; CHECK-SAME: ptr addrspace(1) [[OUT:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: switch i32 0, label %[[BB_3:.*]] [
+; CHECK-NEXT: i32 18, label %[[BB_2:.*]]
+; CHECK-NEXT: i32 1, label %[[BB_2]]
+; CHECK-NEXT: i32 0, label %[[BB_3]]
+; CHECK-NEXT: ]
+; CHECK: [[BB_1:.*]]:
+; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast ptr addrspace(3) @llvm.amdgcn.kernel.test.lds to ptr
+; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
+; CHECK-NEXT: switch i32 0, label %[[BB_3]] [
+; CHECK-NEXT: i32 18, label %[[BB_2]]
+; CHECK-NEXT: i32 1, label %[[BB_2]]
+; CHECK-NEXT: i32 0, label %[[BB_3]]
+; CHECK-NEXT: ]
+; CHECK: [[BB_2]]:
+; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ [[TMP1]], %[[BB_1]] ], [ [[TMP1]], %[[BB_1]] ], [ 10, %[[ENTRY]] ], [ 10, %[[ENTRY]] ]
+; CHECK-NEXT: store i64 [[PHI]], ptr addrspace(1) [[OUT]], align 8
+; CHECK-NEXT: br label %[[BB_3]]
+; CHECK: [[BB_3]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ switch i32 0, label %bb.3 [
+ i32 18, label %bb.2
+ i32 1, label %bb.2
+ i32 0, label %bb.3
+ ]
+bb.1:
+ switch i32 0, label %bb.3 [
+ i32 18, label %bb.2
+ i32 1, label %bb.2
+ i32 0, label %bb.3
+ ]
+
+bb.2:
+ %phi = phi i64 [ ptrtoint (ptr addrspacecast (ptr addrspace(3) @lds to ptr) to i64), %bb.1 ], [ ptrtoint (ptr addrspacecast (ptr addrspace(3) @lds to ptr) to i64), %bb.1 ], [10, %entry], [10, %entry]
+ store i64 %phi, ptr addrspace(1) %out, align 8
+ br label %bb.3
+
+bb.3:
+ ret void
+}
More information about the llvm-commits
mailing list