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

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 31 18:11:38 PDT 2015


+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
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150831/c82fde4f/attachment-0001.html>


More information about the llvm-commits mailing list