Skip to content

Commit e13573e

Browse files
authored
[InstCombine]PtrReplacer: Correctly handle select with unavailable operands (llvm#3119)
The testcase I added previously failed because a SelectInst with invalid operands was created (one side `addrspace(4)`, the other `addrspace(5)`). PointerReplacer needs to dig deeper if the true and/or false instructions of the select are not available. Fixes SWDEV-542957 llvm#148829
1 parent 1a2974a commit e13573e

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,15 @@ bool PointerReplacer::collectUsers() {
278278
Worklist.emplace_back(I);
279279
};
280280

281+
auto TryPushInstOperand = [&](Instruction *InstOp) {
282+
if (!UsersToReplace.contains(InstOp)) {
283+
if (!ValuesToRevisit.insert(InstOp))
284+
return false;
285+
Worklist.emplace_back(InstOp);
286+
}
287+
return true;
288+
};
289+
281290
PushUsersToWorklist(&Root);
282291
while (!Worklist.empty()) {
283292
Instruction *Inst = Worklist.pop_back_val();
@@ -310,21 +319,26 @@ bool PointerReplacer::collectUsers() {
310319
// incoming values.
311320
Worklist.emplace_back(PHI);
312321
for (unsigned Idx = 0; Idx < PHI->getNumIncomingValues(); ++Idx) {
313-
auto *IncomingValue = cast<Instruction>(PHI->getIncomingValue(Idx));
314-
if (UsersToReplace.contains(IncomingValue))
315-
continue;
316-
if (!ValuesToRevisit.insert(IncomingValue))
322+
if (!TryPushInstOperand(cast<Instruction>(PHI->getIncomingValue(Idx))))
317323
return false;
318-
Worklist.emplace_back(IncomingValue);
319324
}
320325
} else if (auto *SI = dyn_cast<SelectInst>(Inst)) {
321326
auto *TrueInst = dyn_cast<Instruction>(SI->getTrueValue());
322327
auto *FalseInst = dyn_cast<Instruction>(SI->getFalseValue());
323328
if (!TrueInst || !FalseInst)
324329
return false;
325330

326-
UsersToReplace.insert(SI);
327-
PushUsersToWorklist(SI);
331+
if (isAvailable(TrueInst) && isAvailable(FalseInst)) {
332+
UsersToReplace.insert(SI);
333+
PushUsersToWorklist(SI);
334+
continue;
335+
}
336+
337+
// Push select back onto the stack, followed by unavailable true/false
338+
// value.
339+
Worklist.emplace_back(SI);
340+
if (!TryPushInstOperand(TrueInst) || !TryPushInstOperand(FalseInst))
341+
return false;
328342
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
329343
UsersToReplace.insert(GEP);
330344
PushUsersToWorklist(GEP);

llvm/test/Transforms/InstCombine/AMDGPU/ptr-replace-alloca.ll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,37 @@ sink:
7676
ret <2 x i64> %val.sink
7777
}
7878

79+
; Crashed in IC PtrReplacer because an invalid select was generated with addrspace(4) and addrspace(5)
80+
; operands.
81+
define amdgpu_kernel void @select_addr4_addr5(ptr addrspace(4) byref([12 x i8]) align 16 %arg) {
82+
; CHECK-LABEL: define amdgpu_kernel void @select_addr4_addr5(
83+
; CHECK-SAME: ptr addrspace(4) byref([12 x i8]) align 16 [[ARG:%.*]]) {
84+
; CHECK-NEXT: [[BB:.*:]]
85+
; CHECK-NEXT: ret void
86+
;
87+
bb:
88+
%alloca = alloca i32, i32 0, align 8, addrspace(5)
89+
%alloca1 = alloca [12 x i8], align 16, addrspace(5)
90+
call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) %alloca1, ptr addrspace(4) %arg, i64 0, i1 false)
91+
%select = select i1 false, ptr addrspace(5) %alloca1, ptr addrspace(5) %alloca
92+
call void @llvm.memcpy.p0.p5.i64(ptr null, ptr addrspace(5) %select, i64 0, i1 false)
93+
ret void
94+
}
95+
96+
; Same as above but with swapped operands on the select.
97+
define amdgpu_kernel void @select_addr4_addr5_swapped(ptr addrspace(4) byref([12 x i8]) align 16 %arg) {
98+
; CHECK-LABEL: define amdgpu_kernel void @select_addr4_addr5_swapped(
99+
; CHECK-SAME: ptr addrspace(4) byref([12 x i8]) align 16 [[ARG:%.*]]) {
100+
; CHECK-NEXT: [[BB:.*:]]
101+
; CHECK-NEXT: ret void
102+
;
103+
bb:
104+
%alloca = alloca i32, i32 0, align 8, addrspace(5)
105+
%alloca1 = alloca [12 x i8], align 16, addrspace(5)
106+
call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) %alloca1, ptr addrspace(4) %arg, i64 0, i1 false)
107+
%select = select i1 false, ptr addrspace(5) %alloca, ptr addrspace(5) %alloca1
108+
call void @llvm.memcpy.p0.p5.i64(ptr null, ptr addrspace(5) %select, i64 0, i1 false)
109+
ret void
110+
}
111+
79112
declare void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) noalias writeonly captures(none), ptr addrspace(4) noalias readonly captures(none), i64, i1 immarg) #0

0 commit comments

Comments
 (0)