[llvm] r301196 - Compute safety information in a much finer granularity.

Xin Tong via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 11:38:58 PDT 2017


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 |= !isGuaranteedToTransferExecutionToSuccessor(&*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.


More information about the llvm-commits mailing list