diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -160,13 +160,19 @@ // In this table, we will track which indices are loaded from the argument // (where direct loads are tracked as no indices). ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; - for (User *U : I->users()) { - Instruction *UI = cast(U); + for (auto Iter = I->user_begin(), End = I->user_end(); Iter != End;) { + Instruction *UI = cast(*Iter++); Type *SrcTy; if (LoadInst *L = dyn_cast(UI)) SrcTy = L->getType(); else SrcTy = cast(UI)->getSourceElementType(); + // Skip dead GEPs and remove them. + if (isa(UI) && UI->use_empty()) { + UI->eraseFromParent(); + continue; + } + IndicesVector Indices; Indices.reserve(UI->getNumOperands() - 1); // Since loads will only have a single operand, and GEPs only a single @@ -436,6 +442,8 @@ << "' in function '" << F->getName() << "'\n"); } else { GetElementPtrInst *GEP = cast(I->user_back()); + assert(!GEP->use_empty() && + "GEPs without uses should be cleaned up already"); IndicesVector Operands; Operands.reserve(GEP->getNumIndices()); for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); @@ -674,11 +682,7 @@ if (GEP->use_empty()) { // Dead GEP's cause trouble later. Just remove them if we run into // them. - GEP->eraseFromParent(); - // TODO: This runs the above loop over and over again for dead GEPs - // Couldn't we just do increment the UI iterator earlier and erase the - // use? - return isSafeToPromoteArgument(Arg, ByValTy, AAR, MaxElements); + continue; } if (!UpdateBaseTy(GEP->getSourceElementType())) diff --git a/llvm/test/Transforms/ArgumentPromotion/dead-gep-no-promotion.ll b/llvm/test/Transforms/ArgumentPromotion/dead-gep-no-promotion.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/ArgumentPromotion/dead-gep-no-promotion.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -argpromotion -S %s | FileCheck %s + +@glob = external global i32* + +; No arguments in @callee can be promoted, but it contains a dead GEP. Make +; sure it is not removed, as we do not perform any promotion. +define i32 @caller(i32* %ptr) { +; CHECK-LABEL: @caller( +; CHECK-NEXT: call void @callee(i32* [[PTR:%.*]], i32* [[PTR]], i32* [[PTR]]) +; CHECK-NEXT: ret i32 0 +; + call void @callee(i32* %ptr, i32* %ptr, i32* %ptr) + ret i32 0 +} + +define internal void @callee(i32* %arg, i32* %arg1, i32* %arg2) { +; CHECK-LABEL: define internal void @callee( +; CHECK-NEXT: call void @external_fn(i32* [[ARG:%.*]], i32* [[ARG1:%.*]]) +; CHECK-NEXT: [[DEAD_GEP:%.*]] = getelementptr inbounds i32, i32* [[ARG1]], i32 17 +; CHECK-NEXT: store i32* [[ARG2:%.*]], i32** @glob, align 8 +; CHECK-NEXT: ret void +; + call void @external_fn(i32* %arg, i32* %arg1) + %dead.gep = getelementptr inbounds i32, i32* %arg1, i32 17 + store i32* %arg2, i32** @glob, align 8 + ret void +} + +declare void @external_fn(i32*, i32*)