Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1,4 +1,4 @@ -//===- InstCombineCalls.cpp -----------------------------------------------===// +//===- nstCombineCalls.cpp -----------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -1472,24 +1472,30 @@ // start/end intrinsics in between). As this handles only the most trivial // cases, tracking the nesting level is not needed: // -// call @llvm.foo.start(i1 0) ; &I // call @llvm.foo.start(i1 0) -// call @llvm.foo.end(i1 0) ; This one will not be skipped: it will be removed +// call @llvm.foo.start(i1 0) ; This one won't be skipped: it will be removed // call @llvm.foo.end(i1 0) -static bool removeTriviallyEmptyRange(IntrinsicInst &I, unsigned StartID, - unsigned EndID, InstCombiner &IC) { - assert(I.getIntrinsicID() == StartID && - "Start intrinsic does not have expected ID"); - BasicBlock::iterator BI(I), BE(I.getParent()->end()); - for (++BI; BI != BE; ++BI) { - if (auto *E = dyn_cast(BI)) { - if (isa(E) || E->getIntrinsicID() == StartID) +// call @llvm.foo.end(i1 0) ; &I +static bool removeTriviallyEmptyRange( + IntrinsicInst &EndI, InstCombiner &IC, + std::function IsStart) { + // We start from the end intrinsic and scan backwards, so that InstCombine + // has already processed (and potentially removed) all the instructions + // before the end intrinsic. + BasicBlock::reverse_iterator BI(EndI), BE(EndI.getParent()->rend()); + for (; BI != BE; ++BI) { + if (auto *I = dyn_cast(&*BI)) { + if (isa(I) || + I->getIntrinsicID() == EndI.getIntrinsicID()) + continue; + if (IsStart(*I)) { + if (haveSameOperands(EndI, *I, EndI.getNumArgOperands())) { + IC.eraseInstFromFunction(*I); + IC.eraseInstFromFunction(EndI); + return true; + } + // Skip start intrinsics that don't pair with this end intrinsic. continue; - if (E->getIntrinsicID() == EndID && - haveSameOperands(I, *E, E->getNumArgOperands())) { - IC.eraseInstFromFunction(*E); - IC.eraseInstFromFunction(I); - return true; } } break; @@ -1747,13 +1753,11 @@ llvm_unreachable("All SpecialCase enumerators should be handled in switch."); } -Instruction *InstCombiner::visitVAStartInst(VAStartInst &I) { - removeTriviallyEmptyRange(I, Intrinsic::vastart, Intrinsic::vaend, *this); - return nullptr; -} - -Instruction *InstCombiner::visitVACopyInst(VACopyInst &I) { - removeTriviallyEmptyRange(I, Intrinsic::vacopy, Intrinsic::vaend, *this); +Instruction *InstCombiner::visitVAEndInst(VAEndInst &I) { + removeTriviallyEmptyRange(I, *this, [](const IntrinsicInst &I) { + return I.getIntrinsicID() == Intrinsic::vastart || + I.getIntrinsicID() == Intrinsic::vacopy; + }); return nullptr; } @@ -4037,7 +4041,7 @@ return eraseInstFromFunction(CI); break; } - case Intrinsic::lifetime_start: + case Intrinsic::lifetime_end: // Asan needs to poison memory to detect invalid access which is possible // even for empty lifetime range. if (II->getFunction()->hasFnAttribute(Attribute::SanitizeAddress) || @@ -4045,8 +4049,9 @@ II->getFunction()->hasFnAttribute(Attribute::SanitizeHWAddress)) break; - if (removeTriviallyEmptyRange(*II, Intrinsic::lifetime_start, - Intrinsic::lifetime_end, *this)) + if (removeTriviallyEmptyRange(*II, *this, [](const IntrinsicInst &I) { + return I.getIntrinsicID() == Intrinsic::lifetime_start; + })) return nullptr; break; case Intrinsic::assume: { Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -445,8 +445,7 @@ Instruction *visitShuffleVectorInst(ShuffleVectorInst &SVI); Instruction *visitExtractValueInst(ExtractValueInst &EV); Instruction *visitLandingPadInst(LandingPadInst &LI); - Instruction *visitVAStartInst(VAStartInst &I); - Instruction *visitVACopyInst(VACopyInst &I); + Instruction *visitVAEndInst(VAEndInst &I); Instruction *visitFreeze(FreezeInst &I); /// Specify what to return for unhandled instructions. Index: llvm/test/Transforms/InstCombine/lifetime.ll =================================================================== --- llvm/test/Transforms/InstCombine/lifetime.ll +++ llvm/test/Transforms/InstCombine/lifetime.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s +; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s declare void @llvm.dbg.declare(metadata, metadata, metadata) declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) Index: llvm/test/Transforms/InstCombine/vararg.ll =================================================================== --- llvm/test/Transforms/InstCombine/vararg.ll +++ llvm/test/Transforms/InstCombine/vararg.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | FileCheck %s +; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s %struct.__va_list = type { i8*, i8*, i8*, i32, i32 }