Skip to content

Commit 2449cba

Browse files
committed
[InstCombine] Handle PHI nodes in PtrReplacer
This patch adds on to the functionality implemented in rG42ab5dc5a5dd6c79476104bdc921afa2a18559cf, where PHI nodes are supported in the use-def traversal algorithm to determine if an alloca ever overwritten in addition to a memmove/memcpy. This patch implements the support needed by the PointerReplacer to collect all (indirect) users of the alloca in cases where a PHI is involved. Finally, a new PHI is defined in the replace method which takes in replaced incoming values and updates the WorkMap accordingly. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D136201
1 parent 9a47900 commit 2449cba

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,25 +265,59 @@ class PointerReplacer {
265265
void replacePointer(Instruction &I, Value *V);
266266

267267
private:
268+
bool collectUsersRecursive(Instruction &I);
268269
void replace(Instruction *I);
269270
Value *getReplacement(Value *I);
270271

272+
SmallPtrSet<Instruction *, 32> ValuesToRevisit;
271273
SmallSetVector<Instruction *, 4> Worklist;
272274
MapVector<Value *, Value *> WorkMap;
273275
InstCombinerImpl &IC;
274276
};
275277
} // end anonymous namespace
276278

277279
bool PointerReplacer::collectUsers(Instruction &I) {
280+
if (!collectUsersRecursive(I))
281+
return false;
282+
283+
// Ensure that all outstanding (indirect) users of I
284+
// are inserted into the Worklist. Return false
285+
// otherwise.
286+
for (auto *Inst : ValuesToRevisit)
287+
if (!Worklist.contains(Inst))
288+
return false;
289+
return true;
290+
}
291+
292+
bool PointerReplacer::collectUsersRecursive(Instruction &I) {
278293
for (auto *U : I.users()) {
279294
auto *Inst = cast<Instruction>(&*U);
280295
if (auto *Load = dyn_cast<LoadInst>(Inst)) {
281296
if (Load->isVolatile())
282297
return false;
283298
Worklist.insert(Load);
284-
} else if (isa<GetElementPtrInst>(Inst) || isa<BitCastInst>(Inst)) {
299+
} else if (auto *PHI = dyn_cast<PHINode>(Inst)) {
300+
// All incoming values must be instructions for replacability
301+
if (any_of(PHI->incoming_values(),
302+
[](Value *V) { return !isa<Instruction>(V); }))
303+
return false;
304+
305+
// If at least one incoming value of the PHI is not in Worklist,
306+
// store the PHI for revisiting and skip this iteration of the
307+
// loop.
308+
if (any_of(PHI->incoming_values(), [this](Value *V) {
309+
return !Worklist.contains(cast<Instruction>(V));
310+
})) {
311+
ValuesToRevisit.insert(Inst);
312+
continue;
313+
}
314+
315+
Worklist.insert(PHI);
316+
if (!collectUsersRecursive(*PHI))
317+
return false;
318+
} else if (isa<GetElementPtrInst, BitCastInst>(Inst)) {
285319
Worklist.insert(Inst);
286-
if (!collectUsers(*Inst))
320+
if (!collectUsersRecursive(*Inst))
287321
return false;
288322
} else if (auto *MI = dyn_cast<MemTransferInst>(Inst)) {
289323
if (MI->isVolatile())
@@ -318,6 +352,14 @@ void PointerReplacer::replace(Instruction *I) {
318352
IC.InsertNewInstWith(NewI, *LT);
319353
IC.replaceInstUsesWith(*LT, NewI);
320354
WorkMap[LT] = NewI;
355+
} else if (auto *PHI = dyn_cast<PHINode>(I)) {
356+
Type *NewTy = getReplacement(PHI->getIncomingValue(0))->getType();
357+
auto *NewPHI = PHINode::Create(NewTy, PHI->getNumIncomingValues(),
358+
PHI->getName(), PHI);
359+
for (unsigned int I = 0; I < PHI->getNumIncomingValues(); ++I)
360+
NewPHI->addIncoming(getReplacement(PHI->getIncomingValue(I)),
361+
PHI->getIncomingBlock(I));
362+
WorkMap[PHI] = NewPHI;
321363
} else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
322364
auto *V = getReplacement(GEP->getPointerOperand());
323365
assert(V && "Operand not replaced");

llvm/test/Transforms/InstCombine/replace-alloca-phi.ll

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,14 @@ target datalayout="p5:32:32-A5"
99
define i8 @remove_alloca_use_arg(i1 %cond) {
1010
; CHECK-LABEL: @remove_alloca_use_arg(
1111
; CHECK-NEXT: entry:
12-
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
13-
; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
1412
; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
1513
; CHECK: if:
16-
; CHECK-NEXT: [[VAL_IF:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
1714
; CHECK-NEXT: br label [[SINK:%.*]]
1815
; CHECK: else:
19-
; CHECK-NEXT: [[VAL_ELSE:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
2016
; CHECK-NEXT: br label [[SINK]]
2117
; CHECK: sink:
22-
; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL_IF]], [[IF]] ], [ [[VAL_ELSE]], [[ELSE]] ]
23-
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
18+
; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[IF]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ELSE]] ]
19+
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
2420
; CHECK-NEXT: ret i8 [[LOAD]]
2521
;
2622
entry:
@@ -116,18 +112,14 @@ sink:
116112
define i8 @loop_phi_remove_alloca(i1 %cond) {
117113
; CHECK-LABEL: @loop_phi_remove_alloca(
118114
; CHECK-NEXT: entry:
119-
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
120-
; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
121-
; CHECK-NEXT: [[VAL1:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
122115
; CHECK-NEXT: br label [[BB_0:%.*]]
123116
; CHECK: bb.0:
124-
; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL1]], [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[BB_1:%.*]] ]
117+
; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ]
125118
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
126119
; CHECK: bb.1:
127-
; CHECK-NEXT: [[VAL2]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
128120
; CHECK-NEXT: br label [[BB_0]]
129121
; CHECK: exit:
130-
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
122+
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
131123
; CHECK-NEXT: ret i8 [[LOAD]]
132124
;
133125
entry:
@@ -174,21 +166,17 @@ join:
174166
ret i32 %v
175167
}
176168

177-
define i8 @loop_phi_late_memtransfer(i1 %cond) {
178-
; CHECK-LABEL: @loop_phi_late_memtransfer(
169+
define i8 @loop_phi_late_memtransfer_remove_alloca(i1 %cond) {
170+
; CHECK-LABEL: @loop_phi_late_memtransfer_remove_alloca(
179171
; CHECK-NEXT: entry:
180-
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [32 x i8], align 4, addrspace(1)
181-
; CHECK-NEXT: [[VAL1:%.*]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 1
182172
; CHECK-NEXT: br label [[BB_0:%.*]]
183173
; CHECK: bb.0:
184-
; CHECK-NEXT: [[PTR:%.*]] = phi ptr addrspace(1) [ [[VAL1]], [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[BB_1:%.*]] ]
174+
; CHECK-NEXT: [[PTR1:%.*]] = phi ptr [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 1), [[ENTRY:%.*]] ], [ getelementptr inbounds ([32 x i8], ptr @g1, i64 0, i64 2), [[BB_1:%.*]] ]
185175
; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB_1]], label [[EXIT:%.*]]
186176
; CHECK: bb.1:
187-
; CHECK-NEXT: [[VAL2]] = getelementptr inbounds [32 x i8], ptr addrspace(1) [[ALLOCA]], i64 0, i64 2
188-
; CHECK-NEXT: call void @llvm.memcpy.p1.p0.i64(ptr addrspace(1) noundef align 4 dereferenceable(256) [[ALLOCA]], ptr noundef nonnull align 16 dereferenceable(256) @g1, i64 256, i1 false)
189177
; CHECK-NEXT: br label [[BB_0]]
190178
; CHECK: exit:
191-
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr addrspace(1) [[PTR]], align 1
179+
; CHECK-NEXT: [[LOAD:%.*]] = load i8, ptr [[PTR1]], align 1
192180
; CHECK-NEXT: ret i8 [[LOAD]]
193181
;
194182
entry:

0 commit comments

Comments
 (0)