initial
This commit is contained in:
598
thirdparty/clang/include/llvm/Analysis/AliasAnalysis.h
vendored
Normal file
598
thirdparty/clang/include/llvm/Analysis/AliasAnalysis.h
vendored
Normal file
@@ -0,0 +1,598 @@
|
||||
//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- 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 generic AliasAnalysis interface, which is used as the
|
||||
// common interface used by all clients of alias analysis information, and
|
||||
// implemented by all alias analysis implementations. Mod/Ref information is
|
||||
// also captured by this interface.
|
||||
//
|
||||
// Implementations of this interface must implement the various virtual methods,
|
||||
// which automatically provides functionality for the entire suite of client
|
||||
// APIs.
|
||||
//
|
||||
// This API identifies memory regions with the Location class. The pointer
|
||||
// component specifies the base memory address of the region. The Size specifies
|
||||
// the maximum size (in address units) of the memory region, or UnknownSize if
|
||||
// the size is not known. The TBAA tag identifies the "type" of the memory
|
||||
// reference; see the TypeBasedAliasAnalysis class for details.
|
||||
//
|
||||
// Some non-obvious details include:
|
||||
// - Pointers that point to two completely different objects in memory never
|
||||
// alias, regardless of the value of the Size component.
|
||||
// - NoAlias doesn't imply inequal pointers. The most obvious example of this
|
||||
// is two pointers to constant memory. Even if they are equal, constant
|
||||
// memory is never stored to, so there will never be any dependencies.
|
||||
// In this and other situations, the pointers may be both NoAlias and
|
||||
// MustAlias at the same time. The current API can only return one result,
|
||||
// though this is rarely a problem in practice.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASANALYSIS_H
|
||||
#define LLVM_ANALYSIS_ALIASANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Pass;
|
||||
class AnalysisUsage;
|
||||
class MemTransferInst;
|
||||
class MemIntrinsic;
|
||||
class DominatorTree;
|
||||
|
||||
class AliasAnalysis {
|
||||
protected:
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA; // Previous Alias Analysis to chain to.
|
||||
|
||||
protected:
|
||||
/// InitializeAliasAnalysis - Subclasses must call this method to initialize
|
||||
/// the AliasAnalysis interface before any other methods are called. This is
|
||||
/// typically called by the run* methods of these subclasses. This may be
|
||||
/// called multiple times.
|
||||
///
|
||||
void InitializeAliasAnalysis(Pass *P);
|
||||
|
||||
/// getAnalysisUsage - All alias analysis implementations should invoke this
|
||||
/// directly (using AliasAnalysis::getAnalysisUsage(AU)).
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
AliasAnalysis() : TD(0), TLI(0), AA(0) {}
|
||||
virtual ~AliasAnalysis(); // We want to be subclassed
|
||||
|
||||
/// UnknownSize - This is a special value which can be used with the
|
||||
/// size arguments in alias queries to indicate that the caller does not
|
||||
/// know the sizes of the potential memory references.
|
||||
static uint64_t const UnknownSize = ~UINT64_C(0);
|
||||
|
||||
/// getDataLayout - Return a pointer to the current DataLayout object, or
|
||||
/// null if no DataLayout object is available.
|
||||
///
|
||||
const DataLayout *getDataLayout() const { return TD; }
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
///
|
||||
const TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
|
||||
|
||||
/// getTypeStoreSize - Return the DataLayout store size for the given type,
|
||||
/// if known, or a conservative value otherwise.
|
||||
///
|
||||
uint64_t getTypeStoreSize(Type *Ty);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Alias Queries...
|
||||
///
|
||||
|
||||
/// Location - A description of a memory location.
|
||||
struct Location {
|
||||
/// Ptr - The address of the start of the location.
|
||||
const Value *Ptr;
|
||||
/// Size - The maximum size of the location, in address-units, or
|
||||
/// UnknownSize if the size is not known. Note that an unknown size does
|
||||
/// not mean the pointer aliases the entire virtual address space, because
|
||||
/// there are restrictions on stepping out of one object and into another.
|
||||
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
|
||||
uint64_t Size;
|
||||
/// TBAATag - The metadata node which describes the TBAA type of
|
||||
/// the location, or null if there is no known unique tag.
|
||||
const MDNode *TBAATag;
|
||||
|
||||
explicit Location(const Value *P = 0, uint64_t S = UnknownSize,
|
||||
const MDNode *N = 0)
|
||||
: Ptr(P), Size(S), TBAATag(N) {}
|
||||
|
||||
Location getWithNewPtr(const Value *NewPtr) const {
|
||||
Location Copy(*this);
|
||||
Copy.Ptr = NewPtr;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithNewSize(uint64_t NewSize) const {
|
||||
Location Copy(*this);
|
||||
Copy.Size = NewSize;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithoutTBAATag() const {
|
||||
Location Copy(*this);
|
||||
Copy.TBAATag = 0;
|
||||
return Copy;
|
||||
}
|
||||
};
|
||||
|
||||
/// getLocation - Fill in Loc with information about the memory reference by
|
||||
/// the given instruction.
|
||||
Location getLocation(const LoadInst *LI);
|
||||
Location getLocation(const StoreInst *SI);
|
||||
Location getLocation(const VAArgInst *VI);
|
||||
Location getLocation(const AtomicCmpXchgInst *CXI);
|
||||
Location getLocation(const AtomicRMWInst *RMWI);
|
||||
static Location getLocationForSource(const MemTransferInst *MTI);
|
||||
static Location getLocationForDest(const MemIntrinsic *MI);
|
||||
|
||||
/// Alias analysis result - Either we know for sure that it does not alias, we
|
||||
/// know for sure it must alias, or we don't know anything: The two pointers
|
||||
/// _might_ alias. This enum is designed so you can do things like:
|
||||
/// if (AA.alias(P1, P2)) { ... }
|
||||
/// to check to see if two pointers might alias.
|
||||
///
|
||||
/// See docs/AliasAnalysis.html for more information on the specific meanings
|
||||
/// of these values.
|
||||
///
|
||||
enum AliasResult {
|
||||
NoAlias = 0, ///< No dependencies.
|
||||
MayAlias, ///< Anything goes.
|
||||
PartialAlias, ///< Pointers differ, but pointees overlap.
|
||||
MustAlias ///< Pointers are equal.
|
||||
};
|
||||
|
||||
/// alias - The main low level interface to the alias analysis implementation.
|
||||
/// Returns an AliasResult indicating whether the two pointers are aliased to
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// alias analysis implementations.
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
AliasResult alias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return alias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
AliasResult alias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, UnknownSize, V2, UnknownSize);
|
||||
}
|
||||
|
||||
/// isNoAlias - A trivial helper function to check to see if the specified
|
||||
/// pointers are no-alias.
|
||||
bool isNoAlias(const Location &LocA, const Location &LocB) {
|
||||
return alias(LocA, LocB) == NoAlias;
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, const Value *V2) {
|
||||
return isNoAlias(Location(V1), Location(V2));
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
bool isMustAlias(const Location &LocA, const Location &LocB) {
|
||||
return alias(LocA, LocB) == MustAlias;
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
bool isMustAlias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, 1, V2, 1) == MustAlias;
|
||||
}
|
||||
|
||||
/// pointsToConstantMemory - If the specified memory location is
|
||||
/// known to be constant, return true. If OrLocal is true and the
|
||||
/// specified memory location is known to be "local" (derived from
|
||||
/// an alloca), return true. Otherwise return false.
|
||||
virtual bool pointsToConstantMemory(const Location &Loc,
|
||||
bool OrLocal = false);
|
||||
|
||||
/// pointsToConstantMemory - A convenient wrapper.
|
||||
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
|
||||
return pointsToConstantMemory(Location(P), OrLocal);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Simple mod/ref information...
|
||||
///
|
||||
|
||||
/// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are
|
||||
/// bits which may be or'd together.
|
||||
///
|
||||
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
|
||||
|
||||
/// These values define additional bits used to define the
|
||||
/// ModRefBehavior values.
|
||||
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
|
||||
|
||||
/// ModRefBehavior - Summary of how a function affects memory in the program.
|
||||
/// Loads from constant globals are not considered memory accesses for this
|
||||
/// interface. Also, functions may freely modify stack space local to their
|
||||
/// invocation without having to report it through these interfaces.
|
||||
enum ModRefBehavior {
|
||||
/// DoesNotAccessMemory - This function does not perform any non-local loads
|
||||
/// or stores to memory.
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readnone' attribute.
|
||||
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
|
||||
DoesNotAccessMemory = Nowhere | NoModRef,
|
||||
|
||||
/// OnlyReadsArgumentPointees - The only memory references in this function
|
||||
/// (if it has any) are non-volatile loads from objects pointed to by its
|
||||
/// pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
|
||||
OnlyReadsArgumentPointees = ArgumentPointees | Ref,
|
||||
|
||||
/// OnlyAccessesArgumentPointees - The only memory references in this
|
||||
/// function (if it has any) are non-volatile loads and stores from objects
|
||||
/// pointed to by its pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
|
||||
OnlyAccessesArgumentPointees = ArgumentPointees | ModRef,
|
||||
|
||||
/// OnlyReadsMemory - This function does not perform any non-local stores or
|
||||
/// volatile loads, but may read from any memory location.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readonly' attribute.
|
||||
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
|
||||
OnlyReadsMemory = Anywhere | Ref,
|
||||
|
||||
/// UnknownModRefBehavior - This indicates that the function could not be
|
||||
/// classified into one of the behaviors above.
|
||||
UnknownModRefBehavior = Anywhere | ModRef
|
||||
};
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given function.
|
||||
/// For use when the call site is not known.
|
||||
virtual ModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// doesNotAccessMemory - If the specified call is known to never read or
|
||||
/// write memory, return true. If the call only reads from known-constant
|
||||
/// memory, it is also legal to return true. Calls that unwind the stack
|
||||
/// are legal for this predicate.
|
||||
///
|
||||
/// Many optimizations (such as CSE and LICM) can be performed on such calls
|
||||
/// without worrying about aliasing properties, and many calls have this
|
||||
/// property (e.g. calls to 'sin' and 'cos').
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
///
|
||||
bool doesNotAccessMemory(ImmutableCallSite CS) {
|
||||
return getModRefBehavior(CS) == DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// doesNotAccessMemory - If the specified function is known to never read or
|
||||
/// write memory, return true. For use when the call site is not known.
|
||||
///
|
||||
bool doesNotAccessMemory(const Function *F) {
|
||||
return getModRefBehavior(F) == DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified call is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. Calls
|
||||
/// that unwind the stack are legal for this predicate.
|
||||
///
|
||||
/// This property allows many common optimizations to be performed in the
|
||||
/// absence of interfering store instructions, such as CSE of strlen calls.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
///
|
||||
bool onlyReadsMemory(ImmutableCallSite CS) {
|
||||
return onlyReadsMemory(getModRefBehavior(CS));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified function is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. For use
|
||||
/// when the call site is not known.
|
||||
///
|
||||
bool onlyReadsMemory(const Function *F) {
|
||||
return onlyReadsMemory(getModRefBehavior(F));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - Return true if functions with the specified behavior are
|
||||
/// known to only read from non-volatile memory (or not access memory at all).
|
||||
///
|
||||
static bool onlyReadsMemory(ModRefBehavior MRB) {
|
||||
return !(MRB & Mod);
|
||||
}
|
||||
|
||||
/// onlyAccessesArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to read and write at most from objects pointed to by
|
||||
/// their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool onlyAccessesArgPointees(ModRefBehavior MRB) {
|
||||
return !(MRB & Anywhere & ~ArgumentPointees);
|
||||
}
|
||||
|
||||
/// doesAccessArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to potentially read or write from objects pointed
|
||||
/// to be their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool doesAccessArgPointees(ModRefBehavior MRB) {
|
||||
return (MRB & ModRef) && (MRB & ArgumentPointees);
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether or not an instruction may
|
||||
/// read or write the specified memory location. An instruction
|
||||
/// that doesn't read or write memory may be trivially LICM'd for example.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Location &Loc) {
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
|
||||
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
|
||||
case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc);
|
||||
case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc);
|
||||
case Instruction::AtomicCmpXchg:
|
||||
return getModRefInfo((const AtomicCmpXchgInst*)I, Loc);
|
||||
case Instruction::AtomicRMW:
|
||||
return getModRefInfo((const AtomicRMWInst*)I, Loc);
|
||||
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
|
||||
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
|
||||
default: return NoModRef;
|
||||
}
|
||||
}
|
||||
|
||||
/// getModRefInfo - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for call sites) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(CS, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - Return information about whether
|
||||
/// a particular call modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(C), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(C, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - Return information about whether
|
||||
/// a particular invoke modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(I), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for loads) - Return information about whether
|
||||
/// a particular load modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for loads) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(L, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for stores) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for stores) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
|
||||
// Conservatively correct. (We could possibly be a bit smarter if
|
||||
// Loc is a alloca that doesn't escape.)
|
||||
return ModRef;
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - Return information about whether
|
||||
/// a particular cmpxchg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(CX, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - Return information about whether
|
||||
/// a particular atomicrmw modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(RMW, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for va_args) - Return information about whether
|
||||
/// a particular va_arg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for va_args) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether two call sites may refer
|
||||
/// to the same set of memory locations. See
|
||||
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
|
||||
/// for details.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2);
|
||||
|
||||
/// callCapturesBefore - Return information about whether a particular call
|
||||
/// site modifies or reads the specified memory location.
|
||||
ModRefResult callCapturesBefore(const Instruction *I,
|
||||
const AliasAnalysis::Location &MemLoc,
|
||||
DominatorTree *DT);
|
||||
|
||||
/// callCapturesBefore - A convenience wrapper.
|
||||
ModRefResult callCapturesBefore(const Instruction *I, const Value *P,
|
||||
uint64_t Size, DominatorTree *DT) {
|
||||
return callCapturesBefore(I, Location(P, Size), DT);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Higher level methods for querying mod/ref information.
|
||||
///
|
||||
|
||||
/// canBasicBlockModify - Return true if it is possible for execution of the
|
||||
/// specified basic block to modify the value pointed to by Ptr.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
|
||||
|
||||
/// canBasicBlockModify - A convenience wrapper.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){
|
||||
return canBasicBlockModify(BB, Location(P, Size));
|
||||
}
|
||||
|
||||
/// canInstructionRangeModify - Return true if it is possible for the
|
||||
/// execution of the specified instructions to modify the value pointed to by
|
||||
/// Ptr. The instructions to consider are all of the instructions in the
|
||||
/// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
|
||||
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
|
||||
const Location &Loc);
|
||||
|
||||
/// canInstructionRangeModify - A convenience wrapper.
|
||||
bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2,
|
||||
const Value *Ptr, uint64_t Size) {
|
||||
return canInstructionRangeModify(I1, I2, Location(Ptr, Size));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Methods that clients should call when they transform the program to allow
|
||||
/// alias analyses to update their internal data structures. Note that these
|
||||
/// methods may be called on any instruction, regardless of whether or not
|
||||
/// they have pointer-analysis implications.
|
||||
///
|
||||
|
||||
/// deleteValue - This method should be called whenever an LLVM Value is
|
||||
/// deleted from the program, for example when an instruction is found to be
|
||||
/// redundant and is eliminated.
|
||||
///
|
||||
virtual void deleteValue(Value *V);
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in the
|
||||
/// program is copied or cloned, introducing a new value. Note that analysis
|
||||
/// implementations should tolerate clients that use this method to introduce
|
||||
/// the same value multiple times: if the analysis already knows about a
|
||||
/// value, it should ignore the request.
|
||||
///
|
||||
virtual void copyValue(Value *From, Value *To);
|
||||
|
||||
/// addEscapingUse - This method should be used whenever an escaping use is
|
||||
/// added to a pointer value. Analysis implementations may either return
|
||||
/// conservative responses for that value in the future, or may recompute
|
||||
/// some or all internal state to continue providing precise responses.
|
||||
///
|
||||
/// Escaping uses are considered by anything _except_ the following:
|
||||
/// - GEPs or bitcasts of the pointer
|
||||
/// - Loads through the pointer
|
||||
/// - Stores through (but not of) the pointer
|
||||
virtual void addEscapingUse(Use &U);
|
||||
|
||||
/// replaceWithNewValue - This method is the obvious combination of the two
|
||||
/// above, and it provided as a helper to simplify client code.
|
||||
///
|
||||
void replaceWithNewValue(Value *Old, Value *New) {
|
||||
copyValue(Old, New);
|
||||
deleteValue(Old);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize DenseMapInfo for Location.
|
||||
template<>
|
||||
struct DenseMapInfo<AliasAnalysis::Location> {
|
||||
static inline AliasAnalysis::Location getEmptyKey() {
|
||||
return
|
||||
AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
|
||||
0, 0);
|
||||
}
|
||||
static inline AliasAnalysis::Location getTombstoneKey() {
|
||||
return
|
||||
AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(),
|
||||
0, 0);
|
||||
}
|
||||
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
|
||||
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
|
||||
DenseMapInfo<const MDNode *>::getHashValue(Val.TBAATag);
|
||||
}
|
||||
static bool isEqual(const AliasAnalysis::Location &LHS,
|
||||
const AliasAnalysis::Location &RHS) {
|
||||
return LHS.Ptr == RHS.Ptr &&
|
||||
LHS.Size == RHS.Size &&
|
||||
LHS.TBAATag == RHS.TBAATag;
|
||||
}
|
||||
};
|
||||
|
||||
/// isNoAliasCall - Return true if this pointer is returned by a noalias
|
||||
/// function.
|
||||
bool isNoAliasCall(const Value *V);
|
||||
|
||||
/// isIdentifiedObject - Return true if this pointer refers to a distinct and
|
||||
/// identifiable object. This returns true for:
|
||||
/// Global Variables and Functions (but not Global Aliases)
|
||||
/// Allocas
|
||||
/// ByVal and NoAlias Arguments
|
||||
/// NoAlias returns (e.g. calls to malloc)
|
||||
///
|
||||
bool isIdentifiedObject(const Value *V);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
437
thirdparty/clang/include/llvm/Analysis/AliasSetTracker.h
vendored
Normal file
437
thirdparty/clang/include/llvm/Analysis/AliasSetTracker.h
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- 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 two classes: AliasSetTracker and AliasSet. These interface
|
||||
// are used to classify a collection of pointer references into a maximal number
|
||||
// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker
|
||||
// object refers to memory disjoint from the other sets.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H
|
||||
#define LLVM_ANALYSIS_ALIASSETTRACKER_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
class AliasSetTracker;
|
||||
class AliasSet;
|
||||
|
||||
class AliasSet : public ilist_node<AliasSet> {
|
||||
friend class AliasSetTracker;
|
||||
|
||||
class PointerRec {
|
||||
Value *Val; // The pointer this record corresponds to.
|
||||
PointerRec **PrevInList, *NextInList;
|
||||
AliasSet *AS;
|
||||
uint64_t Size;
|
||||
const MDNode *TBAAInfo;
|
||||
public:
|
||||
PointerRec(Value *V)
|
||||
: Val(V), PrevInList(0), NextInList(0), AS(0), Size(0),
|
||||
TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {}
|
||||
|
||||
Value *getValue() const { return Val; }
|
||||
|
||||
PointerRec *getNext() const { return NextInList; }
|
||||
bool hasAliasSet() const { return AS != 0; }
|
||||
|
||||
PointerRec** setPrevInList(PointerRec **PIL) {
|
||||
PrevInList = PIL;
|
||||
return &NextInList;
|
||||
}
|
||||
|
||||
void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) {
|
||||
if (NewSize > Size) Size = NewSize;
|
||||
|
||||
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey())
|
||||
// We don't have a TBAAInfo yet. Set it to NewTBAAInfo.
|
||||
TBAAInfo = NewTBAAInfo;
|
||||
else if (TBAAInfo != NewTBAAInfo)
|
||||
// NewTBAAInfo conflicts with TBAAInfo.
|
||||
TBAAInfo = DenseMapInfo<const MDNode *>::getTombstoneKey();
|
||||
}
|
||||
|
||||
uint64_t getSize() const { return Size; }
|
||||
|
||||
/// getTBAAInfo - Return the TBAAInfo, or null if there is no
|
||||
/// information or conflicting information.
|
||||
const MDNode *getTBAAInfo() const {
|
||||
// If we have missing or conflicting TBAAInfo, return null.
|
||||
if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() ||
|
||||
TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey())
|
||||
return 0;
|
||||
return TBAAInfo;
|
||||
}
|
||||
|
||||
AliasSet *getAliasSet(AliasSetTracker &AST) {
|
||||
assert(AS && "No AliasSet yet!");
|
||||
if (AS->Forward) {
|
||||
AliasSet *OldAS = AS;
|
||||
AS = OldAS->getForwardedTarget(AST);
|
||||
AS->addRef();
|
||||
OldAS->dropRef(AST);
|
||||
}
|
||||
return AS;
|
||||
}
|
||||
|
||||
void setAliasSet(AliasSet *as) {
|
||||
assert(AS == 0 && "Already have an alias set!");
|
||||
AS = as;
|
||||
}
|
||||
|
||||
void eraseFromList() {
|
||||
if (NextInList) NextInList->PrevInList = PrevInList;
|
||||
*PrevInList = NextInList;
|
||||
if (AS->PtrListEnd == &NextInList) {
|
||||
AS->PtrListEnd = PrevInList;
|
||||
assert(*AS->PtrListEnd == 0 && "List not terminated right!");
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
PointerRec *PtrList, **PtrListEnd; // Doubly linked list of nodes.
|
||||
AliasSet *Forward; // Forwarding pointer.
|
||||
|
||||
// All instructions without a specific address in this alias set.
|
||||
std::vector<AssertingVH<Instruction> > UnknownInsts;
|
||||
|
||||
// RefCount - Number of nodes pointing to this AliasSet plus the number of
|
||||
// AliasSets forwarding to it.
|
||||
unsigned RefCount : 28;
|
||||
|
||||
/// AccessType - Keep track of whether this alias set merely refers to the
|
||||
/// locations of memory, whether it modifies the memory, or whether it does
|
||||
/// both. The lattice goes from "NoModRef" to either Refs or Mods, then to
|
||||
/// ModRef as necessary.
|
||||
///
|
||||
enum AccessType {
|
||||
NoModRef = 0, Refs = 1, // Ref = bit 1
|
||||
Mods = 2, ModRef = 3 // Mod = bit 2
|
||||
};
|
||||
unsigned AccessTy : 2;
|
||||
|
||||
/// AliasType - Keep track the relationships between the pointers in the set.
|
||||
/// Lattice goes from MustAlias to MayAlias.
|
||||
///
|
||||
enum AliasType {
|
||||
MustAlias = 0, MayAlias = 1
|
||||
};
|
||||
unsigned AliasTy : 1;
|
||||
|
||||
// Volatile - True if this alias set contains volatile loads or stores.
|
||||
bool Volatile : 1;
|
||||
|
||||
void addRef() { ++RefCount; }
|
||||
void dropRef(AliasSetTracker &AST) {
|
||||
assert(RefCount >= 1 && "Invalid reference count detected!");
|
||||
if (--RefCount == 0)
|
||||
removeFromTracker(AST);
|
||||
}
|
||||
|
||||
Instruction *getUnknownInst(unsigned i) const {
|
||||
assert(i < UnknownInsts.size());
|
||||
return UnknownInsts[i];
|
||||
}
|
||||
|
||||
public:
|
||||
/// Accessors...
|
||||
bool isRef() const { return AccessTy & Refs; }
|
||||
bool isMod() const { return AccessTy & Mods; }
|
||||
bool isMustAlias() const { return AliasTy == MustAlias; }
|
||||
bool isMayAlias() const { return AliasTy == MayAlias; }
|
||||
|
||||
// isVolatile - Return true if this alias set contains volatile loads or
|
||||
// stores.
|
||||
bool isVolatile() const { return Volatile; }
|
||||
|
||||
/// isForwardingAliasSet - Return true if this alias set should be ignored as
|
||||
/// part of the AliasSetTracker object.
|
||||
bool isForwardingAliasSet() const { return Forward; }
|
||||
|
||||
/// mergeSetIn - Merge the specified alias set into this alias set...
|
||||
///
|
||||
void mergeSetIn(AliasSet &AS, AliasSetTracker &AST);
|
||||
|
||||
// Alias Set iteration - Allow access to all of the pointer which are part of
|
||||
// this alias set...
|
||||
class iterator;
|
||||
iterator begin() const { return iterator(PtrList); }
|
||||
iterator end() const { return iterator(); }
|
||||
bool empty() const { return PtrList == 0; }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
/// Define an iterator for alias sets... this is just a forward iterator.
|
||||
class iterator : public std::iterator<std::forward_iterator_tag,
|
||||
PointerRec, ptrdiff_t> {
|
||||
PointerRec *CurNode;
|
||||
public:
|
||||
explicit iterator(PointerRec *CN = 0) : CurNode(CN) {}
|
||||
|
||||
bool operator==(const iterator& x) const {
|
||||
return CurNode == x.CurNode;
|
||||
}
|
||||
bool operator!=(const iterator& x) const { return !operator==(x); }
|
||||
|
||||
const iterator &operator=(const iterator &I) {
|
||||
CurNode = I.CurNode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type &operator*() const {
|
||||
assert(CurNode && "Dereferencing AliasSet.end()!");
|
||||
return *CurNode;
|
||||
}
|
||||
value_type *operator->() const { return &operator*(); }
|
||||
|
||||
Value *getPointer() const { return CurNode->getValue(); }
|
||||
uint64_t getSize() const { return CurNode->getSize(); }
|
||||
const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); }
|
||||
|
||||
iterator& operator++() { // Preincrement
|
||||
assert(CurNode && "Advancing past AliasSet.end()!");
|
||||
CurNode = CurNode->getNext();
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int) { // Postincrement
|
||||
iterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// Can only be created by AliasSetTracker. Also, ilist creates one
|
||||
// to serve as a sentinel.
|
||||
friend struct ilist_sentinel_traits<AliasSet>;
|
||||
AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0),
|
||||
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
|
||||
}
|
||||
|
||||
AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION;
|
||||
|
||||
PointerRec *getSomePointer() const {
|
||||
return PtrList;
|
||||
}
|
||||
|
||||
/// getForwardedTarget - Return the real alias set this represents. If this
|
||||
/// has been merged with another set and is forwarding, return the ultimate
|
||||
/// destination set. This also implements the union-find collapsing as well.
|
||||
AliasSet *getForwardedTarget(AliasSetTracker &AST) {
|
||||
if (!Forward) return this;
|
||||
|
||||
AliasSet *Dest = Forward->getForwardedTarget(AST);
|
||||
if (Dest != Forward) {
|
||||
Dest->addRef();
|
||||
Forward->dropRef(AST);
|
||||
Forward = Dest;
|
||||
}
|
||||
return Dest;
|
||||
}
|
||||
|
||||
void removeFromTracker(AliasSetTracker &AST);
|
||||
|
||||
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
|
||||
const MDNode *TBAAInfo,
|
||||
bool KnownMustAlias = false);
|
||||
void addUnknownInst(Instruction *I, AliasAnalysis &AA);
|
||||
void removeUnknownInst(Instruction *I) {
|
||||
for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i)
|
||||
if (UnknownInsts[i] == I) {
|
||||
UnknownInsts[i] = UnknownInsts.back();
|
||||
UnknownInsts.pop_back();
|
||||
--i; --e; // Revisit the moved entry.
|
||||
}
|
||||
}
|
||||
void setVolatile() { Volatile = true; }
|
||||
|
||||
public:
|
||||
/// aliasesPointer - Return true if the specified pointer "may" (or must)
|
||||
/// alias one of the members in the set.
|
||||
///
|
||||
bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
|
||||
AliasAnalysis &AA) const;
|
||||
bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
|
||||
};
|
||||
|
||||
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
|
||||
AS.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
||||
class AliasSetTracker {
|
||||
/// CallbackVH - A CallbackVH to arrange for AliasSetTracker to be
|
||||
/// notified whenever a Value is deleted.
|
||||
class ASTCallbackVH : public CallbackVH {
|
||||
AliasSetTracker *AST;
|
||||
virtual void deleted();
|
||||
virtual void allUsesReplacedWith(Value *);
|
||||
public:
|
||||
ASTCallbackVH(Value *V, AliasSetTracker *AST = 0);
|
||||
ASTCallbackVH &operator=(Value *V);
|
||||
};
|
||||
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
|
||||
/// compare and hash the value handle.
|
||||
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {};
|
||||
|
||||
AliasAnalysis &AA;
|
||||
ilist<AliasSet> AliasSets;
|
||||
|
||||
typedef DenseMap<ASTCallbackVH, AliasSet::PointerRec*,
|
||||
ASTCallbackVHDenseMapInfo>
|
||||
PointerMapType;
|
||||
|
||||
// Map from pointers to their node
|
||||
PointerMapType PointerMap;
|
||||
|
||||
public:
|
||||
/// AliasSetTracker ctor - Create an empty collection of AliasSets, and use
|
||||
/// the specified alias analysis object to disambiguate load and store
|
||||
/// addresses.
|
||||
explicit AliasSetTracker(AliasAnalysis &aa) : AA(aa) {}
|
||||
~AliasSetTracker() { clear(); }
|
||||
|
||||
/// add methods - These methods are used to add different types of
|
||||
/// instructions to the alias sets. Adding a new instruction can result in
|
||||
/// one of three actions happening:
|
||||
///
|
||||
/// 1. If the instruction doesn't alias any other sets, create a new set.
|
||||
/// 2. If the instruction aliases exactly one set, add it to the set
|
||||
/// 3. If the instruction aliases multiple sets, merge the sets, and add
|
||||
/// the instruction to the result.
|
||||
///
|
||||
/// These methods return true if inserting the instruction resulted in the
|
||||
/// addition of a new alias set (i.e., the pointer did not alias anything).
|
||||
///
|
||||
bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location
|
||||
bool add(LoadInst *LI);
|
||||
bool add(StoreInst *SI);
|
||||
bool add(VAArgInst *VAAI);
|
||||
bool add(Instruction *I); // Dispatch to one of the other add methods...
|
||||
void add(BasicBlock &BB); // Add all instructions in basic block
|
||||
void add(const AliasSetTracker &AST); // Add alias relations from another AST
|
||||
bool addUnknown(Instruction *I);
|
||||
|
||||
/// remove methods - These methods are used to remove all entries that might
|
||||
/// be aliased by the specified instruction. These methods return true if any
|
||||
/// alias sets were eliminated.
|
||||
// Remove a location
|
||||
bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo);
|
||||
bool remove(LoadInst *LI);
|
||||
bool remove(StoreInst *SI);
|
||||
bool remove(VAArgInst *VAAI);
|
||||
bool remove(Instruction *I);
|
||||
void remove(AliasSet &AS);
|
||||
bool removeUnknown(Instruction *I);
|
||||
|
||||
void clear();
|
||||
|
||||
/// getAliasSets - Return the alias sets that are active.
|
||||
///
|
||||
const ilist<AliasSet> &getAliasSets() const { return AliasSets; }
|
||||
|
||||
/// getAliasSetForPointer - Return the alias set that the specified pointer
|
||||
/// lives in. If the New argument is non-null, this method sets the value to
|
||||
/// true if a new alias set is created to contain the pointer (because the
|
||||
/// pointer didn't alias anything).
|
||||
AliasSet &getAliasSetForPointer(Value *P, uint64_t Size,
|
||||
const MDNode *TBAAInfo,
|
||||
bool *New = 0);
|
||||
|
||||
/// getAliasSetForPointerIfExists - Return the alias set containing the
|
||||
/// location specified if one exists, otherwise return null.
|
||||
AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size,
|
||||
const MDNode *TBAAInfo) {
|
||||
return findAliasSetForPointer(P, Size, TBAAInfo);
|
||||
}
|
||||
|
||||
/// containsPointer - Return true if the specified location is represented by
|
||||
/// this alias set, false otherwise. This does not modify the AST object or
|
||||
/// alias sets.
|
||||
bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const;
|
||||
|
||||
/// getAliasAnalysis - Return the underlying alias analysis object used by
|
||||
/// this tracker.
|
||||
AliasAnalysis &getAliasAnalysis() const { return AA; }
|
||||
|
||||
/// deleteValue method - This method is used to remove a pointer value from
|
||||
/// the AliasSetTracker entirely. It should be used when an instruction is
|
||||
/// deleted from the program to update the AST. If you don't use this, you
|
||||
/// would have dangling pointers to deleted instructions.
|
||||
///
|
||||
void deleteValue(Value *PtrVal);
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in the
|
||||
/// program is copied or cloned, introducing a new value. Note that it is ok
|
||||
/// for clients that use this method to introduce the same value multiple
|
||||
/// times: if the tracker already knows about a value, it will ignore the
|
||||
/// request.
|
||||
///
|
||||
void copyValue(Value *From, Value *To);
|
||||
|
||||
|
||||
typedef ilist<AliasSet>::iterator iterator;
|
||||
typedef ilist<AliasSet>::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return AliasSets.begin(); }
|
||||
const_iterator end() const { return AliasSets.end(); }
|
||||
|
||||
iterator begin() { return AliasSets.begin(); }
|
||||
iterator end() { return AliasSets.end(); }
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
friend class AliasSet;
|
||||
void removeAliasSet(AliasSet *AS);
|
||||
|
||||
// getEntryFor - Just like operator[] on the map, except that it creates an
|
||||
// entry for the pointer if it doesn't already exist.
|
||||
AliasSet::PointerRec &getEntryFor(Value *V) {
|
||||
AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)];
|
||||
if (Entry == 0)
|
||||
Entry = new AliasSet::PointerRec(V);
|
||||
return *Entry;
|
||||
}
|
||||
|
||||
AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo,
|
||||
AliasSet::AccessType E,
|
||||
bool &NewSet) {
|
||||
NewSet = false;
|
||||
AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet);
|
||||
AS.AccessTy |= E;
|
||||
return AS;
|
||||
}
|
||||
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
|
||||
const MDNode *TBAAInfo);
|
||||
|
||||
AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
|
||||
};
|
||||
|
||||
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) {
|
||||
AST.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
342
thirdparty/clang/include/llvm/Analysis/BlockFrequencyImpl.h
vendored
Normal file
342
thirdparty/clang/include/llvm/Analysis/BlockFrequencyImpl.h
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Shared implementation of BlockFrequency for IR and Machine Instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
|
||||
#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/Support/BlockFrequency.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
class BlockFrequencyInfo;
|
||||
class MachineBlockFrequencyInfo;
|
||||
|
||||
/// BlockFrequencyImpl implements block frequency algorithm for IR and
|
||||
/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ)
|
||||
/// for the entry block and then propagates frequencies using branch weights
|
||||
/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because
|
||||
/// algorithm can find "backedges" by itself.
|
||||
template<class BlockT, class FunctionT, class BlockProbInfoT>
|
||||
class BlockFrequencyImpl {
|
||||
|
||||
DenseMap<const BlockT *, BlockFrequency> Freqs;
|
||||
|
||||
BlockProbInfoT *BPI;
|
||||
|
||||
FunctionT *Fn;
|
||||
|
||||
typedef GraphTraits< Inverse<BlockT *> > GT;
|
||||
|
||||
const uint32_t EntryFreq;
|
||||
|
||||
std::string getBlockName(BasicBlock *BB) const {
|
||||
return BB->getName().str();
|
||||
}
|
||||
|
||||
std::string getBlockName(MachineBasicBlock *MBB) const {
|
||||
std::string str;
|
||||
raw_string_ostream ss(str);
|
||||
ss << "BB#" << MBB->getNumber();
|
||||
|
||||
if (const BasicBlock *BB = MBB->getBasicBlock())
|
||||
ss << " derived from LLVM BB " << BB->getName();
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void setBlockFreq(BlockT *BB, BlockFrequency Freq) {
|
||||
Freqs[BB] = Freq;
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n");
|
||||
}
|
||||
|
||||
/// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst
|
||||
/// edge probability.
|
||||
BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const {
|
||||
BranchProbability Prob = BPI->getEdgeProbability(Src, Dst);
|
||||
return getBlockFreq(Src) * Prob;
|
||||
}
|
||||
|
||||
/// incBlockFreq - Increase BB block frequency by FREQ.
|
||||
///
|
||||
void incBlockFreq(BlockT *BB, BlockFrequency Freq) {
|
||||
Freqs[BB] += Freq;
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq
|
||||
<< " --> " << Freqs[BB] << "\n");
|
||||
}
|
||||
|
||||
/// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing.
|
||||
///
|
||||
void divBlockFreq(BlockT *BB, BranchProbability Prob) {
|
||||
uint64_t N = Prob.getNumerator();
|
||||
assert(N && "Illegal division by zero!");
|
||||
uint64_t D = Prob.getDenominator();
|
||||
uint64_t Freq = (Freqs[BB].getFrequency() * D) / N;
|
||||
|
||||
// Should we assert it?
|
||||
if (Freq > UINT32_MAX)
|
||||
Freq = UINT32_MAX;
|
||||
|
||||
Freqs[BB] = BlockFrequency(Freq);
|
||||
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob
|
||||
<< ") --> " << Freqs[BB] << "\n");
|
||||
}
|
||||
|
||||
// All blocks in postorder.
|
||||
std::vector<BlockT *> POT;
|
||||
|
||||
// Map Block -> Position in reverse-postorder list.
|
||||
DenseMap<BlockT *, unsigned> RPO;
|
||||
|
||||
// Cycle Probability for each bloch.
|
||||
DenseMap<BlockT *, uint32_t> CycleProb;
|
||||
|
||||
// (reverse-)postorder traversal iterators.
|
||||
typedef typename std::vector<BlockT *>::iterator pot_iterator;
|
||||
typedef typename std::vector<BlockT *>::reverse_iterator rpot_iterator;
|
||||
|
||||
pot_iterator pot_begin() { return POT.begin(); }
|
||||
pot_iterator pot_end() { return POT.end(); }
|
||||
|
||||
rpot_iterator rpot_begin() { return POT.rbegin(); }
|
||||
rpot_iterator rpot_end() { return POT.rend(); }
|
||||
|
||||
rpot_iterator rpot_at(BlockT *BB) {
|
||||
rpot_iterator I = rpot_begin();
|
||||
unsigned idx = RPO[BB];
|
||||
assert(idx);
|
||||
std::advance(I, idx - 1);
|
||||
|
||||
assert(*I == BB);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
/// isReachable - Returns if BB block is reachable from the entry.
|
||||
///
|
||||
bool isReachable(BlockT *BB) {
|
||||
return RPO.count(BB);
|
||||
}
|
||||
|
||||
/// isBackedge - Return if edge Src -> Dst is a backedge.
|
||||
///
|
||||
bool isBackedge(BlockT *Src, BlockT *Dst) {
|
||||
assert(isReachable(Src));
|
||||
assert(isReachable(Dst));
|
||||
|
||||
unsigned a = RPO[Src];
|
||||
unsigned b = RPO[Dst];
|
||||
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
/// getSingleBlockPred - return single BB block predecessor or NULL if
|
||||
/// BB has none or more predecessors.
|
||||
BlockT *getSingleBlockPred(BlockT *BB) {
|
||||
typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
|
||||
if (PI == PE)
|
||||
return 0;
|
||||
|
||||
BlockT *Pred = *PI;
|
||||
|
||||
++PI;
|
||||
if (PI != PE)
|
||||
return 0;
|
||||
|
||||
return Pred;
|
||||
}
|
||||
|
||||
void doBlock(BlockT *BB, BlockT *LoopHead,
|
||||
SmallPtrSet<BlockT *, 8> &BlocksInLoop) {
|
||||
|
||||
DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n");
|
||||
setBlockFreq(BB, 0);
|
||||
|
||||
if (BB == LoopHead) {
|
||||
setBlockFreq(BB, EntryFreq);
|
||||
return;
|
||||
}
|
||||
|
||||
if(BlockT *Pred = getSingleBlockPred(BB)) {
|
||||
if (BlocksInLoop.count(Pred))
|
||||
setBlockFreq(BB, getEdgeFreq(Pred, BB));
|
||||
// TODO: else? irreducible, ignore it for now.
|
||||
return;
|
||||
}
|
||||
|
||||
bool isInLoop = false;
|
||||
bool isLoopHead = false;
|
||||
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *Pred = *PI;
|
||||
|
||||
if (isReachable(Pred) && isBackedge(Pred, BB)) {
|
||||
isLoopHead = true;
|
||||
} else if (BlocksInLoop.count(Pred)) {
|
||||
incBlockFreq(BB, getEdgeFreq(Pred, BB));
|
||||
isInLoop = true;
|
||||
}
|
||||
// TODO: else? irreducible.
|
||||
}
|
||||
|
||||
if (!isInLoop)
|
||||
return;
|
||||
|
||||
if (!isLoopHead)
|
||||
return;
|
||||
|
||||
assert(EntryFreq >= CycleProb[BB]);
|
||||
uint32_t CProb = CycleProb[BB];
|
||||
uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1;
|
||||
divBlockFreq(BB, BranchProbability(Numerator, EntryFreq));
|
||||
}
|
||||
|
||||
/// doLoop - Propagate block frequency down through the loop.
|
||||
void doLoop(BlockT *Head, BlockT *Tail) {
|
||||
DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", "
|
||||
<< getBlockName(Tail) << ")\n");
|
||||
|
||||
SmallPtrSet<BlockT *, 8> BlocksInLoop;
|
||||
|
||||
for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) {
|
||||
BlockT *BB = *I;
|
||||
doBlock(BB, Head, BlocksInLoop);
|
||||
|
||||
BlocksInLoop.insert(BB);
|
||||
if (I == E)
|
||||
break;
|
||||
}
|
||||
|
||||
// Compute loop's cyclic probability using backedges probabilities.
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(Head);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *Pred = *PI;
|
||||
assert(Pred);
|
||||
if (isReachable(Pred) && isBackedge(Pred, Head)) {
|
||||
uint64_t N = getEdgeFreq(Pred, Head).getFrequency();
|
||||
uint64_t D = getBlockFreq(Head).getFrequency();
|
||||
assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!");
|
||||
uint64_t Res = (N * EntryFreq) / D;
|
||||
|
||||
assert(Res <= UINT32_MAX);
|
||||
CycleProb[Head] += (uint32_t) Res;
|
||||
DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res
|
||||
<< " --> " << CycleProb[Head] << "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend class BlockFrequencyInfo;
|
||||
friend class MachineBlockFrequencyInfo;
|
||||
|
||||
BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { }
|
||||
|
||||
void doFunction(FunctionT *fn, BlockProbInfoT *bpi) {
|
||||
Fn = fn;
|
||||
BPI = bpi;
|
||||
|
||||
// Clear everything.
|
||||
RPO.clear();
|
||||
POT.clear();
|
||||
CycleProb.clear();
|
||||
Freqs.clear();
|
||||
|
||||
BlockT *EntryBlock = fn->begin();
|
||||
|
||||
std::copy(po_begin(EntryBlock), po_end(EntryBlock), std::back_inserter(POT));
|
||||
|
||||
unsigned RPOidx = 0;
|
||||
for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
|
||||
BlockT *BB = *I;
|
||||
RPO[BB] = ++RPOidx;
|
||||
DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n");
|
||||
}
|
||||
|
||||
// Travel over all blocks in postorder.
|
||||
for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) {
|
||||
BlockT *BB = *I;
|
||||
BlockT *LastTail = 0;
|
||||
DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n");
|
||||
|
||||
for (typename GT::ChildIteratorType
|
||||
PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB),
|
||||
PE = GraphTraits< Inverse<BlockT *> >::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
|
||||
BlockT *Pred = *PI;
|
||||
if (isReachable(Pred) && isBackedge(Pred, BB)
|
||||
&& (!LastTail || RPO[Pred] > RPO[LastTail]))
|
||||
LastTail = Pred;
|
||||
}
|
||||
|
||||
if (LastTail)
|
||||
doLoop(BB, LastTail);
|
||||
}
|
||||
|
||||
// At the end assume the whole function as a loop, and travel over it once
|
||||
// again.
|
||||
doLoop(*(rpot_begin()), *(pot_begin()));
|
||||
}
|
||||
|
||||
public:
|
||||
/// getBlockFreq - Return block frequency. Return 0 if we don't have it.
|
||||
BlockFrequency getBlockFreq(const BlockT *BB) const {
|
||||
typename DenseMap<const BlockT *, BlockFrequency>::const_iterator
|
||||
I = Freqs.find(BB);
|
||||
if (I != Freqs.end())
|
||||
return I->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS) const {
|
||||
OS << "\n\n---- Block Freqs ----\n";
|
||||
for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) {
|
||||
BlockT *BB = I++;
|
||||
OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n";
|
||||
|
||||
for (typename GraphTraits<BlockT *>::ChildIteratorType
|
||||
SI = GraphTraits<BlockT *>::child_begin(BB),
|
||||
SE = GraphTraits<BlockT *>::child_end(BB); SI != SE; ++SI) {
|
||||
BlockT *Succ = *SI;
|
||||
OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ)
|
||||
<< " = " << getEdgeFreq(BB, Succ) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump() const {
|
||||
print(dbgs());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
55
thirdparty/clang/include/llvm/Analysis/BlockFrequencyInfo.h
vendored
Normal file
55
thirdparty/clang/include/llvm/Analysis/BlockFrequencyInfo.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Loops should be simplified before this analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
|
||||
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/BlockFrequency.h"
|
||||
#include <climits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BranchProbabilityInfo;
|
||||
template<class BlockT, class FunctionT, class BranchProbInfoT>
|
||||
class BlockFrequencyImpl;
|
||||
|
||||
/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
|
||||
/// IR basic block frequencies.
|
||||
class BlockFrequencyInfo : public FunctionPass {
|
||||
|
||||
BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BlockFrequencyInfo();
|
||||
|
||||
~BlockFrequencyInfo();
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
void print(raw_ostream &O, const Module *M) const;
|
||||
|
||||
/// getblockFreq - Return block frequency. Return 0 if we don't have the
|
||||
/// information. Please note that initial frequency is equal to 1024. It means
|
||||
/// that we should not rely on the value itself, but only on the comparison to
|
||||
/// the other block frequencies. We do this to avoid using of floating points.
|
||||
///
|
||||
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
148
thirdparty/clang/include/llvm/Analysis/BranchProbabilityInfo.h
vendored
Normal file
148
thirdparty/clang/include/llvm/Analysis/BranchProbabilityInfo.h
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
//===--- BranchProbabilityInfo.h - Branch Probability Analysis --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass is used to evaluate branch probabilties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
|
||||
#define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
|
||||
namespace llvm {
|
||||
class LoopInfo;
|
||||
class raw_ostream;
|
||||
|
||||
/// \brief Analysis pass providing branch probability information.
|
||||
///
|
||||
/// This is a function analysis pass which provides information on the relative
|
||||
/// probabilities of each "edge" in the function's CFG where such an edge is
|
||||
/// defined by a pair (PredBlock and an index in the successors). The
|
||||
/// probability of an edge from one block is always relative to the
|
||||
/// probabilities of other edges from the block. The probabilites of all edges
|
||||
/// from a block sum to exactly one (100%).
|
||||
/// We use a pair (PredBlock and an index in the successors) to uniquely
|
||||
/// identify an edge, since we can have multiple edges from Src to Dst.
|
||||
/// As an example, we can have a switch which jumps to Dst with value 0 and
|
||||
/// value 10.
|
||||
class BranchProbabilityInfo : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BranchProbabilityInfo() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
bool runOnFunction(Function &F);
|
||||
void print(raw_ostream &OS, const Module *M = 0) const;
|
||||
|
||||
/// \brief Get an edge's probability, relative to other out-edges of the Src.
|
||||
///
|
||||
/// This routine provides access to the fractional probability between zero
|
||||
/// (0%) and one (100%) of this edge executing, relative to other edges
|
||||
/// leaving the 'Src' block. The returned probability is never zero, and can
|
||||
/// only be one if the source block has only one successor.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
unsigned IndexInSuccessors) const;
|
||||
|
||||
/// \brief Get the probability of going from Src to Dst.
|
||||
///
|
||||
/// It returns the sum of all probabilities for edges from Src to Dst.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Test if an edge is hot relative to other out-edges of the Src.
|
||||
///
|
||||
/// Check whether this edge out of the source block is 'hot'. We define hot
|
||||
/// as having a relative probability >= 80%.
|
||||
bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Retrieve the hot successor of a block if one exists.
|
||||
///
|
||||
/// Given a basic block, look through its successors and if one exists for
|
||||
/// which \see isEdgeHot would return true, return that successor block.
|
||||
BasicBlock *getHotSucc(BasicBlock *BB) const;
|
||||
|
||||
/// \brief Print an edge's probability.
|
||||
///
|
||||
/// Retrieves an edge's probability similarly to \see getEdgeProbability, but
|
||||
/// then prints that probability to the provided stream. That stream is then
|
||||
/// returned.
|
||||
raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Get the raw edge weight calculated for the edge.
|
||||
///
|
||||
/// This returns the raw edge weight. It is guaranteed to fall between 1 and
|
||||
/// UINT32_MAX. Note that the raw edge weight is not meaningful in isolation.
|
||||
/// This interface should be very carefully, and primarily by routines that
|
||||
/// are updating the analysis by later calling setEdgeWeight.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src,
|
||||
unsigned IndexInSuccessors) const;
|
||||
|
||||
/// \brief Get the raw edge weight calculated for the block pair.
|
||||
///
|
||||
/// This returns the sum of all raw edge weights from Src to Dst.
|
||||
/// It is guaranteed to fall between 1 and UINT32_MAX.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Set the raw edge weight for a given edge.
|
||||
///
|
||||
/// This allows a pass to explicitly set the edge weight for an edge. It can
|
||||
/// be used when updating the CFG to update and preserve the branch
|
||||
/// probability information. Read the implementation of how these edge
|
||||
/// weights are calculated carefully before using!
|
||||
void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors,
|
||||
uint32_t Weight);
|
||||
|
||||
private:
|
||||
// Since we allow duplicate edges from one basic block to another, we use
|
||||
// a pair (PredBlock and an index in the successors) to specify an edge.
|
||||
typedef std::pair<const BasicBlock *, unsigned> Edge;
|
||||
|
||||
// Default weight value. Used when we don't have information about the edge.
|
||||
// TODO: DEFAULT_WEIGHT makes sense during static predication, when none of
|
||||
// the successors have a weight yet. But it doesn't make sense when providing
|
||||
// weight to an edge that may have siblings with non-zero weights. This can
|
||||
// be handled various ways, but it's probably fine for an edge with unknown
|
||||
// weight to just "inherit" the non-zero weight of an adjacent successor.
|
||||
static const uint32_t DEFAULT_WEIGHT = 16;
|
||||
|
||||
DenseMap<Edge, uint32_t> Weights;
|
||||
|
||||
/// \brief Handle to the LoopInfo analysis.
|
||||
LoopInfo *LI;
|
||||
|
||||
/// \brief Track the last function we run over for printing.
|
||||
Function *LastF;
|
||||
|
||||
/// \brief Track the set of blocks directly succeeded by a returning block.
|
||||
SmallPtrSet<BasicBlock *, 16> PostDominatedByUnreachable;
|
||||
|
||||
/// \brief Get sum of the block successors' weights.
|
||||
uint32_t getSumForBlock(const BasicBlock *BB) const;
|
||||
|
||||
bool calcUnreachableHeuristics(BasicBlock *BB);
|
||||
bool calcMetadataWeights(BasicBlock *BB);
|
||||
bool calcPointerHeuristics(BasicBlock *BB);
|
||||
bool calcLoopBranchHeuristics(BasicBlock *BB);
|
||||
bool calcZeroHeuristics(BasicBlock *BB);
|
||||
bool calcFloatingPointHeuristics(BasicBlock *BB);
|
||||
bool calcInvokeHeuristics(BasicBlock *BB);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
114
thirdparty/clang/include/llvm/Analysis/CFGPrinter.h
vendored
Normal file
114
thirdparty/clang/include/llvm/Analysis/CFGPrinter.h
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
//===-- CFGPrinter.h - CFG printer external interface -----------*- 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 external functions that can be called to explicitly
|
||||
// instantiate the CFG printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CFGPRINTER_H
|
||||
#define LLVM_ANALYSIS_CFGPRINTER_H
|
||||
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
|
||||
namespace llvm {
|
||||
template<>
|
||||
struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
||||
|
||||
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
static std::string getGraphName(const Function *F) {
|
||||
return "CFG for '" + F->getName().str() + "' function";
|
||||
}
|
||||
|
||||
static std::string getSimpleNodeLabel(const BasicBlock *Node,
|
||||
const Function *) {
|
||||
if (!Node->getName().empty())
|
||||
return Node->getName().str();
|
||||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
WriteAsOperand(OS, Node, false);
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
static std::string getCompleteNodeLabel(const BasicBlock *Node,
|
||||
const Function *) {
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
if (Node->getName().empty()) {
|
||||
WriteAsOperand(OS, Node, false);
|
||||
OS << ":";
|
||||
}
|
||||
|
||||
OS << *Node;
|
||||
std::string OutStr = OS.str();
|
||||
if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
|
||||
|
||||
// Process string output to make it nicer...
|
||||
for (unsigned i = 0; i != OutStr.length(); ++i)
|
||||
if (OutStr[i] == '\n') { // Left justify
|
||||
OutStr[i] = '\\';
|
||||
OutStr.insert(OutStr.begin()+i+1, 'l');
|
||||
} else if (OutStr[i] == ';') { // Delete comments!
|
||||
unsigned Idx = OutStr.find('\n', i+1); // Find end of line
|
||||
OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx);
|
||||
--i;
|
||||
}
|
||||
|
||||
return OutStr;
|
||||
}
|
||||
|
||||
std::string getNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
if (isSimple())
|
||||
return getSimpleNodeLabel(Node, Graph);
|
||||
else
|
||||
return getCompleteNodeLabel(Node, Graph);
|
||||
}
|
||||
|
||||
static std::string getEdgeSourceLabel(const BasicBlock *Node,
|
||||
succ_const_iterator I) {
|
||||
// Label source of conditional branches with "T" or "F"
|
||||
if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator()))
|
||||
if (BI->isConditional())
|
||||
return (I == succ_begin(Node)) ? "T" : "F";
|
||||
|
||||
// Label source of switch edges with the associated value.
|
||||
if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) {
|
||||
unsigned SuccNo = I.getSuccessorIndex();
|
||||
|
||||
if (SuccNo == 0) return "def";
|
||||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
SwitchInst::ConstCaseIt Case =
|
||||
SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
|
||||
OS << Case.getCaseValue()->getValue();
|
||||
return OS.str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
FunctionPass *createCFGPrinterPass ();
|
||||
FunctionPass *createCFGOnlyPrinterPass ();
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
378
thirdparty/clang/include/llvm/Analysis/CallGraph.h
vendored
Normal file
378
thirdparty/clang/include/llvm/Analysis/CallGraph.h
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This interface is used to build and manipulate a call graph, which is a very
|
||||
// useful tool for interprocedural optimization.
|
||||
//
|
||||
// Every function in a module is represented as a node in the call graph. The
|
||||
// callgraph node keeps track of which functions the are called by the function
|
||||
// corresponding to the node.
|
||||
//
|
||||
// A call graph may contain nodes where the function that they correspond to is
|
||||
// null. These 'external' nodes are used to represent control flow that is not
|
||||
// represented (or analyzable) in the module. In particular, this analysis
|
||||
// builds one external node such that:
|
||||
// 1. All functions in the module without internal linkage will have edges
|
||||
// from this external node, indicating that they could be called by
|
||||
// functions outside of the module.
|
||||
// 2. All functions whose address is used for something more than a direct
|
||||
// call, for example being stored into a memory location will also have an
|
||||
// edge from this external node. Since they may be called by an unknown
|
||||
// caller later, they must be tracked as such.
|
||||
//
|
||||
// There is a second external node added for calls that leave this module.
|
||||
// Functions have a call edge to the external node iff:
|
||||
// 1. The function is external, reflecting the fact that they could call
|
||||
// anything without internal linkage or that has its address taken.
|
||||
// 2. The function contains an indirect function call.
|
||||
//
|
||||
// As an extension in the future, there may be multiple nodes with a null
|
||||
// function. These will be used when we can prove (through pointer analysis)
|
||||
// that an indirect call site can call only a specific set of functions.
|
||||
//
|
||||
// Because of these properties, the CallGraph captures a conservative superset
|
||||
// of all of the caller-callee relationships, which is useful for
|
||||
// transformations.
|
||||
//
|
||||
// The CallGraph class also attempts to figure out what the root of the
|
||||
// CallGraph is, which it currently does by looking for a function named 'main'.
|
||||
// If no function named 'main' is found, the external node is used as the entry
|
||||
// node, reflecting the fact that any function without internal linkage could
|
||||
// be called into (which is common for libraries).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLGRAPH_H
|
||||
#define LLVM_ANALYSIS_CALLGRAPH_H
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include "llvm/Support/IncludeFile.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
class CallGraphNode;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallGraph class definition
|
||||
//
|
||||
class CallGraph {
|
||||
protected:
|
||||
Module *Mod; // The module this call graph represents
|
||||
|
||||
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
|
||||
FunctionMapTy FunctionMap; // Map from a function to its node
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
//===---------------------------------------------------------------------
|
||||
// Accessors.
|
||||
//
|
||||
typedef FunctionMapTy::iterator iterator;
|
||||
typedef FunctionMapTy::const_iterator const_iterator;
|
||||
|
||||
/// getModule - Return the module the call graph corresponds to.
|
||||
///
|
||||
Module &getModule() const { return *Mod; }
|
||||
|
||||
inline iterator begin() { return FunctionMap.begin(); }
|
||||
inline iterator end() { return FunctionMap.end(); }
|
||||
inline const_iterator begin() const { return FunctionMap.begin(); }
|
||||
inline const_iterator end() const { return FunctionMap.end(); }
|
||||
|
||||
// Subscripting operators, return the call graph node for the provided
|
||||
// function
|
||||
inline const CallGraphNode *operator[](const Function *F) const {
|
||||
const_iterator I = FunctionMap.find(F);
|
||||
assert(I != FunctionMap.end() && "Function not in callgraph!");
|
||||
return I->second;
|
||||
}
|
||||
inline CallGraphNode *operator[](const Function *F) {
|
||||
const_iterator I = FunctionMap.find(F);
|
||||
assert(I != FunctionMap.end() && "Function not in callgraph!");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// Returns the CallGraphNode which is used to represent undetermined calls
|
||||
/// into the callgraph. Override this if you want behavioral inheritance.
|
||||
virtual CallGraphNode* getExternalCallingNode() const { return 0; }
|
||||
virtual CallGraphNode* getCallsExternalNode() const { return 0; }
|
||||
|
||||
/// Return the root/main method in the module, or some other root node, such
|
||||
/// as the externalcallingnode. Overload these if you behavioral
|
||||
/// inheritance.
|
||||
virtual CallGraphNode* getRoot() { return 0; }
|
||||
virtual const CallGraphNode* getRoot() const { return 0; }
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Functions to keep a call graph up to date with a function that has been
|
||||
// modified.
|
||||
//
|
||||
|
||||
/// removeFunctionFromModule - Unlink the function from this module, returning
|
||||
/// it. Because this removes the function from the module, the call graph
|
||||
/// node is destroyed. This is only valid if the function does not call any
|
||||
/// other functions (ie, there are no edges in it's CGN). The easiest way to
|
||||
/// do this is to dropAllReferences before calling this.
|
||||
///
|
||||
Function *removeFunctionFromModule(CallGraphNode *CGN);
|
||||
Function *removeFunctionFromModule(Function *F) {
|
||||
return removeFunctionFromModule((*this)[F]);
|
||||
}
|
||||
|
||||
/// getOrInsertFunction - This method is identical to calling operator[], but
|
||||
/// it will insert a new CallGraphNode for the specified function if one does
|
||||
/// not already exist.
|
||||
CallGraphNode *getOrInsertFunction(const Function *F);
|
||||
|
||||
/// spliceFunction - Replace the function represented by this node by another.
|
||||
/// This does not rescan the body of the function, so it is suitable when
|
||||
/// splicing the body of one function to another while also updating all
|
||||
/// callers from the old function to the new.
|
||||
///
|
||||
void spliceFunction(const Function *From, const Function *To);
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Pass infrastructure interface glue code.
|
||||
//
|
||||
protected:
|
||||
CallGraph() {}
|
||||
|
||||
public:
|
||||
virtual ~CallGraph() { destroy(); }
|
||||
|
||||
/// initialize - Call this method before calling other methods,
|
||||
/// re/initializes the state of the CallGraph.
|
||||
///
|
||||
void initialize(Module &M);
|
||||
|
||||
void print(raw_ostream &o, Module *) const;
|
||||
void dump() const;
|
||||
protected:
|
||||
// destroy - Release memory for the call graph
|
||||
virtual void destroy();
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CallGraphNode class definition.
|
||||
//
|
||||
class CallGraphNode {
|
||||
friend class CallGraph;
|
||||
|
||||
AssertingVH<Function> F;
|
||||
|
||||
// CallRecord - This is a pair of the calling instruction (a call or invoke)
|
||||
// and the callgraph node being called.
|
||||
public:
|
||||
typedef std::pair<WeakVH, CallGraphNode*> CallRecord;
|
||||
private:
|
||||
std::vector<CallRecord> CalledFunctions;
|
||||
|
||||
/// NumReferences - This is the number of times that this CallGraphNode occurs
|
||||
/// in the CalledFunctions array of this or other CallGraphNodes.
|
||||
unsigned NumReferences;
|
||||
|
||||
CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
void DropRef() { --NumReferences; }
|
||||
void AddRef() { ++NumReferences; }
|
||||
public:
|
||||
typedef std::vector<CallRecord> CalledFunctionsVector;
|
||||
|
||||
|
||||
// CallGraphNode ctor - Create a node for the specified function.
|
||||
inline CallGraphNode(Function *f) : F(f), NumReferences(0) {}
|
||||
~CallGraphNode() {
|
||||
assert(NumReferences == 0 && "Node deleted while references remain");
|
||||
}
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Accessor methods.
|
||||
//
|
||||
|
||||
typedef std::vector<CallRecord>::iterator iterator;
|
||||
typedef std::vector<CallRecord>::const_iterator const_iterator;
|
||||
|
||||
// getFunction - Return the function that this call graph node represents.
|
||||
Function *getFunction() const { return F; }
|
||||
|
||||
inline iterator begin() { return CalledFunctions.begin(); }
|
||||
inline iterator end() { return CalledFunctions.end(); }
|
||||
inline const_iterator begin() const { return CalledFunctions.begin(); }
|
||||
inline const_iterator end() const { return CalledFunctions.end(); }
|
||||
inline bool empty() const { return CalledFunctions.empty(); }
|
||||
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
|
||||
|
||||
/// getNumReferences - Return the number of other CallGraphNodes in this
|
||||
/// CallGraph that reference this node in their callee list.
|
||||
unsigned getNumReferences() const { return NumReferences; }
|
||||
|
||||
// Subscripting operator - Return the i'th called function.
|
||||
//
|
||||
CallGraphNode *operator[](unsigned i) const {
|
||||
assert(i < CalledFunctions.size() && "Invalid index");
|
||||
return CalledFunctions[i].second;
|
||||
}
|
||||
|
||||
/// dump - Print out this call graph node.
|
||||
///
|
||||
void dump() const;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
//===---------------------------------------------------------------------
|
||||
// Methods to keep a call graph up to date with a function that has been
|
||||
// modified
|
||||
//
|
||||
|
||||
/// removeAllCalledFunctions - As the name implies, this removes all edges
|
||||
/// from this CallGraphNode to any functions it calls.
|
||||
void removeAllCalledFunctions() {
|
||||
while (!CalledFunctions.empty()) {
|
||||
CalledFunctions.back().second->DropRef();
|
||||
CalledFunctions.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// stealCalledFunctionsFrom - Move all the callee information from N to this
|
||||
/// node.
|
||||
void stealCalledFunctionsFrom(CallGraphNode *N) {
|
||||
assert(CalledFunctions.empty() &&
|
||||
"Cannot steal callsite information if I already have some");
|
||||
std::swap(CalledFunctions, N->CalledFunctions);
|
||||
}
|
||||
|
||||
|
||||
/// addCalledFunction - Add a function to the list of functions called by this
|
||||
/// one.
|
||||
void addCalledFunction(CallSite CS, CallGraphNode *M) {
|
||||
assert(!CS.getInstruction() ||
|
||||
!CS.getCalledFunction() ||
|
||||
!CS.getCalledFunction()->isIntrinsic());
|
||||
CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M));
|
||||
M->AddRef();
|
||||
}
|
||||
|
||||
void removeCallEdge(iterator I) {
|
||||
I->second->DropRef();
|
||||
*I = CalledFunctions.back();
|
||||
CalledFunctions.pop_back();
|
||||
}
|
||||
|
||||
|
||||
/// removeCallEdgeFor - This method removes the edge in the node for the
|
||||
/// specified call site. Note that this method takes linear time, so it
|
||||
/// should be used sparingly.
|
||||
void removeCallEdgeFor(CallSite CS);
|
||||
|
||||
/// removeAnyCallEdgeTo - This method removes all call edges from this node
|
||||
/// to the specified callee function. This takes more time to execute than
|
||||
/// removeCallEdgeTo, so it should not be used unless necessary.
|
||||
void removeAnyCallEdgeTo(CallGraphNode *Callee);
|
||||
|
||||
/// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite
|
||||
/// from this node to the specified callee function.
|
||||
void removeOneAbstractEdgeTo(CallGraphNode *Callee);
|
||||
|
||||
/// replaceCallEdge - This method replaces the edge in the node for the
|
||||
/// specified call site with a new one. Note that this method takes linear
|
||||
/// time, so it should be used sparingly.
|
||||
void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode);
|
||||
|
||||
/// allReferencesDropped - This is a special function that should only be
|
||||
/// used by the CallGraph class.
|
||||
void allReferencesDropped() {
|
||||
NumReferences = 0;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// GraphTraits specializations for call graphs so that they can be treated as
|
||||
// graphs by the generic graph algorithms.
|
||||
//
|
||||
|
||||
// Provide graph traits for tranversing call graphs using standard graph
|
||||
// traversals.
|
||||
template <> struct GraphTraits<CallGraphNode*> {
|
||||
typedef CallGraphNode NodeType;
|
||||
|
||||
typedef CallGraphNode::CallRecord CGNPairTy;
|
||||
typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun;
|
||||
|
||||
static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; }
|
||||
|
||||
typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
static inline ChildIteratorType child_end (NodeType *N) {
|
||||
return map_iterator(N->end(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
|
||||
static CallGraphNode *CGNDeref(CGNPairTy P) {
|
||||
return P.second;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<const CallGraphNode*> {
|
||||
typedef const CallGraphNode NodeType;
|
||||
typedef NodeType::const_iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
|
||||
static inline ChildIteratorType child_end (NodeType *N) { return N->end(); }
|
||||
};
|
||||
|
||||
template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> {
|
||||
static NodeType *getEntryNode(CallGraph *CGN) {
|
||||
return CGN->getExternalCallingNode(); // Start at the external node!
|
||||
}
|
||||
typedef std::pair<const Function*, CallGraphNode*> PairTy;
|
||||
typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun;
|
||||
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef mapped_iterator<CallGraph::iterator, DerefFun> nodes_iterator;
|
||||
static nodes_iterator nodes_begin(CallGraph *CG) {
|
||||
return map_iterator(CG->begin(), DerefFun(CGdereference));
|
||||
}
|
||||
static nodes_iterator nodes_end (CallGraph *CG) {
|
||||
return map_iterator(CG->end(), DerefFun(CGdereference));
|
||||
}
|
||||
|
||||
static CallGraphNode &CGdereference(PairTy P) {
|
||||
return *P.second;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GraphTraits<const CallGraph*> :
|
||||
public GraphTraits<const CallGraphNode*> {
|
||||
static NodeType *getEntryNode(const CallGraph *CGN) {
|
||||
return CGN->getExternalCallingNode();
|
||||
}
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
typedef CallGraph::const_iterator nodes_iterator;
|
||||
static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); }
|
||||
static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); }
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// Make sure that any clients of this file link in CallGraph.cpp
|
||||
FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph)
|
||||
|
||||
#endif
|
||||
107
thirdparty/clang/include/llvm/Analysis/CallGraphSCCPass.h
vendored
Normal file
107
thirdparty/clang/include/llvm/Analysis/CallGraphSCCPass.h
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- 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 CallGraphSCCPass class, which is used for passes which
|
||||
// are implemented as bottom-up traversals on the call graph. Because there may
|
||||
// be cycles in the call graph, passes of this type operate on the call-graph in
|
||||
// SCC order: that is, they process function bottom-up, except for recursive
|
||||
// functions, which they process all at once.
|
||||
//
|
||||
// These passes are inherently interprocedural, and are required to keep the
|
||||
// call graph up-to-date if they do anything which could modify it.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLGRAPHSCCPASS_H
|
||||
#define LLVM_ANALYSIS_CALLGRAPHSCCPASS_H
|
||||
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CallGraphNode;
|
||||
class CallGraph;
|
||||
class PMStack;
|
||||
class CallGraphSCC;
|
||||
|
||||
class CallGraphSCCPass : public Pass {
|
||||
public:
|
||||
explicit CallGraphSCCPass(char &pid) : Pass(PT_CallGraphSCC, pid) {}
|
||||
|
||||
/// createPrinterPass - Get a pass that prints the Module
|
||||
/// corresponding to a CallGraph.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
using llvm::Pass::doInitialization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
/// doInitialization - This method is called before the SCC's of the program
|
||||
/// has been processed, allowing the pass to do initialization as necessary.
|
||||
virtual bool doInitialization(CallGraph &CG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// runOnSCC - This method should be implemented by the subclass to perform
|
||||
/// whatever action is necessary for the specified SCC. Note that
|
||||
/// non-recursive (or only self-recursive) functions will have an SCC size of
|
||||
/// 1, where recursive portions of the call graph will have SCC size > 1.
|
||||
///
|
||||
/// SCC passes that add or delete functions to the SCC are required to update
|
||||
/// the SCC list, otherwise stale pointers may be dereferenced.
|
||||
///
|
||||
virtual bool runOnSCC(CallGraphSCC &SCC) = 0;
|
||||
|
||||
/// doFinalization - This method is called after the SCC's of the program has
|
||||
/// been processed, allowing the pass to do final cleanup as necessary.
|
||||
virtual bool doFinalization(CallGraph &CG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Assign pass manager to manager this pass
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_CallGraphPassManager;
|
||||
}
|
||||
|
||||
/// getAnalysisUsage - For this class, we declare that we require and preserve
|
||||
/// the call graph. If the derived class implements this method, it should
|
||||
/// always explicitly call the implementation here.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||
};
|
||||
|
||||
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
|
||||
class CallGraphSCC {
|
||||
void *Context; // The CGPassManager object that is vending this.
|
||||
std::vector<CallGraphNode*> Nodes;
|
||||
public:
|
||||
CallGraphSCC(void *context) : Context(context) {}
|
||||
|
||||
void initialize(CallGraphNode*const*I, CallGraphNode*const*E) {
|
||||
Nodes.assign(I, E);
|
||||
}
|
||||
|
||||
bool isSingular() const { return Nodes.size() == 1; }
|
||||
unsigned size() const { return Nodes.size(); }
|
||||
|
||||
/// ReplaceNode - This informs the SCC and the pass manager that the specified
|
||||
/// Old node has been deleted, and New is to be used in its place.
|
||||
void ReplaceNode(CallGraphNode *Old, CallGraphNode *New);
|
||||
|
||||
typedef std::vector<CallGraphNode*>::const_iterator iterator;
|
||||
iterator begin() const { return Nodes.begin(); }
|
||||
iterator end() const { return Nodes.end(); }
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
27
thirdparty/clang/include/llvm/Analysis/CallPrinter.h
vendored
Normal file
27
thirdparty/clang/include/llvm/Analysis/CallPrinter.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
//===-- CallPrinter.h - Call graph printer external interface ----*- 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 external functions that can be called to explicitly
|
||||
// instantiate the call graph printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CALLPRINTER_H
|
||||
#define LLVM_ANALYSIS_CALLPRINTER_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ModulePass;
|
||||
|
||||
ModulePass *createCallGraphViewerPass();
|
||||
ModulePass *createCallGraphPrinterPass();
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
62
thirdparty/clang/include/llvm/Analysis/CaptureTracking.h
vendored
Normal file
62
thirdparty/clang/include/llvm/Analysis/CaptureTracking.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
//===----- llvm/Analysis/CaptureTracking.h - Pointer capture ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains routines that help determine which pointers are captured.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
#define LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
class Use;
|
||||
|
||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
/// be expensive, so consider caching the results. The boolean ReturnCaptures
|
||||
/// specifies whether 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.
|
||||
bool PointerMayBeCaptured(const Value *V,
|
||||
bool ReturnCaptures,
|
||||
bool StoreCaptures);
|
||||
|
||||
/// This callback is used in conjunction with PointerMayBeCaptured. In
|
||||
/// addition to the interface here, you'll need to provide your own getters
|
||||
/// to see whether anything was captured.
|
||||
struct CaptureTracker {
|
||||
virtual ~CaptureTracker();
|
||||
|
||||
/// tooManyUses - The depth of traversal has breached a limit. There may be
|
||||
/// capturing instructions that will not be passed into captured().
|
||||
virtual void tooManyUses() = 0;
|
||||
|
||||
/// shouldExplore - This is the use of a value derived from the pointer.
|
||||
/// To prune the search (ie., assume that none of its users could possibly
|
||||
/// capture) return false. To search it, return true.
|
||||
///
|
||||
/// U->getUser() is always an Instruction.
|
||||
virtual bool shouldExplore(Use *U);
|
||||
|
||||
/// captured - Information about the pointer was captured by the user of
|
||||
/// use U. Return true to stop the traversal or false to continue looking
|
||||
/// for more capturing instructions.
|
||||
virtual bool captured(Use *U) = 0;
|
||||
};
|
||||
|
||||
/// PointerMayBeCaptured - Visit the value and the values derived from it and
|
||||
/// find values which appear to be capturing the pointer value. This feeds
|
||||
/// results into and is controlled by the CaptureTracker object.
|
||||
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
93
thirdparty/clang/include/llvm/Analysis/CodeMetrics.h
vendored
Normal file
93
thirdparty/clang/include/llvm/Analysis/CodeMetrics.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
//===- CodeMetrics.h - Code cost measurements -------------------*- 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 various weight measurements for code, helping
|
||||
// the Inliner and other passes decide whether to duplicate its contents.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CODEMETRICS_H
|
||||
#define LLVM_ANALYSIS_CODEMETRICS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class TargetTransformInfo;
|
||||
class Value;
|
||||
|
||||
/// \brief Check whether a call will lower to something small.
|
||||
///
|
||||
/// This tests checks whether this callsite will lower to something
|
||||
/// significantly cheaper than a traditional call, often a single
|
||||
/// instruction. Note that if isInstructionFree(CS.getInstruction()) would
|
||||
/// return true, so will this function.
|
||||
bool callIsSmall(ImmutableCallSite CS);
|
||||
|
||||
/// \brief Utility to calculate the size and a few similar metrics for a set
|
||||
/// of basic blocks.
|
||||
struct CodeMetrics {
|
||||
/// \brief True if this function contains a call to setjmp or other functions
|
||||
/// with attribute "returns twice" without having the attribute itself.
|
||||
bool exposesReturnsTwice;
|
||||
|
||||
/// \brief True if this function calls itself.
|
||||
bool isRecursive;
|
||||
|
||||
/// \brief True if this function cannot be duplicated.
|
||||
///
|
||||
/// True if this function contains one or more indirect branches, or it contains
|
||||
/// one or more 'noduplicate' instructions.
|
||||
bool notDuplicatable;
|
||||
|
||||
/// \brief True if this function calls alloca (in the C sense).
|
||||
bool usesDynamicAlloca;
|
||||
|
||||
/// \brief Number of instructions in the analyzed blocks.
|
||||
unsigned NumInsts;
|
||||
|
||||
/// \brief Number of analyzed blocks.
|
||||
unsigned NumBlocks;
|
||||
|
||||
/// \brief Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// \brief Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
/// \brief The number of calls to internal functions with a single caller.
|
||||
///
|
||||
/// These are likely targets for future inlining, likely exposed by
|
||||
/// interleaved devirtualization.
|
||||
unsigned NumInlineCandidates;
|
||||
|
||||
/// \brief How many instructions produce vector values.
|
||||
///
|
||||
/// The inliner is more aggressive with inlining vector kernels.
|
||||
unsigned NumVectorInsts;
|
||||
|
||||
/// \brief How many 'ret' instructions the blocks contain.
|
||||
unsigned NumRets;
|
||||
|
||||
CodeMetrics()
|
||||
: exposesReturnsTwice(false), isRecursive(false), notDuplicatable(false),
|
||||
usesDynamicAlloca(false), NumInsts(0), NumBlocks(0), NumCalls(0),
|
||||
NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {}
|
||||
|
||||
/// \brief Add information about a block to the current state.
|
||||
void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
102
thirdparty/clang/include/llvm/Analysis/ConstantFolding.h
vendored
Normal file
102
thirdparty/clang/include/llvm/Analysis/ConstantFolding.h
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
//===-- ConstantFolding.h - Fold instructions into constants --------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares routines for folding instructions into constants when all
|
||||
// operands are constants, for example "sub i32 1, 0" -> "1".
|
||||
//
|
||||
// Also, to supplement the basic VMCore ConstantExpr simplifications,
|
||||
// this file declares some additional folding routines that can make use of
|
||||
// DataLayout information. These functions cannot go in VMCore due to library
|
||||
// dependency issues.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H
|
||||
#define LLVM_ANALYSIS_CONSTANTFOLDING_H
|
||||
|
||||
namespace llvm {
|
||||
class Constant;
|
||||
class ConstantExpr;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Function;
|
||||
class Type;
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
|
||||
/// ConstantFoldInstruction - Try to constant fold the specified instruction.
|
||||
/// If successful, the constant result is returned, if not, null is returned.
|
||||
/// Note that this fails if not all of the operands are constant. Otherwise,
|
||||
/// this function can only fail when attempting to fold instructions like loads
|
||||
/// and stores, which have no constant expression form.
|
||||
Constant *ConstantFoldInstruction(Instruction *I, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
|
||||
/// using the specified DataLayout. If successful, the constant result is
|
||||
/// result is returned, if not, null is returned.
|
||||
Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
|
||||
/// specified operands. If successful, the constant result is returned, if not,
|
||||
/// null is returned. Note that this function can fail when attempting to
|
||||
/// fold instructions like loads and stores, which have no constant expression
|
||||
/// form.
|
||||
///
|
||||
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
|
||||
ArrayRef<Constant *> Ops,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
|
||||
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
|
||||
/// returns a constant expression of the specified operands.
|
||||
///
|
||||
Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
|
||||
Constant *LHS, Constant *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
|
||||
/// instruction with the specified operands and indices. The constant result is
|
||||
/// returned if successful; if not, null is returned.
|
||||
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
|
||||
ArrayRef<unsigned> Idxs);
|
||||
|
||||
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
|
||||
/// produce if it is constant and determinable. If this is not determinable,
|
||||
/// return null.
|
||||
Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout *TD = 0);
|
||||
|
||||
/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a
|
||||
/// getelementptr constantexpr, return the constant value being addressed by the
|
||||
/// constant expression, or null if something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE);
|
||||
|
||||
/// ConstantFoldLoadThroughGEPIndices - Given a constant and getelementptr
|
||||
/// indices (with an *implied* zero pointer index that is not in the list),
|
||||
/// return the constant value being addressed by a virtual load, or null if
|
||||
/// something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
|
||||
ArrayRef<Constant*> Indices);
|
||||
|
||||
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
|
||||
/// the specified function.
|
||||
bool canConstantFoldCallTo(const Function *F);
|
||||
|
||||
/// ConstantFoldCall - Attempt to constant fold a call to the specified function
|
||||
/// with the specified arguments, returning null if unsuccessful.
|
||||
Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
93
thirdparty/clang/include/llvm/Analysis/ConstantsScanner.h
vendored
Normal file
93
thirdparty/clang/include/llvm/Analysis/ConstantsScanner.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class implements an iterator to walk through the constants referenced by
|
||||
// a method. This is used by the Bitcode & Assembly writers to build constant
|
||||
// pools.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H
|
||||
#define LLVM_ANALYSIS_CONSTANTSSCANNER_H
|
||||
|
||||
#include "llvm/Support/InstIterator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Constant;
|
||||
|
||||
class constant_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
const Constant, ptrdiff_t> {
|
||||
const_inst_iterator InstI; // Method instruction iterator
|
||||
unsigned OpIdx; // Operand index
|
||||
|
||||
typedef constant_iterator _Self;
|
||||
|
||||
inline bool isAtConstant() const {
|
||||
assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() &&
|
||||
"isAtConstant called with invalid arguments!");
|
||||
return isa<Constant>(InstI->getOperand(OpIdx));
|
||||
}
|
||||
|
||||
public:
|
||||
inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) {
|
||||
// Advance to first constant... if we are not already at constant or end
|
||||
if (InstI != inst_end(F) && // InstI is valid?
|
||||
(InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant?
|
||||
operator++();
|
||||
}
|
||||
|
||||
inline constant_iterator(const Function *F, bool) // end ctor
|
||||
: InstI(inst_end(F)), OpIdx(0) {
|
||||
}
|
||||
|
||||
inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx &&
|
||||
InstI == x.InstI; }
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
assert(isAtConstant() && "Dereferenced an iterator at the end!");
|
||||
return cast<Constant>(InstI->getOperand(OpIdx));
|
||||
}
|
||||
inline pointer operator->() const { return operator*(); }
|
||||
|
||||
inline _Self& operator++() { // Preincrement implementation
|
||||
++OpIdx;
|
||||
do {
|
||||
unsigned NumOperands = InstI->getNumOperands();
|
||||
while (OpIdx < NumOperands && !isAtConstant()) {
|
||||
++OpIdx;
|
||||
}
|
||||
|
||||
if (OpIdx < NumOperands) return *this; // Found a constant!
|
||||
++InstI;
|
||||
OpIdx = 0;
|
||||
} while (!InstI.atEnd());
|
||||
|
||||
return *this; // At the end of the method
|
||||
}
|
||||
|
||||
inline _Self operator++(int) { // Postincrement
|
||||
_Self tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
inline bool atEnd() const { return InstI.atEnd(); }
|
||||
};
|
||||
|
||||
inline constant_iterator constant_begin(const Function *F) {
|
||||
return constant_iterator(F);
|
||||
}
|
||||
|
||||
inline constant_iterator constant_end(const Function *F) {
|
||||
return constant_iterator(F, true);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
142
thirdparty/clang/include/llvm/Analysis/DOTGraphTraitsPass.h
vendored
Normal file
142
thirdparty/clang/include/llvm/Analysis/DOTGraphTraitsPass.h
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Templates to create dotty viewer and printer passes for GraphTraits graphs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
|
||||
#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
|
||||
|
||||
#include "llvm/Analysis/CFGPrinter.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsViewer : public FunctionPass {
|
||||
public:
|
||||
DOTGraphTraitsViewer(StringRef GraphName, char &ID)
|
||||
: FunctionPass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
|
||||
ViewGraph(Graph, Name, Simple, Title);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsPrinter : public FunctionPass {
|
||||
public:
|
||||
DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
|
||||
: FunctionPass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Filename = Name + "." + F.getName().str() + ".dot";
|
||||
std::string ErrorInfo;
|
||||
|
||||
errs() << "Writing '" << Filename << "'...";
|
||||
|
||||
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
|
||||
std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
std::string Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
|
||||
if (ErrorInfo.empty())
|
||||
WriteGraph(File, Graph, Simple, Title);
|
||||
else
|
||||
errs() << " error opening file for writing!";
|
||||
errs() << "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsModuleViewer : public ModulePass {
|
||||
public:
|
||||
DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
|
||||
: ModulePass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnModule(Module &M) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
|
||||
ViewGraph(Graph, Name, Simple, Title);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
template <class Analysis, bool Simple>
|
||||
class DOTGraphTraitsModulePrinter : public ModulePass {
|
||||
public:
|
||||
DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
|
||||
: ModulePass(ID), Name(GraphName) {}
|
||||
|
||||
virtual bool runOnModule(Module &M) {
|
||||
Analysis *Graph = &getAnalysis<Analysis>();
|
||||
std::string Filename = Name + ".dot";
|
||||
std::string ErrorInfo;
|
||||
|
||||
errs() << "Writing '" << Filename << "'...";
|
||||
|
||||
raw_fd_ostream File(Filename.c_str(), ErrorInfo);
|
||||
std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
|
||||
if (ErrorInfo.empty())
|
||||
WriteGraph(File, Graph, Simple, Title);
|
||||
else
|
||||
errs() << " error opening file for writing!";
|
||||
errs() << "\n";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<Analysis>();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
895
thirdparty/clang/include/llvm/Analysis/DependenceAnalysis.h
vendored
Normal file
895
thirdparty/clang/include/llvm/Analysis/DependenceAnalysis.h
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
//===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DependenceAnalysis is an LLVM pass that analyses dependences between memory
|
||||
// accesses. Currently, it is an implementation of the approach described in
|
||||
//
|
||||
// Practical Dependence Testing
|
||||
// Goff, Kennedy, Tseng
|
||||
// PLDI 1991
|
||||
//
|
||||
// There's a single entry point that analyzes the dependence between a pair
|
||||
// of memory references in a function, returning either NULL, for no dependence,
|
||||
// or a more-or-less detailed description of the dependence between them.
|
||||
//
|
||||
// This pass exists to support the DependenceGraph pass. There are two separate
|
||||
// passes because there's a useful separation of concerns. A dependence exists
|
||||
// if two conditions are met:
|
||||
//
|
||||
// 1) Two instructions reference the same memory location, and
|
||||
// 2) There is a flow of control leading from one instruction to the other.
|
||||
//
|
||||
// DependenceAnalysis attacks the first condition; DependenceGraph will attack
|
||||
// the second (it's not yet ready).
|
||||
//
|
||||
// Please note that this is work in progress and the interface is subject to
|
||||
// change.
|
||||
//
|
||||
// Plausible changes:
|
||||
// Return a set of more precise dependences instead of just one dependence
|
||||
// summarizing all.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
|
||||
#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class AliasAnalysis;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class SCEVConstant;
|
||||
class raw_ostream;
|
||||
|
||||
/// Dependence - This class represents a dependence between two memory
|
||||
/// memory references in a function. It contains minimal information and
|
||||
/// is used in the very common situation where the compiler is unable to
|
||||
/// determine anything beyond the existence of a dependence; that is, it
|
||||
/// represents a confused dependence (see also FullDependence). In most
|
||||
/// cases (for output, flow, and anti dependences), the dependence implies
|
||||
/// an ordering, where the source must precede the destination; in contrast,
|
||||
/// input dependences are unordered.
|
||||
class Dependence {
|
||||
public:
|
||||
Dependence(Instruction *Source,
|
||||
Instruction *Destination) :
|
||||
Src(Source), Dst(Destination) {}
|
||||
virtual ~Dependence() {}
|
||||
|
||||
/// Dependence::DVEntry - Each level in the distance/direction vector
|
||||
/// has a direction (or perhaps a union of several directions), and
|
||||
/// perhaps a distance.
|
||||
struct DVEntry {
|
||||
enum { NONE = 0,
|
||||
LT = 1,
|
||||
EQ = 2,
|
||||
LE = 3,
|
||||
GT = 4,
|
||||
NE = 5,
|
||||
GE = 6,
|
||||
ALL = 7 };
|
||||
unsigned char Direction : 3; // Init to ALL, then refine.
|
||||
bool Scalar : 1; // Init to true.
|
||||
bool PeelFirst : 1; // Peeling the first iteration will break dependence.
|
||||
bool PeelLast : 1; // Peeling the last iteration will break the dependence.
|
||||
bool Splitable : 1; // Splitting the loop will break dependence.
|
||||
const SCEV *Distance; // NULL implies no distance available.
|
||||
DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false),
|
||||
PeelLast(false), Splitable(false), Distance(NULL) { }
|
||||
};
|
||||
|
||||
/// getSrc - Returns the source instruction for this dependence.
|
||||
///
|
||||
Instruction *getSrc() const { return Src; }
|
||||
|
||||
/// getDst - Returns the destination instruction for this dependence.
|
||||
///
|
||||
Instruction *getDst() const { return Dst; }
|
||||
|
||||
/// isInput - Returns true if this is an input dependence.
|
||||
///
|
||||
bool isInput() const;
|
||||
|
||||
/// isOutput - Returns true if this is an output dependence.
|
||||
///
|
||||
bool isOutput() const;
|
||||
|
||||
/// isFlow - Returns true if this is a flow (aka true) dependence.
|
||||
///
|
||||
bool isFlow() const;
|
||||
|
||||
/// isAnti - Returns true if this is an anti dependence.
|
||||
///
|
||||
bool isAnti() const;
|
||||
|
||||
/// isOrdered - Returns true if dependence is Output, Flow, or Anti
|
||||
///
|
||||
bool isOrdered() const { return isOutput() || isFlow() || isAnti(); }
|
||||
|
||||
/// isUnordered - Returns true if dependence is Input
|
||||
///
|
||||
bool isUnordered() const { return isInput(); }
|
||||
|
||||
/// isLoopIndependent - Returns true if this is a loop-independent
|
||||
/// dependence.
|
||||
virtual bool isLoopIndependent() const { return true; }
|
||||
|
||||
/// isConfused - Returns true if this dependence is confused
|
||||
/// (the compiler understands nothing and makes worst-case
|
||||
/// assumptions).
|
||||
virtual bool isConfused() const { return true; }
|
||||
|
||||
/// isConsistent - Returns true if this dependence is consistent
|
||||
/// (occurs every time the source and destination are executed).
|
||||
virtual bool isConsistent() const { return false; }
|
||||
|
||||
/// getLevels - Returns the number of common loops surrounding the
|
||||
/// source and destination of the dependence.
|
||||
virtual unsigned getLevels() const { return 0; }
|
||||
|
||||
/// getDirection - Returns the direction associated with a particular
|
||||
/// level.
|
||||
virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
|
||||
|
||||
/// getDistance - Returns the distance (or NULL) associated with a
|
||||
/// particular level.
|
||||
virtual const SCEV *getDistance(unsigned Level) const { return NULL; }
|
||||
|
||||
/// isPeelFirst - Returns true if peeling the first iteration from
|
||||
/// this loop will break this dependence.
|
||||
virtual bool isPeelFirst(unsigned Level) const { return false; }
|
||||
|
||||
/// isPeelLast - Returns true if peeling the last iteration from
|
||||
/// this loop will break this dependence.
|
||||
virtual bool isPeelLast(unsigned Level) const { return false; }
|
||||
|
||||
/// isSplitable - Returns true if splitting this loop will break
|
||||
/// the dependence.
|
||||
virtual bool isSplitable(unsigned Level) const { return false; }
|
||||
|
||||
/// isScalar - Returns true if a particular level is scalar; that is,
|
||||
/// if no subscript in the source or destination mention the induction
|
||||
/// variable associated with the loop at this level.
|
||||
virtual bool isScalar(unsigned Level) const;
|
||||
|
||||
/// dump - For debugging purposes, dumps a dependence to OS.
|
||||
///
|
||||
void dump(raw_ostream &OS) const;
|
||||
private:
|
||||
Instruction *Src, *Dst;
|
||||
friend class DependenceAnalysis;
|
||||
};
|
||||
|
||||
|
||||
/// FullDependence - This class represents a dependence between two memory
|
||||
/// references in a function. It contains detailed information about the
|
||||
/// dependence (direction vectors, etc.) and is used when the compiler is
|
||||
/// able to accurately analyze the interaction of the references; that is,
|
||||
/// it is not a confused dependence (see Dependence). In most cases
|
||||
/// (for output, flow, and anti dependences), the dependence implies an
|
||||
/// ordering, where the source must precede the destination; in contrast,
|
||||
/// input dependences are unordered.
|
||||
class FullDependence : public Dependence {
|
||||
public:
|
||||
FullDependence(Instruction *Src,
|
||||
Instruction *Dst,
|
||||
bool LoopIndependent,
|
||||
unsigned Levels);
|
||||
~FullDependence() {
|
||||
delete[] DV;
|
||||
}
|
||||
|
||||
/// isLoopIndependent - Returns true if this is a loop-independent
|
||||
/// dependence.
|
||||
bool isLoopIndependent() const { return LoopIndependent; }
|
||||
|
||||
/// isConfused - Returns true if this dependence is confused
|
||||
/// (the compiler understands nothing and makes worst-case
|
||||
/// assumptions).
|
||||
bool isConfused() const { return false; }
|
||||
|
||||
/// isConsistent - Returns true if this dependence is consistent
|
||||
/// (occurs every time the source and destination are executed).
|
||||
bool isConsistent() const { return Consistent; }
|
||||
|
||||
/// getLevels - Returns the number of common loops surrounding the
|
||||
/// source and destination of the dependence.
|
||||
unsigned getLevels() const { return Levels; }
|
||||
|
||||
/// getDirection - Returns the direction associated with a particular
|
||||
/// level.
|
||||
unsigned getDirection(unsigned Level) const;
|
||||
|
||||
/// getDistance - Returns the distance (or NULL) associated with a
|
||||
/// particular level.
|
||||
const SCEV *getDistance(unsigned Level) const;
|
||||
|
||||
/// isPeelFirst - Returns true if peeling the first iteration from
|
||||
/// this loop will break this dependence.
|
||||
bool isPeelFirst(unsigned Level) const;
|
||||
|
||||
/// isPeelLast - Returns true if peeling the last iteration from
|
||||
/// this loop will break this dependence.
|
||||
bool isPeelLast(unsigned Level) const;
|
||||
|
||||
/// isSplitable - Returns true if splitting the loop will break
|
||||
/// the dependence.
|
||||
bool isSplitable(unsigned Level) const;
|
||||
|
||||
/// isScalar - Returns true if a particular level is scalar; that is,
|
||||
/// if no subscript in the source or destination mention the induction
|
||||
/// variable associated with the loop at this level.
|
||||
bool isScalar(unsigned Level) const;
|
||||
private:
|
||||
unsigned short Levels;
|
||||
bool LoopIndependent;
|
||||
bool Consistent; // Init to true, then refine.
|
||||
DVEntry *DV;
|
||||
friend class DependenceAnalysis;
|
||||
};
|
||||
|
||||
|
||||
/// DependenceAnalysis - This class is the main dependence-analysis driver.
|
||||
///
|
||||
class DependenceAnalysis : public FunctionPass {
|
||||
void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
|
||||
DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
/// depends - Tests for a dependence between the Src and Dst instructions.
|
||||
/// Returns NULL if no dependence; otherwise, returns a Dependence (or a
|
||||
/// FullDependence) with as much information as can be gleaned.
|
||||
/// The flag PossiblyLoopIndependent should be set by the caller
|
||||
/// if it appears that control flow can reach from Src to Dst
|
||||
/// without traversing a loop back edge.
|
||||
Dependence *depends(Instruction *Src,
|
||||
Instruction *Dst,
|
||||
bool PossiblyLoopIndependent);
|
||||
|
||||
/// getSplitIteration - Give a dependence that's splittable at some
|
||||
/// particular level, return the iteration that should be used to split
|
||||
/// the loop.
|
||||
///
|
||||
/// Generally, the dependence analyzer will be used to build
|
||||
/// a dependence graph for a function (basically a map from instructions
|
||||
/// to dependences). Looking for cycles in the graph shows us loops
|
||||
/// that cannot be trivially vectorized/parallelized.
|
||||
///
|
||||
/// We can try to improve the situation by examining all the dependences
|
||||
/// that make up the cycle, looking for ones we can break.
|
||||
/// Sometimes, peeling the first or last iteration of a loop will break
|
||||
/// dependences, and there are flags for those possibilities.
|
||||
/// Sometimes, splitting a loop at some other iteration will do the trick,
|
||||
/// and we've got a flag for that case. Rather than waste the space to
|
||||
/// record the exact iteration (since we rarely know), we provide
|
||||
/// a method that calculates the iteration. It's a drag that it must work
|
||||
/// from scratch, but wonderful in that it's possible.
|
||||
///
|
||||
/// Here's an example:
|
||||
///
|
||||
/// for (i = 0; i < 10; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
///
|
||||
/// There's a loop-carried flow dependence from the store to the load,
|
||||
/// found by the weak-crossing SIV test. The dependence will have a flag,
|
||||
/// indicating that the dependence can be broken by splitting the loop.
|
||||
/// Calling getSplitIteration will return 5.
|
||||
/// Splitting the loop breaks the dependence, like so:
|
||||
///
|
||||
/// for (i = 0; i <= 5; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
/// for (i = 6; i < 10; i++)
|
||||
/// A[i] = ...
|
||||
/// ... = A[11 - i]
|
||||
///
|
||||
/// breaks the dependence and allows us to vectorize/parallelize
|
||||
/// both loops.
|
||||
const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level);
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA;
|
||||
ScalarEvolution *SE;
|
||||
LoopInfo *LI;
|
||||
Function *F;
|
||||
|
||||
/// Subscript - This private struct represents a pair of subscripts from
|
||||
/// a pair of potentially multi-dimensional array references. We use a
|
||||
/// vector of them to guide subscript partitioning.
|
||||
struct Subscript {
|
||||
const SCEV *Src;
|
||||
const SCEV *Dst;
|
||||
enum ClassificationKind { ZIV, SIV, RDIV, MIV, NonLinear } Classification;
|
||||
SmallBitVector Loops;
|
||||
SmallBitVector GroupLoops;
|
||||
SmallBitVector Group;
|
||||
};
|
||||
|
||||
struct CoefficientInfo {
|
||||
const SCEV *Coeff;
|
||||
const SCEV *PosPart;
|
||||
const SCEV *NegPart;
|
||||
const SCEV *Iterations;
|
||||
};
|
||||
|
||||
struct BoundInfo {
|
||||
const SCEV *Iterations;
|
||||
const SCEV *Upper[8];
|
||||
const SCEV *Lower[8];
|
||||
unsigned char Direction;
|
||||
unsigned char DirSet;
|
||||
};
|
||||
|
||||
/// Constraint - This private class represents a constraint, as defined
|
||||
/// in the paper
|
||||
///
|
||||
/// Practical Dependence Testing
|
||||
/// Goff, Kennedy, Tseng
|
||||
/// PLDI 1991
|
||||
///
|
||||
/// There are 5 kinds of constraint, in a hierarchy.
|
||||
/// 1) Any - indicates no constraint, any dependence is possible.
|
||||
/// 2) Line - A line ax + by = c, where a, b, and c are parameters,
|
||||
/// representing the dependence equation.
|
||||
/// 3) Distance - The value d of the dependence distance;
|
||||
/// 4) Point - A point <x, y> representing the dependence from
|
||||
/// iteration x to iteration y.
|
||||
/// 5) Empty - No dependence is possible.
|
||||
class Constraint {
|
||||
private:
|
||||
enum ConstraintKind { Empty, Point, Distance, Line, Any } Kind;
|
||||
ScalarEvolution *SE;
|
||||
const SCEV *A;
|
||||
const SCEV *B;
|
||||
const SCEV *C;
|
||||
const Loop *AssociatedLoop;
|
||||
public:
|
||||
/// isEmpty - Return true if the constraint is of kind Empty.
|
||||
bool isEmpty() const { return Kind == Empty; }
|
||||
|
||||
/// isPoint - Return true if the constraint is of kind Point.
|
||||
bool isPoint() const { return Kind == Point; }
|
||||
|
||||
/// isDistance - Return true if the constraint is of kind Distance.
|
||||
bool isDistance() const { return Kind == Distance; }
|
||||
|
||||
/// isLine - Return true if the constraint is of kind Line.
|
||||
/// Since Distance's can also be represented as Lines, we also return
|
||||
/// true if the constraint is of kind Distance.
|
||||
bool isLine() const { return Kind == Line || Kind == Distance; }
|
||||
|
||||
/// isAny - Return true if the constraint is of kind Any;
|
||||
bool isAny() const { return Kind == Any; }
|
||||
|
||||
/// getX - If constraint is a point <X, Y>, returns X.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getX() const;
|
||||
|
||||
/// getY - If constraint is a point <X, Y>, returns Y.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getY() const;
|
||||
|
||||
/// getA - If constraint is a line AX + BY = C, returns A.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getA() const;
|
||||
|
||||
/// getB - If constraint is a line AX + BY = C, returns B.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getB() const;
|
||||
|
||||
/// getC - If constraint is a line AX + BY = C, returns C.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getC() const;
|
||||
|
||||
/// getD - If constraint is a distance, returns D.
|
||||
/// Otherwise assert.
|
||||
const SCEV *getD() const;
|
||||
|
||||
/// getAssociatedLoop - Returns the loop associated with this constraint.
|
||||
const Loop *getAssociatedLoop() const;
|
||||
|
||||
/// setPoint - Change a constraint to Point.
|
||||
void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop);
|
||||
|
||||
/// setLine - Change a constraint to Line.
|
||||
void setLine(const SCEV *A, const SCEV *B,
|
||||
const SCEV *C, const Loop *CurrentLoop);
|
||||
|
||||
/// setDistance - Change a constraint to Distance.
|
||||
void setDistance(const SCEV *D, const Loop *CurrentLoop);
|
||||
|
||||
/// setEmpty - Change a constraint to Empty.
|
||||
void setEmpty();
|
||||
|
||||
/// setAny - Change a constraint to Any.
|
||||
void setAny(ScalarEvolution *SE);
|
||||
|
||||
/// dump - For debugging purposes. Dumps the constraint
|
||||
/// out to OS.
|
||||
void dump(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
|
||||
/// establishNestingLevels - Examines the loop nesting of the Src and Dst
|
||||
/// instructions and establishes their shared loops. Sets the variables
|
||||
/// CommonLevels, SrcLevels, and MaxLevels.
|
||||
/// The source and destination instructions needn't be contained in the same
|
||||
/// loop. The routine establishNestingLevels finds the level of most deeply
|
||||
/// nested loop that contains them both, CommonLevels. An instruction that's
|
||||
/// not contained in a loop is at level = 0. MaxLevels is equal to the level
|
||||
/// of the source plus the level of the destination, minus CommonLevels.
|
||||
/// This lets us allocate vectors MaxLevels in length, with room for every
|
||||
/// distinct loop referenced in both the source and destination subscripts.
|
||||
/// The variable SrcLevels is the nesting depth of the source instruction.
|
||||
/// It's used to help calculate distinct loops referenced by the destination.
|
||||
/// Here's the map from loops to levels:
|
||||
/// 0 - unused
|
||||
/// 1 - outermost common loop
|
||||
/// ... - other common loops
|
||||
/// CommonLevels - innermost common loop
|
||||
/// ... - loops containing Src but not Dst
|
||||
/// SrcLevels - innermost loop containing Src but not Dst
|
||||
/// ... - loops containing Dst but not Src
|
||||
/// MaxLevels - innermost loop containing Dst but not Src
|
||||
/// Consider the follow code fragment:
|
||||
/// for (a = ...) {
|
||||
/// for (b = ...) {
|
||||
/// for (c = ...) {
|
||||
/// for (d = ...) {
|
||||
/// A[] = ...;
|
||||
/// }
|
||||
/// }
|
||||
/// for (e = ...) {
|
||||
/// for (f = ...) {
|
||||
/// for (g = ...) {
|
||||
/// ... = A[];
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// If we're looking at the possibility of a dependence between the store
|
||||
/// to A (the Src) and the load from A (the Dst), we'll note that they
|
||||
/// have 2 loops in common, so CommonLevels will equal 2 and the direction
|
||||
/// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7.
|
||||
/// A map from loop names to level indices would look like
|
||||
/// a - 1
|
||||
/// b - 2 = CommonLevels
|
||||
/// c - 3
|
||||
/// d - 4 = SrcLevels
|
||||
/// e - 5
|
||||
/// f - 6
|
||||
/// g - 7 = MaxLevels
|
||||
void establishNestingLevels(const Instruction *Src,
|
||||
const Instruction *Dst);
|
||||
|
||||
unsigned CommonLevels, SrcLevels, MaxLevels;
|
||||
|
||||
/// mapSrcLoop - Given one of the loops containing the source, return
|
||||
/// its level index in our numbering scheme.
|
||||
unsigned mapSrcLoop(const Loop *SrcLoop) const;
|
||||
|
||||
/// mapDstLoop - Given one of the loops containing the destination,
|
||||
/// return its level index in our numbering scheme.
|
||||
unsigned mapDstLoop(const Loop *DstLoop) const;
|
||||
|
||||
/// isLoopInvariant - Returns true if Expression is loop invariant
|
||||
/// in LoopNest.
|
||||
bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
|
||||
|
||||
/// removeMatchingExtensions - Examines a subscript pair.
|
||||
/// If the source and destination are identically sign (or zero)
|
||||
/// extended, it strips off the extension in an effort to
|
||||
/// simplify the actual analysis.
|
||||
void removeMatchingExtensions(Subscript *Pair);
|
||||
|
||||
/// collectCommonLoops - Finds the set of loops from the LoopNest that
|
||||
/// have a level <= CommonLevels and are referred to by the SCEV Expression.
|
||||
void collectCommonLoops(const SCEV *Expression,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops) const;
|
||||
|
||||
/// checkSrcSubscript - Examines the SCEV Src, returning true iff it's
|
||||
/// linear. Collect the set of loops mentioned by Src.
|
||||
bool checkSrcSubscript(const SCEV *Src,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// checkDstSubscript - Examines the SCEV Dst, returning true iff it's
|
||||
/// linear. Collect the set of loops mentioned by Dst.
|
||||
bool checkDstSubscript(const SCEV *Dst,
|
||||
const Loop *LoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// isKnownPredicate - Compare X and Y using the predicate Pred.
|
||||
/// Basically a wrapper for SCEV::isKnownPredicate,
|
||||
/// but tries harder, especially in the presence of sign and zero
|
||||
/// extensions and symbolics.
|
||||
bool isKnownPredicate(ICmpInst::Predicate Pred,
|
||||
const SCEV *X,
|
||||
const SCEV *Y) const;
|
||||
|
||||
/// collectUpperBound - All subscripts are the same type (on my machine,
|
||||
/// an i64). The loop bound may be a smaller type. collectUpperBound
|
||||
/// find the bound, if available, and zero extends it to the Type T.
|
||||
/// (I zero extend since the bound should always be >= 0.)
|
||||
/// If no upper bound is available, return NULL.
|
||||
const SCEV *collectUpperBound(const Loop *l, Type *T) const;
|
||||
|
||||
/// collectConstantUpperBound - Calls collectUpperBound(), then
|
||||
/// attempts to cast it to SCEVConstant. If the cast fails,
|
||||
/// returns NULL.
|
||||
const SCEVConstant *collectConstantUpperBound(const Loop *l, Type *T) const;
|
||||
|
||||
/// classifyPair - Examines the subscript pair (the Src and Dst SCEVs)
|
||||
/// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear.
|
||||
/// Collects the associated loops in a set.
|
||||
Subscript::ClassificationKind classifyPair(const SCEV *Src,
|
||||
const Loop *SrcLoopNest,
|
||||
const SCEV *Dst,
|
||||
const Loop *DstLoopNest,
|
||||
SmallBitVector &Loops);
|
||||
|
||||
/// testZIV - Tests the ZIV subscript pair (Src and Dst) for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// If the dependence isn't proven to exist,
|
||||
/// marks the Result as inconsistent.
|
||||
bool testZIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// testSIV - Tests the SIV subscript pair (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*j], where
|
||||
/// i and j are induction variables, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction vector entry and, when possible,
|
||||
/// the distance vector entry.
|
||||
/// If the dependence isn't proven to exist,
|
||||
/// marks the Result as inconsistent.
|
||||
bool testSIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
unsigned &Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint,
|
||||
const SCEV *&SplitIter) const;
|
||||
|
||||
/// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*j]
|
||||
/// where i and j are induction variables, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// With minor algebra, this test can also be used for things like
|
||||
/// [c1 + a1*i + a2*j][c2].
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Marks the Result as inconsistent.
|
||||
bool testRDIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// testMIV - Tests the MIV subscript pair (Src and Dst) for dependence.
|
||||
/// Returns true if dependence disproved.
|
||||
/// Can sometimes refine direction vectors.
|
||||
bool testMIV(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
const SmallBitVector &Loops,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// strongSIVtest - Tests the strong SIV subscript pair (Src and Dst)
|
||||
/// for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction and distance.
|
||||
bool strongSIVtest(const SCEV *Coeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 - a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// Marks the dependence as splitable.
|
||||
bool weakCrossingSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint,
|
||||
const SCEV *&SplitIter) const;
|
||||
|
||||
/// ExactSIVtest - Tests the SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a1*i] and [c2 + a2*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a1 and a2 are constant.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
bool exactSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1] and [c2 + a*i],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant. See also weakZeroDstSIVtest.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// If loop peeling will break the dependence, mark appropriately.
|
||||
bool weakZeroSrcSIVtest(const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
|
||||
/// (Src and Dst) for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2],
|
||||
/// where i is an induction variable, c1 and c2 are loop invariant,
|
||||
/// and a is a constant. See also weakZeroSrcSIVtest.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// If there might be a dependence, returns false.
|
||||
/// Sets appropriate direction entry.
|
||||
/// Set consistent to false.
|
||||
/// If loop peeling will break the dependence, mark appropriately.
|
||||
bool weakZeroDstSIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *CurrentLoop,
|
||||
unsigned Level,
|
||||
FullDependence &Result,
|
||||
Constraint &NewConstraint) const;
|
||||
|
||||
/// exactRDIVtest - Tests the RDIV subscript pair for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + b*j],
|
||||
/// where i and j are induction variable, c1 and c2 are loop invariant,
|
||||
/// and a and b are constants.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Works in some cases that symbolicRDIVtest doesn't,
|
||||
/// and vice versa.
|
||||
bool exactRDIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *SrcLoop,
|
||||
const Loop *DstLoop,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// symbolicRDIVtest - Tests the RDIV subscript pair for dependence.
|
||||
/// Things of the form [c1 + a*i] and [c2 + b*j],
|
||||
/// where i and j are induction variable, c1 and c2 are loop invariant,
|
||||
/// and a and b are constants.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Works in some cases that exactRDIVtest doesn't,
|
||||
/// and vice versa. Can also be used as a backup for
|
||||
/// ordinary SIV tests.
|
||||
bool symbolicRDIVtest(const SCEV *SrcCoeff,
|
||||
const SCEV *DstCoeff,
|
||||
const SCEV *SrcConst,
|
||||
const SCEV *DstConst,
|
||||
const Loop *SrcLoop,
|
||||
const Loop *DstLoop) const;
|
||||
|
||||
/// gcdMIVtest - Tests an MIV subscript pair for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Can sometimes disprove the equal direction for 1 or more loops.
|
||||
// Can handle some symbolics that even the SIV tests don't get,
|
||||
/// so we use it as a backup for everything.
|
||||
bool gcdMIVtest(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// banerjeeMIVtest - Tests an MIV subscript pair for dependence.
|
||||
/// Returns true if any possible dependence is disproved.
|
||||
/// Marks the result as inconsistent.
|
||||
/// Computes directions.
|
||||
bool banerjeeMIVtest(const SCEV *Src,
|
||||
const SCEV *Dst,
|
||||
const SmallBitVector &Loops,
|
||||
FullDependence &Result) const;
|
||||
|
||||
/// collectCoefficientInfo - Walks through the subscript,
|
||||
/// collecting each coefficient, the associated loop bounds,
|
||||
/// and recording its positive and negative parts for later use.
|
||||
CoefficientInfo *collectCoeffInfo(const SCEV *Subscript,
|
||||
bool SrcFlag,
|
||||
const SCEV *&Constant) const;
|
||||
|
||||
/// getPositivePart - X^+ = max(X, 0).
|
||||
///
|
||||
const SCEV *getPositivePart(const SCEV *X) const;
|
||||
|
||||
/// getNegativePart - X^- = min(X, 0).
|
||||
///
|
||||
const SCEV *getNegativePart(const SCEV *X) const;
|
||||
|
||||
/// getLowerBound - Looks through all the bounds info and
|
||||
/// computes the lower bound given the current direction settings
|
||||
/// at each level.
|
||||
const SCEV *getLowerBound(BoundInfo *Bound) const;
|
||||
|
||||
/// getUpperBound - Looks through all the bounds info and
|
||||
/// computes the upper bound given the current direction settings
|
||||
/// at each level.
|
||||
const SCEV *getUpperBound(BoundInfo *Bound) const;
|
||||
|
||||
/// exploreDirections - Hierarchically expands the direction vector
|
||||
/// search space, combining the directions of discovered dependences
|
||||
/// in the DirSet field of Bound. Returns the number of distinct
|
||||
/// dependences discovered. If the dependence is disproved,
|
||||
/// it will return 0.
|
||||
unsigned exploreDirections(unsigned Level,
|
||||
CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
const SmallBitVector &Loops,
|
||||
unsigned &DepthExpanded,
|
||||
const SCEV *Delta) const;
|
||||
|
||||
/// testBounds - Returns true iff the current bounds are plausible.
|
||||
///
|
||||
bool testBounds(unsigned char DirKind,
|
||||
unsigned Level,
|
||||
BoundInfo *Bound,
|
||||
const SCEV *Delta) const;
|
||||
|
||||
/// findBoundsALL - Computes the upper and lower bounds for level K
|
||||
/// using the * direction. Records them in Bound.
|
||||
void findBoundsALL(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsLT - Computes the upper and lower bounds for level K
|
||||
/// using the < direction. Records them in Bound.
|
||||
void findBoundsLT(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsGT - Computes the upper and lower bounds for level K
|
||||
/// using the > direction. Records them in Bound.
|
||||
void findBoundsGT(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// findBoundsEQ - Computes the upper and lower bounds for level K
|
||||
/// using the = direction. Records them in Bound.
|
||||
void findBoundsEQ(CoefficientInfo *A,
|
||||
CoefficientInfo *B,
|
||||
BoundInfo *Bound,
|
||||
unsigned K) const;
|
||||
|
||||
/// intersectConstraints - Updates X with the intersection
|
||||
/// of the Constraints X and Y. Returns true if X has changed.
|
||||
bool intersectConstraints(Constraint *X,
|
||||
const Constraint *Y);
|
||||
|
||||
/// propagate - Review the constraints, looking for opportunities
|
||||
/// to simplify a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagate(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
SmallBitVector &Loops,
|
||||
SmallVector<Constraint, 4> &Constraints,
|
||||
bool &Consistent);
|
||||
|
||||
/// propagateDistance - Attempt to propagate a distance
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagateDistance(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint,
|
||||
bool &Consistent);
|
||||
|
||||
/// propagatePoint - Attempt to propagate a point
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
bool propagatePoint(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint);
|
||||
|
||||
/// propagateLine - Attempt to propagate a line
|
||||
/// constraint into a subscript pair (Src and Dst).
|
||||
/// Return true if some simplification occurs.
|
||||
/// If the simplification isn't exact (that is, if it is conservative
|
||||
/// in terms of dependence), set consistent to false.
|
||||
bool propagateLine(const SCEV *&Src,
|
||||
const SCEV *&Dst,
|
||||
Constraint &CurConstraint,
|
||||
bool &Consistent);
|
||||
|
||||
/// findCoefficient - Given a linear SCEV,
|
||||
/// return the coefficient corresponding to specified loop.
|
||||
/// If there isn't one, return the SCEV constant 0.
|
||||
/// For example, given a*i + b*j + c*k, returning the coefficient
|
||||
/// corresponding to the j loop would yield b.
|
||||
const SCEV *findCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop) const;
|
||||
|
||||
/// zeroCoefficient - Given a linear SCEV,
|
||||
/// return the SCEV given by zeroing out the coefficient
|
||||
/// corresponding to the specified loop.
|
||||
/// For example, given a*i + b*j + c*k, zeroing the coefficient
|
||||
/// corresponding to the j loop would yield a*i + c*k.
|
||||
const SCEV *zeroCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop) const;
|
||||
|
||||
/// addToCoefficient - Given a linear SCEV Expr,
|
||||
/// return the SCEV given by adding some Value to the
|
||||
/// coefficient corresponding to the specified TargetLoop.
|
||||
/// For example, given a*i + b*j + c*k, adding 1 to the coefficient
|
||||
/// corresponding to the j loop would yield a*i + (b+1)*j + c*k.
|
||||
const SCEV *addToCoefficient(const SCEV *Expr,
|
||||
const Loop *TargetLoop,
|
||||
const SCEV *Value) const;
|
||||
|
||||
/// updateDirection - Update direction vector entry
|
||||
/// based on the current constraint.
|
||||
void updateDirection(Dependence::DVEntry &Level,
|
||||
const Constraint &CurConstraint) const;
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
DependenceAnalysis() : FunctionPass(ID) {
|
||||
initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
void releaseMemory();
|
||||
void getAnalysisUsage(AnalysisUsage &) const;
|
||||
void print(raw_ostream &, const Module * = 0) const;
|
||||
}; // class DependenceAnalysis
|
||||
|
||||
/// createDependenceAnalysisPass - This creates an instance of the
|
||||
/// DependenceAnalysis pass.
|
||||
FunctionPass *createDependenceAnalysisPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
30
thirdparty/clang/include/llvm/Analysis/DomPrinter.h
vendored
Normal file
30
thirdparty/clang/include/llvm/Analysis/DomPrinter.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
//===-- DomPrinter.h - Dom printer external interface ------------*- 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 external functions that can be called to explicitly
|
||||
// instantiate the dominance tree printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMPRINTER_H
|
||||
#define LLVM_ANALYSIS_DOMPRINTER_H
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
FunctionPass *createDomPrinterPass();
|
||||
FunctionPass *createDomOnlyPrinterPass();
|
||||
FunctionPass *createDomViewerPass();
|
||||
FunctionPass *createDomOnlyViewerPass();
|
||||
FunctionPass *createPostDomPrinterPass();
|
||||
FunctionPass *createPostDomOnlyPrinterPass();
|
||||
FunctionPass *createPostDomViewerPass();
|
||||
FunctionPass *createPostDomOnlyViewerPass();
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
190
thirdparty/clang/include/llvm/Analysis/DominanceFrontier.h
vendored
Normal file
190
thirdparty/clang/include/llvm/Analysis/DominanceFrontier.h
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- 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 DominanceFrontier class, which calculate and holds the
|
||||
// dominance frontier for a function.
|
||||
//
|
||||
// This should be considered deprecated, don't add any more uses of this data
|
||||
// structure.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H
|
||||
#define LLVM_ANALYSIS_DOMINANCEFRONTIER_H
|
||||
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominanceFrontierBase - Common base class for computing forward and inverse
|
||||
/// dominance frontiers for a function.
|
||||
///
|
||||
class DominanceFrontierBase : public FunctionPass {
|
||||
public:
|
||||
typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb
|
||||
typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map
|
||||
protected:
|
||||
DomSetMapType Frontiers;
|
||||
std::vector<BasicBlock*> Roots;
|
||||
const bool IsPostDominators;
|
||||
|
||||
public:
|
||||
DominanceFrontierBase(char &ID, bool isPostDom)
|
||||
: FunctionPass(ID), IsPostDominators(isPostDom) {}
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<BasicBlock*> &getRoots() const { return Roots; }
|
||||
|
||||
/// isPostDominator - Returns true if analysis based of postdoms
|
||||
///
|
||||
bool isPostDominator() const { return IsPostDominators; }
|
||||
|
||||
virtual void releaseMemory() { Frontiers.clear(); }
|
||||
|
||||
// Accessor interface:
|
||||
typedef DomSetMapType::iterator iterator;
|
||||
typedef DomSetMapType::const_iterator const_iterator;
|
||||
iterator begin() { return Frontiers.begin(); }
|
||||
const_iterator begin() const { return Frontiers.begin(); }
|
||||
iterator end() { return Frontiers.end(); }
|
||||
const_iterator end() const { return Frontiers.end(); }
|
||||
iterator find(BasicBlock *B) { return Frontiers.find(B); }
|
||||
const_iterator find(BasicBlock *B) const { return Frontiers.find(B); }
|
||||
|
||||
iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) {
|
||||
assert(find(BB) == end() && "Block already in DominanceFrontier!");
|
||||
return Frontiers.insert(std::make_pair(BB, frontier)).first;
|
||||
}
|
||||
|
||||
/// removeBlock - Remove basic block BB's frontier.
|
||||
void removeBlock(BasicBlock *BB) {
|
||||
assert(find(BB) != end() && "Block is not in DominanceFrontier!");
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
I->second.erase(BB);
|
||||
Frontiers.erase(BB);
|
||||
}
|
||||
|
||||
void addToFrontier(iterator I, BasicBlock *Node) {
|
||||
assert(I != end() && "BB is not in DominanceFrontier!");
|
||||
I->second.insert(Node);
|
||||
}
|
||||
|
||||
void removeFromFrontier(iterator I, BasicBlock *Node) {
|
||||
assert(I != end() && "BB is not in DominanceFrontier!");
|
||||
assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB");
|
||||
I->second.erase(Node);
|
||||
}
|
||||
|
||||
/// compareDomSet - Return false if two domsets match. Otherwise
|
||||
/// return true;
|
||||
bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const {
|
||||
std::set<BasicBlock *> tmpSet;
|
||||
for (DomSetType::const_iterator I = DS2.begin(),
|
||||
E = DS2.end(); I != E; ++I)
|
||||
tmpSet.insert(*I);
|
||||
|
||||
for (DomSetType::const_iterator I = DS1.begin(),
|
||||
E = DS1.end(); I != E; ) {
|
||||
BasicBlock *Node = *I++;
|
||||
|
||||
if (tmpSet.erase(Node) == 0)
|
||||
// Node is in DS1 but not in DS2.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!tmpSet.empty())
|
||||
// There are nodes that are in DS2 but not in DS1.
|
||||
return true;
|
||||
|
||||
// DS1 and DS2 matches.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// compare - Return true if the other dominance frontier base matches
|
||||
/// this dominance frontier base. Otherwise return false.
|
||||
bool compare(DominanceFrontierBase &Other) const {
|
||||
DomSetMapType tmpFrontiers;
|
||||
for (DomSetMapType::const_iterator I = Other.begin(),
|
||||
E = Other.end(); I != E; ++I)
|
||||
tmpFrontiers.insert(std::make_pair(I->first, I->second));
|
||||
|
||||
for (DomSetMapType::iterator I = tmpFrontiers.begin(),
|
||||
E = tmpFrontiers.end(); I != E; ) {
|
||||
BasicBlock *Node = I->first;
|
||||
const_iterator DFI = find(Node);
|
||||
if (DFI == end())
|
||||
return true;
|
||||
|
||||
if (compareDomSet(I->second, DFI->second))
|
||||
return true;
|
||||
|
||||
++I;
|
||||
tmpFrontiers.erase(Node);
|
||||
}
|
||||
|
||||
if (!tmpFrontiers.empty())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// print - Convert to human readable form
|
||||
///
|
||||
virtual void print(raw_ostream &OS, const Module* = 0) const;
|
||||
|
||||
/// dump - Dump the dominance frontier to dbgs().
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is
|
||||
/// used to compute a forward dominator frontiers.
|
||||
///
|
||||
class DominanceFrontier : public DominanceFrontierBase {
|
||||
virtual void anchor();
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
DominanceFrontier() :
|
||||
DominanceFrontierBase(ID, false) {
|
||||
initializeDominanceFrontierPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
BasicBlock *getRoot() const {
|
||||
assert(Roots.size() == 1 && "Should always have entry node!");
|
||||
return Roots[0];
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(Function &) {
|
||||
Frontiers.clear();
|
||||
DominatorTree &DT = getAnalysis<DominatorTree>();
|
||||
Roots = DT.getRoots();
|
||||
assert(Roots.size() == 1 && "Only one entry block for forward domfronts!");
|
||||
calculate(DT, DT[Roots[0]]);
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<DominatorTree>();
|
||||
}
|
||||
|
||||
const DomSetType &calculate(const DominatorTree &DT,
|
||||
const DomTreeNode *Node);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
289
thirdparty/clang/include/llvm/Analysis/DominatorInternals.h
vendored
Normal file
289
thirdparty/clang/include/llvm/Analysis/DominatorInternals.h
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
//=== llvm/Analysis/DominatorInternals.h - Dominator Calculation -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H
|
||||
#define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DominatorTree construction - This pass constructs immediate dominator
|
||||
// information for a flow-graph based on the algorithm described in this
|
||||
// document:
|
||||
//
|
||||
// A Fast Algorithm for Finding Dominators in a Flowgraph
|
||||
// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141.
|
||||
//
|
||||
// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns
|
||||
// out that the theoretically slower O(n*log(n)) implementation is actually
|
||||
// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<class GraphT>
|
||||
unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V, unsigned N) {
|
||||
// This is more understandable as a recursive algorithm, but we can't use the
|
||||
// recursive algorithm due to stack depth issues. Keep it here for
|
||||
// documentation purposes.
|
||||
#if 0
|
||||
InfoRec &VInfo = DT.Info[DT.Roots[i]];
|
||||
VInfo.DFSNum = VInfo.Semi = ++N;
|
||||
VInfo.Label = V;
|
||||
|
||||
Vertex.push_back(V); // Vertex[n] = V;
|
||||
|
||||
for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) {
|
||||
InfoRec &SuccVInfo = DT.Info[*SI];
|
||||
if (SuccVInfo.Semi == 0) {
|
||||
SuccVInfo.Parent = V;
|
||||
N = DTDFSPass(DT, *SI, N);
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool IsChildOfArtificialExit = (N != 0);
|
||||
|
||||
SmallVector<std::pair<typename GraphT::NodeType*,
|
||||
typename GraphT::ChildIteratorType>, 32> Worklist;
|
||||
Worklist.push_back(std::make_pair(V, GraphT::child_begin(V)));
|
||||
while (!Worklist.empty()) {
|
||||
typename GraphT::NodeType* BB = Worklist.back().first;
|
||||
typename GraphT::ChildIteratorType NextSucc = Worklist.back().second;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo =
|
||||
DT.Info[BB];
|
||||
|
||||
// First time we visited this BB?
|
||||
if (NextSucc == GraphT::child_begin(BB)) {
|
||||
BBInfo.DFSNum = BBInfo.Semi = ++N;
|
||||
BBInfo.Label = BB;
|
||||
|
||||
DT.Vertex.push_back(BB); // Vertex[n] = V;
|
||||
|
||||
if (IsChildOfArtificialExit)
|
||||
BBInfo.Parent = 1;
|
||||
|
||||
IsChildOfArtificialExit = false;
|
||||
}
|
||||
|
||||
// store the DFS number of the current BB - the reference to BBInfo might
|
||||
// get invalidated when processing the successors.
|
||||
unsigned BBDFSNum = BBInfo.DFSNum;
|
||||
|
||||
// If we are done with this block, remove it from the worklist.
|
||||
if (NextSucc == GraphT::child_end(BB)) {
|
||||
Worklist.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Increment the successor number for the next time we get to it.
|
||||
++Worklist.back().second;
|
||||
|
||||
// Visit the successor next, if it isn't already visited.
|
||||
typename GraphT::NodeType* Succ = *NextSucc;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &SuccVInfo =
|
||||
DT.Info[Succ];
|
||||
if (SuccVInfo.Semi == 0) {
|
||||
SuccVInfo.Parent = BBDFSNum;
|
||||
Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return N;
|
||||
}
|
||||
|
||||
template<class GraphT>
|
||||
typename GraphT::NodeType*
|
||||
Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType *VIn, unsigned LastLinked) {
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo =
|
||||
DT.Info[VIn];
|
||||
if (VInInfo.DFSNum < LastLinked)
|
||||
return VIn;
|
||||
|
||||
SmallVector<typename GraphT::NodeType*, 32> Work;
|
||||
SmallPtrSet<typename GraphT::NodeType*, 32> Visited;
|
||||
|
||||
if (VInInfo.Parent >= LastLinked)
|
||||
Work.push_back(VIn);
|
||||
|
||||
while (!Work.empty()) {
|
||||
typename GraphT::NodeType* V = Work.back();
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
|
||||
DT.Info[V];
|
||||
typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent];
|
||||
|
||||
// Process Ancestor first
|
||||
if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) {
|
||||
Work.push_back(VAncestor);
|
||||
continue;
|
||||
}
|
||||
Work.pop_back();
|
||||
|
||||
// Update VInfo based on Ancestor info
|
||||
if (VInfo.Parent < LastLinked)
|
||||
continue;
|
||||
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo =
|
||||
DT.Info[VAncestor];
|
||||
typename GraphT::NodeType* VAncestorLabel = VAInfo.Label;
|
||||
typename GraphT::NodeType* VLabel = VInfo.Label;
|
||||
if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi)
|
||||
VInfo.Label = VAncestorLabel;
|
||||
VInfo.Parent = VAInfo.Parent;
|
||||
}
|
||||
|
||||
return VInInfo.Label;
|
||||
}
|
||||
|
||||
template<class FuncT, class NodeT>
|
||||
void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
|
||||
FuncT& F) {
|
||||
typedef GraphTraits<NodeT> GraphT;
|
||||
|
||||
unsigned N = 0;
|
||||
bool MultipleRoots = (DT.Roots.size() > 1);
|
||||
if (MultipleRoots) {
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo =
|
||||
DT.Info[NULL];
|
||||
BBInfo.DFSNum = BBInfo.Semi = ++N;
|
||||
BBInfo.Label = NULL;
|
||||
|
||||
DT.Vertex.push_back(NULL); // Vertex[n] = V;
|
||||
}
|
||||
|
||||
// Step #1: Number blocks in depth-first order and initialize variables used
|
||||
// in later stages of the algorithm.
|
||||
for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
|
||||
i != e; ++i)
|
||||
N = DFSPass<GraphT>(DT, DT.Roots[i], N);
|
||||
|
||||
// it might be that some blocks did not get a DFS number (e.g., blocks of
|
||||
// infinite loops). In these cases an artificial exit node is required.
|
||||
MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F));
|
||||
|
||||
// When naively implemented, the Lengauer-Tarjan algorithm requires a separate
|
||||
// bucket for each vertex. However, this is unnecessary, because each vertex
|
||||
// is only placed into a single bucket (that of its semidominator), and each
|
||||
// vertex's bucket is processed before it is added to any bucket itself.
|
||||
//
|
||||
// Instead of using a bucket per vertex, we use a single array Buckets that
|
||||
// has two purposes. Before the vertex V with preorder number i is processed,
|
||||
// Buckets[i] stores the index of the first element in V's bucket. After V's
|
||||
// bucket is processed, Buckets[i] stores the index of the next element in the
|
||||
// bucket containing V, if any.
|
||||
SmallVector<unsigned, 32> Buckets;
|
||||
Buckets.resize(N + 1);
|
||||
for (unsigned i = 1; i <= N; ++i)
|
||||
Buckets[i] = i;
|
||||
|
||||
for (unsigned i = N; i >= 2; --i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo =
|
||||
DT.Info[W];
|
||||
|
||||
// Step #2: Implicitly define the immediate dominator of vertices
|
||||
for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) {
|
||||
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
|
||||
typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1);
|
||||
DT.IDoms[V] = DT.Info[U].Semi < i ? U : W;
|
||||
}
|
||||
|
||||
// Step #3: Calculate the semidominators of all vertices
|
||||
|
||||
// initialize the semi dominator to point to the parent node
|
||||
WInfo.Semi = WInfo.Parent;
|
||||
typedef GraphTraits<Inverse<NodeT> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType CI =
|
||||
InvTraits::child_begin(W),
|
||||
E = InvTraits::child_end(W); CI != E; ++CI) {
|
||||
typename InvTraits::NodeType *N = *CI;
|
||||
if (DT.Info.count(N)) { // Only if this predecessor is reachable!
|
||||
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi;
|
||||
if (SemiU < WInfo.Semi)
|
||||
WInfo.Semi = SemiU;
|
||||
}
|
||||
}
|
||||
|
||||
// If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is
|
||||
// necessarily parent(V). In this case, set idom(V) here and avoid placing
|
||||
// V into a bucket.
|
||||
if (WInfo.Semi == WInfo.Parent) {
|
||||
DT.IDoms[W] = DT.Vertex[WInfo.Parent];
|
||||
} else {
|
||||
Buckets[i] = Buckets[WInfo.Semi];
|
||||
Buckets[WInfo.Semi] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (N >= 1) {
|
||||
typename GraphT::NodeType* Root = DT.Vertex[1];
|
||||
for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) {
|
||||
typename GraphT::NodeType* V = DT.Vertex[Buckets[j]];
|
||||
DT.IDoms[V] = Root;
|
||||
}
|
||||
}
|
||||
|
||||
// Step #4: Explicitly define the immediate dominator of each vertex
|
||||
for (unsigned i = 2; i <= N; ++i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
typename GraphT::NodeType*& WIDom = DT.IDoms[W];
|
||||
if (WIDom != DT.Vertex[DT.Info[W].Semi])
|
||||
WIDom = DT.IDoms[WIDom];
|
||||
}
|
||||
|
||||
if (DT.Roots.empty()) return;
|
||||
|
||||
// Add a node for the root. This node might be the actual root, if there is
|
||||
// one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0)
|
||||
// which postdominates all real exits if there are multiple exit blocks, or
|
||||
// an infinite loop.
|
||||
typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : 0;
|
||||
|
||||
DT.DomTreeNodes[Root] = DT.RootNode =
|
||||
new DomTreeNodeBase<typename GraphT::NodeType>(Root, 0);
|
||||
|
||||
// Loop over all of the reachable blocks in the function...
|
||||
for (unsigned i = 2; i <= N; ++i) {
|
||||
typename GraphT::NodeType* W = DT.Vertex[i];
|
||||
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W];
|
||||
if (BBNode) continue; // Haven't calculated this node yet?
|
||||
|
||||
typename GraphT::NodeType* ImmDom = DT.getIDom(W);
|
||||
|
||||
assert(ImmDom || DT.DomTreeNodes[NULL]);
|
||||
|
||||
// Get or calculate the node for the immediate dominator
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *IDomNode =
|
||||
DT.getNodeForBlock(ImmDom);
|
||||
|
||||
// Add a new tree node for this BasicBlock, and link it as a child of
|
||||
// IDomNode
|
||||
DomTreeNodeBase<typename GraphT::NodeType> *C =
|
||||
new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode);
|
||||
DT.DomTreeNodes[W] = IDomNode->addChild(C);
|
||||
}
|
||||
|
||||
// Free temporary memory used to construct idom's
|
||||
DT.IDoms.clear();
|
||||
DT.Info.clear();
|
||||
std::vector<typename GraphT::NodeType*>().swap(DT.Vertex);
|
||||
|
||||
DT.updateDFSNumbers();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
920
thirdparty/clang/include/llvm/Analysis/Dominators.h
vendored
Normal file
920
thirdparty/clang/include/llvm/Analysis/Dominators.h
vendored
Normal file
@@ -0,0 +1,920 @@
|
||||
//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- 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 DominatorTree class, which provides fast and efficient
|
||||
// dominance queries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_DOMINATORS_H
|
||||
#define LLVM_ANALYSIS_DOMINATORS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DepthFirstIterator.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominatorBase - Base class that other, more interesting dominator analyses
|
||||
/// inherit from.
|
||||
///
|
||||
template <class NodeT>
|
||||
class DominatorBase {
|
||||
protected:
|
||||
std::vector<NodeT*> Roots;
|
||||
const bool IsPostDominators;
|
||||
inline explicit DominatorBase(bool isPostDom) :
|
||||
Roots(), IsPostDominators(isPostDom) {}
|
||||
public:
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<NodeT*> &getRoots() const { return Roots; }
|
||||
|
||||
/// isPostDominator - Returns true if analysis based of postdoms
|
||||
///
|
||||
bool isPostDominator() const { return IsPostDominators; }
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DomTreeNode - Dominator Tree Node
|
||||
template<class NodeT> class DominatorTreeBase;
|
||||
struct PostDominatorTree;
|
||||
class MachineBasicBlock;
|
||||
|
||||
template <class NodeT>
|
||||
class DomTreeNodeBase {
|
||||
NodeT *TheBB;
|
||||
DomTreeNodeBase<NodeT> *IDom;
|
||||
std::vector<DomTreeNodeBase<NodeT> *> Children;
|
||||
int DFSNumIn, DFSNumOut;
|
||||
|
||||
template<class N> friend class DominatorTreeBase;
|
||||
friend struct PostDominatorTree;
|
||||
public:
|
||||
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator;
|
||||
typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator
|
||||
const_iterator;
|
||||
|
||||
iterator begin() { return Children.begin(); }
|
||||
iterator end() { return Children.end(); }
|
||||
const_iterator begin() const { return Children.begin(); }
|
||||
const_iterator end() const { return Children.end(); }
|
||||
|
||||
NodeT *getBlock() const { return TheBB; }
|
||||
DomTreeNodeBase<NodeT> *getIDom() const { return IDom; }
|
||||
const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const {
|
||||
return Children;
|
||||
}
|
||||
|
||||
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom)
|
||||
: TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { }
|
||||
|
||||
DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) {
|
||||
Children.push_back(C);
|
||||
return C;
|
||||
}
|
||||
|
||||
size_t getNumChildren() const {
|
||||
return Children.size();
|
||||
}
|
||||
|
||||
void clearAllChildren() {
|
||||
Children.clear();
|
||||
}
|
||||
|
||||
bool compare(const DomTreeNodeBase<NodeT> *Other) const {
|
||||
if (getNumChildren() != Other->getNumChildren())
|
||||
return true;
|
||||
|
||||
SmallPtrSet<const NodeT *, 4> OtherChildren;
|
||||
for (const_iterator I = Other->begin(), E = Other->end(); I != E; ++I) {
|
||||
const NodeT *Nd = (*I)->getBlock();
|
||||
OtherChildren.insert(Nd);
|
||||
}
|
||||
|
||||
for (const_iterator I = begin(), E = end(); I != E; ++I) {
|
||||
const NodeT *N = (*I)->getBlock();
|
||||
if (OtherChildren.count(N) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setIDom(DomTreeNodeBase<NodeT> *NewIDom) {
|
||||
assert(IDom && "No immediate dominator?");
|
||||
if (IDom != NewIDom) {
|
||||
typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
|
||||
std::find(IDom->Children.begin(), IDom->Children.end(), this);
|
||||
assert(I != IDom->Children.end() &&
|
||||
"Not in immediate dominator children set!");
|
||||
// I am no longer your child...
|
||||
IDom->Children.erase(I);
|
||||
|
||||
// Switch to new dominator
|
||||
IDom = NewIDom;
|
||||
IDom->Children.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do
|
||||
/// not call them.
|
||||
unsigned getDFSNumIn() const { return DFSNumIn; }
|
||||
unsigned getDFSNumOut() const { return DFSNumOut; }
|
||||
private:
|
||||
// Return true if this node is dominated by other. Use this only if DFS info
|
||||
// is valid.
|
||||
bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const {
|
||||
return this->DFSNumIn >= other->DFSNumIn &&
|
||||
this->DFSNumOut <= other->DFSNumOut;
|
||||
}
|
||||
};
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<MachineBasicBlock>);
|
||||
|
||||
template<class NodeT>
|
||||
inline raw_ostream &operator<<(raw_ostream &o,
|
||||
const DomTreeNodeBase<NodeT> *Node) {
|
||||
if (Node->getBlock())
|
||||
WriteAsOperand(o, Node->getBlock(), false);
|
||||
else
|
||||
o << " <<exit node>>";
|
||||
|
||||
o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}";
|
||||
|
||||
return o << "\n";
|
||||
}
|
||||
|
||||
template<class NodeT>
|
||||
inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o,
|
||||
unsigned Lev) {
|
||||
o.indent(2*Lev) << "[" << Lev << "] " << N;
|
||||
for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(),
|
||||
E = N->end(); I != E; ++I)
|
||||
PrintDomTree<NodeT>(*I, o, Lev+1);
|
||||
}
|
||||
|
||||
typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// DominatorTree - Calculate the immediate dominator tree for a function.
|
||||
///
|
||||
|
||||
template<class FuncT, class N>
|
||||
void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
|
||||
FuncT& F);
|
||||
|
||||
template<class NodeT>
|
||||
class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) const {
|
||||
assert(A != B);
|
||||
assert(isReachableFromEntry(B));
|
||||
assert(isReachableFromEntry(A));
|
||||
|
||||
const DomTreeNodeBase<NodeT> *IDom;
|
||||
while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B)
|
||||
B = IDom; // Walk up the tree
|
||||
return IDom != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
|
||||
DomTreeNodeMapType DomTreeNodes;
|
||||
DomTreeNodeBase<NodeT> *RootNode;
|
||||
|
||||
bool DFSInfoValid;
|
||||
unsigned int SlowQueries;
|
||||
// Information record used during immediate dominators computation.
|
||||
struct InfoRec {
|
||||
unsigned DFSNum;
|
||||
unsigned Parent;
|
||||
unsigned Semi;
|
||||
NodeT *Label;
|
||||
|
||||
InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {}
|
||||
};
|
||||
|
||||
DenseMap<NodeT*, NodeT*> IDoms;
|
||||
|
||||
// Vertex - Map the DFS number to the BasicBlock*
|
||||
std::vector<NodeT*> Vertex;
|
||||
|
||||
// Info - Collection of information used during the computation of idoms.
|
||||
DenseMap<NodeT*, InfoRec> Info;
|
||||
|
||||
void reset() {
|
||||
for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(),
|
||||
E = DomTreeNodes.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
DomTreeNodes.clear();
|
||||
IDoms.clear();
|
||||
this->Roots.clear();
|
||||
Vertex.clear();
|
||||
RootNode = 0;
|
||||
}
|
||||
|
||||
// NewBB is split and now it has one successor. Update dominator tree to
|
||||
// reflect this change.
|
||||
template<class N, class GraphT>
|
||||
void Split(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* NewBB) {
|
||||
assert(std::distance(GraphT::child_begin(NewBB),
|
||||
GraphT::child_end(NewBB)) == 1 &&
|
||||
"NewBB should have a single successor!");
|
||||
typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
|
||||
|
||||
std::vector<typename GraphT::NodeType*> PredBlocks;
|
||||
typedef GraphTraits<Inverse<N> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBB),
|
||||
PE = InvTraits::child_end(NewBB); PI != PE; ++PI)
|
||||
PredBlocks.push_back(*PI);
|
||||
|
||||
assert(!PredBlocks.empty() && "No predblocks?");
|
||||
|
||||
bool NewBBDominatesNewBBSucc = true;
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBBSucc),
|
||||
E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) {
|
||||
typename InvTraits::NodeType *ND = *PI;
|
||||
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
|
||||
DT.isReachableFromEntry(ND)) {
|
||||
NewBBDominatesNewBBSucc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find NewBB's immediate dominator and create new dominator tree node for
|
||||
// NewBB.
|
||||
NodeT *NewBBIDom = 0;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < PredBlocks.size(); ++i)
|
||||
if (DT.isReachableFromEntry(PredBlocks[i])) {
|
||||
NewBBIDom = PredBlocks[i];
|
||||
break;
|
||||
}
|
||||
|
||||
// It's possible that none of the predecessors of NewBB are reachable;
|
||||
// in that case, NewBB itself is unreachable, so nothing needs to be
|
||||
// changed.
|
||||
if (!NewBBIDom)
|
||||
return;
|
||||
|
||||
for (i = i + 1; i < PredBlocks.size(); ++i) {
|
||||
if (DT.isReachableFromEntry(PredBlocks[i]))
|
||||
NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
|
||||
}
|
||||
|
||||
// Create the new dominator tree node... and set the idom of NewBB.
|
||||
DomTreeNodeBase<NodeT> *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom);
|
||||
|
||||
// If NewBB strictly dominates other blocks, then it is now the immediate
|
||||
// dominator of NewBBSucc. Update the dominator tree as appropriate.
|
||||
if (NewBBDominatesNewBBSucc) {
|
||||
DomTreeNodeBase<NodeT> *NewBBSuccNode = DT.getNode(NewBBSucc);
|
||||
DT.changeImmediateDominator(NewBBSuccNode, NewBBNode);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit DominatorTreeBase(bool isPostDom)
|
||||
: DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {}
|
||||
virtual ~DominatorTreeBase() { reset(); }
|
||||
|
||||
/// compare - Return false if the other dominator tree base matches this
|
||||
/// dominator tree base. Otherwise return true.
|
||||
bool compare(DominatorTreeBase &Other) const {
|
||||
|
||||
const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes;
|
||||
if (DomTreeNodes.size() != OtherDomTreeNodes.size())
|
||||
return true;
|
||||
|
||||
for (typename DomTreeNodeMapType::const_iterator
|
||||
I = this->DomTreeNodes.begin(),
|
||||
E = this->DomTreeNodes.end(); I != E; ++I) {
|
||||
NodeT *BB = I->first;
|
||||
typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB);
|
||||
if (OI == OtherDomTreeNodes.end())
|
||||
return true;
|
||||
|
||||
DomTreeNodeBase<NodeT>* MyNd = I->second;
|
||||
DomTreeNodeBase<NodeT>* OtherNd = OI->second;
|
||||
|
||||
if (MyNd->compare(OtherNd))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void releaseMemory() { reset(); }
|
||||
|
||||
/// getNode - return the (Post)DominatorTree node for the specified basic
|
||||
/// block. This is the same as using operator[] on this class.
|
||||
///
|
||||
inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
|
||||
return DomTreeNodes.lookup(BB);
|
||||
}
|
||||
|
||||
/// getRootNode - This returns the entry node for the CFG of the function. If
|
||||
/// this tree represents the post-dominance relations for a function, however,
|
||||
/// this root may be a node with the block == NULL. This is the case when
|
||||
/// there are multiple exit nodes from a particular function. Consumers of
|
||||
/// post-dominance information must be capable of dealing with this
|
||||
/// possibility.
|
||||
///
|
||||
DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; }
|
||||
const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; }
|
||||
|
||||
/// properlyDominates - Returns true iff A dominates B and A != B.
|
||||
/// Note that this is not a constant time operation!
|
||||
///
|
||||
bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
if (A == 0 || B == 0)
|
||||
return false;
|
||||
if (A == B)
|
||||
return false;
|
||||
return dominates(A, B);
|
||||
}
|
||||
|
||||
bool properlyDominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
/// isReachableFromEntry - Return true if A is dominated by the entry
|
||||
/// block of the function containing it.
|
||||
bool isReachableFromEntry(const NodeT* A) const {
|
||||
assert(!this->isPostDominator() &&
|
||||
"This is not implemented for post dominators");
|
||||
return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
|
||||
}
|
||||
|
||||
inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const {
|
||||
return A;
|
||||
}
|
||||
|
||||
/// dominates - Returns true iff A dominates B. Note that this is not a
|
||||
/// constant time operation!
|
||||
///
|
||||
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
// A node trivially dominates itself.
|
||||
if (B == A)
|
||||
return true;
|
||||
|
||||
// An unreachable node is dominated by anything.
|
||||
if (!isReachableFromEntry(B))
|
||||
return true;
|
||||
|
||||
// And dominates nothing.
|
||||
if (!isReachableFromEntry(A))
|
||||
return false;
|
||||
|
||||
// Compare the result of the tree walk and the dfs numbers, if expensive
|
||||
// checks are enabled.
|
||||
#ifdef XDEBUG
|
||||
assert((!DFSInfoValid ||
|
||||
(dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
|
||||
"Tree walk disagrees with dfs numbers!");
|
||||
#endif
|
||||
|
||||
if (DFSInfoValid)
|
||||
return B->DominatedBy(A);
|
||||
|
||||
// If we end up with too many slow queries, just update the
|
||||
// DFS numbers on the theory that we are going to keep querying.
|
||||
SlowQueries++;
|
||||
if (SlowQueries > 32) {
|
||||
updateDFSNumbers();
|
||||
return B->DominatedBy(A);
|
||||
}
|
||||
|
||||
return dominatedBySlowTreeWalk(A, B);
|
||||
}
|
||||
|
||||
bool dominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
NodeT *getRoot() const {
|
||||
assert(this->Roots.size() == 1 && "Should always have entry node!");
|
||||
return this->Roots[0];
|
||||
}
|
||||
|
||||
/// findNearestCommonDominator - Find nearest common dominator basic block
|
||||
/// for basic block A and B. If there is no such block then return NULL.
|
||||
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
|
||||
assert(A->getParent() == B->getParent() &&
|
||||
"Two blocks are not in same function");
|
||||
|
||||
// If either A or B is a entry block then it is nearest common dominator
|
||||
// (for forward-dominators).
|
||||
if (!this->isPostDominator()) {
|
||||
NodeT &Entry = A->getParent()->front();
|
||||
if (A == &Entry || B == &Entry)
|
||||
return &Entry;
|
||||
}
|
||||
|
||||
// If B dominates A then B is nearest common dominator.
|
||||
if (dominates(B, A))
|
||||
return B;
|
||||
|
||||
// If A dominates B then A is nearest common dominator.
|
||||
if (dominates(A, B))
|
||||
return A;
|
||||
|
||||
DomTreeNodeBase<NodeT> *NodeA = getNode(A);
|
||||
DomTreeNodeBase<NodeT> *NodeB = getNode(B);
|
||||
|
||||
// Collect NodeA dominators set.
|
||||
SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms;
|
||||
NodeADoms.insert(NodeA);
|
||||
DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom();
|
||||
while (IDomA) {
|
||||
NodeADoms.insert(IDomA);
|
||||
IDomA = IDomA->getIDom();
|
||||
}
|
||||
|
||||
// Walk NodeB immediate dominators chain and find common dominator node.
|
||||
DomTreeNodeBase<NodeT> *IDomB = NodeB->getIDom();
|
||||
while (IDomB) {
|
||||
if (NodeADoms.count(IDomB) != 0)
|
||||
return IDomB->getBlock();
|
||||
|
||||
IDomB = IDomB->getIDom();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) {
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// const is re-introduced on the return type.
|
||||
return findNearestCommonDominator(const_cast<NodeT *>(A),
|
||||
const_cast<NodeT *>(B));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// API to update (Post)DominatorTree information based on modifications to
|
||||
// the CFG...
|
||||
|
||||
/// addNewBlock - Add a new node to the dominator tree information. This
|
||||
/// creates a new node as a child of DomBB dominator node,linking it into
|
||||
/// the children list of the immediate dominator.
|
||||
DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) {
|
||||
assert(getNode(BB) == 0 && "Block already in dominator tree!");
|
||||
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
|
||||
assert(IDomNode && "Not immediate dominator specified for block!");
|
||||
DFSInfoValid = false;
|
||||
return DomTreeNodes[BB] =
|
||||
IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode));
|
||||
}
|
||||
|
||||
/// changeImmediateDominator - This method is used to update the dominator
|
||||
/// tree information when a node's immediate dominator changes.
|
||||
///
|
||||
void changeImmediateDominator(DomTreeNodeBase<NodeT> *N,
|
||||
DomTreeNodeBase<NodeT> *NewIDom) {
|
||||
assert(N && NewIDom && "Cannot change null node pointers!");
|
||||
DFSInfoValid = false;
|
||||
N->setIDom(NewIDom);
|
||||
}
|
||||
|
||||
void changeImmediateDominator(NodeT *BB, NodeT *NewBB) {
|
||||
changeImmediateDominator(getNode(BB), getNode(NewBB));
|
||||
}
|
||||
|
||||
/// eraseNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Removes node from its immediate dominator's
|
||||
/// children list. Deletes dominator node associated with basic block BB.
|
||||
void eraseNode(NodeT *BB) {
|
||||
DomTreeNodeBase<NodeT> *Node = getNode(BB);
|
||||
assert(Node && "Removing node that isn't in dominator tree.");
|
||||
assert(Node->getChildren().empty() && "Node is not a leaf node.");
|
||||
|
||||
// Remove node from immediate dominator's children list.
|
||||
DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
|
||||
if (IDom) {
|
||||
typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I =
|
||||
std::find(IDom->Children.begin(), IDom->Children.end(), Node);
|
||||
assert(I != IDom->Children.end() &&
|
||||
"Not in immediate dominator children set!");
|
||||
// I am no longer your child...
|
||||
IDom->Children.erase(I);
|
||||
}
|
||||
|
||||
DomTreeNodes.erase(BB);
|
||||
delete Node;
|
||||
}
|
||||
|
||||
/// removeNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Invalidates any node pointing to removed
|
||||
/// block.
|
||||
void removeNode(NodeT *BB) {
|
||||
assert(getNode(BB) && "Removing node that isn't in dominator tree.");
|
||||
DomTreeNodes.erase(BB);
|
||||
}
|
||||
|
||||
/// splitBlock - BB is split and now it has one successor. Update dominator
|
||||
/// tree to reflect this change.
|
||||
void splitBlock(NodeT* NewBB) {
|
||||
if (this->IsPostDominators)
|
||||
this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB);
|
||||
else
|
||||
this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB);
|
||||
}
|
||||
|
||||
/// print - Convert to human readable form
|
||||
///
|
||||
void print(raw_ostream &o) const {
|
||||
o << "=============================--------------------------------\n";
|
||||
if (this->isPostDominator())
|
||||
o << "Inorder PostDominator Tree: ";
|
||||
else
|
||||
o << "Inorder Dominator Tree: ";
|
||||
if (!this->DFSInfoValid)
|
||||
o << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
|
||||
o << "\n";
|
||||
|
||||
// The postdom tree can have a null root if there are no returns.
|
||||
if (getRootNode())
|
||||
PrintDomTree<NodeT>(getRootNode(), o, 1);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<class GraphT>
|
||||
friend typename GraphT::NodeType* Eval(
|
||||
DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V,
|
||||
unsigned LastLinked);
|
||||
|
||||
template<class GraphT>
|
||||
friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType* V,
|
||||
unsigned N);
|
||||
|
||||
template<class FuncT, class N>
|
||||
friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
|
||||
FuncT& F);
|
||||
|
||||
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
|
||||
/// dominator tree in dfs order.
|
||||
void updateDFSNumbers() {
|
||||
unsigned DFSNum = 0;
|
||||
|
||||
SmallVector<std::pair<DomTreeNodeBase<NodeT>*,
|
||||
typename DomTreeNodeBase<NodeT>::iterator>, 32> WorkStack;
|
||||
|
||||
DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
|
||||
|
||||
if (!ThisRoot)
|
||||
return;
|
||||
|
||||
// Even in the case of multiple exits that form the post dominator root
|
||||
// nodes, do not iterate over all exits, but start from the virtual root
|
||||
// node. Otherwise bbs, that are not post dominated by any exit but by the
|
||||
// virtual root node, will never be assigned a DFS number.
|
||||
WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin()));
|
||||
ThisRoot->DFSNumIn = DFSNum++;
|
||||
|
||||
while (!WorkStack.empty()) {
|
||||
DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
|
||||
typename DomTreeNodeBase<NodeT>::iterator ChildIt =
|
||||
WorkStack.back().second;
|
||||
|
||||
// If we visited all of the children of this node, "recurse" back up the
|
||||
// stack setting the DFOutNum.
|
||||
if (ChildIt == Node->end()) {
|
||||
Node->DFSNumOut = DFSNum++;
|
||||
WorkStack.pop_back();
|
||||
} else {
|
||||
// Otherwise, recursively visit this child.
|
||||
DomTreeNodeBase<NodeT> *Child = *ChildIt;
|
||||
++WorkStack.back().second;
|
||||
|
||||
WorkStack.push_back(std::make_pair(Child, Child->begin()));
|
||||
Child->DFSNumIn = DFSNum++;
|
||||
}
|
||||
}
|
||||
|
||||
SlowQueries = 0;
|
||||
DFSInfoValid = true;
|
||||
}
|
||||
|
||||
DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
|
||||
if (DomTreeNodeBase<NodeT> *Node = getNode(BB))
|
||||
return Node;
|
||||
|
||||
// Haven't calculated this node yet? Get or calculate the node for the
|
||||
// immediate dominator.
|
||||
NodeT *IDom = getIDom(BB);
|
||||
|
||||
assert(IDom || this->DomTreeNodes[NULL]);
|
||||
DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom);
|
||||
|
||||
// Add a new tree node for this BasicBlock, and link it as a child of
|
||||
// IDomNode
|
||||
DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode);
|
||||
return this->DomTreeNodes[BB] = IDomNode->addChild(C);
|
||||
}
|
||||
|
||||
inline NodeT *getIDom(NodeT *BB) const {
|
||||
return IDoms.lookup(BB);
|
||||
}
|
||||
|
||||
inline void addRoot(NodeT* BB) {
|
||||
this->Roots.push_back(BB);
|
||||
}
|
||||
|
||||
public:
|
||||
/// recalculate - compute a dominator tree for the given function
|
||||
template<class FT>
|
||||
void recalculate(FT& F) {
|
||||
typedef GraphTraits<FT*> TraitsTy;
|
||||
reset();
|
||||
this->Vertex.push_back(0);
|
||||
|
||||
if (!this->IsPostDominators) {
|
||||
// Initialize root
|
||||
NodeT *entry = TraitsTy::getEntryNode(&F);
|
||||
this->Roots.push_back(entry);
|
||||
this->IDoms[entry] = 0;
|
||||
this->DomTreeNodes[entry] = 0;
|
||||
|
||||
Calculate<FT, NodeT*>(*this, F);
|
||||
} else {
|
||||
// Initialize the roots list
|
||||
for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
|
||||
E = TraitsTy::nodes_end(&F); I != E; ++I) {
|
||||
if (TraitsTy::child_begin(I) == TraitsTy::child_end(I))
|
||||
addRoot(I);
|
||||
|
||||
// Prepopulate maps so that we don't get iterator invalidation issues later.
|
||||
this->IDoms[I] = 0;
|
||||
this->DomTreeNodes[I] = 0;
|
||||
}
|
||||
|
||||
Calculate<FT, Inverse<NodeT*> >(*this, F);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// These two functions are declared out of line as a workaround for building
|
||||
// with old (< r147295) versions of clang because of pr11642.
|
||||
template<class NodeT>
|
||||
bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return true;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
template<class NodeT>
|
||||
bool
|
||||
DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return false;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
|
||||
|
||||
class BasicBlockEdge {
|
||||
const BasicBlock *Start;
|
||||
const BasicBlock *End;
|
||||
public:
|
||||
BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) :
|
||||
Start(Start_), End(End_) { }
|
||||
const BasicBlock *getStart() const {
|
||||
return Start;
|
||||
}
|
||||
const BasicBlock *getEnd() const {
|
||||
return End;
|
||||
}
|
||||
bool isSingleEdge() const;
|
||||
};
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
|
||||
/// compute a normal dominator tree.
|
||||
///
|
||||
class DominatorTree : public FunctionPass {
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
DominatorTreeBase<BasicBlock>* DT;
|
||||
|
||||
DominatorTree() : FunctionPass(ID) {
|
||||
initializeDominatorTreePass(*PassRegistry::getPassRegistry());
|
||||
DT = new DominatorTreeBase<BasicBlock>(false);
|
||||
}
|
||||
|
||||
~DominatorTree() {
|
||||
delete DT;
|
||||
}
|
||||
|
||||
DominatorTreeBase<BasicBlock>& getBase() { return *DT; }
|
||||
|
||||
/// getRoots - Return the root blocks of the current CFG. This may include
|
||||
/// multiple blocks if we are computing post dominators. For forward
|
||||
/// dominators, this will always be a single block (the entry node).
|
||||
///
|
||||
inline const std::vector<BasicBlock*> &getRoots() const {
|
||||
return DT->getRoots();
|
||||
}
|
||||
|
||||
inline BasicBlock *getRoot() const {
|
||||
return DT->getRoot();
|
||||
}
|
||||
|
||||
inline DomTreeNode *getRootNode() const {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
/// compare - Return false if the other dominator tree matches this
|
||||
/// dominator tree. Otherwise return true.
|
||||
inline bool compare(DominatorTree &Other) const {
|
||||
DomTreeNode *R = getRootNode();
|
||||
DomTreeNode *OtherR = Other.getRootNode();
|
||||
|
||||
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
|
||||
return true;
|
||||
|
||||
if (DT->compare(Other.getBase()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
// dominates - Return true if Def dominates a use in User. This performs
|
||||
// the special checks necessary if Def and User are in the same basic block.
|
||||
// Note that Def doesn't dominate a use in Def itself!
|
||||
bool dominates(const Instruction *Def, const Use &U) const;
|
||||
bool dominates(const Instruction *Def, const Instruction *User) const;
|
||||
bool dominates(const Instruction *Def, const BasicBlock *BB) const;
|
||||
bool dominates(const BasicBlockEdge &BBE, const Use &U) const;
|
||||
bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const;
|
||||
|
||||
bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
/// findNearestCommonDominator - Find nearest common dominator basic block
|
||||
/// for basic block A and B. If there is no such block then return NULL.
|
||||
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A,
|
||||
const BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
inline DomTreeNode *operator[](BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
/// getNode - return the (Post)DominatorTree node for the specified basic
|
||||
/// block. This is the same as using operator[] on this class.
|
||||
///
|
||||
inline DomTreeNode *getNode(BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
/// addNewBlock - Add a new node to the dominator tree information. This
|
||||
/// creates a new node as a child of DomBB dominator node,linking it into
|
||||
/// the children list of the immediate dominator.
|
||||
inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) {
|
||||
return DT->addNewBlock(BB, DomBB);
|
||||
}
|
||||
|
||||
/// changeImmediateDominator - This method is used to update the dominator
|
||||
/// tree information when a node's immediate dominator changes.
|
||||
///
|
||||
inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) {
|
||||
DT->changeImmediateDominator(N, NewIDom);
|
||||
}
|
||||
|
||||
inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) {
|
||||
DT->changeImmediateDominator(N, NewIDom);
|
||||
}
|
||||
|
||||
/// eraseNode - Removes a node from the dominator tree. Block must not
|
||||
/// dominate any other blocks. Removes node from its immediate dominator's
|
||||
/// children list. Deletes dominator node associated with basic block BB.
|
||||
inline void eraseNode(BasicBlock *BB) {
|
||||
DT->eraseNode(BB);
|
||||
}
|
||||
|
||||
/// splitBlock - BB is split and now it has one successor. Update dominator
|
||||
/// tree to reflect this change.
|
||||
inline void splitBlock(BasicBlock* NewBB) {
|
||||
DT->splitBlock(NewBB);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const BasicBlock* A) const {
|
||||
return DT->isReachableFromEntry(A);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const Use &U) const;
|
||||
|
||||
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS, const Module* M= 0) const;
|
||||
};
|
||||
|
||||
//===-------------------------------------
|
||||
/// DominatorTree GraphTraits specialization so the DominatorTree can be
|
||||
/// iterable by generic graph iterators.
|
||||
///
|
||||
template <> struct GraphTraits<DomTreeNode*> {
|
||||
typedef DomTreeNode NodeType;
|
||||
typedef NodeType::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(NodeType *N) {
|
||||
return N;
|
||||
}
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
|
||||
typedef df_iterator<DomTreeNode*> nodes_iterator;
|
||||
|
||||
static nodes_iterator nodes_begin(DomTreeNode *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(DomTreeNode *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<DominatorTree*>
|
||||
: public GraphTraits<DomTreeNode*> {
|
||||
static NodeType *getEntryNode(DominatorTree *DT) {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(DominatorTree *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(DominatorTree *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
66
thirdparty/clang/include/llvm/Analysis/FindUsedTypes.h
vendored
Normal file
66
thirdparty/clang/include/llvm/Analysis/FindUsedTypes.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass is used to seek out all of the types in use by the program.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H
|
||||
#define LLVM_ANALYSIS_FINDUSEDTYPES_H
|
||||
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
class FindUsedTypes : public ModulePass {
|
||||
SetVector<Type *> UsedTypes;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
FindUsedTypes() : ModulePass(ID) {
|
||||
initializeFindUsedTypesPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
/// getTypes - After the pass has been run, return the set containing all of
|
||||
/// the types used in the module.
|
||||
///
|
||||
const SetVector<Type *> &getTypes() const { return UsedTypes; }
|
||||
|
||||
/// Print the types found in the module. If the optional Module parameter is
|
||||
/// passed in, then the types are printed symbolically if possible, using the
|
||||
/// symbol table from the module.
|
||||
///
|
||||
void print(raw_ostream &o, const Module *M) const;
|
||||
|
||||
private:
|
||||
/// IncorporateType - Incorporate one type and all of its subtypes into the
|
||||
/// collection of used types.
|
||||
///
|
||||
void IncorporateType(Type *Ty);
|
||||
|
||||
/// IncorporateValue - Incorporate all of the types used by this value.
|
||||
///
|
||||
void IncorporateValue(const Value *V);
|
||||
|
||||
public:
|
||||
/// run - This incorporates all types used by the specified module
|
||||
bool runOnModule(Module &M);
|
||||
|
||||
/// getAnalysisUsage - We do not modify anything.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
184
thirdparty/clang/include/llvm/Analysis/IVUsers.h
vendored
Normal file
184
thirdparty/clang/include/llvm/Analysis/IVUsers.h
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
//===- llvm/Analysis/IVUsers.h - Induction Variable Users -------*- 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 bookkeeping for "interesting" users of expressions
|
||||
// computed from induction variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_IVUSERS_H
|
||||
#define LLVM_ANALYSIS_IVUSERS_H
|
||||
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionNormalization.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class Value;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class IVUsers;
|
||||
class DataLayout;
|
||||
|
||||
/// IVStrideUse - Keep track of one use of a strided induction variable.
|
||||
/// The Expr member keeps track of the expression, User is the actual user
|
||||
/// instruction of the operand, and 'OperandValToReplace' is the operand of
|
||||
/// the User that is the use.
|
||||
class IVStrideUse : public CallbackVH, public ilist_node<IVStrideUse> {
|
||||
friend class IVUsers;
|
||||
public:
|
||||
IVStrideUse(IVUsers *P, Instruction* U, Value *O)
|
||||
: CallbackVH(U), Parent(P), OperandValToReplace(O) {
|
||||
}
|
||||
|
||||
/// getUser - Return the user instruction for this use.
|
||||
Instruction *getUser() const {
|
||||
return cast<Instruction>(getValPtr());
|
||||
}
|
||||
|
||||
/// setUser - Assign a new user instruction for this use.
|
||||
void setUser(Instruction *NewUser) {
|
||||
setValPtr(NewUser);
|
||||
}
|
||||
|
||||
/// getOperandValToReplace - Return the Value of the operand in the user
|
||||
/// instruction that this IVStrideUse is representing.
|
||||
Value *getOperandValToReplace() const {
|
||||
return OperandValToReplace;
|
||||
}
|
||||
|
||||
/// setOperandValToReplace - Assign a new Value as the operand value
|
||||
/// to replace.
|
||||
void setOperandValToReplace(Value *Op) {
|
||||
OperandValToReplace = Op;
|
||||
}
|
||||
|
||||
/// getPostIncLoops - Return the set of loops for which the expression has
|
||||
/// been adjusted to use post-inc mode.
|
||||
const PostIncLoopSet &getPostIncLoops() const {
|
||||
return PostIncLoops;
|
||||
}
|
||||
|
||||
/// transformToPostInc - Transform the expression to post-inc form for the
|
||||
/// given loop.
|
||||
void transformToPostInc(const Loop *L);
|
||||
|
||||
private:
|
||||
/// Parent - a pointer to the IVUsers that owns this IVStrideUse.
|
||||
IVUsers *Parent;
|
||||
|
||||
/// OperandValToReplace - The Value of the operand in the user instruction
|
||||
/// that this IVStrideUse is representing.
|
||||
WeakVH OperandValToReplace;
|
||||
|
||||
/// PostIncLoops - The set of loops for which Expr has been adjusted to
|
||||
/// use post-inc mode. This corresponds with SCEVExpander's post-inc concept.
|
||||
PostIncLoopSet PostIncLoops;
|
||||
|
||||
/// Deleted - Implementation of CallbackVH virtual function to
|
||||
/// receive notification when the User is deleted.
|
||||
virtual void deleted();
|
||||
};
|
||||
|
||||
template<> struct ilist_traits<IVStrideUse>
|
||||
: public ilist_default_traits<IVStrideUse> {
|
||||
// createSentinel is used to get hold of a node that marks the end of
|
||||
// the list...
|
||||
// The sentinel is relative to this instance, so we use a non-static
|
||||
// method.
|
||||
IVStrideUse *createSentinel() const {
|
||||
// since i(p)lists always publicly derive from the corresponding
|
||||
// traits, placing a data member in this class will augment i(p)list.
|
||||
// But since the NodeTy is expected to publicly derive from
|
||||
// ilist_node<NodeTy>, there is a legal viable downcast from it
|
||||
// to NodeTy. We use this trick to superpose i(p)list with a "ghostly"
|
||||
// NodeTy, which becomes the sentinel. Dereferencing the sentinel is
|
||||
// forbidden (save the ilist_node<NodeTy>) so no one will ever notice
|
||||
// the superposition.
|
||||
return static_cast<IVStrideUse*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(IVStrideUse*) {}
|
||||
|
||||
IVStrideUse *provideInitialHead() const { return createSentinel(); }
|
||||
IVStrideUse *ensureHead(IVStrideUse*) const { return createSentinel(); }
|
||||
static void noteHead(IVStrideUse*, IVStrideUse*) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<IVStrideUse> Sentinel;
|
||||
};
|
||||
|
||||
class IVUsers : public LoopPass {
|
||||
friend class IVStrideUse;
|
||||
Loop *L;
|
||||
LoopInfo *LI;
|
||||
DominatorTree *DT;
|
||||
ScalarEvolution *SE;
|
||||
DataLayout *TD;
|
||||
SmallPtrSet<Instruction*,16> Processed;
|
||||
|
||||
/// IVUses - A list of all tracked IV uses of induction variable expressions
|
||||
/// we are interested in.
|
||||
ilist<IVStrideUse> IVUses;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
|
||||
|
||||
virtual void releaseMemory();
|
||||
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
IVUsers();
|
||||
|
||||
Loop *getLoop() const { return L; }
|
||||
|
||||
/// AddUsersIfInteresting - Inspect the specified Instruction. If it is a
|
||||
/// reducible SCEV, recursively add its users to the IVUsesByStride set and
|
||||
/// return true. Otherwise, return false.
|
||||
bool AddUsersIfInteresting(Instruction *I);
|
||||
|
||||
IVStrideUse &AddUser(Instruction *User, Value *Operand);
|
||||
|
||||
/// getReplacementExpr - Return a SCEV expression which computes the
|
||||
/// value of the OperandValToReplace of the given IVStrideUse.
|
||||
const SCEV *getReplacementExpr(const IVStrideUse &IU) const;
|
||||
|
||||
/// getExpr - Return the expression for the use.
|
||||
const SCEV *getExpr(const IVStrideUse &IU) const;
|
||||
|
||||
const SCEV *getStride(const IVStrideUse &IU, const Loop *L) const;
|
||||
|
||||
typedef ilist<IVStrideUse>::iterator iterator;
|
||||
typedef ilist<IVStrideUse>::const_iterator const_iterator;
|
||||
iterator begin() { return IVUses.begin(); }
|
||||
iterator end() { return IVUses.end(); }
|
||||
const_iterator begin() const { return IVUses.begin(); }
|
||||
const_iterator end() const { return IVUses.end(); }
|
||||
bool empty() const { return IVUses.empty(); }
|
||||
|
||||
bool isIVUserOrOperand(Instruction *Inst) const {
|
||||
return Processed.count(Inst);
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS, const Module* = 0) const;
|
||||
|
||||
/// dump - This method is used for debugging.
|
||||
void dump() const;
|
||||
protected:
|
||||
bool AddUsersImpl(Instruction *I, SmallPtrSet<Loop*,16> &SimpleLoopNests);
|
||||
};
|
||||
|
||||
Pass *createIVUsersPass();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
143
thirdparty/clang/include/llvm/Analysis/InlineCost.h
vendored
Normal file
143
thirdparty/clang/include/llvm/Analysis/InlineCost.h
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
//===- InlineCost.h - Cost analysis for inliner -----------------*- 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 heuristics for inlining decisions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INLINECOST_H
|
||||
#define LLVM_ANALYSIS_INLINECOST_H
|
||||
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
|
||||
namespace llvm {
|
||||
class CallSite;
|
||||
class DataLayout;
|
||||
class Function;
|
||||
class TargetTransformInfo;
|
||||
|
||||
namespace InlineConstants {
|
||||
// Various magic constants used to adjust heuristics.
|
||||
const int InstrCost = 5;
|
||||
const int IndirectCallThreshold = 100;
|
||||
const int CallPenalty = 25;
|
||||
const int LastCallToStaticBonus = -15000;
|
||||
const int ColdccPenalty = 2000;
|
||||
const int NoreturnPenalty = 10000;
|
||||
/// Do not inline functions which allocate this many bytes on the stack
|
||||
/// when the caller is recursive.
|
||||
const unsigned TotalAllocaSizeRecursiveCaller = 1024;
|
||||
}
|
||||
|
||||
/// \brief Represents the cost of inlining a function.
|
||||
///
|
||||
/// This supports special values for functions which should "always" or
|
||||
/// "never" be inlined. Otherwise, the cost represents a unitless amount;
|
||||
/// smaller values increase the likelihood of the function being inlined.
|
||||
///
|
||||
/// Objects of this type also provide the adjusted threshold for inlining
|
||||
/// based on the information available for a particular callsite. They can be
|
||||
/// directly tested to determine if inlining should occur given the cost and
|
||||
/// threshold for this cost metric.
|
||||
class InlineCost {
|
||||
enum SentinelValues {
|
||||
AlwaysInlineCost = INT_MIN,
|
||||
NeverInlineCost = INT_MAX
|
||||
};
|
||||
|
||||
/// \brief The estimated cost of inlining this callsite.
|
||||
const int Cost;
|
||||
|
||||
/// \brief The adjusted threshold against which this cost was computed.
|
||||
const int Threshold;
|
||||
|
||||
// Trivial constructor, interesting logic in the factory functions below.
|
||||
InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {}
|
||||
|
||||
public:
|
||||
static InlineCost get(int Cost, int Threshold) {
|
||||
assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
|
||||
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
|
||||
return InlineCost(Cost, Threshold);
|
||||
}
|
||||
static InlineCost getAlways() {
|
||||
return InlineCost(AlwaysInlineCost, 0);
|
||||
}
|
||||
static InlineCost getNever() {
|
||||
return InlineCost(NeverInlineCost, 0);
|
||||
}
|
||||
|
||||
/// \brief Test whether the inline cost is low enough for inlining.
|
||||
operator bool() const {
|
||||
return Cost < Threshold;
|
||||
}
|
||||
|
||||
bool isAlways() const { return Cost == AlwaysInlineCost; }
|
||||
bool isNever() const { return Cost == NeverInlineCost; }
|
||||
bool isVariable() const { return !isAlways() && !isNever(); }
|
||||
|
||||
/// \brief Get the inline cost estimate.
|
||||
/// It is an error to call this on an "always" or "never" InlineCost.
|
||||
int getCost() const {
|
||||
assert(isVariable() && "Invalid access of InlineCost");
|
||||
return Cost;
|
||||
}
|
||||
|
||||
/// \brief Get the cost delta from the threshold for inlining.
|
||||
/// Only valid if the cost is of the variable kind. Returns a negative
|
||||
/// value if the cost is too high to inline.
|
||||
int getCostDelta() const { return Threshold - getCost(); }
|
||||
};
|
||||
|
||||
/// \brief Cost analyzer used by inliner.
|
||||
class InlineCostAnalysis : public CallGraphSCCPass {
|
||||
const DataLayout *TD;
|
||||
const TargetTransformInfo *TTI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
InlineCostAnalysis();
|
||||
~InlineCostAnalysis();
|
||||
|
||||
// Pass interface implementation.
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
bool runOnSCC(CallGraphSCC &SCC);
|
||||
|
||||
/// \brief Get an InlineCost object representing the cost of inlining this
|
||||
/// callsite.
|
||||
///
|
||||
/// Note that threshold is passed into this function. Only costs below the
|
||||
/// threshold are computed with any accuracy. The threshold can be used to
|
||||
/// bound the computation necessary to determine whether the cost is
|
||||
/// sufficiently low to warrant inlining.
|
||||
///
|
||||
/// Also note that calling this function *dynamically* computes the cost of
|
||||
/// inlining the callsite. It is an expensive, heavyweight call.
|
||||
InlineCost getInlineCost(CallSite CS, int Threshold);
|
||||
|
||||
/// \brief Get an InlineCost with the callee explicitly specified.
|
||||
/// This allows you to calculate the cost of inlining a function via a
|
||||
/// pointer. This behaves exactly as the version with no explicit callee
|
||||
/// parameter in all other respects.
|
||||
//
|
||||
// Note: This is used by out-of-tree passes, please do not remove without
|
||||
// adding a replacement API.
|
||||
InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold);
|
||||
|
||||
/// \brief Minimal filter to detect invalid constructs for inlining.
|
||||
bool isInlineViable(Function &Callee);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
274
thirdparty/clang/include/llvm/Analysis/InstructionSimplify.h
vendored
Normal file
274
thirdparty/clang/include/llvm/Analysis/InstructionSimplify.h
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares routines for folding instructions into simpler forms
|
||||
// that do not require creating new instructions. This does constant folding
|
||||
// ("add i32 1, 1" -> "2") but can also handle non-constant operands, either
|
||||
// returning a constant ("and i32 %x, 0" -> "0") or an already existing value
|
||||
// ("and i32 %x, %x" -> "%x"). If the simplification is also an instruction
|
||||
// then it dominates the original instruction.
|
||||
//
|
||||
// These routines implicitly resolve undef uses. The easiest way to be safe when
|
||||
// using these routines to obtain simplified values for existing instructions is
|
||||
// to always replace all uses of the instructions with the resulting simplified
|
||||
// values. This will prevent other code from seeing the same undef uses and
|
||||
// resolving them to different values.
|
||||
//
|
||||
// These routines are designed to tolerate moderately incomplete IR, such as
|
||||
// instructions that are not connected to basic blocks yet. However, they do
|
||||
// require that all the IR that they encounter be valid. In particular, they
|
||||
// require that all non-constant values be defined in the same function, and the
|
||||
// same call context of that function (and not split between caller and callee
|
||||
// contexts of a directly recursive call, for example).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
|
||||
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
|
||||
|
||||
#include "llvm/IR/User.h"
|
||||
|
||||
namespace llvm {
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class DataLayout;
|
||||
class FastMathFlags;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
/// SimplifyAddInst - Given operands for an Add, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySubInst - Given operands for a Sub, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FAdd, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FSub, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// Given operands for an FMul, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
Value *SimplifyFMulInst(Value *LHS, Value *RHS,
|
||||
FastMathFlags FMF,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyMulInst - Given operands for a Mul, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySDivInst - Given operands for an SDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySRemInst - Given operands for an SRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyURemInst - Given operands for a URem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFRemInst - Given operands for an FRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyShlInst - Given operands for a Shl, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyLShrInst - Given operands for a LShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAShrInst - Given operands for a AShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyOrInst - Given operands for an Or, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyXorInst - Given operands for a Xor, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
|
||||
/// can fold the result. If not, this returns null.
|
||||
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
|
||||
ArrayRef<unsigned> Idxs,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
//=== Helper functions for higher up the class hierarchy.
|
||||
|
||||
|
||||
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Given a function and iterators over arguments, see if we can fold
|
||||
/// the result.
|
||||
///
|
||||
/// If this call could not be simplified returns null.
|
||||
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
|
||||
User::op_iterator ArgEnd, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Given a function and set of arguments, see if we can fold the
|
||||
/// result.
|
||||
///
|
||||
/// If this call could not be simplified returns null.
|
||||
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInstruction - See if we can compute a simplified version of this
|
||||
/// instruction. If not, this returns null.
|
||||
Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
|
||||
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
|
||||
/// recursively.
|
||||
///
|
||||
/// This first performs a normal RAUW of I with SimpleV. It then recursively
|
||||
/// attempts to simplify those users updated by the operation. The 'I'
|
||||
/// instruction must not be equal to the simplified value 'SimpleV'.
|
||||
///
|
||||
/// The function returns true if any simplifications were performed.
|
||||
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Recursively attempt to simplify an instruction.
|
||||
///
|
||||
/// This routine uses SimplifyInstruction to simplify 'I', and if successful
|
||||
/// replaces uses of 'I' with the simplified value. It then recurses on each
|
||||
/// of the users impacted. It returns true if any simplifications were
|
||||
/// performed.
|
||||
bool recursivelySimplifyInstruction(Instruction *I,
|
||||
const DataLayout *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
153
thirdparty/clang/include/llvm/Analysis/Interval.h
vendored
Normal file
153
thirdparty/clang/include/llvm/Analysis/Interval.h
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the Interval class, which
|
||||
// represents a set of CFG nodes and is a portion of an interval partition.
|
||||
//
|
||||
// Intervals have some interesting and useful properties, including the
|
||||
// following:
|
||||
// 1. The header node of an interval dominates all of the elements of the
|
||||
// interval
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVAL_H
|
||||
#define LLVM_ANALYSIS_INTERVAL_H
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class raw_ostream;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// Interval Class - An Interval is a set of nodes defined such that every node
|
||||
/// in the interval has all of its predecessors in the interval (except for the
|
||||
/// header)
|
||||
///
|
||||
class Interval {
|
||||
/// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this
|
||||
/// interval. Also, any loops in this interval must go through the HeaderNode.
|
||||
///
|
||||
BasicBlock *HeaderNode;
|
||||
public:
|
||||
typedef std::vector<BasicBlock*>::iterator succ_iterator;
|
||||
typedef std::vector<BasicBlock*>::iterator pred_iterator;
|
||||
typedef std::vector<BasicBlock*>::iterator node_iterator;
|
||||
|
||||
inline Interval(BasicBlock *Header) : HeaderNode(Header) {
|
||||
Nodes.push_back(Header);
|
||||
}
|
||||
|
||||
inline Interval(const Interval &I) // copy ctor
|
||||
: HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {}
|
||||
|
||||
inline BasicBlock *getHeaderNode() const { return HeaderNode; }
|
||||
|
||||
/// Nodes - The basic blocks in this interval.
|
||||
///
|
||||
std::vector<BasicBlock*> Nodes;
|
||||
|
||||
/// Successors - List of BasicBlocks that are reachable directly from nodes in
|
||||
/// this interval, but are not in the interval themselves.
|
||||
/// These nodes necessarily must be header nodes for other intervals.
|
||||
///
|
||||
std::vector<BasicBlock*> Successors;
|
||||
|
||||
/// Predecessors - List of BasicBlocks that have this Interval's header block
|
||||
/// as one of their successors.
|
||||
///
|
||||
std::vector<BasicBlock*> Predecessors;
|
||||
|
||||
/// contains - Find out if a basic block is in this interval
|
||||
inline bool contains(BasicBlock *BB) const {
|
||||
for (unsigned i = 0; i < Nodes.size(); ++i)
|
||||
if (Nodes[i] == BB) return true;
|
||||
return false;
|
||||
// I don't want the dependency on <algorithm>
|
||||
//return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end();
|
||||
}
|
||||
|
||||
/// isSuccessor - find out if a basic block is a successor of this Interval
|
||||
inline bool isSuccessor(BasicBlock *BB) const {
|
||||
for (unsigned i = 0; i < Successors.size(); ++i)
|
||||
if (Successors[i] == BB) return true;
|
||||
return false;
|
||||
// I don't want the dependency on <algorithm>
|
||||
//return find(Successors.begin(), Successors.end(), BB) != Successors.end();
|
||||
}
|
||||
|
||||
/// Equality operator. It is only valid to compare two intervals from the
|
||||
/// same partition, because of this, all we have to check is the header node
|
||||
/// for equality.
|
||||
///
|
||||
inline bool operator==(const Interval &I) const {
|
||||
return HeaderNode == I.HeaderNode;
|
||||
}
|
||||
|
||||
/// isLoop - Find out if there is a back edge in this interval...
|
||||
bool isLoop() const;
|
||||
|
||||
/// print - Show contents in human readable format...
|
||||
void print(raw_ostream &O) const;
|
||||
};
|
||||
|
||||
/// succ_begin/succ_end - define methods so that Intervals may be used
|
||||
/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator.
|
||||
///
|
||||
inline Interval::succ_iterator succ_begin(Interval *I) {
|
||||
return I->Successors.begin();
|
||||
}
|
||||
inline Interval::succ_iterator succ_end(Interval *I) {
|
||||
return I->Successors.end();
|
||||
}
|
||||
|
||||
/// pred_begin/pred_end - define methods so that Intervals may be used
|
||||
/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator.
|
||||
///
|
||||
inline Interval::pred_iterator pred_begin(Interval *I) {
|
||||
return I->Predecessors.begin();
|
||||
}
|
||||
inline Interval::pred_iterator pred_end(Interval *I) {
|
||||
return I->Predecessors.end();
|
||||
}
|
||||
|
||||
template <> struct GraphTraits<Interval*> {
|
||||
typedef Interval NodeType;
|
||||
typedef Interval::succ_iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(Interval *I) { return I; }
|
||||
|
||||
/// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return succ_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return succ_end(N);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse<Interval*> > {
|
||||
typedef Interval NodeType;
|
||||
typedef Interval::pred_iterator ChildIteratorType;
|
||||
static NodeType *getEntryNode(Inverse<Interval *> G) { return G.Graph; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return pred_begin(N);
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return pred_end(N);
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
259
thirdparty/clang/include/llvm/Analysis/IntervalIterator.h
vendored
Normal file
259
thirdparty/clang/include/llvm/Analysis/IntervalIterator.h
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
//===- IntervalIterator.h - Interval Iterator Declaration -------*- 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 an iterator that enumerates the intervals in a control flow
|
||||
// graph of some sort. This iterator is parametric, allowing iterator over the
|
||||
// following types of graphs:
|
||||
//
|
||||
// 1. A Function* object, composed of BasicBlock nodes.
|
||||
// 2. An IntervalPartition& object, composed of Interval nodes.
|
||||
//
|
||||
// This iterator is defined to walk the control flow graph, returning intervals
|
||||
// in depth first order. These intervals are completely filled in except for
|
||||
// the predecessor fields (the successor information is filled in however).
|
||||
//
|
||||
// By default, the intervals created by this iterator are deleted after they
|
||||
// are no longer any use to the iterator. This behavior can be changed by
|
||||
// passing a false value into the intervals_begin() function. This causes the
|
||||
// IOwnMem member to be set, and the intervals to not be deleted.
|
||||
//
|
||||
// It is only safe to use this if all of the intervals are deleted by the caller
|
||||
// and all of the intervals are processed. However, the user of the iterator is
|
||||
// not allowed to modify or delete the intervals until after the iterator has
|
||||
// been used completely. The IntervalPartition class uses this functionality.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVALITERATOR_H
|
||||
#define LLVM_ANALYSIS_INTERVALITERATOR_H
|
||||
|
||||
#include "llvm/Analysis/IntervalPartition.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// getNodeHeader - Given a source graph node and the source graph, return the
|
||||
// BasicBlock that is the header node. This is the opposite of
|
||||
// getSourceGraphNode.
|
||||
//
|
||||
inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; }
|
||||
inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); }
|
||||
|
||||
// getSourceGraphNode - Given a BasicBlock and the source graph, return the
|
||||
// source graph node that corresponds to the BasicBlock. This is the opposite
|
||||
// of getNodeHeader.
|
||||
//
|
||||
inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) {
|
||||
return BB;
|
||||
}
|
||||
inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) {
|
||||
return IP->getBlockInterval(BB);
|
||||
}
|
||||
|
||||
// addNodeToInterval - This method exists to assist the generic ProcessNode
|
||||
// with the task of adding a node to the new interval, depending on the
|
||||
// type of the source node. In the case of a CFG source graph (BasicBlock
|
||||
// case), the BasicBlock itself is added to the interval.
|
||||
//
|
||||
inline void addNodeToInterval(Interval *Int, BasicBlock *BB) {
|
||||
Int->Nodes.push_back(BB);
|
||||
}
|
||||
|
||||
// addNodeToInterval - This method exists to assist the generic ProcessNode
|
||||
// with the task of adding a node to the new interval, depending on the
|
||||
// type of the source node. In the case of a CFG source graph (BasicBlock
|
||||
// case), the BasicBlock itself is added to the interval. In the case of
|
||||
// an IntervalPartition source graph (Interval case), all of the member
|
||||
// BasicBlocks are added to the interval.
|
||||
//
|
||||
inline void addNodeToInterval(Interval *Int, Interval *I) {
|
||||
// Add all of the nodes in I as new nodes in Int.
|
||||
copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>,
|
||||
class IGT = GraphTraits<Inverse<NodeTy*> > >
|
||||
class IntervalIterator {
|
||||
std::vector<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
|
||||
std::set<BasicBlock*> Visited;
|
||||
OrigContainer_t *OrigContainer;
|
||||
bool IOwnMem; // If True, delete intervals when done with them
|
||||
// See file header for conditions of use
|
||||
public:
|
||||
typedef IntervalIterator<NodeTy, OrigContainer_t> _Self;
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
|
||||
IntervalIterator() {} // End iterator, empty stack
|
||||
IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = M;
|
||||
if (!ProcessInterval(&M->front())) {
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = &IP;
|
||||
if (!ProcessInterval(IP.getRootInterval())) {
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
inline ~IntervalIterator() {
|
||||
if (IOwnMem)
|
||||
while (!IntStack.empty()) {
|
||||
delete operator*();
|
||||
IntStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline const Interval *operator*() const { return IntStack.back().first; }
|
||||
inline Interval *operator*() { return IntStack.back().first; }
|
||||
inline const Interval *operator->() const { return operator*(); }
|
||||
inline Interval *operator->() { return operator*(); }
|
||||
|
||||
_Self& operator++() { // Preincrement
|
||||
assert(!IntStack.empty() && "Attempting to use interval iterator at end!");
|
||||
do {
|
||||
// All of the intervals on the stack have been visited. Try visiting
|
||||
// their successors now.
|
||||
Interval::succ_iterator &SuccIt = IntStack.back().second,
|
||||
EndIt = succ_end(IntStack.back().first);
|
||||
while (SuccIt != EndIt) { // Loop over all interval succs
|
||||
bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt));
|
||||
++SuccIt; // Increment iterator
|
||||
if (Done) return *this; // Found a new interval! Use it!
|
||||
}
|
||||
|
||||
// Free interval memory... if necessary
|
||||
if (IOwnMem) delete IntStack.back().first;
|
||||
|
||||
// We ran out of successors for this interval... pop off the stack
|
||||
IntStack.pop_back();
|
||||
} while (!IntStack.empty());
|
||||
|
||||
return *this;
|
||||
}
|
||||
inline _Self operator++(int) { // Postincrement
|
||||
_Self tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
// ProcessInterval - This method is used during the construction of the
|
||||
// interval graph. It walks through the source graph, recursively creating
|
||||
// an interval per invocation until the entire graph is covered. This uses
|
||||
// the ProcessNode method to add all of the nodes to the interval.
|
||||
//
|
||||
// This method is templated because it may operate on two different source
|
||||
// graphs: a basic block graph, or a preexisting interval graph.
|
||||
//
|
||||
bool ProcessInterval(NodeTy *Node) {
|
||||
BasicBlock *Header = getNodeHeader(Node);
|
||||
if (Visited.count(Header)) return false;
|
||||
|
||||
Interval *Int = new Interval(Header);
|
||||
Visited.insert(Header); // The header has now been visited!
|
||||
|
||||
// Check all of our successors to see if they are in the interval...
|
||||
for (typename GT::ChildIteratorType I = GT::child_begin(Node),
|
||||
E = GT::child_end(Node); I != E; ++I)
|
||||
ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
|
||||
|
||||
IntStack.push_back(std::make_pair(Int, succ_begin(Int)));
|
||||
return true;
|
||||
}
|
||||
|
||||
// ProcessNode - This method is called by ProcessInterval to add nodes to the
|
||||
// interval being constructed, and it is also called recursively as it walks
|
||||
// the source graph. A node is added to the current interval only if all of
|
||||
// its predecessors are already in the graph. This also takes care of keeping
|
||||
// the successor set of an interval up to date.
|
||||
//
|
||||
// This method is templated because it may operate on two different source
|
||||
// graphs: a basic block graph, or a preexisting interval graph.
|
||||
//
|
||||
void ProcessNode(Interval *Int, NodeTy *Node) {
|
||||
assert(Int && "Null interval == bad!");
|
||||
assert(Node && "Null Node == bad!");
|
||||
|
||||
BasicBlock *NodeHeader = getNodeHeader(Node);
|
||||
|
||||
if (Visited.count(NodeHeader)) { // Node already been visited?
|
||||
if (Int->contains(NodeHeader)) { // Already in this interval...
|
||||
return;
|
||||
} else { // In other interval, add as successor
|
||||
if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
|
||||
Int->Successors.push_back(NodeHeader);
|
||||
}
|
||||
} else { // Otherwise, not in interval yet
|
||||
for (typename IGT::ChildIteratorType I = IGT::child_begin(Node),
|
||||
E = IGT::child_end(Node); I != E; ++I) {
|
||||
if (!Int->contains(*I)) { // If pred not in interval, we can't be
|
||||
if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set
|
||||
Int->Successors.push_back(NodeHeader);
|
||||
return; // See you later
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then all of the predecessors of BB are in the interval
|
||||
// already. In this case, we must add BB to the interval!
|
||||
addNodeToInterval(Int, Node);
|
||||
Visited.insert(NodeHeader); // The node has now been visited!
|
||||
|
||||
if (Int->isSuccessor(NodeHeader)) {
|
||||
// If we were in the successor list from before... remove from succ list
|
||||
Int->Successors.erase(std::remove(Int->Successors.begin(),
|
||||
Int->Successors.end(), NodeHeader),
|
||||
Int->Successors.end());
|
||||
}
|
||||
|
||||
// Now that we have discovered that Node is in the interval, perhaps some
|
||||
// of its successors are as well?
|
||||
for (typename GT::ChildIteratorType It = GT::child_begin(Node),
|
||||
End = GT::child_end(Node); It != End; ++It)
|
||||
ProcessNode(Int, getSourceGraphNode(OrigContainer, *It));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef IntervalIterator<BasicBlock, Function> function_interval_iterator;
|
||||
typedef IntervalIterator<Interval, IntervalPartition>
|
||||
interval_part_interval_iterator;
|
||||
|
||||
|
||||
inline function_interval_iterator intervals_begin(Function *F,
|
||||
bool DeleteInts = true) {
|
||||
return function_interval_iterator(F, DeleteInts);
|
||||
}
|
||||
inline function_interval_iterator intervals_end(Function *) {
|
||||
return function_interval_iterator();
|
||||
}
|
||||
|
||||
inline interval_part_interval_iterator
|
||||
intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) {
|
||||
return interval_part_interval_iterator(IP, DeleteIntervals);
|
||||
}
|
||||
|
||||
inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) {
|
||||
return interval_part_interval_iterator();
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
111
thirdparty/clang/include/llvm/Analysis/IntervalPartition.h
vendored
Normal file
111
thirdparty/clang/include/llvm/Analysis/IntervalPartition.h
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declaration of the IntervalPartition class, which
|
||||
// calculates and represents the interval partition of a function, or a
|
||||
// preexisting interval partition.
|
||||
//
|
||||
// In this way, the interval partition may be used to reduce a flow graph down
|
||||
// to its degenerate single node interval partition (unless it is irreducible).
|
||||
//
|
||||
// TODO: The IntervalPartition class should take a bool parameter that tells
|
||||
// whether it should add the "tails" of an interval to an interval itself or if
|
||||
// they should be represented as distinct intervals.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_INTERVALPARTITION_H
|
||||
#define LLVM_ANALYSIS_INTERVALPARTITION_H
|
||||
|
||||
#include "llvm/Analysis/Interval.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// IntervalPartition - This class builds and holds an "interval partition" for
|
||||
// a function. This partition divides the control flow graph into a set of
|
||||
// maximal intervals, as defined with the properties above. Intuitively, an
|
||||
// interval is a (possibly nonexistent) loop with a "tail" of non looping
|
||||
// nodes following it.
|
||||
//
|
||||
class IntervalPartition : public FunctionPass {
|
||||
typedef std::map<BasicBlock*, Interval*> IntervalMapTy;
|
||||
IntervalMapTy IntervalMap;
|
||||
|
||||
typedef std::vector<Interval*> IntervalListTy;
|
||||
Interval *RootInterval;
|
||||
std::vector<Interval*> Intervals;
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
IntervalPartition() : FunctionPass(ID), RootInterval(0) {
|
||||
initializeIntervalPartitionPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
// run - Calculate the interval partition for this function
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
// IntervalPartition ctor - Build a reduced interval partition from an
|
||||
// existing interval graph. This takes an additional boolean parameter to
|
||||
// distinguish it from a copy constructor. Always pass in false for now.
|
||||
//
|
||||
IntervalPartition(IntervalPartition &I, bool);
|
||||
|
||||
// print - Show contents in human readable format...
|
||||
virtual void print(raw_ostream &O, const Module* = 0) const;
|
||||
|
||||
// getRootInterval() - Return the root interval that contains the starting
|
||||
// block of the function.
|
||||
inline Interval *getRootInterval() { return RootInterval; }
|
||||
|
||||
// isDegeneratePartition() - Returns true if the interval partition contains
|
||||
// a single interval, and thus cannot be simplified anymore.
|
||||
bool isDegeneratePartition() { return Intervals.size() == 1; }
|
||||
|
||||
// TODO: isIrreducible - look for triangle graph.
|
||||
|
||||
// getBlockInterval - Return the interval that a basic block exists in.
|
||||
inline Interval *getBlockInterval(BasicBlock *BB) {
|
||||
IntervalMapTy::iterator I = IntervalMap.find(BB);
|
||||
return I != IntervalMap.end() ? I->second : 0;
|
||||
}
|
||||
|
||||
// getAnalysisUsage - Implement the Pass API
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
// Interface to Intervals vector...
|
||||
const std::vector<Interval*> &getIntervals() const { return Intervals; }
|
||||
|
||||
// releaseMemory - Reset state back to before function was analyzed
|
||||
void releaseMemory();
|
||||
|
||||
private:
|
||||
// addIntervalToPartition - Add an interval to the internal list of intervals,
|
||||
// and then add mappings from all of the basic blocks in the interval to the
|
||||
// interval itself (in the IntervalMap).
|
||||
//
|
||||
void addIntervalToPartition(Interval *I);
|
||||
|
||||
// updatePredecessors - Interval generation only sets the successor fields of
|
||||
// the interval data structures. After interval generation is complete,
|
||||
// run through all of the intervals and propagate successor info as
|
||||
// predecessor info.
|
||||
//
|
||||
void updatePredecessors(Interval *Int);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
81
thirdparty/clang/include/llvm/Analysis/LazyValueInfo.h
vendored
Normal file
81
thirdparty/clang/include/llvm/Analysis/LazyValueInfo.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//===- LazyValueInfo.h - Value constraint analysis --------------*- 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 interface for lazy computation of value constraint
|
||||
// information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LAZYVALUEINFO_H
|
||||
#define LLVM_ANALYSIS_LAZYVALUEINFO_H
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class Constant;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Value;
|
||||
|
||||
/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
|
||||
/// information.
|
||||
class LazyValueInfo : public FunctionPass {
|
||||
class DataLayout *TD;
|
||||
class TargetLibraryInfo *TLI;
|
||||
void *PImpl;
|
||||
LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
static char ID;
|
||||
LazyValueInfo() : FunctionPass(ID), PImpl(0) {
|
||||
initializeLazyValueInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); }
|
||||
|
||||
/// Tristate - This is used to return true/false/dunno results.
|
||||
enum Tristate {
|
||||
Unknown = -1, False = 0, True = 1
|
||||
};
|
||||
|
||||
|
||||
// Public query interface.
|
||||
|
||||
/// getPredicateOnEdge - Determine whether the specified value comparison
|
||||
/// with a constant is known to be true or false on the specified CFG edge.
|
||||
/// Pred is a CmpInst predicate.
|
||||
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
|
||||
BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
|
||||
|
||||
/// getConstant - Determine whether the specified value is known to be a
|
||||
/// constant at the end of the specified block. Return null if not.
|
||||
Constant *getConstant(Value *V, BasicBlock *BB);
|
||||
|
||||
/// getConstantOnEdge - Determine whether the specified value is known to be a
|
||||
/// constant on the specified edge. Return null if not.
|
||||
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB);
|
||||
|
||||
/// threadEdge - Inform the analysis cache that we have threaded an edge from
|
||||
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
|
||||
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
|
||||
|
||||
/// eraseBlock - Inform the analysis cache that we have erased a block.
|
||||
void eraseBlock(BasicBlock *BB);
|
||||
|
||||
// Implementation boilerplate.
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
virtual bool runOnFunction(Function &F);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
73
thirdparty/clang/include/llvm/Analysis/LibCallAliasAnalysis.h
vendored
Normal file
73
thirdparty/clang/include/llvm/Analysis/LibCallAliasAnalysis.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
//===- LibCallAliasAnalysis.h - Implement AliasAnalysis for libcalls ------===//
|
||||
//
|
||||
// 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 LibCallAliasAnalysis class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
|
||||
#define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class LibCallInfo;
|
||||
struct LibCallFunctionInfo;
|
||||
|
||||
/// LibCallAliasAnalysis - Alias analysis driven from LibCallInfo.
|
||||
struct LibCallAliasAnalysis : public FunctionPass, public AliasAnalysis {
|
||||
static char ID; // Class identification
|
||||
|
||||
LibCallInfo *LCI;
|
||||
|
||||
explicit LibCallAliasAnalysis(LibCallInfo *LC = 0)
|
||||
: FunctionPass(ID), LCI(LC) {
|
||||
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit LibCallAliasAnalysis(char &ID, LibCallInfo *LC)
|
||||
: FunctionPass(ID), LCI(LC) {
|
||||
initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
~LibCallAliasAnalysis();
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
// TODO: Could compare two direct calls against each other if we cared to.
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
InitializeAliasAnalysis(this); // set up super class
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
virtual void *getAdjustedAnalysisPointer(const void *PI) {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis*)this;
|
||||
return this;
|
||||
}
|
||||
|
||||
private:
|
||||
ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
};
|
||||
} // End of llvm namespace
|
||||
|
||||
#endif
|
||||
167
thirdparty/clang/include/llvm/Analysis/LibCallSemantics.h
vendored
Normal file
167
thirdparty/clang/include/llvm/Analysis/LibCallSemantics.h
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
//===- LibCallSemantics.h - Describe library semantics --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines interfaces that can be used to describe language specific
|
||||
// runtime library interfaces (e.g. libc, libm, etc) to LLVM optimizers.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LIBCALLSEMANTICS_H
|
||||
#define LLVM_ANALYSIS_LIBCALLSEMANTICS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// LibCallLocationInfo - This struct describes a set of memory locations that
|
||||
/// are accessed by libcalls. Identification of a location is doing with a
|
||||
/// simple callback function.
|
||||
///
|
||||
/// For example, the LibCallInfo may be set up to model the behavior of
|
||||
/// standard libm functions. The location that they may be interested in is
|
||||
/// an abstract location that represents errno for the current target. In
|
||||
/// this case, a location for errno is anything such that the predicate
|
||||
/// returns true. On Mac OS/X, this predicate would return true if the
|
||||
/// pointer is the result of a call to "__error()".
|
||||
///
|
||||
/// Locations can also be defined in a constant-sensitive way. For example,
|
||||
/// it is possible to define a location that returns true iff it is passed
|
||||
/// into the call as a specific argument. This is useful for modeling things
|
||||
/// like "printf", which can store to memory, but only through pointers passed
|
||||
/// with a '%n' constraint.
|
||||
///
|
||||
struct LibCallLocationInfo {
|
||||
// TODO: Flags: isContextSensitive etc.
|
||||
|
||||
/// isLocation - Return a LocResult if the specified pointer refers to this
|
||||
/// location for the specified call site. This returns "Yes" if we can tell
|
||||
/// that the pointer *does definitely* refer to the location, "No" if we can
|
||||
/// tell that the location *definitely does not* refer to the location, and
|
||||
/// returns "Unknown" if we cannot tell for certain.
|
||||
enum LocResult {
|
||||
Yes, No, Unknown
|
||||
};
|
||||
LocResult (*isLocation)(ImmutableCallSite CS,
|
||||
const AliasAnalysis::Location &Loc);
|
||||
};
|
||||
|
||||
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
|
||||
/// records the behavior of one libcall that is known by the optimizer. This
|
||||
/// captures things like the side effects of the call. Side effects are
|
||||
/// modeled both universally (in the readnone/readonly) sense, but also
|
||||
/// potentially against a set of abstract locations defined by the optimizer.
|
||||
/// This allows an optimizer to define that some libcall (e.g. sqrt) is
|
||||
/// side-effect free except that it might modify errno (thus, the call is
|
||||
/// *not* universally readonly). Or it might say that the side effects
|
||||
/// are unknown other than to say that errno is not modified.
|
||||
///
|
||||
struct LibCallFunctionInfo {
|
||||
/// Name - This is the name of the libcall this describes.
|
||||
const char *Name;
|
||||
|
||||
/// TODO: Constant folding function: Constant* vector -> Constant*.
|
||||
|
||||
/// UniversalBehavior - This captures the absolute mod/ref behavior without
|
||||
/// any specific context knowledge. For example, if the function is known
|
||||
/// to be readonly, this would be set to 'ref'. If known to be readnone,
|
||||
/// this is set to NoModRef.
|
||||
AliasAnalysis::ModRefResult UniversalBehavior;
|
||||
|
||||
/// LocationMRInfo - This pair captures info about whether a specific
|
||||
/// location is modified or referenced by a libcall.
|
||||
struct LocationMRInfo {
|
||||
/// LocationID - ID # of the accessed location or ~0U for array end.
|
||||
unsigned LocationID;
|
||||
/// MRInfo - Mod/Ref info for this location.
|
||||
AliasAnalysis::ModRefResult MRInfo;
|
||||
};
|
||||
|
||||
/// DetailsType - Indicate the sense of the LocationDetails array. This
|
||||
/// controls how the LocationDetails array is interpreted.
|
||||
enum {
|
||||
/// DoesOnly - If DetailsType is set to DoesOnly, then we know that the
|
||||
/// *only* mod/ref behavior of this function is captured by the
|
||||
/// LocationDetails array. If we are trying to say that 'sqrt' can only
|
||||
/// modify errno, we'd have the {errnoloc,mod} in the LocationDetails
|
||||
/// array and have DetailsType set to DoesOnly.
|
||||
DoesOnly,
|
||||
|
||||
/// DoesNot - If DetailsType is set to DoesNot, then the sense of the
|
||||
/// LocationDetails array is completely inverted. This means that we *do
|
||||
/// not* know everything about the side effects of this libcall, but we do
|
||||
/// know things that the libcall cannot do. This is useful for complex
|
||||
/// functions like 'ctime' which have crazy mod/ref behavior, but are
|
||||
/// known to never read or write errno. In this case, we'd have
|
||||
/// {errnoloc,modref} in the LocationDetails array and DetailsType would
|
||||
/// be set to DoesNot, indicating that ctime does not read or write the
|
||||
/// errno location.
|
||||
DoesNot
|
||||
} DetailsType;
|
||||
|
||||
/// LocationDetails - This is a pointer to an array of LocationMRInfo
|
||||
/// structs which indicates the behavior of the libcall w.r.t. specific
|
||||
/// locations. For example, if this libcall is known to only modify
|
||||
/// 'errno', it would have a LocationDetails array with the errno ID and
|
||||
/// 'mod' in it. See the DetailsType field for how this is interpreted.
|
||||
///
|
||||
/// In the "DoesOnly" case, this information is 'may' information for: there
|
||||
/// is no guarantee that the specified side effect actually does happen,
|
||||
/// just that it could. In the "DoesNot" case, this is 'must not' info.
|
||||
///
|
||||
/// If this pointer is null, no details are known.
|
||||
///
|
||||
const LocationMRInfo *LocationDetails;
|
||||
};
|
||||
|
||||
|
||||
/// LibCallInfo - Abstract interface to query about library call information.
|
||||
/// Instances of this class return known information about some set of
|
||||
/// libcalls.
|
||||
///
|
||||
class LibCallInfo {
|
||||
// Implementation details of this object, private.
|
||||
mutable void *Impl;
|
||||
mutable const LibCallLocationInfo *Locations;
|
||||
mutable unsigned NumLocations;
|
||||
public:
|
||||
LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {}
|
||||
virtual ~LibCallInfo();
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Accessor Methods: Efficient access to contained data.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// getLocationInfo - Return information about the specified LocationID.
|
||||
const LibCallLocationInfo &getLocationInfo(unsigned LocID) const;
|
||||
|
||||
|
||||
/// getFunctionInfo - Return the LibCallFunctionInfo object corresponding to
|
||||
/// the specified function if we have it. If not, return null.
|
||||
const LibCallFunctionInfo *getFunctionInfo(const Function *F) const;
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Implementation Methods: Subclasses should implement these.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
/// getLocationInfo - Return descriptors for the locations referenced by
|
||||
/// this set of libcalls.
|
||||
virtual unsigned getLocationInfo(const LibCallLocationInfo *&Array) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getFunctionInfoArray - Return an array of descriptors that describe the
|
||||
/// set of libcalls represented by this LibCallInfo object. This array is
|
||||
/// terminated by an entry with a NULL name.
|
||||
virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
49
thirdparty/clang/include/llvm/Analysis/Lint.h
vendored
Normal file
49
thirdparty/clang/include/llvm/Analysis/Lint.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
//===-- llvm/Analysis/Lint.h - LLVM IR Lint ---------------------*- 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 lint interfaces that can be used for some sanity checking
|
||||
// of input to the system, and for checking that transformations
|
||||
// haven't done something bad. In contrast to the Verifier, the Lint checker
|
||||
// checks for undefined behavior or constructions with likely unintended
|
||||
// behavior.
|
||||
//
|
||||
// To see what specifically is checked, look at Lint.cpp
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LINT_H
|
||||
#define LLVM_ANALYSIS_LINT_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class FunctionPass;
|
||||
class Module;
|
||||
class Function;
|
||||
|
||||
/// @brief Create a lint pass.
|
||||
///
|
||||
/// Check a module or function.
|
||||
FunctionPass *createLintPass();
|
||||
|
||||
/// @brief Check a module.
|
||||
///
|
||||
/// This should only be used for debugging, because it plays games with
|
||||
/// PassManagers and stuff.
|
||||
void lintModule(
|
||||
const Module &M ///< The module to be checked
|
||||
);
|
||||
|
||||
// lintFunction - Check a function.
|
||||
void lintFunction(
|
||||
const Function &F ///< The function to be checked
|
||||
);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
57
thirdparty/clang/include/llvm/Analysis/Loads.h
vendored
Normal file
57
thirdparty/clang/include/llvm/Analysis/Loads.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
//===- Loads.h - Local load analysis --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares simple local analyses for load instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOADS_H
|
||||
#define LLVM_ANALYSIS_LOADS_H
|
||||
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class DataLayout;
|
||||
class MDNode;
|
||||
|
||||
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
|
||||
/// from this value cannot trap. If it is not obviously safe to load from the
|
||||
/// specified pointer, we do a quick local scan of the basic block containing
|
||||
/// ScanFrom, to determine if the address is already accessed.
|
||||
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
|
||||
unsigned Align, const DataLayout *TD = 0);
|
||||
|
||||
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
|
||||
/// the instruction before ScanFrom) checking to see if we have the value at
|
||||
/// the memory address *Ptr locally available within a small number of
|
||||
/// instructions. If the value is available, return it.
|
||||
///
|
||||
/// If not, return the iterator for the last validated instruction that the
|
||||
/// value would be live through. If we scanned the entire block and didn't
|
||||
/// find something that invalidates *Ptr or provides it, ScanFrom would be
|
||||
/// left at begin() and this returns null. ScanFrom could also be left
|
||||
///
|
||||
/// MaxInstsToScan specifies the maximum instructions to scan in the block.
|
||||
/// If it is set to 0, it will scan the whole block. You can also optionally
|
||||
/// specify an alias analysis implementation, which makes this more precise.
|
||||
///
|
||||
/// If TBAATag is non-null and a load or store is found, the TBAA tag from the
|
||||
/// load or store is recorded there. If there is no TBAA tag or if no access
|
||||
/// is found, it is left unmodified.
|
||||
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
|
||||
BasicBlock::iterator &ScanFrom,
|
||||
unsigned MaxInstsToScan = 6,
|
||||
AliasAnalysis *AA = 0,
|
||||
MDNode **TBAATag = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
124
thirdparty/clang/include/llvm/Analysis/LoopDependenceAnalysis.h
vendored
Normal file
124
thirdparty/clang/include/llvm/Analysis/LoopDependenceAnalysis.h
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
//===- llvm/Analysis/LoopDependenceAnalysis.h --------------- -*- C++ -*---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// LoopDependenceAnalysis is an LLVM pass that analyses dependences in memory
|
||||
// accesses in loops.
|
||||
//
|
||||
// Please note that this is work in progress and the interface is subject to
|
||||
// change.
|
||||
//
|
||||
// TODO: adapt as interface progresses
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H
|
||||
#define LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class AnalysisUsage;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class Value;
|
||||
class raw_ostream;
|
||||
|
||||
class LoopDependenceAnalysis : public LoopPass {
|
||||
AliasAnalysis *AA;
|
||||
ScalarEvolution *SE;
|
||||
|
||||
/// L - The loop we are currently analysing.
|
||||
Loop *L;
|
||||
|
||||
/// TODO: doc
|
||||
enum DependenceResult { Independent = 0, Dependent = 1, Unknown = 2 };
|
||||
|
||||
/// TODO: doc
|
||||
struct Subscript {
|
||||
/// TODO: Add distance, direction, breaking conditions, ...
|
||||
};
|
||||
|
||||
/// DependencePair - Represents a data dependence relation between to memory
|
||||
/// reference instructions.
|
||||
struct DependencePair : public FastFoldingSetNode {
|
||||
Value *A;
|
||||
Value *B;
|
||||
DependenceResult Result;
|
||||
SmallVector<Subscript, 4> Subscripts;
|
||||
|
||||
DependencePair(const FoldingSetNodeID &ID, Value *a, Value *b) :
|
||||
FastFoldingSetNode(ID), A(a), B(b), Result(Unknown), Subscripts() {}
|
||||
};
|
||||
|
||||
/// findOrInsertDependencePair - Return true if a DependencePair for the
|
||||
/// given Values already exists, false if a new DependencePair had to be
|
||||
/// created. The third argument is set to the pair found or created.
|
||||
bool findOrInsertDependencePair(Value*, Value*, DependencePair*&);
|
||||
|
||||
/// getLoops - Collect all loops of the loop nest L in which
|
||||
/// a given SCEV is variant.
|
||||
void getLoops(const SCEV*, DenseSet<const Loop*>*) const;
|
||||
|
||||
/// isLoopInvariant - True if a given SCEV is invariant in all loops of the
|
||||
/// loop nest starting at the innermost loop L.
|
||||
bool isLoopInvariant(const SCEV*) const;
|
||||
|
||||
/// isAffine - An SCEV is affine with respect to the loop nest starting at
|
||||
/// the innermost loop L if it is of the form A+B*X where A, B are invariant
|
||||
/// in the loop nest and X is a induction variable in the loop nest.
|
||||
bool isAffine(const SCEV*) const;
|
||||
|
||||
/// TODO: doc
|
||||
bool isZIVPair(const SCEV*, const SCEV*) const;
|
||||
bool isSIVPair(const SCEV*, const SCEV*) const;
|
||||
DependenceResult analyseZIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseSIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseMIV(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analyseSubscript(const SCEV*, const SCEV*, Subscript*) const;
|
||||
DependenceResult analysePair(DependencePair*) const;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
LoopDependenceAnalysis() : LoopPass(ID) {
|
||||
initializeLoopDependenceAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
/// isDependencePair - Check whether two values can possibly give rise to
|
||||
/// a data dependence: that is the case if both are instructions accessing
|
||||
/// memory and at least one of those accesses is a write.
|
||||
bool isDependencePair(const Value*, const Value*) const;
|
||||
|
||||
/// depends - Return a boolean indicating if there is a data dependence
|
||||
/// between two instructions.
|
||||
bool depends(Value*, Value*);
|
||||
|
||||
bool runOnLoop(Loop*, LPPassManager&);
|
||||
virtual void releaseMemory();
|
||||
virtual void getAnalysisUsage(AnalysisUsage&) const;
|
||||
void print(raw_ostream&, const Module* = 0) const;
|
||||
|
||||
private:
|
||||
FoldingSet<DependencePair> Pairs;
|
||||
BumpPtrAllocator PairAllocator;
|
||||
}; // class LoopDependenceAnalysis
|
||||
|
||||
// createLoopDependenceAnalysisPass - This creates an instance of the
|
||||
// LoopDependenceAnalysis pass.
|
||||
//
|
||||
LoopPass *createLoopDependenceAnalysisPass();
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif /* LLVM_ANALYSIS_LOOP_DEPENDENCE_ANALYSIS_H */
|
||||
710
thirdparty/clang/include/llvm/Analysis/LoopInfo.h
vendored
Normal file
710
thirdparty/clang/include/llvm/Analysis/LoopInfo.h
vendored
Normal file
@@ -0,0 +1,710 @@
|
||||
//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- 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 LoopInfo class that is used to identify natural loops
|
||||
// and determine the loop depth of various nodes of the CFG. A natural loop
|
||||
// has exactly one entry-point, which is called the header. Note that natural
|
||||
// loops may actually be several loops that share the same header node.
|
||||
//
|
||||
// This analysis calculates the nesting structure of loops in a function. For
|
||||
// each natural loop identified, this analysis identifies natural loops
|
||||
// contained entirely within the loop and the basic blocks the make up the loop.
|
||||
//
|
||||
// It can calculate on the fly various bits of information, for example:
|
||||
//
|
||||
// * whether there is a preheader for the loop
|
||||
// * the number of back edges to the header
|
||||
// * whether or not a particular block branches out of the loop
|
||||
// * the successor blocks of the loop
|
||||
// * the loop depth
|
||||
// * etc...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPINFO_H
|
||||
#define LLVM_ANALYSIS_LOOPINFO_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename T>
|
||||
inline void RemoveFromVector(std::vector<T*> &V, T *N) {
|
||||
typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
|
||||
assert(I != V.end() && "N is not in this list!");
|
||||
V.erase(I);
|
||||
}
|
||||
|
||||
class DominatorTree;
|
||||
class LoopInfo;
|
||||
class Loop;
|
||||
class PHINode;
|
||||
class raw_ostream;
|
||||
template<class N, class M> class LoopInfoBase;
|
||||
template<class N, class M> class LoopBase;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// LoopBase class - Instances of this class are used to represent loops that
|
||||
/// are detected in the flow graph
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
class LoopBase {
|
||||
LoopT *ParentLoop;
|
||||
// SubLoops - Loops contained entirely within this one.
|
||||
std::vector<LoopT *> SubLoops;
|
||||
|
||||
// Blocks - The list of blocks in this loop. First entry is the header node.
|
||||
std::vector<BlockT*> Blocks;
|
||||
|
||||
LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
const LoopBase<BlockT, LoopT>&
|
||||
operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
/// Loop ctor - This creates an empty loop.
|
||||
LoopBase() : ParentLoop(0) {}
|
||||
~LoopBase() {
|
||||
for (size_t i = 0, e = SubLoops.size(); i != e; ++i)
|
||||
delete SubLoops[i];
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the nesting level of this loop. An outer-most
|
||||
/// loop has depth 1, for consistency with loop depth values used for basic
|
||||
/// blocks, where depth 0 is used for blocks not inside any loops.
|
||||
unsigned getLoopDepth() const {
|
||||
unsigned D = 1;
|
||||
for (const LoopT *CurLoop = ParentLoop; CurLoop;
|
||||
CurLoop = CurLoop->ParentLoop)
|
||||
++D;
|
||||
return D;
|
||||
}
|
||||
BlockT *getHeader() const { return Blocks.front(); }
|
||||
LoopT *getParentLoop() const { return ParentLoop; }
|
||||
|
||||
/// setParentLoop is a raw interface for bypassing addChildLoop.
|
||||
void setParentLoop(LoopT *L) { ParentLoop = L; }
|
||||
|
||||
/// contains - Return true if the specified loop is contained within in
|
||||
/// this loop.
|
||||
///
|
||||
bool contains(const LoopT *L) const {
|
||||
if (L == this) return true;
|
||||
if (L == 0) return false;
|
||||
return contains(L->getParentLoop());
|
||||
}
|
||||
|
||||
/// contains - Return true if the specified basic block is in this loop.
|
||||
///
|
||||
bool contains(const BlockT *BB) const {
|
||||
return std::find(block_begin(), block_end(), BB) != block_end();
|
||||
}
|
||||
|
||||
/// contains - Return true if the specified instruction is in this loop.
|
||||
///
|
||||
template<class InstT>
|
||||
bool contains(const InstT *Inst) const {
|
||||
return contains(Inst->getParent());
|
||||
}
|
||||
|
||||
/// iterator/begin/end - Return the loops contained entirely within this loop.
|
||||
///
|
||||
const std::vector<LoopT *> &getSubLoops() const { return SubLoops; }
|
||||
std::vector<LoopT *> &getSubLoopsVector() { return SubLoops; }
|
||||
typedef typename std::vector<LoopT *>::const_iterator iterator;
|
||||
typedef typename std::vector<LoopT *>::const_reverse_iterator
|
||||
reverse_iterator;
|
||||
iterator begin() const { return SubLoops.begin(); }
|
||||
iterator end() const { return SubLoops.end(); }
|
||||
reverse_iterator rbegin() const { return SubLoops.rbegin(); }
|
||||
reverse_iterator rend() const { return SubLoops.rend(); }
|
||||
bool empty() const { return SubLoops.empty(); }
|
||||
|
||||
/// getBlocks - Get a list of the basic blocks which make up this loop.
|
||||
///
|
||||
const std::vector<BlockT*> &getBlocks() const { return Blocks; }
|
||||
std::vector<BlockT*> &getBlocksVector() { return Blocks; }
|
||||
typedef typename std::vector<BlockT*>::const_iterator block_iterator;
|
||||
block_iterator block_begin() const { return Blocks.begin(); }
|
||||
block_iterator block_end() const { return Blocks.end(); }
|
||||
|
||||
/// getNumBlocks - Get the number of blocks in this loop in constant time.
|
||||
unsigned getNumBlocks() const {
|
||||
return Blocks.size();
|
||||
}
|
||||
|
||||
/// isLoopExiting - True if terminator in the block can branch to another
|
||||
/// block that is outside of the current loop.
|
||||
///
|
||||
bool isLoopExiting(const BlockT *BB) const {
|
||||
typedef GraphTraits<const BlockT*> BlockTraits;
|
||||
for (typename BlockTraits::ChildIteratorType SI =
|
||||
BlockTraits::child_begin(BB),
|
||||
SE = BlockTraits::child_end(BB); SI != SE; ++SI) {
|
||||
if (!contains(*SI))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getNumBackEdges - Calculate the number of back edges to the loop header
|
||||
///
|
||||
unsigned getNumBackEdges() const {
|
||||
unsigned NumBackEdges = 0;
|
||||
BlockT *H = getHeader();
|
||||
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType I =
|
||||
InvBlockTraits::child_begin(H),
|
||||
E = InvBlockTraits::child_end(H); I != E; ++I)
|
||||
if (contains(*I))
|
||||
++NumBackEdges;
|
||||
|
||||
return NumBackEdges;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// APIs for simple analysis of the loop.
|
||||
//
|
||||
// Note that all of these methods can fail on general loops (ie, there may not
|
||||
// be a preheader, etc). For best success, the loop simplification and
|
||||
// induction variable canonicalization pass should be used to normalize loops
|
||||
// for easy analysis. These methods assume canonical loops.
|
||||
|
||||
/// getExitingBlocks - Return all blocks inside the loop that have successors
|
||||
/// outside of the loop. These are the blocks _inside of the current loop_
|
||||
/// which branch out. The returned list is always unique.
|
||||
///
|
||||
void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const;
|
||||
|
||||
/// getExitingBlock - If getExitingBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
BlockT *getExitingBlock() const;
|
||||
|
||||
/// getExitBlocks - Return all of the successor blocks of this loop. These
|
||||
/// are the blocks _outside of the current loop_ which are branched to.
|
||||
///
|
||||
void getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const;
|
||||
|
||||
/// getExitBlock - If getExitBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
BlockT *getExitBlock() const;
|
||||
|
||||
/// Edge type.
|
||||
typedef std::pair<const BlockT*, const BlockT*> Edge;
|
||||
|
||||
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
|
||||
void getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const;
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
BlockT *getLoopPreheader() const;
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
/// This is less strict that the loop "preheader" concept, which requires
|
||||
/// the predecessor to have exactly one successor.
|
||||
///
|
||||
BlockT *getLoopPredecessor() const;
|
||||
|
||||
/// getLoopLatch - If there is a single latch block for this loop, return it.
|
||||
/// A latch block is a block that contains a branch back to the header.
|
||||
BlockT *getLoopLatch() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// APIs for updating loop information after changing the CFG
|
||||
//
|
||||
|
||||
/// addBasicBlockToLoop - This method is used by other analyses to update loop
|
||||
/// information. NewBB is set to be a new member of the current loop.
|
||||
/// Because of this, it is added as a member of all parent loops, and is added
|
||||
/// to the specified LoopInfo object as being in the current basic block. It
|
||||
/// is not valid to replace the loop header with this method.
|
||||
///
|
||||
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LI);
|
||||
|
||||
/// replaceChildLoopWith - This is used when splitting loops up. It replaces
|
||||
/// the OldChild entry in our children list with NewChild, and updates the
|
||||
/// parent pointer of OldChild to be null and the NewChild to be this loop.
|
||||
/// This updates the loop depth of the new child.
|
||||
void replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild);
|
||||
|
||||
/// addChildLoop - Add the specified loop to be a child of this loop. This
|
||||
/// updates the loop depth of the new child.
|
||||
///
|
||||
void addChildLoop(LoopT *NewChild) {
|
||||
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
|
||||
NewChild->ParentLoop = static_cast<LoopT *>(this);
|
||||
SubLoops.push_back(NewChild);
|
||||
}
|
||||
|
||||
/// removeChildLoop - This removes the specified child from being a subloop of
|
||||
/// this loop. The loop is not deleted, as it will presumably be inserted
|
||||
/// into another loop.
|
||||
LoopT *removeChildLoop(iterator I) {
|
||||
assert(I != SubLoops.end() && "Cannot remove end iterator!");
|
||||
LoopT *Child = *I;
|
||||
assert(Child->ParentLoop == this && "Child is not a child of this loop!");
|
||||
SubLoops.erase(SubLoops.begin()+(I-begin()));
|
||||
Child->ParentLoop = 0;
|
||||
return Child;
|
||||
}
|
||||
|
||||
/// addBlockEntry - This adds a basic block directly to the basic block list.
|
||||
/// This should only be used by transformations that create new loops. Other
|
||||
/// transformations should use addBasicBlockToLoop.
|
||||
void addBlockEntry(BlockT *BB) {
|
||||
Blocks.push_back(BB);
|
||||
}
|
||||
|
||||
/// moveToHeader - This method is used to move BB (which must be part of this
|
||||
/// loop) to be the loop header of the loop (the block that dominates all
|
||||
/// others).
|
||||
void moveToHeader(BlockT *BB) {
|
||||
if (Blocks[0] == BB) return;
|
||||
for (unsigned i = 0; ; ++i) {
|
||||
assert(i != Blocks.size() && "Loop does not contain BB!");
|
||||
if (Blocks[i] == BB) {
|
||||
Blocks[i] = Blocks[0];
|
||||
Blocks[0] = BB;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// removeBlockFromLoop - This removes the specified basic block from the
|
||||
/// current loop, updating the Blocks as appropriate. This does not update
|
||||
/// the mapping in the LoopInfo class.
|
||||
void removeBlockFromLoop(BlockT *BB) {
|
||||
RemoveFromVector(Blocks, BB);
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure
|
||||
void verifyLoop() const;
|
||||
|
||||
/// verifyLoop - Verify loop structure of this loop and all nested loops.
|
||||
void verifyLoopNest(DenseSet<const LoopT*> *Loops) const;
|
||||
|
||||
void print(raw_ostream &OS, unsigned Depth = 0) const;
|
||||
|
||||
protected:
|
||||
friend class LoopInfoBase<BlockT, LoopT>;
|
||||
explicit LoopBase(BlockT *BB) : ParentLoop(0) {
|
||||
Blocks.push_back(BB);
|
||||
}
|
||||
};
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
|
||||
Loop.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
|
||||
class Loop : public LoopBase<BasicBlock, Loop> {
|
||||
public:
|
||||
Loop() {}
|
||||
|
||||
/// isLoopInvariant - Return true if the specified value is loop invariant
|
||||
///
|
||||
bool isLoopInvariant(Value *V) const;
|
||||
|
||||
/// hasLoopInvariantOperands - Return true if all the operands of the
|
||||
/// specified instruction are loop invariant.
|
||||
bool hasLoopInvariantOperands(Instruction *I) const;
|
||||
|
||||
/// makeLoopInvariant - If the given value is an instruction inside of the
|
||||
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
|
||||
/// Return true if the value after any hoisting is loop invariant. This
|
||||
/// function can be used as a slightly more aggressive replacement for
|
||||
/// isLoopInvariant.
|
||||
///
|
||||
/// If InsertPt is specified, it is the point to hoist instructions to.
|
||||
/// If null, the terminator of the loop preheader is used.
|
||||
///
|
||||
bool makeLoopInvariant(Value *V, bool &Changed,
|
||||
Instruction *InsertPt = 0) const;
|
||||
|
||||
/// makeLoopInvariant - If the given instruction is inside of the
|
||||
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
|
||||
/// Return true if the instruction after any hoisting is loop invariant. This
|
||||
/// function can be used as a slightly more aggressive replacement for
|
||||
/// isLoopInvariant.
|
||||
///
|
||||
/// If InsertPt is specified, it is the point to hoist instructions to.
|
||||
/// If null, the terminator of the loop preheader is used.
|
||||
///
|
||||
bool makeLoopInvariant(Instruction *I, bool &Changed,
|
||||
Instruction *InsertPt = 0) const;
|
||||
|
||||
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
|
||||
/// induction variable: an integer recurrence that starts at 0 and increments
|
||||
/// by one each time through the loop. If so, return the phi node that
|
||||
/// corresponds to it.
|
||||
///
|
||||
/// The IndVarSimplify pass transforms loops to have a canonical induction
|
||||
/// variable.
|
||||
///
|
||||
PHINode *getCanonicalInductionVariable() const;
|
||||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool isLCSSAForm(DominatorTree &DT) const;
|
||||
|
||||
/// isLoopSimplifyForm - Return true if the Loop is in the form that
|
||||
/// the LoopSimplify form transforms loops to, which is sometimes called
|
||||
/// normal form.
|
||||
bool isLoopSimplifyForm() const;
|
||||
|
||||
/// isSafeToClone - Return true if the loop body is safe to clone in practice.
|
||||
bool isSafeToClone() const;
|
||||
|
||||
/// Returns true if the loop is annotated parallel.
|
||||
///
|
||||
/// A parallel loop can be assumed to not contain any dependencies between
|
||||
/// iterations by the compiler. That is, any loop-carried dependency checking
|
||||
/// can be skipped completely when parallelizing the loop on the target
|
||||
/// machine. Thus, if the parallel loop information originates from the
|
||||
/// programmer, e.g. via the OpenMP parallel for pragma, it is the
|
||||
/// programmer's responsibility to ensure there are no loop-carried
|
||||
/// dependencies. The final execution order of the instructions across
|
||||
/// iterations is not guaranteed, thus, the end result might or might not
|
||||
/// implement actual concurrent execution of instructions across multiple
|
||||
/// iterations.
|
||||
bool isAnnotatedParallel() const;
|
||||
|
||||
/// hasDedicatedExits - Return true if no exit block for the loop
|
||||
/// has a predecessor that is outside the loop.
|
||||
bool hasDedicatedExits() const;
|
||||
|
||||
/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
|
||||
/// These are the blocks _outside of the current loop_ which are branched to.
|
||||
/// This assumes that loop exits are in canonical form.
|
||||
///
|
||||
void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
|
||||
|
||||
/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
|
||||
/// block, return that block. Otherwise return null.
|
||||
BasicBlock *getUniqueExitBlock() const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
friend class LoopInfoBase<BasicBlock, Loop>;
|
||||
explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// LoopInfo - This class builds and contains all of the top level loop
|
||||
/// structures in the specified function.
|
||||
///
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
class LoopInfoBase {
|
||||
// BBMap - Mapping of basic blocks to the inner most loop they occur in
|
||||
DenseMap<BlockT *, LoopT *> BBMap;
|
||||
std::vector<LoopT *> TopLevelLoops;
|
||||
friend class LoopBase<BlockT, LoopT>;
|
||||
friend class LoopInfo;
|
||||
|
||||
void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION;
|
||||
LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
LoopInfoBase() { }
|
||||
~LoopInfoBase() { releaseMemory(); }
|
||||
|
||||
void releaseMemory() {
|
||||
for (typename std::vector<LoopT *>::iterator I =
|
||||
TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
|
||||
delete *I; // Delete all of the loops...
|
||||
|
||||
BBMap.clear(); // Reset internal state of analysis
|
||||
TopLevelLoops.clear();
|
||||
}
|
||||
|
||||
/// iterator/begin/end - The interface to the top-level loops in the current
|
||||
/// function.
|
||||
///
|
||||
typedef typename std::vector<LoopT *>::const_iterator iterator;
|
||||
typedef typename std::vector<LoopT *>::const_reverse_iterator
|
||||
reverse_iterator;
|
||||
iterator begin() const { return TopLevelLoops.begin(); }
|
||||
iterator end() const { return TopLevelLoops.end(); }
|
||||
reverse_iterator rbegin() const { return TopLevelLoops.rbegin(); }
|
||||
reverse_iterator rend() const { return TopLevelLoops.rend(); }
|
||||
bool empty() const { return TopLevelLoops.empty(); }
|
||||
|
||||
/// getLoopFor - Return the inner most loop that BB lives in. If a basic
|
||||
/// block is in no loop (for example the entry node), null is returned.
|
||||
///
|
||||
LoopT *getLoopFor(const BlockT *BB) const {
|
||||
return BBMap.lookup(const_cast<BlockT*>(BB));
|
||||
}
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
///
|
||||
const LoopT *operator[](const BlockT *BB) const {
|
||||
return getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the loop nesting level of the specified block. A
|
||||
/// depth of 0 means the block is not inside any loop.
|
||||
///
|
||||
unsigned getLoopDepth(const BlockT *BB) const {
|
||||
const LoopT *L = getLoopFor(BB);
|
||||
return L ? L->getLoopDepth() : 0;
|
||||
}
|
||||
|
||||
// isLoopHeader - True if the block is a loop header node
|
||||
bool isLoopHeader(BlockT *BB) const {
|
||||
const LoopT *L = getLoopFor(BB);
|
||||
return L && L->getHeader() == BB;
|
||||
}
|
||||
|
||||
/// removeLoop - This removes the specified top-level loop from this loop info
|
||||
/// object. The loop is not deleted, as it will presumably be inserted into
|
||||
/// another loop.
|
||||
LoopT *removeLoop(iterator I) {
|
||||
assert(I != end() && "Cannot remove end iterator!");
|
||||
LoopT *L = *I;
|
||||
assert(L->getParentLoop() == 0 && "Not a top-level loop!");
|
||||
TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin()));
|
||||
return L;
|
||||
}
|
||||
|
||||
/// changeLoopFor - Change the top-level loop that contains BB to the
|
||||
/// specified loop. This should be used by transformations that restructure
|
||||
/// the loop hierarchy tree.
|
||||
void changeLoopFor(BlockT *BB, LoopT *L) {
|
||||
if (!L) {
|
||||
BBMap.erase(BB);
|
||||
return;
|
||||
}
|
||||
BBMap[BB] = L;
|
||||
}
|
||||
|
||||
/// changeTopLevelLoop - Replace the specified loop in the top-level loops
|
||||
/// list with the indicated loop.
|
||||
void changeTopLevelLoop(LoopT *OldLoop,
|
||||
LoopT *NewLoop) {
|
||||
typename std::vector<LoopT *>::iterator I =
|
||||
std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
|
||||
assert(I != TopLevelLoops.end() && "Old loop not at top level!");
|
||||
*I = NewLoop;
|
||||
assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 &&
|
||||
"Loops already embedded into a subloop!");
|
||||
}
|
||||
|
||||
/// addTopLevelLoop - This adds the specified loop to the collection of
|
||||
/// top-level loops.
|
||||
void addTopLevelLoop(LoopT *New) {
|
||||
assert(New->getParentLoop() == 0 && "Loop already in subloop!");
|
||||
TopLevelLoops.push_back(New);
|
||||
}
|
||||
|
||||
/// removeBlock - This method completely removes BB from all data structures,
|
||||
/// including all of the Loop objects it is nested in and our mapping from
|
||||
/// BasicBlocks to loops.
|
||||
void removeBlock(BlockT *BB) {
|
||||
typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
|
||||
if (I != BBMap.end()) {
|
||||
for (LoopT *L = I->second; L; L = L->getParentLoop())
|
||||
L->removeBlockFromLoop(BB);
|
||||
|
||||
BBMap.erase(I);
|
||||
}
|
||||
}
|
||||
|
||||
// Internals
|
||||
|
||||
static bool isNotAlreadyContainedIn(const LoopT *SubLoop,
|
||||
const LoopT *ParentLoop) {
|
||||
if (SubLoop == 0) return true;
|
||||
if (SubLoop == ParentLoop) return false;
|
||||
return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop);
|
||||
}
|
||||
|
||||
/// Create the loop forest using a stable algorithm.
|
||||
void Analyze(DominatorTreeBase<BlockT> &DomTree);
|
||||
|
||||
// Debugging
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
|
||||
class LoopInfo : public FunctionPass {
|
||||
LoopInfoBase<BasicBlock, Loop> LI;
|
||||
friend class LoopBase<BasicBlock, Loop>;
|
||||
|
||||
void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
LoopInfo() : FunctionPass(ID) {
|
||||
initializeLoopInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }
|
||||
|
||||
/// iterator/begin/end - The interface to the top-level loops in the current
|
||||
/// function.
|
||||
///
|
||||
typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
|
||||
typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator;
|
||||
inline iterator begin() const { return LI.begin(); }
|
||||
inline iterator end() const { return LI.end(); }
|
||||
inline reverse_iterator rbegin() const { return LI.rbegin(); }
|
||||
inline reverse_iterator rend() const { return LI.rend(); }
|
||||
bool empty() const { return LI.empty(); }
|
||||
|
||||
/// getLoopFor - Return the inner most loop that BB lives in. If a basic
|
||||
/// block is in no loop (for example the entry node), null is returned.
|
||||
///
|
||||
inline Loop *getLoopFor(const BasicBlock *BB) const {
|
||||
return LI.getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
///
|
||||
inline const Loop *operator[](const BasicBlock *BB) const {
|
||||
return LI.getLoopFor(BB);
|
||||
}
|
||||
|
||||
/// getLoopDepth - Return the loop nesting level of the specified block. A
|
||||
/// depth of 0 means the block is not inside any loop.
|
||||
///
|
||||
inline unsigned getLoopDepth(const BasicBlock *BB) const {
|
||||
return LI.getLoopDepth(BB);
|
||||
}
|
||||
|
||||
// isLoopHeader - True if the block is a loop header node
|
||||
inline bool isLoopHeader(BasicBlock *BB) const {
|
||||
return LI.isLoopHeader(BB);
|
||||
}
|
||||
|
||||
/// runOnFunction - Calculate the natural loop information.
|
||||
///
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
virtual void releaseMemory() { LI.releaseMemory(); }
|
||||
|
||||
virtual void print(raw_ostream &O, const Module* M = 0) const;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
/// removeLoop - This removes the specified top-level loop from this loop info
|
||||
/// object. The loop is not deleted, as it will presumably be inserted into
|
||||
/// another loop.
|
||||
inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); }
|
||||
|
||||
/// changeLoopFor - Change the top-level loop that contains BB to the
|
||||
/// specified loop. This should be used by transformations that restructure
|
||||
/// the loop hierarchy tree.
|
||||
inline void changeLoopFor(BasicBlock *BB, Loop *L) {
|
||||
LI.changeLoopFor(BB, L);
|
||||
}
|
||||
|
||||
/// changeTopLevelLoop - Replace the specified loop in the top-level loops
|
||||
/// list with the indicated loop.
|
||||
inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) {
|
||||
LI.changeTopLevelLoop(OldLoop, NewLoop);
|
||||
}
|
||||
|
||||
/// addTopLevelLoop - This adds the specified loop to the collection of
|
||||
/// top-level loops.
|
||||
inline void addTopLevelLoop(Loop *New) {
|
||||
LI.addTopLevelLoop(New);
|
||||
}
|
||||
|
||||
/// removeBlock - This method completely removes BB from all data structures,
|
||||
/// including all of the Loop objects it is nested in and our mapping from
|
||||
/// BasicBlocks to loops.
|
||||
void removeBlock(BasicBlock *BB) {
|
||||
LI.removeBlock(BB);
|
||||
}
|
||||
|
||||
/// updateUnloop - Update LoopInfo after removing the last backedge from a
|
||||
/// loop--now the "unloop". This updates the loop forest and parent loops for
|
||||
/// each block so that Unloop is no longer referenced, but the caller must
|
||||
/// actually delete the Unloop object.
|
||||
void updateUnloop(Loop *Unloop);
|
||||
|
||||
/// replacementPreservesLCSSAForm - Returns true if replacing From with To
|
||||
/// everywhere is guaranteed to preserve LCSSA form.
|
||||
bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {
|
||||
// Preserving LCSSA form is only problematic if the replacing value is an
|
||||
// instruction.
|
||||
Instruction *I = dyn_cast<Instruction>(To);
|
||||
if (!I) return true;
|
||||
// If both instructions are defined in the same basic block then replacement
|
||||
// cannot break LCSSA form.
|
||||
if (I->getParent() == From->getParent())
|
||||
return true;
|
||||
// If the instruction is not defined in a loop then it can safely replace
|
||||
// anything.
|
||||
Loop *ToLoop = getLoopFor(I->getParent());
|
||||
if (!ToLoop) return true;
|
||||
// If the replacing instruction is defined in the same loop as the original
|
||||
// instruction, or in a loop that contains it as an inner loop, then using
|
||||
// it as a replacement will not break LCSSA form.
|
||||
return ToLoop->contains(getLoopFor(From->getParent()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Allow clients to walk the list of nested loops...
|
||||
template <> struct GraphTraits<const Loop*> {
|
||||
typedef const Loop NodeType;
|
||||
typedef LoopInfo::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(const Loop *L) { return L; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Loop*> {
|
||||
typedef Loop NodeType;
|
||||
typedef LoopInfo::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(Loop *L) { return L; }
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
570
thirdparty/clang/include/llvm/Analysis/LoopInfoImpl.h
vendored
Normal file
570
thirdparty/clang/include/llvm/Analysis/LoopInfoImpl.h
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
//===- llvm/Analysis/LoopInfoImpl.h - Natural Loop Calculator ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the generic implementation of LoopInfo used for both Loops and
|
||||
// MachineLoops.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H
|
||||
#define LLVM_ANALYSIS_LOOPINFOIMPL_H
|
||||
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APIs for simple analysis of the loop. See header notes.
|
||||
|
||||
/// getExitingBlocks - Return all blocks inside the loop that have successors
|
||||
/// outside of the loop. These are the blocks _inside of the current loop_
|
||||
/// which branch out. The returned list is always unique.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) {
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitingBlocks.push_back(*BI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// getExitingBlock - If getExitingBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
|
||||
SmallVector<BlockT*, 8> ExitingBlocks;
|
||||
getExitingBlocks(ExitingBlocks);
|
||||
if (ExitingBlocks.size() == 1)
|
||||
return ExitingBlocks[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getExitBlocks - Return all of the successor blocks of this loop. These
|
||||
/// are the blocks _outside of the current loop_ which are branched to.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitBlocks.push_back(*I);
|
||||
}
|
||||
|
||||
/// getExitBlock - If getExitBlocks would return exactly one block,
|
||||
/// return that block. Otherwise return null.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
|
||||
SmallVector<BlockT*, 8> ExitBlocks;
|
||||
getExitBlocks(ExitBlocks);
|
||||
if (ExitBlocks.size() == 1)
|
||||
return ExitBlocks[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
array_pod_sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
|
||||
for (typename BlockTraits::ChildIteratorType I =
|
||||
BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
|
||||
I != E; ++I)
|
||||
if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
|
||||
// Not in current loop? It must be an exit block.
|
||||
ExitEdges.push_back(Edge(*BI, *I));
|
||||
}
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = getLoopPredecessor();
|
||||
if (!Out) return 0;
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
++SI;
|
||||
if (SI != BlockTraits::child_end(Out))
|
||||
return 0; // Multiple exits from the block, must not be a preheader.
|
||||
|
||||
// The predecessor has exactly one successor, so it is a preheader.
|
||||
return Out;
|
||||
}
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
/// This is less strict that the loop "preheader" concept, which requires
|
||||
/// the predecessor to have exactly one successor.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = 0;
|
||||
|
||||
// Loop over the predecessors of the header node...
|
||||
BlockT *Header = getHeader();
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header),
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (!contains(N)) { // If the block is not in the loop...
|
||||
if (Out && Out != N)
|
||||
return 0; // Multiple predecessors outside the loop
|
||||
Out = N;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
assert(Out && "Header of loop has no predecessors from outside loop?");
|
||||
return Out;
|
||||
}
|
||||
|
||||
/// getLoopLatch - If there is a single latch block for this loop, return it.
|
||||
/// A latch block is a block that contains a branch back to the header.
|
||||
template<class BlockT, class LoopT>
|
||||
BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
|
||||
BlockT *Header = getHeader();
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header);
|
||||
typename InvBlockTraits::ChildIteratorType PE =
|
||||
InvBlockTraits::child_end(Header);
|
||||
BlockT *Latch = 0;
|
||||
for (; PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (contains(N)) {
|
||||
if (Latch) return 0;
|
||||
Latch = N;
|
||||
}
|
||||
}
|
||||
|
||||
return Latch;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// APIs for updating loop information after changing the CFG
|
||||
//
|
||||
|
||||
/// addBasicBlockToLoop - This method is used by other analyses to update loop
|
||||
/// information. NewBB is set to be a new member of the current loop.
|
||||
/// Because of this, it is added as a member of all parent loops, and is added
|
||||
/// to the specified LoopInfo object as being in the current basic block. It
|
||||
/// is not valid to replace the loop header with this method.
|
||||
///
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) {
|
||||
assert((Blocks.empty() || LIB[getHeader()] == this) &&
|
||||
"Incorrect LI specified for this loop!");
|
||||
assert(NewBB && "Cannot add a null basic block to the loop!");
|
||||
assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!");
|
||||
|
||||
LoopT *L = static_cast<LoopT *>(this);
|
||||
|
||||
// Add the loop mapping to the LoopInfo object...
|
||||
LIB.BBMap[NewBB] = L;
|
||||
|
||||
// Add the basic block to this loop and all parent loops...
|
||||
while (L) {
|
||||
L->Blocks.push_back(NewBB);
|
||||
L = L->getParentLoop();
|
||||
}
|
||||
}
|
||||
|
||||
/// replaceChildLoopWith - This is used when splitting loops up. It replaces
|
||||
/// the OldChild entry in our children list with NewChild, and updates the
|
||||
/// parent pointer of OldChild to be null and the NewChild to be this loop.
|
||||
/// This updates the loop depth of the new child.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::
|
||||
replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild) {
|
||||
assert(OldChild->ParentLoop == this && "This loop is already broken!");
|
||||
assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
|
||||
typename std::vector<LoopT *>::iterator I =
|
||||
std::find(SubLoops.begin(), SubLoops.end(), OldChild);
|
||||
assert(I != SubLoops.end() && "OldChild not in loop!");
|
||||
*I = NewChild;
|
||||
OldChild->ParentLoop = 0;
|
||||
NewChild->ParentLoop = static_cast<LoopT *>(this);
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::verifyLoop() const {
|
||||
#ifndef NDEBUG
|
||||
assert(!Blocks.empty() && "Loop header is missing");
|
||||
|
||||
// Setup for using a depth-first iterator to visit every block in the loop.
|
||||
SmallVector<BlockT*, 8> ExitBBs;
|
||||
getExitBlocks(ExitBBs);
|
||||
llvm::SmallPtrSet<BlockT*, 8> VisitSet;
|
||||
VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
|
||||
df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> >
|
||||
BI = df_ext_begin(getHeader(), VisitSet),
|
||||
BE = df_ext_end(getHeader(), VisitSet);
|
||||
|
||||
// Keep track of the number of BBs visited.
|
||||
unsigned NumVisited = 0;
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
// Check the individual blocks.
|
||||
for ( ; BI != BE; ++BI) {
|
||||
BlockT *BB = *BI;
|
||||
bool HasInsideLoopSuccs = false;
|
||||
bool HasInsideLoopPreds = false;
|
||||
SmallVector<BlockT *, 2> OutsideLoopPreds;
|
||||
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
for (typename BlockTraits::ChildIteratorType SI =
|
||||
BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
|
||||
SI != SE; ++SI)
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) {
|
||||
HasInsideLoopSuccs = true;
|
||||
break;
|
||||
}
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
BlockT *N = *PI;
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
|
||||
HasInsideLoopPreds = true;
|
||||
else
|
||||
OutsideLoopPreds.push_back(N);
|
||||
}
|
||||
|
||||
if (BB == getHeader()) {
|
||||
assert(!OutsideLoopPreds.empty() && "Loop is unreachable!");
|
||||
} else if (!OutsideLoopPreds.empty()) {
|
||||
// A non-header loop shouldn't be reachable from outside the loop,
|
||||
// though it is permitted if the predecessor is not itself actually
|
||||
// reachable.
|
||||
BlockT *EntryBB = BB->getParent()->begin();
|
||||
for (df_iterator<BlockT *> NI = df_begin(EntryBB),
|
||||
NE = df_end(EntryBB); NI != NE; ++NI)
|
||||
for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
|
||||
assert(*NI != OutsideLoopPreds[i] &&
|
||||
"Loop has multiple entry points!");
|
||||
}
|
||||
assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
|
||||
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
|
||||
assert(BB != getHeader()->getParent()->begin() &&
|
||||
"Loop contains function entry block!");
|
||||
|
||||
NumVisited++;
|
||||
}
|
||||
|
||||
assert(NumVisited == getNumBlocks() && "Unreachable block in loop");
|
||||
|
||||
// Check the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
// Each block in each subloop should be contained within this loop.
|
||||
for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
|
||||
BI != BE; ++BI) {
|
||||
assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) &&
|
||||
"Loop does not contain all the blocks of a subloop!");
|
||||
}
|
||||
|
||||
// Check the parent loop pointer.
|
||||
if (ParentLoop) {
|
||||
assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) !=
|
||||
ParentLoop->end() &&
|
||||
"Loop is not a subloop of its parent!");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// verifyLoop - Verify loop structure of this loop and all nested loops.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::verifyLoopNest(
|
||||
DenseSet<const LoopT*> *Loops) const {
|
||||
Loops->insert(static_cast<const LoopT *>(this));
|
||||
// Verify this loop.
|
||||
verifyLoop();
|
||||
// Verify the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
(*I)->verifyLoopNest(Loops);
|
||||
}
|
||||
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const {
|
||||
OS.indent(Depth*2) << "Loop at depth " << getLoopDepth()
|
||||
<< " containing: ";
|
||||
|
||||
for (unsigned i = 0; i < getBlocks().size(); ++i) {
|
||||
if (i) OS << ",";
|
||||
BlockT *BB = getBlocks()[i];
|
||||
WriteAsOperand(OS, BB, false);
|
||||
if (BB == getHeader()) OS << "<header>";
|
||||
if (BB == getLoopLatch()) OS << "<latch>";
|
||||
if (isLoopExiting(BB)) OS << "<exiting>";
|
||||
}
|
||||
OS << "\n";
|
||||
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
(*I)->print(OS, Depth+2);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Stable LoopInfo Analysis - Build a loop tree using stable iterators so the
|
||||
/// result does / not depend on use list (block predecessor) order.
|
||||
///
|
||||
|
||||
/// Discover a subloop with the specified backedges such that: All blocks within
|
||||
/// this loop are mapped to this loop or a subloop. And all subloops within this
|
||||
/// loop have their parent loop set to this loop or a subloop.
|
||||
template<class BlockT, class LoopT>
|
||||
static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
|
||||
LoopInfoBase<BlockT, LoopT> *LI,
|
||||
DominatorTreeBase<BlockT> &DomTree) {
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
|
||||
unsigned NumBlocks = 0;
|
||||
unsigned NumSubloops = 0;
|
||||
|
||||
// Perform a backward CFG traversal using a worklist.
|
||||
std::vector<BlockT *> ReverseCFGWorklist(Backedges.begin(), Backedges.end());
|
||||
while (!ReverseCFGWorklist.empty()) {
|
||||
BlockT *PredBB = ReverseCFGWorklist.back();
|
||||
ReverseCFGWorklist.pop_back();
|
||||
|
||||
LoopT *Subloop = LI->getLoopFor(PredBB);
|
||||
if (!Subloop) {
|
||||
if (!DomTree.isReachableFromEntry(PredBB))
|
||||
continue;
|
||||
|
||||
// This is an undiscovered block. Map it to the current loop.
|
||||
LI->changeLoopFor(PredBB, L);
|
||||
++NumBlocks;
|
||||
if (PredBB == L->getHeader())
|
||||
continue;
|
||||
// Push all block predecessors on the worklist.
|
||||
ReverseCFGWorklist.insert(ReverseCFGWorklist.end(),
|
||||
InvBlockTraits::child_begin(PredBB),
|
||||
InvBlockTraits::child_end(PredBB));
|
||||
}
|
||||
else {
|
||||
// This is a discovered block. Find its outermost discovered loop.
|
||||
while (LoopT *Parent = Subloop->getParentLoop())
|
||||
Subloop = Parent;
|
||||
|
||||
// If it is already discovered to be a subloop of this loop, continue.
|
||||
if (Subloop == L)
|
||||
continue;
|
||||
|
||||
// Discover a subloop of this loop.
|
||||
Subloop->setParentLoop(L);
|
||||
++NumSubloops;
|
||||
NumBlocks += Subloop->getBlocks().capacity();
|
||||
PredBB = Subloop->getHeader();
|
||||
// Continue traversal along predecessors that are not loop-back edges from
|
||||
// within this subloop tree itself. Note that a predecessor may directly
|
||||
// reach another subloop that is not yet discovered to be a subloop of
|
||||
// this loop, which we must traverse.
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(PredBB),
|
||||
PE = InvBlockTraits::child_end(PredBB); PI != PE; ++PI) {
|
||||
if (LI->getLoopFor(*PI) != Subloop)
|
||||
ReverseCFGWorklist.push_back(*PI);
|
||||
}
|
||||
}
|
||||
}
|
||||
L->getSubLoopsVector().reserve(NumSubloops);
|
||||
L->getBlocksVector().reserve(NumBlocks);
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Populate all loop data in a stable order during a single forward DFS.
|
||||
template<class BlockT, class LoopT>
|
||||
class PopulateLoopsDFS {
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typedef typename BlockTraits::ChildIteratorType SuccIterTy;
|
||||
|
||||
LoopInfoBase<BlockT, LoopT> *LI;
|
||||
DenseSet<const BlockT *> VisitedBlocks;
|
||||
std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack;
|
||||
|
||||
public:
|
||||
PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li):
|
||||
LI(li) {}
|
||||
|
||||
void traverse(BlockT *EntryBlock);
|
||||
|
||||
protected:
|
||||
void insertIntoLoop(BlockT *Block);
|
||||
|
||||
BlockT *dfsSource() { return DFSStack.back().first; }
|
||||
SuccIterTy &dfsSucc() { return DFSStack.back().second; }
|
||||
SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); }
|
||||
|
||||
void pushBlock(BlockT *Block) {
|
||||
DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block)));
|
||||
}
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
/// Top-level driver for the forward DFS within the loop.
|
||||
template<class BlockT, class LoopT>
|
||||
void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) {
|
||||
pushBlock(EntryBlock);
|
||||
VisitedBlocks.insert(EntryBlock);
|
||||
while (!DFSStack.empty()) {
|
||||
// Traverse the leftmost path as far as possible.
|
||||
while (dfsSucc() != dfsSuccEnd()) {
|
||||
BlockT *BB = *dfsSucc();
|
||||
++dfsSucc();
|
||||
if (!VisitedBlocks.insert(BB).second)
|
||||
continue;
|
||||
|
||||
// Push the next DFS successor onto the stack.
|
||||
pushBlock(BB);
|
||||
}
|
||||
// Visit the top of the stack in postorder and backtrack.
|
||||
insertIntoLoop(dfsSource());
|
||||
DFSStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a single Block to its ancestor loops in PostOrder. If the block is a
|
||||
/// subloop header, add the subloop to its parent in PostOrder, then reverse the
|
||||
/// Block and Subloop vectors of the now complete subloop to achieve RPO.
|
||||
template<class BlockT, class LoopT>
|
||||
void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
|
||||
LoopT *Subloop = LI->getLoopFor(Block);
|
||||
if (Subloop && Block == Subloop->getHeader()) {
|
||||
// We reach this point once per subloop after processing all the blocks in
|
||||
// the subloop.
|
||||
if (Subloop->getParentLoop())
|
||||
Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop);
|
||||
else
|
||||
LI->addTopLevelLoop(Subloop);
|
||||
|
||||
// For convenience, Blocks and Subloops are inserted in postorder. Reverse
|
||||
// the lists, except for the loop header, which is always at the beginning.
|
||||
std::reverse(Subloop->getBlocksVector().begin()+1,
|
||||
Subloop->getBlocksVector().end());
|
||||
std::reverse(Subloop->getSubLoopsVector().begin(),
|
||||
Subloop->getSubLoopsVector().end());
|
||||
|
||||
Subloop = Subloop->getParentLoop();
|
||||
}
|
||||
for (; Subloop; Subloop = Subloop->getParentLoop())
|
||||
Subloop->getBlocksVector().push_back(Block);
|
||||
}
|
||||
|
||||
/// Analyze LoopInfo discovers loops during a postorder DominatorTree traversal
|
||||
/// interleaved with backward CFG traversals within each subloop
|
||||
/// (discoverAndMapSubloop). The backward traversal skips inner subloops, so
|
||||
/// this part of the algorithm is linear in the number of CFG edges. Subloop and
|
||||
/// Block vectors are then populated during a single forward CFG traversal
|
||||
/// (PopulateLoopDFS).
|
||||
///
|
||||
/// During the two CFG traversals each block is seen three times:
|
||||
/// 1) Discovered and mapped by a reverse CFG traversal.
|
||||
/// 2) Visited during a forward DFS CFG traversal.
|
||||
/// 3) Reverse-inserted in the loop in postorder following forward DFS.
|
||||
///
|
||||
/// The Block vectors are inclusive, so step 3 requires loop-depth number of
|
||||
/// insertions per block.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopInfoBase<BlockT, LoopT>::
|
||||
Analyze(DominatorTreeBase<BlockT> &DomTree) {
|
||||
|
||||
// Postorder traversal of the dominator tree.
|
||||
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
|
||||
for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot),
|
||||
DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) {
|
||||
|
||||
BlockT *Header = DomIter->getBlock();
|
||||
SmallVector<BlockT *, 4> Backedges;
|
||||
|
||||
// Check each predecessor of the potential loop header.
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header),
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
|
||||
|
||||
BlockT *Backedge = *PI;
|
||||
|
||||
// If Header dominates predBB, this is a new loop. Collect the backedges.
|
||||
if (DomTree.dominates(Header, Backedge)
|
||||
&& DomTree.isReachableFromEntry(Backedge)) {
|
||||
Backedges.push_back(Backedge);
|
||||
}
|
||||
}
|
||||
// Perform a backward CFG traversal to discover and map blocks in this loop.
|
||||
if (!Backedges.empty()) {
|
||||
LoopT *L = new LoopT(Header);
|
||||
discoverAndMapSubloop(L, ArrayRef<BlockT*>(Backedges), this, DomTree);
|
||||
}
|
||||
}
|
||||
// Perform a single forward CFG traversal to populate block and subloop
|
||||
// vectors for all loops.
|
||||
PopulateLoopsDFS<BlockT, LoopT> DFS(this);
|
||||
DFS.traverse(DomRoot->getBlock());
|
||||
}
|
||||
|
||||
// Debugging
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
|
||||
for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
|
||||
TopLevelLoops[i]->print(OS);
|
||||
#if 0
|
||||
for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
|
||||
E = BBMap.end(); I != E; ++I)
|
||||
OS << "BB '" << I->first->getName() << "' level = "
|
||||
<< I->second->getLoopDepth() << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
181
thirdparty/clang/include/llvm/Analysis/LoopIterator.h
vendored
Normal file
181
thirdparty/clang/include/llvm/Analysis/LoopIterator.h
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
//===--------- LoopIterator.h - Iterate over loop blocks --------*- 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 iterators to visit the basic blocks within a loop.
|
||||
//
|
||||
// These iterators currently visit blocks within subloops as well.
|
||||
// Unfortunately we have no efficient way of summarizing loop exits which would
|
||||
// allow skipping subloops during traversal.
|
||||
//
|
||||
// If you want to visit all blocks in a loop and don't need an ordered traveral,
|
||||
// use Loop::block_begin() instead.
|
||||
//
|
||||
// This is intentionally designed to work with ill-formed loops in which the
|
||||
// backedge has been deleted. The only prerequisite is that all blocks
|
||||
// contained within the loop according to the most recent LoopInfo analysis are
|
||||
// reachable from the loop header.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPITERATOR_H
|
||||
#define LLVM_ANALYSIS_LOOPITERATOR_H
|
||||
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoopBlocksTraversal;
|
||||
|
||||
/// Store the result of a depth first search within basic blocks contained by a
|
||||
/// single loop.
|
||||
///
|
||||
/// TODO: This could be generalized for any CFG region, or the entire CFG.
|
||||
class LoopBlocksDFS {
|
||||
public:
|
||||
/// Postorder list iterators.
|
||||
typedef std::vector<BasicBlock*>::const_iterator POIterator;
|
||||
typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
|
||||
|
||||
friend class LoopBlocksTraversal;
|
||||
|
||||
private:
|
||||
Loop *L;
|
||||
|
||||
/// Map each block to its postorder number. A block is only mapped after it is
|
||||
/// preorder visited by DFS. It's postorder number is initially zero and set
|
||||
/// to nonzero after it is finished by postorder traversal.
|
||||
DenseMap<BasicBlock*, unsigned> PostNumbers;
|
||||
std::vector<BasicBlock*> PostBlocks;
|
||||
|
||||
public:
|
||||
LoopBlocksDFS(Loop *Container) :
|
||||
L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
|
||||
PostBlocks.reserve(Container->getNumBlocks());
|
||||
}
|
||||
|
||||
Loop *getLoop() const { return L; }
|
||||
|
||||
/// Traverse the loop blocks and store the DFS result.
|
||||
void perform(LoopInfo *LI);
|
||||
|
||||
/// Return true if postorder numbers are assigned to all loop blocks.
|
||||
bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
|
||||
|
||||
/// Iterate over the cached postorder blocks.
|
||||
POIterator beginPostorder() const {
|
||||
assert(isComplete() && "bad loop DFS");
|
||||
return PostBlocks.begin();
|
||||
}
|
||||
POIterator endPostorder() const { return PostBlocks.end(); }
|
||||
|
||||
/// Reverse iterate over the cached postorder blocks.
|
||||
RPOIterator beginRPO() const {
|
||||
assert(isComplete() && "bad loop DFS");
|
||||
return PostBlocks.rbegin();
|
||||
}
|
||||
RPOIterator endRPO() const { return PostBlocks.rend(); }
|
||||
|
||||
/// Return true if this block has been preorder visited.
|
||||
bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
|
||||
|
||||
/// Return true if this block has a postorder number.
|
||||
bool hasPostorder(BasicBlock *BB) const {
|
||||
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
|
||||
return I != PostNumbers.end() && I->second;
|
||||
}
|
||||
|
||||
/// Get a block's postorder number.
|
||||
unsigned getPostorder(BasicBlock *BB) const {
|
||||
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
|
||||
assert(I != PostNumbers.end() && "block not visited by DFS");
|
||||
assert(I->second && "block not finished by DFS");
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// Get a block's reverse postorder number.
|
||||
unsigned getRPO(BasicBlock *BB) const {
|
||||
return 1 + PostBlocks.size() - getPostorder(BB);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
PostNumbers.clear();
|
||||
PostBlocks.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/// Specialize po_iterator_storage to record postorder numbers.
|
||||
template<> class po_iterator_storage<LoopBlocksTraversal, true> {
|
||||
LoopBlocksTraversal &LBT;
|
||||
public:
|
||||
po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {}
|
||||
// These functions are defined below.
|
||||
bool insertEdge(BasicBlock *From, BasicBlock *To);
|
||||
void finishPostorder(BasicBlock *BB);
|
||||
};
|
||||
|
||||
/// Traverse the blocks in a loop using a depth-first search.
|
||||
class LoopBlocksTraversal {
|
||||
public:
|
||||
/// Graph traversal iterator.
|
||||
typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
|
||||
|
||||
private:
|
||||
LoopBlocksDFS &DFS;
|
||||
LoopInfo *LI;
|
||||
|
||||
public:
|
||||
LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) :
|
||||
DFS(Storage), LI(LInfo) {}
|
||||
|
||||
/// Postorder traversal over the graph. This only needs to be done once.
|
||||
/// po_iterator "automatically" calls back to visitPreorder and
|
||||
/// finishPostorder to record the DFS result.
|
||||
POTIterator begin() {
|
||||
assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
|
||||
assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
|
||||
return po_ext_begin(DFS.L->getHeader(), *this);
|
||||
}
|
||||
POTIterator end() {
|
||||
// po_ext_end interface requires a basic block, but ignores its value.
|
||||
return po_ext_end(DFS.L->getHeader(), *this);
|
||||
}
|
||||
|
||||
/// Called by po_iterator upon reaching a block via a CFG edge. If this block
|
||||
/// is contained in the loop and has not been visited, then mark it preorder
|
||||
/// visited and return true.
|
||||
///
|
||||
/// TODO: If anyone is interested, we could record preorder numbers here.
|
||||
bool visitPreorder(BasicBlock *BB) {
|
||||
if (!DFS.L->contains(LI->getLoopFor(BB)))
|
||||
return false;
|
||||
|
||||
return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
|
||||
}
|
||||
|
||||
/// Called by po_iterator each time it advances, indicating a block's
|
||||
/// postorder.
|
||||
void finishPostorder(BasicBlock *BB) {
|
||||
assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
|
||||
DFS.PostBlocks.push_back(BB);
|
||||
DFS.PostNumbers[BB] = DFS.PostBlocks.size();
|
||||
}
|
||||
};
|
||||
|
||||
inline bool po_iterator_storage<LoopBlocksTraversal, true>::
|
||||
insertEdge(BasicBlock *From, BasicBlock *To) {
|
||||
return LBT.visitPreorder(To);
|
||||
}
|
||||
|
||||
inline void po_iterator_storage<LoopBlocksTraversal, true>::
|
||||
finishPostorder(BasicBlock *BB) {
|
||||
LBT.finishPostorder(BB);
|
||||
}
|
||||
|
||||
} // End namespace llvm
|
||||
|
||||
#endif
|
||||
160
thirdparty/clang/include/llvm/Analysis/LoopPass.h
vendored
Normal file
160
thirdparty/clang/include/llvm/Analysis/LoopPass.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
//===- LoopPass.h - LoopPass class ----------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines LoopPass class. All loop optimization
|
||||
// and transformation passes are derived from LoopPass.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOOPPASS_H
|
||||
#define LLVM_ANALYSIS_LOOPPASS_H
|
||||
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/PassManagers.h"
|
||||
#include <deque>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LPPassManager;
|
||||
class Function;
|
||||
class PMStack;
|
||||
|
||||
class LoopPass : public Pass {
|
||||
public:
|
||||
explicit LoopPass(char &pid) : Pass(PT_Loop, pid) {}
|
||||
|
||||
/// getPrinterPass - Get a pass to print the function corresponding
|
||||
/// to a Loop.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
// runOnLoop - This method should be implemented by the subclass to perform
|
||||
// whatever action is necessary for the specified Loop.
|
||||
virtual bool runOnLoop(Loop *L, LPPassManager &LPM) = 0;
|
||||
|
||||
using llvm::Pass::doInitialization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
// Initialization and finalization hooks.
|
||||
virtual bool doInitialization(Loop *L, LPPassManager &LPM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finalization hook does not supply Loop because at this time
|
||||
// loop nest is completely different.
|
||||
virtual bool doFinalization() { return false; }
|
||||
|
||||
// Check if this pass is suitable for the current LPPassManager, if
|
||||
// available. This pass P is not suitable for a LPPassManager if P
|
||||
// is not preserving higher level analysis info used by other
|
||||
// LPPassManager passes. In such case, pop LPPassManager from the
|
||||
// stack. This will force assignPassManager() to create new
|
||||
// LPPassManger as expected.
|
||||
void preparePassManager(PMStack &PMS);
|
||||
|
||||
/// Assign pass manager to manage this pass
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_LoopPassManager;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SimpleAnalysis - Provides simple interface to update analysis info
|
||||
/// maintained by various passes. Note, if required this interface can
|
||||
/// be extracted into a separate abstract class but it would require
|
||||
/// additional use of multiple inheritance in Pass class hierarchy, something
|
||||
/// we are trying to avoid.
|
||||
|
||||
/// Each loop pass can override these simple analysis hooks to update
|
||||
/// desired analysis information.
|
||||
/// cloneBasicBlockAnalysis - Clone analysis info associated with basic block.
|
||||
virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {}
|
||||
|
||||
/// deleteAnalysisValue - Delete analysis info associated with value V.
|
||||
virtual void deleteAnalysisValue(Value *V, Loop *L) {}
|
||||
};
|
||||
|
||||
class LPPassManager : public FunctionPass, public PMDataManager {
|
||||
public:
|
||||
static char ID;
|
||||
explicit LPPassManager();
|
||||
|
||||
/// run - Execute all of the passes scheduled for execution. Keep track of
|
||||
/// whether any of the passes modifies the module, and if so, return true.
|
||||
bool runOnFunction(Function &F);
|
||||
|
||||
/// Pass Manager itself does not invalidate any analysis info.
|
||||
// LPPassManager needs LoopInfo.
|
||||
void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "Loop Pass Manager";
|
||||
}
|
||||
|
||||
virtual PMDataManager *getAsPMDataManager() { return this; }
|
||||
virtual Pass *getAsPass() { return this; }
|
||||
|
||||
/// Print passes managed by this manager
|
||||
void dumpPassStructure(unsigned Offset);
|
||||
|
||||
LoopPass *getContainedPass(unsigned N) {
|
||||
assert(N < PassVector.size() && "Pass number out of range!");
|
||||
LoopPass *LP = static_cast<LoopPass *>(PassVector[N]);
|
||||
return LP;
|
||||
}
|
||||
|
||||
virtual PassManagerType getPassManagerType() const {
|
||||
return PMT_LoopPassManager;
|
||||
}
|
||||
|
||||
public:
|
||||
// Delete loop from the loop queue and loop nest (LoopInfo).
|
||||
void deleteLoopFromQueue(Loop *L);
|
||||
|
||||
// Insert loop into the loop queue and add it as a child of the
|
||||
// given parent.
|
||||
void insertLoop(Loop *L, Loop *ParentLoop);
|
||||
|
||||
// Insert a loop into the loop queue.
|
||||
void insertLoopIntoQueue(Loop *L);
|
||||
|
||||
// Reoptimize this loop. LPPassManager will re-insert this loop into the
|
||||
// queue. This allows LoopPass to change loop nest for the loop. This
|
||||
// utility may send LPPassManager into infinite loops so use caution.
|
||||
void redoLoop(Loop *L);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SimpleAnalysis - Provides simple interface to update analysis info
|
||||
/// maintained by various passes. Note, if required this interface can
|
||||
/// be extracted into a separate abstract class but it would require
|
||||
/// additional use of multiple inheritance in Pass class hierarchy, something
|
||||
/// we are trying to avoid.
|
||||
|
||||
/// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for
|
||||
/// all passes that implement simple analysis interface.
|
||||
void cloneBasicBlockSimpleAnalysis(BasicBlock *From, BasicBlock *To, Loop *L);
|
||||
|
||||
/// deleteSimpleAnalysisValue - Invoke deleteAnalysisValue hook for all passes
|
||||
/// that implement simple analysis interface.
|
||||
void deleteSimpleAnalysisValue(Value *V, Loop *L);
|
||||
|
||||
private:
|
||||
std::deque<Loop *> LQ;
|
||||
bool skipThisLoop;
|
||||
bool redoThisLoop;
|
||||
LoopInfo *LI;
|
||||
Loop *CurrentLoop;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
268
thirdparty/clang/include/llvm/Analysis/MemoryBuiltins.h
vendored
Normal file
268
thirdparty/clang/include/llvm/Analysis/MemoryBuiltins.h
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This family of functions identifies calls to builtin functions that allocate
|
||||
// or free memory.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||
#define LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/InstVisitor.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/TargetFolder.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
|
||||
namespace llvm {
|
||||
class CallInst;
|
||||
class PointerType;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
||||
/// like).
|
||||
bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a function that returns a
|
||||
/// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions).
|
||||
bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates uninitialized memory (such as malloc).
|
||||
bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates zero-filled memory (such as calloc).
|
||||
bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// allocates memory (either malloc, calloc, or strdup like).
|
||||
bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
/// \brief Tests if a value is a call or invoke to a library function that
|
||||
/// reallocates memory (such as realloc).
|
||||
bool isReallocLikeFn(const Value *V, const TargetLibraryInfo *TLI,
|
||||
bool LookThroughBitCast = false);
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// malloc Call Utility Functions.
|
||||
//
|
||||
|
||||
/// extractMallocCall - Returns the corresponding CallInst if the instruction
|
||||
/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we
|
||||
/// ignore InvokeInst here.
|
||||
const CallInst *extractMallocCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
static inline CallInst *extractMallocCall(Value *I,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
/// isArrayMalloc - Returns the corresponding CallInst if the instruction
|
||||
/// is a call to malloc whose array size can be determined and the array size
|
||||
/// is not constant 1. Otherwise, return NULL.
|
||||
const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocType - Returns the PointerType resulting from the malloc call.
|
||||
/// The PointerType depends on the number of bitcast uses of the malloc call:
|
||||
/// 0: PointerType is the malloc calls' return type.
|
||||
/// 1: PointerType is the bitcast's result type.
|
||||
/// >1: Unique PointerType cannot be determined, return NULL.
|
||||
PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocAllocatedType - Returns the Type allocated by malloc call.
|
||||
/// The Type depends on the number of bitcast uses of the malloc call:
|
||||
/// 0: PointerType is the malloc calls' return type.
|
||||
/// 1: PointerType is the bitcast's result type.
|
||||
/// >1: Unique PointerType cannot be determined, return NULL.
|
||||
Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI);
|
||||
|
||||
/// getMallocArraySize - Returns the array size of a malloc call. If the
|
||||
/// argument passed to malloc is a multiple of the size of the malloced type,
|
||||
/// then return that multiple. For non-array mallocs, the multiple is
|
||||
/// constant 1. Otherwise, return NULL for mallocs whose array size cannot be
|
||||
/// determined.
|
||||
Value *getMallocArraySize(CallInst *CI, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI,
|
||||
bool LookThroughSExt = false);
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// calloc Call Utility Functions.
|
||||
//
|
||||
|
||||
/// extractCallocCall - Returns the corresponding CallInst if the instruction
|
||||
/// is a calloc call.
|
||||
const CallInst *extractCallocCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
static inline CallInst *extractCallocCall(Value *I,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(extractCallocCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// free Call Utility Functions.
|
||||
//
|
||||
|
||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||
const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI);
|
||||
|
||||
static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
|
||||
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions to compute size of objects.
|
||||
//
|
||||
|
||||
/// \brief Compute the size of the object pointed by Ptr. Returns true and the
|
||||
/// object size in Size if successful, and false otherwise. In this context, by
|
||||
/// object we mean the region of memory starting at Ptr to the end of the
|
||||
/// underlying object pointed to by Ptr.
|
||||
/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas,
|
||||
/// byval arguments, and global variables.
|
||||
bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD,
|
||||
const TargetLibraryInfo *TLI, bool RoundToAlign = false);
|
||||
|
||||
|
||||
|
||||
typedef std::pair<APInt, APInt> SizeOffsetType;
|
||||
|
||||
/// \brief Evaluate the size and offset of an object ponted by a Value*
|
||||
/// statically. Fails if size or offset are not known at compile time.
|
||||
class ObjectSizeOffsetVisitor
|
||||
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
|
||||
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
bool RoundToAlign;
|
||||
unsigned IntTyBits;
|
||||
APInt Zero;
|
||||
SmallPtrSet<Instruction *, 8> SeenInsts;
|
||||
|
||||
APInt align(APInt Size, uint64_t Align);
|
||||
|
||||
SizeOffsetType unknown() {
|
||||
return std::make_pair(APInt(), APInt());
|
||||
}
|
||||
|
||||
public:
|
||||
ObjectSizeOffsetVisitor(const DataLayout *TD, const TargetLibraryInfo *TLI,
|
||||
LLVMContext &Context, bool RoundToAlign = false);
|
||||
|
||||
SizeOffsetType compute(Value *V);
|
||||
|
||||
bool knownSize(SizeOffsetType &SizeOffset) {
|
||||
return SizeOffset.first.getBitWidth() > 1;
|
||||
}
|
||||
|
||||
bool knownOffset(SizeOffsetType &SizeOffset) {
|
||||
return SizeOffset.second.getBitWidth() > 1;
|
||||
}
|
||||
|
||||
bool bothKnown(SizeOffsetType &SizeOffset) {
|
||||
return knownSize(SizeOffset) && knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
SizeOffsetType visitAllocaInst(AllocaInst &I);
|
||||
SizeOffsetType visitArgument(Argument &A);
|
||||
SizeOffsetType visitCallSite(CallSite CS);
|
||||
SizeOffsetType visitConstantPointerNull(ConstantPointerNull&);
|
||||
SizeOffsetType visitExtractElementInst(ExtractElementInst &I);
|
||||
SizeOffsetType visitExtractValueInst(ExtractValueInst &I);
|
||||
SizeOffsetType visitGEPOperator(GEPOperator &GEP);
|
||||
SizeOffsetType visitGlobalAlias(GlobalAlias &GA);
|
||||
SizeOffsetType visitGlobalVariable(GlobalVariable &GV);
|
||||
SizeOffsetType visitIntToPtrInst(IntToPtrInst&);
|
||||
SizeOffsetType visitLoadInst(LoadInst &I);
|
||||
SizeOffsetType visitPHINode(PHINode&);
|
||||
SizeOffsetType visitSelectInst(SelectInst &I);
|
||||
SizeOffsetType visitUndefValue(UndefValue&);
|
||||
SizeOffsetType visitInstruction(Instruction &I);
|
||||
};
|
||||
|
||||
typedef std::pair<Value*, Value*> SizeOffsetEvalType;
|
||||
|
||||
|
||||
/// \brief Evaluate the size and offset of an object ponted by a Value*.
|
||||
/// May create code to compute the result at run-time.
|
||||
class ObjectSizeOffsetEvaluator
|
||||
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
|
||||
|
||||
typedef IRBuilder<true, TargetFolder> BuilderTy;
|
||||
typedef std::pair<WeakVH, WeakVH> WeakEvalType;
|
||||
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
|
||||
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
|
||||
|
||||
const DataLayout *TD;
|
||||
const TargetLibraryInfo *TLI;
|
||||
LLVMContext &Context;
|
||||
BuilderTy Builder;
|
||||
IntegerType *IntTy;
|
||||
Value *Zero;
|
||||
CacheMapTy CacheMap;
|
||||
PtrSetTy SeenVals;
|
||||
|
||||
SizeOffsetEvalType unknown() {
|
||||
return std::make_pair((Value*)0, (Value*)0);
|
||||
}
|
||||
SizeOffsetEvalType compute_(Value *V);
|
||||
|
||||
public:
|
||||
ObjectSizeOffsetEvaluator(const DataLayout *TD, const TargetLibraryInfo *TLI,
|
||||
LLVMContext &Context);
|
||||
SizeOffsetEvalType compute(Value *V);
|
||||
|
||||
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
||||
return SizeOffset.first;
|
||||
}
|
||||
|
||||
bool knownOffset(SizeOffsetEvalType SizeOffset) {
|
||||
return SizeOffset.second;
|
||||
}
|
||||
|
||||
bool anyKnown(SizeOffsetEvalType SizeOffset) {
|
||||
return knownSize(SizeOffset) || knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
bool bothKnown(SizeOffsetEvalType SizeOffset) {
|
||||
return knownSize(SizeOffset) && knownOffset(SizeOffset);
|
||||
}
|
||||
|
||||
SizeOffsetEvalType visitAllocaInst(AllocaInst &I);
|
||||
SizeOffsetEvalType visitCallSite(CallSite CS);
|
||||
SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I);
|
||||
SizeOffsetEvalType visitExtractValueInst(ExtractValueInst &I);
|
||||
SizeOffsetEvalType visitGEPOperator(GEPOperator &GEP);
|
||||
SizeOffsetEvalType visitIntToPtrInst(IntToPtrInst&);
|
||||
SizeOffsetEvalType visitLoadInst(LoadInst &I);
|
||||
SizeOffsetEvalType visitPHINode(PHINode &PHI);
|
||||
SizeOffsetEvalType visitSelectInst(SelectInst &I);
|
||||
SizeOffsetEvalType visitInstruction(Instruction &I);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
445
thirdparty/clang/include/llvm/Analysis/MemoryDependenceAnalysis.h
vendored
Normal file
445
thirdparty/clang/include/llvm/Analysis/MemoryDependenceAnalysis.h
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- 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 MemoryDependenceAnalysis analysis pass.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
|
||||
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
|
||||
namespace llvm {
|
||||
class Function;
|
||||
class FunctionPass;
|
||||
class Instruction;
|
||||
class CallSite;
|
||||
class AliasAnalysis;
|
||||
class DataLayout;
|
||||
class MemoryDependenceAnalysis;
|
||||
class PredIteratorCache;
|
||||
class DominatorTree;
|
||||
class PHITransAddr;
|
||||
|
||||
/// MemDepResult - A memory dependence query can return one of three different
|
||||
/// answers, described below.
|
||||
class MemDepResult {
|
||||
enum DepType {
|
||||
/// Invalid - Clients of MemDep never see this.
|
||||
Invalid = 0,
|
||||
|
||||
/// Clobber - This is a dependence on the specified instruction which
|
||||
/// clobbers the desired value. The pointer member of the MemDepResult
|
||||
/// pair holds the instruction that clobbers the memory. For example,
|
||||
/// this occurs when we see a may-aliased store to the memory location we
|
||||
/// care about.
|
||||
///
|
||||
/// There are several cases that may be interesting here:
|
||||
/// 1. Loads are clobbered by may-alias stores.
|
||||
/// 2. Loads are considered clobbered by partially-aliased loads. The
|
||||
/// client may choose to analyze deeper into these cases.
|
||||
Clobber,
|
||||
|
||||
/// Def - This is a dependence on the specified instruction which
|
||||
/// defines/produces the desired memory location. The pointer member of
|
||||
/// the MemDepResult pair holds the instruction that defines the memory.
|
||||
/// Cases of interest:
|
||||
/// 1. This could be a load or store for dependence queries on
|
||||
/// load/store. The value loaded or stored is the produced value.
|
||||
/// Note that the pointer operand may be different than that of the
|
||||
/// queried pointer due to must aliases and phi translation. Note
|
||||
/// that the def may not be the same type as the query, the pointers
|
||||
/// may just be must aliases.
|
||||
/// 2. For loads and stores, this could be an allocation instruction. In
|
||||
/// this case, the load is loading an undef value or a store is the
|
||||
/// first store to (that part of) the allocation.
|
||||
/// 3. Dependence queries on calls return Def only when they are
|
||||
/// readonly calls or memory use intrinsics with identical callees
|
||||
/// and no intervening clobbers. No validation is done that the
|
||||
/// operands to the calls are the same.
|
||||
Def,
|
||||
|
||||
/// Other - This marker indicates that the query has no known dependency
|
||||
/// in the specified block. More detailed state info is encoded in the
|
||||
/// upper part of the pair (i.e. the Instruction*)
|
||||
Other
|
||||
};
|
||||
/// If DepType is "Other", the upper part of the pair
|
||||
/// (i.e. the Instruction* part) is instead used to encode more detailed
|
||||
/// type information as follows
|
||||
enum OtherType {
|
||||
/// NonLocal - This marker indicates that the query has no dependency in
|
||||
/// the specified block. To find out more, the client should query other
|
||||
/// predecessor blocks.
|
||||
NonLocal = 0x4,
|
||||
/// NonFuncLocal - This marker indicates that the query has no
|
||||
/// dependency in the specified function.
|
||||
NonFuncLocal = 0x8,
|
||||
/// Unknown - This marker indicates that the query dependency
|
||||
/// is unknown.
|
||||
Unknown = 0xc
|
||||
};
|
||||
|
||||
typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
|
||||
PairTy Value;
|
||||
explicit MemDepResult(PairTy V) : Value(V) {}
|
||||
public:
|
||||
MemDepResult() : Value(0, Invalid) {}
|
||||
|
||||
/// get methods: These are static ctor methods for creating various
|
||||
/// MemDepResult kinds.
|
||||
static MemDepResult getDef(Instruction *Inst) {
|
||||
assert(Inst && "Def requires inst");
|
||||
return MemDepResult(PairTy(Inst, Def));
|
||||
}
|
||||
static MemDepResult getClobber(Instruction *Inst) {
|
||||
assert(Inst && "Clobber requires inst");
|
||||
return MemDepResult(PairTy(Inst, Clobber));
|
||||
}
|
||||
static MemDepResult getNonLocal() {
|
||||
return MemDepResult(
|
||||
PairTy(reinterpret_cast<Instruction*>(NonLocal), Other));
|
||||
}
|
||||
static MemDepResult getNonFuncLocal() {
|
||||
return MemDepResult(
|
||||
PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
|
||||
}
|
||||
static MemDepResult getUnknown() {
|
||||
return MemDepResult(
|
||||
PairTy(reinterpret_cast<Instruction*>(Unknown), Other));
|
||||
}
|
||||
|
||||
/// isClobber - Return true if this MemDepResult represents a query that is
|
||||
/// an instruction clobber dependency.
|
||||
bool isClobber() const { return Value.getInt() == Clobber; }
|
||||
|
||||
/// isDef - Return true if this MemDepResult represents a query that is
|
||||
/// an instruction definition dependency.
|
||||
bool isDef() const { return Value.getInt() == Def; }
|
||||
|
||||
/// isNonLocal - Return true if this MemDepResult represents a query that
|
||||
/// is transparent to the start of the block, but where a non-local hasn't
|
||||
/// been done.
|
||||
bool isNonLocal() const {
|
||||
return Value.getInt() == Other
|
||||
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonLocal);
|
||||
}
|
||||
|
||||
/// isNonFuncLocal - Return true if this MemDepResult represents a query
|
||||
/// that is transparent to the start of the function.
|
||||
bool isNonFuncLocal() const {
|
||||
return Value.getInt() == Other
|
||||
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal);
|
||||
}
|
||||
|
||||
/// isUnknown - Return true if this MemDepResult represents a query which
|
||||
/// cannot and/or will not be computed.
|
||||
bool isUnknown() const {
|
||||
return Value.getInt() == Other
|
||||
&& Value.getPointer() == reinterpret_cast<Instruction*>(Unknown);
|
||||
}
|
||||
|
||||
/// getInst() - If this is a normal dependency, return the instruction that
|
||||
/// is depended on. Otherwise, return null.
|
||||
Instruction *getInst() const {
|
||||
if (Value.getInt() == Other) return NULL;
|
||||
return Value.getPointer();
|
||||
}
|
||||
|
||||
bool operator==(const MemDepResult &M) const { return Value == M.Value; }
|
||||
bool operator!=(const MemDepResult &M) const { return Value != M.Value; }
|
||||
bool operator<(const MemDepResult &M) const { return Value < M.Value; }
|
||||
bool operator>(const MemDepResult &M) const { return Value > M.Value; }
|
||||
private:
|
||||
friend class MemoryDependenceAnalysis;
|
||||
/// Dirty - Entries with this marker occur in a LocalDeps map or
|
||||
/// NonLocalDeps map when the instruction they previously referenced was
|
||||
/// removed from MemDep. In either case, the entry may include an
|
||||
/// instruction pointer. If so, the pointer is an instruction in the
|
||||
/// block where scanning can start from, saving some work.
|
||||
///
|
||||
/// In a default-constructed MemDepResult object, the type will be Dirty
|
||||
/// and the instruction pointer will be null.
|
||||
///
|
||||
|
||||
/// isDirty - Return true if this is a MemDepResult in its dirty/invalid.
|
||||
/// state.
|
||||
bool isDirty() const { return Value.getInt() == Invalid; }
|
||||
|
||||
static MemDepResult getDirty(Instruction *Inst) {
|
||||
return MemDepResult(PairTy(Inst, Invalid));
|
||||
}
|
||||
};
|
||||
|
||||
/// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache. For
|
||||
/// each BasicBlock (the BB entry) it keeps a MemDepResult.
|
||||
class NonLocalDepEntry {
|
||||
BasicBlock *BB;
|
||||
MemDepResult Result;
|
||||
public:
|
||||
NonLocalDepEntry(BasicBlock *bb, MemDepResult result)
|
||||
: BB(bb), Result(result) {}
|
||||
|
||||
// This is used for searches.
|
||||
NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
|
||||
|
||||
// BB is the sort key, it can't be changed.
|
||||
BasicBlock *getBB() const { return BB; }
|
||||
|
||||
void setResult(const MemDepResult &R) { Result = R; }
|
||||
|
||||
const MemDepResult &getResult() const { return Result; }
|
||||
|
||||
bool operator<(const NonLocalDepEntry &RHS) const {
|
||||
return BB < RHS.BB;
|
||||
}
|
||||
};
|
||||
|
||||
/// NonLocalDepResult - This is a result from a NonLocal dependence query.
|
||||
/// For each BasicBlock (the BB entry) it keeps a MemDepResult and the
|
||||
/// (potentially phi translated) address that was live in the block.
|
||||
class NonLocalDepResult {
|
||||
NonLocalDepEntry Entry;
|
||||
Value *Address;
|
||||
public:
|
||||
NonLocalDepResult(BasicBlock *bb, MemDepResult result, Value *address)
|
||||
: Entry(bb, result), Address(address) {}
|
||||
|
||||
// BB is the sort key, it can't be changed.
|
||||
BasicBlock *getBB() const { return Entry.getBB(); }
|
||||
|
||||
void setResult(const MemDepResult &R, Value *Addr) {
|
||||
Entry.setResult(R);
|
||||
Address = Addr;
|
||||
}
|
||||
|
||||
const MemDepResult &getResult() const { return Entry.getResult(); }
|
||||
|
||||
/// getAddress - Return the address of this pointer in this block. This can
|
||||
/// be different than the address queried for the non-local result because
|
||||
/// of phi translation. This returns null if the address was not available
|
||||
/// in a block (i.e. because phi translation failed) or if this is a cached
|
||||
/// result and that address was deleted.
|
||||
///
|
||||
/// The address is always null for a non-local 'call' dependence.
|
||||
Value *getAddress() const { return Address; }
|
||||
};
|
||||
|
||||
/// MemoryDependenceAnalysis - This is an analysis that determines, for a
|
||||
/// given memory operation, what preceding memory operations it depends on.
|
||||
/// It builds on alias analysis information, and tries to provide a lazy,
|
||||
/// caching interface to a common kind of alias information query.
|
||||
///
|
||||
/// The dependency information returned is somewhat unusual, but is pragmatic.
|
||||
/// If queried about a store or call that might modify memory, the analysis
|
||||
/// will return the instruction[s] that may either load from that memory or
|
||||
/// store to it. If queried with a load or call that can never modify memory,
|
||||
/// the analysis will return calls and stores that might modify the pointer,
|
||||
/// but generally does not return loads unless a) they are volatile, or
|
||||
/// b) they load from *must-aliased* pointers. Returning a dependence on
|
||||
/// must-alias'd pointers instead of all pointers interacts well with the
|
||||
/// internal caching mechanism.
|
||||
///
|
||||
class MemoryDependenceAnalysis : public FunctionPass {
|
||||
// A map from instructions to their dependency.
|
||||
typedef DenseMap<Instruction*, MemDepResult> LocalDepMapType;
|
||||
LocalDepMapType LocalDeps;
|
||||
|
||||
public:
|
||||
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
|
||||
private:
|
||||
/// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if
|
||||
/// the dependence is a read only dependence, false if read/write.
|
||||
typedef PointerIntPair<const Value*, 1, bool> ValueIsLoadPair;
|
||||
|
||||
/// BBSkipFirstBlockPair - This pair is used when caching information for a
|
||||
/// block. If the pointer is null, the cache value is not a full query that
|
||||
/// starts at the specified block. If non-null, the bool indicates whether
|
||||
/// or not the contents of the block was skipped.
|
||||
typedef PointerIntPair<BasicBlock*, 1, bool> BBSkipFirstBlockPair;
|
||||
|
||||
/// NonLocalPointerInfo - This record is the information kept for each
|
||||
/// (value, is load) pair.
|
||||
struct NonLocalPointerInfo {
|
||||
/// Pair - The pair of the block and the skip-first-block flag.
|
||||
BBSkipFirstBlockPair Pair;
|
||||
/// NonLocalDeps - The results of the query for each relevant block.
|
||||
NonLocalDepInfo NonLocalDeps;
|
||||
/// Size - The maximum size of the dereferences of the
|
||||
/// pointer. May be UnknownSize if the sizes are unknown.
|
||||
uint64_t Size;
|
||||
/// TBAATag - The TBAA tag associated with dereferences of the
|
||||
/// pointer. May be null if there are no tags or conflicting tags.
|
||||
const MDNode *TBAATag;
|
||||
|
||||
NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {}
|
||||
};
|
||||
|
||||
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
|
||||
/// a pointer lookup at the bottom of a block. The key of this map is the
|
||||
/// pointer+isload bit, the value is a list of <bb->result> mappings.
|
||||
typedef DenseMap<ValueIsLoadPair,
|
||||
NonLocalPointerInfo> CachedNonLocalPointerInfo;
|
||||
CachedNonLocalPointerInfo NonLocalPointerDeps;
|
||||
|
||||
// A map from instructions to their non-local pointer dependencies.
|
||||
typedef DenseMap<Instruction*,
|
||||
SmallPtrSet<ValueIsLoadPair, 4> > ReverseNonLocalPtrDepTy;
|
||||
ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
|
||||
|
||||
|
||||
/// PerInstNLInfo - This is the instruction we keep for each cached access
|
||||
/// that we have for an instruction. The pointer is an owning pointer and
|
||||
/// the bool indicates whether we have any dirty bits in the set.
|
||||
typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
|
||||
|
||||
// A map from instructions to their non-local dependencies.
|
||||
typedef DenseMap<Instruction*, PerInstNLInfo> NonLocalDepMapType;
|
||||
|
||||
NonLocalDepMapType NonLocalDeps;
|
||||
|
||||
// A reverse mapping from dependencies to the dependees. This is
|
||||
// used when removing instructions to keep the cache coherent.
|
||||
typedef DenseMap<Instruction*,
|
||||
SmallPtrSet<Instruction*, 4> > ReverseDepMapType;
|
||||
ReverseDepMapType ReverseLocalDeps;
|
||||
|
||||
// A reverse mapping from dependencies to the non-local dependees.
|
||||
ReverseDepMapType ReverseNonLocalDeps;
|
||||
|
||||
/// Current AA implementation, just a cache.
|
||||
AliasAnalysis *AA;
|
||||
DataLayout *TD;
|
||||
DominatorTree *DT;
|
||||
OwningPtr<PredIteratorCache> PredCache;
|
||||
public:
|
||||
MemoryDependenceAnalysis();
|
||||
~MemoryDependenceAnalysis();
|
||||
static char ID;
|
||||
|
||||
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
|
||||
bool runOnFunction(Function &);
|
||||
|
||||
/// Clean up memory in between runs
|
||||
void releaseMemory();
|
||||
|
||||
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering
|
||||
/// and Alias Analysis.
|
||||
///
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
/// getDependency - Return the instruction on which a memory operation
|
||||
/// depends. See the class comment for more details. It is illegal to call
|
||||
/// this on non-memory instructions.
|
||||
MemDepResult getDependency(Instruction *QueryInst);
|
||||
|
||||
/// getNonLocalCallDependency - Perform a full dependency query for the
|
||||
/// specified call, returning the set of blocks that the value is
|
||||
/// potentially live across. The returned set of results will include a
|
||||
/// "NonLocal" result for all blocks where the value is live across.
|
||||
///
|
||||
/// This method assumes the instruction returns a "NonLocal" dependency
|
||||
/// within its own block.
|
||||
///
|
||||
/// This returns a reference to an internal data structure that may be
|
||||
/// invalidated on the next non-local query or when an instruction is
|
||||
/// removed. Clients must copy this data if they want it around longer than
|
||||
/// that.
|
||||
const NonLocalDepInfo &getNonLocalCallDependency(CallSite QueryCS);
|
||||
|
||||
|
||||
/// getNonLocalPointerDependency - Perform a full dependency query for an
|
||||
/// access to the specified (non-volatile) memory location, returning the
|
||||
/// set of instructions that either define or clobber the value.
|
||||
///
|
||||
/// This method assumes the pointer has a "NonLocal" dependency within BB.
|
||||
void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
SmallVectorImpl<NonLocalDepResult> &Result);
|
||||
|
||||
/// removeInstruction - Remove an instruction from the dependence analysis,
|
||||
/// updating the dependence of instructions that previously depended on it.
|
||||
void removeInstruction(Instruction *InstToRemove);
|
||||
|
||||
/// invalidateCachedPointerInfo - This method is used to invalidate cached
|
||||
/// information about the specified pointer, because it may be too
|
||||
/// conservative in memdep. This is an optional call that can be used when
|
||||
/// the client detects an equivalence between the pointer and some other
|
||||
/// value and replaces the other value with ptr. This can make Ptr available
|
||||
/// in more places that cached info does not necessarily keep.
|
||||
void invalidateCachedPointerInfo(Value *Ptr);
|
||||
|
||||
/// invalidateCachedPredecessors - Clear the PredIteratorCache info.
|
||||
/// This needs to be done when the CFG changes, e.g., due to splitting
|
||||
/// critical edges.
|
||||
void invalidateCachedPredecessors();
|
||||
|
||||
/// getPointerDependencyFrom - Return the instruction on which a memory
|
||||
/// location depends. If isLoad is true, this routine ignores may-aliases
|
||||
/// with read-only operations. If isLoad is false, this routine ignores
|
||||
/// may-aliases with reads from read-only locations. If possible, pass
|
||||
/// the query instruction as well; this function may take advantage of
|
||||
/// the metadata annotated to the query instruction to refine the result.
|
||||
///
|
||||
/// Note that this is an uncached query, and thus may be inefficient.
|
||||
///
|
||||
MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
|
||||
bool isLoad,
|
||||
BasicBlock::iterator ScanIt,
|
||||
BasicBlock *BB,
|
||||
Instruction *QueryInst = 0);
|
||||
|
||||
|
||||
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
|
||||
/// looks at a memory location for a load (specified by MemLocBase, Offs,
|
||||
/// and Size) and compares it against a load. If the specified load could
|
||||
/// be safely widened to a larger integer load that is 1) still efficient,
|
||||
/// 2) safe for the target, and 3) would provide the specified memory
|
||||
/// location value, then this function returns the size in bytes of the
|
||||
/// load width to use. If not, this returns zero.
|
||||
static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase,
|
||||
int64_t MemLocOffs,
|
||||
unsigned MemLocSize,
|
||||
const LoadInst *LI,
|
||||
const DataLayout &TD);
|
||||
|
||||
private:
|
||||
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
|
||||
BasicBlock::iterator ScanIt,
|
||||
BasicBlock *BB);
|
||||
bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer,
|
||||
const AliasAnalysis::Location &Loc,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
SmallVectorImpl<NonLocalDepResult> &Result,
|
||||
DenseMap<BasicBlock*, Value*> &Visited,
|
||||
bool SkipFirstBlock = false);
|
||||
MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
NonLocalDepInfo *Cache,
|
||||
unsigned NumSortedEntries);
|
||||
|
||||
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
|
||||
|
||||
/// verifyRemoved - Verify that the specified instruction does not occur
|
||||
/// in our internal data structures.
|
||||
void verifyRemoved(Instruction *Inst) const;
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
121
thirdparty/clang/include/llvm/Analysis/PHITransAddr.h
vendored
Normal file
121
thirdparty/clang/include/llvm/Analysis/PHITransAddr.h
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
//===- PHITransAddr.h - PHI Translation for Addresses -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the PHITransAddr class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PHITRANSADDR_H
|
||||
#define LLVM_ANALYSIS_PHITRANSADDR_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
|
||||
namespace llvm {
|
||||
class DominatorTree;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
|
||||
/// PHITransAddr - An address value which tracks and handles phi translation.
|
||||
/// As we walk "up" the CFG through predecessors, we need to ensure that the
|
||||
/// address we're tracking is kept up to date. For example, if we're analyzing
|
||||
/// an address of "&A[i]" and walk through the definition of 'i' which is a PHI
|
||||
/// node, we *must* phi translate i to get "&A[j]" or else we will analyze an
|
||||
/// incorrect pointer in the predecessor block.
|
||||
///
|
||||
/// This is designed to be a relatively small object that lives on the stack and
|
||||
/// is copyable.
|
||||
///
|
||||
class PHITransAddr {
|
||||
/// Addr - The actual address we're analyzing.
|
||||
Value *Addr;
|
||||
|
||||
/// TD - The target data we are playing with if known, otherwise null.
|
||||
const DataLayout *TD;
|
||||
|
||||
/// TLI - The target library info if known, otherwise null.
|
||||
const TargetLibraryInfo *TLI;
|
||||
|
||||
/// InstInputs - The inputs for our symbolic address.
|
||||
SmallVector<Instruction*, 4> InstInputs;
|
||||
public:
|
||||
PHITransAddr(Value *addr, const DataLayout *td) : Addr(addr), TD(td), TLI(0) {
|
||||
// If the address is an instruction, the whole thing is considered an input.
|
||||
if (Instruction *I = dyn_cast<Instruction>(Addr))
|
||||
InstInputs.push_back(I);
|
||||
}
|
||||
|
||||
Value *getAddr() const { return Addr; }
|
||||
|
||||
/// NeedsPHITranslationFromBlock - Return true if moving from the specified
|
||||
/// BasicBlock to its predecessors requires PHI translation.
|
||||
bool NeedsPHITranslationFromBlock(BasicBlock *BB) const {
|
||||
// We do need translation if one of our input instructions is defined in
|
||||
// this block.
|
||||
for (unsigned i = 0, e = InstInputs.size(); i != e; ++i)
|
||||
if (InstInputs[i]->getParent() == BB)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// IsPotentiallyPHITranslatable - If this needs PHI translation, return true
|
||||
/// if we have some hope of doing it. This should be used as a filter to
|
||||
/// avoid calling PHITranslateValue in hopeless situations.
|
||||
bool IsPotentiallyPHITranslatable() const;
|
||||
|
||||
/// PHITranslateValue - PHI translate the current address up the CFG from
|
||||
/// CurBB to Pred, updating our state to reflect any needed changes. If the
|
||||
/// dominator tree DT is non-null, the translated value must dominate
|
||||
/// PredBB. This returns true on failure and sets Addr to null.
|
||||
bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree *DT);
|
||||
|
||||
/// PHITranslateWithInsertion - PHI translate this value into the specified
|
||||
/// predecessor block, inserting a computation of the value if it is
|
||||
/// unavailable.
|
||||
///
|
||||
/// All newly created instructions are added to the NewInsts list. This
|
||||
/// returns null on failure.
|
||||
///
|
||||
Value *PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts);
|
||||
|
||||
void dump() const;
|
||||
|
||||
/// Verify - Check internal consistency of this data structure. If the
|
||||
/// structure is valid, it returns true. If invalid, it prints errors and
|
||||
/// returns false.
|
||||
bool Verify() const;
|
||||
private:
|
||||
Value *PHITranslateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree *DT);
|
||||
|
||||
/// InsertPHITranslatedSubExpr - Insert a computation of the PHI translated
|
||||
/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
|
||||
/// block. All newly created instructions are added to the NewInsts list.
|
||||
/// This returns null on failure.
|
||||
///
|
||||
Value *InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB,
|
||||
BasicBlock *PredBB, const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts);
|
||||
|
||||
/// AddAsInput - If the specified value is an instruction, add it as an input.
|
||||
Value *AddAsInput(Value *V) {
|
||||
// If V is an instruction, it is now an input.
|
||||
if (Instruction *VI = dyn_cast<Instruction>(V))
|
||||
InstInputs.push_back(VI);
|
||||
return V;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
219
thirdparty/clang/include/llvm/Analysis/Passes.h
vendored
Normal file
219
thirdparty/clang/include/llvm/Analysis/Passes.h
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
//===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header file defines prototypes for accessor functions that expose passes
|
||||
// in the analysis libraries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PASSES_H
|
||||
#define LLVM_ANALYSIS_PASSES_H
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
class ImmutablePass;
|
||||
class LoopPass;
|
||||
class ModulePass;
|
||||
class Pass;
|
||||
class PassInfo;
|
||||
class LibCallInfo;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createGlobalsModRefPass - This pass provides alias and mod/ref info for
|
||||
// global values that do not have their addresses taken.
|
||||
//
|
||||
Pass *createGlobalsModRefPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createAliasDebugger - This pass helps debug clients of AA
|
||||
//
|
||||
Pass *createAliasDebugger();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createAliasAnalysisCounterPass - This pass counts alias queries and how the
|
||||
// alias analysis implementation responds.
|
||||
//
|
||||
ModulePass *createAliasAnalysisCounterPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createAAEvalPass - This pass implements a simple N^2 alias analysis
|
||||
// accuracy evaluator.
|
||||
//
|
||||
FunctionPass *createAAEvalPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createNoAAPass - This pass implements a "I don't know" alias analysis.
|
||||
//
|
||||
ImmutablePass *createNoAAPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createBasicAliasAnalysisPass - This pass implements the stateless alias
|
||||
// analysis.
|
||||
//
|
||||
ImmutablePass *createBasicAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
/// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows
|
||||
/// about the semantics of a set of libcalls specified by LCI. The newly
|
||||
/// constructed pass takes ownership of the pointer that is provided.
|
||||
///
|
||||
FunctionPass *createLibCallAliasAnalysisPass(LibCallInfo *LCI);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createScalarEvolutionAliasAnalysisPass - This pass implements a simple
|
||||
// alias analysis using ScalarEvolution queries.
|
||||
//
|
||||
FunctionPass *createScalarEvolutionAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createTypeBasedAliasAnalysisPass - This pass implements metadata-based
|
||||
// type-based alias analysis.
|
||||
//
|
||||
ImmutablePass *createTypeBasedAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based
|
||||
// alias analysis.
|
||||
//
|
||||
ImmutablePass *createObjCARCAliasAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createProfileLoaderPass - This pass loads information from a profile dump
|
||||
// file.
|
||||
//
|
||||
ModulePass *createProfileLoaderPass();
|
||||
extern char &ProfileLoaderPassID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createProfileMetadataLoaderPass - This pass loads information from a
|
||||
// profile dump file and sets branch weight metadata.
|
||||
//
|
||||
ModulePass *createProfileMetadataLoaderPass();
|
||||
extern char &ProfileMetadataLoaderPassID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createNoProfileInfoPass - This pass implements the default "no profile".
|
||||
//
|
||||
ImmutablePass *createNoProfileInfoPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createProfileEstimatorPass - This pass estimates profiling information
|
||||
// instead of loading it from a previous run.
|
||||
//
|
||||
FunctionPass *createProfileEstimatorPass();
|
||||
extern char &ProfileEstimatorPassID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createProfileVerifierPass - This pass verifies profiling information.
|
||||
//
|
||||
FunctionPass *createProfileVerifierPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createPathProfileLoaderPass - This pass loads information from a path
|
||||
// profile dump file.
|
||||
//
|
||||
ModulePass *createPathProfileLoaderPass();
|
||||
extern char &PathProfileLoaderPassID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createNoPathProfileInfoPass - This pass implements the default
|
||||
// "no path profile".
|
||||
//
|
||||
ImmutablePass *createNoPathProfileInfoPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createPathProfileVerifierPass - This pass verifies path profiling
|
||||
// information.
|
||||
//
|
||||
ModulePass *createPathProfileVerifierPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createDSAAPass - This pass implements simple context sensitive alias
|
||||
// analysis.
|
||||
//
|
||||
ModulePass *createDSAAPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createDSOptPass - This pass uses DSA to do a series of simple
|
||||
// optimizations.
|
||||
//
|
||||
ModulePass *createDSOptPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createSteensgaardPass - This pass uses the data structure graphs to do a
|
||||
// simple context insensitive alias analysis.
|
||||
//
|
||||
ModulePass *createSteensgaardPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
/// createLazyValueInfoPass - This creates an instance of the LazyValueInfo
|
||||
/// pass.
|
||||
FunctionPass *createLazyValueInfoPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createDependenceAnalysisPass - This creates an instance of the
|
||||
// DependenceAnalysis pass.
|
||||
//
|
||||
FunctionPass *createDependenceAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createCostModelAnalysisPass - This creates an instance of the
|
||||
// CostModelAnalysis pass.
|
||||
//
|
||||
FunctionPass *createCostModelAnalysisPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// Minor pass prototypes, allowing us to expose them through bugpoint and
|
||||
// analyze.
|
||||
FunctionPass *createInstCountPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createRegionInfoPass - This pass finds all single entry single exit regions
|
||||
// in a function and builds the region hierarchy.
|
||||
//
|
||||
FunctionPass *createRegionInfoPass();
|
||||
|
||||
// Print module-level debug info metadata in human-readable form.
|
||||
ModulePass *createModuleDebugInfoPrinterPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createMemDepPrinter - This pass exhaustively collects all memdep
|
||||
// information and prints it with -analyze.
|
||||
//
|
||||
FunctionPass *createMemDepPrinter();
|
||||
}
|
||||
|
||||
#endif
|
||||
304
thirdparty/clang/include/llvm/Analysis/PathNumbering.h
vendored
Normal file
304
thirdparty/clang/include/llvm/Analysis/PathNumbering.h
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
//===- PathNumbering.h ----------------------------------------*- C++ -*---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Ball-Larus path numbers uniquely identify paths through a directed acyclic
|
||||
// graph (DAG) [Ball96]. For a CFG backedges are removed and replaced by phony
|
||||
// edges to obtain a DAG, and thus the unique path numbers [Ball96].
|
||||
//
|
||||
// The purpose of this analysis is to enumerate the edges in a CFG in order
|
||||
// to obtain paths from path numbers in a convenient manner. As described in
|
||||
// [Ball96] edges can be enumerated such that given a path number by following
|
||||
// the CFG and updating the path number, the path is obtained.
|
||||
//
|
||||
// [Ball96]
|
||||
// T. Ball and J. R. Larus. "Efficient Path Profiling."
|
||||
// International Symposium on Microarchitecture, pages 46-57, 1996.
|
||||
// http://portal.acm.org/citation.cfm?id=243857
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PATHNUMBERING_H
|
||||
#define LLVM_ANALYSIS_PATHNUMBERING_H
|
||||
|
||||
#include "llvm/Analysis/ProfileInfoTypes.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class BallLarusNode;
|
||||
class BallLarusEdge;
|
||||
class BallLarusDag;
|
||||
|
||||
// typedefs for storage/ interators of various DAG components
|
||||
typedef std::vector<BallLarusNode*> BLNodeVector;
|
||||
typedef std::vector<BallLarusNode*>::iterator BLNodeIterator;
|
||||
typedef std::vector<BallLarusEdge*> BLEdgeVector;
|
||||
typedef std::vector<BallLarusEdge*>::iterator BLEdgeIterator;
|
||||
typedef std::map<BasicBlock*, BallLarusNode*> BLBlockNodeMap;
|
||||
typedef std::stack<BallLarusNode*> BLNodeStack;
|
||||
|
||||
// Represents a basic block with information necessary for the BallLarus
|
||||
// algorithms.
|
||||
class BallLarusNode {
|
||||
public:
|
||||
enum NodeColor { WHITE, GRAY, BLACK };
|
||||
|
||||
// Constructor: Initializes a new Node for the given BasicBlock
|
||||
BallLarusNode(BasicBlock* BB) :
|
||||
_basicBlock(BB), _numberPaths(0), _color(WHITE) {
|
||||
static unsigned nextUID = 0;
|
||||
_uid = nextUID++;
|
||||
}
|
||||
|
||||
// Returns the basic block for the BallLarusNode
|
||||
BasicBlock* getBlock();
|
||||
|
||||
// Get/set the number of paths to the exit starting at the node.
|
||||
unsigned getNumberPaths();
|
||||
void setNumberPaths(unsigned numberPaths);
|
||||
|
||||
// Get/set the NodeColor used in graph algorithms.
|
||||
NodeColor getColor();
|
||||
void setColor(NodeColor color);
|
||||
|
||||
// Iterator information for predecessor edges. Includes phony and
|
||||
// backedges.
|
||||
BLEdgeIterator predBegin();
|
||||
BLEdgeIterator predEnd();
|
||||
unsigned getNumberPredEdges();
|
||||
|
||||
// Iterator information for successor edges. Includes phony and
|
||||
// backedges.
|
||||
BLEdgeIterator succBegin();
|
||||
BLEdgeIterator succEnd();
|
||||
unsigned getNumberSuccEdges();
|
||||
|
||||
// Add an edge to the predecessor list.
|
||||
void addPredEdge(BallLarusEdge* edge);
|
||||
|
||||
// Remove an edge from the predecessor list.
|
||||
void removePredEdge(BallLarusEdge* edge);
|
||||
|
||||
// Add an edge to the successor list.
|
||||
void addSuccEdge(BallLarusEdge* edge);
|
||||
|
||||
// Remove an edge from the successor list.
|
||||
void removeSuccEdge(BallLarusEdge* edge);
|
||||
|
||||
// Returns the name of the BasicBlock being represented. If BasicBlock
|
||||
// is null then returns "<null>". If BasicBlock has no name, then
|
||||
// "<unnamed>" is returned. Intended for use with debug output.
|
||||
std::string getName();
|
||||
|
||||
private:
|
||||
// The corresponding underlying BB.
|
||||
BasicBlock* _basicBlock;
|
||||
|
||||
// Holds the predecessor edges of this node.
|
||||
BLEdgeVector _predEdges;
|
||||
|
||||
// Holds the successor edges of this node.
|
||||
BLEdgeVector _succEdges;
|
||||
|
||||
// The number of paths from the node to the exit.
|
||||
unsigned _numberPaths;
|
||||
|
||||
// 'Color' used by graph algorithms to mark the node.
|
||||
NodeColor _color;
|
||||
|
||||
// Unique ID to ensure naming difference with dotgraphs
|
||||
unsigned _uid;
|
||||
|
||||
// Removes an edge from an edgeVector. Used by removePredEdge and
|
||||
// removeSuccEdge.
|
||||
void removeEdge(BLEdgeVector& v, BallLarusEdge* e);
|
||||
};
|
||||
|
||||
// Represents an edge in the Dag. For an edge, v -> w, v is the source, and
|
||||
// w is the target.
|
||||
class BallLarusEdge {
|
||||
public:
|
||||
enum EdgeType { NORMAL, BACKEDGE, SPLITEDGE,
|
||||
BACKEDGE_PHONY, SPLITEDGE_PHONY, CALLEDGE_PHONY };
|
||||
|
||||
// Constructor: Initializes an BallLarusEdge with a source and target.
|
||||
BallLarusEdge(BallLarusNode* source, BallLarusNode* target,
|
||||
unsigned duplicateNumber)
|
||||
: _source(source), _target(target), _weight(0), _edgeType(NORMAL),
|
||||
_realEdge(NULL), _duplicateNumber(duplicateNumber) {}
|
||||
|
||||
// Returns the source/ target node of this edge.
|
||||
BallLarusNode* getSource() const;
|
||||
BallLarusNode* getTarget() const;
|
||||
|
||||
// Sets the type of the edge.
|
||||
EdgeType getType() const;
|
||||
|
||||
// Gets the type of the edge.
|
||||
void setType(EdgeType type);
|
||||
|
||||
// Returns the weight of this edge. Used to decode path numbers to
|
||||
// sequences of basic blocks.
|
||||
unsigned getWeight();
|
||||
|
||||
// Sets the weight of the edge. Used during path numbering.
|
||||
void setWeight(unsigned weight);
|
||||
|
||||
// Gets/sets the phony edge originating at the root.
|
||||
BallLarusEdge* getPhonyRoot();
|
||||
void setPhonyRoot(BallLarusEdge* phonyRoot);
|
||||
|
||||
// Gets/sets the phony edge terminating at the exit.
|
||||
BallLarusEdge* getPhonyExit();
|
||||
void setPhonyExit(BallLarusEdge* phonyExit);
|
||||
|
||||
// Gets/sets the associated real edge if this is a phony edge.
|
||||
BallLarusEdge* getRealEdge();
|
||||
void setRealEdge(BallLarusEdge* realEdge);
|
||||
|
||||
// Returns the duplicate number of the edge.
|
||||
unsigned getDuplicateNumber();
|
||||
|
||||
protected:
|
||||
// Source node for this edge.
|
||||
BallLarusNode* _source;
|
||||
|
||||
// Target node for this edge.
|
||||
BallLarusNode* _target;
|
||||
|
||||
private:
|
||||
// Edge weight cooresponding to path number increments before removing
|
||||
// increments along a spanning tree. The sum over the edge weights gives
|
||||
// the path number.
|
||||
unsigned _weight;
|
||||
|
||||
// Type to represent for what this edge is intended
|
||||
EdgeType _edgeType;
|
||||
|
||||
// For backedges and split-edges, the phony edge which is linked to the
|
||||
// root node of the DAG. This contains a path number initialization.
|
||||
BallLarusEdge* _phonyRoot;
|
||||
|
||||
// For backedges and split-edges, the phony edge which is linked to the
|
||||
// exit node of the DAG. This contains a path counter increment, and
|
||||
// potentially a path number increment.
|
||||
BallLarusEdge* _phonyExit;
|
||||
|
||||
// If this is a phony edge, _realEdge is a link to the back or split
|
||||
// edge. Otherwise, this is null.
|
||||
BallLarusEdge* _realEdge;
|
||||
|
||||
// An ID to differentiate between those edges which have the same source
|
||||
// and destination blocks.
|
||||
unsigned _duplicateNumber;
|
||||
};
|
||||
|
||||
// Represents the Ball Larus DAG for a given Function. Can calculate
|
||||
// various properties required for instrumentation or analysis. E.g. the
|
||||
// edge weights that determine the path number.
|
||||
class BallLarusDag {
|
||||
public:
|
||||
// Initializes a BallLarusDag from the CFG of a given function. Must
|
||||
// call init() after creation, since some initialization requires
|
||||
// virtual functions.
|
||||
BallLarusDag(Function &F)
|
||||
: _root(NULL), _exit(NULL), _function(F) {}
|
||||
|
||||
// Initialization that requires virtual functions which are not fully
|
||||
// functional in the constructor.
|
||||
void init();
|
||||
|
||||
// Frees all memory associated with the DAG.
|
||||
virtual ~BallLarusDag();
|
||||
|
||||
// Calculate the path numbers by assigning edge increments as prescribed
|
||||
// in Ball-Larus path profiling.
|
||||
void calculatePathNumbers();
|
||||
|
||||
// Returns the number of paths for the DAG.
|
||||
unsigned getNumberOfPaths();
|
||||
|
||||
// Returns the root (i.e. entry) node for the DAG.
|
||||
BallLarusNode* getRoot();
|
||||
|
||||
// Returns the exit node for the DAG.
|
||||
BallLarusNode* getExit();
|
||||
|
||||
// Returns the function for the DAG.
|
||||
Function& getFunction();
|
||||
|
||||
// Clears the node colors.
|
||||
void clearColors(BallLarusNode::NodeColor color);
|
||||
|
||||
protected:
|
||||
// All nodes in the DAG.
|
||||
BLNodeVector _nodes;
|
||||
|
||||
// All edges in the DAG.
|
||||
BLEdgeVector _edges;
|
||||
|
||||
// All backedges in the DAG.
|
||||
BLEdgeVector _backEdges;
|
||||
|
||||
// Allows subclasses to determine which type of Node is created.
|
||||
// Override this method to produce subclasses of BallLarusNode if
|
||||
// necessary. The destructor of BallLarusDag will call free on each pointer
|
||||
// created.
|
||||
virtual BallLarusNode* createNode(BasicBlock* BB);
|
||||
|
||||
// Allows subclasses to determine which type of Edge is created.
|
||||
// Override this method to produce subclasses of BallLarusEdge if
|
||||
// necessary. Parameters source and target will have been created by
|
||||
// createNode and can be cast to the subclass of BallLarusNode*
|
||||
// returned by createNode. The destructor of BallLarusDag will call free
|
||||
// on each pointer created.
|
||||
virtual BallLarusEdge* createEdge(BallLarusNode* source, BallLarusNode*
|
||||
target, unsigned duplicateNumber);
|
||||
|
||||
// Proxy to node's constructor. Updates the DAG state.
|
||||
BallLarusNode* addNode(BasicBlock* BB);
|
||||
|
||||
// Proxy to edge's constructor. Updates the DAG state.
|
||||
BallLarusEdge* addEdge(BallLarusNode* source, BallLarusNode* target,
|
||||
unsigned duplicateNumber);
|
||||
|
||||
private:
|
||||
// The root (i.e. entry) node for this DAG.
|
||||
BallLarusNode* _root;
|
||||
|
||||
// The exit node for this DAG.
|
||||
BallLarusNode* _exit;
|
||||
|
||||
// The function represented by this DAG.
|
||||
Function& _function;
|
||||
|
||||
// Processes one node and its imediate edges for building the DAG.
|
||||
void buildNode(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack);
|
||||
|
||||
// Process an edge in the CFG for DAG building.
|
||||
void buildEdge(BLBlockNodeMap& inDag, std::stack<BallLarusNode*>& dfsStack,
|
||||
BallLarusNode* currentNode, BasicBlock* succBB,
|
||||
unsigned duplicateNumber);
|
||||
|
||||
// The weight on each edge is the increment required along any path that
|
||||
// contains that edge.
|
||||
void calculatePathNumbersFrom(BallLarusNode* node);
|
||||
|
||||
// Adds a backedge with its phony edges. Updates the DAG state.
|
||||
void addBackedge(BallLarusNode* source, BallLarusNode* target,
|
||||
unsigned duplicateCount);
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
112
thirdparty/clang/include/llvm/Analysis/PathProfileInfo.h
vendored
Normal file
112
thirdparty/clang/include/llvm/Analysis/PathProfileInfo.h
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
//===- PathProfileInfo.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 outlines the interface used by optimizers to load path profiles.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PATHPROFILEINFO_H
|
||||
#define LLVM_ANALYSIS_PATHPROFILEINFO_H
|
||||
|
||||
#include "llvm/Analysis/PathNumbering.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ProfilePath;
|
||||
class ProfilePathEdge;
|
||||
class PathProfileInfo;
|
||||
|
||||
typedef std::vector<ProfilePathEdge> ProfilePathEdgeVector;
|
||||
typedef std::vector<ProfilePathEdge>::iterator ProfilePathEdgeIterator;
|
||||
|
||||
typedef std::vector<BasicBlock*> ProfilePathBlockVector;
|
||||
typedef std::vector<BasicBlock*>::iterator ProfilePathBlockIterator;
|
||||
|
||||
typedef std::map<unsigned int,ProfilePath*> ProfilePathMap;
|
||||
typedef std::map<unsigned int,ProfilePath*>::iterator ProfilePathIterator;
|
||||
|
||||
typedef std::map<Function*,unsigned int> FunctionPathCountMap;
|
||||
typedef std::map<Function*,ProfilePathMap> FunctionPathMap;
|
||||
typedef std::map<Function*,ProfilePathMap>::iterator FunctionPathIterator;
|
||||
|
||||
class ProfilePathEdge {
|
||||
public:
|
||||
ProfilePathEdge(BasicBlock* source, BasicBlock* target,
|
||||
unsigned duplicateNumber);
|
||||
|
||||
inline unsigned getDuplicateNumber() { return _duplicateNumber; }
|
||||
inline BasicBlock* getSource() { return _source; }
|
||||
inline BasicBlock* getTarget() { return _target; }
|
||||
|
||||
protected:
|
||||
BasicBlock* _source;
|
||||
BasicBlock* _target;
|
||||
unsigned _duplicateNumber;
|
||||
};
|
||||
|
||||
class ProfilePath {
|
||||
public:
|
||||
ProfilePath(unsigned int number, unsigned int count,
|
||||
double countStdDev, PathProfileInfo* ppi);
|
||||
|
||||
double getFrequency() const;
|
||||
|
||||
inline unsigned int getNumber() const { return _number; }
|
||||
inline unsigned int getCount() const { return _count; }
|
||||
inline double getCountStdDev() const { return _countStdDev; }
|
||||
|
||||
ProfilePathEdgeVector* getPathEdges() const;
|
||||
ProfilePathBlockVector* getPathBlocks() const;
|
||||
|
||||
BasicBlock* getFirstBlockInPath() const;
|
||||
|
||||
private:
|
||||
unsigned int _number;
|
||||
unsigned int _count;
|
||||
double _countStdDev;
|
||||
|
||||
// double pointer back to the profiling info
|
||||
PathProfileInfo* _ppi;
|
||||
};
|
||||
|
||||
// TODO: overload [] operator for getting path
|
||||
// Add: getFunctionCallCount()
|
||||
class PathProfileInfo {
|
||||
public:
|
||||
PathProfileInfo();
|
||||
~PathProfileInfo();
|
||||
|
||||
void setCurrentFunction(Function* F);
|
||||
Function* getCurrentFunction() const;
|
||||
BasicBlock* getCurrentFunctionEntry();
|
||||
|
||||
ProfilePath* getPath(unsigned int number);
|
||||
unsigned int getPotentialPathCount();
|
||||
|
||||
ProfilePathIterator pathBegin();
|
||||
ProfilePathIterator pathEnd();
|
||||
unsigned int pathsRun();
|
||||
|
||||
static char ID; // Pass identification
|
||||
std::string argList;
|
||||
|
||||
protected:
|
||||
FunctionPathMap _functionPaths;
|
||||
FunctionPathCountMap _functionPathCounts;
|
||||
|
||||
private:
|
||||
BallLarusDag* _currentDag;
|
||||
Function* _currentFunction;
|
||||
|
||||
friend class ProfilePath;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
106
thirdparty/clang/include/llvm/Analysis/PostDominators.h
vendored
Normal file
106
thirdparty/clang/include/llvm/Analysis/PostDominators.h
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file exposes interfaces to post dominance information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_POSTDOMINATORS_H
|
||||
#define LLVM_ANALYSIS_POSTDOMINATORS_H
|
||||
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
|
||||
/// compute the a post-dominator tree.
|
||||
///
|
||||
struct PostDominatorTree : public FunctionPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
DominatorTreeBase<BasicBlock>* DT;
|
||||
|
||||
PostDominatorTree() : FunctionPass(ID) {
|
||||
initializePostDominatorTreePass(*PassRegistry::getPassRegistry());
|
||||
DT = new DominatorTreeBase<BasicBlock>(true);
|
||||
}
|
||||
|
||||
~PostDominatorTree();
|
||||
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
inline const std::vector<BasicBlock*> &getRoots() const {
|
||||
return DT->getRoots();
|
||||
}
|
||||
|
||||
inline DomTreeNode *getRootNode() const {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
inline DomTreeNode *operator[](BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
inline DomTreeNode *getNode(BasicBlock *BB) const {
|
||||
return DT->getNode(BB);
|
||||
}
|
||||
|
||||
inline bool dominates(DomTreeNode* A, DomTreeNode* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
inline bool dominates(const BasicBlock* A, const BasicBlock* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
inline bool properlyDominates(const DomTreeNode* A, DomTreeNode* B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
inline bool properlyDominates(BasicBlock* A, BasicBlock* B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS, const Module*) const;
|
||||
};
|
||||
|
||||
FunctionPass* createPostDomTree();
|
||||
|
||||
template <> struct GraphTraits<PostDominatorTree*>
|
||||
: public GraphTraits<DomTreeNode*> {
|
||||
static NodeType *getEntryNode(PostDominatorTree *DT) {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(PostDominatorTree *N) {
|
||||
if (getEntryNode(N))
|
||||
return df_begin(getEntryNode(N));
|
||||
else
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(PostDominatorTree *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
140
thirdparty/clang/include/llvm/Analysis/ProfileDataLoader.h
vendored
Normal file
140
thirdparty/clang/include/llvm/Analysis/ProfileDataLoader.h
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
//===- ProfileDataLoader.h - Load & convert profile info ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ProfileDataLoader class is used to load profiling data from a dump file.
|
||||
// The ProfileDataT<FType, BType> class is used to store the mapping of this
|
||||
// data to control flow edges.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILEDATALOADER_H
|
||||
#define LLVM_ANALYSIS_PROFILEDATALOADER_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class ModulePass;
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
|
||||
// Helper for dumping edges to dbgs().
|
||||
raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *,
|
||||
const BasicBlock *> E);
|
||||
|
||||
/// \brief The ProfileDataT<FType, BType> class is used to store the mapping of
|
||||
/// profiling data to control flow edges.
|
||||
///
|
||||
/// An edge is defined by its source and sink basic blocks.
|
||||
template<class FType, class BType>
|
||||
class ProfileDataT {
|
||||
public:
|
||||
// The profiling information defines an Edge by its source and sink basic
|
||||
// blocks.
|
||||
typedef std::pair<const BType*, const BType*> Edge;
|
||||
|
||||
private:
|
||||
typedef DenseMap<Edge, unsigned> EdgeWeights;
|
||||
|
||||
/// \brief Count the number of times a transition between two blocks is
|
||||
/// executed.
|
||||
///
|
||||
/// As a special case, we also hold an edge from the null BasicBlock to the
|
||||
/// entry block to indicate how many times the function was entered.
|
||||
DenseMap<const FType*, EdgeWeights> EdgeInformation;
|
||||
|
||||
public:
|
||||
/// getFunction() - Returns the Function for an Edge.
|
||||
static const FType *getFunction(Edge e) {
|
||||
// e.first may be NULL
|
||||
assert(((!e.first) || (e.first->getParent() == e.second->getParent()))
|
||||
&& "A ProfileData::Edge can not be between two functions");
|
||||
assert(e.second && "A ProfileData::Edge must have a real sink");
|
||||
return e.second->getParent();
|
||||
}
|
||||
|
||||
/// getEdge() - Creates an Edge between two BasicBlocks.
|
||||
static Edge getEdge(const BType *Src, const BType *Dest) {
|
||||
return Edge(Src, Dest);
|
||||
}
|
||||
|
||||
/// getEdgeWeight - Return the number of times that a given edge was
|
||||
/// executed.
|
||||
unsigned getEdgeWeight(Edge e) const {
|
||||
const FType *f = getFunction(e);
|
||||
assert((EdgeInformation.find(f) != EdgeInformation.end())
|
||||
&& "No profiling information for function");
|
||||
EdgeWeights weights = EdgeInformation.find(f)->second;
|
||||
|
||||
assert((weights.find(e) != weights.end())
|
||||
&& "No profiling information for edge");
|
||||
return weights.find(e)->second;
|
||||
}
|
||||
|
||||
/// addEdgeWeight - Add 'weight' to the already stored execution count for
|
||||
/// this edge.
|
||||
void addEdgeWeight(Edge e, unsigned weight) {
|
||||
EdgeInformation[getFunction(e)][e] += weight;
|
||||
}
|
||||
};
|
||||
|
||||
typedef ProfileDataT<Function, BasicBlock> ProfileData;
|
||||
//typedef ProfileDataT<MachineFunction, MachineBasicBlock> MachineProfileData;
|
||||
|
||||
/// The ProfileDataLoader class is used to load raw profiling data from the
|
||||
/// dump file.
|
||||
class ProfileDataLoader {
|
||||
private:
|
||||
/// The name of the file where the raw profiling data is stored.
|
||||
const std::string &Filename;
|
||||
|
||||
/// A vector of the command line arguments used when the target program was
|
||||
/// run to generate profiling data. One entry per program run.
|
||||
SmallVector<std::string, 1> CommandLines;
|
||||
|
||||
/// The raw values for how many times each edge was traversed, values from
|
||||
/// multiple program runs are accumulated.
|
||||
SmallVector<unsigned, 32> EdgeCounts;
|
||||
|
||||
public:
|
||||
/// ProfileDataLoader ctor - Read the specified profiling data file, exiting
|
||||
/// the program if the file is invalid or broken.
|
||||
ProfileDataLoader(const char *ToolName, const std::string &Filename);
|
||||
|
||||
/// A special value used to represent the weight of an edge which has not
|
||||
/// been counted yet.
|
||||
static const unsigned Uncounted;
|
||||
|
||||
/// getNumExecutions - Return the number of times the target program was run
|
||||
/// to generate this profiling data.
|
||||
unsigned getNumExecutions() const { return CommandLines.size(); }
|
||||
|
||||
/// getExecution - Return the command line parameters used to generate the
|
||||
/// i'th set of profiling data.
|
||||
const std::string &getExecution(unsigned i) const { return CommandLines[i]; }
|
||||
|
||||
const std::string &getFileName() const { return Filename; }
|
||||
|
||||
/// getRawEdgeCounts - Return the raw profiling data, this is just a list of
|
||||
/// numbers with no mappings to edges.
|
||||
ArrayRef<unsigned> getRawEdgeCounts() const { return EdgeCounts; }
|
||||
};
|
||||
|
||||
/// createProfileMetadataLoaderPass - This function returns a Pass that loads
|
||||
/// the profiling information for the module from the specified filename.
|
||||
ModulePass *createProfileMetadataLoaderPass(const std::string &Filename);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
39
thirdparty/clang/include/llvm/Analysis/ProfileDataTypes.h
vendored
Normal file
39
thirdparty/clang/include/llvm/Analysis/ProfileDataTypes.h
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
/*===-- ProfileDataTypes.h - Profiling info shared constants --------------===*\
|
||||
|*
|
||||
|* The LLVM Compiler Infrastructure
|
||||
|*
|
||||
|* This file is distributed under the University of Illinois Open Source
|
||||
|* License. See LICENSE.TXT for details.
|
||||
|*
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|*
|
||||
|* This file defines constants shared by the various different profiling
|
||||
|* runtime libraries and the LLVM C++ profile metadata loader. It must be a
|
||||
|* C header because, at present, the profiling runtimes are written in C.
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILEDATATYPES_H
|
||||
#define LLVM_ANALYSIS_PROFILEDATATYPES_H
|
||||
|
||||
/* Included by libprofile. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* TODO: Strip out unused entries once ProfileInfo etc has been removed. */
|
||||
enum ProfilingType {
|
||||
ArgumentInfo = 1, /* The command line argument block */
|
||||
FunctionInfo = 2, /* Function profiling information */
|
||||
BlockInfo = 3, /* Block profiling information */
|
||||
EdgeInfo = 4, /* Edge profiling information */
|
||||
PathInfo = 5, /* Path profiling information */
|
||||
BBTraceInfo = 6, /* Basic block trace information */
|
||||
OptEdgeInfo = 7 /* Edge profiling information, optimal version */
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LLVM_ANALYSIS_PROFILEDATATYPES_H */
|
||||
247
thirdparty/clang/include/llvm/Analysis/ProfileInfo.h
vendored
Normal file
247
thirdparty/clang/include/llvm/Analysis/ProfileInfo.h
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- 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 generic ProfileInfo interface, which is used as the
|
||||
// common interface used by all clients of profiling information, and
|
||||
// implemented either by making static guestimations, or by actually reading in
|
||||
// profiling information gathered by running the program.
|
||||
//
|
||||
// Note that to be useful, all profile-based optimizations should preserve
|
||||
// ProfileInfo, which requires that they notify it when changes to the CFG are
|
||||
// made. (This is not implemented yet.)
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILEINFO_H
|
||||
#define LLVM_ANALYSIS_PROFILEINFO_H
|
||||
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class Pass;
|
||||
class raw_ostream;
|
||||
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
|
||||
// Helper for dumping edges to dbgs().
|
||||
raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *, const BasicBlock *> E);
|
||||
raw_ostream& operator<<(raw_ostream &O, std::pair<const MachineBasicBlock *, const MachineBasicBlock *> E);
|
||||
|
||||
raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB);
|
||||
raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB);
|
||||
|
||||
raw_ostream& operator<<(raw_ostream &O, const Function *F);
|
||||
raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF);
|
||||
|
||||
/// ProfileInfo Class - This class holds and maintains profiling
|
||||
/// information for some unit of code.
|
||||
template<class FType, class BType>
|
||||
class ProfileInfoT {
|
||||
public:
|
||||
// Types for handling profiling information.
|
||||
typedef std::pair<const BType*, const BType*> Edge;
|
||||
typedef std::pair<Edge, double> EdgeWeight;
|
||||
typedef std::map<Edge, double> EdgeWeights;
|
||||
typedef std::map<const BType*, double> BlockCounts;
|
||||
typedef std::map<const BType*, const BType*> Path;
|
||||
|
||||
protected:
|
||||
// EdgeInformation - Count the number of times a transition between two
|
||||
// blocks is executed. As a special case, we also hold an edge from the
|
||||
// null BasicBlock to the entry block to indicate how many times the
|
||||
// function was entered.
|
||||
std::map<const FType*, EdgeWeights> EdgeInformation;
|
||||
|
||||
// BlockInformation - Count the number of times a block is executed.
|
||||
std::map<const FType*, BlockCounts> BlockInformation;
|
||||
|
||||
// FunctionInformation - Count the number of times a function is executed.
|
||||
std::map<const FType*, double> FunctionInformation;
|
||||
|
||||
ProfileInfoT<MachineFunction, MachineBasicBlock> *MachineProfile;
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
ProfileInfoT();
|
||||
~ProfileInfoT(); // We want to be subclassed
|
||||
|
||||
// MissingValue - The value that is returned for execution counts in case
|
||||
// no value is available.
|
||||
static const double MissingValue;
|
||||
|
||||
// getFunction() - Returns the Function for an Edge, checking for validity.
|
||||
static const FType* getFunction(Edge e) {
|
||||
if (e.first)
|
||||
return e.first->getParent();
|
||||
if (e.second)
|
||||
return e.second->getParent();
|
||||
llvm_unreachable("Invalid ProfileInfo::Edge");
|
||||
}
|
||||
|
||||
// getEdge() - Creates an Edge from two BasicBlocks.
|
||||
static Edge getEdge(const BType *Src, const BType *Dest) {
|
||||
return std::make_pair(Src, Dest);
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
/// Profile Information Queries
|
||||
///
|
||||
double getExecutionCount(const FType *F);
|
||||
|
||||
double getExecutionCount(const BType *BB);
|
||||
|
||||
void setExecutionCount(const BType *BB, double w);
|
||||
|
||||
void addExecutionCount(const BType *BB, double w);
|
||||
|
||||
double getEdgeWeight(Edge e) const {
|
||||
typename std::map<const FType*, EdgeWeights>::const_iterator J =
|
||||
EdgeInformation.find(getFunction(e));
|
||||
if (J == EdgeInformation.end()) return MissingValue;
|
||||
|
||||
typename EdgeWeights::const_iterator I = J->second.find(e);
|
||||
if (I == J->second.end()) return MissingValue;
|
||||
|
||||
return I->second;
|
||||
}
|
||||
|
||||
void setEdgeWeight(Edge e, double w) {
|
||||
DEBUG_WITH_TYPE("profile-info",
|
||||
dbgs() << "Creating Edge " << e
|
||||
<< " (weight: " << format("%.20g",w) << ")\n");
|
||||
EdgeInformation[getFunction(e)][e] = w;
|
||||
}
|
||||
|
||||
void addEdgeWeight(Edge e, double w);
|
||||
|
||||
EdgeWeights &getEdgeWeights (const FType *F) {
|
||||
return EdgeInformation[F];
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
/// Analysis Update Methods
|
||||
///
|
||||
void removeBlock(const BType *BB);
|
||||
|
||||
void removeEdge(Edge e);
|
||||
|
||||
void replaceEdge(const Edge &, const Edge &);
|
||||
|
||||
enum GetPathMode {
|
||||
GetPathToExit = 1,
|
||||
GetPathToValue = 2,
|
||||
GetPathToDest = 4,
|
||||
GetPathWithNewEdges = 8
|
||||
};
|
||||
|
||||
const BType *GetPath(const BType *Src, const BType *Dest,
|
||||
Path &P, unsigned Mode);
|
||||
|
||||
void divertFlow(const Edge &, const Edge &);
|
||||
|
||||
void splitEdge(const BType *FirstBB, const BType *SecondBB,
|
||||
const BType *NewBB, bool MergeIdenticalEdges = false);
|
||||
|
||||
void splitBlock(const BType *Old, const BType* New);
|
||||
|
||||
void splitBlock(const BType *BB, const BType* NewBB,
|
||||
BType *const *Preds, unsigned NumPreds);
|
||||
|
||||
void replaceAllUses(const BType *RmBB, const BType *DestBB);
|
||||
|
||||
void transfer(const FType *Old, const FType *New);
|
||||
|
||||
void repair(const FType *F);
|
||||
|
||||
void dump(FType *F = 0, bool real = true) {
|
||||
dbgs() << "**** This is ProfileInfo " << this << " speaking:\n";
|
||||
if (!real) {
|
||||
typename std::set<const FType*> Functions;
|
||||
|
||||
dbgs() << "Functions: \n";
|
||||
if (F) {
|
||||
dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n";
|
||||
Functions.insert(F);
|
||||
} else {
|
||||
for (typename std::map<const FType*, double>::iterator fi = FunctionInformation.begin(),
|
||||
fe = FunctionInformation.end(); fi != fe; ++fi) {
|
||||
dbgs() << fi->first << "@" << format("%p",fi->first) << ": " << format("%.20g",fi->second) << "\n";
|
||||
Functions.insert(fi->first);
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end();
|
||||
FI != FE; ++FI) {
|
||||
const FType *F = *FI;
|
||||
typename std::map<const FType*, BlockCounts>::iterator bwi = BlockInformation.find(F);
|
||||
dbgs() << "BasicBlocks for Function " << F << ":\n";
|
||||
for (typename BlockCounts::const_iterator bi = bwi->second.begin(), be = bwi->second.end(); bi != be; ++bi) {
|
||||
dbgs() << bi->first << "@" << format("%p", bi->first) << ": " << format("%.20g",bi->second) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end();
|
||||
FI != FE; ++FI) {
|
||||
typename std::map<const FType*, EdgeWeights>::iterator ei = EdgeInformation.find(*FI);
|
||||
dbgs() << "Edges for Function " << ei->first << ":\n";
|
||||
for (typename EdgeWeights::iterator ewi = ei->second.begin(), ewe = ei->second.end();
|
||||
ewi != ewe; ++ewi) {
|
||||
dbgs() << ewi->first << ": " << format("%.20g",ewi->second) << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(F && "No function given, this is not supported!");
|
||||
dbgs() << "Functions: \n";
|
||||
dbgs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n";
|
||||
|
||||
dbgs() << "BasicBlocks for Function " << F << ":\n";
|
||||
for (typename FType::const_iterator BI = F->begin(), BE = F->end();
|
||||
BI != BE; ++BI) {
|
||||
const BType *BB = &(*BI);
|
||||
dbgs() << BB << "@" << format("%p", BB) << ": " << format("%.20g",getExecutionCount(BB)) << "\n";
|
||||
}
|
||||
}
|
||||
dbgs() << "**** ProfileInfo " << this << ", over and out.\n";
|
||||
}
|
||||
|
||||
bool CalculateMissingEdge(const BType *BB, Edge &removed, bool assumeEmptyExit = false);
|
||||
|
||||
bool EstimateMissingEdges(const BType *BB);
|
||||
|
||||
ProfileInfoT<MachineFunction, MachineBasicBlock> *MI() {
|
||||
if (MachineProfile == 0)
|
||||
MachineProfile = new ProfileInfoT<MachineFunction, MachineBasicBlock>();
|
||||
return MachineProfile;
|
||||
}
|
||||
|
||||
bool hasMI() const {
|
||||
return (MachineProfile != 0);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ProfileInfoT<Function, BasicBlock> ProfileInfo;
|
||||
typedef ProfileInfoT<MachineFunction, MachineBasicBlock> MachineProfileInfo;
|
||||
|
||||
/// createProfileLoaderPass - This function returns a Pass that loads the
|
||||
/// profiling information for the module from the specified filename, making
|
||||
/// it available to the optimizers.
|
||||
Pass *createProfileLoaderPass(const std::string &Filename);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
81
thirdparty/clang/include/llvm/Analysis/ProfileInfoLoader.h
vendored
Normal file
81
thirdparty/clang/include/llvm/Analysis/ProfileInfoLoader.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ProfileInfoLoader class is used to load and represent profiling
|
||||
// information read in from the dump file. If conversions between formats are
|
||||
// needed, it can also do this.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H
|
||||
#define LLVM_ANALYSIS_PROFILEINFOLOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
|
||||
class ProfileInfoLoader {
|
||||
const std::string &Filename;
|
||||
std::vector<std::string> CommandLines;
|
||||
std::vector<unsigned> FunctionCounts;
|
||||
std::vector<unsigned> BlockCounts;
|
||||
std::vector<unsigned> EdgeCounts;
|
||||
std::vector<unsigned> OptimalEdgeCounts;
|
||||
std::vector<unsigned> BBTrace;
|
||||
public:
|
||||
// ProfileInfoLoader ctor - Read the specified profiling data file, exiting
|
||||
// the program if the file is invalid or broken.
|
||||
ProfileInfoLoader(const char *ToolName, const std::string &Filename);
|
||||
|
||||
static const unsigned Uncounted;
|
||||
|
||||
unsigned getNumExecutions() const { return CommandLines.size(); }
|
||||
const std::string &getExecution(unsigned i) const { return CommandLines[i]; }
|
||||
|
||||
const std::string &getFileName() const { return Filename; }
|
||||
|
||||
// getRawFunctionCounts - This method is used by consumers of function
|
||||
// counting information.
|
||||
//
|
||||
const std::vector<unsigned> &getRawFunctionCounts() const {
|
||||
return FunctionCounts;
|
||||
}
|
||||
|
||||
// getRawBlockCounts - This method is used by consumers of block counting
|
||||
// information.
|
||||
//
|
||||
const std::vector<unsigned> &getRawBlockCounts() const {
|
||||
return BlockCounts;
|
||||
}
|
||||
|
||||
// getEdgeCounts - This method is used by consumers of edge counting
|
||||
// information.
|
||||
//
|
||||
const std::vector<unsigned> &getRawEdgeCounts() const {
|
||||
return EdgeCounts;
|
||||
}
|
||||
|
||||
// getEdgeOptimalCounts - This method is used by consumers of optimal edge
|
||||
// counting information.
|
||||
//
|
||||
const std::vector<unsigned> &getRawOptimalEdgeCounts() const {
|
||||
return OptimalEdgeCounts;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
52
thirdparty/clang/include/llvm/Analysis/ProfileInfoTypes.h
vendored
Normal file
52
thirdparty/clang/include/llvm/Analysis/ProfileInfoTypes.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*===-- ProfileInfoTypes.h - Profiling info shared constants --------------===*\
|
||||
|*
|
||||
|* The LLVM Compiler Infrastructure
|
||||
|*
|
||||
|* This file is distributed under the University of Illinois Open Source
|
||||
|* License. See LICENSE.TXT for details.
|
||||
|*
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|*
|
||||
|* This file defines constants shared by the various different profiling
|
||||
|* runtime libraries and the LLVM C++ profile info loader. It must be a
|
||||
|* C header because, at present, the profiling runtimes are written in C.
|
||||
|*
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H
|
||||
#define LLVM_ANALYSIS_PROFILEINFOTYPES_H
|
||||
|
||||
/* Included by libprofile. */
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* IDs to distinguish between those path counters stored in hashses vs arrays */
|
||||
enum ProfilingStorageType {
|
||||
ProfilingArray = 1,
|
||||
ProfilingHash = 2
|
||||
};
|
||||
|
||||
#include "llvm/Analysis/ProfileDataTypes.h"
|
||||
|
||||
/*
|
||||
* The header for tables that map path numbers to path counters.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned fnNumber; /* function number for these counters */
|
||||
unsigned numEntries; /* number of entries stored */
|
||||
} PathProfileHeader;
|
||||
|
||||
/*
|
||||
* Describes an entry in a tagged table for path counters.
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned pathNumber;
|
||||
unsigned pathCounter;
|
||||
} PathProfileTableEntry;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */
|
||||
285
thirdparty/clang/include/llvm/Analysis/PtrUseVisitor.h
vendored
Normal file
285
thirdparty/clang/include/llvm/Analysis/PtrUseVisitor.h
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
//===- PtrUseVisitor.h - InstVisitors over a pointers uses ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file provides a collection of visitors which walk the (instruction)
|
||||
/// uses of a pointer. These visitors all provide the same essential behavior
|
||||
/// as an InstVisitor with similar template-based flexibility and
|
||||
/// implementation strategies.
|
||||
///
|
||||
/// These can be used, for example, to quickly analyze the uses of an alloca,
|
||||
/// global variable, or function argument.
|
||||
///
|
||||
/// FIXME: Provide a variant which doesn't track offsets and is cheaper.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PTRUSEVISITOR_H
|
||||
#define LLVM_ANALYSIS_PTRUSEVISITOR_H
|
||||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/InstVisitor.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace detail {
|
||||
/// \brief Implementation of non-dependent functionality for \c PtrUseVisitor.
|
||||
///
|
||||
/// See \c PtrUseVisitor for the public interface and detailed comments about
|
||||
/// usage. This class is just a helper base class which is not templated and
|
||||
/// contains all common code to be shared between different instantiations of
|
||||
/// PtrUseVisitor.
|
||||
class PtrUseVisitorBase {
|
||||
public:
|
||||
/// \brief This class provides information about the result of a visit.
|
||||
///
|
||||
/// After walking all the users (recursively) of a pointer, the basic
|
||||
/// infrastructure records some commonly useful information such as escape
|
||||
/// analysis and whether the visit completed or aborted early.
|
||||
class PtrInfo {
|
||||
public:
|
||||
PtrInfo() : AbortedInfo(0, false), EscapedInfo(0, false) {}
|
||||
|
||||
/// \brief Reset the pointer info, clearing all state.
|
||||
void reset() {
|
||||
AbortedInfo.setPointer(0);
|
||||
AbortedInfo.setInt(false);
|
||||
EscapedInfo.setPointer(0);
|
||||
EscapedInfo.setInt(false);
|
||||
}
|
||||
|
||||
/// \brief Did we abort the visit early?
|
||||
bool isAborted() const { return AbortedInfo.getInt(); }
|
||||
|
||||
/// \brief Is the pointer escaped at some point?
|
||||
bool isEscaped() const { return EscapedInfo.getInt(); }
|
||||
|
||||
/// \brief Get the instruction causing the visit to abort.
|
||||
/// \returns a pointer to the instruction causing the abort if one is
|
||||
/// available; otherwise returns null.
|
||||
Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); }
|
||||
|
||||
/// \brief Get the instruction causing the pointer to escape.
|
||||
/// \returns a pointer to the instruction which escapes the pointer if one
|
||||
/// is available; otherwise returns null.
|
||||
Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); }
|
||||
|
||||
/// \brief Mark the visit as aborted. Intended for use in a void return.
|
||||
/// \param I The instruction which caused the visit to abort, if available.
|
||||
void setAborted(Instruction *I = 0) {
|
||||
AbortedInfo.setInt(true);
|
||||
AbortedInfo.setPointer(I);
|
||||
}
|
||||
|
||||
/// \brief Mark the pointer as escaped. Intended for use in a void return.
|
||||
/// \param I The instruction which escapes the pointer, if available.
|
||||
void setEscaped(Instruction *I = 0) {
|
||||
EscapedInfo.setInt(true);
|
||||
EscapedInfo.setPointer(I);
|
||||
}
|
||||
|
||||
/// \brief Mark the pointer as escaped, and the visit as aborted. Intended
|
||||
/// for use in a void return.
|
||||
/// \param I The instruction which both escapes the pointer and aborts the
|
||||
/// visit, if available.
|
||||
void setEscapedAndAborted(Instruction *I = 0) {
|
||||
setEscaped(I);
|
||||
setAborted(I);
|
||||
}
|
||||
|
||||
private:
|
||||
PointerIntPair<Instruction *, 1, bool> AbortedInfo, EscapedInfo;
|
||||
};
|
||||
|
||||
protected:
|
||||
const DataLayout &DL;
|
||||
|
||||
/// \name Visitation infrastructure
|
||||
/// @{
|
||||
|
||||
/// \brief The info collected about the pointer being visited thus far.
|
||||
PtrInfo PI;
|
||||
|
||||
/// \brief A struct of the data needed to visit a particular use.
|
||||
///
|
||||
/// This is used to maintain a worklist fo to-visit uses. This is used to
|
||||
/// make the visit be iterative rather than recursive.
|
||||
struct UseToVisit {
|
||||
typedef PointerIntPair<Use *, 1, bool> UseAndIsOffsetKnownPair;
|
||||
UseAndIsOffsetKnownPair UseAndIsOffsetKnown;
|
||||
APInt Offset;
|
||||
};
|
||||
|
||||
/// \brief The worklist of to-visit uses.
|
||||
SmallVector<UseToVisit, 8> Worklist;
|
||||
|
||||
/// \brief A set of visited uses to break cycles in unreachable code.
|
||||
SmallPtrSet<Use *, 8> VisitedUses;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// \name Per-visit state
|
||||
/// This state is reset for each instruction visited.
|
||||
/// @{
|
||||
|
||||
/// \brief The use currently being visited.
|
||||
Use *U;
|
||||
|
||||
/// \brief True if we have a known constant offset for the use currently
|
||||
/// being visited.
|
||||
bool IsOffsetKnown;
|
||||
|
||||
/// \brief The constant offset of the use if that is known.
|
||||
APInt Offset;
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
/// Note that the constructor is protected because this class must be a base
|
||||
/// class, we can't create instances directly of this class.
|
||||
PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {}
|
||||
|
||||
/// \brief Enqueue the users of this instruction in the visit worklist.
|
||||
///
|
||||
/// This will visit the users with the same offset of the current visit
|
||||
/// (including an unknown offset if that is the current state).
|
||||
void enqueueUsers(Instruction &I);
|
||||
|
||||
/// \brief Walk the operands of a GEP and adjust the offset as appropriate.
|
||||
///
|
||||
/// This routine does the heavy lifting of the pointer walk by computing
|
||||
/// offsets and looking through GEPs.
|
||||
bool adjustOffsetForGEP(GetElementPtrInst &GEPI);
|
||||
};
|
||||
} // end namespace detail
|
||||
|
||||
/// \brief A base class for visitors over the uses of a pointer value.
|
||||
///
|
||||
/// Once constructed, a user can call \c visit on a pointer value, and this
|
||||
/// will walk its uses and visit each instruction using an InstVisitor. It also
|
||||
/// provides visit methods which will recurse through any pointer-to-pointer
|
||||
/// transformations such as GEPs and bitcasts.
|
||||
///
|
||||
/// During the visit, the current Use* being visited is available to the
|
||||
/// subclass, as well as the current offset from the original base pointer if
|
||||
/// known.
|
||||
///
|
||||
/// The recursive visit of uses is accomplished with a worklist, so the only
|
||||
/// ordering guarantee is that an instruction is visited before any uses of it
|
||||
/// are visited. Note that this does *not* mean before any of its users are
|
||||
/// visited! This is because users can be visited multiple times due to
|
||||
/// multiple, different uses of pointers derived from the same base.
|
||||
///
|
||||
/// A particular Use will only be visited once, but a User may be visited
|
||||
/// multiple times, once per Use. This visits may notably have different
|
||||
/// offsets.
|
||||
///
|
||||
/// All visit methods on the underlying InstVisitor return a boolean. This
|
||||
/// return short-circuits the visit, stopping it immediately.
|
||||
///
|
||||
/// FIXME: Generalize this for all values rather than just instructions.
|
||||
template <typename DerivedT>
|
||||
class PtrUseVisitor : protected InstVisitor<DerivedT>,
|
||||
public detail::PtrUseVisitorBase {
|
||||
friend class InstVisitor<DerivedT>;
|
||||
typedef InstVisitor<DerivedT> Base;
|
||||
|
||||
public:
|
||||
PtrUseVisitor(const DataLayout &DL) : PtrUseVisitorBase(DL) {}
|
||||
|
||||
/// \brief Recursively visit the uses of the given pointer.
|
||||
/// \returns An info struct about the pointer. See \c PtrInfo for details.
|
||||
PtrInfo visitPtr(Instruction &I) {
|
||||
// This must be a pointer type. Get an integer type suitable to hold
|
||||
// offsets on this pointer.
|
||||
// FIXME: Support a vector of pointers.
|
||||
assert(I.getType()->isPointerTy());
|
||||
IntegerType *IntPtrTy = cast<IntegerType>(DL.getIntPtrType(I.getType()));
|
||||
IsOffsetKnown = true;
|
||||
Offset = APInt(IntPtrTy->getBitWidth(), 0);
|
||||
PI.reset();
|
||||
|
||||
// Enqueue the uses of this pointer.
|
||||
enqueueUsers(I);
|
||||
|
||||
// Visit all the uses off the worklist until it is empty.
|
||||
while (!Worklist.empty()) {
|
||||
UseToVisit ToVisit = Worklist.pop_back_val();
|
||||
U = ToVisit.UseAndIsOffsetKnown.getPointer();
|
||||
IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt();
|
||||
if (IsOffsetKnown)
|
||||
Offset = llvm_move(ToVisit.Offset);
|
||||
|
||||
Instruction *I = cast<Instruction>(U->getUser());
|
||||
static_cast<DerivedT*>(this)->visit(I);
|
||||
if (PI.isAborted())
|
||||
break;
|
||||
}
|
||||
return PI;
|
||||
}
|
||||
|
||||
protected:
|
||||
void visitStoreInst(StoreInst &SI) {
|
||||
if (SI.getValueOperand() == U->get())
|
||||
PI.setEscaped(&SI);
|
||||
}
|
||||
|
||||
void visitBitCastInst(BitCastInst &BC) {
|
||||
enqueueUsers(BC);
|
||||
}
|
||||
|
||||
void visitPtrToIntInst(PtrToIntInst &I) {
|
||||
PI.setEscaped(&I);
|
||||
}
|
||||
|
||||
void visitGetElementPtrInst(GetElementPtrInst &GEPI) {
|
||||
if (GEPI.use_empty())
|
||||
return;
|
||||
|
||||
// If we can't walk the GEP, clear the offset.
|
||||
if (!adjustOffsetForGEP(GEPI)) {
|
||||
IsOffsetKnown = false;
|
||||
Offset = APInt();
|
||||
}
|
||||
|
||||
// Enqueue the users now that the offset has been adjusted.
|
||||
enqueueUsers(GEPI);
|
||||
}
|
||||
|
||||
// No-op intrinsics which we know don't escape the pointer to to logic in
|
||||
// some other function.
|
||||
void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {}
|
||||
void visitMemIntrinsic(MemIntrinsic &I) {}
|
||||
void visitIntrinsicInst(IntrinsicInst &II) {
|
||||
switch (II.getIntrinsicID()) {
|
||||
default:
|
||||
return Base::visitIntrinsicInst(II);
|
||||
|
||||
case Intrinsic::lifetime_start:
|
||||
case Intrinsic::lifetime_end:
|
||||
return; // No-op intrinsics.
|
||||
}
|
||||
}
|
||||
|
||||
// Generically, arguments to calls and invokes escape the pointer to some
|
||||
// other function. Mark that.
|
||||
void visitCallSite(CallSite CS) {
|
||||
PI.setEscaped(CS.getInstruction());
|
||||
Base::visitCallSite(CS);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
739
thirdparty/clang/include/llvm/Analysis/RegionInfo.h
vendored
Normal file
739
thirdparty/clang/include/llvm/Analysis/RegionInfo.h
vendored
Normal file
@@ -0,0 +1,739 @@
|
||||
//===- RegionInfo.h - SESE region analysis ----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Calculate a program structure tree built out of single entry single exit
|
||||
// regions.
|
||||
// The basic ideas are taken from "The Program Structure Tree - Richard Johnson,
|
||||
// David Pearson, Keshav Pingali - 1994", however enriched with ideas from "The
|
||||
// Refined Process Structure Tree - Jussi Vanhatalo, Hagen Voelyer, Jana
|
||||
// Koehler - 2009".
|
||||
// The algorithm to calculate these data structures however is completely
|
||||
// different, as it takes advantage of existing information already available
|
||||
// in (Post)dominace tree and dominance frontier passes. This leads to a simpler
|
||||
// and in practice hopefully better performing algorithm. The runtime of the
|
||||
// algorithms described in the papers above are both linear in graph size,
|
||||
// O(V+E), whereas this algorithm is not, as the dominance frontier information
|
||||
// itself is not, but in practice runtime seems to be in the order of magnitude
|
||||
// of dominance tree calculation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_REGIONINFO_H
|
||||
#define LLVM_ANALYSIS_REGIONINFO_H
|
||||
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/Analysis/DominanceFrontier.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Region;
|
||||
class RegionInfo;
|
||||
class raw_ostream;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
|
||||
/// @brief Marker class to iterate over the elements of a Region in flat mode.
|
||||
///
|
||||
/// The class is used to either iterate in Flat mode or by not using it to not
|
||||
/// iterate in Flat mode. During a Flat mode iteration all Regions are entered
|
||||
/// and the iteration returns every BasicBlock. If the Flat mode is not
|
||||
/// selected for SubRegions just one RegionNode containing the subregion is
|
||||
/// returned.
|
||||
template <class GraphType>
|
||||
class FlatIt {};
|
||||
|
||||
/// @brief A RegionNode represents a subregion or a BasicBlock that is part of a
|
||||
/// Region.
|
||||
class RegionNode {
|
||||
RegionNode(const RegionNode &) LLVM_DELETED_FUNCTION;
|
||||
const RegionNode &operator=(const RegionNode &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
protected:
|
||||
/// This is the entry basic block that starts this region node. If this is a
|
||||
/// BasicBlock RegionNode, then entry is just the basic block, that this
|
||||
/// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode.
|
||||
///
|
||||
/// In the BBtoRegionNode map of the parent of this node, BB will always map
|
||||
/// to this node no matter which kind of node this one is.
|
||||
///
|
||||
/// The node can hold either a Region or a BasicBlock.
|
||||
/// Use one bit to save, if this RegionNode is a subregion or BasicBlock
|
||||
/// RegionNode.
|
||||
PointerIntPair<BasicBlock*, 1, bool> entry;
|
||||
|
||||
/// @brief The parent Region of this RegionNode.
|
||||
/// @see getParent()
|
||||
Region* parent;
|
||||
|
||||
public:
|
||||
/// @brief Create a RegionNode.
|
||||
///
|
||||
/// @param Parent The parent of this RegionNode.
|
||||
/// @param Entry The entry BasicBlock of the RegionNode. If this
|
||||
/// RegionNode represents a BasicBlock, this is the
|
||||
/// BasicBlock itself. If it represents a subregion, this
|
||||
/// is the entry BasicBlock of the subregion.
|
||||
/// @param isSubRegion If this RegionNode represents a SubRegion.
|
||||
inline RegionNode(Region* Parent, BasicBlock* Entry, bool isSubRegion = 0)
|
||||
: entry(Entry, isSubRegion), parent(Parent) {}
|
||||
|
||||
/// @brief Get the parent Region of this RegionNode.
|
||||
///
|
||||
/// The parent Region is the Region this RegionNode belongs to. If for
|
||||
/// example a BasicBlock is element of two Regions, there exist two
|
||||
/// RegionNodes for this BasicBlock. Each with the getParent() function
|
||||
/// pointing to the Region this RegionNode belongs to.
|
||||
///
|
||||
/// @return Get the parent Region of this RegionNode.
|
||||
inline Region* getParent() const { return parent; }
|
||||
|
||||
/// @brief Get the entry BasicBlock of this RegionNode.
|
||||
///
|
||||
/// If this RegionNode represents a BasicBlock this is just the BasicBlock
|
||||
/// itself, otherwise we return the entry BasicBlock of the Subregion
|
||||
///
|
||||
/// @return The entry BasicBlock of this RegionNode.
|
||||
inline BasicBlock* getEntry() const { return entry.getPointer(); }
|
||||
|
||||
/// @brief Get the content of this RegionNode.
|
||||
///
|
||||
/// This can be either a BasicBlock or a subregion. Before calling getNodeAs()
|
||||
/// check the type of the content with the isSubRegion() function call.
|
||||
///
|
||||
/// @return The content of this RegionNode.
|
||||
template<class T>
|
||||
inline T* getNodeAs() const;
|
||||
|
||||
/// @brief Is this RegionNode a subregion?
|
||||
///
|
||||
/// @return True if it contains a subregion. False if it contains a
|
||||
/// BasicBlock.
|
||||
inline bool isSubRegion() const {
|
||||
return entry.getInt();
|
||||
}
|
||||
};
|
||||
|
||||
/// Print a RegionNode.
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node);
|
||||
|
||||
template<>
|
||||
inline BasicBlock* RegionNode::getNodeAs<BasicBlock>() const {
|
||||
assert(!isSubRegion() && "This is not a BasicBlock RegionNode!");
|
||||
return getEntry();
|
||||
}
|
||||
|
||||
template<>
|
||||
inline Region* RegionNode::getNodeAs<Region>() const {
|
||||
assert(isSubRegion() && "This is not a subregion RegionNode!");
|
||||
return reinterpret_cast<Region*>(const_cast<RegionNode*>(this));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @brief A single entry single exit Region.
|
||||
///
|
||||
/// A Region is a connected subgraph of a control flow graph that has exactly
|
||||
/// two connections to the remaining graph. It can be used to analyze or
|
||||
/// optimize parts of the control flow graph.
|
||||
///
|
||||
/// A <em> simple Region </em> is connected to the remaining graph by just two
|
||||
/// edges. One edge entering the Region and another one leaving the Region.
|
||||
///
|
||||
/// An <em> extended Region </em> (or just Region) is a subgraph that can be
|
||||
/// transform into a simple Region. The transformation is done by adding
|
||||
/// BasicBlocks that merge several entry or exit edges so that after the merge
|
||||
/// just one entry and one exit edge exists.
|
||||
///
|
||||
/// The \e Entry of a Region is the first BasicBlock that is passed after
|
||||
/// entering the Region. It is an element of the Region. The entry BasicBlock
|
||||
/// dominates all BasicBlocks in the Region.
|
||||
///
|
||||
/// The \e Exit of a Region is the first BasicBlock that is passed after
|
||||
/// leaving the Region. It is not an element of the Region. The exit BasicBlock,
|
||||
/// postdominates all BasicBlocks in the Region.
|
||||
///
|
||||
/// A <em> canonical Region </em> cannot be constructed by combining smaller
|
||||
/// Regions.
|
||||
///
|
||||
/// Region A is the \e parent of Region B, if B is completely contained in A.
|
||||
///
|
||||
/// Two canonical Regions either do not intersect at all or one is
|
||||
/// the parent of the other.
|
||||
///
|
||||
/// The <em> Program Structure Tree</em> is a graph (V, E) where V is the set of
|
||||
/// Regions in the control flow graph and E is the \e parent relation of these
|
||||
/// Regions.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// \verbatim
|
||||
/// A simple control flow graph, that contains two regions.
|
||||
///
|
||||
/// 1
|
||||
/// / |
|
||||
/// 2 |
|
||||
/// / \ 3
|
||||
/// 4 5 |
|
||||
/// | | |
|
||||
/// 6 7 8
|
||||
/// \ | /
|
||||
/// \ |/ Region A: 1 -> 9 {1,2,3,4,5,6,7,8}
|
||||
/// 9 Region B: 2 -> 9 {2,4,5,6,7}
|
||||
/// \endverbatim
|
||||
///
|
||||
/// You can obtain more examples by either calling
|
||||
///
|
||||
/// <tt> "opt -regions -analyze anyprogram.ll" </tt>
|
||||
/// or
|
||||
/// <tt> "opt -view-regions-only anyprogram.ll" </tt>
|
||||
///
|
||||
/// on any LLVM file you are interested in.
|
||||
///
|
||||
/// The first call returns a textual representation of the program structure
|
||||
/// tree, the second one creates a graphical representation using graphviz.
|
||||
class Region : public RegionNode {
|
||||
friend class RegionInfo;
|
||||
Region(const Region &) LLVM_DELETED_FUNCTION;
|
||||
const Region &operator=(const Region &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
// Information necessary to manage this Region.
|
||||
RegionInfo* RI;
|
||||
DominatorTree *DT;
|
||||
|
||||
// The exit BasicBlock of this region.
|
||||
// (The entry BasicBlock is part of RegionNode)
|
||||
BasicBlock *exit;
|
||||
|
||||
typedef std::vector<Region*> RegionSet;
|
||||
|
||||
// The subregions of this region.
|
||||
RegionSet children;
|
||||
|
||||
typedef std::map<BasicBlock*, RegionNode*> BBNodeMapT;
|
||||
|
||||
// Save the BasicBlock RegionNodes that are element of this Region.
|
||||
mutable BBNodeMapT BBNodeMap;
|
||||
|
||||
/// verifyBBInRegion - Check if a BB is in this Region. This check also works
|
||||
/// if the region is incorrectly built. (EXPENSIVE!)
|
||||
void verifyBBInRegion(BasicBlock* BB) const;
|
||||
|
||||
/// verifyWalk - Walk over all the BBs of the region starting from BB and
|
||||
/// verify that all reachable basic blocks are elements of the region.
|
||||
/// (EXPENSIVE!)
|
||||
void verifyWalk(BasicBlock* BB, std::set<BasicBlock*>* visitedBB) const;
|
||||
|
||||
/// verifyRegionNest - Verify if the region and its children are valid
|
||||
/// regions (EXPENSIVE!)
|
||||
void verifyRegionNest() const;
|
||||
|
||||
public:
|
||||
/// @brief Create a new region.
|
||||
///
|
||||
/// @param Entry The entry basic block of the region.
|
||||
/// @param Exit The exit basic block of the region.
|
||||
/// @param RI The region info object that is managing this region.
|
||||
/// @param DT The dominator tree of the current function.
|
||||
/// @param Parent The surrounding region or NULL if this is a top level
|
||||
/// region.
|
||||
Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RI,
|
||||
DominatorTree *DT, Region *Parent = 0);
|
||||
|
||||
/// Delete the Region and all its subregions.
|
||||
~Region();
|
||||
|
||||
/// @brief Get the entry BasicBlock of the Region.
|
||||
/// @return The entry BasicBlock of the region.
|
||||
BasicBlock *getEntry() const { return RegionNode::getEntry(); }
|
||||
|
||||
/// @brief Replace the entry basic block of the region with the new basic
|
||||
/// block.
|
||||
///
|
||||
/// @param BB The new entry basic block of the region.
|
||||
void replaceEntry(BasicBlock *BB);
|
||||
|
||||
/// @brief Replace the exit basic block of the region with the new basic
|
||||
/// block.
|
||||
///
|
||||
/// @param BB The new exit basic block of the region.
|
||||
void replaceExit(BasicBlock *BB);
|
||||
|
||||
/// @brief Recursively replace the entry basic block of the region.
|
||||
///
|
||||
/// This function replaces the entry basic block with a new basic block. It
|
||||
/// also updates all child regions that have the same entry basic block as
|
||||
/// this region.
|
||||
///
|
||||
/// @param NewEntry The new entry basic block.
|
||||
void replaceEntryRecursive(BasicBlock *NewEntry);
|
||||
|
||||
/// @brief Recursively replace the exit basic block of the region.
|
||||
///
|
||||
/// This function replaces the exit basic block with a new basic block. It
|
||||
/// also updates all child regions that have the same exit basic block as
|
||||
/// this region.
|
||||
///
|
||||
/// @param NewExit The new exit basic block.
|
||||
void replaceExitRecursive(BasicBlock *NewExit);
|
||||
|
||||
/// @brief Get the exit BasicBlock of the Region.
|
||||
/// @return The exit BasicBlock of the Region, NULL if this is the TopLevel
|
||||
/// Region.
|
||||
BasicBlock *getExit() const { return exit; }
|
||||
|
||||
/// @brief Get the parent of the Region.
|
||||
/// @return The parent of the Region or NULL if this is a top level
|
||||
/// Region.
|
||||
Region *getParent() const { return RegionNode::getParent(); }
|
||||
|
||||
/// @brief Get the RegionNode representing the current Region.
|
||||
/// @return The RegionNode representing the current Region.
|
||||
RegionNode* getNode() const {
|
||||
return const_cast<RegionNode*>(reinterpret_cast<const RegionNode*>(this));
|
||||
}
|
||||
|
||||
/// @brief Get the nesting level of this Region.
|
||||
///
|
||||
/// An toplevel Region has depth 0.
|
||||
///
|
||||
/// @return The depth of the region.
|
||||
unsigned getDepth() const;
|
||||
|
||||
/// @brief Check if a Region is the TopLevel region.
|
||||
///
|
||||
/// The toplevel region represents the whole function.
|
||||
bool isTopLevelRegion() const { return exit == NULL; }
|
||||
|
||||
/// @brief Return a new (non canonical) region, that is obtained by joining
|
||||
/// this region with its predecessors.
|
||||
///
|
||||
/// @return A region also starting at getEntry(), but reaching to the next
|
||||
/// basic block that forms with getEntry() a (non canonical) region.
|
||||
/// NULL if such a basic block does not exist.
|
||||
Region *getExpandedRegion() const;
|
||||
|
||||
/// @brief Return the first block of this region's single entry edge,
|
||||
/// if existing.
|
||||
///
|
||||
/// @return The BasicBlock starting this region's single entry edge,
|
||||
/// else NULL.
|
||||
BasicBlock *getEnteringBlock() const;
|
||||
|
||||
/// @brief Return the first block of this region's single exit edge,
|
||||
/// if existing.
|
||||
///
|
||||
/// @return The BasicBlock starting this region's single exit edge,
|
||||
/// else NULL.
|
||||
BasicBlock *getExitingBlock() const;
|
||||
|
||||
/// @brief Is this a simple region?
|
||||
///
|
||||
/// A region is simple if it has exactly one exit and one entry edge.
|
||||
///
|
||||
/// @return True if the Region is simple.
|
||||
bool isSimple() const;
|
||||
|
||||
/// @brief Returns the name of the Region.
|
||||
/// @return The Name of the Region.
|
||||
std::string getNameStr() const;
|
||||
|
||||
/// @brief Return the RegionInfo object, that belongs to this Region.
|
||||
RegionInfo *getRegionInfo() const {
|
||||
return RI;
|
||||
}
|
||||
|
||||
/// PrintStyle - Print region in difference ways.
|
||||
enum PrintStyle { PrintNone, PrintBB, PrintRN };
|
||||
|
||||
/// @brief Print the region.
|
||||
///
|
||||
/// @param OS The output stream the Region is printed to.
|
||||
/// @param printTree Print also the tree of subregions.
|
||||
/// @param level The indentation level used for printing.
|
||||
void print(raw_ostream& OS, bool printTree = true, unsigned level = 0,
|
||||
enum PrintStyle Style = PrintNone) const;
|
||||
|
||||
/// @brief Print the region to stderr.
|
||||
void dump() const;
|
||||
|
||||
/// @brief Check if the region contains a BasicBlock.
|
||||
///
|
||||
/// @param BB The BasicBlock that might be contained in this Region.
|
||||
/// @return True if the block is contained in the region otherwise false.
|
||||
bool contains(const BasicBlock *BB) const;
|
||||
|
||||
/// @brief Check if the region contains another region.
|
||||
///
|
||||
/// @param SubRegion The region that might be contained in this Region.
|
||||
/// @return True if SubRegion is contained in the region otherwise false.
|
||||
bool contains(const Region *SubRegion) const {
|
||||
// Toplevel Region.
|
||||
if (!getExit())
|
||||
return true;
|
||||
|
||||
return contains(SubRegion->getEntry())
|
||||
&& (contains(SubRegion->getExit()) || SubRegion->getExit() == getExit());
|
||||
}
|
||||
|
||||
/// @brief Check if the region contains an Instruction.
|
||||
///
|
||||
/// @param Inst The Instruction that might be contained in this region.
|
||||
/// @return True if the Instruction is contained in the region otherwise false.
|
||||
bool contains(const Instruction *Inst) const {
|
||||
return contains(Inst->getParent());
|
||||
}
|
||||
|
||||
/// @brief Check if the region contains a loop.
|
||||
///
|
||||
/// @param L The loop that might be contained in this region.
|
||||
/// @return True if the loop is contained in the region otherwise false.
|
||||
/// In case a NULL pointer is passed to this function the result
|
||||
/// is false, except for the region that describes the whole function.
|
||||
/// In that case true is returned.
|
||||
bool contains(const Loop *L) const;
|
||||
|
||||
/// @brief Get the outermost loop in the region that contains a loop.
|
||||
///
|
||||
/// Find for a Loop L the outermost loop OuterL that is a parent loop of L
|
||||
/// and is itself contained in the region.
|
||||
///
|
||||
/// @param L The loop the lookup is started.
|
||||
/// @return The outermost loop in the region, NULL if such a loop does not
|
||||
/// exist or if the region describes the whole function.
|
||||
Loop *outermostLoopInRegion(Loop *L) const;
|
||||
|
||||
/// @brief Get the outermost loop in the region that contains a basic block.
|
||||
///
|
||||
/// Find for a basic block BB the outermost loop L that contains BB and is
|
||||
/// itself contained in the region.
|
||||
///
|
||||
/// @param LI A pointer to a LoopInfo analysis.
|
||||
/// @param BB The basic block surrounded by the loop.
|
||||
/// @return The outermost loop in the region, NULL if such a loop does not
|
||||
/// exist or if the region describes the whole function.
|
||||
Loop *outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const;
|
||||
|
||||
/// @brief Get the subregion that starts at a BasicBlock
|
||||
///
|
||||
/// @param BB The BasicBlock the subregion should start.
|
||||
/// @return The Subregion if available, otherwise NULL.
|
||||
Region* getSubRegionNode(BasicBlock *BB) const;
|
||||
|
||||
/// @brief Get the RegionNode for a BasicBlock
|
||||
///
|
||||
/// @param BB The BasicBlock at which the RegionNode should start.
|
||||
/// @return If available, the RegionNode that represents the subregion
|
||||
/// starting at BB. If no subregion starts at BB, the RegionNode
|
||||
/// representing BB.
|
||||
RegionNode* getNode(BasicBlock *BB) const;
|
||||
|
||||
/// @brief Get the BasicBlock RegionNode for a BasicBlock
|
||||
///
|
||||
/// @param BB The BasicBlock for which the RegionNode is requested.
|
||||
/// @return The RegionNode representing the BB.
|
||||
RegionNode* getBBNode(BasicBlock *BB) const;
|
||||
|
||||
/// @brief Add a new subregion to this Region.
|
||||
///
|
||||
/// @param SubRegion The new subregion that will be added.
|
||||
/// @param moveChildren Move the children of this region, that are also
|
||||
/// contained in SubRegion into SubRegion.
|
||||
void addSubRegion(Region *SubRegion, bool moveChildren = false);
|
||||
|
||||
/// @brief Remove a subregion from this Region.
|
||||
///
|
||||
/// The subregion is not deleted, as it will probably be inserted into another
|
||||
/// region.
|
||||
/// @param SubRegion The SubRegion that will be removed.
|
||||
Region *removeSubRegion(Region *SubRegion);
|
||||
|
||||
/// @brief Move all direct child nodes of this Region to another Region.
|
||||
///
|
||||
/// @param To The Region the child nodes will be transferred to.
|
||||
void transferChildrenTo(Region *To);
|
||||
|
||||
/// @brief Verify if the region is a correct region.
|
||||
///
|
||||
/// Check if this is a correctly build Region. This is an expensive check, as
|
||||
/// the complete CFG of the Region will be walked.
|
||||
void verifyRegion() const;
|
||||
|
||||
/// @brief Clear the cache for BB RegionNodes.
|
||||
///
|
||||
/// After calling this function the BasicBlock RegionNodes will be stored at
|
||||
/// different memory locations. RegionNodes obtained before this function is
|
||||
/// called are therefore not comparable to RegionNodes abtained afterwords.
|
||||
void clearNodeCache();
|
||||
|
||||
/// @name Subregion Iterators
|
||||
///
|
||||
/// These iterators iterator over all subregions of this Region.
|
||||
//@{
|
||||
typedef RegionSet::iterator iterator;
|
||||
typedef RegionSet::const_iterator const_iterator;
|
||||
|
||||
iterator begin() { return children.begin(); }
|
||||
iterator end() { return children.end(); }
|
||||
|
||||
const_iterator begin() const { return children.begin(); }
|
||||
const_iterator end() const { return children.end(); }
|
||||
//@}
|
||||
|
||||
/// @name BasicBlock Iterators
|
||||
///
|
||||
/// These iterators iterate over all BasicBlocks that are contained in this
|
||||
/// Region. The iterator also iterates over BasicBlocks that are elements of
|
||||
/// a subregion of this Region. It is therefore called a flat iterator.
|
||||
//@{
|
||||
template <bool IsConst>
|
||||
class block_iterator_wrapper
|
||||
: public df_iterator<typename conditional<IsConst,
|
||||
const BasicBlock,
|
||||
BasicBlock>::type*> {
|
||||
typedef df_iterator<typename conditional<IsConst,
|
||||
const BasicBlock,
|
||||
BasicBlock>::type*>
|
||||
super;
|
||||
public:
|
||||
typedef block_iterator_wrapper<IsConst> Self;
|
||||
typedef typename super::pointer pointer;
|
||||
|
||||
// Construct the begin iterator.
|
||||
block_iterator_wrapper(pointer Entry, pointer Exit) : super(df_begin(Entry))
|
||||
{
|
||||
// Mark the exit of the region as visited, so that the children of the
|
||||
// exit and the exit itself, i.e. the block outside the region will never
|
||||
// be visited.
|
||||
super::Visited.insert(Exit);
|
||||
}
|
||||
|
||||
// Construct the end iterator.
|
||||
block_iterator_wrapper() : super(df_end<pointer>((BasicBlock *)0)) {}
|
||||
|
||||
/*implicit*/ block_iterator_wrapper(super I) : super(I) {}
|
||||
|
||||
// FIXME: Even a const_iterator returns a non-const BasicBlock pointer.
|
||||
// This was introduced for backwards compatibility, but should
|
||||
// be removed as soon as all users are fixed.
|
||||
BasicBlock *operator*() const {
|
||||
return const_cast<BasicBlock*>(super::operator*());
|
||||
}
|
||||
};
|
||||
|
||||
typedef block_iterator_wrapper<false> block_iterator;
|
||||
typedef block_iterator_wrapper<true> const_block_iterator;
|
||||
|
||||
block_iterator block_begin() {
|
||||
return block_iterator(getEntry(), getExit());
|
||||
}
|
||||
|
||||
block_iterator block_end() {
|
||||
return block_iterator();
|
||||
}
|
||||
|
||||
const_block_iterator block_begin() const {
|
||||
return const_block_iterator(getEntry(), getExit());
|
||||
}
|
||||
const_block_iterator block_end() const {
|
||||
return const_block_iterator();
|
||||
}
|
||||
//@}
|
||||
|
||||
/// @name Element Iterators
|
||||
///
|
||||
/// These iterators iterate over all BasicBlock and subregion RegionNodes that
|
||||
/// are direct children of this Region. It does not iterate over any
|
||||
/// RegionNodes that are also element of a subregion of this Region.
|
||||
//@{
|
||||
typedef df_iterator<RegionNode*, SmallPtrSet<RegionNode*, 8>, false,
|
||||
GraphTraits<RegionNode*> > element_iterator;
|
||||
|
||||
typedef df_iterator<const RegionNode*, SmallPtrSet<const RegionNode*, 8>,
|
||||
false, GraphTraits<const RegionNode*> >
|
||||
const_element_iterator;
|
||||
|
||||
element_iterator element_begin();
|
||||
element_iterator element_end();
|
||||
|
||||
const_element_iterator element_begin() const;
|
||||
const_element_iterator element_end() const;
|
||||
//@}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @brief Analysis that detects all canonical Regions.
|
||||
///
|
||||
/// The RegionInfo pass detects all canonical regions in a function. The Regions
|
||||
/// are connected using the parent relation. This builds a Program Structure
|
||||
/// Tree.
|
||||
class RegionInfo : public FunctionPass {
|
||||
typedef DenseMap<BasicBlock*,BasicBlock*> BBtoBBMap;
|
||||
typedef DenseMap<BasicBlock*, Region*> BBtoRegionMap;
|
||||
typedef SmallPtrSet<Region*, 4> RegionSet;
|
||||
|
||||
RegionInfo(const RegionInfo &) LLVM_DELETED_FUNCTION;
|
||||
const RegionInfo &operator=(const RegionInfo &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
DominatorTree *DT;
|
||||
PostDominatorTree *PDT;
|
||||
DominanceFrontier *DF;
|
||||
|
||||
/// The top level region.
|
||||
Region *TopLevelRegion;
|
||||
|
||||
/// Map every BB to the smallest region, that contains BB.
|
||||
BBtoRegionMap BBtoRegion;
|
||||
|
||||
// isCommonDomFrontier - Returns true if BB is in the dominance frontier of
|
||||
// entry, because it was inherited from exit. In the other case there is an
|
||||
// edge going from entry to BB without passing exit.
|
||||
bool isCommonDomFrontier(BasicBlock* BB, BasicBlock* entry,
|
||||
BasicBlock* exit) const;
|
||||
|
||||
// isRegion - Check if entry and exit surround a valid region, based on
|
||||
// dominance tree and dominance frontier.
|
||||
bool isRegion(BasicBlock* entry, BasicBlock* exit) const;
|
||||
|
||||
// insertShortCut - Saves a shortcut pointing from entry to exit.
|
||||
// This function may extend this shortcut if possible.
|
||||
void insertShortCut(BasicBlock* entry, BasicBlock* exit,
|
||||
BBtoBBMap* ShortCut) const;
|
||||
|
||||
// getNextPostDom - Returns the next BB that postdominates N, while skipping
|
||||
// all post dominators that cannot finish a canonical region.
|
||||
DomTreeNode *getNextPostDom(DomTreeNode* N, BBtoBBMap *ShortCut) const;
|
||||
|
||||
// isTrivialRegion - A region is trivial, if it contains only one BB.
|
||||
bool isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const;
|
||||
|
||||
// createRegion - Creates a single entry single exit region.
|
||||
Region *createRegion(BasicBlock *entry, BasicBlock *exit);
|
||||
|
||||
// findRegionsWithEntry - Detect all regions starting with bb 'entry'.
|
||||
void findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut);
|
||||
|
||||
// scanForRegions - Detects regions in F.
|
||||
void scanForRegions(Function &F, BBtoBBMap *ShortCut);
|
||||
|
||||
// getTopMostParent - Get the top most parent with the same entry block.
|
||||
Region *getTopMostParent(Region *region);
|
||||
|
||||
// buildRegionsTree - build the region hierarchy after all region detected.
|
||||
void buildRegionsTree(DomTreeNode *N, Region *region);
|
||||
|
||||
// Calculate - detecte all regions in function and build the region tree.
|
||||
void Calculate(Function& F);
|
||||
|
||||
void releaseMemory();
|
||||
|
||||
// updateStatistics - Update statistic about created regions.
|
||||
void updateStatistics(Region *R);
|
||||
|
||||
// isSimple - Check if a region is a simple region with exactly one entry
|
||||
// edge and exactly one exit edge.
|
||||
bool isSimple(Region* R) const;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
explicit RegionInfo();
|
||||
|
||||
~RegionInfo();
|
||||
|
||||
/// @name FunctionPass interface
|
||||
//@{
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void print(raw_ostream &OS, const Module *) const;
|
||||
virtual void verifyAnalysis() const;
|
||||
//@}
|
||||
|
||||
/// @brief Get the smallest region that contains a BasicBlock.
|
||||
///
|
||||
/// @param BB The basic block.
|
||||
/// @return The smallest region, that contains BB or NULL, if there is no
|
||||
/// region containing BB.
|
||||
Region *getRegionFor(BasicBlock *BB) const;
|
||||
|
||||
/// @brief Set the smallest region that surrounds a basic block.
|
||||
///
|
||||
/// @param BB The basic block surrounded by a region.
|
||||
/// @param R The smallest region that surrounds BB.
|
||||
void setRegionFor(BasicBlock *BB, Region *R);
|
||||
|
||||
/// @brief A shortcut for getRegionFor().
|
||||
///
|
||||
/// @param BB The basic block.
|
||||
/// @return The smallest region, that contains BB or NULL, if there is no
|
||||
/// region containing BB.
|
||||
Region *operator[](BasicBlock *BB) const;
|
||||
|
||||
/// @brief Return the exit of the maximal refined region, that starts at a
|
||||
/// BasicBlock.
|
||||
///
|
||||
/// @param BB The BasicBlock the refined region starts.
|
||||
BasicBlock *getMaxRegionExit(BasicBlock *BB) const;
|
||||
|
||||
/// @brief Find the smallest region that contains two regions.
|
||||
///
|
||||
/// @param A The first region.
|
||||
/// @param B The second region.
|
||||
/// @return The smallest region containing A and B.
|
||||
Region *getCommonRegion(Region* A, Region *B) const;
|
||||
|
||||
/// @brief Find the smallest region that contains two basic blocks.
|
||||
///
|
||||
/// @param A The first basic block.
|
||||
/// @param B The second basic block.
|
||||
/// @return The smallest region that contains A and B.
|
||||
Region* getCommonRegion(BasicBlock* A, BasicBlock *B) const {
|
||||
return getCommonRegion(getRegionFor(A), getRegionFor(B));
|
||||
}
|
||||
|
||||
/// @brief Find the smallest region that contains a set of regions.
|
||||
///
|
||||
/// @param Regions A vector of regions.
|
||||
/// @return The smallest region that contains all regions in Regions.
|
||||
Region* getCommonRegion(SmallVectorImpl<Region*> &Regions) const;
|
||||
|
||||
/// @brief Find the smallest region that contains a set of basic blocks.
|
||||
///
|
||||
/// @param BBs A vector of basic blocks.
|
||||
/// @return The smallest region that contains all basic blocks in BBS.
|
||||
Region* getCommonRegion(SmallVectorImpl<BasicBlock*> &BBs) const;
|
||||
|
||||
Region *getTopLevelRegion() const {
|
||||
return TopLevelRegion;
|
||||
}
|
||||
|
||||
/// @brief Update RegionInfo after a basic block was split.
|
||||
///
|
||||
/// @param NewBB The basic block that was created before OldBB.
|
||||
/// @param OldBB The old basic block.
|
||||
void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB);
|
||||
|
||||
/// @brief Clear the Node Cache for all Regions.
|
||||
///
|
||||
/// @see Region::clearNodeCache()
|
||||
void clearNodeCache() {
|
||||
if (TopLevelRegion)
|
||||
TopLevelRegion->clearNodeCache();
|
||||
}
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) {
|
||||
if (Node.isSubRegion())
|
||||
return OS << Node.getNodeAs<Region>()->getNameStr();
|
||||
else
|
||||
return OS << Node.getNodeAs<BasicBlock>()->getName();
|
||||
}
|
||||
} // End llvm namespace
|
||||
#endif
|
||||
|
||||
342
thirdparty/clang/include/llvm/Analysis/RegionIterator.h
vendored
Normal file
342
thirdparty/clang/include/llvm/Analysis/RegionIterator.h
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
//===- RegionIterator.h - Iterators to iteratate over Regions ---*- 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 iterators to iterate over the elements of a Region.
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef LLVM_ANALYSIS_REGIONITERATOR_H
|
||||
#define LLVM_ANALYSIS_REGIONITERATOR_H
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/RegionInfo.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @brief Hierarchical RegionNode successor iterator.
|
||||
///
|
||||
/// This iterator iterates over all successors of a RegionNode.
|
||||
///
|
||||
/// For a BasicBlock RegionNode it skips all BasicBlocks that are not part of
|
||||
/// the parent Region. Furthermore for BasicBlocks that start a subregion, a
|
||||
/// RegionNode representing the subregion is returned.
|
||||
///
|
||||
/// For a subregion RegionNode there is just one successor. The RegionNode
|
||||
/// representing the exit of the subregion.
|
||||
template<class NodeType>
|
||||
class RNSuccIterator : public std::iterator<std::forward_iterator_tag,
|
||||
NodeType, ptrdiff_t>
|
||||
{
|
||||
typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super;
|
||||
// The iterator works in two modes, bb mode or region mode.
|
||||
enum ItMode{
|
||||
// In BB mode it returns all successors of this BasicBlock as its
|
||||
// successors.
|
||||
ItBB,
|
||||
// In region mode there is only one successor, thats the regionnode mapping
|
||||
// to the exit block of the regionnode
|
||||
ItRgBegin, // At the beginning of the regionnode successor.
|
||||
ItRgEnd // At the end of the regionnode successor.
|
||||
};
|
||||
|
||||
// Use two bit to represent the mode iterator.
|
||||
PointerIntPair<NodeType*, 2, enum ItMode> Node;
|
||||
|
||||
// The block successor iterator.
|
||||
succ_iterator BItor;
|
||||
|
||||
// advanceRegionSucc - A region node has only one successor. It reaches end
|
||||
// once we advance it.
|
||||
void advanceRegionSucc() {
|
||||
assert(Node.getInt() == ItRgBegin && "Cannot advance region successor!");
|
||||
Node.setInt(ItRgEnd);
|
||||
}
|
||||
|
||||
NodeType* getNode() const{ return Node.getPointer(); }
|
||||
|
||||
// isRegionMode - Is the current iterator in region mode?
|
||||
bool isRegionMode() const { return Node.getInt() != ItBB; }
|
||||
|
||||
// Get the immediate successor. This function may return a Basic Block
|
||||
// RegionNode or a subregion RegionNode.
|
||||
RegionNode* getISucc(BasicBlock* BB) const {
|
||||
RegionNode *succ;
|
||||
succ = getNode()->getParent()->getNode(BB);
|
||||
assert(succ && "BB not in Region or entered subregion!");
|
||||
return succ;
|
||||
}
|
||||
|
||||
// getRegionSucc - Return the successor basic block of a SubRegion RegionNode.
|
||||
inline BasicBlock* getRegionSucc() const {
|
||||
assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!");
|
||||
return getNode()->template getNodeAs<Region>()->getExit();
|
||||
}
|
||||
|
||||
// isExit - Is this the exit BB of the Region?
|
||||
inline bool isExit(BasicBlock* BB) const {
|
||||
return getNode()->getParent()->getExit() == BB;
|
||||
}
|
||||
public:
|
||||
typedef RNSuccIterator<NodeType> Self;
|
||||
|
||||
typedef typename super::pointer pointer;
|
||||
|
||||
/// @brief Create begin iterator of a RegionNode.
|
||||
inline RNSuccIterator(NodeType* node)
|
||||
: Node(node, node->isSubRegion() ? ItRgBegin : ItBB),
|
||||
BItor(succ_begin(node->getEntry())) {
|
||||
|
||||
|
||||
// Skip the exit block
|
||||
if (!isRegionMode())
|
||||
while (succ_end(node->getEntry()) != BItor && isExit(*BItor))
|
||||
++BItor;
|
||||
|
||||
if (isRegionMode() && isExit(getRegionSucc()))
|
||||
advanceRegionSucc();
|
||||
}
|
||||
|
||||
/// @brief Create an end iterator.
|
||||
inline RNSuccIterator(NodeType* node, bool)
|
||||
: Node(node, node->isSubRegion() ? ItRgEnd : ItBB),
|
||||
BItor(succ_end(node->getEntry())) {}
|
||||
|
||||
inline bool operator==(const Self& x) const {
|
||||
assert(isRegionMode() == x.isRegionMode() && "Broken iterator!");
|
||||
if (isRegionMode())
|
||||
return Node.getInt() == x.Node.getInt();
|
||||
else
|
||||
return BItor == x.BItor;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
BasicBlock* BB = isRegionMode() ? getRegionSucc() : *BItor;
|
||||
assert(!isExit(BB) && "Iterator out of range!");
|
||||
return getISucc(BB);
|
||||
}
|
||||
|
||||
inline Self& operator++() {
|
||||
if(isRegionMode()) {
|
||||
// The Region only has 1 successor.
|
||||
advanceRegionSucc();
|
||||
} else {
|
||||
// Skip the exit.
|
||||
do
|
||||
++BItor;
|
||||
while (BItor != succ_end(getNode()->getEntry())
|
||||
&& isExit(*BItor));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Self operator++(int) {
|
||||
Self tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline const Self &operator=(const Self &I) {
|
||||
if (this != &I) {
|
||||
assert(getNode()->getParent() == I.getNode()->getParent()
|
||||
&& "Cannot assign iterators of two different regions!");
|
||||
Node = I.Node;
|
||||
BItor = I.BItor;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @brief Flat RegionNode iterator.
|
||||
///
|
||||
/// The Flat Region iterator will iterate over all BasicBlock RegionNodes that
|
||||
/// are contained in the Region and its subregions. This is close to a virtual
|
||||
/// control flow graph of the Region.
|
||||
template<class NodeType>
|
||||
class RNSuccIterator<FlatIt<NodeType> >
|
||||
: public std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t>
|
||||
{
|
||||
typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super;
|
||||
NodeType* Node;
|
||||
succ_iterator Itor;
|
||||
|
||||
public:
|
||||
typedef RNSuccIterator<FlatIt<NodeType> > Self;
|
||||
typedef typename super::pointer pointer;
|
||||
|
||||
/// @brief Create the iterator from a RegionNode.
|
||||
///
|
||||
/// Note that the incoming node must be a bb node, otherwise it will trigger
|
||||
/// an assertion when we try to get a BasicBlock.
|
||||
inline RNSuccIterator(NodeType* node) : Node(node),
|
||||
Itor(succ_begin(node->getEntry())) {
|
||||
assert(!Node->isSubRegion()
|
||||
&& "Subregion node not allowed in flat iterating mode!");
|
||||
assert(Node->getParent() && "A BB node must have a parent!");
|
||||
|
||||
// Skip the exit block of the iterating region.
|
||||
while (succ_end(Node->getEntry()) != Itor
|
||||
&& Node->getParent()->getExit() == *Itor)
|
||||
++Itor;
|
||||
}
|
||||
/// @brief Create an end iterator
|
||||
inline RNSuccIterator(NodeType* node, bool) : Node(node),
|
||||
Itor(succ_end(node->getEntry())) {
|
||||
assert(!Node->isSubRegion()
|
||||
&& "Subregion node not allowed in flat iterating mode!");
|
||||
}
|
||||
|
||||
inline bool operator==(const Self& x) const {
|
||||
assert(Node->getParent() == x.Node->getParent()
|
||||
&& "Cannot compare iterators of different regions!");
|
||||
|
||||
return Itor == x.Itor && Node == x.Node;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
BasicBlock* BB = *Itor;
|
||||
|
||||
// Get the iterating region.
|
||||
Region* Parent = Node->getParent();
|
||||
|
||||
// The only case that the successor reaches out of the region is it reaches
|
||||
// the exit of the region.
|
||||
assert(Parent->getExit() != BB && "iterator out of range!");
|
||||
|
||||
return Parent->getBBNode(BB);
|
||||
}
|
||||
|
||||
inline Self& operator++() {
|
||||
// Skip the exit block of the iterating region.
|
||||
do
|
||||
++Itor;
|
||||
while (Itor != succ_end(Node->getEntry())
|
||||
&& Node->getParent()->getExit() == *Itor);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Self operator++(int) {
|
||||
Self tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline const Self &operator=(const Self &I) {
|
||||
if (this != &I) {
|
||||
assert(Node->getParent() == I.Node->getParent()
|
||||
&& "Cannot assign iterators to two different regions!");
|
||||
Node = I.Node;
|
||||
Itor = I.Itor;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class NodeType>
|
||||
inline RNSuccIterator<NodeType> succ_begin(NodeType* Node) {
|
||||
return RNSuccIterator<NodeType>(Node);
|
||||
}
|
||||
|
||||
template<class NodeType>
|
||||
inline RNSuccIterator<NodeType> succ_end(NodeType* Node) {
|
||||
return RNSuccIterator<NodeType>(Node, true);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// RegionNode GraphTraits specialization so the bbs in the region can be
|
||||
// iterate by generic graph iterators.
|
||||
//
|
||||
// NodeT can either be region node or const region node, otherwise child_begin
|
||||
// and child_end fail.
|
||||
|
||||
#define RegionNodeGraphTraits(NodeT) \
|
||||
template<> struct GraphTraits<NodeT*> { \
|
||||
typedef NodeT NodeType; \
|
||||
typedef RNSuccIterator<NodeType> ChildIteratorType; \
|
||||
static NodeType *getEntryNode(NodeType* N) { return N; } \
|
||||
static inline ChildIteratorType child_begin(NodeType *N) { \
|
||||
return RNSuccIterator<NodeType>(N); \
|
||||
} \
|
||||
static inline ChildIteratorType child_end(NodeType *N) { \
|
||||
return RNSuccIterator<NodeType>(N, true); \
|
||||
} \
|
||||
}; \
|
||||
template<> struct GraphTraits<FlatIt<NodeT*> > { \
|
||||
typedef NodeT NodeType; \
|
||||
typedef RNSuccIterator<FlatIt<NodeT> > ChildIteratorType; \
|
||||
static NodeType *getEntryNode(NodeType* N) { return N; } \
|
||||
static inline ChildIteratorType child_begin(NodeType *N) { \
|
||||
return RNSuccIterator<FlatIt<NodeType> >(N); \
|
||||
} \
|
||||
static inline ChildIteratorType child_end(NodeType *N) { \
|
||||
return RNSuccIterator<FlatIt<NodeType> >(N, true); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define RegionGraphTraits(RegionT, NodeT) \
|
||||
template<> struct GraphTraits<RegionT*> \
|
||||
: public GraphTraits<NodeT*> { \
|
||||
typedef df_iterator<NodeType*> nodes_iterator; \
|
||||
static NodeType *getEntryNode(RegionT* R) { \
|
||||
return R->getNode(R->getEntry()); \
|
||||
} \
|
||||
static nodes_iterator nodes_begin(RegionT* R) { \
|
||||
return nodes_iterator::begin(getEntryNode(R)); \
|
||||
} \
|
||||
static nodes_iterator nodes_end(RegionT* R) { \
|
||||
return nodes_iterator::end(getEntryNode(R)); \
|
||||
} \
|
||||
}; \
|
||||
template<> struct GraphTraits<FlatIt<RegionT*> > \
|
||||
: public GraphTraits<FlatIt<NodeT*> > { \
|
||||
typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false, \
|
||||
GraphTraits<FlatIt<NodeType*> > > nodes_iterator; \
|
||||
static NodeType *getEntryNode(RegionT* R) { \
|
||||
return R->getBBNode(R->getEntry()); \
|
||||
} \
|
||||
static nodes_iterator nodes_begin(RegionT* R) { \
|
||||
return nodes_iterator::begin(getEntryNode(R)); \
|
||||
} \
|
||||
static nodes_iterator nodes_end(RegionT* R) { \
|
||||
return nodes_iterator::end(getEntryNode(R)); \
|
||||
} \
|
||||
}
|
||||
|
||||
RegionNodeGraphTraits(RegionNode);
|
||||
RegionNodeGraphTraits(const RegionNode);
|
||||
|
||||
RegionGraphTraits(Region, RegionNode);
|
||||
RegionGraphTraits(const Region, const RegionNode);
|
||||
|
||||
template <> struct GraphTraits<RegionInfo*>
|
||||
: public GraphTraits<FlatIt<RegionNode*> > {
|
||||
typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false,
|
||||
GraphTraits<FlatIt<NodeType*> > > nodes_iterator;
|
||||
|
||||
static NodeType *getEntryNode(RegionInfo *RI) {
|
||||
return GraphTraits<FlatIt<Region*> >::getEntryNode(RI->getTopLevelRegion());
|
||||
}
|
||||
static nodes_iterator nodes_begin(RegionInfo* RI) {
|
||||
return nodes_iterator::begin(getEntryNode(RI));
|
||||
}
|
||||
static nodes_iterator nodes_end(RegionInfo *RI) {
|
||||
return nodes_iterator::end(getEntryNode(RI));
|
||||
}
|
||||
};
|
||||
|
||||
} // End namespace llvm
|
||||
|
||||
#endif
|
||||
127
thirdparty/clang/include/llvm/Analysis/RegionPass.h
vendored
Normal file
127
thirdparty/clang/include/llvm/Analysis/RegionPass.h
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
//===- RegionPass.h - RegionPass class ------------------------------------===//
|
||||
//
|
||||
// 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 RegionPass class. All region based analysis,
|
||||
// optimization and transformation passes are derived from RegionPass.
|
||||
// This class is implemented following the some ideas of the LoopPass.h class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_REGIONPASS_H
|
||||
#define LLVM_ANALYSIS_REGIONPASS_H
|
||||
|
||||
#include "llvm/Analysis/RegionInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/PassManagers.h"
|
||||
#include <deque>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RGPassManager;
|
||||
class Function;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @brief A pass that runs on each Region in a function.
|
||||
///
|
||||
/// RegionPass is managed by RGPassManager.
|
||||
class RegionPass : public Pass {
|
||||
public:
|
||||
explicit RegionPass(char &pid) : Pass(PT_Region, pid) {}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// @name To be implemented by every RegionPass
|
||||
///
|
||||
//@{
|
||||
/// @brief Run the pass on a specific Region
|
||||
///
|
||||
/// Accessing regions not contained in the current region is not allowed.
|
||||
///
|
||||
/// @param R The region this pass is run on.
|
||||
/// @param RGM The RegionPassManager that manages this Pass.
|
||||
///
|
||||
/// @return True if the pass modifies this Region.
|
||||
virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0;
|
||||
|
||||
/// @brief Get a pass to print the LLVM IR in the region.
|
||||
///
|
||||
/// @param O The ouput stream to print the Region.
|
||||
/// @param Banner The banner to separate different printed passes.
|
||||
///
|
||||
/// @return The pass to print the LLVM IR in the region.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
using llvm::Pass::doInitialization;
|
||||
using llvm::Pass::doFinalization;
|
||||
|
||||
virtual bool doInitialization(Region *R, RGPassManager &RGM) { return false; }
|
||||
virtual bool doFinalization() { return false; }
|
||||
//@}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// @name PassManager API
|
||||
///
|
||||
//@{
|
||||
void preparePassManager(PMStack &PMS);
|
||||
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT = PMT_RegionPassManager);
|
||||
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_RegionPassManager;
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
/// @brief The pass manager to schedule RegionPasses.
|
||||
class RGPassManager : public FunctionPass, public PMDataManager {
|
||||
std::deque<Region*> RQ;
|
||||
bool skipThisRegion;
|
||||
bool redoThisRegion;
|
||||
RegionInfo *RI;
|
||||
Region *CurrentRegion;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
explicit RGPassManager();
|
||||
|
||||
/// @brief Execute all of the passes scheduled for execution.
|
||||
///
|
||||
/// @return True if any of the passes modifies the function.
|
||||
bool runOnFunction(Function &F);
|
||||
|
||||
/// Pass Manager itself does not invalidate any analysis info.
|
||||
/// RGPassManager needs RegionInfo.
|
||||
void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "Region Pass Manager";
|
||||
}
|
||||
|
||||
virtual PMDataManager *getAsPMDataManager() { return this; }
|
||||
virtual Pass *getAsPass() { return this; }
|
||||
|
||||
/// @brief Print passes managed by this manager.
|
||||
void dumpPassStructure(unsigned Offset);
|
||||
|
||||
/// @brief Get passes contained by this manager.
|
||||
Pass *getContainedPass(unsigned N) {
|
||||
assert(N < PassVector.size() && "Pass number out of range!");
|
||||
Pass *FP = static_cast<Pass *>(PassVector[N]);
|
||||
return FP;
|
||||
}
|
||||
|
||||
virtual PassManagerType getPassManagerType() const {
|
||||
return PMT_RegionPassManager;
|
||||
}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
26
thirdparty/clang/include/llvm/Analysis/RegionPrinter.h
vendored
Normal file
26
thirdparty/clang/include/llvm/Analysis/RegionPrinter.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//===-- RegionPrinter.h - Region printer external interface -----*- 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 external functions that can be called to explicitly
|
||||
// instantiate the region printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_REGIONPRINTER_H
|
||||
#define LLVM_ANALYSIS_REGIONPRINTER_H
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
FunctionPass *createRegionViewerPass();
|
||||
FunctionPass *createRegionOnlyViewerPass();
|
||||
FunctionPass *createRegionPrinterPass();
|
||||
FunctionPass *createRegionOnlyPrinterPass();
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
893
thirdparty/clang/include/llvm/Analysis/ScalarEvolution.h
vendored
Normal file
893
thirdparty/clang/include/llvm/Analysis/ScalarEvolution.h
vendored
Normal file
@@ -0,0 +1,893 @@
|
||||
//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ScalarEvolution class is an LLVM pass which can be used to analyze and
|
||||
// categorize scalar expressions in loops. It specializes in recognizing
|
||||
// general induction variables, representing them with the abstract and opaque
|
||||
// SCEV class. Given this analysis, trip counts of loops and other important
|
||||
// properties can be obtained.
|
||||
//
|
||||
// This analysis is primarily useful for induction variable substitution and
|
||||
// strength reduction.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H
|
||||
#define LLVM_ANALYSIS_SCALAREVOLUTION_H
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/ConstantRange.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
class APInt;
|
||||
class Constant;
|
||||
class ConstantInt;
|
||||
class DominatorTree;
|
||||
class Type;
|
||||
class ScalarEvolution;
|
||||
class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class LLVMContext;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
class Operator;
|
||||
class SCEVUnknown;
|
||||
class SCEV;
|
||||
template<> struct FoldingSetTrait<SCEV>;
|
||||
|
||||
/// SCEV - This class represents an analyzed expression in the program. These
|
||||
/// are opaque objects that the client is not allowed to do much with
|
||||
/// directly.
|
||||
///
|
||||
class SCEV : public FoldingSetNode {
|
||||
friend struct FoldingSetTrait<SCEV>;
|
||||
|
||||
/// FastID - A reference to an Interned FoldingSetNodeID for this node.
|
||||
/// The ScalarEvolution's BumpPtrAllocator holds the data.
|
||||
FoldingSetNodeIDRef FastID;
|
||||
|
||||
// The SCEV baseclass this node corresponds to
|
||||
const unsigned short SCEVType;
|
||||
|
||||
protected:
|
||||
/// SubclassData - This field is initialized to zero and may be used in
|
||||
/// subclasses to store miscellaneous information.
|
||||
unsigned short SubclassData;
|
||||
|
||||
private:
|
||||
SCEV(const SCEV &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const SCEV &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
public:
|
||||
/// NoWrapFlags are bitfield indices into SubclassData.
|
||||
///
|
||||
/// Add and Mul expressions may have no-unsigned-wrap <NUW> or
|
||||
/// no-signed-wrap <NSW> properties, which are derived from the IR
|
||||
/// operator. NSW is a misnomer that we use to mean no signed overflow or
|
||||
/// underflow.
|
||||
///
|
||||
/// AddRec expression may have a no-self-wraparound <NW> property if the
|
||||
/// result can never reach the start value. This property is independent of
|
||||
/// the actual start value and step direction. Self-wraparound is defined
|
||||
/// purely in terms of the recurrence's loop, step size, and
|
||||
/// bitwidth. Formally, a recurrence with no self-wraparound satisfies:
|
||||
/// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth).
|
||||
///
|
||||
/// Note that NUW and NSW are also valid properties of a recurrence, and
|
||||
/// either implies NW. For convenience, NW will be set for a recurrence
|
||||
/// whenever either NUW or NSW are set.
|
||||
enum NoWrapFlags { FlagAnyWrap = 0, // No guarantee.
|
||||
FlagNW = (1 << 0), // No self-wrap.
|
||||
FlagNUW = (1 << 1), // No unsigned wrap.
|
||||
FlagNSW = (1 << 2), // No signed wrap.
|
||||
NoWrapMask = (1 << 3) -1 };
|
||||
|
||||
explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) :
|
||||
FastID(ID), SCEVType(SCEVTy), SubclassData(0) {}
|
||||
|
||||
unsigned getSCEVType() const { return SCEVType; }
|
||||
|
||||
/// getType - Return the LLVM type of this SCEV expression.
|
||||
///
|
||||
Type *getType() const;
|
||||
|
||||
/// isZero - Return true if the expression is a constant zero.
|
||||
///
|
||||
bool isZero() const;
|
||||
|
||||
/// isOne - Return true if the expression is a constant one.
|
||||
///
|
||||
bool isOne() const;
|
||||
|
||||
/// isAllOnesValue - Return true if the expression is a constant
|
||||
/// all-ones value.
|
||||
///
|
||||
bool isAllOnesValue() const;
|
||||
|
||||
/// isNonConstantNegative - Return true if the specified scev is negated,
|
||||
/// but not a constant.
|
||||
bool isNonConstantNegative() const;
|
||||
|
||||
/// print - Print out the internal representation of this scalar to the
|
||||
/// specified stream. This should really only be used for debugging
|
||||
/// purposes.
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
/// dump - This method is used for debugging.
|
||||
///
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
// Specialize FoldingSetTrait for SCEV to avoid needing to compute
|
||||
// temporary FoldingSetNodeID values.
|
||||
template<> struct FoldingSetTrait<SCEV> : DefaultFoldingSetTrait<SCEV> {
|
||||
static void Profile(const SCEV &X, FoldingSetNodeID& ID) {
|
||||
ID = X.FastID;
|
||||
}
|
||||
static bool Equals(const SCEV &X, const FoldingSetNodeID &ID,
|
||||
unsigned IDHash, FoldingSetNodeID &TempID) {
|
||||
return ID == X.FastID;
|
||||
}
|
||||
static unsigned ComputeHash(const SCEV &X, FoldingSetNodeID &TempID) {
|
||||
return X.FastID.ComputeHash();
|
||||
}
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const SCEV &S) {
|
||||
S.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
/// SCEVCouldNotCompute - An object of this class is returned by queries that
|
||||
/// could not be answered. For example, if you ask for the number of
|
||||
/// iterations of a linked-list traversal loop, you will get one of these.
|
||||
/// None of the standard SCEV operations are valid on this class, it is just a
|
||||
/// marker.
|
||||
struct SCEVCouldNotCompute : public SCEV {
|
||||
SCEVCouldNotCompute();
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static bool classof(const SCEV *S);
|
||||
};
|
||||
|
||||
/// ScalarEvolution - This class is the main scalar evolution driver. Because
|
||||
/// client code (intentionally) can't do much with the SCEV objects directly,
|
||||
/// they must ask this class for services.
|
||||
///
|
||||
class ScalarEvolution : public FunctionPass {
|
||||
public:
|
||||
/// LoopDisposition - An enum describing the relationship between a
|
||||
/// SCEV and a loop.
|
||||
enum LoopDisposition {
|
||||
LoopVariant, ///< The SCEV is loop-variant (unknown).
|
||||
LoopInvariant, ///< The SCEV is loop-invariant.
|
||||
LoopComputable ///< The SCEV varies predictably with the loop.
|
||||
};
|
||||
|
||||
/// BlockDisposition - An enum describing the relationship between a
|
||||
/// SCEV and a basic block.
|
||||
enum BlockDisposition {
|
||||
DoesNotDominateBlock, ///< The SCEV does not dominate the block.
|
||||
DominatesBlock, ///< The SCEV dominates the block.
|
||||
ProperlyDominatesBlock ///< The SCEV properly dominates the block.
|
||||
};
|
||||
|
||||
/// Convenient NoWrapFlags manipulation that hides enum casts and is
|
||||
/// visible in the ScalarEvolution name space.
|
||||
static SCEV::NoWrapFlags maskFlags(SCEV::NoWrapFlags Flags, int Mask) {
|
||||
return (SCEV::NoWrapFlags)(Flags & Mask);
|
||||
}
|
||||
static SCEV::NoWrapFlags setFlags(SCEV::NoWrapFlags Flags,
|
||||
SCEV::NoWrapFlags OnFlags) {
|
||||
return (SCEV::NoWrapFlags)(Flags | OnFlags);
|
||||
}
|
||||
static SCEV::NoWrapFlags clearFlags(SCEV::NoWrapFlags Flags,
|
||||
SCEV::NoWrapFlags OffFlags) {
|
||||
return (SCEV::NoWrapFlags)(Flags & ~OffFlags);
|
||||
}
|
||||
|
||||
private:
|
||||
/// SCEVCallbackVH - A CallbackVH to arrange for ScalarEvolution to be
|
||||
/// notified whenever a Value is deleted.
|
||||
class SCEVCallbackVH : public CallbackVH {
|
||||
ScalarEvolution *SE;
|
||||
virtual void deleted();
|
||||
virtual void allUsesReplacedWith(Value *New);
|
||||
public:
|
||||
SCEVCallbackVH(Value *V, ScalarEvolution *SE = 0);
|
||||
};
|
||||
|
||||
friend class SCEVCallbackVH;
|
||||
friend class SCEVExpander;
|
||||
friend class SCEVUnknown;
|
||||
|
||||
/// F - The function we are analyzing.
|
||||
///
|
||||
Function *F;
|
||||
|
||||
/// LI - The loop information for the function we are currently analyzing.
|
||||
///
|
||||
LoopInfo *LI;
|
||||
|
||||
/// TD - The target data information for the target we are targeting.
|
||||
///
|
||||
DataLayout *TD;
|
||||
|
||||
/// TLI - The target library information for the target we are targeting.
|
||||
///
|
||||
TargetLibraryInfo *TLI;
|
||||
|
||||
/// DT - The dominator tree.
|
||||
///
|
||||
DominatorTree *DT;
|
||||
|
||||
/// CouldNotCompute - This SCEV is used to represent unknown trip
|
||||
/// counts and things.
|
||||
SCEVCouldNotCompute CouldNotCompute;
|
||||
|
||||
/// ValueExprMapType - The typedef for ValueExprMap.
|
||||
///
|
||||
typedef DenseMap<SCEVCallbackVH, const SCEV *, DenseMapInfo<Value *> >
|
||||
ValueExprMapType;
|
||||
|
||||
/// ValueExprMap - This is a cache of the values we have analyzed so far.
|
||||
///
|
||||
ValueExprMapType ValueExprMap;
|
||||
|
||||
/// Mark predicate values currently being processed by isImpliedCond.
|
||||
DenseSet<Value*> PendingLoopPredicates;
|
||||
|
||||
/// ExitLimit - Information about the number of loop iterations for
|
||||
/// which a loop exit's branch condition evaluates to the not-taken path.
|
||||
/// This is a temporary pair of exact and max expressions that are
|
||||
/// eventually summarized in ExitNotTakenInfo and BackedgeTakenInfo.
|
||||
struct ExitLimit {
|
||||
const SCEV *Exact;
|
||||
const SCEV *Max;
|
||||
|
||||
/*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
|
||||
|
||||
ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {}
|
||||
|
||||
/// hasAnyInfo - Test whether this ExitLimit contains any computed
|
||||
/// information, or whether it's all SCEVCouldNotCompute values.
|
||||
bool hasAnyInfo() const {
|
||||
return !isa<SCEVCouldNotCompute>(Exact) ||
|
||||
!isa<SCEVCouldNotCompute>(Max);
|
||||
}
|
||||
};
|
||||
|
||||
/// ExitNotTakenInfo - Information about the number of times a particular
|
||||
/// loop exit may be reached before exiting the loop.
|
||||
struct ExitNotTakenInfo {
|
||||
AssertingVH<BasicBlock> ExitingBlock;
|
||||
const SCEV *ExactNotTaken;
|
||||
PointerIntPair<ExitNotTakenInfo*, 1> NextExit;
|
||||
|
||||
ExitNotTakenInfo() : ExitingBlock(0), ExactNotTaken(0) {}
|
||||
|
||||
/// isCompleteList - Return true if all loop exits are computable.
|
||||
bool isCompleteList() const {
|
||||
return NextExit.getInt() == 0;
|
||||
}
|
||||
|
||||
void setIncomplete() { NextExit.setInt(1); }
|
||||
|
||||
/// getNextExit - Return a pointer to the next exit's not-taken info.
|
||||
ExitNotTakenInfo *getNextExit() const {
|
||||
return NextExit.getPointer();
|
||||
}
|
||||
|
||||
void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); }
|
||||
};
|
||||
|
||||
/// BackedgeTakenInfo - Information about the backedge-taken count
|
||||
/// of a loop. This currently includes an exact count and a maximum count.
|
||||
///
|
||||
class BackedgeTakenInfo {
|
||||
/// ExitNotTaken - A list of computable exits and their not-taken counts.
|
||||
/// Loops almost never have more than one computable exit.
|
||||
ExitNotTakenInfo ExitNotTaken;
|
||||
|
||||
/// Max - An expression indicating the least maximum backedge-taken
|
||||
/// count of the loop that is known, or a SCEVCouldNotCompute.
|
||||
const SCEV *Max;
|
||||
|
||||
public:
|
||||
BackedgeTakenInfo() : Max(0) {}
|
||||
|
||||
/// Initialize BackedgeTakenInfo from a list of exact exit counts.
|
||||
BackedgeTakenInfo(
|
||||
SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
|
||||
bool Complete, const SCEV *MaxCount);
|
||||
|
||||
/// hasAnyInfo - Test whether this BackedgeTakenInfo contains any
|
||||
/// computed information, or whether it's all SCEVCouldNotCompute
|
||||
/// values.
|
||||
bool hasAnyInfo() const {
|
||||
return ExitNotTaken.ExitingBlock || !isa<SCEVCouldNotCompute>(Max);
|
||||
}
|
||||
|
||||
/// getExact - Return an expression indicating the exact backedge-taken
|
||||
/// count of the loop if it is known, or SCEVCouldNotCompute
|
||||
/// otherwise. This is the number of times the loop header can be
|
||||
/// guaranteed to execute, minus one.
|
||||
const SCEV *getExact(ScalarEvolution *SE) const;
|
||||
|
||||
/// getExact - Return the number of times this loop exit may fall through
|
||||
/// to the back edge, or SCEVCouldNotCompute. The loop is guaranteed not
|
||||
/// to exit via this block before this number of iterations, but may exit
|
||||
/// via another block.
|
||||
const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const;
|
||||
|
||||
/// getMax - Get the max backedge taken count for the loop.
|
||||
const SCEV *getMax(ScalarEvolution *SE) const;
|
||||
|
||||
/// Return true if any backedge taken count expressions refer to the given
|
||||
/// subexpression.
|
||||
bool hasOperand(const SCEV *S, ScalarEvolution *SE) const;
|
||||
|
||||
/// clear - Invalidate this result and free associated memory.
|
||||
void clear();
|
||||
};
|
||||
|
||||
/// BackedgeTakenCounts - Cache the backedge-taken count of the loops for
|
||||
/// this function as they are computed.
|
||||
DenseMap<const Loop*, BackedgeTakenInfo> BackedgeTakenCounts;
|
||||
|
||||
/// ConstantEvolutionLoopExitValue - This map contains entries for all of
|
||||
/// the PHI instructions that we attempt to compute constant evolutions for.
|
||||
/// This allows us to avoid potentially expensive recomputation of these
|
||||
/// properties. An instruction maps to null if we are unable to compute its
|
||||
/// exit value.
|
||||
DenseMap<PHINode*, Constant*> ConstantEvolutionLoopExitValue;
|
||||
|
||||
/// ValuesAtScopes - This map contains entries for all the expressions
|
||||
/// that we attempt to compute getSCEVAtScope information for, which can
|
||||
/// be expensive in extreme cases.
|
||||
DenseMap<const SCEV *,
|
||||
std::map<const Loop *, const SCEV *> > ValuesAtScopes;
|
||||
|
||||
/// LoopDispositions - Memoized computeLoopDisposition results.
|
||||
DenseMap<const SCEV *,
|
||||
std::map<const Loop *, LoopDisposition> > LoopDispositions;
|
||||
|
||||
/// computeLoopDisposition - Compute a LoopDisposition value.
|
||||
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
|
||||
|
||||
/// BlockDispositions - Memoized computeBlockDisposition results.
|
||||
DenseMap<const SCEV *,
|
||||
std::map<const BasicBlock *, BlockDisposition> > BlockDispositions;
|
||||
|
||||
/// computeBlockDisposition - Compute a BlockDisposition value.
|
||||
BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB);
|
||||
|
||||
/// UnsignedRanges - Memoized results from getUnsignedRange
|
||||
DenseMap<const SCEV *, ConstantRange> UnsignedRanges;
|
||||
|
||||
/// SignedRanges - Memoized results from getSignedRange
|
||||
DenseMap<const SCEV *, ConstantRange> SignedRanges;
|
||||
|
||||
/// setUnsignedRange - Set the memoized unsigned range for the given SCEV.
|
||||
const ConstantRange &setUnsignedRange(const SCEV *S,
|
||||
const ConstantRange &CR) {
|
||||
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
|
||||
UnsignedRanges.insert(std::make_pair(S, CR));
|
||||
if (!Pair.second)
|
||||
Pair.first->second = CR;
|
||||
return Pair.first->second;
|
||||
}
|
||||
|
||||
/// setUnsignedRange - Set the memoized signed range for the given SCEV.
|
||||
const ConstantRange &setSignedRange(const SCEV *S,
|
||||
const ConstantRange &CR) {
|
||||
std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair =
|
||||
SignedRanges.insert(std::make_pair(S, CR));
|
||||
if (!Pair.second)
|
||||
Pair.first->second = CR;
|
||||
return Pair.first->second;
|
||||
}
|
||||
|
||||
/// createSCEV - We know that there is no SCEV for the specified value.
|
||||
/// Analyze the expression.
|
||||
const SCEV *createSCEV(Value *V);
|
||||
|
||||
/// createNodeForPHI - Provide the special handling we need to analyze PHI
|
||||
/// SCEVs.
|
||||
const SCEV *createNodeForPHI(PHINode *PN);
|
||||
|
||||
/// createNodeForGEP - Provide the special handling we need to analyze GEP
|
||||
/// SCEVs.
|
||||
const SCEV *createNodeForGEP(GEPOperator *GEP);
|
||||
|
||||
/// computeSCEVAtScope - Implementation code for getSCEVAtScope; called
|
||||
/// at most once for each SCEV+Loop pair.
|
||||
///
|
||||
const SCEV *computeSCEVAtScope(const SCEV *S, const Loop *L);
|
||||
|
||||
/// ForgetSymbolicValue - This looks up computed SCEV values for all
|
||||
/// instructions that depend on the given instruction and removes them from
|
||||
/// the ValueExprMap map if they reference SymName. This is used during PHI
|
||||
/// resolution.
|
||||
void ForgetSymbolicName(Instruction *I, const SCEV *SymName);
|
||||
|
||||
/// getBECount - Subtract the end and start values and divide by the step,
|
||||
/// rounding up, to get the number of times the backedge is executed. Return
|
||||
/// CouldNotCompute if an intermediate computation overflows.
|
||||
const SCEV *getBECount(const SCEV *Start,
|
||||
const SCEV *End,
|
||||
const SCEV *Step,
|
||||
bool NoWrap);
|
||||
|
||||
/// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given
|
||||
/// loop, lazily computing new values if the loop hasn't been analyzed
|
||||
/// yet.
|
||||
const BackedgeTakenInfo &getBackedgeTakenInfo(const Loop *L);
|
||||
|
||||
/// ComputeBackedgeTakenCount - Compute the number of times the specified
|
||||
/// loop will iterate.
|
||||
BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L);
|
||||
|
||||
/// ComputeExitLimit - Compute the number of times the backedge of the
|
||||
/// specified loop will execute if it exits via the specified block.
|
||||
ExitLimit ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
/// ComputeExitLimitFromCond - Compute the number of times the backedge of
|
||||
/// the specified loop will execute if its exit condition were a conditional
|
||||
/// branch of ExitCond, TBB, and FBB.
|
||||
ExitLimit ComputeExitLimitFromCond(const Loop *L,
|
||||
Value *ExitCond,
|
||||
BasicBlock *TBB,
|
||||
BasicBlock *FBB);
|
||||
|
||||
/// ComputeExitLimitFromICmp - Compute the number of times the backedge of
|
||||
/// the specified loop will execute if its exit condition were a conditional
|
||||
/// branch of the ICmpInst ExitCond, TBB, and FBB.
|
||||
ExitLimit ComputeExitLimitFromICmp(const Loop *L,
|
||||
ICmpInst *ExitCond,
|
||||
BasicBlock *TBB,
|
||||
BasicBlock *FBB);
|
||||
|
||||
/// ComputeLoadConstantCompareExitLimit - Given an exit condition
|
||||
/// of 'icmp op load X, cst', try to see if we can compute the
|
||||
/// backedge-taken count.
|
||||
ExitLimit ComputeLoadConstantCompareExitLimit(LoadInst *LI,
|
||||
Constant *RHS,
|
||||
const Loop *L,
|
||||
ICmpInst::Predicate p);
|
||||
|
||||
/// ComputeExitCountExhaustively - If the loop is known to execute a
|
||||
/// constant number of times (the condition evolves only from constants),
|
||||
/// try to evaluate a few iterations of the loop until we get the exit
|
||||
/// condition gets a value of ExitWhen (true or false). If we cannot
|
||||
/// evaluate the exit count of the loop, return CouldNotCompute.
|
||||
const SCEV *ComputeExitCountExhaustively(const Loop *L,
|
||||
Value *Cond,
|
||||
bool ExitWhen);
|
||||
|
||||
/// HowFarToZero - Return the number of times an exit condition comparing
|
||||
/// the specified value to zero will execute. If not computable, return
|
||||
/// CouldNotCompute.
|
||||
ExitLimit HowFarToZero(const SCEV *V, const Loop *L);
|
||||
|
||||
/// HowFarToNonZero - Return the number of times an exit condition checking
|
||||
/// the specified value for nonzero will execute. If not computable, return
|
||||
/// CouldNotCompute.
|
||||
ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L);
|
||||
|
||||
/// HowManyLessThans - Return the number of times an exit condition
|
||||
/// containing the specified less-than comparison will execute. If not
|
||||
/// computable, return CouldNotCompute. isSigned specifies whether the
|
||||
/// less-than is signed.
|
||||
ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
||||
const Loop *L, bool isSigned);
|
||||
|
||||
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
|
||||
/// (which may not be an immediate predecessor) which has exactly one
|
||||
/// successor from which BB is reachable, or null if no such block is
|
||||
/// found.
|
||||
std::pair<BasicBlock *, BasicBlock *>
|
||||
getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB);
|
||||
|
||||
/// isImpliedCond - Test whether the condition described by Pred, LHS, and
|
||||
/// RHS is true whenever the given FoundCondValue value evaluates to true.
|
||||
bool isImpliedCond(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS,
|
||||
Value *FoundCondValue,
|
||||
bool Inverse);
|
||||
|
||||
/// isImpliedCondOperands - Test whether the condition described by Pred,
|
||||
/// LHS, and RHS is true whenever the condition described by Pred, FoundLHS,
|
||||
/// and FoundRHS is true.
|
||||
bool isImpliedCondOperands(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS,
|
||||
const SCEV *FoundLHS, const SCEV *FoundRHS);
|
||||
|
||||
/// isImpliedCondOperandsHelper - Test whether the condition described by
|
||||
/// Pred, LHS, and RHS is true whenever the condition described by Pred,
|
||||
/// FoundLHS, and FoundRHS is true.
|
||||
bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS,
|
||||
const SCEV *FoundLHS,
|
||||
const SCEV *FoundRHS);
|
||||
|
||||
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
|
||||
/// in the header of its containing loop, we know the loop executes a
|
||||
/// constant number of times, and the PHI node is just a recurrence
|
||||
/// involving constants, fold it.
|
||||
Constant *getConstantEvolutionLoopExitValue(PHINode *PN, const APInt& BEs,
|
||||
const Loop *L);
|
||||
|
||||
/// isKnownPredicateWithRanges - Test if the given expression is known to
|
||||
/// satisfy the condition described by Pred and the known constant ranges
|
||||
/// of LHS and RHS.
|
||||
///
|
||||
bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// forgetMemoizedResults - Drop memoized information computed for S.
|
||||
void forgetMemoizedResults(const SCEV *S);
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
ScalarEvolution();
|
||||
|
||||
LLVMContext &getContext() const { return F->getContext(); }
|
||||
|
||||
/// isSCEVable - Test if values of the given type are analyzable within
|
||||
/// the SCEV framework. This primarily includes integer types, and it
|
||||
/// can optionally include pointer types if the ScalarEvolution class
|
||||
/// has access to target-specific information.
|
||||
bool isSCEVable(Type *Ty) const;
|
||||
|
||||
/// getTypeSizeInBits - Return the size in bits of the specified type,
|
||||
/// for which isSCEVable must return true.
|
||||
uint64_t getTypeSizeInBits(Type *Ty) const;
|
||||
|
||||
/// getEffectiveSCEVType - Return a type with the same bitwidth as
|
||||
/// the given type and which represents how SCEV will treat the given
|
||||
/// type, for which isSCEVable must return true. For pointer types,
|
||||
/// this is the pointer-sized integer type.
|
||||
Type *getEffectiveSCEVType(Type *Ty) const;
|
||||
|
||||
/// getSCEV - Return a SCEV expression for the full generality of the
|
||||
/// specified expression.
|
||||
const SCEV *getSCEV(Value *V);
|
||||
|
||||
const SCEV *getConstant(ConstantInt *V);
|
||||
const SCEV *getConstant(const APInt& Val);
|
||||
const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
|
||||
const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty);
|
||||
const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty);
|
||||
const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
|
||||
const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
|
||||
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
|
||||
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
|
||||
SmallVector<const SCEV *, 2> Ops;
|
||||
Ops.push_back(LHS);
|
||||
Ops.push_back(RHS);
|
||||
return getAddExpr(Ops, Flags);
|
||||
}
|
||||
const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
|
||||
SmallVector<const SCEV *, 3> Ops;
|
||||
Ops.push_back(Op0);
|
||||
Ops.push_back(Op1);
|
||||
Ops.push_back(Op2);
|
||||
return getAddExpr(Ops, Flags);
|
||||
}
|
||||
const SCEV *getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
|
||||
const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap)
|
||||
{
|
||||
SmallVector<const SCEV *, 2> Ops;
|
||||
Ops.push_back(LHS);
|
||||
Ops.push_back(RHS);
|
||||
return getMulExpr(Ops, Flags);
|
||||
}
|
||||
const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
|
||||
SmallVector<const SCEV *, 3> Ops;
|
||||
Ops.push_back(Op0);
|
||||
Ops.push_back(Op1);
|
||||
Ops.push_back(Op2);
|
||||
return getMulExpr(Ops, Flags);
|
||||
}
|
||||
const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
|
||||
const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step,
|
||||
const Loop *L, SCEV::NoWrapFlags Flags);
|
||||
const SCEV *getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
|
||||
const Loop *L, SCEV::NoWrapFlags Flags);
|
||||
const SCEV *getAddRecExpr(const SmallVectorImpl<const SCEV *> &Operands,
|
||||
const Loop *L, SCEV::NoWrapFlags Flags) {
|
||||
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
|
||||
return getAddRecExpr(NewOp, L, Flags);
|
||||
}
|
||||
const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS);
|
||||
const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
|
||||
const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
|
||||
const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
|
||||
const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS);
|
||||
const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS);
|
||||
const SCEV *getUnknown(Value *V);
|
||||
const SCEV *getCouldNotCompute();
|
||||
|
||||
/// getSizeOfExpr - Return an expression for sizeof on the given type.
|
||||
///
|
||||
const SCEV *getSizeOfExpr(Type *AllocTy);
|
||||
|
||||
/// getAlignOfExpr - Return an expression for alignof on the given type.
|
||||
///
|
||||
const SCEV *getAlignOfExpr(Type *AllocTy);
|
||||
|
||||
/// getOffsetOfExpr - Return an expression for offsetof on the given field.
|
||||
///
|
||||
const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo);
|
||||
|
||||
/// getOffsetOfExpr - Return an expression for offsetof on the given field.
|
||||
///
|
||||
const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo);
|
||||
|
||||
/// getNegativeSCEV - Return the SCEV object corresponding to -V.
|
||||
///
|
||||
const SCEV *getNegativeSCEV(const SCEV *V);
|
||||
|
||||
/// getNotSCEV - Return the SCEV object corresponding to ~V.
|
||||
///
|
||||
const SCEV *getNotSCEV(const SCEV *V);
|
||||
|
||||
/// getMinusSCEV - Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
|
||||
const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
|
||||
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
|
||||
|
||||
/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion
|
||||
/// of the input value to the specified type. If the type must be
|
||||
/// extended, it is zero extended.
|
||||
const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion
|
||||
/// of the input value to the specified type. If the type must be
|
||||
/// extended, it is sign extended.
|
||||
const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of
|
||||
/// the input value to the specified type. If the type must be extended,
|
||||
/// it is zero extended. The conversion must not be narrowing.
|
||||
const SCEV *getNoopOrZeroExtend(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of
|
||||
/// the input value to the specified type. If the type must be extended,
|
||||
/// it is sign extended. The conversion must not be narrowing.
|
||||
const SCEV *getNoopOrSignExtend(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of
|
||||
/// the input value to the specified type. If the type must be extended,
|
||||
/// it is extended with unspecified bits. The conversion must not be
|
||||
/// narrowing.
|
||||
const SCEV *getNoopOrAnyExtend(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the
|
||||
/// input value to the specified type. The conversion must not be
|
||||
/// widening.
|
||||
const SCEV *getTruncateOrNoop(const SCEV *V, Type *Ty);
|
||||
|
||||
/// getUMaxFromMismatchedTypes - Promote the operands to the wider of
|
||||
/// the types using zero-extension, and then perform a umax operation
|
||||
/// with them.
|
||||
const SCEV *getUMaxFromMismatchedTypes(const SCEV *LHS,
|
||||
const SCEV *RHS);
|
||||
|
||||
/// getUMinFromMismatchedTypes - Promote the operands to the wider of
|
||||
/// the types using zero-extension, and then perform a umin operation
|
||||
/// with them.
|
||||
const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS,
|
||||
const SCEV *RHS);
|
||||
|
||||
/// getPointerBase - Transitively follow the chain of pointer-type operands
|
||||
/// until reaching a SCEV that does not have a single pointer operand. This
|
||||
/// returns a SCEVUnknown pointer for well-formed pointer-type expressions,
|
||||
/// but corner cases do exist.
|
||||
const SCEV *getPointerBase(const SCEV *V);
|
||||
|
||||
/// getSCEVAtScope - Return a SCEV expression for the specified value
|
||||
/// at the specified scope in the program. The L value specifies a loop
|
||||
/// nest to evaluate the expression at, where null is the top-level or a
|
||||
/// specified loop is immediately inside of the loop.
|
||||
///
|
||||
/// This method can be used to compute the exit value for a variable defined
|
||||
/// in a loop by querying what the value will hold in the parent loop.
|
||||
///
|
||||
/// In the case that a relevant loop exit value cannot be computed, the
|
||||
/// original value V is returned.
|
||||
const SCEV *getSCEVAtScope(const SCEV *S, const Loop *L);
|
||||
|
||||
/// getSCEVAtScope - This is a convenience function which does
|
||||
/// getSCEVAtScope(getSCEV(V), L).
|
||||
const SCEV *getSCEVAtScope(Value *V, const Loop *L);
|
||||
|
||||
/// isLoopEntryGuardedByCond - Test whether entry to the loop is protected
|
||||
/// by a conditional between LHS and RHS. This is used to help avoid max
|
||||
/// expressions in loop trip counts, and to eliminate casts.
|
||||
bool isLoopEntryGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// isLoopBackedgeGuardedByCond - Test whether the backedge of the loop is
|
||||
/// protected by a conditional between LHS and RHS. This is used to
|
||||
/// to eliminate casts.
|
||||
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// getSmallConstantTripCount - Returns the maximum trip count of this loop
|
||||
/// as a normal unsigned value. Returns 0 if the trip count is unknown or
|
||||
/// not constant. This "trip count" assumes that control exits via
|
||||
/// ExitingBlock. More precisely, it is the number of times that control may
|
||||
/// reach ExitingBlock before taking the branch. For loops with multiple
|
||||
/// exits, it may not be the number times that the loop header executes if
|
||||
/// the loop exits prematurely via another branch.
|
||||
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
/// getSmallConstantTripMultiple - Returns the largest constant divisor of
|
||||
/// the trip count of this loop as a normal unsigned value, if
|
||||
/// possible. This means that the actual trip count is always a multiple of
|
||||
/// the returned value (don't forget the trip count could very well be zero
|
||||
/// as well!). As explained in the comments for getSmallConstantTripCount,
|
||||
/// this assumes that control exits the loop via ExitingBlock.
|
||||
unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
// getExitCount - Get the expression for the number of loop iterations for
|
||||
// which this loop is guaranteed not to exit via ExitingBlock. Otherwise
|
||||
// return SCEVCouldNotCompute.
|
||||
const SCEV *getExitCount(Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
/// getBackedgeTakenCount - If the specified loop has a predictable
|
||||
/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute
|
||||
/// object. The backedge-taken count is the number of times the loop header
|
||||
/// will be branched to from within the loop. This is one less than the
|
||||
/// trip count of the loop, since it doesn't count the first iteration,
|
||||
/// when the header is branched to from outside the loop.
|
||||
///
|
||||
/// Note that it is not valid to call this method on a loop without a
|
||||
/// loop-invariant backedge-taken count (see
|
||||
/// hasLoopInvariantBackedgeTakenCount).
|
||||
///
|
||||
const SCEV *getBackedgeTakenCount(const Loop *L);
|
||||
|
||||
/// getMaxBackedgeTakenCount - Similar to getBackedgeTakenCount, except
|
||||
/// return the least SCEV value that is known never to be less than the
|
||||
/// actual backedge taken count.
|
||||
const SCEV *getMaxBackedgeTakenCount(const Loop *L);
|
||||
|
||||
/// hasLoopInvariantBackedgeTakenCount - Return true if the specified loop
|
||||
/// has an analyzable loop-invariant backedge-taken count.
|
||||
bool hasLoopInvariantBackedgeTakenCount(const Loop *L);
|
||||
|
||||
/// forgetLoop - This method should be called by the client when it has
|
||||
/// changed a loop in a way that may effect ScalarEvolution's ability to
|
||||
/// compute a trip count, or if the loop is deleted.
|
||||
void forgetLoop(const Loop *L);
|
||||
|
||||
/// forgetValue - This method should be called by the client when it has
|
||||
/// changed a value in a way that may effect its value, or which may
|
||||
/// disconnect it from a def-use chain linking it to a loop.
|
||||
void forgetValue(Value *V);
|
||||
|
||||
/// GetMinTrailingZeros - Determine the minimum number of zero bits that S
|
||||
/// is guaranteed to end in (at every loop iteration). It is, at the same
|
||||
/// time, the minimum number of times S is divisible by 2. For example,
|
||||
/// given {4,+,8} it returns 2. If S is guaranteed to be 0, it returns the
|
||||
/// bitwidth of S.
|
||||
uint32_t GetMinTrailingZeros(const SCEV *S);
|
||||
|
||||
/// getUnsignedRange - Determine the unsigned range for a particular SCEV.
|
||||
///
|
||||
ConstantRange getUnsignedRange(const SCEV *S);
|
||||
|
||||
/// getSignedRange - Determine the signed range for a particular SCEV.
|
||||
///
|
||||
ConstantRange getSignedRange(const SCEV *S);
|
||||
|
||||
/// isKnownNegative - Test if the given expression is known to be negative.
|
||||
///
|
||||
bool isKnownNegative(const SCEV *S);
|
||||
|
||||
/// isKnownPositive - Test if the given expression is known to be positive.
|
||||
///
|
||||
bool isKnownPositive(const SCEV *S);
|
||||
|
||||
/// isKnownNonNegative - Test if the given expression is known to be
|
||||
/// non-negative.
|
||||
///
|
||||
bool isKnownNonNegative(const SCEV *S);
|
||||
|
||||
/// isKnownNonPositive - Test if the given expression is known to be
|
||||
/// non-positive.
|
||||
///
|
||||
bool isKnownNonPositive(const SCEV *S);
|
||||
|
||||
/// isKnownNonZero - Test if the given expression is known to be
|
||||
/// non-zero.
|
||||
///
|
||||
bool isKnownNonZero(const SCEV *S);
|
||||
|
||||
/// isKnownPredicate - Test if the given expression is known to satisfy
|
||||
/// the condition described by Pred, LHS, and RHS.
|
||||
///
|
||||
bool isKnownPredicate(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with
|
||||
/// predicate Pred. Return true iff any changes were made. If the
|
||||
/// operands are provably equal or unequal, LHS and RHS are set to
|
||||
/// the same value and Pred is set to either ICMP_EQ or ICMP_NE.
|
||||
///
|
||||
bool SimplifyICmpOperands(ICmpInst::Predicate &Pred,
|
||||
const SCEV *&LHS,
|
||||
const SCEV *&RHS,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// getLoopDisposition - Return the "disposition" of the given SCEV with
|
||||
/// respect to the given loop.
|
||||
LoopDisposition getLoopDisposition(const SCEV *S, const Loop *L);
|
||||
|
||||
/// isLoopInvariant - Return true if the value of the given SCEV is
|
||||
/// unchanging in the specified loop.
|
||||
bool isLoopInvariant(const SCEV *S, const Loop *L);
|
||||
|
||||
/// hasComputableLoopEvolution - Return true if the given SCEV changes value
|
||||
/// in a known way in the specified loop. This property being true implies
|
||||
/// that the value is variant in the loop AND that we can emit an expression
|
||||
/// to compute the value of the expression at any particular loop iteration.
|
||||
bool hasComputableLoopEvolution(const SCEV *S, const Loop *L);
|
||||
|
||||
/// getLoopDisposition - Return the "disposition" of the given SCEV with
|
||||
/// respect to the given block.
|
||||
BlockDisposition getBlockDisposition(const SCEV *S, const BasicBlock *BB);
|
||||
|
||||
/// dominates - Return true if elements that makes up the given SCEV
|
||||
/// dominate the specified basic block.
|
||||
bool dominates(const SCEV *S, const BasicBlock *BB);
|
||||
|
||||
/// properlyDominates - Return true if elements that makes up the given SCEV
|
||||
/// properly dominate the specified basic block.
|
||||
bool properlyDominates(const SCEV *S, const BasicBlock *BB);
|
||||
|
||||
/// hasOperand - Test whether the given SCEV has Op as a direct or
|
||||
/// indirect operand.
|
||||
bool hasOperand(const SCEV *S, const SCEV *Op) const;
|
||||
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual void releaseMemory();
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void print(raw_ostream &OS, const Module* = 0) const;
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
private:
|
||||
FoldingSet<SCEV> UniqueSCEVs;
|
||||
BumpPtrAllocator SCEVAllocator;
|
||||
|
||||
/// FirstUnknown - The head of a linked list of all SCEVUnknown
|
||||
/// values that have been allocated. This is used by releaseMemory
|
||||
/// to locate them all and call their destructors.
|
||||
SCEVUnknown *FirstUnknown;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
271
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionExpander.h
vendored
Normal file
271
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionExpander.h
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
//===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- 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 classes used to generate code from scalar expressions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H
|
||||
#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPANDER_H
|
||||
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionNormalization.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/Support/TargetFolder.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
class TargetTransformInfo;
|
||||
|
||||
/// Return true if the given expression is safe to expand in the sense that
|
||||
/// all materialized values are safe to speculate.
|
||||
bool isSafeToExpand(const SCEV *S);
|
||||
|
||||
/// SCEVExpander - This class uses information about analyze scalars to
|
||||
/// rewrite expressions in canonical form.
|
||||
///
|
||||
/// Clients should create an instance of this class when rewriting is needed,
|
||||
/// and destroy it when finished to allow the release of the associated
|
||||
/// memory.
|
||||
class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> {
|
||||
ScalarEvolution &SE;
|
||||
|
||||
// New instructions receive a name to identifies them with the current pass.
|
||||
const char* IVName;
|
||||
|
||||
// InsertedExpressions caches Values for reuse, so must track RAUW.
|
||||
std::map<std::pair<const SCEV *, Instruction *>, TrackingVH<Value> >
|
||||
InsertedExpressions;
|
||||
// InsertedValues only flags inserted instructions so needs no RAUW.
|
||||
std::set<AssertingVH<Value> > InsertedValues;
|
||||
std::set<AssertingVH<Value> > InsertedPostIncValues;
|
||||
|
||||
/// RelevantLoops - A memoization of the "relevant" loop for a given SCEV.
|
||||
DenseMap<const SCEV *, const Loop *> RelevantLoops;
|
||||
|
||||
/// PostIncLoops - Addrecs referring to any of the given loops are expanded
|
||||
/// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
|
||||
/// returns the add instruction that adds one to the phi for {0,+,1}<L>,
|
||||
/// as opposed to a new phi starting at 1. This is only supported in
|
||||
/// non-canonical mode.
|
||||
PostIncLoopSet PostIncLoops;
|
||||
|
||||
/// IVIncInsertPos - When this is non-null, addrecs expanded in the
|
||||
/// loop it indicates should be inserted with increments at
|
||||
/// IVIncInsertPos.
|
||||
const Loop *IVIncInsertLoop;
|
||||
|
||||
/// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop,
|
||||
/// insert the IV increment at this position.
|
||||
Instruction *IVIncInsertPos;
|
||||
|
||||
/// Phis that complete an IV chain. Reuse
|
||||
std::set<AssertingVH<PHINode> > ChainedPhis;
|
||||
|
||||
/// CanonicalMode - When true, expressions are expanded in "canonical"
|
||||
/// form. In particular, addrecs are expanded as arithmetic based on
|
||||
/// a canonical induction variable. When false, expression are expanded
|
||||
/// in a more literal form.
|
||||
bool CanonicalMode;
|
||||
|
||||
/// When invoked from LSR, the expander is in "strength reduction" mode. The
|
||||
/// only difference is that phi's are only reused if they are already in
|
||||
/// "expanded" form.
|
||||
bool LSRMode;
|
||||
|
||||
typedef IRBuilder<true, TargetFolder> BuilderType;
|
||||
BuilderType Builder;
|
||||
|
||||
#ifndef NDEBUG
|
||||
const char *DebugType;
|
||||
#endif
|
||||
|
||||
friend struct SCEVVisitor<SCEVExpander, Value*>;
|
||||
|
||||
public:
|
||||
/// SCEVExpander - Construct a SCEVExpander in "canonical" mode.
|
||||
explicit SCEVExpander(ScalarEvolution &se, const char *name)
|
||||
: SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0),
|
||||
CanonicalMode(true), LSRMode(false),
|
||||
Builder(se.getContext(), TargetFolder(se.TD)) {
|
||||
#ifndef NDEBUG
|
||||
DebugType = "";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void setDebugType(const char* s) { DebugType = s; }
|
||||
#endif
|
||||
|
||||
/// clear - Erase the contents of the InsertedExpressions map so that users
|
||||
/// trying to expand the same expression into multiple BasicBlocks or
|
||||
/// different places within the same BasicBlock can do so.
|
||||
void clear() {
|
||||
InsertedExpressions.clear();
|
||||
InsertedValues.clear();
|
||||
InsertedPostIncValues.clear();
|
||||
ChainedPhis.clear();
|
||||
}
|
||||
|
||||
/// getOrInsertCanonicalInductionVariable - This method returns the
|
||||
/// canonical induction variable of the specified type for the specified
|
||||
/// loop (inserting one if there is none). A canonical induction variable
|
||||
/// starts at zero and steps by one on each iteration.
|
||||
PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty);
|
||||
|
||||
/// getIVIncOperand - Return the induction variable increment's IV operand.
|
||||
Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos,
|
||||
bool allowScale);
|
||||
|
||||
/// hoistIVInc - Utility for hoisting an IV increment.
|
||||
bool hoistIVInc(Instruction *IncV, Instruction *InsertPos);
|
||||
|
||||
/// replaceCongruentIVs - replace congruent phis with their most canonical
|
||||
/// representative. Return the number of phis eliminated.
|
||||
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
|
||||
SmallVectorImpl<WeakVH> &DeadInsts,
|
||||
const TargetTransformInfo *TTI = NULL);
|
||||
|
||||
/// expandCodeFor - Insert code to directly compute the specified SCEV
|
||||
/// expression into the program. The inserted code is inserted into the
|
||||
/// specified block.
|
||||
Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I);
|
||||
|
||||
/// setIVIncInsertPos - Set the current IV increment loop and position.
|
||||
void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
|
||||
assert(!CanonicalMode &&
|
||||
"IV increment positions are not supported in CanonicalMode");
|
||||
IVIncInsertLoop = L;
|
||||
IVIncInsertPos = Pos;
|
||||
}
|
||||
|
||||
/// setPostInc - Enable post-inc expansion for addrecs referring to the
|
||||
/// given loops. Post-inc expansion is only supported in non-canonical
|
||||
/// mode.
|
||||
void setPostInc(const PostIncLoopSet &L) {
|
||||
assert(!CanonicalMode &&
|
||||
"Post-inc expansion is not supported in CanonicalMode");
|
||||
PostIncLoops = L;
|
||||
}
|
||||
|
||||
/// clearPostInc - Disable all post-inc expansion.
|
||||
void clearPostInc() {
|
||||
PostIncLoops.clear();
|
||||
|
||||
// When we change the post-inc loop set, cached expansions may no
|
||||
// longer be valid.
|
||||
InsertedPostIncValues.clear();
|
||||
}
|
||||
|
||||
/// disableCanonicalMode - Disable the behavior of expanding expressions in
|
||||
/// canonical form rather than in a more literal form. Non-canonical mode
|
||||
/// is useful for late optimization passes.
|
||||
void disableCanonicalMode() { CanonicalMode = false; }
|
||||
|
||||
void enableLSRMode() { LSRMode = true; }
|
||||
|
||||
/// clearInsertPoint - Clear the current insertion point. This is useful
|
||||
/// if the instruction that had been serving as the insertion point may
|
||||
/// have been deleted.
|
||||
void clearInsertPoint() {
|
||||
Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
/// isInsertedInstruction - Return true if the specified instruction was
|
||||
/// inserted by the code rewriter. If so, the client should not modify the
|
||||
/// instruction.
|
||||
bool isInsertedInstruction(Instruction *I) const {
|
||||
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
|
||||
}
|
||||
|
||||
void setChainedPhi(PHINode *PN) { ChainedPhis.insert(PN); }
|
||||
|
||||
private:
|
||||
LLVMContext &getContext() const { return SE.getContext(); }
|
||||
|
||||
/// InsertBinop - Insert the specified binary operator, doing a small amount
|
||||
/// of work to avoid inserting an obviously redundant operation.
|
||||
Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS);
|
||||
|
||||
/// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP,
|
||||
/// reusing an existing cast if a suitable one exists, moving an existing
|
||||
/// cast if a suitable one exists but isn't in the right place, or
|
||||
/// or creating a new one.
|
||||
Value *ReuseOrCreateCast(Value *V, Type *Ty,
|
||||
Instruction::CastOps Op,
|
||||
BasicBlock::iterator IP);
|
||||
|
||||
/// InsertNoopCastOfTo - Insert a cast of V to the specified type,
|
||||
/// which must be possible with a noop cast, doing what we can to
|
||||
/// share the casts.
|
||||
Value *InsertNoopCastOfTo(Value *V, Type *Ty);
|
||||
|
||||
/// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
|
||||
/// instead of using ptrtoint+arithmetic+inttoptr.
|
||||
Value *expandAddToGEP(const SCEV *const *op_begin,
|
||||
const SCEV *const *op_end,
|
||||
PointerType *PTy, Type *Ty, Value *V);
|
||||
|
||||
Value *expand(const SCEV *S);
|
||||
|
||||
/// expandCodeFor - Insert code to directly compute the specified SCEV
|
||||
/// expression into the program. The inserted code is inserted into the
|
||||
/// SCEVExpander's current insertion point. If a type is specified, the
|
||||
/// result will be expanded to have that type, with a cast if necessary.
|
||||
Value *expandCodeFor(const SCEV *SH, Type *Ty = 0);
|
||||
|
||||
/// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
|
||||
const Loop *getRelevantLoop(const SCEV *);
|
||||
|
||||
Value *visitConstant(const SCEVConstant *S) {
|
||||
return S->getValue();
|
||||
}
|
||||
|
||||
Value *visitTruncateExpr(const SCEVTruncateExpr *S);
|
||||
|
||||
Value *visitZeroExtendExpr(const SCEVZeroExtendExpr *S);
|
||||
|
||||
Value *visitSignExtendExpr(const SCEVSignExtendExpr *S);
|
||||
|
||||
Value *visitAddExpr(const SCEVAddExpr *S);
|
||||
|
||||
Value *visitMulExpr(const SCEVMulExpr *S);
|
||||
|
||||
Value *visitUDivExpr(const SCEVUDivExpr *S);
|
||||
|
||||
Value *visitAddRecExpr(const SCEVAddRecExpr *S);
|
||||
|
||||
Value *visitSMaxExpr(const SCEVSMaxExpr *S);
|
||||
|
||||
Value *visitUMaxExpr(const SCEVUMaxExpr *S);
|
||||
|
||||
Value *visitUnknown(const SCEVUnknown *S) {
|
||||
return S->getValue();
|
||||
}
|
||||
|
||||
void rememberInstruction(Value *I);
|
||||
|
||||
void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I);
|
||||
|
||||
bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
|
||||
|
||||
bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
|
||||
|
||||
Value *expandAddRecExprLiterally(const SCEVAddRecExpr *);
|
||||
PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
|
||||
const Loop *L,
|
||||
Type *ExpandTy,
|
||||
Type *IntTy);
|
||||
Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
|
||||
Type *ExpandTy, Type *IntTy, bool useSubtract);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
698
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionExpressions.h
vendored
Normal file
698
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionExpressions.h
vendored
Normal file
@@ -0,0 +1,698 @@
|
||||
//===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- 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 classes used to represent and build scalar expressions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H
|
||||
#define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
class ConstantInt;
|
||||
class ConstantRange;
|
||||
class DominatorTree;
|
||||
|
||||
enum SCEVTypes {
|
||||
// These should be ordered in terms of increasing complexity to make the
|
||||
// folders simpler.
|
||||
scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr,
|
||||
scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr,
|
||||
scUnknown, scCouldNotCompute
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVConstant - This class represents a constant integer value.
|
||||
///
|
||||
class SCEVConstant : public SCEV {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
ConstantInt *V;
|
||||
SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) :
|
||||
SCEV(ID, scConstant), V(v) {}
|
||||
public:
|
||||
ConstantInt *getValue() const { return V; }
|
||||
|
||||
Type *getType() const { return V->getType(); }
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scConstant;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVCastExpr - This is the base class for unary cast operator classes.
|
||||
///
|
||||
class SCEVCastExpr : public SCEV {
|
||||
protected:
|
||||
const SCEV *Op;
|
||||
Type *Ty;
|
||||
|
||||
SCEVCastExpr(const FoldingSetNodeIDRef ID,
|
||||
unsigned SCEVTy, const SCEV *op, Type *ty);
|
||||
|
||||
public:
|
||||
const SCEV *getOperand() const { return Op; }
|
||||
Type *getType() const { return Ty; }
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scTruncate ||
|
||||
S->getSCEVType() == scZeroExtend ||
|
||||
S->getSCEVType() == scSignExtend;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVTruncateExpr - This class represents a truncation of an integer value
|
||||
/// to a smaller integer value.
|
||||
///
|
||||
class SCEVTruncateExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, Type *ty);
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scTruncate;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVZeroExtendExpr - This class represents a zero extension of a small
|
||||
/// integer value to a larger integer value.
|
||||
///
|
||||
class SCEVZeroExtendExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, Type *ty);
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scZeroExtend;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVSignExtendExpr - This class represents a sign extension of a small
|
||||
/// integer value to a larger integer value.
|
||||
///
|
||||
class SCEVSignExtendExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, Type *ty);
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scSignExtend;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVNAryExpr - This node is a base class providing common
|
||||
/// functionality for n'ary operators.
|
||||
///
|
||||
class SCEVNAryExpr : public SCEV {
|
||||
protected:
|
||||
// Since SCEVs are immutable, ScalarEvolution allocates operand
|
||||
// arrays with its SCEVAllocator, so this class just needs a simple
|
||||
// pointer rather than a more elaborate vector-like data structure.
|
||||
// This also avoids the need for a non-trivial destructor.
|
||||
const SCEV *const *Operands;
|
||||
size_t NumOperands;
|
||||
|
||||
SCEVNAryExpr(const FoldingSetNodeIDRef ID,
|
||||
enum SCEVTypes T, const SCEV *const *O, size_t N)
|
||||
: SCEV(ID, T), Operands(O), NumOperands(N) {}
|
||||
|
||||
public:
|
||||
size_t getNumOperands() const { return NumOperands; }
|
||||
const SCEV *getOperand(unsigned i) const {
|
||||
assert(i < NumOperands && "Operand index out of range!");
|
||||
return Operands[i];
|
||||
}
|
||||
|
||||
typedef const SCEV *const *op_iterator;
|
||||
op_iterator op_begin() const { return Operands; }
|
||||
op_iterator op_end() const { return Operands + NumOperands; }
|
||||
|
||||
Type *getType() const { return getOperand(0)->getType(); }
|
||||
|
||||
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const {
|
||||
return (NoWrapFlags)(SubclassData & Mask);
|
||||
}
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scAddExpr ||
|
||||
S->getSCEVType() == scMulExpr ||
|
||||
S->getSCEVType() == scSMaxExpr ||
|
||||
S->getSCEVType() == scUMaxExpr ||
|
||||
S->getSCEVType() == scAddRecExpr;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVCommutativeExpr - This node is the base class for n'ary commutative
|
||||
/// operators.
|
||||
///
|
||||
class SCEVCommutativeExpr : public SCEVNAryExpr {
|
||||
protected:
|
||||
SCEVCommutativeExpr(const FoldingSetNodeIDRef ID,
|
||||
enum SCEVTypes T, const SCEV *const *O, size_t N)
|
||||
: SCEVNAryExpr(ID, T, O, N) {}
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scAddExpr ||
|
||||
S->getSCEVType() == scMulExpr ||
|
||||
S->getSCEVType() == scSMaxExpr ||
|
||||
S->getSCEVType() == scUMaxExpr;
|
||||
}
|
||||
|
||||
/// Set flags for a non-recurrence without clearing previously set flags.
|
||||
void setNoWrapFlags(NoWrapFlags Flags) {
|
||||
SubclassData |= Flags;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVAddExpr - This node represents an addition of some number of SCEVs.
|
||||
///
|
||||
class SCEVAddExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVAddExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scAddExpr, O, N) {
|
||||
}
|
||||
|
||||
public:
|
||||
Type *getType() const {
|
||||
// Use the type of the last operand, which is likely to be a pointer
|
||||
// type, if there is one. This doesn't usually matter, but it can help
|
||||
// reduce casts when the expressions are expanded.
|
||||
return getOperand(getNumOperands() - 1)->getType();
|
||||
}
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scAddExpr;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVMulExpr - This node represents multiplication of some number of SCEVs.
|
||||
///
|
||||
class SCEVMulExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVMulExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scMulExpr, O, N) {
|
||||
}
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scMulExpr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVUDivExpr - This class represents a binary unsigned division operation.
|
||||
///
|
||||
class SCEVUDivExpr : public SCEV {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
const SCEV *LHS;
|
||||
const SCEV *RHS;
|
||||
SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs)
|
||||
: SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {}
|
||||
|
||||
public:
|
||||
const SCEV *getLHS() const { return LHS; }
|
||||
const SCEV *getRHS() const { return RHS; }
|
||||
|
||||
Type *getType() const {
|
||||
// In most cases the types of LHS and RHS will be the same, but in some
|
||||
// crazy cases one or the other may be a pointer. ScalarEvolution doesn't
|
||||
// depend on the type for correctness, but handling types carefully can
|
||||
// avoid extra casts in the SCEVExpander. The LHS is more likely to be
|
||||
// a pointer type than the RHS, so use the RHS' type here.
|
||||
return getRHS()->getType();
|
||||
}
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scUDivExpr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip
|
||||
/// count of the specified loop. This is the primary focus of the
|
||||
/// ScalarEvolution framework; all the other SCEV subclasses are mostly just
|
||||
/// supporting infrastructure to allow SCEVAddRecExpr expressions to be
|
||||
/// created and analyzed.
|
||||
///
|
||||
/// All operands of an AddRec are required to be loop invariant.
|
||||
///
|
||||
class SCEVAddRecExpr : public SCEVNAryExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
const Loop *L;
|
||||
|
||||
SCEVAddRecExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N, const Loop *l)
|
||||
: SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {}
|
||||
|
||||
public:
|
||||
const SCEV *getStart() const { return Operands[0]; }
|
||||
const Loop *getLoop() const { return L; }
|
||||
|
||||
/// getStepRecurrence - This method constructs and returns the recurrence
|
||||
/// indicating how much this expression steps by. If this is a polynomial
|
||||
/// of degree N, it returns a chrec of degree N-1.
|
||||
/// We cannot determine whether the step recurrence has self-wraparound.
|
||||
const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
|
||||
if (isAffine()) return getOperand(1);
|
||||
return SE.getAddRecExpr(SmallVector<const SCEV *, 3>(op_begin()+1,
|
||||
op_end()),
|
||||
getLoop(), FlagAnyWrap);
|
||||
}
|
||||
|
||||
/// isAffine - Return true if this is an affine AddRec (i.e., it represents
|
||||
/// an expressions A+B*x where A and B are loop invariant values.
|
||||
bool isAffine() const {
|
||||
// We know that the start value is invariant. This expression is thus
|
||||
// affine iff the step is also invariant.
|
||||
return getNumOperands() == 2;
|
||||
}
|
||||
|
||||
/// isQuadratic - Return true if this is an quadratic AddRec (i.e., it
|
||||
/// represents an expressions A+B*x+C*x^2 where A, B and C are loop
|
||||
/// invariant values. This corresponds to an addrec of the form {L,+,M,+,N}
|
||||
bool isQuadratic() const {
|
||||
return getNumOperands() == 3;
|
||||
}
|
||||
|
||||
/// Set flags for a recurrence without clearing any previously set flags.
|
||||
/// For AddRec, either NUW or NSW implies NW. Keep track of this fact here
|
||||
/// to make it easier to propagate flags.
|
||||
void setNoWrapFlags(NoWrapFlags Flags) {
|
||||
if (Flags & (FlagNUW | FlagNSW))
|
||||
Flags = ScalarEvolution::setFlags(Flags, FlagNW);
|
||||
SubclassData |= Flags;
|
||||
}
|
||||
|
||||
/// evaluateAtIteration - Return the value of this chain of recurrences at
|
||||
/// the specified iteration number.
|
||||
const SCEV *evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const;
|
||||
|
||||
/// getNumIterationsInRange - Return the number of iterations of this loop
|
||||
/// that produce values in the specified constant range. Another way of
|
||||
/// looking at this is that it returns the first iteration number where the
|
||||
/// value is not in the condition, thus computing the exit count. If the
|
||||
/// iteration count can't be computed, an instance of SCEVCouldNotCompute is
|
||||
/// returned.
|
||||
const SCEV *getNumIterationsInRange(ConstantRange Range,
|
||||
ScalarEvolution &SE) const;
|
||||
|
||||
/// getPostIncExpr - Return an expression representing the value of
|
||||
/// this expression one iteration of the loop ahead.
|
||||
const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const {
|
||||
return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE)));
|
||||
}
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scAddRecExpr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVSMaxExpr - This class represents a signed maximum selection.
|
||||
///
|
||||
class SCEVSMaxExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVSMaxExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scSMaxExpr, O, N) {
|
||||
// Max never overflows.
|
||||
setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW));
|
||||
}
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scSMaxExpr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVUMaxExpr - This class represents an unsigned maximum selection.
|
||||
///
|
||||
class SCEVUMaxExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVUMaxExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scUMaxExpr, O, N) {
|
||||
// Max never overflows.
|
||||
setNoWrapFlags((NoWrapFlags)(FlagNUW | FlagNSW));
|
||||
}
|
||||
|
||||
public:
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scUMaxExpr;
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV
|
||||
/// value, and only represent it as its LLVM Value. This is the "bottom"
|
||||
/// value for the analysis.
|
||||
///
|
||||
class SCEVUnknown : public SCEV, private CallbackVH {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
// Implement CallbackVH.
|
||||
virtual void deleted();
|
||||
virtual void allUsesReplacedWith(Value *New);
|
||||
|
||||
/// SE - The parent ScalarEvolution value. This is used to update
|
||||
/// the parent's maps when the value associated with a SCEVUnknown
|
||||
/// is deleted or RAUW'd.
|
||||
ScalarEvolution *SE;
|
||||
|
||||
/// Next - The next pointer in the linked list of all
|
||||
/// SCEVUnknown instances owned by a ScalarEvolution.
|
||||
SCEVUnknown *Next;
|
||||
|
||||
SCEVUnknown(const FoldingSetNodeIDRef ID, Value *V,
|
||||
ScalarEvolution *se, SCEVUnknown *next) :
|
||||
SCEV(ID, scUnknown), CallbackVH(V), SE(se), Next(next) {}
|
||||
|
||||
public:
|
||||
Value *getValue() const { return getValPtr(); }
|
||||
|
||||
/// isSizeOf, isAlignOf, isOffsetOf - Test whether this is a special
|
||||
/// constant representing a type size, alignment, or field offset in
|
||||
/// a target-independent manner, and hasn't happened to have been
|
||||
/// folded with other operations into something unrecognizable. This
|
||||
/// is mainly only useful for pretty-printing and other situations
|
||||
/// where it isn't absolutely required for these to succeed.
|
||||
bool isSizeOf(Type *&AllocTy) const;
|
||||
bool isAlignOf(Type *&AllocTy) const;
|
||||
bool isOffsetOf(Type *&STy, Constant *&FieldNo) const;
|
||||
|
||||
Type *getType() const { return getValPtr()->getType(); }
|
||||
|
||||
/// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scUnknown;
|
||||
}
|
||||
};
|
||||
|
||||
/// SCEVVisitor - This class defines a simple visitor class that may be used
|
||||
/// for various SCEV analysis purposes.
|
||||
template<typename SC, typename RetVal=void>
|
||||
struct SCEVVisitor {
|
||||
RetVal visit(const SCEV *S) {
|
||||
switch (S->getSCEVType()) {
|
||||
case scConstant:
|
||||
return ((SC*)this)->visitConstant((const SCEVConstant*)S);
|
||||
case scTruncate:
|
||||
return ((SC*)this)->visitTruncateExpr((const SCEVTruncateExpr*)S);
|
||||
case scZeroExtend:
|
||||
return ((SC*)this)->visitZeroExtendExpr((const SCEVZeroExtendExpr*)S);
|
||||
case scSignExtend:
|
||||
return ((SC*)this)->visitSignExtendExpr((const SCEVSignExtendExpr*)S);
|
||||
case scAddExpr:
|
||||
return ((SC*)this)->visitAddExpr((const SCEVAddExpr*)S);
|
||||
case scMulExpr:
|
||||
return ((SC*)this)->visitMulExpr((const SCEVMulExpr*)S);
|
||||
case scUDivExpr:
|
||||
return ((SC*)this)->visitUDivExpr((const SCEVUDivExpr*)S);
|
||||
case scAddRecExpr:
|
||||
return ((SC*)this)->visitAddRecExpr((const SCEVAddRecExpr*)S);
|
||||
case scSMaxExpr:
|
||||
return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S);
|
||||
case scUMaxExpr:
|
||||
return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S);
|
||||
case scUnknown:
|
||||
return ((SC*)this)->visitUnknown((const SCEVUnknown*)S);
|
||||
case scCouldNotCompute:
|
||||
return ((SC*)this)->visitCouldNotCompute((const SCEVCouldNotCompute*)S);
|
||||
default:
|
||||
llvm_unreachable("Unknown SCEV type!");
|
||||
}
|
||||
}
|
||||
|
||||
RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) {
|
||||
llvm_unreachable("Invalid use of SCEVCouldNotCompute!");
|
||||
}
|
||||
};
|
||||
|
||||
/// Visit all nodes in the expression tree using worklist traversal.
|
||||
///
|
||||
/// Visitor implements:
|
||||
/// // return true to follow this node.
|
||||
/// bool follow(const SCEV *S);
|
||||
/// // return true to terminate the search.
|
||||
/// bool isDone();
|
||||
template<typename SV>
|
||||
class SCEVTraversal {
|
||||
SV &Visitor;
|
||||
SmallVector<const SCEV *, 8> Worklist;
|
||||
SmallPtrSet<const SCEV *, 8> Visited;
|
||||
|
||||
void push(const SCEV *S) {
|
||||
if (Visited.insert(S) && Visitor.follow(S))
|
||||
Worklist.push_back(S);
|
||||
}
|
||||
public:
|
||||
SCEVTraversal(SV& V): Visitor(V) {}
|
||||
|
||||
void visitAll(const SCEV *Root) {
|
||||
push(Root);
|
||||
while (!Worklist.empty() && !Visitor.isDone()) {
|
||||
const SCEV *S = Worklist.pop_back_val();
|
||||
|
||||
switch (S->getSCEVType()) {
|
||||
case scConstant:
|
||||
case scUnknown:
|
||||
break;
|
||||
case scTruncate:
|
||||
case scZeroExtend:
|
||||
case scSignExtend:
|
||||
push(cast<SCEVCastExpr>(S)->getOperand());
|
||||
break;
|
||||
case scAddExpr:
|
||||
case scMulExpr:
|
||||
case scSMaxExpr:
|
||||
case scUMaxExpr:
|
||||
case scAddRecExpr: {
|
||||
const SCEVNAryExpr *NAry = cast<SCEVNAryExpr>(S);
|
||||
for (SCEVNAryExpr::op_iterator I = NAry->op_begin(),
|
||||
E = NAry->op_end(); I != E; ++I) {
|
||||
push(*I);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case scUDivExpr: {
|
||||
const SCEVUDivExpr *UDiv = cast<SCEVUDivExpr>(S);
|
||||
push(UDiv->getLHS());
|
||||
push(UDiv->getRHS());
|
||||
break;
|
||||
}
|
||||
case scCouldNotCompute:
|
||||
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
|
||||
default:
|
||||
llvm_unreachable("Unknown SCEV kind!");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Use SCEVTraversal to visit all nodes in the givien expression tree.
|
||||
template<typename SV>
|
||||
void visitAll(const SCEV *Root, SV& Visitor) {
|
||||
SCEVTraversal<SV> T(Visitor);
|
||||
T.visitAll(Root);
|
||||
}
|
||||
|
||||
/// The SCEVRewriter takes a scalar evolution expression and copies all its
|
||||
/// components. The result after a rewrite is an identical SCEV.
|
||||
struct SCEVRewriter
|
||||
: public SCEVVisitor<SCEVRewriter, const SCEV*> {
|
||||
public:
|
||||
SCEVRewriter(ScalarEvolution &S) : SE(S) {}
|
||||
|
||||
virtual ~SCEVRewriter() {}
|
||||
|
||||
virtual const SCEV *visitConstant(const SCEVConstant *Constant) {
|
||||
return Constant;
|
||||
}
|
||||
|
||||
virtual const SCEV *visitTruncateExpr(const SCEVTruncateExpr *Expr) {
|
||||
const SCEV *Operand = visit(Expr->getOperand());
|
||||
return SE.getTruncateExpr(Operand, Expr->getType());
|
||||
}
|
||||
|
||||
virtual const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
|
||||
const SCEV *Operand = visit(Expr->getOperand());
|
||||
return SE.getZeroExtendExpr(Operand, Expr->getType());
|
||||
}
|
||||
|
||||
virtual const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
|
||||
const SCEV *Operand = visit(Expr->getOperand());
|
||||
return SE.getSignExtendExpr(Operand, Expr->getType());
|
||||
}
|
||||
|
||||
virtual const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
return SE.getAddExpr(Operands);
|
||||
}
|
||||
|
||||
virtual const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
return SE.getMulExpr(Operands);
|
||||
}
|
||||
|
||||
virtual const SCEV *visitUDivExpr(const SCEVUDivExpr *Expr) {
|
||||
return SE.getUDivExpr(visit(Expr->getLHS()), visit(Expr->getRHS()));
|
||||
}
|
||||
|
||||
virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
return SE.getAddRecExpr(Operands, Expr->getLoop(),
|
||||
Expr->getNoWrapFlags());
|
||||
}
|
||||
|
||||
virtual const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
return SE.getSMaxExpr(Operands);
|
||||
}
|
||||
|
||||
virtual const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
return SE.getUMaxExpr(Operands);
|
||||
}
|
||||
|
||||
virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) {
|
||||
return Expr;
|
||||
}
|
||||
|
||||
virtual const SCEV *visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
|
||||
return Expr;
|
||||
}
|
||||
|
||||
protected:
|
||||
ScalarEvolution &SE;
|
||||
};
|
||||
|
||||
typedef DenseMap<const Value*, Value*> ValueToValueMap;
|
||||
|
||||
/// The SCEVParameterRewriter takes a scalar evolution expression and updates
|
||||
/// the SCEVUnknown components following the Map (Value -> Value).
|
||||
struct SCEVParameterRewriter: public SCEVRewriter {
|
||||
public:
|
||||
static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE,
|
||||
ValueToValueMap &Map) {
|
||||
SCEVParameterRewriter Rewriter(SE, Map);
|
||||
return Rewriter.visit(Scev);
|
||||
}
|
||||
SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M)
|
||||
: SCEVRewriter(S), Map(M) {}
|
||||
|
||||
virtual const SCEV *visitUnknown(const SCEVUnknown *Expr) {
|
||||
Value *V = Expr->getValue();
|
||||
if (Map.count(V))
|
||||
return SE.getUnknown(Map[V]);
|
||||
return Expr;
|
||||
}
|
||||
|
||||
private:
|
||||
ValueToValueMap ⤅
|
||||
};
|
||||
|
||||
typedef DenseMap<const Loop*, const SCEV*> LoopToScevMapT;
|
||||
|
||||
/// The SCEVApplyRewriter takes a scalar evolution expression and applies
|
||||
/// the Map (Loop -> SCEV) to all AddRecExprs.
|
||||
struct SCEVApplyRewriter: public SCEVRewriter {
|
||||
public:
|
||||
static const SCEV *rewrite(const SCEV *Scev, LoopToScevMapT &Map,
|
||||
ScalarEvolution &SE) {
|
||||
SCEVApplyRewriter Rewriter(SE, Map);
|
||||
return Rewriter.visit(Scev);
|
||||
}
|
||||
SCEVApplyRewriter(ScalarEvolution &S, LoopToScevMapT &M)
|
||||
: SCEVRewriter(S), Map(M) {}
|
||||
|
||||
virtual const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
|
||||
SmallVector<const SCEV *, 2> Operands;
|
||||
for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
|
||||
Operands.push_back(visit(Expr->getOperand(i)));
|
||||
|
||||
const Loop *L = Expr->getLoop();
|
||||
const SCEV *Res = SE.getAddRecExpr(Operands, L, Expr->getNoWrapFlags());
|
||||
|
||||
if (0 == Map.count(L))
|
||||
return Res;
|
||||
|
||||
const SCEVAddRecExpr *Rec = (const SCEVAddRecExpr *) Res;
|
||||
return Rec->evaluateAtIteration(Map[L], SE);
|
||||
}
|
||||
|
||||
private:
|
||||
LoopToScevMapT ⤅
|
||||
};
|
||||
|
||||
/// Applies the Map (Loop -> SCEV) to the given Scev.
|
||||
static inline const SCEV *apply(const SCEV *Scev, LoopToScevMapT &Map,
|
||||
ScalarEvolution &SE) {
|
||||
return SCEVApplyRewriter::rewrite(Scev, Map, SE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
78
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionNormalization.h
vendored
Normal file
78
thirdparty/clang/include/llvm/Analysis/ScalarEvolutionNormalization.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
//===- llvm/Analysis/ScalarEvolutionNormalization.h - See below -*- 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 utilities for working with "normalized" ScalarEvolution
|
||||
// expressions.
|
||||
//
|
||||
// The following example illustrates post-increment uses and how normalized
|
||||
// expressions help.
|
||||
//
|
||||
// for (i=0; i!=n; ++i) {
|
||||
// ...
|
||||
// }
|
||||
// use(i);
|
||||
//
|
||||
// While the expression for most uses of i inside the loop is {0,+,1}<%L>, the
|
||||
// expression for the use of i outside the loop is {1,+,1}<%L>, since i is
|
||||
// incremented at the end of the loop body. This is inconveient, since it
|
||||
// suggests that we need two different induction variables, one that starts
|
||||
// at 0 and one that starts at 1. We'd prefer to be able to think of these as
|
||||
// the same induction variable, with uses inside the loop using the
|
||||
// "pre-incremented" value, and uses after the loop using the
|
||||
// "post-incremented" value.
|
||||
//
|
||||
// Expressions for post-incremented uses are represented as an expression
|
||||
// paired with a set of loops for which the expression is in "post-increment"
|
||||
// mode (there may be multiple loops).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H
|
||||
#define LLVM_ANALYSIS_SCALAREVOLUTIONNORMALIZATION_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Instruction;
|
||||
class DominatorTree;
|
||||
class Loop;
|
||||
class ScalarEvolution;
|
||||
class SCEV;
|
||||
class Value;
|
||||
|
||||
/// TransformKind - Different types of transformations that
|
||||
/// TransformForPostIncUse can do.
|
||||
enum TransformKind {
|
||||
/// Normalize - Normalize according to the given loops.
|
||||
Normalize,
|
||||
/// NormalizeAutodetect - Detect post-inc opportunities on new expressions,
|
||||
/// update the given loop set, and normalize.
|
||||
NormalizeAutodetect,
|
||||
/// Denormalize - Perform the inverse transform on the expression with the
|
||||
/// given loop set.
|
||||
Denormalize
|
||||
};
|
||||
|
||||
/// PostIncLoopSet - A set of loops.
|
||||
typedef SmallPtrSet<const Loop *, 2> PostIncLoopSet;
|
||||
|
||||
/// TransformForPostIncUse - Transform the given expression according to the
|
||||
/// given transformation kind.
|
||||
const SCEV *TransformForPostIncUse(TransformKind Kind,
|
||||
const SCEV *S,
|
||||
Instruction *User,
|
||||
Value *OperandValToReplace,
|
||||
PostIncLoopSet &Loops,
|
||||
ScalarEvolution &SE,
|
||||
DominatorTree &DT);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
206
thirdparty/clang/include/llvm/Analysis/SparsePropagation.h
vendored
Normal file
206
thirdparty/clang/include/llvm/Analysis/SparsePropagation.h
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
//===- SparsePropagation.h - Sparse Conditional Property Propagation ------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements an abstract sparse conditional propagation algorithm,
|
||||
// modeled after SCCP, but with a customizable lattice function.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_SPARSEPROPAGATION_H
|
||||
#define LLVM_ANALYSIS_SPARSEPROPAGATION_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class Value;
|
||||
class Constant;
|
||||
class Argument;
|
||||
class Instruction;
|
||||
class PHINode;
|
||||
class TerminatorInst;
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class SparseSolver;
|
||||
class raw_ostream;
|
||||
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
||||
/// AbstractLatticeFunction - This class is implemented by the dataflow instance
|
||||
/// to specify what the lattice values are and how they handle merges etc.
|
||||
/// This gives the client the power to compute lattice values from instructions,
|
||||
/// constants, etc. The requirement is that lattice values must all fit into
|
||||
/// a void*. If a void* is not sufficient, the implementation should use this
|
||||
/// pointer to be a pointer into a uniquing set or something.
|
||||
///
|
||||
class AbstractLatticeFunction {
|
||||
public:
|
||||
typedef void *LatticeVal;
|
||||
private:
|
||||
LatticeVal UndefVal, OverdefinedVal, UntrackedVal;
|
||||
public:
|
||||
AbstractLatticeFunction(LatticeVal undefVal, LatticeVal overdefinedVal,
|
||||
LatticeVal untrackedVal) {
|
||||
UndefVal = undefVal;
|
||||
OverdefinedVal = overdefinedVal;
|
||||
UntrackedVal = untrackedVal;
|
||||
}
|
||||
virtual ~AbstractLatticeFunction();
|
||||
|
||||
LatticeVal getUndefVal() const { return UndefVal; }
|
||||
LatticeVal getOverdefinedVal() const { return OverdefinedVal; }
|
||||
LatticeVal getUntrackedVal() const { return UntrackedVal; }
|
||||
|
||||
/// IsUntrackedValue - If the specified Value is something that is obviously
|
||||
/// uninteresting to the analysis (and would always return UntrackedVal),
|
||||
/// this function can return true to avoid pointless work.
|
||||
virtual bool IsUntrackedValue(Value *V) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ComputeConstant - Given a constant value, compute and return a lattice
|
||||
/// value corresponding to the specified constant.
|
||||
virtual LatticeVal ComputeConstant(Constant *C) {
|
||||
return getOverdefinedVal(); // always safe
|
||||
}
|
||||
|
||||
/// IsSpecialCasedPHI - Given a PHI node, determine whether this PHI node is
|
||||
/// one that the we want to handle through ComputeInstructionState.
|
||||
virtual bool IsSpecialCasedPHI(PHINode *PN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// GetConstant - If the specified lattice value is representable as an LLVM
|
||||
/// constant value, return it. Otherwise return null. The returned value
|
||||
/// must be in the same LLVM type as Val.
|
||||
virtual Constant *GetConstant(LatticeVal LV, Value *Val, SparseSolver &SS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// ComputeArgument - Given a formal argument value, compute and return a
|
||||
/// lattice value corresponding to the specified argument.
|
||||
virtual LatticeVal ComputeArgument(Argument *I) {
|
||||
return getOverdefinedVal(); // always safe
|
||||
}
|
||||
|
||||
/// MergeValues - Compute and return the merge of the two specified lattice
|
||||
/// values. Merging should only move one direction down the lattice to
|
||||
/// guarantee convergence (toward overdefined).
|
||||
virtual LatticeVal MergeValues(LatticeVal X, LatticeVal Y) {
|
||||
return getOverdefinedVal(); // always safe, never useful.
|
||||
}
|
||||
|
||||
/// ComputeInstructionState - Given an instruction and a vector of its operand
|
||||
/// values, compute the result value of the instruction.
|
||||
virtual LatticeVal ComputeInstructionState(Instruction &I, SparseSolver &SS) {
|
||||
return getOverdefinedVal(); // always safe, never useful.
|
||||
}
|
||||
|
||||
/// PrintValue - Render the specified lattice value to the specified stream.
|
||||
virtual void PrintValue(LatticeVal V, raw_ostream &OS);
|
||||
};
|
||||
|
||||
|
||||
/// SparseSolver - This class is a general purpose solver for Sparse Conditional
|
||||
/// Propagation with a programmable lattice function.
|
||||
///
|
||||
class SparseSolver {
|
||||
typedef AbstractLatticeFunction::LatticeVal LatticeVal;
|
||||
|
||||
/// LatticeFunc - This is the object that knows the lattice and how to do
|
||||
/// compute transfer functions.
|
||||
AbstractLatticeFunction *LatticeFunc;
|
||||
|
||||
DenseMap<Value*, LatticeVal> ValueState; // The state each value is in.
|
||||
SmallPtrSet<BasicBlock*, 16> BBExecutable; // The bbs that are executable.
|
||||
|
||||
std::vector<Instruction*> InstWorkList; // Worklist of insts to process.
|
||||
|
||||
std::vector<BasicBlock*> BBWorkList; // The BasicBlock work list
|
||||
|
||||
/// KnownFeasibleEdges - Entries in this set are edges which have already had
|
||||
/// PHI nodes retriggered.
|
||||
typedef std::pair<BasicBlock*,BasicBlock*> Edge;
|
||||
std::set<Edge> KnownFeasibleEdges;
|
||||
|
||||
SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION;
|
||||
public:
|
||||
explicit SparseSolver(AbstractLatticeFunction *Lattice)
|
||||
: LatticeFunc(Lattice) {}
|
||||
~SparseSolver() {
|
||||
delete LatticeFunc;
|
||||
}
|
||||
|
||||
/// Solve - Solve for constants and executable blocks.
|
||||
///
|
||||
void Solve(Function &F);
|
||||
|
||||
void Print(Function &F, raw_ostream &OS) const;
|
||||
|
||||
/// getLatticeState - Return the LatticeVal object that corresponds to the
|
||||
/// value. If an value is not in the map, it is returned as untracked,
|
||||
/// unlike the getOrInitValueState method.
|
||||
LatticeVal getLatticeState(Value *V) const {
|
||||
DenseMap<Value*, LatticeVal>::const_iterator I = ValueState.find(V);
|
||||
return I != ValueState.end() ? I->second : LatticeFunc->getUntrackedVal();
|
||||
}
|
||||
|
||||
/// getOrInitValueState - Return the LatticeVal object that corresponds to the
|
||||
/// value, initializing the value's state if it hasn't been entered into the
|
||||
/// map yet. This function is necessary because not all values should start
|
||||
/// out in the underdefined state... Arguments should be overdefined, and
|
||||
/// constants should be marked as constants.
|
||||
///
|
||||
LatticeVal getOrInitValueState(Value *V);
|
||||
|
||||
/// isEdgeFeasible - Return true if the control flow edge from the 'From'
|
||||
/// basic block to the 'To' basic block is currently feasible. If
|
||||
/// AggressiveUndef is true, then this treats values with unknown lattice
|
||||
/// values as undefined. This is generally only useful when solving the
|
||||
/// lattice, not when querying it.
|
||||
bool isEdgeFeasible(BasicBlock *From, BasicBlock *To,
|
||||
bool AggressiveUndef = false);
|
||||
|
||||
/// isBlockExecutable - Return true if there are any known feasible
|
||||
/// edges into the basic block. This is generally only useful when
|
||||
/// querying the lattice.
|
||||
bool isBlockExecutable(BasicBlock *BB) const {
|
||||
return BBExecutable.count(BB);
|
||||
}
|
||||
|
||||
private:
|
||||
/// UpdateState - When the state for some instruction is potentially updated,
|
||||
/// this function notices and adds I to the worklist if needed.
|
||||
void UpdateState(Instruction &Inst, LatticeVal V);
|
||||
|
||||
/// MarkBlockExecutable - This method can be used by clients to mark all of
|
||||
/// the blocks that are known to be intrinsically live in the processed unit.
|
||||
void MarkBlockExecutable(BasicBlock *BB);
|
||||
|
||||
/// markEdgeExecutable - Mark a basic block as executable, adding it to the BB
|
||||
/// work list if it is not already executable.
|
||||
void markEdgeExecutable(BasicBlock *Source, BasicBlock *Dest);
|
||||
|
||||
/// getFeasibleSuccessors - Return a vector of booleans to indicate which
|
||||
/// successors are reachable from a given terminator instruction.
|
||||
void getFeasibleSuccessors(TerminatorInst &TI, SmallVectorImpl<bool> &Succs,
|
||||
bool AggressiveUndef);
|
||||
|
||||
void visitInst(Instruction &I);
|
||||
void visitPHINode(PHINode &I);
|
||||
void visitTerminatorInst(TerminatorInst &TI);
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ANALYSIS_SPARSEPROPAGATION_H
|
||||
349
thirdparty/clang/include/llvm/Analysis/TargetTransformInfo.h
vendored
Normal file
349
thirdparty/clang/include/llvm/Analysis/TargetTransformInfo.h
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass exposes codegen information to IR-level passes. Every
|
||||
// transformation that uses codegen information is broken into three parts:
|
||||
// 1. The IR-level analysis pass.
|
||||
// 2. The IR-level transformation interface which provides the needed
|
||||
// information.
|
||||
// 3. Codegen-level implementation which uses target-specific hooks.
|
||||
//
|
||||
// This file defines #2, which is the interface that IR-level transformations
|
||||
// use for querying the codegen.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
|
||||
#define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H
|
||||
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class GlobalValue;
|
||||
class Type;
|
||||
class User;
|
||||
class Value;
|
||||
|
||||
/// TargetTransformInfo - This pass provides access to the codegen
|
||||
/// interfaces that are needed for IR-level transformations.
|
||||
class TargetTransformInfo {
|
||||
protected:
|
||||
/// \brief The TTI instance one level down the stack.
|
||||
///
|
||||
/// This is used to implement the default behavior all of the methods which
|
||||
/// is to delegate up through the stack of TTIs until one can answer the
|
||||
/// query.
|
||||
TargetTransformInfo *PrevTTI;
|
||||
|
||||
/// \brief The top of the stack of TTI analyses available.
|
||||
///
|
||||
/// This is a convenience routine maintained as TTI analyses become available
|
||||
/// that complements the PrevTTI delegation chain. When one part of an
|
||||
/// analysis pass wants to query another part of the analysis pass it can use
|
||||
/// this to start back at the top of the stack.
|
||||
TargetTransformInfo *TopTTI;
|
||||
|
||||
/// All pass subclasses must in their initializePass routine call
|
||||
/// pushTTIStack with themselves to update the pointers tracking the previous
|
||||
/// TTI instance in the analysis group's stack, and the top of the analysis
|
||||
/// group's stack.
|
||||
void pushTTIStack(Pass *P);
|
||||
|
||||
/// All pass subclasses must in their finalizePass routine call popTTIStack
|
||||
/// to update the pointers tracking the previous TTI instance in the analysis
|
||||
/// group's stack, and the top of the analysis group's stack.
|
||||
void popTTIStack();
|
||||
|
||||
/// All pass subclasses must call TargetTransformInfo::getAnalysisUsage.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
public:
|
||||
/// This class is intended to be subclassed by real implementations.
|
||||
virtual ~TargetTransformInfo() = 0;
|
||||
|
||||
/// \name Generic Target Information
|
||||
/// @{
|
||||
|
||||
/// \brief Underlying constants for 'cost' values in this interface.
|
||||
///
|
||||
/// Many APIs in this interface return a cost. This enum defines the
|
||||
/// fundamental values that should be used to interpret (and produce) those
|
||||
/// costs. The costs are returned as an unsigned rather than a member of this
|
||||
/// enumeration because it is expected that the cost of one IR instruction
|
||||
/// may have a multiplicative factor to it or otherwise won't fit directly
|
||||
/// into the enum. Moreover, it is common to sum or average costs which works
|
||||
/// better as simple integral values. Thus this enum only provides constants.
|
||||
///
|
||||
/// Note that these costs should usually reflect the intersection of code-size
|
||||
/// cost and execution cost. A free instruction is typically one that folds
|
||||
/// into another instruction. For example, reg-to-reg moves can often be
|
||||
/// skipped by renaming the registers in the CPU, but they still are encoded
|
||||
/// and thus wouldn't be considered 'free' here.
|
||||
enum TargetCostConstants {
|
||||
TCC_Free = 0, ///< Expected to fold away in lowering.
|
||||
TCC_Basic = 1, ///< The cost of a typical 'add' instruction.
|
||||
TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86.
|
||||
};
|
||||
|
||||
/// \brief Estimate the cost of a specific operation when lowered.
|
||||
///
|
||||
/// Note that this is designed to work on an arbitrary synthetic opcode, and
|
||||
/// thus work for hypothetical queries before an instruction has even been
|
||||
/// formed. However, this does *not* work for GEPs, and must not be called
|
||||
/// for a GEP instruction. Instead, use the dedicated getGEPCost interface as
|
||||
/// analyzing a GEP's cost required more information.
|
||||
///
|
||||
/// Typically only the result type is required, and the operand type can be
|
||||
/// omitted. However, if the opcode is one of the cast instructions, the
|
||||
/// operand type is required.
|
||||
///
|
||||
/// The returned cost is defined in terms of \c TargetCostConstants, see its
|
||||
/// comments for a detailed explanation of the cost values.
|
||||
virtual unsigned getOperationCost(unsigned Opcode, Type *Ty,
|
||||
Type *OpTy = 0) const;
|
||||
|
||||
/// \brief Estimate the cost of a GEP operation when lowered.
|
||||
///
|
||||
/// The contract for this function is the same as \c getOperationCost except
|
||||
/// that it supports an interface that provides extra information specific to
|
||||
/// the GEP operation.
|
||||
virtual unsigned getGEPCost(const Value *Ptr,
|
||||
ArrayRef<const Value *> Operands) const;
|
||||
|
||||
/// \brief Estimate the cost of a function call when lowered.
|
||||
///
|
||||
/// The contract for this is the same as \c getOperationCost except that it
|
||||
/// supports an interface that provides extra information specific to call
|
||||
/// instructions.
|
||||
///
|
||||
/// This is the most basic query for estimating call cost: it only knows the
|
||||
/// function type and (potentially) the number of arguments at the call site.
|
||||
/// The latter is only interesting for varargs function types.
|
||||
virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const;
|
||||
|
||||
/// \brief Estimate the cost of calling a specific function when lowered.
|
||||
///
|
||||
/// This overload adds the ability to reason about the particular function
|
||||
/// being called in the event it is a library call with special lowering.
|
||||
virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const;
|
||||
|
||||
/// \brief Estimate the cost of calling a specific function when lowered.
|
||||
///
|
||||
/// This overload allows specifying a set of candidate argument values.
|
||||
virtual unsigned getCallCost(const Function *F,
|
||||
ArrayRef<const Value *> Arguments) const;
|
||||
|
||||
/// \brief Estimate the cost of an intrinsic when lowered.
|
||||
///
|
||||
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
|
||||
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
|
||||
ArrayRef<Type *> ParamTys) const;
|
||||
|
||||
/// \brief Estimate the cost of an intrinsic when lowered.
|
||||
///
|
||||
/// Mirrors the \c getCallCost method but uses an intrinsic identifier.
|
||||
virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
|
||||
ArrayRef<const Value *> Arguments) const;
|
||||
|
||||
/// \brief Estimate the cost of a given IR user when lowered.
|
||||
///
|
||||
/// This can estimate the cost of either a ConstantExpr or Instruction when
|
||||
/// lowered. It has two primary advantages over the \c getOperationCost and
|
||||
/// \c getGEPCost above, and one significant disadvantage: it can only be
|
||||
/// used when the IR construct has already been formed.
|
||||
///
|
||||
/// The advantages are that it can inspect the SSA use graph to reason more
|
||||
/// accurately about the cost. For example, all-constant-GEPs can often be
|
||||
/// folded into a load or other instruction, but if they are used in some
|
||||
/// other context they may not be folded. This routine can distinguish such
|
||||
/// cases.
|
||||
///
|
||||
/// The returned cost is defined in terms of \c TargetCostConstants, see its
|
||||
/// comments for a detailed explanation of the cost values.
|
||||
virtual unsigned getUserCost(const User *U) const;
|
||||
|
||||
/// \brief Test whether calls to a function lower to actual program function
|
||||
/// calls.
|
||||
///
|
||||
/// The idea is to test whether the program is likely to require a 'call'
|
||||
/// instruction or equivalent in order to call the given function.
|
||||
///
|
||||
/// FIXME: It's not clear that this is a good or useful query API. Client's
|
||||
/// should probably move to simpler cost metrics using the above.
|
||||
/// Alternatively, we could split the cost interface into distinct code-size
|
||||
/// and execution-speed costs. This would allow modelling the core of this
|
||||
/// query more accurately as the a call is a single small instruction, but
|
||||
/// incurs significant execution cost.
|
||||
virtual bool isLoweredToCall(const Function *F) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Scalar Target Information
|
||||
/// @{
|
||||
|
||||
/// \brief Flags indicating the kind of support for population count.
|
||||
///
|
||||
/// Compared to the SW implementation, HW support is supposed to
|
||||
/// significantly boost the performance when the population is dense, and it
|
||||
/// may or may not degrade performance if the population is sparse. A HW
|
||||
/// support is considered as "Fast" if it can outperform, or is on a par
|
||||
/// with, SW implementation when the population is sparse; otherwise, it is
|
||||
/// considered as "Slow".
|
||||
enum PopcntSupportKind {
|
||||
PSK_Software,
|
||||
PSK_SlowHardware,
|
||||
PSK_FastHardware
|
||||
};
|
||||
|
||||
/// isLegalAddImmediate - Return true if the specified immediate is legal
|
||||
/// add immediate, that is the target has add instructions which can add
|
||||
/// a register with the immediate without having to materialize the
|
||||
/// immediate into a register.
|
||||
virtual bool isLegalAddImmediate(int64_t Imm) const;
|
||||
|
||||
/// isLegalICmpImmediate - Return true if the specified immediate is legal
|
||||
/// icmp immediate, that is the target has icmp instructions which can compare
|
||||
/// a register against the immediate without having to materialize the
|
||||
/// immediate into a register.
|
||||
virtual bool isLegalICmpImmediate(int64_t Imm) const;
|
||||
|
||||
/// isLegalAddressingMode - Return true if the addressing mode represented by
|
||||
/// AM is legal for this target, for a load/store of the specified type.
|
||||
/// The type may be VoidTy, in which case only return true if the addressing
|
||||
/// mode is legal for a load/store of any legal type.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
|
||||
int64_t BaseOffset, bool HasBaseReg,
|
||||
int64_t Scale) const;
|
||||
|
||||
/// isTruncateFree - Return true if it's free to truncate a value of
|
||||
/// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in
|
||||
/// register EAX to i16 by referencing its sub-register AX.
|
||||
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
|
||||
|
||||
/// Is this type legal.
|
||||
virtual bool isTypeLegal(Type *Ty) const;
|
||||
|
||||
/// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes
|
||||
virtual unsigned getJumpBufAlignment() const;
|
||||
|
||||
/// getJumpBufSize - returns the target's jmp_buf size in bytes.
|
||||
virtual unsigned getJumpBufSize() const;
|
||||
|
||||
/// shouldBuildLookupTables - Return true if switches should be turned into
|
||||
/// lookup tables for the target.
|
||||
virtual bool shouldBuildLookupTables() const;
|
||||
|
||||
/// getPopcntSupport - Return hardware support for population count.
|
||||
virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const;
|
||||
|
||||
/// getIntImmCost - Return the expected cost of materializing the given
|
||||
/// integer immediate of the specified type.
|
||||
virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Vector Target Information
|
||||
/// @{
|
||||
|
||||
/// \brief The various kinds of shuffle patterns for vector queries.
|
||||
enum ShuffleKind {
|
||||
SK_Broadcast, ///< Broadcast element 0 to all other elements.
|
||||
SK_Reverse, ///< Reverse the order of the vector.
|
||||
SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset.
|
||||
SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset.
|
||||
};
|
||||
|
||||
/// \brief Additonal information about an operand's possible values.
|
||||
enum OperandValueKind {
|
||||
OK_AnyValue, // Operand can have any value.
|
||||
OK_UniformValue, // Operand is uniform (splat of a value).
|
||||
OK_UniformConstantValue // Operand is uniform constant.
|
||||
};
|
||||
|
||||
/// \return The number of scalar or vector registers that the target has.
|
||||
/// If 'Vectors' is true, it returns the number of vector registers. If it is
|
||||
/// set to false, it returns the number of scalar registers.
|
||||
virtual unsigned getNumberOfRegisters(bool Vector) const;
|
||||
|
||||
/// \return The width of the largest scalar or vector register type.
|
||||
virtual unsigned getRegisterBitWidth(bool Vector) const;
|
||||
|
||||
/// \return The maximum unroll factor that the vectorizer should try to
|
||||
/// perform for this target. This number depends on the level of parallelism
|
||||
/// and the number of execution units in the CPU.
|
||||
virtual unsigned getMaximumUnrollFactor() const;
|
||||
|
||||
/// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc.
|
||||
virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty,
|
||||
OperandValueKind Opd1Info = OK_AnyValue,
|
||||
OperandValueKind Opd2Info = OK_AnyValue) const;
|
||||
|
||||
/// \return The cost of a shuffle instruction of kind Kind and of type Tp.
|
||||
/// The index and subtype parameters are used by the subvector insertion and
|
||||
/// extraction shuffle kinds.
|
||||
virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0,
|
||||
Type *SubTp = 0) const;
|
||||
|
||||
/// \return The expected cost of cast instructions, such as bitcast, trunc,
|
||||
/// zext, etc.
|
||||
virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst,
|
||||
Type *Src) const;
|
||||
|
||||
/// \return The expected cost of control-flow related instructions such as
|
||||
/// Phi, Ret, Br.
|
||||
virtual unsigned getCFInstrCost(unsigned Opcode) const;
|
||||
|
||||
/// \returns The expected cost of compare and select instructions.
|
||||
virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
|
||||
Type *CondTy = 0) const;
|
||||
|
||||
/// \return The expected cost of vector Insert and Extract.
|
||||
/// Use -1 to indicate that there is no information on the index value.
|
||||
virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
|
||||
unsigned Index = -1) const;
|
||||
|
||||
/// \return The cost of Load and Store instructions.
|
||||
virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) const;
|
||||
|
||||
/// \returns The cost of Intrinsic instructions.
|
||||
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
|
||||
ArrayRef<Type *> Tys) const;
|
||||
|
||||
/// \returns The number of pieces into which the provided type must be
|
||||
/// split during legalization. Zero is returned when the answer is unknown.
|
||||
virtual unsigned getNumberOfParts(Type *Tp) const;
|
||||
|
||||
/// \returns The cost of the address computation. For most targets this can be
|
||||
/// merged into the instruction indexing mode. Some targets might want to
|
||||
/// distinguish between address computation for memory operations on vector
|
||||
/// types and scalar types. Such targets should override this function.
|
||||
virtual unsigned getAddressComputationCost(Type *Ty) const;
|
||||
|
||||
/// @}
|
||||
|
||||
/// Analysis group identification.
|
||||
static char ID;
|
||||
};
|
||||
|
||||
/// \brief Create the base case instance of a pass in the TTI analysis group.
|
||||
///
|
||||
/// This class provides the base case for the stack of TTI analyzes. It doesn't
|
||||
/// delegate to anything and uses the STTI and VTTI objects passed in to
|
||||
/// satisfy the queries.
|
||||
ImmutablePass *createNoTargetTransformInfoPass();
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
119
thirdparty/clang/include/llvm/Analysis/Trace.h
vendored
Normal file
119
thirdparty/clang/include/llvm/Analysis/Trace.h
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
//===- llvm/Analysis/Trace.h - Represent one trace of LLVM code -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class represents a single trace of LLVM basic blocks. A trace is a
|
||||
// single entry, multiple exit, region of code that is often hot. Trace-based
|
||||
// optimizations treat traces almost like they are a large, strange, basic
|
||||
// block: because the trace path is assumed to be hot, optimizations for the
|
||||
// fall-through path are made at the expense of the non-fall-through paths.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_TRACE_H
|
||||
#define LLVM_ANALYSIS_TRACE_H
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Module;
|
||||
class raw_ostream;
|
||||
|
||||
class Trace {
|
||||
typedef std::vector<BasicBlock *> BasicBlockListType;
|
||||
BasicBlockListType BasicBlocks;
|
||||
|
||||
public:
|
||||
/// Trace ctor - Make a new trace from a vector of basic blocks,
|
||||
/// residing in the function which is the parent of the first
|
||||
/// basic block in the vector.
|
||||
///
|
||||
Trace(const std::vector<BasicBlock *> &vBB) : BasicBlocks (vBB) {}
|
||||
|
||||
/// getEntryBasicBlock - Return the entry basic block (first block)
|
||||
/// of the trace.
|
||||
///
|
||||
BasicBlock *getEntryBasicBlock () const { return BasicBlocks[0]; }
|
||||
|
||||
/// operator[]/getBlock - Return basic block N in the trace.
|
||||
///
|
||||
BasicBlock *operator[](unsigned i) const { return BasicBlocks[i]; }
|
||||
BasicBlock *getBlock(unsigned i) const { return BasicBlocks[i]; }
|
||||
|
||||
/// getFunction - Return this trace's parent function.
|
||||
///
|
||||
Function *getFunction () const;
|
||||
|
||||
/// getModule - Return this Module that contains this trace's parent
|
||||
/// function.
|
||||
///
|
||||
Module *getModule () const;
|
||||
|
||||
/// getBlockIndex - Return the index of the specified basic block in the
|
||||
/// trace, or -1 if it is not in the trace.
|
||||
int getBlockIndex(const BasicBlock *X) const {
|
||||
for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i)
|
||||
if (BasicBlocks[i] == X)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// contains - Returns true if this trace contains the given basic
|
||||
/// block.
|
||||
///
|
||||
bool contains(const BasicBlock *X) const {
|
||||
return getBlockIndex(X) != -1;
|
||||
}
|
||||
|
||||
/// Returns true if B1 occurs before B2 in the trace, or if it is the same
|
||||
/// block as B2.. Both blocks must be in the trace.
|
||||
///
|
||||
bool dominates(const BasicBlock *B1, const BasicBlock *B2) const {
|
||||
int B1Idx = getBlockIndex(B1), B2Idx = getBlockIndex(B2);
|
||||
assert(B1Idx != -1 && B2Idx != -1 && "Block is not in the trace!");
|
||||
return B1Idx <= B2Idx;
|
||||
}
|
||||
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
typedef BasicBlockListType::const_iterator const_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
|
||||
iterator begin() { return BasicBlocks.begin(); }
|
||||
const_iterator begin() const { return BasicBlocks.begin(); }
|
||||
iterator end () { return BasicBlocks.end(); }
|
||||
const_iterator end () const { return BasicBlocks.end(); }
|
||||
|
||||
reverse_iterator rbegin() { return BasicBlocks.rbegin(); }
|
||||
const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); }
|
||||
reverse_iterator rend () { return BasicBlocks.rend(); }
|
||||
const_reverse_iterator rend () const { return BasicBlocks.rend(); }
|
||||
|
||||
unsigned size() const { return BasicBlocks.size(); }
|
||||
bool empty() const { return BasicBlocks.empty(); }
|
||||
|
||||
iterator erase(iterator q) { return BasicBlocks.erase (q); }
|
||||
iterator erase(iterator q1, iterator q2) { return BasicBlocks.erase (q1, q2); }
|
||||
|
||||
/// print - Write trace to output stream.
|
||||
///
|
||||
void print(raw_ostream &O) const;
|
||||
|
||||
/// dump - Debugger convenience method; writes trace to standard error
|
||||
/// output stream.
|
||||
///
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ANALYSIS_TRACE_H
|
||||
193
thirdparty/clang/include/llvm/Analysis/ValueTracking.h
vendored
Normal file
193
thirdparty/clang/include/llvm/Analysis/ValueTracking.h
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
//===- llvm/Analysis/ValueTracking.h - Walk computations --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains routines that help analyze properties that chains of
|
||||
// computations have.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_VALUETRACKING_H
|
||||
#define LLVM_ANALYSIS_VALUETRACKING_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class Value;
|
||||
class Instruction;
|
||||
class APInt;
|
||||
class DataLayout;
|
||||
class StringRef;
|
||||
class MDNode;
|
||||
|
||||
/// ComputeMaskedBits - Determine which of the bits specified in Mask are
|
||||
/// known to be either zero or one and return them in the KnownZero/KnownOne
|
||||
/// bit sets. This code only analyzes bits in Mask, in order to short-circuit
|
||||
/// processing.
|
||||
///
|
||||
/// This function is defined on values with integer type, values with pointer
|
||||
/// type (but only if TD is non-null), and vectors of integers. In the case
|
||||
/// where V is a vector, the mask, known zero, and known one values are the
|
||||
/// same width as the vector element, and the bit is set only if it is true
|
||||
/// for all of the elements in the vector.
|
||||
void ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne,
|
||||
const DataLayout *TD = 0, unsigned Depth = 0);
|
||||
void computeMaskedBitsLoad(const MDNode &Ranges, APInt &KnownZero);
|
||||
|
||||
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
|
||||
/// one. Convenience wrapper around ComputeMaskedBits.
|
||||
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
|
||||
const DataLayout *TD = 0, unsigned Depth = 0);
|
||||
|
||||
/// isKnownToBeAPowerOfTwo - Return true if the given value is known to have
|
||||
/// exactly one bit set when defined. For vectors return true if every
|
||||
/// element is known to be a power of two when defined. Supports values with
|
||||
/// integer or pointer type and vectors of integers. If 'OrZero' is set then
|
||||
/// returns true if the given value is either a power of two or zero.
|
||||
bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0);
|
||||
|
||||
/// isKnownNonZero - Return true if the given value is known to be non-zero
|
||||
/// when defined. For vectors return true if every element is known to be
|
||||
/// non-zero when defined. Supports values with integer or pointer type and
|
||||
/// vectors of integers.
|
||||
bool isKnownNonZero(Value *V, const DataLayout *TD = 0, unsigned Depth = 0);
|
||||
|
||||
/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use
|
||||
/// this predicate to simplify operations downstream. Mask is known to be
|
||||
/// zero for bits that V cannot have.
|
||||
///
|
||||
/// This function is defined on values with integer type, values with pointer
|
||||
/// type (but only if TD is non-null), and vectors of integers. In the case
|
||||
/// where V is a vector, the mask, known zero, and known one values are the
|
||||
/// same width as the vector element, and the bit is set only if it is true
|
||||
/// for all of the elements in the vector.
|
||||
bool MaskedValueIsZero(Value *V, const APInt &Mask,
|
||||
const DataLayout *TD = 0, unsigned Depth = 0);
|
||||
|
||||
|
||||
/// ComputeNumSignBits - Return the number of times the sign bit of the
|
||||
/// register is replicated into the other bits. We know that at least 1 bit
|
||||
/// is always equal to the sign bit (itself), but other cases can give us
|
||||
/// information. For example, immediately after an "ashr X, 2", we know that
|
||||
/// the top 3 bits are all equal to each other, so we return 3.
|
||||
///
|
||||
/// 'Op' must have a scalar integer type.
|
||||
///
|
||||
unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = 0,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// ComputeMultiple - This function computes the integer multiple of Base that
|
||||
/// equals V. If successful, it returns true and returns the multiple in
|
||||
/// Multiple. If unsuccessful, it returns false. Also, if V can be
|
||||
/// simplified to an integer, then the simplified V is returned in Val. Look
|
||||
/// through sext only if LookThroughSExt=true.
|
||||
bool ComputeMultiple(Value *V, unsigned Base, Value *&Multiple,
|
||||
bool LookThroughSExt = false,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// CannotBeNegativeZero - Return true if we can prove that the specified FP
|
||||
/// value is never equal to -0.0.
|
||||
///
|
||||
bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0);
|
||||
|
||||
/// isBytewiseValue - If the specified value can be set by repeating the same
|
||||
/// byte in memory, return the i8 value that it is represented with. This is
|
||||
/// true for all i8 values obviously, but is also true for i32 0, i32 -1,
|
||||
/// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated
|
||||
/// byte store (e.g. i16 0x1234), return null.
|
||||
Value *isBytewiseValue(Value *V);
|
||||
|
||||
/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if
|
||||
/// the scalar value indexed is already around as a register, for example if
|
||||
/// it were inserted directly into the aggregrate.
|
||||
///
|
||||
/// If InsertBefore is not null, this function will duplicate (modified)
|
||||
/// insertvalues when a part of a nested struct is extracted.
|
||||
Value *FindInsertedValue(Value *V,
|
||||
ArrayRef<unsigned> idx_range,
|
||||
Instruction *InsertBefore = 0);
|
||||
|
||||
/// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if
|
||||
/// it can be expressed as a base pointer plus a constant offset. Return the
|
||||
/// base and offset to the caller.
|
||||
Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
|
||||
const DataLayout *TD);
|
||||
static inline const Value *
|
||||
GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset,
|
||||
const DataLayout *TD) {
|
||||
return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
|
||||
}
|
||||
|
||||
/// getConstantStringInfo - This function computes the length of a
|
||||
/// null-terminated C string pointed to by V. If successful, it returns true
|
||||
/// and returns the string in Str. If unsuccessful, it returns false. This
|
||||
/// does not include the trailing nul character by default. If TrimAtNul is
|
||||
/// set to false, then this returns any trailing nul characters as well as any
|
||||
/// other characters that come after it.
|
||||
bool getConstantStringInfo(const Value *V, StringRef &Str,
|
||||
uint64_t Offset = 0, bool TrimAtNul = true);
|
||||
|
||||
/// GetStringLength - If we can compute the length of the string pointed to by
|
||||
/// the specified pointer, return 'len+1'. If we can't, return 0.
|
||||
uint64_t GetStringLength(Value *V);
|
||||
|
||||
/// GetUnderlyingObject - This method strips off any GEP address adjustments
|
||||
/// and pointer casts from the specified value, returning the original object
|
||||
/// being addressed. Note that the returned value has pointer type if the
|
||||
/// specified value does. If the MaxLookup value is non-zero, it limits the
|
||||
/// number of instructions to be stripped off.
|
||||
Value *GetUnderlyingObject(Value *V, const DataLayout *TD = 0,
|
||||
unsigned MaxLookup = 6);
|
||||
static inline const Value *
|
||||
GetUnderlyingObject(const Value *V, const DataLayout *TD = 0,
|
||||
unsigned MaxLookup = 6) {
|
||||
return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup);
|
||||
}
|
||||
|
||||
/// GetUnderlyingObjects - This method is similar to GetUnderlyingObject
|
||||
/// except that it can look through phi and select instructions and return
|
||||
/// multiple objects.
|
||||
void GetUnderlyingObjects(Value *V,
|
||||
SmallVectorImpl<Value *> &Objects,
|
||||
const DataLayout *TD = 0,
|
||||
unsigned MaxLookup = 6);
|
||||
|
||||
/// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer
|
||||
/// are lifetime markers.
|
||||
bool onlyUsedByLifetimeMarkers(const Value *V);
|
||||
|
||||
/// isSafeToSpeculativelyExecute - Return true if the instruction does not
|
||||
/// have any effects besides calculating the result and does not have
|
||||
/// undefined behavior.
|
||||
///
|
||||
/// This method never returns true for an instruction that returns true for
|
||||
/// mayHaveSideEffects; however, this method also does some other checks in
|
||||
/// addition. It checks for undefined behavior, like dividing by zero or
|
||||
/// loading from an invalid pointer (but not for undefined results, like a
|
||||
/// shift with a shift amount larger than the width of the result). It checks
|
||||
/// for malloc and alloca because speculatively executing them might cause a
|
||||
/// memory leak. It also returns false for instructions related to control
|
||||
/// flow, specifically terminators and PHI nodes.
|
||||
///
|
||||
/// This method only looks at the instruction itself and its operands, so if
|
||||
/// this method returns true, it is safe to move the instruction as long as
|
||||
/// the correct dominance relationships for the operands and users hold.
|
||||
/// However, this method can return true for instructions that read memory;
|
||||
/// for such instructions, moving them may change the resulting value.
|
||||
bool isSafeToSpeculativelyExecute(const Value *V,
|
||||
const DataLayout *TD = 0);
|
||||
|
||||
/// isKnownNonNull - Return true if this pointer couldn't possibly be null by
|
||||
/// its definition. This returns true for allocas, non-extern-weak globals
|
||||
/// and byval arguments.
|
||||
bool isKnownNonNull(const Value *V);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
75
thirdparty/clang/include/llvm/Analysis/Verifier.h
vendored
Normal file
75
thirdparty/clang/include/llvm/Analysis/Verifier.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
//===-- llvm/Analysis/Verifier.h - LLVM IR Verifier -------------*- 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 function verifier interface, that can be used for some
|
||||
// sanity checking of input to the system, and for checking that transformations
|
||||
// haven't done something bad.
|
||||
//
|
||||
// Note that this does not provide full 'java style' security and verifications,
|
||||
// instead it just tries to ensure that code is well formed.
|
||||
//
|
||||
// To see what specifically is checked, look at the top of Verifier.cpp
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_VERIFIER_H
|
||||
#define LLVM_ANALYSIS_VERIFIER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class FunctionPass;
|
||||
class Module;
|
||||
class Function;
|
||||
|
||||
/// @brief An enumeration to specify the action to be taken if errors found.
|
||||
///
|
||||
/// This enumeration is used in the functions below to indicate what should
|
||||
/// happen if the verifier finds errors. Each of the functions that uses
|
||||
/// this enumeration as an argument provides a default value for it. The
|
||||
/// actions are listed below.
|
||||
enum VerifierFailureAction {
|
||||
AbortProcessAction, ///< verifyModule will print to stderr and abort()
|
||||
PrintMessageAction, ///< verifyModule will print to stderr and return true
|
||||
ReturnStatusAction ///< verifyModule will just return true
|
||||
};
|
||||
|
||||
/// @brief Create a verifier pass.
|
||||
///
|
||||
/// Check a module or function for validity. When the pass is used, the
|
||||
/// action indicated by the \p action argument will be used if errors are
|
||||
/// found.
|
||||
FunctionPass *createVerifierPass(
|
||||
VerifierFailureAction action = AbortProcessAction ///< Action to take
|
||||
);
|
||||
|
||||
/// @brief Check a module for errors.
|
||||
///
|
||||
/// If there are no errors, the function returns false. If an error is found,
|
||||
/// the action taken depends on the \p action parameter.
|
||||
/// This should only be used for debugging, because it plays games with
|
||||
/// PassManagers and stuff.
|
||||
|
||||
bool verifyModule(
|
||||
const Module &M, ///< The module to be verified
|
||||
VerifierFailureAction action = AbortProcessAction, ///< Action to take
|
||||
std::string *ErrorInfo = 0 ///< Information about failures.
|
||||
);
|
||||
|
||||
// verifyFunction - Check a function for errors, useful for use when debugging a
|
||||
// pass.
|
||||
bool verifyFunction(
|
||||
const Function &F, ///< The function to be verified
|
||||
VerifierFailureAction action = AbortProcessAction ///< Action to take
|
||||
);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user