diff options
| -rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 23 | ||||
| -rw-r--r-- | llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode.ll | 17 |
2 files changed, 33 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index bbd1f59eb2f..e6a7a3e978c 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -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"); diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode.ll b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode.ll index 088b177c2e1..9d2e3fff59d 100644 --- a/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode.ll +++ b/llvm/test/Transforms/CodeGenPrepare/X86/sink-addrmode.ll @@ -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 +} |

