[CGP] In optimizeMemoryInst handle select similarly to phi

This lets us optimize away selects that perform the same address computation in
two different ways and is also the first step towards being able to handle
selects between two different, but compatible, address computations.

Differential Revision: https://reviews.llvm.org/D38242

llvm-svn: 314794
This commit is contained in:
John Brawn 2017-10-03 13:04:15 +00:00
parent 68aa7de517
commit eb83c7554e
2 changed files with 33 additions and 7 deletions

View File

@ -4389,11 +4389,11 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
SmallPtrSet<Value*, 16> Visited;
worklist.push_back(Addr);
// Use a worklist to iteratively look through PHI nodes, and ensure that
// the addressing mode obtained from the non-PHI roots of the graph
// are equivalent.
// Use a worklist to iteratively look through PHI and select nodes, and
// ensure that the addressing mode obtained from the non-PHI/select roots of
// the graph are equivalent.
bool AddrModeFound = false;
bool PhiSeen = false;
bool PhiOrSelectSeen = false;
SmallVector<Instruction*, 16> AddrModeInsts;
ExtAddrMode AddrMode;
TypePromotionTransaction TPT(RemovedInsts);
@ -4419,7 +4419,14 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
if (PHINode *P = dyn_cast<PHINode>(V)) {
for (Value *IncValue : P->incoming_values())
worklist.push_back(IncValue);
PhiSeen = true;
PhiOrSelectSeen = true;
continue;
}
// Similar for select.
if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
worklist.push_back(SI->getFalseValue());
worklist.push_back(SI->getTrueValue());
PhiOrSelectSeen = true;
continue;
}
@ -4452,8 +4459,10 @@ bool CodeGenPrepare::optimizeMemoryInst(Instruction *MemoryInst, Value *Addr,
TPT.commit();
// If all the instructions matched are already in this BB, don't do anything.
// If we saw Phi node then it is not local definitely.
if (!PhiSeen && none_of(AddrModeInsts, [&](Value *V) {
// If we saw a Phi node then it is not local definitely, and if we saw a select
// then we want to push the address calculation past it even if it's already
// in this BB.
if (!PhiOrSelectSeen && none_of(AddrModeInsts, [&](Value *V) {
return IsNonLocalValue(V, MemoryInst->getParent());
})) {
DEBUG(dbgs() << "CGP: Found local addrmode: " << AddrMode << "\n");

View File

@ -251,3 +251,20 @@ backedge:
exit:
ret void
}
; Make sure we can eliminate a select when both arguments perform equivalent
; address computation.
define void @test10(i1 %cond, i64* %base) {
; CHECK-LABEL: @test10
; CHECK: getelementptr i8, {{.+}} 40
; CHECK-NOT: select
entry:
%gep1 = getelementptr inbounds i64, i64* %base, i64 5
%gep1.casted = bitcast i64* %gep1 to i32*
%base.casted = bitcast i64* %base to i32*
%gep2 = getelementptr inbounds i32, i32* %base.casted, i64 10
%casted.merged = select i1 %cond, i32* %gep1.casted, i32* %gep2
%v = load i32, i32* %casted.merged, align 4
call void @foo(i32 %v)
ret void
}