[llvm] r243750 - [CaptureTracker] Provide an ordered basic block to PointerMayBeCapturedBefore

Bruno Cardoso Lopes via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 18 07:12:25 PDT 2015


Hi Kostya,

Sorry for the delay, just got back from vacations.
This is interesting. Did you measure compile time before the
introduction of this functionality?

Hard to tell offhand, but I would be happy to help if you can
synthesise a testcase!

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



-- 
Bruno Cardoso Lopes
http://www.brunocardoso.cc


More information about the llvm-commits mailing list