forked from OSchip/llvm-project
[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:
parent
68aa7de517
commit
eb83c7554e
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue