<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 18, 2015 at 7:12 AM, Bruno Cardoso Lopes <span dir="ltr"><<a href="mailto:bruno.cardoso@gmail.com" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=bruno.cardoso@gmail.com&cc=&bcc=&su=&body=','_blank');return false;">bruno.cardoso@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Kostya,<br>
<br>
Sorry for the delay, just got back from vacations.<br>
This is interesting. Did you measure compile time before the<br>
introduction of this functionality?<br></blockquote><div><br></div><div>The compile time was horrible even before this change due to <a href="https://llvm.org/bugs/show_bug.cgi?id=17409">https://llvm.org/bugs/show_bug.cgi?id=17409</a></div><div>It became worse and new hot functions have appeared, but now they are gone again (17409 is still there) </div><div><br></div><div>Thanks! </div><div><br></div><div>--kcc </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Hard to tell offhand, but I would be happy to help if you can<br>
synthesise a testcase!<br></blockquote><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div><div><br>
On Mon, Aug 31, 2015 at 10:11 PM, Kostya Serebryany <<a href="mailto:kcc@google.com" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=kcc@google.com&cc=&bcc=&su=&body=','_blank');return false;">kcc@google.com</a>> wrote:<br>
> +<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=llvm-commits@lists.llvm.org&cc=&bcc=&su=&body=','_blank');return false;">llvm-commits@lists.llvm.org</a><br>
><br>
> On Mon, Aug 31, 2015 at 6:08 PM, Kostya Serebryany <<a href="mailto:kcc@google.com" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=kcc@google.com&cc=&bcc=&su=&body=','_blank');return false;">kcc@google.com</a>> wrote:<br>
>><br>
>> Hi Bruno,<br>
>><br>
>> I have an input source file where this new functionality consumes<br>
>> almost half of compile time (~ 500 seconds out of total ~1000, which leads<br>
>> to compilation timeout)<br>
>> when compiled with -O2 -fsanitize=address.<br>
>><br>
>> The profile looks like this:<br>
>> +  25.41%            clang  clang               [.]<br>
>> llvm::OrderedBasicBlock::comesBefore(llvm::Instruction const*,<br>
>> llvm::Instruction const*)<br>
>> +  12.13%            clang  clang               [.]<br>
>> llvm::DenseMapBase<llvm::SmallDenseMap<llvm::Instruction const*, unsigned<br>
>> int, 32u, llvm::DenseMapInfo<llvm::Instruction const*>, ll<br>
>> +   3.79%            clang  clang               [.]<br>
>> llvm::DenseMapBase<llvm::SmallDenseMap<llvm::Instruction const*, unsigned<br>
>> int, 32u, llvm::DenseMapInfo<llvm::Instruction const*>, llvm::detail:▒<br>
>><br>
>> Is a substantially non-linear behavior expected here?<br>
>> Can the code be tuned to avoid it?<br>
>><br>
>> Unfortunately, I can't provide the reproducer (at least, not easy),<br>
>> but I'd be happy to make experiments if you suggest any.<br>
>><br>
>> Thanks,<br>
>><br>
>> --kcc<br>
>><br>
>><br>
>> On Fri, Jul 31, 2015 at 7:31 AM, Bruno Cardoso Lopes<br>
>> <<a href="mailto:bruno.cardoso@gmail.com" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=bruno.cardoso@gmail.com&cc=&bcc=&su=&body=','_blank');return false;">bruno.cardoso@gmail.com</a>> wrote:<br>
>>><br>
>>> Author: bruno<br>
>>> Date: Fri Jul 31 09:31:35 2015<br>
>>> New Revision: 243750<br>
>>><br>
>>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=243750&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=243750&view=rev</a><br>
>>> Log:<br>
>>> [CaptureTracker] Provide an ordered basic block to<br>
>>> PointerMayBeCapturedBefore<br>
>>><br>
>>> This patch is a follow up from r240560 and is a step further into<br>
>>> mitigating the compile time performance issues in CaptureTracker.<br>
>>><br>
>>> By providing the CaptureTracker with a "cached ordered basic block"<br>
>>> instead of computing it every time, MemDepAnalysis can use this cache<br>
>>> throughout its calls to AA->callCapturesBefore, avoiding to recompute it<br>
>>> for every scanned instruction. In the same testcase used in r240560,<br>
>>> compile time is reduced from 2min to 30s.<br>
>>><br>
>>> This also fixes PR22348.<br>
>>><br>
>>> rdar://problem/19230319<br>
>>> Differential Revision: <a href="http://reviews.llvm.org/D11364" rel="noreferrer" target="_blank">http://reviews.llvm.org/D11364</a><br>
>>><br>
>>> Added:<br>
>>>     llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h<br>
>>>     llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp<br>
>>> Modified:<br>
>>>     llvm/trunk/include/llvm/Analysis/AliasAnalysis.h<br>
>>>     llvm/trunk/include/llvm/Analysis/CaptureTracking.h<br>
>>>     llvm/trunk/lib/Analysis/AliasAnalysis.cpp<br>
>>>     llvm/trunk/lib/Analysis/CMakeLists.txt<br>
>>>     llvm/trunk/lib/Analysis/CaptureTracking.cpp<br>
>>>     llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp<br>
>>><br>
>>> Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)<br>
>>> +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Fri Jul 31 09:31:35<br>
>>> 2015<br>
>>> @@ -55,6 +55,7 @@ class AnalysisUsage;<br>
>>>  class MemTransferInst;<br>
>>>  class MemIntrinsic;<br>
>>>  class DominatorTree;<br>
>>> +class OrderedBasicBlock;<br>
>>><br>
>>>  /// The possible results of an alias query.<br>
>>>  ///<br>
>>> @@ -501,16 +502,19 @@ public:<br>
>>>    virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,<br>
>>>                                     ImmutableCallSite CS2);<br>
>>><br>
>>> -  /// Return information about whether a particular call site modifies<br>
>>> or reads<br>
>>> -  /// the specified memory location.<br>
>>> +  /// \brief Return information about whether a particular call site<br>
>>> modifies<br>
>>> +  /// or reads the specified memory location \p MemLoc before<br>
>>> instruction \p I<br>
>>> +  /// in a BasicBlock. A ordered basic block \p OBB can be used to speed<br>
>>> up<br>
>>> +  /// instruction ordering queries inside the BasicBlock containing \p<br>
>>> I.<br>
>>>    ModRefInfo callCapturesBefore(const Instruction *I,<br>
>>> -                                const MemoryLocation &MemLoc,<br>
>>> -                                DominatorTree *DT);<br>
>>> +                                const MemoryLocation &MemLoc,<br>
>>> DominatorTree *DT,<br>
>>> +                                OrderedBasicBlock *OBB = nullptr);<br>
>>><br>
>>> -  /// A convenience wrapper to synthesize a memory location.<br>
>>> +  /// \brief A convenience wrapper to synthesize a memory location.<br>
>>>    ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,<br>
>>> -                                uint64_t Size, DominatorTree *DT) {<br>
>>> -    return callCapturesBefore(I, MemoryLocation(P, Size), DT);<br>
>>> +                                uint64_t Size, DominatorTree *DT,<br>
>>> +                                OrderedBasicBlock *OBB = nullptr) {<br>
>>> +    return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);<br>
>>>    }<br>
>>><br>
>>>    /// @}<br>
>>><br>
>>> Modified: llvm/trunk/include/llvm/Analysis/CaptureTracking.h<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CaptureTracking.h?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CaptureTracking.h?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/include/llvm/Analysis/CaptureTracking.h (original)<br>
>>> +++ llvm/trunk/include/llvm/Analysis/CaptureTracking.h Fri Jul 31<br>
>>> 09:31:35 2015<br>
>>> @@ -20,6 +20,7 @@ namespace llvm {<br>
>>>    class Use;<br>
>>>    class Instruction;<br>
>>>    class DominatorTree;<br>
>>> +  class OrderedBasicBlock;<br>
>>><br>
>>>    /// PointerMayBeCaptured - Return true if this pointer value may be<br>
>>> captured<br>
>>>    /// by the enclosing function (which is required to exist).  This<br>
>>> routine can<br>
>>> @@ -41,10 +42,12 @@ namespace llvm {<br>
>>>    /// it or not.  The boolean StoreCaptures specified whether storing<br>
>>> the value<br>
>>>    /// (or part of it) into memory anywhere automatically counts as<br>
>>> capturing it<br>
>>>    /// or not. Captures by the provided instruction are considered if the<br>
>>> -  /// final parameter is true.<br>
>>> +  /// final parameter is true. An ordered basic block in \p OBB could be<br>
>>> used<br>
>>> +  /// to speed up capture-tracker queries.<br>
>>>    bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,<br>
>>>                                    bool StoreCaptures, const Instruction<br>
>>> *I,<br>
>>> -                                  DominatorTree *DT, bool IncludeI =<br>
>>> false);<br>
>>> +                                  DominatorTree *DT, bool IncludeI =<br>
>>> false,<br>
>>> +                                  OrderedBasicBlock *OBB = nullptr);<br>
>>><br>
>>>    /// This callback is used in conjunction with PointerMayBeCaptured. In<br>
>>>    /// addition to the interface here, you'll need to provide your own<br>
>>> getters<br>
>>><br>
>>> Added: llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h?rev=243750&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h?rev=243750&view=auto</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h (added)<br>
>>> +++ llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h Fri Jul 31<br>
>>> 09:31:35 2015<br>
>>> @@ -0,0 +1,66 @@<br>
>>> +//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++<br>
>>> -*-===//<br>
>>> +//<br>
>>> +//                     The LLVM Compiler Infrastructure<br>
>>> +//<br>
>>> +// This file is distributed under the University of Illinois Open Source<br>
>>> +// License. See LICENSE.TXT for details.<br>
>>> +//<br>
>>><br>
>>> +//===----------------------------------------------------------------------===//<br>
>>> +//<br>
>>> +// This file defines the OrderedBasicBlock class. OrderedBasicBlock<br>
>>> maintains<br>
>>> +// an interface where clients can query if one instruction comes before<br>
>>> another<br>
>>> +// in a BasicBlock. Since BasicBlock currently lacks a reliable way to<br>
>>> query<br>
>>> +// relative position between instructions one can use OrderedBasicBlock<br>
>>> to do<br>
>>> +// such queries. OrderedBasicBlock is lazily built on a source<br>
>>> BasicBlock and<br>
>>> +// maintains an internal Instruction -> Position map. A<br>
>>> OrderedBasicBlock<br>
>>> +// instance should be discarded whenever the source BasicBlock changes.<br>
>>> +//<br>
>>> +// It's currently used by the CaptureTracker in order to find relative<br>
>>> +// positions of a pair of instructions inside a BasicBlock.<br>
>>> +//<br>
>>><br>
>>> +//===----------------------------------------------------------------------===//<br>
>>> +<br>
>>> +#ifndef LLVM_ANALYSIS_ORDEREDBASICBLOCK_H<br>
>>> +#define LLVM_ANALYSIS_ORDEREDBASICBLOCK_H<br>
>>> +<br>
>>> +#include "llvm/ADT/DenseMap.h"<br>
>>> +#include "llvm/IR/BasicBlock.h"<br>
>>> +<br>
>>> +namespace llvm {<br>
>>> +<br>
>>> +class Instruction;<br>
>>> +class BasicBlock;<br>
>>> +<br>
>>> +class OrderedBasicBlock {<br>
>>> +private:<br>
>>> +  /// \brief Map a instruction to its position in a BasicBlock.<br>
>>> +  SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts;<br>
>>> +<br>
>>> +  /// \brief Keep track of last instruction inserted into \p<br>
>>> NumberedInsts.<br>
>>> +  /// It speeds up queries for uncached instructions by providing a<br>
>>> start point<br>
>>> +  /// for new queries in OrderedBasicBlock::comesBefore.<br>
>>> +  BasicBlock::const_iterator LastInstFound;<br>
>>> +<br>
>>> +  /// \brief The position/number to tag the next instruction to be<br>
>>> found.<br>
>>> +  unsigned NextInstPos;<br>
>>> +<br>
>>> +  /// \brief The source BasicBlock to map.<br>
>>> +  const BasicBlock *BB;<br>
>>> +<br>
>>> +  /// \brief Given no cached results, find if \p A comes before \p B in<br>
>>> \p BB.<br>
>>> +  /// Cache and number out instruction while walking \p BB.<br>
>>> +  bool comesBefore(const Instruction *A, const Instruction *B);<br>
>>> +<br>
>>> +public:<br>
>>> +  OrderedBasicBlock(const BasicBlock *BasicB);<br>
>>> +<br>
>>> +  /// \brief Find out whether \p A dominates \p B, meaning whether \p A<br>
>>> +  /// comes before \p B in \p BB. This is a simplification that<br>
>>> considers<br>
>>> +  /// cached instruction positions and ignores other basic blocks, being<br>
>>> +  /// only relevant to compare relative instructions positions inside \p<br>
>>> BB.<br>
>>> +  bool dominates(const Instruction *A, const Instruction *B);<br>
>>> +};<br>
>>> +<br>
>>> +} // End llvm namespace<br>
>>> +<br>
>>> +#endif<br>
>>><br>
>>> Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)<br>
>>> +++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Fri Jul 31 09:31:35 2015<br>
>>> @@ -335,13 +335,18 @@ ModRefInfo AliasAnalysis::getModRefInfo(<br>
>>>    return MRI_ModRef;<br>
>>>  }<br>
>>><br>
>>> -// FIXME: this is really just shoring-up a deficiency in alias analysis.<br>
>>> -// BasicAA isn't willing to spend linear time determining whether an<br>
>>> alloca<br>
>>> -// was captured before or after this particular call, while we are.<br>
>>> However,<br>
>>> -// with a smarter AA in place, this test is just wasting compile time.<br>
>>> +/// \brief Return information about whether a particular call site<br>
>>> modifies<br>
>>> +/// or reads the specified memory location \p MemLoc before instruction<br>
>>> \p I<br>
>>> +/// in a BasicBlock. A ordered basic block \p OBB can be used to speed<br>
>>> up<br>
>>> +/// instruction-ordering queries inside the BasicBlock containing \p I.<br>
>>> +/// FIXME: this is really just shoring-up a deficiency in alias<br>
>>> analysis.<br>
>>> +/// BasicAA isn't willing to spend linear time determining whether an<br>
>>> alloca<br>
>>> +/// was captured before or after this particular call, while we are.<br>
>>> However,<br>
>>> +/// with a smarter AA in place, this test is just wasting compile time.<br>
>>>  ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,<br>
>>>                                               const MemoryLocation<br>
>>> &MemLoc,<br>
>>> -                                             DominatorTree *DT) {<br>
>>> +                                             DominatorTree *DT,<br>
>>> +                                             OrderedBasicBlock *OBB) {<br>
>>>    if (!DT)<br>
>>>      return MRI_ModRef;<br>
>>><br>
>>> @@ -356,7 +361,8 @@ ModRefInfo AliasAnalysis::callCapturesBe<br>
>>><br>
>>>    if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */<br>
>>> true,<br>
>>>                                         /* StoreCaptures */ true, I, DT,<br>
>>> -                                       /* include Object */ true))<br>
>>> +                                       /* include Object */ true,<br>
>>> +                                       /* OrderedBasicBlock */ OBB))<br>
>>>      return MRI_ModRef;<br>
>>><br>
>>>    unsigned ArgNo = 0;<br>
>>><br>
>>> Modified: llvm/trunk/lib/Analysis/CMakeLists.txt<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)<br>
>>> +++ llvm/trunk/lib/Analysis/CMakeLists.txt Fri Jul 31 09:31:35 2015<br>
>>> @@ -45,6 +45,7 @@ add_llvm_library(LLVMAnalysis<br>
>>>    MemoryLocation.cpp<br>
>>>    ModuleDebugInfoPrinter.cpp<br>
>>>    NoAliasAnalysis.cpp<br>
>>> +  OrderedBasicBlock.cpp<br>
>>>    PHITransAddr.cpp<br>
>>>    PostDominators.cpp<br>
>>>    PtrUseVisitor.cpp<br>
>>><br>
>>> Modified: llvm/trunk/lib/Analysis/CaptureTracking.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CaptureTracking.cpp?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CaptureTracking.cpp?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Analysis/CaptureTracking.cpp (original)<br>
>>> +++ llvm/trunk/lib/Analysis/CaptureTracking.cpp Fri Jul 31 09:31:35 2015<br>
>>> @@ -21,6 +21,7 @@<br>
>>>  #include "llvm/Analysis/AliasAnalysis.h"<br>
>>>  #include "llvm/Analysis/CFG.h"<br>
>>>  #include "llvm/Analysis/CaptureTracking.h"<br>
>>> +#include "llvm/Analysis/OrderedBasicBlock.h"<br>
>>>  #include "llvm/IR/CallSite.h"<br>
>>>  #include "llvm/IR/Constants.h"<br>
>>>  #include "llvm/IR/Dominators.h"<br>
>>> @@ -52,63 +53,6 @@ namespace {<br>
>>>      bool Captured;<br>
>>>    };<br>
>>><br>
>>> -  struct NumberedInstCache {<br>
>>> -    SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts;<br>
>>> -    BasicBlock::const_iterator LastInstFound;<br>
>>> -    unsigned LastInstPos;<br>
>>> -    const BasicBlock *BB;<br>
>>> -<br>
>>> -    NumberedInstCache(const BasicBlock *BasicB) : LastInstPos(0),<br>
>>> BB(BasicB) {<br>
>>> -      LastInstFound = BB->end();<br>
>>> -    }<br>
>>> -<br>
>>> -    /// \brief Find the first instruction 'A' or 'B' in 'BB'. Number out<br>
>>> -    /// instruction while walking 'BB'.<br>
>>> -    const Instruction *find(const Instruction *A, const Instruction *B)<br>
>>> {<br>
>>> -      const Instruction *Inst = nullptr;<br>
>>> -      assert(!(LastInstFound == BB->end() && LastInstPos != 0) &&<br>
>>> -             "Instruction supposed to be in NumberedInsts");<br>
>>> -<br>
>>> -      // Start the search with the instruction found in the last lookup<br>
>>> round.<br>
>>> -      auto II = BB->begin();<br>
>>> -      auto IE = BB->end();<br>
>>> -      if (LastInstFound != IE)<br>
>>> -        II = std::next(LastInstFound);<br>
>>> -<br>
>>> -      // Number all instructions up to the point where we find 'A' or<br>
>>> 'B'.<br>
>>> -      for (++LastInstPos; II != IE; ++II, ++LastInstPos) {<br>
>>> -        Inst = cast<Instruction>(II);<br>
>>> -        NumberedInsts[Inst] = LastInstPos;<br>
>>> -        if (Inst == A || Inst == B)<br>
>>> -          break;<br>
>>> -      }<br>
>>> -<br>
>>> -      assert(II != IE && "Instruction not found?");<br>
>>> -      LastInstFound = II;<br>
>>> -      return Inst;<br>
>>> -    }<br>
>>> -<br>
>>> -    /// \brief Find out whether 'A' dominates 'B', meaning whether 'A'<br>
>>> -    /// comes before 'B' in 'BB'. This is a simplification that<br>
>>> considers<br>
>>> -    /// cached instruction positions and ignores other basic blocks,<br>
>>> being<br>
>>> -    /// only relevant to compare relative instructions positions inside<br>
>>> 'BB'.<br>
>>> -    bool dominates(const Instruction *A, const Instruction *B) {<br>
>>> -      assert(A->getParent() == B->getParent() &&<br>
>>> -             "Instructions must be in the same basic block!");<br>
>>> -<br>
>>> -      unsigned NA = NumberedInsts.lookup(A);<br>
>>> -      unsigned NB = NumberedInsts.lookup(B);<br>
>>> -      if (NA && NB)<br>
>>> -        return NA < NB;<br>
>>> -      if (NA)<br>
>>> -        return true;<br>
>>> -      if (NB)<br>
>>> -        return false;<br>
>>> -<br>
>>> -      return A == find(A, B);<br>
>>> -    }<br>
>>> -  };<br>
>>> -<br>
>>>    /// Only find pointer captures which happen before the given<br>
>>> instruction. Uses<br>
>>>    /// the dominator tree to determine whether one instruction is before<br>
>>> another.<br>
>>>    /// Only support the case where the Value is defined in the same basic<br>
>>> block<br>
>>> @@ -116,8 +60,8 @@ namespace {<br>
>>>    struct CapturesBefore : public CaptureTracker {<br>
>>><br>
>>>      CapturesBefore(bool ReturnCaptures, const Instruction *I,<br>
>>> DominatorTree *DT,<br>
>>> -                   bool IncludeI)<br>
>>> -      : LocalInstCache(I->getParent()), BeforeHere(I), DT(DT),<br>
>>> +                   bool IncludeI, OrderedBasicBlock *IC)<br>
>>> +      : OrderedBB(IC), BeforeHere(I), DT(DT),<br>
>>>          ReturnCaptures(ReturnCaptures), IncludeI(IncludeI),<br>
>>> Captured(false) {}<br>
>>><br>
>>>      void tooManyUses() override { Captured = true; }<br>
>>> @@ -131,7 +75,7 @@ namespace {<br>
>>><br>
>>>        // Compute the case where both instructions are inside the same<br>
>>> basic<br>
>>>        // block. Since instructions in the same BB as BeforeHere are<br>
>>> numbered in<br>
>>> -      // 'LocalInstCache', avoid using 'dominates' and<br>
>>> 'isPotentiallyReachable'<br>
>>> +      // 'OrderedBB', avoid using 'dominates' and<br>
>>> 'isPotentiallyReachable'<br>
>>>        // which are very expensive for large basic blocks.<br>
>>>        if (BB == BeforeHere->getParent()) {<br>
>>>          // 'I' dominates 'BeforeHere' => not safe to prune.<br>
>>> @@ -142,7 +86,7 @@ namespace {<br>
>>>          // UseBB == BB, avoid pruning.<br>
>>>          if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I ==<br>
>>> BeforeHere)<br>
>>>            return false;<br>
>>> -        if (!LocalInstCache.dominates(BeforeHere, I))<br>
>>> +        if (!OrderedBB->dominates(BeforeHere, I))<br>
>>>            return false;<br>
>>><br>
>>>          // 'BeforeHere' comes before 'I', it's safe to prune if we also<br>
>>> @@ -196,7 +140,7 @@ namespace {<br>
>>>        return true;<br>
>>>      }<br>
>>><br>
>>> -    NumberedInstCache LocalInstCache;<br>
>>> +    OrderedBasicBlock *OrderedBB;<br>
>>>      const Instruction *BeforeHere;<br>
>>>      DominatorTree *DT;<br>
>>><br>
>>> @@ -238,21 +182,29 @@ bool llvm::PointerMayBeCaptured(const Va<br>
>>>  /// returning the value (or part of it) from the function counts as<br>
>>> capturing<br>
>>>  /// it or not.  The boolean StoreCaptures specified whether storing the<br>
>>> value<br>
>>>  /// (or part of it) into memory anywhere automatically counts as<br>
>>> capturing it<br>
>>> -/// or not.<br>
>>> +/// or not. A ordered basic block \p OBB can be used in order to speed<br>
>>> up<br>
>>> +/// queries about relative order among instructions in the same basic<br>
>>> block.<br>
>>>  bool llvm::PointerMayBeCapturedBefore(const Value *V, bool<br>
>>> ReturnCaptures,<br>
>>>                                        bool StoreCaptures, const<br>
>>> Instruction *I,<br>
>>> -                                      DominatorTree *DT, bool IncludeI)<br>
>>> {<br>
>>> +                                      DominatorTree *DT, bool IncludeI,<br>
>>> +                                      OrderedBasicBlock *OBB) {<br>
>>>    assert(!isa<GlobalValue>(V) &&<br>
>>>           "It doesn't make sense to ask whether a global is captured.");<br>
>>> +  bool UseNewOBB = OBB == nullptr;<br>
>>><br>
>>>    if (!DT)<br>
>>>      return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures);<br>
>>> +  if (UseNewOBB)<br>
>>> +    OBB = new OrderedBasicBlock(I->getParent());<br>
>>><br>
>>>    // TODO: See comment in PointerMayBeCaptured regarding what could be<br>
>>> done<br>
>>>    // with StoreCaptures.<br>
>>><br>
>>> -  CapturesBefore CB(ReturnCaptures, I, DT, IncludeI);<br>
>>> +  CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, OBB);<br>
>>>    PointerMayBeCaptured(V, &CB);<br>
>>> +<br>
>>> +  if (UseNewOBB)<br>
>>> +    delete OBB;<br>
>>>    return CB.Captured;<br>
>>>  }<br>
>>><br>
>>><br>
>>> Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=243750&r1=243749&r2=243750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=243750&r1=243749&r2=243750&view=diff</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)<br>
>>> +++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Fri Jul 31<br>
>>> 09:31:35 2015<br>
>>> @@ -22,6 +22,7 @@<br>
>>>  #include "llvm/Analysis/InstructionSimplify.h"<br>
>>>  #include "llvm/Analysis/MemoryBuiltins.h"<br>
>>>  #include "llvm/Analysis/PHITransAddr.h"<br>
>>> +#include "llvm/Analysis/OrderedBasicBlock.h"<br>
>>>  #include "llvm/Analysis/ValueTracking.h"<br>
>>>  #include "llvm/IR/DataLayout.h"<br>
>>>  #include "llvm/IR/Dominators.h"<br>
>>> @@ -420,6 +421,12 @@ MemDepResult MemoryDependenceAnalysis::g<br>
>>><br>
>>>    const DataLayout &DL = BB->getModule()->getDataLayout();<br>
>>><br>
>>> +  // Create a numbered basic block to lazily compute and cache<br>
>>> instruction<br>
>>> +  // positions inside a BB. This is used to provide fast queries for<br>
>>> relative<br>
>>> +  // position between two instructions in a BB and can be used by<br>
>>> +  // AliasAnalysis::callCapturesBefore.<br>
>>> +  OrderedBasicBlock OBB(BB);<br>
>>> +<br>
>>>    // Walk backwards through the basic block, looking for dependencies.<br>
>>>    while (ScanIt != BB->begin()) {<br>
>>>      Instruction *Inst = --ScanIt;<br>
>>> @@ -623,7 +630,7 @@ MemDepResult MemoryDependenceAnalysis::g<br>
>>>      ModRefInfo MR = AA->getModRefInfo(Inst, MemLoc);<br>
>>>      // If necessary, perform additional analysis.<br>
>>>      if (MR == MRI_ModRef)<br>
>>> -      MR = AA->callCapturesBefore(Inst, MemLoc, DT);<br>
>>> +      MR = AA->callCapturesBefore(Inst, MemLoc, DT, &OBB);<br>
>>>      switch (MR) {<br>
>>>      case MRI_NoModRef:<br>
>>>        // If the call has no effect on the queried pointer, just ignore<br>
>>> it.<br>
>>><br>
>>> Added: llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp?rev=243750&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp?rev=243750&view=auto</a><br>
>>><br>
>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp (added)<br>
>>> +++ llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp Fri Jul 31 09:31:35<br>
>>> 2015<br>
>>> @@ -0,0 +1,85 @@<br>
>>> +//===- OrderedBasicBlock.cpp --------------------------------- -*- C++<br>
>>> -*-===//<br>
>>> +//<br>
>>> +//                     The LLVM Compiler Infrastructure<br>
>>> +//<br>
>>> +// This file is distributed under the University of Illinois Open Source<br>
>>> +// License. See LICENSE.TXT for details.<br>
>>> +//<br>
>>><br>
>>> +//===----------------------------------------------------------------------===//<br>
>>> +//<br>
>>> +// This file implements the OrderedBasicBlock class. OrderedBasicBlock<br>
>>> +// maintains an interface where clients can query if one instruction<br>
>>> comes<br>
>>> +// before another in a BasicBlock. Since BasicBlock currently lacks a<br>
>>> reliable<br>
>>> +// way to query relative position between instructions one can use<br>
>>> +// OrderedBasicBlock to do such queries. OrderedBasicBlock is lazily<br>
>>> built on a<br>
>>> +// source BasicBlock and maintains an internal Instruction -> Position<br>
>>> map. A<br>
>>> +// OrderedBasicBlock instance should be discarded whenever the source<br>
>>> +// BasicBlock changes.<br>
>>> +//<br>
>>> +// It's currently used by the CaptureTracker in order to find relative<br>
>>> +// positions of a pair of instructions inside a BasicBlock.<br>
>>> +//<br>
>>><br>
>>> +//===----------------------------------------------------------------------===//<br>
>>> +<br>
>>> +#include "llvm/Analysis/OrderedBasicBlock.h"<br>
>>> +#include "llvm/IR/Instruction.h"<br>
>>> +using namespace llvm;<br>
>>> +<br>
>>> +OrderedBasicBlock::OrderedBasicBlock(const BasicBlock *BasicB)<br>
>>> +    : NextInstPos(0), BB(BasicB) {<br>
>>> +  LastInstFound = BB->end();<br>
>>> +}<br>
>>> +<br>
>>> +/// \brief Given no cached results, find if \p A comes before \p B in \p<br>
>>> BB.<br>
>>> +/// Cache and number out instruction while walking \p BB.<br>
>>> +bool OrderedBasicBlock::comesBefore(const Instruction *A,<br>
>>> +                                    const Instruction *B) {<br>
>>> +  const Instruction *Inst = nullptr;<br>
>>> +  assert(!(LastInstFound == BB->end() && NextInstPos != 0) &&<br>
>>> +         "Instruction supposed to be in NumberedInsts");<br>
>>> +<br>
>>> +  // Start the search with the instruction found in the last lookup<br>
>>> round.<br>
>>> +  auto II = BB->begin();<br>
>>> +  auto IE = BB->end();<br>
>>> +  if (LastInstFound != IE)<br>
>>> +    II = std::next(LastInstFound);<br>
>>> +<br>
>>> +  // Number all instructions up to the point where we find 'A' or 'B'.<br>
>>> +  for (; II != IE; ++II) {<br>
>>> +    Inst = cast<Instruction>(II);<br>
>>> +    NumberedInsts[Inst] = NextInstPos++;<br>
>>> +    if (Inst == A || Inst == B)<br>
>>> +      break;<br>
>>> +  }<br>
>>> +<br>
>>> +  assert(II != IE && "Instruction not found?");<br>
>>> +  assert((Inst == A || Inst == B) && "Should find A or B");<br>
>>> +  LastInstFound = II;<br>
>>> +  return Inst == A;<br>
>>> +}<br>
>>> +<br>
>>> +/// \brief Find out whether \p A dominates \p B, meaning whether \p A<br>
>>> +/// comes before \p B in \p BB. This is a simplification that considers<br>
>>> +/// cached instruction positions and ignores other basic blocks, being<br>
>>> +/// only relevant to compare relative instructions positions inside \p<br>
>>> BB.<br>
>>> +bool OrderedBasicBlock::dominates(const Instruction *A, const<br>
>>> Instruction *B) {<br>
>>> +  assert(A->getParent() == B->getParent() &&<br>
>>> +         "Instructions must be in the same basic block!");<br>
>>> +<br>
>>> +  // First we lookup the instructions. If they don't exist, lookup will<br>
>>> give us<br>
>>> +  // back ::end(). If they both exist, we compare the numbers.<br>
>>> Otherwise, if NA<br>
>>> +  // exists and NB doesn't, it means NA must come before NB because we<br>
>>> would<br>
>>> +  // have numbered NB as well if it didn't. The same is true for NB. If<br>
>>> it<br>
>>> +  // exists, but NA does not, NA must come after it. If neither exist,<br>
>>> we need<br>
>>> +  // to number the block and cache the results (by calling comesBefore).<br>
>>> +  auto NAI = NumberedInsts.find(A);<br>
>>> +  auto NBI = NumberedInsts.find(B);<br>
>>> +  if (NAI != NumberedInsts.end() && NBI != NumberedInsts.end())<br>
>>> +    return NAI->second < NBI->second;<br>
>>> +  if (NAI != NumberedInsts.end())<br>
>>> +    return true;<br>
>>> +  if (NBI != NumberedInsts.end())<br>
>>> +    return false;<br>
>>> +<br>
>>> +  return comesBefore(A, B);<br>
>>> +}<br>
>>><br>
>>><br>
>>> _______________________________________________<br>
>>> llvm-commits mailing list<br>
>>> <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank" onclick="window.open('https://mail.google.com/mail/?view=cm&tf=1&to=llvm-commits@cs.uiuc.edu&cc=&bcc=&su=&body=','_blank');return false;">llvm-commits@cs.uiuc.edu</a><br>
>>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
>><br>
>><br>
><br>
<br>
<br>
<br>
</div></div><span><font color="#888888">--<br>
Bruno Cardoso Lopes<br>
<a href="http://www.brunocardoso.cc" rel="noreferrer" target="_blank">http://www.brunocardoso.cc</a><br>
</font></span></blockquote></div><br></div></div>