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