mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-06-29 00:30:47 +00:00
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243750 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
289b5e7f39
commit
8fea35acad
|
@ -55,6 +55,7 @@ class AnalysisUsage;
|
||||||
class MemTransferInst;
|
class MemTransferInst;
|
||||||
class MemIntrinsic;
|
class MemIntrinsic;
|
||||||
class DominatorTree;
|
class DominatorTree;
|
||||||
|
class OrderedBasicBlock;
|
||||||
|
|
||||||
/// The possible results of an alias query.
|
/// The possible results of an alias query.
|
||||||
///
|
///
|
||||||
|
@ -501,16 +502,19 @@ public:
|
||||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||||
ImmutableCallSite CS2);
|
ImmutableCallSite CS2);
|
||||||
|
|
||||||
/// Return information about whether a particular call site modifies or reads
|
/// \brief Return information about whether a particular call site modifies
|
||||||
/// the specified memory location.
|
/// 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,
|
ModRefInfo callCapturesBefore(const Instruction *I,
|
||||||
const MemoryLocation &MemLoc,
|
const MemoryLocation &MemLoc, DominatorTree *DT,
|
||||||
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,
|
ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
|
||||||
uint64_t Size, DominatorTree *DT) {
|
uint64_t Size, DominatorTree *DT,
|
||||||
return callCapturesBefore(I, MemoryLocation(P, Size), DT);
|
OrderedBasicBlock *OBB = nullptr) {
|
||||||
|
return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace llvm {
|
||||||
class Use;
|
class Use;
|
||||||
class Instruction;
|
class Instruction;
|
||||||
class DominatorTree;
|
class DominatorTree;
|
||||||
|
class OrderedBasicBlock;
|
||||||
|
|
||||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||||
/// by the enclosing function (which is required to exist). This routine can
|
/// 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
|
/// it or not. The boolean StoreCaptures specified whether storing the value
|
||||||
/// (or part of it) into memory anywhere automatically counts as capturing it
|
/// (or part of it) into memory anywhere automatically counts as capturing it
|
||||||
/// or not. Captures by the provided instruction are considered if the
|
/// 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 PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
|
||||||
bool StoreCaptures, const Instruction *I,
|
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
|
/// This callback is used in conjunction with PointerMayBeCaptured. In
|
||||||
/// addition to the interface here, you'll need to provide your own getters
|
/// addition to the interface here, you'll need to provide your own getters
|
||||||
|
|
66
include/llvm/Analysis/OrderedBasicBlock.h
Normal file
66
include/llvm/Analysis/OrderedBasicBlock.h
Normal file
|
@ -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
|
|
@ -335,13 +335,18 @@ ModRefInfo AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW,
|
||||||
return MRI_ModRef;
|
return MRI_ModRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is really just shoring-up a deficiency in alias analysis.
|
/// \brief Return information about whether a particular call site modifies
|
||||||
// BasicAA isn't willing to spend linear time determining whether an alloca
|
/// or reads the specified memory location \p MemLoc before instruction \p I
|
||||||
// was captured before or after this particular call, while we are. However,
|
/// in a BasicBlock. A ordered basic block \p OBB can be used to speed up
|
||||||
// with a smarter AA in place, this test is just wasting compile time.
|
/// 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,
|
ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
|
||||||
const MemoryLocation &MemLoc,
|
const MemoryLocation &MemLoc,
|
||||||
DominatorTree *DT) {
|
DominatorTree *DT,
|
||||||
|
OrderedBasicBlock *OBB) {
|
||||||
if (!DT)
|
if (!DT)
|
||||||
return MRI_ModRef;
|
return MRI_ModRef;
|
||||||
|
|
||||||
|
@ -356,7 +361,8 @@ ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
|
||||||
|
|
||||||
if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
|
if (llvm::PointerMayBeCapturedBefore(Object, /* ReturnCaptures */ true,
|
||||||
/* StoreCaptures */ true, I, DT,
|
/* StoreCaptures */ true, I, DT,
|
||||||
/* include Object */ true))
|
/* include Object */ true,
|
||||||
|
/* OrderedBasicBlock */ OBB))
|
||||||
return MRI_ModRef;
|
return MRI_ModRef;
|
||||||
|
|
||||||
unsigned ArgNo = 0;
|
unsigned ArgNo = 0;
|
||||||
|
|
|
@ -45,6 +45,7 @@ add_llvm_library(LLVMAnalysis
|
||||||
MemoryLocation.cpp
|
MemoryLocation.cpp
|
||||||
ModuleDebugInfoPrinter.cpp
|
ModuleDebugInfoPrinter.cpp
|
||||||
NoAliasAnalysis.cpp
|
NoAliasAnalysis.cpp
|
||||||
|
OrderedBasicBlock.cpp
|
||||||
PHITransAddr.cpp
|
PHITransAddr.cpp
|
||||||
PostDominators.cpp
|
PostDominators.cpp
|
||||||
PtrUseVisitor.cpp
|
PtrUseVisitor.cpp
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Analysis/CFG.h"
|
#include "llvm/Analysis/CFG.h"
|
||||||
#include "llvm/Analysis/CaptureTracking.h"
|
#include "llvm/Analysis/CaptureTracking.h"
|
||||||
|
#include "llvm/Analysis/OrderedBasicBlock.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
|
@ -52,63 +53,6 @@ namespace {
|
||||||
bool Captured;
|
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
|
/// Only find pointer captures which happen before the given instruction. Uses
|
||||||
/// the dominator tree to determine whether one instruction is before another.
|
/// 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
|
/// Only support the case where the Value is defined in the same basic block
|
||||||
|
@ -116,8 +60,8 @@ namespace {
|
||||||
struct CapturesBefore : public CaptureTracker {
|
struct CapturesBefore : public CaptureTracker {
|
||||||
|
|
||||||
CapturesBefore(bool ReturnCaptures, const Instruction *I, DominatorTree *DT,
|
CapturesBefore(bool ReturnCaptures, const Instruction *I, DominatorTree *DT,
|
||||||
bool IncludeI)
|
bool IncludeI, OrderedBasicBlock *IC)
|
||||||
: LocalInstCache(I->getParent()), BeforeHere(I), DT(DT),
|
: OrderedBB(IC), BeforeHere(I), DT(DT),
|
||||||
ReturnCaptures(ReturnCaptures), IncludeI(IncludeI), Captured(false) {}
|
ReturnCaptures(ReturnCaptures), IncludeI(IncludeI), Captured(false) {}
|
||||||
|
|
||||||
void tooManyUses() override { Captured = true; }
|
void tooManyUses() override { Captured = true; }
|
||||||
|
@ -131,7 +75,7 @@ namespace {
|
||||||
|
|
||||||
// Compute the case where both instructions are inside the same basic
|
// Compute the case where both instructions are inside the same basic
|
||||||
// block. Since instructions in the same BB as BeforeHere are numbered in
|
// 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.
|
// which are very expensive for large basic blocks.
|
||||||
if (BB == BeforeHere->getParent()) {
|
if (BB == BeforeHere->getParent()) {
|
||||||
// 'I' dominates 'BeforeHere' => not safe to prune.
|
// 'I' dominates 'BeforeHere' => not safe to prune.
|
||||||
|
@ -142,7 +86,7 @@ namespace {
|
||||||
// UseBB == BB, avoid pruning.
|
// UseBB == BB, avoid pruning.
|
||||||
if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I == BeforeHere)
|
if (isa<InvokeInst>(BeforeHere) || isa<PHINode>(I) || I == BeforeHere)
|
||||||
return false;
|
return false;
|
||||||
if (!LocalInstCache.dominates(BeforeHere, I))
|
if (!OrderedBB->dominates(BeforeHere, I))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 'BeforeHere' comes before 'I', it's safe to prune if we also
|
// 'BeforeHere' comes before 'I', it's safe to prune if we also
|
||||||
|
@ -196,7 +140,7 @@ namespace {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NumberedInstCache LocalInstCache;
|
OrderedBasicBlock *OrderedBB;
|
||||||
const Instruction *BeforeHere;
|
const Instruction *BeforeHere;
|
||||||
DominatorTree *DT;
|
DominatorTree *DT;
|
||||||
|
|
||||||
|
@ -238,21 +182,29 @@ bool llvm::PointerMayBeCaptured(const Value *V,
|
||||||
/// returning the value (or part of it) from the function counts as capturing
|
/// returning the value (or part of it) from the function counts as capturing
|
||||||
/// it or not. The boolean StoreCaptures specified whether storing the value
|
/// it or not. The boolean StoreCaptures specified whether storing the value
|
||||||
/// (or part of it) into memory anywhere automatically counts as capturing it
|
/// (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 llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
|
||||||
bool StoreCaptures, const Instruction *I,
|
bool StoreCaptures, const Instruction *I,
|
||||||
DominatorTree *DT, bool IncludeI) {
|
DominatorTree *DT, bool IncludeI,
|
||||||
|
OrderedBasicBlock *OBB) {
|
||||||
assert(!isa<GlobalValue>(V) &&
|
assert(!isa<GlobalValue>(V) &&
|
||||||
"It doesn't make sense to ask whether a global is captured.");
|
"It doesn't make sense to ask whether a global is captured.");
|
||||||
|
bool UseNewOBB = OBB == nullptr;
|
||||||
|
|
||||||
if (!DT)
|
if (!DT)
|
||||||
return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures);
|
return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures);
|
||||||
|
if (UseNewOBB)
|
||||||
|
OBB = new OrderedBasicBlock(I->getParent());
|
||||||
|
|
||||||
// TODO: See comment in PointerMayBeCaptured regarding what could be done
|
// TODO: See comment in PointerMayBeCaptured regarding what could be done
|
||||||
// with StoreCaptures.
|
// with StoreCaptures.
|
||||||
|
|
||||||
CapturesBefore CB(ReturnCaptures, I, DT, IncludeI);
|
CapturesBefore CB(ReturnCaptures, I, DT, IncludeI, OBB);
|
||||||
PointerMayBeCaptured(V, &CB);
|
PointerMayBeCaptured(V, &CB);
|
||||||
|
|
||||||
|
if (UseNewOBB)
|
||||||
|
delete OBB;
|
||||||
return CB.Captured;
|
return CB.Captured;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "llvm/Analysis/InstructionSimplify.h"
|
#include "llvm/Analysis/InstructionSimplify.h"
|
||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
#include "llvm/Analysis/PHITransAddr.h"
|
#include "llvm/Analysis/PHITransAddr.h"
|
||||||
|
#include "llvm/Analysis/OrderedBasicBlock.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
|
@ -420,6 +421,12 @@ MemDepResult MemoryDependenceAnalysis::getPointerDependencyFrom(
|
||||||
|
|
||||||
const DataLayout &DL = BB->getModule()->getDataLayout();
|
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.
|
// Walk backwards through the basic block, looking for dependencies.
|
||||||
while (ScanIt != BB->begin()) {
|
while (ScanIt != BB->begin()) {
|
||||||
Instruction *Inst = --ScanIt;
|
Instruction *Inst = --ScanIt;
|
||||||
|
@ -623,7 +630,7 @@ MemDepResult MemoryDependenceAnalysis::getPointerDependencyFrom(
|
||||||
ModRefInfo MR = AA->getModRefInfo(Inst, MemLoc);
|
ModRefInfo MR = AA->getModRefInfo(Inst, MemLoc);
|
||||||
// If necessary, perform additional analysis.
|
// If necessary, perform additional analysis.
|
||||||
if (MR == MRI_ModRef)
|
if (MR == MRI_ModRef)
|
||||||
MR = AA->callCapturesBefore(Inst, MemLoc, DT);
|
MR = AA->callCapturesBefore(Inst, MemLoc, DT, &OBB);
|
||||||
switch (MR) {
|
switch (MR) {
|
||||||
case MRI_NoModRef:
|
case MRI_NoModRef:
|
||||||
// If the call has no effect on the queried pointer, just ignore it.
|
// If the call has no effect on the queried pointer, just ignore it.
|
||||||
|
|
85
lib/Analysis/OrderedBasicBlock.cpp
Normal file
85
lib/Analysis/OrderedBasicBlock.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user