<div dir="ltr">+<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 31, 2015 at 6:08 PM, Kostya Serebryany <span dir="ltr"><<a href="mailto:kcc@google.com" target="_blank">kcc@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Bruno, <div><br></div><div>I have an input source file where this new functionality consumes</div><div>almost half of compile time (~ 500 seconds out of total ~1000, which leads to compilation timeout)</div><div>when compiled with -O2 -fsanitize=address. </div><div><br></div><div>The profile looks like this: </div><div>+ 25.41% clang clang [.] llvm::OrderedBasicBlock::comesBefore(llvm::Instruction const*, llvm::Instruction const*) <br></div><div>+ 12.13% clang clang [.] llvm::DenseMapBase<llvm::SmallDenseMap<llvm::Instruction const*, unsigned int, 32u, llvm::DenseMapInfo<llvm::Instruction const*>, ll<br></div><div><div>+ 3.79% clang clang [.] llvm::DenseMapBase<llvm::SmallDenseMap<llvm::Instruction const*, unsigned int, 32u, llvm::DenseMapInfo<llvm::Instruction const*>, llvm::detail:▒</div></div><div><br></div><div>Is a substantially non-linear behavior expected here?</div><div>Can the code be tuned to avoid it?</div><div><br></div><div>Unfortunately, I can't provide the reproducer (at least, not easy), </div><div>but I'd be happy to make experiments if you suggest any. </div><div><br></div><div>Thanks, </div><div><br></div><div>--kcc </div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 31, 2015 at 7:31 AM, Bruno Cardoso Lopes <span dir="ltr"><<a href="mailto:bruno.cardoso@gmail.com" target="_blank">bruno.cardoso@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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 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: <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>
--- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Fri Jul 31 09:31:35 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 or reads<br>
- /// the specified memory location.<br>
+ /// \brief Return information about whether a particular call site modifies<br>
+ /// or reads the specified memory location \p MemLoc before instruction \p I<br>
+ /// in a BasicBlock. A ordered basic block \p OBB can be used to speed up<br>
+ /// instruction ordering queries inside the BasicBlock containing \p I.<br>
ModRefInfo callCapturesBefore(const Instruction *I,<br>
- const MemoryLocation &MemLoc,<br>
- DominatorTree *DT);<br>
+ const MemoryLocation &MemLoc, 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: <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>
--- llvm/trunk/include/llvm/Analysis/CaptureTracking.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/CaptureTracking.h Fri Jul 31 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 captured<br>
/// by the enclosing function (which is required to exist). This routine can<br>
@@ -41,10 +42,12 @@ namespace llvm {<br>
/// it or not. The boolean StoreCaptures specified whether storing the value<br>
/// (or part of it) into memory anywhere automatically counts as 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 used<br>
+ /// to speed up capture-tracker queries.<br>
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,<br>
bool StoreCaptures, const Instruction *I,<br>
- DominatorTree *DT, bool IncludeI = false);<br>
+ DominatorTree *DT, bool IncludeI = 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 getters<br>
<br>
Added: llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h<br>
URL: <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>
--- llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h (added)<br>
+++ llvm/trunk/include/llvm/Analysis/OrderedBasicBlock.h Fri Jul 31 09:31:35 2015<br>
@@ -0,0 +1,66 @@<br>
+//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++ -*-===//<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>
+// This file defines the OrderedBasicBlock class. OrderedBasicBlock maintains<br>
+// an interface where clients can query if one instruction comes before another<br>
+// in a BasicBlock. Since BasicBlock currently lacks a reliable way to query<br>
+// relative position between instructions one can use OrderedBasicBlock to do<br>
+// such queries. OrderedBasicBlock is lazily built on a source BasicBlock and<br>
+// maintains an internal Instruction -> Position map. A 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>
+#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 NumberedInsts.<br>
+ /// It speeds up queries for uncached instructions by providing a 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 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 \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 considers<br>
+ /// cached instruction positions and ignores other basic blocks, being<br>
+ /// only relevant to compare relative instructions positions inside \p 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: <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>
--- 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 alloca<br>
-// was captured before or after this particular call, while we are. 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 modifies<br>
+/// or reads the specified memory location \p MemLoc before instruction \p I<br>
+/// in a BasicBlock. A ordered basic block \p OBB can be used to speed up<br>
+/// instruction-ordering queries inside the BasicBlock containing \p I.<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 alloca<br>
+/// was captured before or after this particular call, while we are. 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 &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 */ 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: <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>
--- 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: <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>
--- 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), 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>
- 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 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 (++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 considers<br>
- /// cached instruction positions and ignores other basic blocks, being<br>
- /// only relevant to compare relative instructions positions inside '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 instruction. Uses<br>
/// the dominator tree to determine whether one instruction is before another.<br>
/// Only support the case where the Value is defined in the same basic block<br>
@@ -116,8 +60,8 @@ namespace {<br>
struct CapturesBefore : public CaptureTracker {<br>
<br>
CapturesBefore(bool ReturnCaptures, const Instruction *I, 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), 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 basic<br>
// block. Since instructions in the same BB as BeforeHere are numbered in<br>
- // 'LocalInstCache', avoid using 'dominates' and 'isPotentiallyReachable'<br>
+ // 'OrderedBB', avoid using 'dominates' and '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 == 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 capturing<br>
/// it or not. The boolean StoreCaptures specified whether storing the value<br>
/// (or part of it) into memory anywhere automatically counts as capturing it<br>
-/// or not.<br>
+/// or not. A ordered basic block \p OBB can be used in order to speed up<br>
+/// queries about relative order among instructions in the same basic block.<br>
bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,<br>
bool StoreCaptures, const Instruction *I,<br>
- DominatorTree *DT, bool IncludeI) {<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 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: <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>
--- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Fri Jul 31 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 instruction<br>
+ // positions inside a BB. This is used to provide fast queries for 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 it.<br>
<br>
Added: llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp<br>
URL: <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>
--- llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp (added)<br>
+++ llvm/trunk/lib/Analysis/OrderedBasicBlock.cpp Fri Jul 31 09:31:35 2015<br>
@@ -0,0 +1,85 @@<br>
+//===- OrderedBasicBlock.cpp --------------------------------- -*- C++ -*-===//<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>
+// This file implements the OrderedBasicBlock class. OrderedBasicBlock<br>
+// maintains an interface where clients can query if one instruction comes<br>
+// before another in a BasicBlock. Since BasicBlock currently lacks a reliable<br>
+// way to query relative position between instructions one can use<br>
+// OrderedBasicBlock to do such queries. OrderedBasicBlock is lazily built on a<br>
+// source BasicBlock and maintains an internal Instruction -> Position 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>
+#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 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 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 BB.<br>
+bool OrderedBasicBlock::dominates(const Instruction *A, const 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 give us<br>
+ // back ::end(). If they both exist, we compare the numbers. Otherwise, if NA<br>
+ // exists and NB doesn't, it means NA must come before NB because we would<br>
+ // have numbered NB as well if it didn't. The same is true for NB. If it<br>
+ // exists, but NA does not, NA must come after it. If neither exist, 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">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>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>