Skip to content

Commit f223411

Browse files
authored
[InstCombine]PtrReplacer: Correctly handle select with unavailable operands (llvm#148829)
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
1 parent afe8150 commit f223411

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
@@ -277,6 +277,15 @@ bool PointerReplacer::collectUsers() {
277277
Worklist.emplace_back(I);
278278
};
279279

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

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