diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1802,14 +1802,27 @@ return ClassifyResult::None; }; - // If the save is right next to the restore, remove the restore. This can - // happen when variable allocas are DCE'd. + // If the stacksave and the stackrestore are in the same BB, and there is + // no intervening call, alloca, or stackrestore, remove the restore. This + // can happen when variable allocas are DCE'd. if (IntrinsicInst *SS = dyn_cast(II->getArgOperand(0))) { - if (SS->getIntrinsicID() == Intrinsic::stacksave) { - // Skip over debug info. - if (SS->getNextNonDebugInstruction() == II) { - return eraseInstFromFunction(CI); + if (SS->getIntrinsicID() == Intrinsic::stacksave && + SS->getParent() == II->getParent()) { + BasicBlock::iterator BI(SS); + bool CannotRemove = false; + for (++BI; &*BI != II; ++BI) { + // Note that we don't need to skip over stackrestores from the same + // stacksave because they will have been eliminated by this code when + // they were visited. + if (Classify(&*BI) == ClassifyResult::None) + continue; + + CannotRemove = true; + break; } + + if (!CannotRemove) + return eraseInstFromFunction(CI); } } diff --git a/llvm/test/Transforms/InstCombine/stacksaverestore.ll b/llvm/test/Transforms/InstCombine/stacksaverestore.ll --- a/llvm/test/Transforms/InstCombine/stacksaverestore.ll +++ b/llvm/test/Transforms/InstCombine/stacksaverestore.ll @@ -110,3 +110,27 @@ ; CHECK: call void @llvm.stackrestore(i8* %save1) ; CHECK: br i1 %done, label %loop, label %return ; CHECK: ret void + +define i32 @test4(i32 %m, i32* nocapture readonly %a) { +entry: + br label %for.body + +for.body: + %x.012 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %i.011 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + %0 = call i8* @llvm.stacksave() + %1 = load i32, i32* %a, align 4 + %mul = mul nsw i32 %1, %m + %add = add nsw i32 %mul, %x.012 + call void @llvm.stackrestore(i8* %0) + %inc = add nuw nsw i32 %i.011, 1 + %exitcond.not = icmp eq i32 %inc, 100 + br i1 %exitcond.not, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret i32 %add +} + +; CHECK-LABEL: define i32 @test4( +; CHECK-NOT: call void @llvm.stackrestore +; CHECK: ret i32 %add