[llvm] r301196 - Compute safety information in a much finer granularity.
Daniel Berlin via llvm-commits
llvm-commits at lists.llvm.org
Mon May 1 08:48:38 PDT 2017
Thanks
There are now more comments on the review anyway :)
On Mon, Apr 24, 2017 at 11:38 AM, Xin Tong via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Thanks. I will take a look.
> -Xin
>
> On Mon, Apr 24, 2017 at 11:38 AM, Evgenii Stepanov
> <eugeni.stepanov at gmail.com> wrote:
> > Verified and reverted.
> >
> > On Mon, Apr 24, 2017 at 11:34 AM, Evgenii Stepanov
> > <eugeni.stepanov at gmail.com> wrote:
> >> Hi,
> >>
> >> this must be yours. It it flakily crashing check-msan target on
> >> Linux/x86_64. To reproduce, opt -O3 the attached IR file.
> >>
> >> ==50569==ERROR: AddressSanitizer: heap-use-after-free on address
> >> 0x60e0000808f8 at pc 0x000000ccf4e2 bp 0x7ffe16d0e8c0 sp
> >> 0x7ffe16d0e8b8
> >> READ of size 8 at 0x60e0000808f8 thread T0
> >> #0 0xccf4e1 in llvm::Instruction::getParent() const
> >> /code/llvm/include/llvm/IR/Instruction.h:62:55
> >> #1 0x30cbbb5 in llvm::DominatorTree::dominates(llvm::Instruction
> >> const*, llvm::Instruction const*) const
> >> /code/llvm/lib/IR/Dominators.cpp:90:35
> >> #2 0x3cd60f2 in llvm::isGuaranteedToExecute(llvm::Instruction
> >> const&, llvm::DominatorTree const*, llvm::Loop const*,
> >> llvm::LoopSafetyInfo const*)
> >> /code/llvm/lib/Transforms/Utils/LoopUtils.cpp:1050:14
> >> #3 0x390bdd4 in (anonymous
> >> namespace)::LoopUnswitch::processCurrentLoop()
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:652:10
> >> #4 0x390a555 in (anonymous
> >> namespace)::LoopUnswitch::runOnLoop(llvm::Loop*, llvm::LPPassManager&)
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:518:16
> >> #5 0x265efc3 in
> >> llvm::LPPassManager::runOnFunction(llvm::Function&)
> >> /code/llvm/lib/Analysis/LoopPass.cpp:203:23
> >> #6 0x3157d2b in
> >> llvm::FPPassManager::runOnFunction(llvm::Function&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1513:27
> >> #7 0x24efdb2 in (anonymous
> >> namespace)::CGPassManager::RunPassOnSCC(llvm::Pass*,
> >> llvm::CallGraphSCC&, llvm::CallGraph&, bool&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:149:25
> >> #8 0x24ef78b in (anonymous
> >> namespace)::CGPassManager::RunAllPassesOnSCC(llvm::CallGraphSCC&,
> >> llvm::CallGraph&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:417:16
> >> #9 0x24eee8b in (anonymous
> >> namespace)::CGPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:473:18
> >> #10 0x31588cc in (anonymous
> >> namespace)::MPPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1590:27
> >> #11 0x3158385 in llvm::legacy::PassManagerImpl::run(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1693:44
> >> #12 0xc69ebf in main /code/llvm/tools/opt/opt.cpp:738:10
> >> #13 0x7f34fc5c0f44 in __libc_start_main
> >> /build/eglibc-MjiXCM/eglibc-2.19/csu/libc-start.c:287
> >> #14 0xb602c4 in _start (/code/build-llvm-asan/bin/opt+0xb602c4)
> >>
> >> 0x60e0000808f8 is located 120 bytes inside of 152-byte region
> >> [0x60e000080880,0x60e000080918)
> >> freed by thread T0 here:
> >> #0 0xc2fcc2 in operator delete(void*)
> >> /code/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:126:3
> >> #1 0x107cff9 in
> >> llvm::iplist_impl<llvm::simple_ilist<llvm::Instruction>,
> >> llvm::SymbolTableListTraits<llvm::Instruction>
> >>>::erase(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::
> Instruction,
> >> true, false, void>, false, false>)
> >> /code/llvm/include/llvm/ADT/ilist.h:281:5
> >> #2 0x2fa5a7c in
> >> llvm::iplist_impl<llvm::simple_ilist<llvm::Instruction>,
> >> llvm::SymbolTableListTraits<llvm::Instruction>
> >>>::erase(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::
> Instruction,
> >> true, false, void>, false, false>,
> >> llvm::ilist_iterator<llvm::ilist_detail::node_options<
> llvm::Instruction,
> >> true, false, void>, false, false>)
> >> /code/llvm/include/llvm/ADT/ilist.h:318:15
> >> #3 0x2fa17f7 in llvm::BasicBlock::~BasicBlock()
> >> /code/llvm/lib/IR/BasicBlock.cpp:85:12
> >> #4 0x2fa1a0d in llvm::BasicBlock::~BasicBlock()
> >> /code/llvm/lib/IR/BasicBlock.cpp:64:27
> >> #5 0x2fa4a59 in
> >> llvm::iplist_impl<llvm::simple_ilist<llvm::BasicBlock>,
> >> llvm::SymbolTableListTraits<llvm::BasicBlock>
> >>>::erase(llvm::ilist_iterator<llvm::ilist_detail::
> node_options<llvm::BasicBlock,
> >> true, false, void>, false, false>)
> >> /code/llvm/include/llvm/ADT/ilist.h:281:5
> >> #6 0x3ca62a2 in llvm::removeUnreachableBlocks(llvm::Function&,
> >> llvm::LazyValueInfo*)
> >> /code/llvm/lib/Transforms/Utils/Local.cpp:1725:33
> >> #7 0x3a2a34c in simplifyFunctionCFG(llvm::Function&,
> >> llvm::TargetTransformInfo const&, llvm::AssumptionCache*, int, bool)
> >> /code/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp:162:22
> >> #8 0x3157d2b in
> >> llvm::FPPassManager::runOnFunction(llvm::Function&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1513:27
> >> #9 0x24efdb2 in (anonymous
> >> namespace)::CGPassManager::RunPassOnSCC(llvm::Pass*,
> >> llvm::CallGraphSCC&, llvm::CallGraph&, bool&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:149:25
> >> #10 0x24ef78b in (anonymous
> >> namespace)::CGPassManager::RunAllPassesOnSCC(llvm::CallGraphSCC&,
> >> llvm::CallGraph&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:417:16
> >> #11 0x24eee8b in (anonymous
> >> namespace)::CGPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:473:18
> >> #12 0x31588cc in (anonymous
> >> namespace)::MPPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1590:27
> >> #13 0x3158385 in llvm::legacy::PassManagerImpl::run(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1693:44
> >> #14 0xc69ebf in main /code/llvm/tools/opt/opt.cpp:738:10
> >> #15 0x7f34fc5c0f44 in __libc_start_main
> >> /build/eglibc-MjiXCM/eglibc-2.19/csu/libc-start.c:287
> >>
> >> previously allocated by thread T0 here:
> >> #0 0xc2f0c2 in operator new(unsigned long)
> >> /code/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82:35
> >> #1 0x3202025 in llvm::User::allocateFixedOperandUser(unsigned
> >> long, unsigned int, unsigned int) /code/llvm/lib/IR/User.cpp:128:7
> >> #2 0x3202025 in llvm::User::operator new(unsigned long, unsigned
> >> int) /code/llvm/lib/IR/User.cpp:146
> >> #3 0x3122ce8 in llvm::CallInst::cloneImpl() const
> >> /code/llvm/lib/IR/Instructions.cpp:3955:11
> >> #4 0x310ab55 in llvm::Instruction::clone() const
> >> /code/llvm/include/llvm/IR/Instruction.def:186:1
> >> #5 0x3c345bf in llvm::CloneBasicBlock(llvm::BasicBlock const*,
> >> llvm::ValueMap<llvm::Value const*, llvm::WeakVH,
> >> llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false>
> >>> >&, llvm::Twine const&, llvm::Function*, llvm::ClonedCodeInfo*)
> >> /code/llvm/lib/Transforms/Utils/CloneFunction.cpp:52:32
> >> #6 0x39129f7 in (anonymous
> >> namespace)::LoopUnswitch::UnswitchNontrivialCondition(llvm::Value*,
> >> llvm::Constant*, llvm::Loop*, llvm::TerminatorInst*)
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1148:25
> >> #7 0x390ddf7 in (anonymous
> >> namespace)::LoopUnswitch::UnswitchIfProfitable(llvm::Value*,
> >> llvm::Constant*, llvm::TerminatorInst*)
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:826:3
> >> #8 0x390c004 in (anonymous
> >> namespace)::LoopUnswitch::processCurrentLoop()
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:670:13
> >> #9 0x390a555 in (anonymous
> >> namespace)::LoopUnswitch::runOnLoop(llvm::Loop*, llvm::LPPassManager&)
> >> /code/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:518:16
> >> #10 0x265efc3 in
> >> llvm::LPPassManager::runOnFunction(llvm::Function&)
> >> /code/llvm/lib/Analysis/LoopPass.cpp:203:23
> >> #11 0x3157d2b in
> >> llvm::FPPassManager::runOnFunction(llvm::Function&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1513:27
> >> #12 0x24efdb2 in (anonymous
> >> namespace)::CGPassManager::RunPassOnSCC(llvm::Pass*,
> >> llvm::CallGraphSCC&, llvm::CallGraph&, bool&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:149:25
> >> #13 0x24ef78b in (anonymous
> >> namespace)::CGPassManager::RunAllPassesOnSCC(llvm::CallGraphSCC&,
> >> llvm::CallGraph&, bool&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:417:16
> >> #14 0x24eee8b in (anonymous
> >> namespace)::CGPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/Analysis/CallGraphSCCPass.cpp:473:18
> >> #15 0x31588cc in (anonymous
> >> namespace)::MPPassManager::runOnModule(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1590:27
> >> #16 0x3158385 in llvm::legacy::PassManagerImpl::run(llvm::Module&)
> >> /code/llvm/lib/IR/LegacyPassManager.cpp:1693:44
> >> #17 0xc69ebf in main /code/llvm/tools/opt/opt.cpp:738:10
> >> #18 0x7f34fc5c0f44 in __libc_start_main
> >> /build/eglibc-MjiXCM/eglibc-2.19/csu/libc-start.c:287
> >>
> >> SUMMARY: AddressSanitizer: heap-use-after-free
> >> /code/llvm/include/llvm/IR/Instruction.h:62:55 in
> >> llvm::Instruction::getParent() const
> >> Shadow bytes around the buggy address:
> >> 0x0c1c800080c0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
> >> 0x0c1c800080d0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
> >> 0x0c1c800080e0: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
> >> 0x0c1c800080f0: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
> >> 0x0c1c80008100: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa
> >> =>0x0c1c80008110: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]
> >> 0x0c1c80008120: fd fd fd fa fa fa fa fa fa fa fa fa fd fd fd fd
> >> 0x0c1c80008130: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
> >> 0x0c1c80008140: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
> >> 0x0c1c80008150: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
> >> 0x0c1c80008160: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
> >> Shadow byte legend (one shadow byte represents 8 application bytes):
> >> Addressable: 00
> >> Partially addressable: 01 02 03 04 05 06 07
> >> Heap left redzone: fa
> >> Freed heap region: fd
> >> Stack left redzone: f1
> >> Stack mid redzone: f2
> >> Stack right redzone: f3
> >> Stack after return: f5
> >> Stack use after scope: f8
> >> Global redzone: f9
> >> Global init order: f6
> >> Poisoned by user: f7
> >> Container overflow: fc
> >> Array cookie: ac
> >> Intra object redzone: bb
> >> ASan internal: fe
> >> Left alloca redzone: ca
> >> Right alloca redzone: cb
> >>
> >>
> >>
> >>
> >> On Mon, Apr 24, 2017 at 10:12 AM, Xin Tong via llvm-commits
> >> <llvm-commits at lists.llvm.org> wrote:
> >>> Author: trentxintong
> >>> Date: Mon Apr 24 12:12:22 2017
> >>> New Revision: 301196
> >>>
> >>> URL: http://llvm.org/viewvc/llvm-project?rev=301196&view=rev
> >>> Log:
> >>> Compute safety information in a much finer granularity.
> >>>
> >>> Summary:
> >>> Instead of keeping a variable indicating whether there are early exits
> >>> in the loop. We keep all the early exits. This improves LICM's
> ability to
> >>> move instructions out of the loop based on is-guaranteed-to-execute.
> >>>
> >>> I am going to update compilation time as well soon.
> >>>
> >>> Reviewers: hfinkel, sanjoy, efriedma, mkuper
> >>>
> >>> Reviewed By: hfinkel
> >>>
> >>> Subscribers: llvm-commits, mzolotukhin
> >>>
> >>> Differential Revision: https://reviews.llvm.org/D32433
> >>>
> >>> Added:
> >>> llvm/trunk/test/Transforms/LICM/loop-early-exits.ll
> >>> Modified:
> >>> llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
> >>> llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> >>> llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
> >>> llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
> >>> llvm/trunk/test/Transforms/LICM/preheader-safe.ll
> >>>
> >>> Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/Transforms/Utils/LoopUtils.h?rev=301196&r1=301195&r2=301196&view=diff
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)
> >>> +++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Mon Apr 24
> 12:12:22 2017
> >>> @@ -46,9 +46,9 @@ class TargetLibraryInfo;
> >>> /// \brief Captures loop safety information.
> >>> /// It keep information for loop & its header may throw exception.
> >>> struct LoopSafetyInfo {
> >>> - bool MayThrow = false; // The current loop contains an
> instruction which
> >>> - // may throw.
> >>> - bool HeaderMayThrow = false; // Same as previous, but specific to
> loop header
> >>> + // The early exits in the loop, excluding loop exits.
> >>> + // These are calls that might throw, infinite loop, etc.
> >>> + SmallVector<Instruction *, 4> EarlyExits;
> >>> // Used to update funclet bundle operands.
> >>> DenseMap<BasicBlock *, ColorVector> BlockColors;
> >>>
> >>>
> >>> Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/Scalar/LICM.cpp?rev=301196&r1=301195&r2=301196&view=diff
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
> >>> +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Mon Apr 24 12:12:22 2017
> >>> @@ -478,27 +478,17 @@ bool llvm::hoistRegion(DomTreeNode *N, A
> >>> ///
> >>> void llvm::computeLoopSafetyInfo(LoopSafetyInfo *SafetyInfo, Loop
> *CurLoop) {
> >>> assert(CurLoop != nullptr && "CurLoop cant be null");
> >>> - BasicBlock *Header = CurLoop->getHeader();
> >>> - // Setting default safety values.
> >>> - SafetyInfo->MayThrow = false;
> >>> - SafetyInfo->HeaderMayThrow = false;
> >>> - // Iterate over header and compute safety info.
> >>> - for (BasicBlock::iterator I = Header->begin(), E = Header->end();
> >>> - (I != E) && !SafetyInfo->HeaderMayThrow; ++I)
> >>> - SafetyInfo->HeaderMayThrow |=
> >>> - !isGuaranteedToTransferExecutionToSuccessor(&*I);
> >>> -
> >>> - SafetyInfo->MayThrow = SafetyInfo->HeaderMayThrow;
> >>> - // Iterate over loop instructions and compute safety info.
> >>> - // Skip header as it has been computed and stored in HeaderMayThrow.
> >>> - // The first block in loopinfo.Blocks is guaranteed to be the
> header.
> >>> - assert(Header == *CurLoop->getBlocks().begin() && "First block must
> be header");
> >>> - for (Loop::block_iterator BB = std::next(CurLoop->block_begin()),
> >>> + // Iterate over loop instructions and compute early exit points.
> >>> + for (Loop::block_iterator BB = CurLoop->block_begin(),
> >>> BBE = CurLoop->block_end();
> >>> - (BB != BBE) && !SafetyInfo->MayThrow; ++BB)
> >>> - for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end();
> >>> - (I != E) && !SafetyInfo->MayThrow; ++I)
> >>> - SafetyInfo->MayThrow |= !isGuaranteedToTransferExecutio
> nToSuccessor(&*I);
> >>> + BB != BBE; ++BB) {
> >>> + for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I
> != E;
> >>> + ++I) {
> >>> + if (isGuaranteedToTransferExecutionToSuccessor(&*I))
> >>> + continue;
> >>> + SafetyInfo->EarlyExits.push_back(&*I);
> >>> + }
> >>> + }
> >>>
> >>> // Compute funclet colors if we might sink/hoist in a function with
> a funclet
> >>> // personality routine.
> >>> @@ -1094,7 +1084,7 @@ bool llvm::promoteLoopAccessesToScalars(
> >>>
> >>> // Do we know this object does not escape ?
> >>> bool IsKnownNonEscapingObject = false;
> >>> - if (SafetyInfo->MayThrow) {
> >>> + if (!SafetyInfo->EarlyExits.empty()) {
> >>> // If a loop can throw, we have to insert a store along each
> unwind edge.
> >>> // That said, we can't actually make the unwind edge explicit.
> Therefore,
> >>> // we have to prove that the store is dead along the unwind edge.
> >>>
> >>> Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/Scalar/LoopIdiomRecognize.cpp?rev=301196&r1=301195&r2=301196&
> view=diff
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
> >>> +++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Mon Apr
> 24 12:12:22 2017
> >>> @@ -272,7 +272,7 @@ bool LoopIdiomRecognize::runOnCountableL
> >>> // Give up if the loop has instructions may throw.
> >>> LoopSafetyInfo SafetyInfo;
> >>> computeLoopSafetyInfo(&SafetyInfo, CurLoop);
> >>> - if (SafetyInfo.MayThrow)
> >>> + if (!SafetyInfo.EarlyExits.empty())
> >>> return MadeChange;
> >>>
> >>> // Scan all the blocks in the loop that are not in subloops.
> >>>
> >>> Modified: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/Utils/LoopUtils.cpp?rev=301196&r1=301195&r2=301196&view=diff
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp (original)
> >>> +++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp Mon Apr 24 12:12:22
> 2017
> >>> @@ -1044,21 +1044,11 @@ bool llvm::isGuaranteedToExecute(const I
> >>> const DominatorTree *DT, const Loop
> *CurLoop,
> >>> const LoopSafetyInfo *SafetyInfo) {
> >>> // We have to check to make sure that the instruction dominates all
> >>> - // of the exit blocks. If it doesn't, then there is a path out of
> the loop
> >>> - // which does not execute this instruction, so we can't hoist it.
> >>> -
> >>> - // If the instruction is in the header block for the loop (which is
> very
> >>> - // common), it is always guaranteed to dominate the exit blocks.
> Since this
> >>> - // is a common case, and can save some work, check it now.
> >>> - if (Inst.getParent() == CurLoop->getHeader())
> >>> - // If there's a throw in the header block, we can't guarantee
> we'll reach
> >>> - // Inst.
> >>> - return !SafetyInfo->HeaderMayThrow;
> >>> -
> >>> - // Somewhere in this loop there is an instruction which may throw
> and make us
> >>> - // exit the loop.
> >>> - if (SafetyInfo->MayThrow)
> >>> - return false;
> >>> + // of the exit points. If it doesn't, then there is a path out of
> the loop
> >>> + // which does not execute this instruction and its not guaranteed
> to execute.
> >>> + for (Instruction *ExitInst : SafetyInfo->EarlyExits)
> >>> + if (!DT->dominates(&Inst, ExitInst))
> >>> + return false;
> >>>
> >>> // Get the exit blocks for the current loop.
> >>> SmallVector<BasicBlock *, 8> ExitBlocks;
> >>> @@ -1071,7 +1061,9 @@ bool llvm::isGuaranteedToExecute(const I
> >>>
> >>> // As a degenerate case, if the loop is statically infinite then we
> haven't
> >>> // proven anything since there are no exit blocks.
> >>> - if (ExitBlocks.empty())
> >>> + // However, we also special case instruction from the header as the
> header
> >>> + // is always guaranteed to execute.
> >>> + if (ExitBlocks.empty() && Inst.getParent() != CurLoop->getHeader())
> >>> return false;
> >>>
> >>> // FIXME: In general, we have to prove that the loop isn't an
> infinite loop.
> >>>
> >>> Added: llvm/trunk/test/Transforms/LICM/loop-early-exits.ll
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/LICM/loop-early-exits.ll?rev=301196&view=auto
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/test/Transforms/LICM/loop-early-exits.ll (added)
> >>> +++ llvm/trunk/test/Transforms/LICM/loop-early-exits.ll Mon Apr 24
> 12:12:22 2017
> >>> @@ -0,0 +1,82 @@
> >>> +; RUN: opt -S -licm < %s | FileCheck %s
> >>> +
> >>> +declare void @use(i64 %a)
> >>> +declare void @use_nothrow(i64 %a) nounwind
> >>> +declare void @use_nothing()
> >>> +
> >>> +; We can move this udiv out of the loop as it comes before
> >>> +; the call instruction that may throw.
> >>> +define void @throw_header1(i64 %x, i64 %y, i1* %cond) {
> >>> +; CHECK-LABEL: throw_header1
> >>> +; CHECK: %div = udiv i64 %x, %y
> >>> +; CHECK-LABEL: loop
> >>> +; CHECK: call void @use(i64 %div)
> >>> +entry:
> >>> + br label %loop
> >>> +
> >>> +loop: ; preds = %entry,
> %for.inc
> >>> + %div = udiv i64 %x, %y
> >>> + call void @use(i64 %div)
> >>> + br label %loop
> >>> +}
> >>> +
> >>> +; We can not move this udiv out of the loop as it comes after
> >>> +; the call instruction that may throw.
> >>> +define void @throw_header2(i64 %x, i64 %y, i1* %cond) {
> >>> +; CHECK-LABEL: throw_header2
> >>> +; CHECK-LABEL: loop
> >>> +; CHECK: call void @use_nothing()
> >>> +; CHECK: %div = udiv i64 %x, %y
> >>> +entry:
> >>> + br label %loop
> >>> +
> >>> +loop: ; preds = %entry,
> %for.inc
> >>> + call void @use_nothing()
> >>> + %div = udiv i64 %x, %y
> >>> + call void @use_nothrow(i64 %div)
> >>> + br label %loop
> >>> +}
> >>> +
> >>> +; We can move this udiv out of the loop as it comes before
> >>> +; the call instruction that may throw.
> >>> +define void @throw_body1(i64 %x, i64 %y, i1* %cond) {
> >>> +; CHECK-LABEL: throw_body1
> >>> +; CHECK: %div = udiv i64 %x, %y
> >>> +; CHECK-LABEL: loop
> >>> +entry:
> >>> + br label %loop
> >>> +
> >>> +loop: ; preds = %entry,
> %for.inc
> >>> + br label %body
> >>> +
> >>> +body:
> >>> + %div = udiv i64 %x, %y
> >>> + call void @use(i64 %div)
> >>> + br i1 undef, label %loop, label %exit
> >>> +
> >>> +exit:
> >>> + ret void
> >>> +}
> >>> +
> >>> +; We can not move this udiv out of the loop as it comes after
> >>> +; the call instruction that may throw.
> >>> +define void @throw_body2(i64 %x, i64 %y, i1* %cond) {
> >>> +; CHECK-LABEL: throw_body2
> >>> +; CHECK-LABEL: loop
> >>> +; CHECK: call void @use_nothing()
> >>> +; CHECK: %div = udiv i64 %x, %y
> >>> +entry:
> >>> + br label %loop
> >>> +
> >>> +loop: ; preds = %entry,
> %for.inc
> >>> + br label %body
> >>> +
> >>> +body:
> >>> + call void @use_nothing()
> >>> + %div = udiv i64 %x, %y
> >>> + call void @use_nothrow(i64 %div)
> >>> + br i1 undef, label %loop, label %exit
> >>> +
> >>> +exit:
> >>> + ret void
> >>> +}
> >>>
> >>> Modified: llvm/trunk/test/Transforms/LICM/preheader-safe.ll
> >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/LICM/preheader-safe.ll?rev=301196&r1=301195&r2=301196&view=diff
> >>> ============================================================
> ==================
> >>> --- llvm/trunk/test/Transforms/LICM/preheader-safe.ll (original)
> >>> +++ llvm/trunk/test/Transforms/LICM/preheader-safe.ll Mon Apr 24
> 12:12:22 2017
> >>> @@ -21,20 +21,6 @@ loop2:
> >>> call void @use_nothrow(i64 %div)
> >>> br label %loop
> >>> }
> >>> -; Negative test
> >>> -define void @throw_header(i64 %x, i64 %y, i1* %cond) {
> >>> -; CHECK-LABEL: throw_header
> >>> -; CHECK-LABEL: loop
> >>> -; CHECK: %div = udiv i64 %x, %y
> >>> -; CHECK: call void @use(i64 %div)
> >>> -entry:
> >>> - br label %loop
> >>> -
> >>> -loop: ; preds = %entry,
> %for.inc
> >>> - %div = udiv i64 %x, %y
> >>> - call void @use(i64 %div)
> >>> - br label %loop
> >>> -}
> >>>
> >>> ; The header is known no throw, but the loop is not. We can
> >>> ; still lift out of the header.
> >>>
> >>>
> >>> _______________________________________________
> >>> llvm-commits mailing list
> >>> llvm-commits at lists.llvm.org
> >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
>
> --
> Software Engineer
> Employee of Facebook Inc.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170501/9dd9742f/attachment.html>
More information about the llvm-commits
mailing list