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