mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[Analysis] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 311048
This commit is contained in:
parent
6a4ddfbe1b
commit
4b30ec0e2d
@ -1,4 +1,4 @@
|
|||||||
//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===//
|
//==- llvm/Analysis/MemoryBuiltins.h - Calls to memory builtins --*- C++ -*-==//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -15,21 +15,42 @@
|
|||||||
#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
|
#ifndef LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||||
#define LLVM_ANALYSIS_MEMORYBUILTINS_H
|
#define LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/APInt.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/Analysis/TargetFolder.h"
|
#include "llvm/Analysis/TargetFolder.h"
|
||||||
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/IRBuilder.h"
|
#include "llvm/IR/IRBuilder.h"
|
||||||
#include "llvm/IR/InstVisitor.h"
|
#include "llvm/IR/InstVisitor.h"
|
||||||
#include "llvm/IR/Operator.h"
|
|
||||||
#include "llvm/IR/ValueHandle.h"
|
#include "llvm/IR/ValueHandle.h"
|
||||||
#include "llvm/Support/DataTypes.h"
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class AllocaInst;
|
||||||
|
class Argument;
|
||||||
class CallInst;
|
class CallInst;
|
||||||
class PointerType;
|
class ConstantInt;
|
||||||
|
class ConstantPointerNull;
|
||||||
class DataLayout;
|
class DataLayout;
|
||||||
|
class ExtractElementInst;
|
||||||
|
class ExtractValueInst;
|
||||||
|
class GEPOperator;
|
||||||
|
class GlobalAlias;
|
||||||
|
class GlobalVariable;
|
||||||
|
class Instruction;
|
||||||
|
class IntegerType;
|
||||||
|
class IntrinsicInst;
|
||||||
|
class IntToPtrInst;
|
||||||
|
class LLVMContext;
|
||||||
|
class LoadInst;
|
||||||
|
class PHINode;
|
||||||
|
class PointerType;
|
||||||
|
class SelectInst;
|
||||||
class TargetLibraryInfo;
|
class TargetLibraryInfo;
|
||||||
class Type;
|
class Type;
|
||||||
|
class UndefValue;
|
||||||
class Value;
|
class Value;
|
||||||
|
|
||||||
/// \brief Tests if a value is a call or invoke to a library function that
|
/// \brief Tests if a value is a call or invoke to a library function that
|
||||||
@ -123,7 +144,6 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) {
|
|||||||
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
|
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Utility functions to compute size of objects.
|
// Utility functions to compute size of objects.
|
||||||
//
|
//
|
||||||
@ -169,13 +189,12 @@ ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize,
|
|||||||
const TargetLibraryInfo *TLI,
|
const TargetLibraryInfo *TLI,
|
||||||
bool MustSucceed);
|
bool MustSucceed);
|
||||||
|
|
||||||
typedef std::pair<APInt, APInt> SizeOffsetType;
|
using SizeOffsetType = std::pair<APInt, APInt>;
|
||||||
|
|
||||||
/// \brief Evaluate the size and offset of an object pointed to by a Value*
|
/// \brief Evaluate the size and offset of an object pointed to by a Value*
|
||||||
/// statically. Fails if size or offset are not known at compile time.
|
/// statically. Fails if size or offset are not known at compile time.
|
||||||
class ObjectSizeOffsetVisitor
|
class ObjectSizeOffsetVisitor
|
||||||
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
|
: public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> {
|
||||||
|
|
||||||
const DataLayout &DL;
|
const DataLayout &DL;
|
||||||
const TargetLibraryInfo *TLI;
|
const TargetLibraryInfo *TLI;
|
||||||
ObjectSizeOpts Options;
|
ObjectSizeOpts Options;
|
||||||
@ -229,18 +248,16 @@ private:
|
|||||||
bool CheckedZextOrTrunc(APInt &I);
|
bool CheckedZextOrTrunc(APInt &I);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::pair<Value*, Value*> SizeOffsetEvalType;
|
using SizeOffsetEvalType = std::pair<Value *, Value *>;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Evaluate the size and offset of an object pointed to by a Value*.
|
/// \brief Evaluate the size and offset of an object pointed to by a Value*.
|
||||||
/// May create code to compute the result at run-time.
|
/// May create code to compute the result at run-time.
|
||||||
class ObjectSizeOffsetEvaluator
|
class ObjectSizeOffsetEvaluator
|
||||||
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
|
: public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> {
|
||||||
|
using BuilderTy = IRBuilder<TargetFolder>;
|
||||||
typedef IRBuilder<TargetFolder> BuilderTy;
|
using WeakEvalType = std::pair<WeakTrackingVH, WeakTrackingVH>;
|
||||||
typedef std::pair<WeakTrackingVH, WeakTrackingVH> WeakEvalType;
|
using CacheMapTy = DenseMap<const Value *, WeakEvalType>;
|
||||||
typedef DenseMap<const Value*, WeakEvalType> CacheMapTy;
|
using PtrSetTy = SmallPtrSet<const Value *, 8>;
|
||||||
typedef SmallPtrSet<const Value*, 8> PtrSetTy;
|
|
||||||
|
|
||||||
const DataLayout &DL;
|
const DataLayout &DL;
|
||||||
const TargetLibraryInfo *TLI;
|
const TargetLibraryInfo *TLI;
|
||||||
@ -255,11 +272,13 @@ class ObjectSizeOffsetEvaluator
|
|||||||
SizeOffsetEvalType unknown() {
|
SizeOffsetEvalType unknown() {
|
||||||
return std::make_pair(nullptr, nullptr);
|
return std::make_pair(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeOffsetEvalType compute_(Value *V);
|
SizeOffsetEvalType compute_(Value *V);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
|
ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI,
|
||||||
LLVMContext &Context, bool RoundToAlign = false);
|
LLVMContext &Context, bool RoundToAlign = false);
|
||||||
|
|
||||||
SizeOffsetEvalType compute(Value *V);
|
SizeOffsetEvalType compute(Value *V);
|
||||||
|
|
||||||
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
bool knownSize(SizeOffsetEvalType SizeOffset) {
|
||||||
@ -291,6 +310,6 @@ public:
|
|||||||
SizeOffsetEvalType visitInstruction(Instruction &I);
|
SizeOffsetEvalType visitInstruction(Instruction &I);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif // LLVM_ANALYSIS_MEMORYBUILTINS_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- C++ -*-===//
|
//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -15,26 +15,35 @@
|
|||||||
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
|
#define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
|
||||||
|
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/ADT/PointerEmbeddedInt.h"
|
#include "llvm/ADT/PointerEmbeddedInt.h"
|
||||||
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
#include "llvm/ADT/PointerSumType.h"
|
#include "llvm/ADT/PointerSumType.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
|
#include "llvm/Analysis/MemoryLocation.h"
|
||||||
#include "llvm/IR/BasicBlock.h"
|
#include "llvm/IR/BasicBlock.h"
|
||||||
|
#include "llvm/IR/Metadata.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/IR/PredIteratorCache.h"
|
#include "llvm/IR/PredIteratorCache.h"
|
||||||
#include "llvm/IR/ValueHandle.h"
|
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class Function;
|
|
||||||
class FunctionPass;
|
|
||||||
class Instruction;
|
|
||||||
class CallSite;
|
|
||||||
class AssumptionCache;
|
class AssumptionCache;
|
||||||
class MemoryDependenceResults;
|
class CallSite;
|
||||||
class PredIteratorCache;
|
|
||||||
class DominatorTree;
|
class DominatorTree;
|
||||||
|
class Function;
|
||||||
|
class Instruction;
|
||||||
|
class LoadInst;
|
||||||
class PHITransAddr;
|
class PHITransAddr;
|
||||||
|
class TargetLibraryInfo;
|
||||||
|
class Value;
|
||||||
|
|
||||||
/// A memory dependence query can return one of three different answers.
|
/// A memory dependence query can return one of three different answers.
|
||||||
class MemDepResult {
|
class MemDepResult {
|
||||||
@ -105,17 +114,17 @@ class MemDepResult {
|
|||||||
Unknown
|
Unknown
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef PointerSumType<
|
using ValueTy = PointerSumType<
|
||||||
DepType, PointerSumTypeMember<Invalid, Instruction *>,
|
DepType, PointerSumTypeMember<Invalid, Instruction *>,
|
||||||
PointerSumTypeMember<Clobber, Instruction *>,
|
PointerSumTypeMember<Clobber, Instruction *>,
|
||||||
PointerSumTypeMember<Def, Instruction *>,
|
PointerSumTypeMember<Def, Instruction *>,
|
||||||
PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>
|
PointerSumTypeMember<Other, PointerEmbeddedInt<OtherType, 3>>>;
|
||||||
ValueTy;
|
|
||||||
ValueTy Value;
|
ValueTy Value;
|
||||||
|
|
||||||
explicit MemDepResult(ValueTy V) : Value(V) {}
|
explicit MemDepResult(ValueTy V) : Value(V) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemDepResult() : Value() {}
|
MemDepResult() = default;
|
||||||
|
|
||||||
/// get methods: These are static ctor methods for creating various
|
/// get methods: These are static ctor methods for creating various
|
||||||
/// MemDepResult kinds.
|
/// MemDepResult kinds.
|
||||||
@ -266,23 +275,23 @@ public:
|
|||||||
/// internal caching mechanism.
|
/// internal caching mechanism.
|
||||||
class MemoryDependenceResults {
|
class MemoryDependenceResults {
|
||||||
// A map from instructions to their dependency.
|
// A map from instructions to their dependency.
|
||||||
typedef DenseMap<Instruction *, MemDepResult> LocalDepMapType;
|
using LocalDepMapType = DenseMap<Instruction *, MemDepResult>;
|
||||||
LocalDepMapType LocalDeps;
|
LocalDepMapType LocalDeps;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
|
using NonLocalDepInfo = std::vector<NonLocalDepEntry>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// A pair<Value*, bool> where the bool is true if the dependence is a read
|
/// A pair<Value*, bool> where the bool is true if the dependence is a read
|
||||||
/// only dependence, false if read/write.
|
/// only dependence, false if read/write.
|
||||||
typedef PointerIntPair<const Value *, 1, bool> ValueIsLoadPair;
|
using ValueIsLoadPair = PointerIntPair<const Value *, 1, bool>;
|
||||||
|
|
||||||
/// This pair is used when caching information for a block.
|
/// 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
|
/// 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
|
/// at the specified block. If non-null, the bool indicates whether or not
|
||||||
/// the contents of the block was skipped.
|
/// the contents of the block was skipped.
|
||||||
typedef PointerIntPair<BasicBlock *, 1, bool> BBSkipFirstBlockPair;
|
using BBSkipFirstBlockPair = PointerIntPair<BasicBlock *, 1, bool>;
|
||||||
|
|
||||||
/// This record is the information kept for each (value, is load) pair.
|
/// This record is the information kept for each (value, is load) pair.
|
||||||
struct NonLocalPointerInfo {
|
struct NonLocalPointerInfo {
|
||||||
@ -293,31 +302,32 @@ private:
|
|||||||
/// The maximum size of the dereferences of the pointer.
|
/// The maximum size of the dereferences of the pointer.
|
||||||
///
|
///
|
||||||
/// May be UnknownSize if the sizes are unknown.
|
/// May be UnknownSize if the sizes are unknown.
|
||||||
uint64_t Size;
|
uint64_t Size = MemoryLocation::UnknownSize;
|
||||||
/// The AA tags associated with dereferences of the pointer.
|
/// The AA tags associated with dereferences of the pointer.
|
||||||
///
|
///
|
||||||
/// The members may be null if there are no tags or conflicting tags.
|
/// The members may be null if there are no tags or conflicting tags.
|
||||||
AAMDNodes AATags;
|
AAMDNodes AATags;
|
||||||
|
|
||||||
NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
|
NonLocalPointerInfo() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Cache storing single nonlocal def for the instruction.
|
/// Cache storing single nonlocal def for the instruction.
|
||||||
/// It is set when nonlocal def would be found in function returning only
|
/// It is set when nonlocal def would be found in function returning only
|
||||||
/// local dependencies.
|
/// local dependencies.
|
||||||
DenseMap<Instruction *, NonLocalDepResult> NonLocalDefsCache;
|
DenseMap<Instruction *, NonLocalDepResult> NonLocalDefsCache;
|
||||||
|
|
||||||
/// This map stores the cached results of doing a pointer lookup at the
|
/// This map stores the cached results of doing a pointer lookup at the
|
||||||
/// bottom of a block.
|
/// bottom of a block.
|
||||||
///
|
///
|
||||||
/// The key of this map is the pointer+isload bit, the value is a list of
|
/// The key of this map is the pointer+isload bit, the value is a list of
|
||||||
/// <bb->result> mappings.
|
/// <bb->result> mappings.
|
||||||
typedef DenseMap<ValueIsLoadPair, NonLocalPointerInfo>
|
using CachedNonLocalPointerInfo =
|
||||||
CachedNonLocalPointerInfo;
|
DenseMap<ValueIsLoadPair, NonLocalPointerInfo>;
|
||||||
CachedNonLocalPointerInfo NonLocalPointerDeps;
|
CachedNonLocalPointerInfo NonLocalPointerDeps;
|
||||||
|
|
||||||
// A map from instructions to their non-local pointer dependencies.
|
// A map from instructions to their non-local pointer dependencies.
|
||||||
typedef DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>
|
using ReverseNonLocalPtrDepTy =
|
||||||
ReverseNonLocalPtrDepTy;
|
DenseMap<Instruction *, SmallPtrSet<ValueIsLoadPair, 4>>;
|
||||||
ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
|
ReverseNonLocalPtrDepTy ReverseNonLocalPtrDeps;
|
||||||
|
|
||||||
/// This is the instruction we keep for each cached access that we have for
|
/// This is the instruction we keep for each cached access that we have for
|
||||||
@ -325,17 +335,17 @@ private:
|
|||||||
///
|
///
|
||||||
/// The pointer is an owning pointer and the bool indicates whether we have
|
/// The pointer is an owning pointer and the bool indicates whether we have
|
||||||
/// any dirty bits in the set.
|
/// any dirty bits in the set.
|
||||||
typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
|
using PerInstNLInfo = std::pair<NonLocalDepInfo, bool>;
|
||||||
|
|
||||||
// A map from instructions to their non-local dependencies.
|
// A map from instructions to their non-local dependencies.
|
||||||
typedef DenseMap<Instruction *, PerInstNLInfo> NonLocalDepMapType;
|
using NonLocalDepMapType = DenseMap<Instruction *, PerInstNLInfo>;
|
||||||
|
|
||||||
NonLocalDepMapType NonLocalDeps;
|
NonLocalDepMapType NonLocalDeps;
|
||||||
|
|
||||||
// A reverse mapping from dependencies to the dependees. This is
|
// A reverse mapping from dependencies to the dependees. This is
|
||||||
// used when removing instructions to keep the cache coherent.
|
// used when removing instructions to keep the cache coherent.
|
||||||
typedef DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>
|
using ReverseDepMapType =
|
||||||
ReverseDepMapType;
|
DenseMap<Instruction *, SmallPtrSet<Instruction *, 4>>;
|
||||||
ReverseDepMapType ReverseLocalDeps;
|
ReverseDepMapType ReverseLocalDeps;
|
||||||
|
|
||||||
// A reverse mapping from dependencies to the non-local dependees.
|
// A reverse mapping from dependencies to the non-local dependees.
|
||||||
@ -493,10 +503,11 @@ private:
|
|||||||
class MemoryDependenceAnalysis
|
class MemoryDependenceAnalysis
|
||||||
: public AnalysisInfoMixin<MemoryDependenceAnalysis> {
|
: public AnalysisInfoMixin<MemoryDependenceAnalysis> {
|
||||||
friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
|
friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
|
||||||
|
|
||||||
static AnalysisKey Key;
|
static AnalysisKey Key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef MemoryDependenceResults Result;
|
using Result = MemoryDependenceResults;
|
||||||
|
|
||||||
MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM);
|
MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM);
|
||||||
};
|
};
|
||||||
@ -505,10 +516,12 @@ public:
|
|||||||
/// MemoryDepnedenceResults instance.
|
/// MemoryDepnedenceResults instance.
|
||||||
class MemoryDependenceWrapperPass : public FunctionPass {
|
class MemoryDependenceWrapperPass : public FunctionPass {
|
||||||
Optional<MemoryDependenceResults> MemDep;
|
Optional<MemoryDependenceResults> MemDep;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static char ID;
|
||||||
|
|
||||||
MemoryDependenceWrapperPass();
|
MemoryDependenceWrapperPass();
|
||||||
~MemoryDependenceWrapperPass() override;
|
~MemoryDependenceWrapperPass() override;
|
||||||
static char ID;
|
|
||||||
|
|
||||||
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
|
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
|
||||||
bool runOnFunction(Function &) override;
|
bool runOnFunction(Function &) override;
|
||||||
@ -522,6 +535,6 @@ public:
|
|||||||
MemoryDependenceResults &getMemDep() { return *MemDep; }
|
MemoryDependenceResults &getMemDep() { return *MemDep; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif // LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
// License. See LICENSE.TXT for details.
|
// License. See LICENSE.TXT for details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
///
|
//
|
||||||
/// \file
|
/// \file
|
||||||
/// \brief This file exposes an interface to building/using memory SSA to
|
/// \brief This file exposes an interface to building/using memory SSA to
|
||||||
/// walk memory instructions using a use/def graph.
|
/// walk memory instructions using a use/def graph.
|
||||||
@ -67,6 +67,7 @@
|
|||||||
/// MemoryDefs are not disambiguated because it would require multiple reaching
|
/// MemoryDefs are not disambiguated because it would require multiple reaching
|
||||||
/// definitions, which would require multiple phis, and multiple memoryaccesses
|
/// definitions, which would require multiple phis, and multiple memoryaccesses
|
||||||
/// per instruction.
|
/// per instruction.
|
||||||
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_ANALYSIS_MEMORYSSA_H
|
#ifndef LLVM_ANALYSIS_MEMORYSSA_H
|
||||||
@ -80,6 +81,7 @@
|
|||||||
#include "llvm/ADT/ilist_node.h"
|
#include "llvm/ADT/ilist_node.h"
|
||||||
#include "llvm/ADT/iterator.h"
|
#include "llvm/ADT/iterator.h"
|
||||||
#include "llvm/ADT/iterator_range.h"
|
#include "llvm/ADT/iterator_range.h"
|
||||||
|
#include "llvm/ADT/simple_ilist.h"
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Analysis/MemoryLocation.h"
|
#include "llvm/Analysis/MemoryLocation.h"
|
||||||
#include "llvm/Analysis/PHITransAddr.h"
|
#include "llvm/Analysis/PHITransAddr.h"
|
||||||
@ -87,14 +89,12 @@
|
|||||||
#include "llvm/IR/DerivedUser.h"
|
#include "llvm/IR/DerivedUser.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/OperandTraits.h"
|
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
#include "llvm/IR/Use.h"
|
#include "llvm/IR/Use.h"
|
||||||
#include "llvm/IR/User.h"
|
#include "llvm/IR/User.h"
|
||||||
#include "llvm/IR/Value.h"
|
#include "llvm/IR/Value.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -107,12 +107,16 @@ namespace llvm {
|
|||||||
class Function;
|
class Function;
|
||||||
class Instruction;
|
class Instruction;
|
||||||
class MemoryAccess;
|
class MemoryAccess;
|
||||||
|
class MemorySSAWalker;
|
||||||
class LLVMContext;
|
class LLVMContext;
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
|
||||||
namespace MSSAHelpers {
|
namespace MSSAHelpers {
|
||||||
|
|
||||||
struct AllAccessTag {};
|
struct AllAccessTag {};
|
||||||
struct DefsOnlyTag {};
|
struct DefsOnlyTag {};
|
||||||
}
|
|
||||||
|
} // end namespace MSSAHelpers
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// Used to signify what the default invalid ID is for MemoryAccess's
|
// Used to signify what the default invalid ID is for MemoryAccess's
|
||||||
@ -137,6 +141,11 @@ public:
|
|||||||
using DefsOnlyType =
|
using DefsOnlyType =
|
||||||
ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
|
ilist_node<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>;
|
||||||
|
|
||||||
|
MemoryAccess(const MemoryAccess &) = delete;
|
||||||
|
MemoryAccess &operator=(const MemoryAccess &) = delete;
|
||||||
|
|
||||||
|
void *operator new(size_t) = delete;
|
||||||
|
|
||||||
// Methods for support type inquiry through isa, cast, and
|
// Methods for support type inquiry through isa, cast, and
|
||||||
// dyn_cast
|
// dyn_cast
|
||||||
static bool classof(const Value *V) {
|
static bool classof(const Value *V) {
|
||||||
@ -144,19 +153,14 @@ public:
|
|||||||
return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
|
return ID == MemoryUseVal || ID == MemoryPhiVal || ID == MemoryDefVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryAccess(const MemoryAccess &) = delete;
|
|
||||||
MemoryAccess &operator=(const MemoryAccess &) = delete;
|
|
||||||
|
|
||||||
void *operator new(size_t) = delete;
|
|
||||||
|
|
||||||
BasicBlock *getBlock() const { return Block; }
|
BasicBlock *getBlock() const { return Block; }
|
||||||
|
|
||||||
void print(raw_ostream &OS) const;
|
void print(raw_ostream &OS) const;
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
|
||||||
/// \brief The user iterators for a memory access
|
/// \brief The user iterators for a memory access
|
||||||
typedef user_iterator iterator;
|
using iterator = user_iterator;
|
||||||
typedef const_user_iterator const_iterator;
|
using const_iterator = const_user_iterator;
|
||||||
|
|
||||||
/// \brief This iterator walks over all of the defs in a given
|
/// \brief This iterator walks over all of the defs in a given
|
||||||
/// MemoryAccess. For MemoryPhi nodes, this walks arguments. For
|
/// MemoryAccess. For MemoryPhi nodes, this walks arguments. For
|
||||||
@ -194,11 +198,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class MemorySSA;
|
|
||||||
friend class MemoryUseOrDef;
|
|
||||||
friend class MemoryUse;
|
|
||||||
friend class MemoryDef;
|
friend class MemoryDef;
|
||||||
friend class MemoryPhi;
|
friend class MemoryPhi;
|
||||||
|
friend class MemorySSA;
|
||||||
|
friend class MemoryUse;
|
||||||
|
friend class MemoryUseOrDef;
|
||||||
|
|
||||||
/// \brief Used by MemorySSA to change the block of a MemoryAccess when it is
|
/// \brief Used by MemorySSA to change the block of a MemoryAccess when it is
|
||||||
/// moved.
|
/// moved.
|
||||||
@ -259,11 +263,13 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
friend class MemorySSA;
|
friend class MemorySSA;
|
||||||
friend class MemorySSAUpdater;
|
friend class MemorySSAUpdater;
|
||||||
|
|
||||||
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
|
MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty,
|
||||||
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
|
DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB)
|
||||||
: MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
|
: MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) {
|
||||||
setDefiningAccess(DMA);
|
setDefiningAccess(DMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
|
void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) {
|
||||||
if (!Optimized) {
|
if (!Optimized) {
|
||||||
setOperand(0, DMA);
|
setOperand(0, DMA);
|
||||||
@ -291,8 +297,7 @@ public:
|
|||||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
||||||
|
|
||||||
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
|
MemoryUse(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB)
|
||||||
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB),
|
: MemoryUseOrDef(C, DMA, MemoryUseVal, deleteMe, MI, BB) {}
|
||||||
OptimizedID(0) {}
|
|
||||||
|
|
||||||
// allocate space for exactly one operand
|
// allocate space for exactly one operand
|
||||||
void *operator new(size_t s) { return User::operator new(s, 1); }
|
void *operator new(size_t s) { return User::operator new(s, 1); }
|
||||||
@ -315,6 +320,7 @@ public:
|
|||||||
MemoryAccess *getOptimized() const {
|
MemoryAccess *getOptimized() const {
|
||||||
return getDefiningAccess();
|
return getDefiningAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetOptimized() {
|
void resetOptimized() {
|
||||||
OptimizedID = INVALID_MEMORYACCESS_ID;
|
OptimizedID = INVALID_MEMORYACCESS_ID;
|
||||||
}
|
}
|
||||||
@ -325,7 +331,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
static void deleteMe(DerivedUser *Self);
|
static void deleteMe(DerivedUser *Self);
|
||||||
|
|
||||||
unsigned int OptimizedID;
|
unsigned int OptimizedID = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -343,12 +349,13 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess)
|
|||||||
/// MemoryDef/MemoryPhi.
|
/// MemoryDef/MemoryPhi.
|
||||||
class MemoryDef final : public MemoryUseOrDef {
|
class MemoryDef final : public MemoryUseOrDef {
|
||||||
public:
|
public:
|
||||||
|
friend class MemorySSA;
|
||||||
|
|
||||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
|
||||||
|
|
||||||
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
|
MemoryDef(LLVMContext &C, MemoryAccess *DMA, Instruction *MI, BasicBlock *BB,
|
||||||
unsigned Ver)
|
unsigned Ver)
|
||||||
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB),
|
: MemoryUseOrDef(C, DMA, MemoryDefVal, deleteMe, MI, BB), ID(Ver) {}
|
||||||
ID(Ver), Optimized(nullptr), OptimizedID(INVALID_MEMORYACCESS_ID) {}
|
|
||||||
|
|
||||||
// allocate space for exactly one operand
|
// allocate space for exactly one operand
|
||||||
void *operator new(size_t s) { return User::operator new(s, 1); }
|
void *operator new(size_t s) { return User::operator new(s, 1); }
|
||||||
@ -361,27 +368,28 @@ public:
|
|||||||
Optimized = MA;
|
Optimized = MA;
|
||||||
OptimizedID = getDefiningAccess()->getID();
|
OptimizedID = getDefiningAccess()->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryAccess *getOptimized() const { return Optimized; }
|
MemoryAccess *getOptimized() const { return Optimized; }
|
||||||
|
|
||||||
bool isOptimized() const {
|
bool isOptimized() const {
|
||||||
return getOptimized() && getDefiningAccess() &&
|
return getOptimized() && getDefiningAccess() &&
|
||||||
OptimizedID == getDefiningAccess()->getID();
|
OptimizedID == getDefiningAccess()->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetOptimized() {
|
void resetOptimized() {
|
||||||
OptimizedID = INVALID_MEMORYACCESS_ID;
|
OptimizedID = INVALID_MEMORYACCESS_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(raw_ostream &OS) const;
|
void print(raw_ostream &OS) const;
|
||||||
|
|
||||||
friend class MemorySSA;
|
|
||||||
|
|
||||||
unsigned getID() const { return ID; }
|
unsigned getID() const { return ID; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void deleteMe(DerivedUser *Self);
|
static void deleteMe(DerivedUser *Self);
|
||||||
|
|
||||||
const unsigned ID;
|
const unsigned ID;
|
||||||
MemoryAccess *Optimized;
|
MemoryAccess *Optimized = nullptr;
|
||||||
unsigned int OptimizedID;
|
unsigned int OptimizedID = INVALID_MEMORYACCESS_ID;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -436,8 +444,8 @@ public:
|
|||||||
|
|
||||||
// Block iterator interface. This provides access to the list of incoming
|
// Block iterator interface. This provides access to the list of incoming
|
||||||
// basic blocks, which parallels the list of incoming values.
|
// basic blocks, which parallels the list of incoming values.
|
||||||
typedef BasicBlock **block_iterator;
|
using block_iterator = BasicBlock **;
|
||||||
typedef BasicBlock *const *const_block_iterator;
|
using const_block_iterator = BasicBlock *const *;
|
||||||
|
|
||||||
block_iterator block_begin() {
|
block_iterator block_begin() {
|
||||||
auto *Ref = reinterpret_cast<Use::UserRef *>(op_begin() + ReservedSpace);
|
auto *Ref = reinterpret_cast<Use::UserRef *>(op_begin() + ReservedSpace);
|
||||||
@ -477,6 +485,7 @@ public:
|
|||||||
assert(V && "PHI node got a null value!");
|
assert(V && "PHI node got a null value!");
|
||||||
setOperand(I, V);
|
setOperand(I, V);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned getOperandNumForIncomingValue(unsigned I) { return I; }
|
static unsigned getOperandNumForIncomingValue(unsigned I) { return I; }
|
||||||
static unsigned getIncomingValueNumForOperand(unsigned I) { return I; }
|
static unsigned getIncomingValueNumForOperand(unsigned I) { return I; }
|
||||||
|
|
||||||
@ -595,12 +604,9 @@ inline void MemoryUseOrDef::resetOptimized() {
|
|||||||
cast<MemoryUse>(this)->resetOptimized();
|
cast<MemoryUse>(this)->resetOptimized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
|
template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {};
|
||||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
|
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess)
|
||||||
|
|
||||||
class MemorySSAWalker;
|
|
||||||
|
|
||||||
/// \brief Encapsulates MemorySSA, including all data associated with memory
|
/// \brief Encapsulates MemorySSA, including all data associated with memory
|
||||||
/// accesses.
|
/// accesses.
|
||||||
class MemorySSA {
|
class MemorySSA {
|
||||||
@ -707,11 +713,13 @@ protected:
|
|||||||
|
|
||||||
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
|
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where);
|
||||||
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point);
|
void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point);
|
||||||
|
|
||||||
// Rename the dominator tree branch rooted at BB.
|
// Rename the dominator tree branch rooted at BB.
|
||||||
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
|
void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal,
|
||||||
SmallPtrSetImpl<BasicBlock *> &Visited) {
|
SmallPtrSetImpl<BasicBlock *> &Visited) {
|
||||||
renamePass(DT->getNode(BB), IncomingVal, Visited, true, true);
|
renamePass(DT->getNode(BB), IncomingVal, Visited, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeFromLookups(MemoryAccess *);
|
void removeFromLookups(MemoryAccess *);
|
||||||
void removeFromLists(MemoryAccess *, bool ShouldDelete = true);
|
void removeFromLists(MemoryAccess *, bool ShouldDelete = true);
|
||||||
void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *,
|
void insertIntoListsForBlock(MemoryAccess *, const BasicBlock *,
|
||||||
@ -729,6 +737,7 @@ private:
|
|||||||
void optimizeUses();
|
void optimizeUses();
|
||||||
|
|
||||||
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
|
void verifyUseInDefs(MemoryAccess *, MemoryAccess *) const;
|
||||||
|
|
||||||
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
|
using AccessMap = DenseMap<const BasicBlock *, std::unique_ptr<AccessList>>;
|
||||||
using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>;
|
using DefsMap = DenseMap<const BasicBlock *, std::unique_ptr<DefsList>>;
|
||||||
|
|
||||||
@ -755,6 +764,7 @@ private:
|
|||||||
|
|
||||||
// Memory SSA mappings
|
// Memory SSA mappings
|
||||||
DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
|
DenseMap<const Value *, MemoryAccess *> ValueToMemoryAccess;
|
||||||
|
|
||||||
// These two mappings contain the main block to access/def mappings for
|
// These two mappings contain the main block to access/def mappings for
|
||||||
// MemorySSA. The list contained in PerBlockAccesses really owns all the
|
// MemorySSA. The list contained in PerBlockAccesses really owns all the
|
||||||
// MemoryAccesses.
|
// MemoryAccesses.
|
||||||
@ -779,8 +789,9 @@ private:
|
|||||||
// Internal MemorySSA utils, for use by MemorySSA classes and walkers
|
// Internal MemorySSA utils, for use by MemorySSA classes and walkers
|
||||||
class MemorySSAUtil {
|
class MemorySSAUtil {
|
||||||
protected:
|
protected:
|
||||||
friend class MemorySSAWalker;
|
|
||||||
friend class GVNHoist;
|
friend class GVNHoist;
|
||||||
|
friend class MemorySSAWalker;
|
||||||
|
|
||||||
// This function should not be used by new passes.
|
// This function should not be used by new passes.
|
||||||
static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
|
static bool defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
|
||||||
AliasAnalysis &AA);
|
AliasAnalysis &AA);
|
||||||
@ -811,6 +822,7 @@ public:
|
|||||||
// unique_ptr<MemorySSA> to avoid build breakage on MSVC.
|
// unique_ptr<MemorySSA> to avoid build breakage on MSVC.
|
||||||
struct Result {
|
struct Result {
|
||||||
Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {}
|
Result(std::unique_ptr<MemorySSA> &&MSSA) : MSSA(std::move(MSSA)) {}
|
||||||
|
|
||||||
MemorySSA &getMSSA() { return *MSSA.get(); }
|
MemorySSA &getMSSA() { return *MSSA.get(); }
|
||||||
|
|
||||||
std::unique_ptr<MemorySSA> MSSA;
|
std::unique_ptr<MemorySSA> MSSA;
|
||||||
@ -978,6 +990,7 @@ public:
|
|||||||
assert(MP && "Tried to get phi arg block when not iterating over a PHI");
|
assert(MP && "Tried to get phi arg block when not iterating over a PHI");
|
||||||
return MP->getIncomingBlock(ArgNo);
|
return MP->getIncomingBlock(ArgNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
typename BaseT::iterator::pointer operator*() const {
|
typename BaseT::iterator::pointer operator*() const {
|
||||||
assert(Access && "Tried to access past the end of our iterator");
|
assert(Access && "Tried to access past the end of our iterator");
|
||||||
// Go to the first argument for phis, and the defining access for everything
|
// Go to the first argument for phis, and the defining access for everything
|
||||||
@ -986,6 +999,7 @@ public:
|
|||||||
return MP->getIncomingValue(ArgNo);
|
return MP->getIncomingValue(ArgNo);
|
||||||
return cast<MemoryUseOrDef>(Access)->getDefiningAccess();
|
return cast<MemoryUseOrDef>(Access)->getDefiningAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
using BaseT::operator++;
|
using BaseT::operator++;
|
||||||
memoryaccess_def_iterator &operator++() {
|
memoryaccess_def_iterator &operator++() {
|
||||||
assert(Access && "Hit end of iterator");
|
assert(Access && "Hit end of iterator");
|
||||||
|
@ -14,13 +14,17 @@
|
|||||||
#ifndef LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
|
#ifndef LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
|
||||||
#define LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
|
#define LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
|
||||||
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/IR/ModuleSummaryIndex.h"
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class BlockFrequencyInfo;
|
class BlockFrequencyInfo;
|
||||||
|
class Function;
|
||||||
|
class Module;
|
||||||
class ProfileSummaryInfo;
|
class ProfileSummaryInfo;
|
||||||
|
|
||||||
/// Direct function to compute a \c ModuleSummaryIndex from a given module.
|
/// Direct function to compute a \c ModuleSummaryIndex from a given module.
|
||||||
@ -38,10 +42,11 @@ ModuleSummaryIndex buildModuleSummaryIndex(
|
|||||||
class ModuleSummaryIndexAnalysis
|
class ModuleSummaryIndexAnalysis
|
||||||
: public AnalysisInfoMixin<ModuleSummaryIndexAnalysis> {
|
: public AnalysisInfoMixin<ModuleSummaryIndexAnalysis> {
|
||||||
friend AnalysisInfoMixin<ModuleSummaryIndexAnalysis>;
|
friend AnalysisInfoMixin<ModuleSummaryIndexAnalysis>;
|
||||||
|
|
||||||
static AnalysisKey Key;
|
static AnalysisKey Key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ModuleSummaryIndex Result;
|
using Result = ModuleSummaryIndex;
|
||||||
|
|
||||||
Result run(Module &M, ModuleAnalysisManager &AM);
|
Result run(Module &M, ModuleAnalysisManager &AM);
|
||||||
};
|
};
|
||||||
@ -70,6 +75,7 @@ public:
|
|||||||
// object for the module, to be written to bitcode or LLVM assembly.
|
// object for the module, to be written to bitcode or LLVM assembly.
|
||||||
//
|
//
|
||||||
ModulePass *createModuleSummaryIndexWrapperPass();
|
ModulePass *createModuleSummaryIndexWrapperPass();
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===//
|
//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation --*- C++ -*-=//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -14,16 +14,20 @@
|
|||||||
#ifndef LLVM_ANALYSIS_POSTDOMINATORS_H
|
#ifndef LLVM_ANALYSIS_POSTDOMINATORS_H
|
||||||
#define LLVM_ANALYSIS_POSTDOMINATORS_H
|
#define LLVM_ANALYSIS_POSTDOMINATORS_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/DepthFirstIterator.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
|
class Function;
|
||||||
|
class raw_ostream;
|
||||||
|
|
||||||
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
|
/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to
|
||||||
/// compute the post-dominator tree.
|
/// compute the post-dominator tree.
|
||||||
///
|
|
||||||
struct PostDominatorTree : public PostDomTreeBase<BasicBlock> {
|
struct PostDominatorTree : public PostDomTreeBase<BasicBlock> {
|
||||||
typedef PostDomTreeBase<BasicBlock> Base;
|
using Base = PostDomTreeBase<BasicBlock>;
|
||||||
|
|
||||||
/// Handle invalidation explicitly.
|
/// Handle invalidation explicitly.
|
||||||
bool invalidate(Function &F, const PreservedAnalyses &PA,
|
bool invalidate(Function &F, const PreservedAnalyses &PA,
|
||||||
@ -34,11 +38,12 @@ struct PostDominatorTree : public PostDomTreeBase<BasicBlock> {
|
|||||||
class PostDominatorTreeAnalysis
|
class PostDominatorTreeAnalysis
|
||||||
: public AnalysisInfoMixin<PostDominatorTreeAnalysis> {
|
: public AnalysisInfoMixin<PostDominatorTreeAnalysis> {
|
||||||
friend AnalysisInfoMixin<PostDominatorTreeAnalysis>;
|
friend AnalysisInfoMixin<PostDominatorTreeAnalysis>;
|
||||||
|
|
||||||
static AnalysisKey Key;
|
static AnalysisKey Key;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// \brief Provide the result typedef for this analysis pass.
|
/// \brief Provide the result type for this analysis pass.
|
||||||
typedef PostDominatorTree Result;
|
using Result = PostDominatorTree;
|
||||||
|
|
||||||
/// \brief Run the analysis pass over a function and produce a post dominator
|
/// \brief Run the analysis pass over a function and produce a post dominator
|
||||||
/// tree.
|
/// tree.
|
||||||
@ -52,11 +57,13 @@ class PostDominatorTreePrinterPass
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PostDominatorTreePrinterPass(raw_ostream &OS);
|
explicit PostDominatorTreePrinterPass(raw_ostream &OS);
|
||||||
|
|
||||||
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PostDominatorTreeWrapperPass : public FunctionPass {
|
struct PostDominatorTreeWrapperPass : public FunctionPass {
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
|
|
||||||
PostDominatorTree DT;
|
PostDominatorTree DT;
|
||||||
|
|
||||||
PostDominatorTreeWrapperPass() : FunctionPass(ID) {
|
PostDominatorTreeWrapperPass() : FunctionPass(ID) {
|
||||||
@ -99,6 +106,6 @@ template <> struct GraphTraits<PostDominatorTree*>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif // LLVM_ANALYSIS_POSTDOMINATORS_H
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===//
|
//===- MemoryBuiltins.cpp - Identify calls to memory builtins -------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
@ -13,20 +13,39 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
|
#include "llvm/ADT/APInt.h"
|
||||||
|
#include "llvm/ADT/None.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Analysis/TargetFolder.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
|
#include "llvm/IR/Argument.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/GlobalAlias.h"
|
||||||
#include "llvm/IR/GlobalVariable.h"
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/Instruction.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/Intrinsics.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/Metadata.h"
|
#include "llvm/IR/Operator.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Transforms/Utils/Local.h"
|
#include "llvm/Transforms/Utils/Local.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "memory-builtins"
|
#define DEBUG_TYPE "memory-builtins"
|
||||||
@ -187,7 +206,6 @@ static bool hasNoAliasAttr(const Value *V, bool LookThroughBitCast) {
|
|||||||
return CS && CS.hasRetAttr(Attribute::NoAlias);
|
return CS && CS.hasRetAttr(Attribute::NoAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Tests if a value is a call or invoke to a library function that
|
/// \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
|
/// allocates or reallocates memory (either malloc, calloc, realloc, or strdup
|
||||||
/// like).
|
/// like).
|
||||||
@ -323,7 +341,6 @@ Value *llvm::getMallocArraySize(CallInst *CI, const DataLayout &DL,
|
|||||||
return computeArraySize(CI, DL, TLI, LookThroughSExt);
|
return computeArraySize(CI, DL, TLI, LookThroughSExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// extractCallocCall - Returns the corresponding CallInst if the instruction
|
/// extractCallocCall - Returns the corresponding CallInst if the instruction
|
||||||
/// is a calloc call.
|
/// is a calloc call.
|
||||||
const CallInst *llvm::extractCallocCall(const Value *I,
|
const CallInst *llvm::extractCallocCall(const Value *I,
|
||||||
@ -331,7 +348,6 @@ const CallInst *llvm::extractCallocCall(const Value *I,
|
|||||||
return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : nullptr;
|
return isCallocLikeFn(I, TLI) ? cast<CallInst>(I) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||||
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
||||||
const CallInst *CI = dyn_cast<CallInst>(I);
|
const CallInst *CI = dyn_cast<CallInst>(I);
|
||||||
@ -387,8 +403,6 @@ const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) {
|
|||||||
return CI;
|
return CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Utility functions to compute size of objects.
|
// Utility functions to compute size of objects.
|
||||||
//
|
//
|
||||||
@ -452,7 +466,6 @@ STATISTIC(ObjectVisitorArgument,
|
|||||||
STATISTIC(ObjectVisitorLoad,
|
STATISTIC(ObjectVisitorLoad,
|
||||||
"Number of load instructions with unsolved size and offset");
|
"Number of load instructions with unsolved size and offset");
|
||||||
|
|
||||||
|
|
||||||
APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
|
APInt ObjectSizeOffsetVisitor::align(APInt Size, uint64_t Align) {
|
||||||
if (Options.RoundToAlign && Align)
|
if (Options.RoundToAlign && Align)
|
||||||
return APInt(IntTyBits, alignTo(Size.getZExtValue(), Align));
|
return APInt(IntTyBits, alignTo(Size.getZExtValue(), Align));
|
||||||
|
@ -15,28 +15,40 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Analysis/AssumptionCache.h"
|
#include "llvm/Analysis/AssumptionCache.h"
|
||||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||||
|
#include "llvm/Analysis/MemoryLocation.h"
|
||||||
#include "llvm/Analysis/OrderedBasicBlock.h"
|
#include "llvm/Analysis/OrderedBasicBlock.h"
|
||||||
#include "llvm/Analysis/PHITransAddr.h"
|
#include "llvm/Analysis/PHITransAddr.h"
|
||||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/InstrTypes.h"
|
||||||
#include "llvm/IR/Instruction.h"
|
#include "llvm/IR/Instruction.h"
|
||||||
#include "llvm/IR/Instructions.h"
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
|
#include "llvm/IR/Metadata.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/PredIteratorCache.h"
|
#include "llvm/IR/PredIteratorCache.h"
|
||||||
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/IR/Use.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
|
#include "llvm/IR/Value.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Support/AtomicOrdering.h"
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
@ -45,7 +57,9 @@
|
|||||||
#include "llvm/Support/MathExtras.h"
|
#include "llvm/Support/MathExtras.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -322,7 +336,6 @@ static bool isVolatile(Instruction *Inst) {
|
|||||||
MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
|
MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
|
||||||
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
|
const MemoryLocation &MemLoc, bool isLoad, BasicBlock::iterator ScanIt,
|
||||||
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
|
BasicBlock *BB, Instruction *QueryInst, unsigned *Limit) {
|
||||||
|
|
||||||
MemDepResult InvariantGroupDependency = MemDepResult::getUnknown();
|
MemDepResult InvariantGroupDependency = MemDepResult::getUnknown();
|
||||||
if (QueryInst != nullptr) {
|
if (QueryInst != nullptr) {
|
||||||
if (auto *LI = dyn_cast<LoadInst>(QueryInst)) {
|
if (auto *LI = dyn_cast<LoadInst>(QueryInst)) {
|
||||||
@ -350,7 +363,6 @@ MemDepResult MemoryDependenceResults::getPointerDependencyFrom(
|
|||||||
MemDepResult
|
MemDepResult
|
||||||
MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
|
MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
|
||||||
BasicBlock *BB) {
|
BasicBlock *BB) {
|
||||||
|
|
||||||
auto *InvariantGroupMD = LI->getMetadata(LLVMContext::MD_invariant_group);
|
auto *InvariantGroupMD = LI->getMetadata(LLVMContext::MD_invariant_group);
|
||||||
if (!InvariantGroupMD)
|
if (!InvariantGroupMD)
|
||||||
return MemDepResult::getUnknown();
|
return MemDepResult::getUnknown();
|
||||||
@ -380,7 +392,6 @@ MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
|
|||||||
return Best;
|
return Best;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// FIXME: This loop is O(N^2) because dominates can be O(n) and in worst case
|
// FIXME: This loop is O(N^2) because dominates can be O(n) and in worst case
|
||||||
// we will see all the instructions. This should be fixed in MSSA.
|
// we will see all the instructions. This should be fixed in MSSA.
|
||||||
while (!LoadOperandsQueue.empty()) {
|
while (!LoadOperandsQueue.empty()) {
|
||||||
@ -541,7 +552,6 @@ MemDepResult MemoryDependenceResults::getSimplePointerDependencyFrom(
|
|||||||
// it does not alias with when this atomic load indicates that another
|
// it does not alias with when this atomic load indicates that another
|
||||||
// thread may be accessing the location.
|
// thread may be accessing the location.
|
||||||
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
|
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
|
||||||
|
|
||||||
// While volatile access cannot be eliminated, they do not have to clobber
|
// While volatile access cannot be eliminated, they do not have to clobber
|
||||||
// non-aliasing locations, as normal accesses, for example, can be safely
|
// non-aliasing locations, as normal accesses, for example, can be safely
|
||||||
// reordered with volatile accesses.
|
// reordered with volatile accesses.
|
||||||
@ -1508,7 +1518,6 @@ void MemoryDependenceResults::removeInstruction(Instruction *RemInst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we have a cached local dependence query for this instruction, remove it.
|
// If we have a cached local dependence query for this instruction, remove it.
|
||||||
//
|
|
||||||
LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst);
|
LocalDepMapType::iterator LocalDepEntry = LocalDeps.find(RemInst);
|
||||||
if (LocalDepEntry != LocalDeps.end()) {
|
if (LocalDepEntry != LocalDeps.end()) {
|
||||||
// Remove us from DepInst's reverse set now that the local dep info is gone.
|
// Remove us from DepInst's reverse set now that the local dep info is gone.
|
||||||
@ -1531,7 +1540,6 @@ void MemoryDependenceResults::removeInstruction(Instruction *RemInst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Loop over all of the things that depend on the instruction we're removing.
|
// Loop over all of the things that depend on the instruction we're removing.
|
||||||
//
|
|
||||||
SmallVector<std::pair<Instruction *, Instruction *>, 8> ReverseDepsToAdd;
|
SmallVector<std::pair<Instruction *, Instruction *>, 8> ReverseDepsToAdd;
|
||||||
|
|
||||||
// If we find RemInst as a clobber or Def in any of the maps for other values,
|
// If we find RemInst as a clobber or Def in any of the maps for other values,
|
||||||
@ -1726,7 +1734,7 @@ MemoryDependenceWrapperPass::MemoryDependenceWrapperPass() : FunctionPass(ID) {
|
|||||||
initializeMemoryDependenceWrapperPassPass(*PassRegistry::getPassRegistry());
|
initializeMemoryDependenceWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryDependenceWrapperPass::~MemoryDependenceWrapperPass() {}
|
MemoryDependenceWrapperPass::~MemoryDependenceWrapperPass() = default;
|
||||||
|
|
||||||
void MemoryDependenceWrapperPass::releaseMemory() {
|
void MemoryDependenceWrapperPass::releaseMemory() {
|
||||||
MemDep.reset();
|
MemDep.reset();
|
||||||
|
@ -1,48 +1,63 @@
|
|||||||
//===-- MemorySSA.cpp - Memory SSA Builder---------------------------===//
|
//===- MemorySSA.cpp - Memory SSA Builder ---------------------------------===//
|
||||||
//
|
//
|
||||||
// The LLVM Compiler Infrastructure
|
// The LLVM Compiler Infrastructure
|
||||||
//
|
//
|
||||||
// This file is distributed under the University of Illinois Open Source
|
// This file is distributed under the University of Illinois Open Source
|
||||||
// License. See LICENSE.TXT for details.
|
// License. See LICENSE.TXT for details.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file implements the MemorySSA class.
|
// This file implements the MemorySSA class.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/MemorySSA.h"
|
#include "llvm/Analysis/MemorySSA.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/DenseMapInfo.h"
|
||||||
#include "llvm/ADT/DenseSet.h"
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/DepthFirstIterator.h"
|
#include "llvm/ADT/DepthFirstIterator.h"
|
||||||
#include "llvm/ADT/GraphTraits.h"
|
#include "llvm/ADT/Hashing.h"
|
||||||
#include "llvm/ADT/PostOrderIterator.h"
|
#include "llvm/ADT/None.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SmallBitVector.h"
|
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/iterator.h"
|
||||||
|
#include "llvm/ADT/iterator_range.h"
|
||||||
#include "llvm/Analysis/AliasAnalysis.h"
|
#include "llvm/Analysis/AliasAnalysis.h"
|
||||||
#include "llvm/Analysis/CFG.h"
|
|
||||||
#include "llvm/Analysis/GlobalsModRef.h"
|
|
||||||
#include "llvm/Analysis/IteratedDominanceFrontier.h"
|
#include "llvm/Analysis/IteratedDominanceFrontier.h"
|
||||||
#include "llvm/Analysis/MemoryLocation.h"
|
#include "llvm/Analysis/MemoryLocation.h"
|
||||||
#include "llvm/Analysis/PHITransAddr.h"
|
|
||||||
#include "llvm/IR/AssemblyAnnotationWriter.h"
|
#include "llvm/IR/AssemblyAnnotationWriter.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/BasicBlock.h"
|
||||||
|
#include "llvm/IR/CallSite.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/GlobalVariable.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/IR/IRBuilder.h"
|
#include "llvm/IR/Instruction.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
|
#include "llvm/IR/Intrinsics.h"
|
||||||
#include "llvm/IR/LLVMContext.h"
|
#include "llvm/IR/LLVMContext.h"
|
||||||
#include "llvm/IR/Metadata.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Use.h"
|
||||||
#include "llvm/IR/PatternMatch.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/AtomicOrdering.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/Support/Compiler.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FormattedStream.h"
|
#include "llvm/Support/FormattedStream.h"
|
||||||
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "memoryssa"
|
#define DEBUG_TYPE "memoryssa"
|
||||||
using namespace llvm;
|
|
||||||
INITIALIZE_PASS_BEGIN(MemorySSAWrapperPass, "memoryssa", "Memory SSA", false,
|
INITIALIZE_PASS_BEGIN(MemorySSAWrapperPass, "memoryssa", "Memory SSA", false,
|
||||||
true)
|
true)
|
||||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||||
@ -66,30 +81,34 @@ static cl::opt<bool>
|
|||||||
cl::desc("Verify MemorySSA in legacy printer pass."));
|
cl::desc("Verify MemorySSA in legacy printer pass."));
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
/// \brief An assembly annotator class to print Memory SSA information in
|
/// \brief An assembly annotator class to print Memory SSA information in
|
||||||
/// comments.
|
/// comments.
|
||||||
class MemorySSAAnnotatedWriter : public AssemblyAnnotationWriter {
|
class MemorySSAAnnotatedWriter : public AssemblyAnnotationWriter {
|
||||||
friend class MemorySSA;
|
friend class MemorySSA;
|
||||||
|
|
||||||
const MemorySSA *MSSA;
|
const MemorySSA *MSSA;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemorySSAAnnotatedWriter(const MemorySSA *M) : MSSA(M) {}
|
MemorySSAAnnotatedWriter(const MemorySSA *M) : MSSA(M) {}
|
||||||
|
|
||||||
virtual void emitBasicBlockStartAnnot(const BasicBlock *BB,
|
void emitBasicBlockStartAnnot(const BasicBlock *BB,
|
||||||
formatted_raw_ostream &OS) {
|
formatted_raw_ostream &OS) override {
|
||||||
if (MemoryAccess *MA = MSSA->getMemoryAccess(BB))
|
if (MemoryAccess *MA = MSSA->getMemoryAccess(BB))
|
||||||
OS << "; " << *MA << "\n";
|
OS << "; " << *MA << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void emitInstructionAnnot(const Instruction *I,
|
void emitInstructionAnnot(const Instruction *I,
|
||||||
formatted_raw_ostream &OS) {
|
formatted_raw_ostream &OS) override {
|
||||||
if (MemoryAccess *MA = MSSA->getMemoryAccess(I))
|
if (MemoryAccess *MA = MSSA->getMemoryAccess(I))
|
||||||
OS << "; " << *MA << "\n";
|
OS << "; " << *MA << "\n";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// Our current alias analysis API differentiates heavily between calls and
|
/// Our current alias analysis API differentiates heavily between calls and
|
||||||
/// non-calls, and functions called on one usually assert on the other.
|
/// non-calls, and functions called on one usually assert on the other.
|
||||||
/// This class encapsulates the distinction to simplify other code that wants
|
/// This class encapsulates the distinction to simplify other code that wants
|
||||||
@ -97,7 +116,9 @@ namespace {
|
|||||||
/// For example, this class is used as a densemap key in the use optimizer.
|
/// For example, this class is used as a densemap key in the use optimizer.
|
||||||
class MemoryLocOrCall {
|
class MemoryLocOrCall {
|
||||||
public:
|
public:
|
||||||
MemoryLocOrCall() : IsCall(false) {}
|
bool IsCall = false;
|
||||||
|
|
||||||
|
MemoryLocOrCall() = default;
|
||||||
MemoryLocOrCall(MemoryUseOrDef *MUD)
|
MemoryLocOrCall(MemoryUseOrDef *MUD)
|
||||||
: MemoryLocOrCall(MUD->getMemoryInst()) {}
|
: MemoryLocOrCall(MUD->getMemoryInst()) {}
|
||||||
MemoryLocOrCall(const MemoryUseOrDef *MUD)
|
MemoryLocOrCall(const MemoryUseOrDef *MUD)
|
||||||
@ -116,14 +137,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit MemoryLocOrCall(const MemoryLocation &Loc)
|
explicit MemoryLocOrCall(const MemoryLocation &Loc) : Loc(Loc) {}
|
||||||
: IsCall(false), Loc(Loc) {}
|
|
||||||
|
|
||||||
bool IsCall;
|
|
||||||
ImmutableCallSite getCS() const {
|
ImmutableCallSite getCS() const {
|
||||||
assert(IsCall);
|
assert(IsCall);
|
||||||
return CS;
|
return CS;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryLocation getLoc() const {
|
MemoryLocation getLoc() const {
|
||||||
assert(!IsCall);
|
assert(!IsCall);
|
||||||
return Loc;
|
return Loc;
|
||||||
@ -144,16 +164,20 @@ private:
|
|||||||
MemoryLocation Loc;
|
MemoryLocation Loc;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
template <> struct DenseMapInfo<MemoryLocOrCall> {
|
template <> struct DenseMapInfo<MemoryLocOrCall> {
|
||||||
static inline MemoryLocOrCall getEmptyKey() {
|
static inline MemoryLocOrCall getEmptyKey() {
|
||||||
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getEmptyKey());
|
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getEmptyKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline MemoryLocOrCall getTombstoneKey() {
|
static inline MemoryLocOrCall getTombstoneKey() {
|
||||||
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getTombstoneKey());
|
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getTombstoneKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned getHashValue(const MemoryLocOrCall &MLOC) {
|
static unsigned getHashValue(const MemoryLocOrCall &MLOC) {
|
||||||
if (MLOC.IsCall)
|
if (MLOC.IsCall)
|
||||||
return hash_combine(MLOC.IsCall,
|
return hash_combine(MLOC.IsCall,
|
||||||
@ -162,6 +186,7 @@ template <> struct DenseMapInfo<MemoryLocOrCall> {
|
|||||||
return hash_combine(
|
return hash_combine(
|
||||||
MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
|
MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
|
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
|
||||||
return LHS == RHS;
|
return LHS == RHS;
|
||||||
}
|
}
|
||||||
@ -169,6 +194,8 @@ template <> struct DenseMapInfo<MemoryLocOrCall> {
|
|||||||
|
|
||||||
enum class Reorderability { Always, IfNoAlias, Never };
|
enum class Reorderability { Always, IfNoAlias, Never };
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
/// This does one-way checks to see if Use could theoretically be hoisted above
|
/// This does one-way checks to see if Use could theoretically be hoisted above
|
||||||
/// MayClobber. This will not check the other way around.
|
/// MayClobber. This will not check the other way around.
|
||||||
///
|
///
|
||||||
@ -271,22 +298,21 @@ bool MemorySSAUtil::defClobbersUseOrDef(MemoryDef *MD, const MemoryUseOrDef *MU,
|
|||||||
AliasAnalysis &AA) {
|
AliasAnalysis &AA) {
|
||||||
return instructionClobbersQuery(MD, MU, MemoryLocOrCall(MU), AA);
|
return instructionClobbersQuery(MD, MU, MemoryLocOrCall(MU), AA);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct UpwardsMemoryQuery {
|
struct UpwardsMemoryQuery {
|
||||||
// True if our original query started off as a call
|
// True if our original query started off as a call
|
||||||
bool IsCall;
|
bool IsCall = false;
|
||||||
// The pointer location we started the query with. This will be empty if
|
// The pointer location we started the query with. This will be empty if
|
||||||
// IsCall is true.
|
// IsCall is true.
|
||||||
MemoryLocation StartingLoc;
|
MemoryLocation StartingLoc;
|
||||||
// This is the instruction we were querying about.
|
// This is the instruction we were querying about.
|
||||||
const Instruction *Inst;
|
const Instruction *Inst = nullptr;
|
||||||
// The MemoryAccess we actually got called with, used to test local domination
|
// The MemoryAccess we actually got called with, used to test local domination
|
||||||
const MemoryAccess *OriginalAccess;
|
const MemoryAccess *OriginalAccess = nullptr;
|
||||||
|
|
||||||
UpwardsMemoryQuery()
|
UpwardsMemoryQuery() = default;
|
||||||
: IsCall(false), Inst(nullptr), OriginalAccess(nullptr) {}
|
|
||||||
|
|
||||||
UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)
|
UpwardsMemoryQuery(const Instruction *Inst, const MemoryAccess *Access)
|
||||||
: IsCall(ImmutableCallSite(Inst)), Inst(Inst), OriginalAccess(Access) {
|
: IsCall(ImmutableCallSite(Inst)), Inst(Inst), OriginalAccess(Access) {
|
||||||
@ -295,6 +321,8 @@ struct UpwardsMemoryQuery {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,
|
static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,
|
||||||
AliasAnalysis &AA) {
|
AliasAnalysis &AA) {
|
||||||
Instruction *Inst = MD->getMemoryInst();
|
Instruction *Inst = MD->getMemoryInst();
|
||||||
@ -394,6 +422,8 @@ checkClobberSanity(MemoryAccess *Start, MemoryAccess *ClobberAt,
|
|||||||
"ClobberAt never acted as a clobber");
|
"ClobberAt never acted as a clobber");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
/// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up
|
/// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up
|
||||||
/// in one class.
|
/// in one class.
|
||||||
class ClobberWalker {
|
class ClobberWalker {
|
||||||
@ -569,7 +599,7 @@ class ClobberWalker {
|
|||||||
struct generic_def_path_iterator
|
struct generic_def_path_iterator
|
||||||
: public iterator_facade_base<generic_def_path_iterator<T, Walker>,
|
: public iterator_facade_base<generic_def_path_iterator<T, Walker>,
|
||||||
std::forward_iterator_tag, T *> {
|
std::forward_iterator_tag, T *> {
|
||||||
generic_def_path_iterator() : W(nullptr), N(None) {}
|
generic_def_path_iterator() = default;
|
||||||
generic_def_path_iterator(Walker *W, ListIndex N) : W(W), N(N) {}
|
generic_def_path_iterator(Walker *W, ListIndex N) : W(W), N(N) {}
|
||||||
|
|
||||||
T &operator*() const { return curNode(); }
|
T &operator*() const { return curNode(); }
|
||||||
@ -588,8 +618,8 @@ class ClobberWalker {
|
|||||||
private:
|
private:
|
||||||
T &curNode() const { return W->Paths[*N]; }
|
T &curNode() const { return W->Paths[*N]; }
|
||||||
|
|
||||||
Walker *W;
|
Walker *W = nullptr;
|
||||||
Optional<ListIndex> N;
|
Optional<ListIndex> N = None;
|
||||||
};
|
};
|
||||||
|
|
||||||
using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
|
using def_path_iterator = generic_def_path_iterator<DefPath, ClobberWalker>;
|
||||||
@ -664,7 +694,7 @@ class ClobberWalker {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MemoryPhi *Current = Phi;
|
MemoryPhi *Current = Phi;
|
||||||
while (1) {
|
while (true) {
|
||||||
assert(!MSSA.isLiveOnEntryDef(Current) &&
|
assert(!MSSA.isLiveOnEntryDef(Current) &&
|
||||||
"liveOnEntry wasn't treated as a clobber?");
|
"liveOnEntry wasn't treated as a clobber?");
|
||||||
|
|
||||||
@ -842,30 +872,34 @@ struct RenamePassData {
|
|||||||
RenamePassData(DomTreeNode *D, DomTreeNode::const_iterator It,
|
RenamePassData(DomTreeNode *D, DomTreeNode::const_iterator It,
|
||||||
MemoryAccess *M)
|
MemoryAccess *M)
|
||||||
: DTN(D), ChildIt(It), IncomingVal(M) {}
|
: DTN(D), ChildIt(It), IncomingVal(M) {}
|
||||||
|
|
||||||
void swap(RenamePassData &RHS) {
|
void swap(RenamePassData &RHS) {
|
||||||
std::swap(DTN, RHS.DTN);
|
std::swap(DTN, RHS.DTN);
|
||||||
std::swap(ChildIt, RHS.ChildIt);
|
std::swap(ChildIt, RHS.ChildIt);
|
||||||
std::swap(IncomingVal, RHS.IncomingVal);
|
std::swap(IncomingVal, RHS.IncomingVal);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // anonymous namespace
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
/// \brief A MemorySSAWalker that does AA walks to disambiguate accesses. It no
|
/// \brief A MemorySSAWalker that does AA walks to disambiguate accesses. It no
|
||||||
/// longer does caching on its own,
|
/// longer does caching on its own,
|
||||||
/// but the name has been retained for the moment.
|
/// but the name has been retained for the moment.
|
||||||
class MemorySSA::CachingWalker final : public MemorySSAWalker {
|
class MemorySSA::CachingWalker final : public MemorySSAWalker {
|
||||||
ClobberWalker Walker;
|
ClobberWalker Walker;
|
||||||
bool AutoResetWalker;
|
bool AutoResetWalker = true;
|
||||||
|
|
||||||
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &);
|
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, UpwardsMemoryQuery &);
|
||||||
void verifyRemoved(MemoryAccess *);
|
void verifyRemoved(MemoryAccess *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CachingWalker(MemorySSA *, AliasAnalysis *, DominatorTree *);
|
CachingWalker(MemorySSA *, AliasAnalysis *, DominatorTree *);
|
||||||
~CachingWalker() override;
|
~CachingWalker() override = default;
|
||||||
|
|
||||||
using MemorySSAWalker::getClobberingMemoryAccess;
|
using MemorySSAWalker::getClobberingMemoryAccess;
|
||||||
|
|
||||||
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
|
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) override;
|
||||||
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
|
MemoryAccess *getClobberingMemoryAccess(MemoryAccess *,
|
||||||
const MemoryLocation &) override;
|
const MemoryLocation &) override;
|
||||||
@ -884,6 +918,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
void MemorySSA::renameSuccessorPhis(BasicBlock *BB, MemoryAccess *IncomingVal,
|
void MemorySSA::renameSuccessorPhis(BasicBlock *BB, MemoryAccess *IncomingVal,
|
||||||
bool RenameAllUses) {
|
bool RenameAllUses) {
|
||||||
// Pass through values to our successors
|
// Pass through values to our successors
|
||||||
@ -1032,17 +1068,20 @@ MemorySSA::AccessList *MemorySSA::getOrCreateAccessList(const BasicBlock *BB) {
|
|||||||
auto Res = PerBlockAccesses.insert(std::make_pair(BB, nullptr));
|
auto Res = PerBlockAccesses.insert(std::make_pair(BB, nullptr));
|
||||||
|
|
||||||
if (Res.second)
|
if (Res.second)
|
||||||
Res.first->second = make_unique<AccessList>();
|
Res.first->second = llvm::make_unique<AccessList>();
|
||||||
return Res.first->second.get();
|
return Res.first->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemorySSA::DefsList *MemorySSA::getOrCreateDefsList(const BasicBlock *BB) {
|
MemorySSA::DefsList *MemorySSA::getOrCreateDefsList(const BasicBlock *BB) {
|
||||||
auto Res = PerBlockDefs.insert(std::make_pair(BB, nullptr));
|
auto Res = PerBlockDefs.insert(std::make_pair(BB, nullptr));
|
||||||
|
|
||||||
if (Res.second)
|
if (Res.second)
|
||||||
Res.first->second = make_unique<DefsList>();
|
Res.first->second = llvm::make_unique<DefsList>();
|
||||||
return Res.first->second.get();
|
return Res.first->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
/// This class is a batch walker of all MemoryUse's in the program, and points
|
/// This class is a batch walker of all MemoryUse's in the program, and points
|
||||||
/// their defining access at the thing that actually clobbers them. Because it
|
/// their defining access at the thing that actually clobbers them. Because it
|
||||||
/// is a batch walker that touches everything, it does not operate like the
|
/// is a batch walker that touches everything, it does not operate like the
|
||||||
@ -1077,15 +1116,19 @@ private:
|
|||||||
unsigned long LastKill;
|
unsigned long LastKill;
|
||||||
bool LastKillValid;
|
bool LastKillValid;
|
||||||
};
|
};
|
||||||
|
|
||||||
void optimizeUsesInBlock(const BasicBlock *, unsigned long &, unsigned long &,
|
void optimizeUsesInBlock(const BasicBlock *, unsigned long &, unsigned long &,
|
||||||
SmallVectorImpl<MemoryAccess *> &,
|
SmallVectorImpl<MemoryAccess *> &,
|
||||||
DenseMap<MemoryLocOrCall, MemlocStackInfo> &);
|
DenseMap<MemoryLocOrCall, MemlocStackInfo> &);
|
||||||
|
|
||||||
MemorySSA *MSSA;
|
MemorySSA *MSSA;
|
||||||
MemorySSAWalker *Walker;
|
MemorySSAWalker *Walker;
|
||||||
AliasAnalysis *AA;
|
AliasAnalysis *AA;
|
||||||
DominatorTree *DT;
|
DominatorTree *DT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
/// Optimize the uses in a given block This is basically the SSA renaming
|
/// Optimize the uses in a given block This is basically the SSA renaming
|
||||||
/// algorithm, with one caveat: We are able to use a single stack for all
|
/// algorithm, with one caveat: We are able to use a single stack for all
|
||||||
/// MemoryUses. This is because the set of *possible* reaching MemoryDefs is
|
/// MemoryUses. This is because the set of *possible* reaching MemoryDefs is
|
||||||
@ -1281,8 +1324,9 @@ void MemorySSA::buildMemorySSA() {
|
|||||||
// semantics do *not* imply that something with no immediate uses can simply
|
// semantics do *not* imply that something with no immediate uses can simply
|
||||||
// be removed.
|
// be removed.
|
||||||
BasicBlock &StartingPoint = F.getEntryBlock();
|
BasicBlock &StartingPoint = F.getEntryBlock();
|
||||||
LiveOnEntryDef = make_unique<MemoryDef>(F.getContext(), nullptr, nullptr,
|
LiveOnEntryDef =
|
||||||
&StartingPoint, NextID++);
|
llvm::make_unique<MemoryDef>(F.getContext(), nullptr, nullptr,
|
||||||
|
&StartingPoint, NextID++);
|
||||||
DenseMap<const BasicBlock *, unsigned int> BBNumbers;
|
DenseMap<const BasicBlock *, unsigned int> BBNumbers;
|
||||||
unsigned NextBBNum = 0;
|
unsigned NextBBNum = 0;
|
||||||
|
|
||||||
@ -1343,7 +1387,7 @@ MemorySSA::CachingWalker *MemorySSA::getWalkerImpl() {
|
|||||||
if (Walker)
|
if (Walker)
|
||||||
return Walker.get();
|
return Walker.get();
|
||||||
|
|
||||||
Walker = make_unique<CachingWalker>(this, AA, DT);
|
Walker = llvm::make_unique<CachingWalker>(this, AA, DT);
|
||||||
return Walker.get();
|
return Walker.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1462,6 +1506,7 @@ static inline bool isOrdered(const Instruction *I) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Helper function to create new memory accesses
|
/// \brief Helper function to create new memory accesses
|
||||||
MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) {
|
MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I) {
|
||||||
// The assume intrinsic has a control dependency which we model by claiming
|
// The assume intrinsic has a control dependency which we model by claiming
|
||||||
@ -1675,7 +1720,6 @@ void MemorySSA::verifyDomination(Function &F) const {
|
|||||||
|
|
||||||
/// \brief Verify the def-use lists in MemorySSA, by verifying that \p Use
|
/// \brief Verify the def-use lists in MemorySSA, by verifying that \p Use
|
||||||
/// appears in the use list of \p Def.
|
/// appears in the use list of \p Def.
|
||||||
|
|
||||||
void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const {
|
void MemorySSA::verifyUseInDefs(MemoryAccess *Def, MemoryAccess *Use) const {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// The live on entry use may cause us to get a NULL def here
|
// The live on entry use may cause us to get a NULL def here
|
||||||
@ -1739,7 +1783,6 @@ void MemorySSA::renumberBlock(const BasicBlock *B) const {
|
|||||||
/// \returns True if \p Dominator dominates \p Dominatee.
|
/// \returns True if \p Dominator dominates \p Dominatee.
|
||||||
bool MemorySSA::locallyDominates(const MemoryAccess *Dominator,
|
bool MemorySSA::locallyDominates(const MemoryAccess *Dominator,
|
||||||
const MemoryAccess *Dominatee) const {
|
const MemoryAccess *Dominatee) const {
|
||||||
|
|
||||||
const BasicBlock *DominatorBlock = Dominator->getBlock();
|
const BasicBlock *DominatorBlock = Dominator->getBlock();
|
||||||
|
|
||||||
assert((DominatorBlock == Dominatee->getBlock()) &&
|
assert((DominatorBlock == Dominatee->getBlock()) &&
|
||||||
@ -1887,7 +1930,7 @@ MemorySSAAnalysis::Result MemorySSAAnalysis::run(Function &F,
|
|||||||
FunctionAnalysisManager &AM) {
|
FunctionAnalysisManager &AM) {
|
||||||
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
|
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
|
||||||
auto &AA = AM.getResult<AAManager>(F);
|
auto &AA = AM.getResult<AAManager>(F);
|
||||||
return MemorySSAAnalysis::Result(make_unique<MemorySSA>(F, &AA, &DT));
|
return MemorySSAAnalysis::Result(llvm::make_unique<MemorySSA>(F, &AA, &DT));
|
||||||
}
|
}
|
||||||
|
|
||||||
PreservedAnalyses MemorySSAPrinterPass::run(Function &F,
|
PreservedAnalyses MemorySSAPrinterPass::run(Function &F,
|
||||||
@ -1936,9 +1979,7 @@ MemorySSAWalker::MemorySSAWalker(MemorySSA *M) : MSSA(M) {}
|
|||||||
|
|
||||||
MemorySSA::CachingWalker::CachingWalker(MemorySSA *M, AliasAnalysis *A,
|
MemorySSA::CachingWalker::CachingWalker(MemorySSA *M, AliasAnalysis *A,
|
||||||
DominatorTree *D)
|
DominatorTree *D)
|
||||||
: MemorySSAWalker(M), Walker(*M, *A, *D), AutoResetWalker(true) {}
|
: MemorySSAWalker(M), Walker(*M, *A, *D) {}
|
||||||
|
|
||||||
MemorySSA::CachingWalker::~CachingWalker() {}
|
|
||||||
|
|
||||||
void MemorySSA::CachingWalker::invalidateInfo(MemoryAccess *MA) {
|
void MemorySSA::CachingWalker::invalidateInfo(MemoryAccess *MA) {
|
||||||
if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA))
|
if (auto *MUD = dyn_cast<MemoryUseOrDef>(MA))
|
||||||
@ -2059,7 +2100,6 @@ MemoryAccess *DoNothingMemorySSAWalker::getClobberingMemoryAccess(
|
|||||||
return Use->getDefiningAccess();
|
return Use->getDefiningAccess();
|
||||||
return StartingAccess;
|
return StartingAccess;
|
||||||
}
|
}
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
void MemoryPhi::deleteMe(DerivedUser *Self) {
|
void MemoryPhi::deleteMe(DerivedUser *Self) {
|
||||||
delete static_cast<MemoryPhi *>(Self);
|
delete static_cast<MemoryPhi *>(Self);
|
||||||
|
@ -13,23 +13,47 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
|
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include "llvm/ADT/MapVector.h"
|
#include "llvm/ADT/MapVector.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/SetVector.h"
|
#include "llvm/ADT/SetVector.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
||||||
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
|
|
||||||
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
||||||
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
|
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
|
||||||
#include "llvm/Analysis/LoopInfo.h"
|
#include "llvm/Analysis/LoopInfo.h"
|
||||||
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
#include "llvm/Analysis/ProfileSummaryInfo.h"
|
||||||
#include "llvm/Analysis/TypeMetadataUtils.h"
|
#include "llvm/Analysis/TypeMetadataUtils.h"
|
||||||
|
#include "llvm/IR/Attributes.h"
|
||||||
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/CallSite.h"
|
#include "llvm/IR/CallSite.h"
|
||||||
|
#include "llvm/IR/Constant.h"
|
||||||
|
#include "llvm/IR/Constants.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/InstIterator.h"
|
#include "llvm/IR/Function.h"
|
||||||
|
#include "llvm/IR/GlobalAlias.h"
|
||||||
|
#include "llvm/IR/GlobalValue.h"
|
||||||
|
#include "llvm/IR/GlobalVariable.h"
|
||||||
|
#include "llvm/IR/Instructions.h"
|
||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/ValueSymbolTable.h"
|
#include "llvm/IR/Intrinsics.h"
|
||||||
|
#include "llvm/IR/Metadata.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
||||||
|
#include "llvm/IR/Use.h"
|
||||||
|
#include "llvm/IR/User.h"
|
||||||
#include "llvm/Object/ModuleSymbolTable.h"
|
#include "llvm/Object/ModuleSymbolTable.h"
|
||||||
|
#include "llvm/Object/SymbolicFile.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/Support/Casting.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "module-summary-analysis"
|
#define DEBUG_TYPE "module-summary-analysis"
|
||||||
@ -514,6 +538,7 @@ ModuleSummaryIndexAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char ModuleSummaryIndexWrapperPass::ID = 0;
|
char ModuleSummaryIndexWrapperPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
|
INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
|
||||||
"Module Summary Analysis", false, true)
|
"Module Summary Analysis", false, true)
|
||||||
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
|
||||||
|
@ -12,13 +12,11 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Analysis/PostDominators.h"
|
#include "llvm/Analysis/PostDominators.h"
|
||||||
#include "llvm/ADT/DepthFirstIterator.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/ADT/SetOperations.h"
|
|
||||||
#include "llvm/IR/CFG.h"
|
|
||||||
#include "llvm/IR/Instructions.h"
|
|
||||||
#include "llvm/IR/PassManager.h"
|
#include "llvm/IR/PassManager.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Support/GenericDomTreeConstruction.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
#define DEBUG_TYPE "postdomtree"
|
#define DEBUG_TYPE "postdomtree"
|
||||||
@ -30,6 +28,7 @@ template class llvm::DominatorTreeBase<BasicBlock, true>; // PostDomTreeBase
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
char PostDominatorTreeWrapperPass::ID = 0;
|
char PostDominatorTreeWrapperPass::ID = 0;
|
||||||
|
|
||||||
INITIALIZE_PASS(PostDominatorTreeWrapperPass, "postdomtree",
|
INITIALIZE_PASS(PostDominatorTreeWrapperPass, "postdomtree",
|
||||||
"Post-Dominator Tree Construction", true, true)
|
"Post-Dominator Tree Construction", true, true)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user