-//===- llvm/Analysis/MemoryBuiltins.h- Calls to memory builtins -*- C++ -*-===//
+//==- llvm/Analysis/MemoryBuiltins.h - Calls to memory builtins --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
#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
return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI));
}
-
//===----------------------------------------------------------------------===//
// Utility functions to compute size of objects.
//
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;
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;
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) {
SizeOffsetEvalType visitInstruction(Instruction &I);
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ANALYSIS_MEMORYBUILTINS_H
-//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- C++ -*-===//
+//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
#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 {
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.
/// 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 {
/// 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
///
/// 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.
class MemoryDependenceAnalysis
: public AnalysisInfoMixin<MemoryDependenceAnalysis> {
friend AnalysisInfoMixin<MemoryDependenceAnalysis>;
+
static AnalysisKey Key;
public:
- typedef MemoryDependenceResults Result;
+ using Result = MemoryDependenceResults;
MemoryDependenceResults run(Function &F, FunctionAnalysisManager &AM);
};
/// 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;
MemoryDependenceResults &getMemDep() { return *MemDep; }
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H
// 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.
/// 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
#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"
#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>
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
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) {
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
}
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.
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);
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); }
MemoryAccess *getOptimized() const {
return getDefiningAccess();
}
+
void resetOptimized() {
OptimizedID = INVALID_MEMORYACCESS_ID;
}
private:
static void deleteMe(DerivedUser *Self);
- unsigned int OptimizedID;
+ unsigned int OptimizedID = 0;
};
template <>
/// 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); }
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 <>
// 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);
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; }
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 {
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 *,
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>>;
// 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.
// 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);
// 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;
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
return MP->getIncomingValue(ArgNo);
return cast<MemoryUseOrDef>(Access)->getDefiningAccess();
}
+
using BaseT::operator++;
memoryaccess_def_iterator &operator++() {
assert(Access && "Hit end of iterator");
#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.
class ModuleSummaryIndexAnalysis
: public AnalysisInfoMixin<ModuleSummaryIndexAnalysis> {
friend AnalysisInfoMixin<ModuleSummaryIndexAnalysis>;
+
static AnalysisKey Key;
public:
- typedef ModuleSummaryIndex Result;
+ using Result = ModuleSummaryIndex;
Result run(Module &M, ModuleAnalysisManager &AM);
};
// object for the module, to be written to bitcode or LLVM assembly.
//
ModulePass *createModuleSummaryIndexWrapperPass();
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_ANALYSIS_MODULESUMMARYANALYSIS_H
-//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===//
+//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation --*- C++ -*-=//
//
// The LLVM Compiler Infrastructure
//
#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,
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.
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) {
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ANALYSIS_POSTDOMINATORS_H
-//===------ MemoryBuiltins.cpp - Identify calls to memory builtins --------===//
+//===- MemoryBuiltins.cpp - Identify calls to memory builtins -------------===//
//
// The LLVM Compiler Infrastructure
//
//===----------------------------------------------------------------------===//
#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"
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).
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,
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);
return CI;
}
-
-
//===----------------------------------------------------------------------===//
// Utility functions to compute size of objects.
//
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));
//===----------------------------------------------------------------------===//
#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"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
+#include <cstdint>
#include <iterator>
+#include <utility>
using namespace llvm;
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)) {
MemDepResult
MemoryDependenceResults::getInvariantGroupPointerDependency(LoadInst *LI,
BasicBlock *BB) {
-
auto *InvariantGroupMD = LI->getMetadata(LLVMContext::MD_invariant_group);
if (!InvariantGroupMD)
return MemDepResult::getUnknown();
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()) {
// 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.
}
// 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.
}
// 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,
initializeMemoryDependenceWrapperPassPass(*PassRegistry::getPassRegistry());
}
-MemoryDependenceWrapperPass::~MemoryDependenceWrapperPass() {}
+MemoryDependenceWrapperPass::~MemoryDependenceWrapperPass() = default;
void MemoryDependenceWrapperPass::releaseMemory() {
MemDep.reset();
-//===-- 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>
-#define DEBUG_TYPE "memoryssa"
using namespace llvm;
+
+#define DEBUG_TYPE "memoryssa"
+
INITIALIZE_PASS_BEGIN(MemorySSAWrapperPass, "memoryssa", "Memory SSA", false,
true)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
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
/// 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)
}
}
- 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;
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,
return hash_combine(
MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
}
+
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
return LHS == RHS;
}
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.
///
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) {
}
};
+} // end anonymous namespace
+
static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc,
AliasAnalysis &AA) {
Instruction *Inst = MD->getMemoryInst();
"ClobberAt never acted as a clobber");
}
+namespace {
+
/// Our algorithm for walking (and trying to optimize) clobbers, all wrapped up
/// in one class.
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(); }
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>;
};
MemoryPhi *Current = Phi;
- while (1) {
+ while (true) {
assert(!MSSA.isLiveOnEntryDef(Current) &&
"liveOnEntry wasn't treated as a clobber?");
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;
}
};
+} // end namespace llvm
+
void MemorySSA::renameSuccessorPhis(BasicBlock *BB, MemoryAccess *IncomingVal,
bool RenameAllUses) {
// Pass through values to our successors
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
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
// 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;
if (Walker)
return Walker.get();
- Walker = make_unique<CachingWalker>(this, AA, DT);
+ Walker = llvm::make_unique<CachingWalker>(this, AA, DT);
return Walker.get();
}
}
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
/// \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
/// \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()) &&
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,
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))
return Use->getDefiningAccess();
return StartingAccess;
}
-} // namespace llvm
void MemoryPhi::deleteMe(DerivedUser *Self) {
delete static_cast<MemoryPhi *>(Self);
//===----------------------------------------------------------------------===//
#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"
}
char ModuleSummaryIndexWrapperPass::ID = 0;
+
INITIALIZE_PASS_BEGIN(ModuleSummaryIndexWrapperPass, "module-summary-analysis",
"Module Summary Analysis", false, true)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
//===----------------------------------------------------------------------===//
#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"
//===----------------------------------------------------------------------===//
char PostDominatorTreeWrapperPass::ID = 0;
+
INITIALIZE_PASS(PostDominatorTreeWrapperPass, "postdomtree",
"Post-Dominator Tree Construction", true, true)