diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:37:50 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-14 15:37:50 +0000 |
commit | 581a6d8501ff5614297da837b81ed3b6956361ea (patch) | |
tree | 985ee91d0ca1d3e6506ac5ff7e37f5b67adfec09 /include/llvm | |
parent | 909545a822eef491158f831688066f0ec2866938 (diff) |
Notes
Diffstat (limited to 'include/llvm')
71 files changed, 1710 insertions, 747 deletions
diff --git a/include/llvm/ADT/PointerSumType.h b/include/llvm/ADT/PointerSumType.h index 005b1c645c935..062544eedf84b 100644 --- a/include/llvm/ADT/PointerSumType.h +++ b/include/llvm/ADT/PointerSumType.h @@ -94,7 +94,7 @@ public: return HelperT::template Lookup<N>::TraitsT::getFromVoidPointer(getImpl()); } - operator bool() const { return Value & HelperT::PointerMask; } + explicit operator bool() const { return Value & HelperT::PointerMask; } bool operator==(const PointerSumType &R) const { return Value == R.Value; } bool operator!=(const PointerSumType &R) const { return Value != R.Value; } bool operator<(const PointerSumType &R) const { return Value < R.Value; } diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 9ccacc10db0d5..6470e09db86cc 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -33,6 +33,32 @@ namespace llvm { /// Another abstraction that this doesn't provide is implementing increment in /// terms of addition of one. These aren't equivalent for all iterator /// categories, and respecting that adds a lot of complexity for little gain. +/// +/// Classes wishing to use `iterator_facade_base` should implement the following +/// methods: +/// +/// Forward Iterators: +/// (All of the following methods) +/// - DerivedT &operator=(const DerivedT &R); +/// - bool operator==(const DerivedT &R) const; +/// - const T &operator*() const; +/// - T &operator*(); +/// - DerivedT &operator++(); +/// +/// Bidirectional Iterators: +/// (All methods of forward iterators, plus the following) +/// - DerivedT &operator--(); +/// +/// Random-access Iterators: +/// (All methods of bidirectional iterators excluding the following) +/// - DerivedT &operator++(); +/// - DerivedT &operator--(); +/// (and plus the following) +/// - bool operator<(const DerivedT &RHS) const; +/// - DifferenceTypeT operator-(const DerivedT &R) const; +/// - DerivedT &operator+=(DifferenceTypeT N); +/// - DerivedT &operator-=(DifferenceTypeT N); +/// template <typename DerivedT, typename IteratorCategoryT, typename T, typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, typename ReferenceT = T &> diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index 406a1fe9f5608..b50545a0484be 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -46,6 +46,30 @@ class AssumptionCache { /// intrinsic. SmallVector<WeakVH, 4> AssumeHandles; + class AffectedValueCallbackVH final : public CallbackVH { + AssumptionCache *AC; + void deleted() override; + void allUsesReplacedWith(Value *) override; + + public: + using DMI = DenseMapInfo<Value *>; + + AffectedValueCallbackVH(Value *V, AssumptionCache *AC = nullptr) + : CallbackVH(V), AC(AC) {} + }; + + friend AffectedValueCallbackVH; + + /// \brief A map of values about which an assumption might be providing + /// information to the relevant set of assumptions. + using AffectedValuesMap = + DenseMap<AffectedValueCallbackVH, SmallVector<WeakVH, 1>, + AffectedValueCallbackVH::DMI>; + AffectedValuesMap AffectedValues; + + /// Get the vector of assumptions which affect a value from the cache. + SmallVector<WeakVH, 1> &getAffectedValues(Value *V); + /// \brief Flag tracking whether we have scanned the function yet. /// /// We want to be as lazy about this as possible, and so we scan the function @@ -66,11 +90,16 @@ public: /// not already be in the cache. void registerAssumption(CallInst *CI); + /// \brief Update the cache of values being affected by this assumption (i.e. + /// the values about which this assumption provides information). + void updateAffectedValues(CallInst *CI); + /// \brief Clear the cache of @llvm.assume intrinsics for a function. /// /// It will be re-scanned the next time it is requested. void clear() { AssumeHandles.clear(); + AffectedValues.clear(); Scanned = false; } @@ -87,6 +116,18 @@ public: scanFunction(); return AssumeHandles; } + + /// \brief Access the list of assumptions which affect this value. + MutableArrayRef<WeakVH> assumptionsFor(const Value *V) { + if (!Scanned) + scanFunction(); + + auto AVI = AffectedValues.find_as(const_cast<Value *>(V)); + if (AVI == AffectedValues.end()) + return MutableArrayRef<WeakVH>(); + + return AVI->second; + } }; /// \brief A function analysis which provides an \c AssumptionCache. diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index e1a5467d8b633..bb572dd5603b4 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -15,8 +15,8 @@ #ifndef LLVM_ANALYSIS_IVUSERS_H #define LLVM_ANALYSIS_IVUSERS_H +#include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" #include "llvm/IR/ValueHandle.h" @@ -193,17 +193,10 @@ class IVUsersAnalysis : public AnalysisInfoMixin<IVUsersAnalysis> { public: typedef IVUsers Result; - IVUsers run(Loop &L, LoopAnalysisManager &AM); + IVUsers run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR); }; -/// Printer pass for the \c IVUsers for a loop. -class IVUsersPrinterPass : public PassInfoMixin<IVUsersPrinterPass> { - raw_ostream &OS; - -public: - explicit IVUsersPrinterPass(raw_ostream &OS) : OS(OS) {} - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); -}; } #endif diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 566e526f89b37..bca0aebe2eefa 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -148,7 +148,7 @@ public: /// /// This happens when an edge has been deleted. We leave the edge objects /// around but clear them. - operator bool() const; + explicit operator bool() const; /// Returnss the \c Kind of the edge. Kind getKind() const; diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 76066f6003e7e..901b193c7e2d4 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -20,7 +20,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" -#include "llvm/Analysis/LoopPassManager.h" +#include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/ValueHandle.h" @@ -753,18 +753,8 @@ class LoopAccessAnalysis public: typedef LoopAccessInfo Result; - Result run(Loop &, LoopAnalysisManager &); - static StringRef name() { return "LoopAccessAnalysis"; } -}; - -/// \brief Printer pass for the \c LoopAccessInfo results. -class LoopAccessInfoPrinterPass - : public PassInfoMixin<LoopAccessInfoPrinterPass> { - raw_ostream &OS; -public: - explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {} - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR); }; inline Instruction *MemoryDepChecker::Dependence::getSource( diff --git a/include/llvm/Analysis/LoopAnalysisManager.h b/include/llvm/Analysis/LoopAnalysisManager.h new file mode 100644 index 0000000000000..17da516889b00 --- /dev/null +++ b/include/llvm/Analysis/LoopAnalysisManager.h @@ -0,0 +1,155 @@ +//===- LoopAnalysisManager.h - Loop analysis management ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides classes for managing per-loop analyses. These are +/// typically used as part of a loop pass pipeline over the loop nests of +/// a function. +/// +/// Loop analyses are allowed to make some simplifying assumptions: +/// 1) Loops are, where possible, in simplified form. +/// 2) Loops are *always* in LCSSA form. +/// 3) A collection of analysis results are available: +/// - LoopInfo +/// - DominatorTree +/// - ScalarEvolution +/// - AAManager +/// +/// The primary mechanism to provide these invariants is the loop pass manager, +/// but they can also be manually provided in order to reason about a loop from +/// outside of a dedicated pass manager. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPANALYSISMANAGER_H +#define LLVM_ANALYSIS_LOOPANALYSISMANAGER_H + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/PriorityWorklist.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// The adaptor from a function pass to a loop pass computes these analyses and +/// makes them available to the loop passes "for free". Each loop pass is +/// expected expected to update these analyses if necessary to ensure they're +/// valid after it runs. +struct LoopStandardAnalysisResults { + AAResults &AA; + AssumptionCache &AC; + DominatorTree &DT; + LoopInfo &LI; + ScalarEvolution &SE; + TargetLibraryInfo &TLI; + TargetTransformInfo &TTI; +}; + +/// Extern template declaration for the analysis set for this IR unit. +extern template class AllAnalysesOn<Loop>; + +extern template class AnalysisManager<Loop, LoopStandardAnalysisResults &>; +/// \brief The loop analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This typedef serves as a convenient way to refer to this +/// construct in the adaptors and proxies used to integrate this into the larger +/// pass manager infrastructure. +typedef AnalysisManager<Loop, LoopStandardAnalysisResults &> + LoopAnalysisManager; + +/// A proxy from a \c LoopAnalysisManager to a \c Function. +typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function> + LoopAnalysisManagerFunctionProxy; + +/// A specialized result for the \c LoopAnalysisManagerFunctionProxy which +/// retains a \c LoopInfo reference. +/// +/// This allows it to collect loop objects for which analysis results may be +/// cached in the \c LoopAnalysisManager. +template <> class LoopAnalysisManagerFunctionProxy::Result { +public: + explicit Result(LoopAnalysisManager &InnerAM, LoopInfo &LI) + : InnerAM(&InnerAM), LI(&LI) {} + Result(Result &&Arg) : InnerAM(std::move(Arg.InnerAM)), LI(Arg.LI) { + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + Arg.InnerAM = nullptr; + } + Result &operator=(Result &&RHS) { + InnerAM = RHS.InnerAM; + LI = RHS.LI; + // We have to null out the analysis manager in the moved-from state + // because we are taking ownership of the responsibilty to clear the + // analysis state. + RHS.InnerAM = nullptr; + return *this; + } + ~Result() { + // InnerAM is cleared in a moved from state where there is nothing to do. + if (!InnerAM) + return; + + // Clear out the analysis manager if we're being destroyed -- it means we + // didn't even see an invalidate call when we got invalidated. + InnerAM->clear(); + } + + /// Accessor for the analysis manager. + LoopAnalysisManager &getManager() { return *InnerAM; } + + /// Handler for invalidation of the proxy for a particular function. + /// + /// If the proxy, \c LoopInfo, and associated analyses are preserved, this + /// will merely forward the invalidation event to any cached loop analysis + /// results for loops within this function. + /// + /// If the necessary loop infrastructure is not preserved, this will forcibly + /// clear all of the cached analysis results that are keyed on the \c + /// LoopInfo for this function. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + +private: + LoopAnalysisManager *InnerAM; + LoopInfo *LI; +}; + +/// Provide a specialized run method for the \c LoopAnalysisManagerFunctionProxy +/// so it can pass the \c LoopInfo to the result. +template <> +LoopAnalysisManagerFunctionProxy::Result +LoopAnalysisManagerFunctionProxy::run(Function &F, FunctionAnalysisManager &AM); + +// Ensure the \c LoopAnalysisManagerFunctionProxy is provided as an extern +// template. +extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; + +extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop, + LoopStandardAnalysisResults &>; +/// A proxy from a \c FunctionAnalysisManager to a \c Loop. +typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop, + LoopStandardAnalysisResults &> + FunctionAnalysisManagerLoopProxy; + +/// Returns the minimum set of Analyses that all loop passes must preserve. +PreservedAnalyses getLoopPassPreservedAnalyses(); +} + +#endif // LLVM_ANALYSIS_LOOPANALYSISMANAGER_H diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 0c99c6297c1e6..20e6af2727fe0 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -853,17 +853,8 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; }; -/// \brief Pass for printing a loop's contents as LLVM's text IR assembly. -class PrintLoopPass : public PassInfoMixin<PrintLoopPass> { - raw_ostream &OS; - std::string Banner; - -public: - PrintLoopPass(); - PrintLoopPass(raw_ostream &OS, const std::string &Banner = ""); - - PreservedAnalyses run(Loop &L, AnalysisManager<Loop> &); -}; +/// Function to print a loop's contents as LLVM's text IR assembly. +void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner = ""); } // End llvm namespace diff --git a/include/llvm/Analysis/LoopPassManager.h b/include/llvm/Analysis/LoopPassManager.h deleted file mode 100644 index ae9c16502feb5..0000000000000 --- a/include/llvm/Analysis/LoopPassManager.h +++ /dev/null @@ -1,149 +0,0 @@ -//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This header provides classes for managing passes over loops in LLVM IR. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_LOOPPASSMANAGER_H -#define LLVM_ANALYSIS_LOOPPASSMANAGER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/PassManager.h" - -namespace llvm { - -extern template class PassManager<Loop>; -/// \brief The loop pass manager. -/// -/// See the documentation for the PassManager template for details. It runs a -/// sequency of loop passes over each loop that the manager is run over. This -/// typedef serves as a convenient way to refer to this construct. -typedef PassManager<Loop> LoopPassManager; - -extern template class AnalysisManager<Loop>; -/// \brief The loop analysis manager. -/// -/// See the documentation for the AnalysisManager template for detail -/// documentation. This typedef serves as a convenient way to refer to this -/// construct in the adaptors and proxies used to integrate this into the larger -/// pass manager infrastructure. -typedef AnalysisManager<Loop> LoopAnalysisManager; - -/// A proxy from a \c LoopAnalysisManager to a \c Function. -typedef InnerAnalysisManagerProxy<LoopAnalysisManager, Function> - LoopAnalysisManagerFunctionProxy; - -/// Specialization of the invalidate method for the \c -/// LoopAnalysisManagerFunctionProxy's result. -template <> -bool LoopAnalysisManagerFunctionProxy::Result::invalidate( - Function &F, const PreservedAnalyses &PA, - FunctionAnalysisManager::Invalidator &Inv); - -// Ensure the \c LoopAnalysisManagerFunctionProxy is provided as an extern -// template. -extern template class InnerAnalysisManagerProxy<LoopAnalysisManager, Function>; - -extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop>; -/// A proxy from a \c FunctionAnalysisManager to a \c Loop. -typedef OuterAnalysisManagerProxy<FunctionAnalysisManager, Loop> - FunctionAnalysisManagerLoopProxy; - -/// Returns the minimum set of Analyses that all loop passes must preserve. -PreservedAnalyses getLoopPassPreservedAnalyses(); - -/// \brief Adaptor that maps from a function to its loops. -/// -/// Designed to allow composition of a LoopPass(Manager) and a -/// FunctionPassManager. Note that if this pass is constructed with a \c -/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy -/// analysis prior to running the loop passes over the function to enable a \c -/// LoopAnalysisManager to be used within this run safely. -template <typename LoopPassT> -class FunctionToLoopPassAdaptor - : public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> { -public: - explicit FunctionToLoopPassAdaptor(LoopPassT Pass) - : Pass(std::move(Pass)) {} - - /// \brief Runs the loop passes across every loop in the function. - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { - // Setup the loop analysis manager from its proxy. - LoopAnalysisManager &LAM = - AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager(); - // Get the loop structure for this function - LoopInfo &LI = AM.getResult<LoopAnalysis>(F); - - // Also precompute all of the function analyses used by loop passes. - // FIXME: These should be handed into the loop passes when the loop pass - // management layer is reworked to follow the design of CGSCC. - (void)AM.getResult<AAManager>(F); - (void)AM.getResult<DominatorTreeAnalysis>(F); - (void)AM.getResult<ScalarEvolutionAnalysis>(F); - (void)AM.getResult<TargetLibraryAnalysis>(F); - - PreservedAnalyses PA = PreservedAnalyses::all(); - - // We want to visit the loops in reverse post-order. We'll build the stack - // of loops to visit in Loops by first walking the loops in pre-order. - SmallVector<Loop *, 2> Loops; - SmallVector<Loop *, 2> WorkList(LI.begin(), LI.end()); - while (!WorkList.empty()) { - Loop *L = WorkList.pop_back_val(); - WorkList.insert(WorkList.end(), L->begin(), L->end()); - Loops.push_back(L); - } - - // Now pop each element off of the stack to visit the loops in reverse - // post-order. - for (auto *L : reverse(Loops)) { - PreservedAnalyses PassPA = Pass.run(*L, LAM); - // FIXME: We should verify the set of analyses relevant to Loop passes - // are preserved. - - // We know that the loop pass couldn't have invalidated any other loop's - // analyses (that's the contract of a loop pass), so directly handle the - // loop analysis manager's invalidation here. - LAM.invalidate(*L, PassPA); - - // Then intersect the preserved set so that invalidation of module - // analyses will eventually occur when the module pass completes. - PA.intersect(std::move(PassPA)); - } - - // By definition we preserve the proxy. We also preserve all analyses on - // Loops. This precludes *any* invalidation of loop analyses by the proxy, - // but that's OK because we've taken care to invalidate analyses in the - // loop analysis manager incrementally above. - PA.preserveSet<AllAnalysesOn<Loop>>(); - PA.preserve<LoopAnalysisManagerFunctionProxy>(); - return PA; - } - -private: - LoopPassT Pass; -}; - -/// \brief A function to deduce a loop pass type and wrap it in the templated -/// adaptor. -template <typename LoopPassT> -FunctionToLoopPassAdaptor<LoopPassT> -createFunctionToLoopPassAdaptor(LoopPassT Pass) { - return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass)); -} -} - -#endif // LLVM_ANALYSIS_LOOPPASSMANAGER_H diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 33dbd22f7a20f..a401887016c94 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -302,6 +302,10 @@ private: NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {} }; + /// 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. /// @@ -441,9 +445,9 @@ public: /// This analysis looks for other loads and stores with invariant.group /// metadata and the same pointer operand. Returns Unknown if it does not /// find anything, and Def if it can be assumed that 2 instructions load or - /// store the same value. - /// FIXME: This analysis works only on single block because of restrictions - /// at the call site. + /// store the same value and NonLocal which indicate that non-local Def was + /// found, which can be retrieved by calling getNonLocalPointerDependency + /// with the same queried instruction. MemDepResult getInvariantGroupPointerDependency(LoadInst *LI, BasicBlock *BB); /// Looks at a memory location for a load (specified by MemLocBase, Offs, and diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index b4a6c5c2fae09..209f05c279d03 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -55,6 +55,11 @@ struct MemIntrinsicInfo { // Same Id is set by the target for corresponding load/store intrinsics. unsigned short MatchingId; int NumMemRefs; + + /// This is the pointer that the intrinsic is loading from or storing to. + /// If this is non-null, then analysis/optimization passes can assume that + /// this intrinsic is functionally equivalent to a load/store from this + /// pointer. Value *PtrVal; }; @@ -518,11 +523,15 @@ public: unsigned getMaxInterleaveFactor(unsigned VF) const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. + /// \p Args is an optional argument which holds the instruction operands + /// values so the TTI can analyize those values searching for special + /// cases\optimizations based on those values. int getArithmeticInstrCost( unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, OperandValueProperties Opd1PropInfo = OP_None, - OperandValueProperties Opd2PropInfo = OP_None) const; + OperandValueProperties Opd2PropInfo = OP_None, + ArrayRef<const Value *> Args = ArrayRef<const Value *>()) const; /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and @@ -763,7 +772,8 @@ public: getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, OperandValueKind Opd2Info, OperandValueProperties Opd1PropInfo, - OperandValueProperties Opd2PropInfo) = 0; + OperandValueProperties Opd2PropInfo, + ArrayRef<const Value *> Args) = 0; virtual int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, Type *SubTp) = 0; virtual int getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0; @@ -984,9 +994,10 @@ public: getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, OperandValueKind Opd2Info, OperandValueProperties Opd1PropInfo, - OperandValueProperties Opd2PropInfo) override { + OperandValueProperties Opd2PropInfo, + ArrayRef<const Value *> Args) override { return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, - Opd1PropInfo, Opd2PropInfo); + Opd1PropInfo, Opd2PropInfo, Args); } int getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, Type *SubTp) override { diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 1d7edbaf7df04..cafc40723c9d6 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -306,7 +306,8 @@ public: TTI::OperandValueKind Opd1Info, TTI::OperandValueKind Opd2Info, TTI::OperandValueProperties Opd1PropInfo, - TTI::OperandValueProperties Opd2PropInfo) { + TTI::OperandValueProperties Opd2PropInfo, + ArrayRef<const Value *> Args) { return 1; } @@ -427,6 +428,63 @@ public: return VF; } protected: + // Obtain the minimum required size to hold the value (without the sign) + // In case of a vector it returns the min required size for one element. + unsigned minRequiredElementSize(const Value* Val, bool &isSigned) { + if (isa<ConstantDataVector>(Val) || isa<ConstantVector>(Val)) { + const auto* VectorValue = cast<Constant>(Val); + + // In case of a vector need to pick the max between the min + // required size for each element + auto *VT = cast<VectorType>(Val->getType()); + + // Assume unsigned elements + isSigned = false; + + // The max required size is the total vector width divided by num + // of elements in the vector + unsigned MaxRequiredSize = VT->getBitWidth() / VT->getNumElements(); + + unsigned MinRequiredSize = 0; + for(unsigned i = 0, e = VT->getNumElements(); i < e; ++i) { + if (auto* IntElement = + dyn_cast<ConstantInt>(VectorValue->getAggregateElement(i))) { + bool signedElement = IntElement->getValue().isNegative(); + // Get the element min required size. + unsigned ElementMinRequiredSize = + IntElement->getValue().getMinSignedBits() - 1; + // In case one element is signed then all the vector is signed. + isSigned |= signedElement; + // Save the max required bit size between all the elements. + MinRequiredSize = std::max(MinRequiredSize, ElementMinRequiredSize); + } + else { + // not an int constant element + return MaxRequiredSize; + } + } + return MinRequiredSize; + } + + if (const auto* CI = dyn_cast<ConstantInt>(Val)) { + isSigned = CI->getValue().isNegative(); + return CI->getValue().getMinSignedBits() - 1; + } + + if (const auto* Cast = dyn_cast<SExtInst>(Val)) { + isSigned = true; + return Cast->getSrcTy()->getScalarSizeInBits() - 1; + } + + if (const auto* Cast = dyn_cast<ZExtInst>(Val)) { + isSigned = false; + return Cast->getSrcTy()->getScalarSizeInBits(); + } + + isSigned = false; + return Val->getType()->getScalarSizeInBits(); + } + bool isStridedAccess(const SCEV *Ptr) { return Ptr && isa<SCEVAddRecExpr>(Ptr); } diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index dd767217345af..aaf6f888e06f5 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -169,8 +169,12 @@ template <typename T> class ArrayRef; /// Return true if we can prove that the specified FP value is either a NaN or /// never less than 0.0. - bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI, - unsigned Depth = 0); + /// If \p IncludeNeg0 is false, -0.0 is considered less than 0.0. + bool CannotBeOrderedLessThanZero(const Value *V, const TargetLibraryInfo *TLI); + + /// \returns true if we can prove that the specified FP value has a 0 sign + /// bit. + bool SignBitMustBeZero(const Value *V, const TargetLibraryInfo *TLI); /// If the specified value can be set by repeating the same byte in memory, /// return the i8 value that it is represented with. This is true for all i8 diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index 8e96336b981f1..7efdbcccdef56 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -308,7 +308,8 @@ public: TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, - TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) { + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, + ArrayRef<const Value *> Args = ArrayRef<const Value *>()) { // Check if any of the operands are vector operands. const TargetLoweringBase *TLI = getTLI(); int ISD = TLI->InstructionOpcodeToISD(Opcode); diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index 09c3bf6a1b56c..95c4b4248bbd0 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -52,13 +52,20 @@ class DIEAbbrevData { /// Dwarf form code. dwarf::Form Form; + /// Dwarf attribute value for DW_FORM_implicit_const + int64_t Value; + public: - DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) + : Attribute(A), Form(F), Value(0) {} + DIEAbbrevData(dwarf::Attribute A, int64_t V) + : Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {} /// Accessors. /// @{ dwarf::Attribute getAttribute() const { return Attribute; } dwarf::Form getForm() const { return Form; } + int64_t getValue() const { return Value; } /// @} /// Used to gather unique data for the abbreviation folding set. @@ -102,6 +109,11 @@ public: Data.push_back(DIEAbbrevData(Attribute, Form)); } + /// Adds attribute with DW_FORM_implicit_const value + void AddImplicitConstAttribute(dwarf::Attribute Attribute, int64_t Value) { + Data.push_back(DIEAbbrevData(Attribute, Value)); + } + /// Used to gather unique data for the abbreviation folding set. void Profile(FoldingSetNodeID &ID) const; diff --git a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index 106fc9ffb8b5e..b331533cd7fb0 100644 --- a/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -76,6 +76,7 @@ class MachineBlockFrequencyInfo; class MachineRegisterInfo; class TargetPassConfig; class TargetRegisterInfo; +class raw_ostream; /// This pass implements the reg bank selector pass used in the GlobalISel /// pipeline. At the end of this pass, all register operands have been assigned @@ -450,6 +451,18 @@ private: bool operator>(const MappingCost &Cost) const { return *this != Cost && Cost < *this; } + + /// Print this on dbgs() stream. + void dump() const; + + /// Print this on \p OS; + void print(raw_ostream &OS) const; + + /// Overload the stream operator for easy debug printing. + friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) { + Cost.print(OS); + return OS; + } }; /// Interface to the target lowering info related @@ -626,6 +639,7 @@ public: /// \endcode bool runOnMachineFunction(MachineFunction &MF) override; }; + } // End namespace llvm. #endif diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/include/llvm/CodeGen/GlobalISel/RegisterBank.h index 075677d30179a..b05bf99482438 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -41,11 +41,8 @@ private: friend RegisterBankInfo; public: - /// The default constructor will leave the object in - /// an invalid state. I.e. isValid() == false. - /// The fields must be updated to fix that and only - /// RegisterBankInfo instances are allowed to do that - RegisterBank(); + RegisterBank(unsigned ID, const char *Name, unsigned Size, + const uint32_t *ContainedRegClasses); /// Get the identifier of this register bank. unsigned getID() const { return ID; } diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 4d4a226eb2d2b..312dc9314d45a 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -384,10 +384,6 @@ protected: /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks /// RegisterBank instances. - /// - /// \note For the verify method to succeed all the \p NumRegBanks - /// must be initialized by createRegisterBank and updated with - /// addRegBankCoverage RegisterBank. RegisterBankInfo(RegisterBank **RegBanks, unsigned NumRegBanks); /// This constructor is meaningless. @@ -400,31 +396,6 @@ protected: llvm_unreachable("This constructor should not be executed"); } - /// Create a new register bank with the given parameter and add it - /// to RegBanks. - /// \pre \p ID must not already be used. - /// \pre \p ID < NumRegBanks. - void createRegisterBank(unsigned ID, const char *Name); - - /// Add \p RCId to the set of register class that the register bank, - /// identified \p ID, covers. - /// This method transitively adds all the sub classes and the subreg-classes - /// of \p RCId to the set of covered register classes. - /// It also adjusts the size of the register bank to reflect the maximal - /// size of a value that can be hold into that register bank. - /// - /// \note This method does *not* add the super classes of \p RCId. - /// The rationale is if \p ID covers the registers of \p RCId, that - /// does not necessarily mean that \p ID covers the set of registers - /// of RCId's superclasses. - /// This method does *not* add the superreg classes as well for consistents. - /// The expected use is to add the coverage top-down with respect to the - /// register hierarchy. - /// - /// \todo TableGen should just generate the BitSet vector for us. - void addRegBankCoverage(unsigned ID, unsigned RCId, - const TargetRegisterInfo &TRI); - /// Get the register bank identified by \p ID. RegisterBank &getRegBank(unsigned ID) { assert(ID < getNumRegBanks() && "Accessing an unknown register bank"); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 420b03ec02bdc..df700bf0c53d9 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -503,19 +503,6 @@ namespace ISD { /// address spaces. ADDRSPACECAST, - /// CONVERT_RNDSAT - This operator is used to support various conversions - /// between various types (float, signed, unsigned and vectors of those - /// types) with rounding and saturation. NOTE: Avoid using this operator as - /// most target don't support it and the operator might be removed in the - /// future. It takes the following arguments: - /// 0) value - /// 1) dest type (type to convert to) - /// 2) src type (type to convert from) - /// 3) rounding imm - /// 4) saturation imm - /// 5) ISD::CvtCode indicating the type of conversion to do - CONVERT_RNDSAT, - /// FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions /// and truncation for half-precision (16 bit) floating numbers. These nodes /// form a semi-softened interface for dealing with f16 (as an i16), which @@ -927,21 +914,6 @@ namespace ISD { /// SETCC_INVALID if it is not possible to represent the resultant comparison. CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger); - //===--------------------------------------------------------------------===// - /// This enum defines the various converts CONVERT_RNDSAT supports. - enum CvtCode { - CVT_FF, /// Float from Float - CVT_FS, /// Float from Signed - CVT_FU, /// Float from Unsigned - CVT_SF, /// Signed from Float - CVT_UF, /// Unsigned from Float - CVT_SS, /// Signed from Signed - CVT_SU, /// Signed from Unsigned - CVT_US, /// Unsigned from Signed - CVT_UU, /// Unsigned from Unsigned - CVT_INVALID /// Marker - Invalid opcode - }; - } // end llvm::ISD namespace } // end llvm namespace diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 7927982e782d1..54d0436e4ab83 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -626,12 +626,6 @@ public: SDValue getCondCode(ISD::CondCode Cond); - /// Returns the ConvertRndSat Note: Avoid using this node because it may - /// disappear in the future and most targets don't support it. - SDValue getConvertRndSat(EVT VT, const SDLoc &dl, SDValue Val, SDValue DTy, - SDValue STy, SDValue Rnd, SDValue Sat, - ISD::CvtCode Code); - /// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT, /// which must be a vector type, must match the number of mask elements /// NumElts. An integer mask element equal to -1 is treated as undefined. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index d4b7170eac3c5..b6f5424dbbd73 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1860,26 +1860,6 @@ public: } }; -/// NOTE: avoid using this node as this may disappear in the -/// future and most targets don't support it. -class CvtRndSatSDNode : public SDNode { - ISD::CvtCode CvtCode; - - friend class SelectionDAG; - - explicit CvtRndSatSDNode(EVT VT, unsigned Order, const DebugLoc &dl, - ISD::CvtCode Code) - : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT)), CvtCode(Code) { - } - -public: - ISD::CvtCode getCvtCode() const { return CvtCode; } - - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::CONVERT_RNDSAT; - } -}; - /// This class is used to represent EVT's, which are used /// to parameterize some operations. class VTSDNode : public SDNode { @@ -2041,7 +2021,7 @@ public: friend class SelectionDAG; MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, - bool isTrunc, bool isCompressing, EVT MemVT, + bool isTrunc, bool isCompressing, EVT MemVT, MachineMemOperand *MMO) : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, MemVT, MMO) { StoreSDNodeBits.IsTruncating = isTrunc; @@ -2054,8 +2034,8 @@ public: bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } /// Returns true if the op does a compression to the vector before storing. - /// The node contiguously stores the active elements (integers or floats) - /// in src (those with their respective bit set in writemask k) to unaligned + /// The node contiguously stores the active elements (integers or floats) + /// in src (those with their respective bit set in writemask k) to unaligned /// memory at base_addr. bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; } diff --git a/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/include/llvm/DebugInfo/CodeView/CVTypeDumper.h new file mode 100644 index 0000000000000..e1dd6a10b5a16 --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/CVTypeDumper.h @@ -0,0 +1,56 @@ +//===-- CVTypeDumper.h - CodeView type info dumper --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H +#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/ScopedPrinter.h" + +namespace llvm { + +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class CVTypeDumper { +public: + explicit CVTypeDumper(TypeDatabase &TypeDB) : TypeDB(TypeDB) {} + + /// Dumps one type record. Returns false if there was a type parsing error, + /// and true otherwise. This should be called in order, since the dumper + /// maintains state about previous records which are necessary for cross + /// type references. + Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper); + + /// Dumps the type records in Types. Returns false if there was a type stream + /// parse error, and true otherwise. + Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper); + + /// Dumps the type records in Data. Returns false if there was a type stream + /// parse error, and true otherwise. Use this method instead of the + /// CVTypeArray overload when type records are laid out contiguously in + /// memory. + Error dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper); + + static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, + TypeIndex TI, TypeDatabase &DB); + +private: + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/include/llvm/DebugInfo/CodeView/SymbolDumper.h index eb63f7895a1e5..a5419b37e7761 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -20,15 +20,15 @@ namespace llvm { class ScopedPrinter; namespace codeview { -class CVTypeDumper; +class TypeDatabase; /// Dumper for CodeView symbol streams found in COFF object files and PDB files. class CVSymbolDumper { public: - CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD, + CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB, std::unique_ptr<SymbolDumpDelegate> ObjDelegate, bool PrintRecordBytes) - : W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)), + : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -43,7 +43,7 @@ public: private: ScopedPrinter &W; - CVTypeDumper &CVTD; + TypeDatabase &TypeDB; std::unique_ptr<SymbolDumpDelegate> ObjDelegate; bool PrintRecordBytes; diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/include/llvm/DebugInfo/CodeView/TypeDatabase.h new file mode 100644 index 0000000000000..cccc2868ffb5f --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/TypeDatabase.h @@ -0,0 +1,55 @@ +//===- TypeDatabase.h - A collection of CodeView type records ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/StringSaver.h" + +namespace llvm { +namespace codeview { +class TypeDatabase { +public: + TypeDatabase() : TypeNameStorage(Allocator) {} + + /// Gets the type index for the next type record. + TypeIndex getNextTypeIndex() const; + + /// Records the name of a type, and reserves its type index. + void recordType(StringRef Name, CVType Data); + + /// Saves the name in a StringSet and creates a stable StringRef. + StringRef saveTypeName(StringRef TypeName); + + StringRef getTypeName(TypeIndex Index) const; + + bool containsTypeIndex(TypeIndex Index) const; + + uint32_t size() const; + +private: + BumpPtrAllocator Allocator; + + /// All user defined type records in .debug$T live in here. Type indices + /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to + /// index into this vector. + SmallVector<StringRef, 10> CVUDTNames; + SmallVector<CVType, 10> TypeRecords; + + StringSaver TypeNameStorage; +}; +} +} + +#endif
\ No newline at end of file diff --git a/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h new file mode 100644 index 0000000000000..39d234cf9814d --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h @@ -0,0 +1,53 @@ +//===-- TypeDatabaseVisitor.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H + +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class TypeDatabaseVisitor : public TypeVisitorCallbacks { +public: + explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(TypeDB) {} + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + bool IsInFieldList = false; + + /// Name of the current type. Only valid before visitTypeEnd. + StringRef Name; + + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h new file mode 100644 index 0000000000000..a466e42981582 --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -0,0 +1,67 @@ +//===-- TypeDumpVisitor.h - CodeView type info dumper -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPVISITOR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +namespace llvm { +class ScopedPrinter; + +namespace codeview { + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class TypeDumpVisitor : public TypeVisitorCallbacks { +public: + TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes) + : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {} + + void printTypeIndex(StringRef FieldName, TypeIndex TI) const; + + /// Action to take on unknown types. By default, they are ignored. + Error visitUnknownType(CVType &Record) override; + Error visitUnknownMember(CVMemberRecord &Record) override; + + /// Paired begin/end actions for all types. Receives all record data, + /// including the fixed-length record prefix. + Error visitTypeBegin(CVType &Record) override; + Error visitTypeEnd(CVType &Record) override; + Error visitMemberBegin(CVMemberRecord &Record) override; + Error visitMemberEnd(CVMemberRecord &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define MEMBER_RECORD(EnumName, EnumVal, Name) \ + Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#include "TypeRecords.def" + +private: + void printMemberAttributes(MemberAttributes Attrs); + void printMemberAttributes(MemberAccess Access, MethodKind Kind, + MethodOptions Options); + + ScopedPrinter *W; + + bool PrintRecordBytes = false; + + TypeDatabase &TypeDB; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/CodeView/TypeDumper.h b/include/llvm/DebugInfo/CodeView/TypeDumper.h deleted file mode 100644 index 5a8b555cec02b..0000000000000 --- a/include/llvm/DebugInfo/CodeView/TypeDumper.h +++ /dev/null @@ -1,108 +0,0 @@ -//===-- TypeDumper.h - CodeView type info dumper ----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" - -namespace llvm { -class ScopedPrinter; - -namespace codeview { - -/// Dumper for CodeView type streams found in COFF object files and PDB files. -class CVTypeDumper : public TypeVisitorCallbacks { -public: - CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes) - : W(W), PrintRecordBytes(PrintRecordBytes) {} - - StringRef getTypeName(TypeIndex TI); - void printTypeIndex(StringRef FieldName, TypeIndex TI); - - /// Dumps one type record. Returns false if there was a type parsing error, - /// and true otherwise. This should be called in order, since the dumper - /// maintains state about previous records which are necessary for cross - /// type references. - Error dump(const CVRecord<TypeLeafKind> &Record); - - /// Dumps the type records in Types. Returns false if there was a type stream - /// parse error, and true otherwise. - Error dump(const CVTypeArray &Types); - - /// Dumps the type records in Data. Returns false if there was a type stream - /// parse error, and true otherwise. Use this method instead of the - /// CVTypeArray overload when type records are laid out contiguously in - /// memory. - Error dump(ArrayRef<uint8_t> Data); - - /// Gets the type index for the next type record. - unsigned getNextTypeIndex() const { - return 0x1000 + CVUDTNames.size(); - } - - /// Records the name of a type, and reserves its type index. - void recordType(StringRef Name) { CVUDTNames.push_back(Name); } - - /// Saves the name in a StringSet and creates a stable StringRef. - StringRef saveName(StringRef TypeName) { - return TypeNames.insert(TypeName).first->getKey(); - } - - void setPrinter(ScopedPrinter *P); - ScopedPrinter *getPrinter() { return W; } - - /// Action to take on unknown types. By default, they are ignored. - Error visitUnknownType(CVType &Record) override; - Error visitUnknownMember(CVMemberRecord &Record) override; - - /// Paired begin/end actions for all types. Receives all record data, - /// including the fixed-length record prefix. - Error visitTypeBegin(CVType &Record) override; - Error visitTypeEnd(CVType &Record) override; - Error visitMemberBegin(CVMemberRecord &Record) override; - Error visitMemberEnd(CVMemberRecord &Record) override; - -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override; -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "TypeRecords.def" - -private: - void printMemberAttributes(MemberAttributes Attrs); - void printMemberAttributes(MemberAccess Access, MethodKind Kind, - MethodOptions Options); - - ScopedPrinter *W; - - bool IsInFieldList = false; - bool PrintRecordBytes = false; - - /// Name of the current type. Only valid before visitTypeEnd. - StringRef Name; - - /// All user defined type records in .debug$T live in here. Type indices - /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to - /// index into this vector. - SmallVector<StringRef, 10> CVUDTNames; - - StringSet<> TypeNames; -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/include/llvm/DebugInfo/CodeView/TypeDumperBase.h b/include/llvm/DebugInfo/CodeView/TypeDumperBase.h new file mode 100644 index 0000000000000..e69de29bb2d1d --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/TypeDumperBase.h diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h index 778817f57bf57..db9bd506be897 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h +++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h @@ -23,21 +23,32 @@ class raw_ostream; class DWARFAbbreviationDeclaration { public: struct AttributeSpec { - AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> S) - : Attr(A), Form(F), ByteSize(S) {} + AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V) + : Attr(A), Form(F), ByteSizeOrValue(V) {} dwarf::Attribute Attr; dwarf::Form Form; - /// If ByteSize has a value, then it contains the fixed size in bytes for - /// the Form in this object. If ByteSize doesn't have a value, then the - /// byte size of Form either varies according to the DWARFUnit that it is - /// contained in or the value size varies and must be decoded from the - /// debug information in order to determine its size. - Optional<uint8_t> ByteSize; + /// The following field is used for ByteSize for non-implicit_const + /// attributes and as value for implicit_const ones, indicated by + /// Form == DW_FORM_implicit_const. + /// The following cases are distinguished: + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue has a value: + /// ByteSizeOrValue contains the fixed size in bytes + /// for the Form in this object. + /// * Form != DW_FORM_implicit_const and ByteSizeOrValue is None: + /// byte size of Form either varies according to the DWARFUnit + /// that it is contained in or the value size varies and must be + /// decoded from the debug information in order to determine its size. + /// * Form == DW_FORM_implicit_const: + /// ByteSizeOrValue contains value for the implicit_const attribute. + Optional<int64_t> ByteSizeOrValue; + bool isImplicitConst() const { + return Form == dwarf::DW_FORM_implicit_const; + } /// Get the fixed byte size of this Form if possible. This function might /// use the DWARFUnit to calculate the size of the Form, like for /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for /// the ByteSize member. - Optional<uint8_t> getByteSize(const DWARFUnit &U) const; + Optional<int64_t> getByteSize(const DWARFUnit &U) const; }; typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index 5a24b7c872995..e335e28b39d73 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -147,21 +147,6 @@ public: /// DW_AT_abstract_origin referenced DIEs. /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the address value of the attribute or FailValue if the - /// attribute doesn't exist or if the attribute's form isn't a form that - /// describes an address. - uint64_t getAttributeValueAsAddress(dwarf::Attribute Attr, - uint64_t FailValue) const; - - /// Extract the specified attribute from this DIE as an address. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. /// \returns an optional value for the attribute. Optional<uint64_t> getAttributeValueAsAddress(dwarf::Attribute Attr) const; @@ -172,21 +157,6 @@ public: /// DW_AT_abstract_origin referenced DIEs. /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the signed integer constant value of the attribute or FailValue - /// if the attribute doesn't exist or if the attribute's form isn't a form - /// that describes a signed integer. - int64_t getAttributeValueAsSignedConstant(dwarf::Attribute Attr, - int64_t FailValue) const; - - /// Extract the specified attribute from this DIE as a signed integer. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. /// \returns an optional value for the attribute. Optional<int64_t> getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const; @@ -198,21 +168,6 @@ public: /// DW_AT_abstract_origin referenced DIEs. /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the unsigned integer constant value of the attribute or FailValue - /// if the attribute doesn't exist or if the attribute's form isn't a form - /// that describes an unsigned integer. - uint64_t getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr, - uint64_t FailValue) const; - - /// Extract the specified attribute from this DIE as an unsigned integer. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. /// \returns an optional value for the attribute. Optional<uint64_t> getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const; @@ -224,21 +179,6 @@ public: /// DW_AT_abstract_origin referenced DIEs. /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the unsigned integer constant value of the attribute or FailValue - /// if the attribute doesn't exist or if the attribute's form isn't a form - /// that describes a reference. - uint64_t getAttributeValueAsReference(dwarf::Attribute Attr, - uint64_t FailValue) const; - - /// Extract the specified attribute from this DIE as absolute DIE Offset. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. /// \returns an optional value for the attribute. Optional<uint64_t> getAttributeValueAsReference(dwarf::Attribute Attr) const; @@ -249,20 +189,6 @@ public: /// DW_AT_abstract_origin referenced DIEs. /// /// \param Attr the attribute to extract. - /// \param FailValue the value to return if this DIE doesn't have this - /// attribute. - /// \returns the unsigned integer constant value of the attribute or FailValue - /// if the attribute doesn't exist or if the attribute's form isn't a form - /// that describes a section offset. - uint64_t getAttributeValueAsSectionOffset(dwarf::Attribute Attr, - uint64_t FailValue) const; - /// Extract the specified attribute from this DIE as absolute section offset. - /// - /// Extract an attribute value from this DIE only. This call doesn't look - /// for the attribute value in any DW_AT_specification or - /// DW_AT_abstract_origin referenced DIEs. - /// - /// \param Attr the attribute to extract. /// \returns an optional value for the attribute. Optional<uint64_t> getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 920880cea10ca..1b7659dfb04ac 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -57,6 +57,9 @@ public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F), U(nullptr) {} dwarf::Form getForm() const { return Form; } void setForm(dwarf::Form F) { Form = F; } + void setUValue(uint64_t V) { Value.uval = V; } + void setSValue(int64_t V) { Value.sval = V; } + void setPValue(const char *V) { Value.cstr = V; } bool isFormClass(FormClass FC) const; const DWARFUnit *getUnit() const { return U; } void dump(raw_ostream &OS) const; diff --git a/include/llvm/DebugInfo/MSF/StreamArray.h b/include/llvm/DebugInfo/MSF/StreamArray.h index 3bba80d807f3f..5dfeb8c524af3 100644 --- a/include/llvm/DebugInfo/MSF/StreamArray.h +++ b/include/llvm/DebugInfo/MSF/StreamArray.h @@ -153,30 +153,24 @@ public: return ThisValue; } - IterType &operator+=(std::ptrdiff_t N) { - while (N > 0) { - // We are done with the current record, discard it so that we are - // positioned at the next record. - IterRef = IterRef.drop_front(ThisLen); - if (IterRef.getLength() == 0) { - // There is nothing after the current record, we must make this an end - // iterator. + IterType &operator++() { + // We are done with the current record, discard it so that we are + // positioned at the next record. + IterRef = IterRef.drop_front(ThisLen); + if (IterRef.getLength() == 0) { + // There is nothing after the current record, we must make this an end + // iterator. + moveToEnd(); + } else { + // There is some data after the current record. + auto EC = Extract(IterRef, ThisLen, ThisValue); + if (EC) { + consumeError(std::move(EC)); + markError(); + } else if (ThisLen == 0) { + // An empty record? Make this an end iterator. moveToEnd(); - return *this; - } else { - // There is some data after the current record. - auto EC = Extract(IterRef, ThisLen, ThisValue); - if (EC) { - consumeError(std::move(EC)); - markError(); - return *this; - } else if (ThisLen == 0) { - // An empty record? Make this an end iterator. - moveToEnd(); - return *this; - } } - --N; } return *this; } diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 932ae51b39dc5..48cb7fe5df6f3 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -17,7 +17,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" @@ -51,6 +53,10 @@ namespace llvm { SmallVector<Metadata *, 4> AllSubprograms; SmallVector<Metadata *, 4> AllGVs; SmallVector<TrackingMDNodeRef, 4> AllImportedModules; + /// Map Macro parent (which can be DIMacroFile or nullptr) to a list of + /// Metadata all of type DIMacroNode. + /// DIMacroNode's with nullptr parent are DICompileUnit direct children. + MapVector<MDNode *, SetVector<Metadata *>> AllMacrosPerParent; /// Track nodes that may be unresolved. SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes; @@ -116,6 +122,24 @@ namespace llvm { DIFile::ChecksumKind CSKind = DIFile::CSK_None, StringRef Checksum = StringRef()); + /// Create debugging information entry for a macro. + /// \param Parent Macro parent (could be nullptr). + /// \param Line Source line number where the macro is defined. + /// \param MacroType DW_MACINFO_define or DW_MACINFO_undef. + /// \param Name Macro name. + /// \param Value Macro value. + DIMacro *createMacro(DIMacroFile *Parent, unsigned Line, unsigned MacroType, + StringRef Name, StringRef Value = StringRef()); + + /// Create debugging information temporary entry for a macro file. + /// List of macro node direct children will be calculated by DIBuilder, + /// using the \p Parent relationship. + /// \param Parent Macro file parent (could be nullptr). + /// \param Line Source line number where the macro file is included. + /// \param File File descriptor containing the name of the macro file. + DIMacroFile *createTempMacroFile(DIMacroFile *Parent, unsigned Line, + DIFile *File); + /// Create a single enumerator value. DIEnumerator *createEnumerator(StringRef Name, int64_t Val); @@ -447,6 +471,9 @@ namespace llvm { /// Get a DINodeArray, create one if required. DINodeArray getOrCreateArray(ArrayRef<Metadata *> Elements); + /// Get a DIMacroNodeArray, create one if required. + DIMacroNodeArray getOrCreateMacroArray(ArrayRef<Metadata *> Elements); + /// Get a DITypeRefArray, create one if required. DITypeRefArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements); diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 26f4626ead10e..187855225c505 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -1295,16 +1295,12 @@ public: /// Check \c this can be discriminated from \c RHS in a linetable entry. /// Scope and inlined-at chains are not recorded in the linetable, so they /// cannot be used to distinguish basic blocks. - /// - /// The current implementation is weaker than it should be, since it just - /// checks filename and line. - /// - /// FIXME: Add a check for getDiscriminator(). - /// FIXME: Add a check for getColumn(). - /// FIXME: Change the getFilename() check to getFile() (or add one for - /// getDirectory()). bool canDiscriminate(const DILocation &RHS) const { - return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + return getLine() != RHS.getLine() || + getColumn() != RHS.getColumn() || + getDiscriminator() != RHS.getDiscriminator() || + getFilename() != RHS.getFilename() || + getDirectory() != RHS.getDirectory(); } /// Get the DWARF discriminator. @@ -1327,10 +1323,13 @@ public: /// represented in a single line entry. In this case, no location /// should be set. /// - /// Currently this function is simply a stub, and no location will be - /// used for all cases. - static DILocation *getMergedLocation(const DILocation *LocA, - const DILocation *LocB) { + /// Currently the function does not create a new location. If the locations + /// are the same, or cannot be discriminated, the first location is returned. + /// Otherwise an empty location will be used. + static const DILocation *getMergedLocation(const DILocation *LocA, + const DILocation *LocB) { + if (LocA && LocB && (LocA == LocB || !LocA->canDiscriminate(*LocB))) + return LocA; return nullptr; } diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 11eb713a4e1d9..1057f564aab3b 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -37,11 +37,11 @@ protected: setGlobalValueSubClassData(0); } - std::string Section; // Section to emit this into, empty means default Comdat *ObjComdat; enum { LastAlignmentBit = 4, HasMetadataHashEntryBit, + HasSectionHashEntryBit, GlobalObjectBits, }; @@ -66,8 +66,26 @@ public: unsigned getGlobalObjectSubClassData() const; void setGlobalObjectSubClassData(unsigned Val); - bool hasSection() const { return !getSection().empty(); } - StringRef getSection() const { return Section; } + /// Check if this global has a custom object file section. + /// + /// This is more efficient than calling getSection() and checking for an empty + /// string. + bool hasSection() const { + return getGlobalValueSubClassData() & (1 << HasSectionHashEntryBit); + } + + /// Get the custom section of this global if it has one. + /// + /// If this global does not have a custom section, this will be empty and the + /// default object file section (.text, .data, etc) will be used. + StringRef getSection() const { + return hasSection() ? getSectionImpl() : StringRef(); + } + + /// Change the section for this global. + /// + /// Setting the section to the empty string tells LLVM to choose an + /// appropriate default object file section. void setSection(StringRef S); bool hasComdat() const { return getComdat() != nullptr; } @@ -134,14 +152,20 @@ public: void clearMetadata(); private: + void setGlobalObjectFlag(unsigned Bit, bool Val) { + unsigned Mask = 1 << Bit; + setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | + (Val ? Mask : 0u)); + } + bool hasMetadataHashEntry() const { return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit); } void setHasMetadataHashEntry(bool HasEntry) { - unsigned Mask = 1 << HasMetadataHashEntryBit; - setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) | - (HasEntry ? Mask : 0u)); + setGlobalObjectFlag(HasMetadataHashEntryBit, HasEntry); } + + StringRef getSectionImpl() const; }; } // end namespace llvm diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 33fd17f20dbe2..89ae94270888b 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -578,8 +578,8 @@ def int_invariant_end : Intrinsic<[], llvm_anyptr_ty], [IntrArgMemOnly, NoCapture<2>]>; -def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty], +def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty], [IntrNoMem]>; //===------------------------ Stackmap Intrinsics -------------------------===// @@ -683,29 +683,6 @@ def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>; def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>; } -// These convert intrinsics are to support various conversions between -// various types with rounding and saturation. NOTE: avoid using these -// intrinsics as they might be removed sometime in the future and -// most targets don't support them. -def int_convertff : Intrinsic<[llvm_anyfloat_ty], - [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertfsi : Intrinsic<[llvm_anyfloat_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertfui : Intrinsic<[llvm_anyfloat_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertsif : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertuif : Intrinsic<[llvm_anyint_ty], - [llvm_anyfloat_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertss : Intrinsic<[llvm_anyint_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertsu : Intrinsic<[llvm_anyint_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertus : Intrinsic<[llvm_anyint_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; -def int_convertuu : Intrinsic<[llvm_anyint_ty], - [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; - // Clear cache intrinsic, default to ignore (ie. emit nothing) // maps to void __clear_cache() on supporting platforms def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index d1e331775b7bf..2c45d148e34b3 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -38,12 +38,6 @@ def int_aarch64_udiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, def int_aarch64_hint : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// -// RBIT - -def int_aarch64_rbit : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], - [IntrNoMem]>; - -//===----------------------------------------------------------------------===// // Data Barrier Instructions def int_aarch64_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 0995985968853..24239689a62ee 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -156,11 +156,6 @@ def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// -// RBIT - -def int_arm_rbit : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; - -//===----------------------------------------------------------------------===// // UND (reserved undefined sequence) def int_arm_undefined : Intrinsic<[], [llvm_i32_ty]>; diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index ecb0435a1e11b..83c4ae0112161 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -317,10 +317,10 @@ struct TypeTestResolution { /// All-Ones Bit Vectors") } TheKind = Unsat; - /// Range of the size expressed as a bit width. For example, if the size is in - /// range [0,256), this number will be 8. This helps generate the most compact + /// Range of size-1 expressed as a bit width. For example, if the size is in + /// range [1,256], this number will be 8. This helps generate the most compact /// instruction sequences. - unsigned SizeBitWidth = 0; + unsigned SizeM1BitWidth = 0; }; struct TypeIdSummary { diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h index aeb66633f2c85..e2880ec6fec8d 100644 --- a/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -29,7 +29,7 @@ template <> struct ScalarEnumerationTraits<TypeTestResolution::Kind> { template <> struct MappingTraits<TypeTestResolution> { static void mapping(IO &io, TypeTestResolution &res) { io.mapOptional("Kind", res.TheKind); - io.mapOptional("SizeBitWidth", res.SizeBitWidth); + io.mapOptional("SizeM1BitWidth", res.SizeM1BitWidth); } }; diff --git a/include/llvm/Object/Decompressor.h b/include/llvm/Object/Decompressor.h new file mode 100644 index 0000000000000..a11857d546aae --- /dev/null +++ b/include/llvm/Object/Decompressor.h @@ -0,0 +1,64 @@ +//===-- Decompressor.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_OBJECT_DECOMPRESSOR_H +#define LLVM_OBJECT_DECOMPRESSOR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { + +/// @brief Decompressor helps to handle decompression of compressed sections. +class Decompressor { +public: + /// @brief Create decompressor object. + /// @param Name Section name. + /// @param Data Section content. + /// @param IsLE Flag determines if Data is in little endian form. + /// @param Is64Bit Flag determines if object is 64 bit. + static Expected<Decompressor> create(StringRef Name, StringRef Data, + bool IsLE, bool Is64Bit); + + /// @brief Resize the buffer and uncompress section data into it. + /// @param Out Destination buffer. + Error decompress(SmallString<32> &Out); + + /// @brief Uncompress section data to raw buffer provided. + /// @param Buffer Destination buffer. + Error decompress(MutableArrayRef<char> Buffer); + + /// @brief Return memory buffer size required for decompression. + uint64_t getDecompressedSize() { return DecompressedSize; } + + /// @brief Return true if section is compressed, including gnu-styled case. + static bool isCompressed(const object::SectionRef &Section); + + /// @brief Return true if section is a ELF compressed one. + static bool isCompressedELFSection(uint64_t Flags, StringRef Name); + + /// @brief Return true if section name matches gnu style compressed one. + static bool isGnuStyle(StringRef Name); + +private: + Decompressor(StringRef Data); + + Error consumeCompressedGnuHeader(); + Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); + + StringRef SectionData; + uint64_t DecompressedSize; +}; + +} // end namespace object +} // end namespace llvm + +#endif // LLVM_OBJECT_DECOMPRESSOR_H diff --git a/include/llvm/ObjectYAML/DWARFYAML.h b/include/llvm/ObjectYAML/DWARFYAML.h index 222cad61a9923..d031b5ac404c5 100644 --- a/include/llvm/ObjectYAML/DWARFYAML.h +++ b/include/llvm/ObjectYAML/DWARFYAML.h @@ -85,6 +85,41 @@ struct Unit { std::vector<Entry> Entries; }; +struct File { + StringRef Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; +}; + +struct LineTableOpcode { + dwarf::LineNumberOps Opcode; + uint64_t ExtLen; + dwarf::LineNumberExtendedOps SubOpcode; + uint64_t Data; + int64_t SData; + File FileEntry; + std::vector<llvm::yaml::Hex8> UnknownOpcodeData; + std::vector<llvm::yaml::Hex64> StandardOpcodeData; +}; + +struct LineTable { + uint32_t TotalLength; + uint64_t TotalLength64; + uint16_t Version; + uint64_t PrologueLength; + uint8_t MinInstLength; + uint8_t MaxOpsPerInst; + uint8_t DefaultIsStmt; + uint8_t LineBase; + uint8_t LineRange; + uint8_t OpcodeBase; + std::vector<uint8_t> StandardOpcodeLengths; + std::vector<StringRef> IncludeDirs; + std::vector<File> Files; + std::vector<LineTableOpcode> Opcodes; +}; + struct Data { bool IsLittleEndian; std::vector<Abbrev> AbbrevDecls; @@ -98,6 +133,8 @@ struct Data { std::vector<Unit> CompileUnits; + std::vector<LineTable> DebugLines; + bool isEmpty() const; }; @@ -105,6 +142,7 @@ struct Data { } // namespace llvm LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex8) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AttributeAbbrev) @@ -115,6 +153,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::PubEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Unit) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::FormValue) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Entry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::File) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTable) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTableOpcode) namespace llvm { namespace yaml { @@ -159,6 +200,18 @@ template <> struct MappingTraits<DWARFYAML::FormValue> { static void mapping(IO &IO, DWARFYAML::FormValue &FormValue); }; +template <> struct MappingTraits<DWARFYAML::File> { + static void mapping(IO &IO, DWARFYAML::File &File); +}; + +template <> struct MappingTraits<DWARFYAML::LineTableOpcode> { + static void mapping(IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode); +}; + +template <> struct MappingTraits<DWARFYAML::LineTable> { + static void mapping(IO &IO, DWARFYAML::LineTable &LineTable); +}; + #define HANDLE_DW_TAG(unused, name) \ io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name); @@ -169,6 +222,26 @@ template <> struct ScalarEnumerationTraits<dwarf::Tag> { } }; +#define HANDLE_DW_LNS(unused, name) \ + io.enumCase(value, "DW_LNS_" #name, dwarf::DW_LNS_##name); + +template <> struct ScalarEnumerationTraits<dwarf::LineNumberOps> { + static void enumeration(IO &io, dwarf::LineNumberOps &value) { +#include "llvm/Support/Dwarf.def" + io.enumFallback<Hex8>(value); + } +}; + +#define HANDLE_DW_LNE(unused, name) \ + io.enumCase(value, "DW_LNE_" #name, dwarf::DW_LNE_##name); + +template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> { + static void enumeration(IO &io, dwarf::LineNumberExtendedOps &value) { +#include "llvm/Support/Dwarf.def" + io.enumFallback<Hex16>(value); + } +}; + #define HANDLE_DW_AT(unused, name) \ io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name); diff --git a/include/llvm/ObjectYAML/MachOYAML.h b/include/llvm/ObjectYAML/MachOYAML.h index 6b7a924f51438..9ec32d265bcae 100644 --- a/include/llvm/ObjectYAML/MachOYAML.h +++ b/include/llvm/ObjectYAML/MachOYAML.h @@ -139,7 +139,6 @@ struct UniversalBinary { LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::LoadCommand) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::Section) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::Hex64) LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::RebaseOpcode) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MachOYAML::BindOpcode) diff --git a/include/llvm/Passes/PassBuilder.h b/include/llvm/Passes/PassBuilder.h index ba3238c860447..d76c13984d11c 100644 --- a/include/llvm/Passes/PassBuilder.h +++ b/include/llvm/Passes/PassBuilder.h @@ -18,8 +18,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/Analysis/CGSCCPassManager.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" #include <vector> namespace llvm { diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 094f3af005d37..c7e558efa3dcc 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -230,6 +230,15 @@ class InstrProfSymtab; /// bytes. This method decodes the string and populates the \c Symtab. Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab); +/// Check if INSTR_PROF_RAW_VERSION_VAR is defined. This global is only being +/// set in IR PGO compilation. +bool isIRPGOFlagSet(const Module *M); + +/// Check if we can safely rename this Comdat function. Instances of the same +/// comdat function may have different control flows thus can not share the +/// same counter variable. +bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false); + enum InstrProfValueKind : uint32_t { #define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value, #include "llvm/ProfileData/InstrProfData.inc" diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 204672f88dd9f..8d4ac81d29429 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -201,7 +201,7 @@ public: void reset(); - operator bool() const; + explicit operator bool() const; StringRef getName() const { return Name; } StringRef getDescription() const { return Description; } diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 1a984037da090..8336b9df9df0d 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -207,7 +207,7 @@ enum DiscriminantList { }; /// Line Number Standard Opcode Encodings. -enum LineNumberOps { +enum LineNumberOps : uint8_t { #define HANDLE_DW_LNS(ID, NAME) DW_LNS_##NAME = ID, #include "llvm/Support/Dwarf.def" }; diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 3bcf64a8a08bd..2c054c75374be 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -78,11 +78,12 @@ private: FileOutputBuffer &operator=(const FileOutputBuffer &) = delete; FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R, - StringRef Path, StringRef TempPath); + StringRef Path, StringRef TempPath, bool IsRegular); std::unique_ptr<llvm::sys::fs::mapped_file_region> Region; SmallString<128> FinalPath; SmallString<128> TempPath; + bool IsRegular; }; } // end namespace llvm diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index 07a53438085a0..6e6ee40016440 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -571,9 +571,15 @@ public: // API to update (Post)DominatorTree information based on modifications to // the CFG... - /// addNewBlock - Add a new node to the dominator tree information. This - /// creates a new node as a child of DomBB dominator node,linking it into - /// the children list of the immediate dominator. + /// Add a new node to the dominator tree information. + /// + /// This creates a new node as a child of DomBB dominator node, linking it + /// into the children list of the immediate dominator. + /// + /// \param BB New node in CFG. + /// \param DomBB CFG node that is dominator for BB. + /// \returns New dominator tree node that represents new CFG node. + /// DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) { assert(getNode(BB) == nullptr && "Block already in dominator tree!"); DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB); @@ -583,6 +589,31 @@ public: llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); } + /// Add a new node to the forward dominator tree and make it a new root. + /// + /// \param BB New node in CFG. + /// \returns New dominator tree node that represents new CFG node. + /// + DomTreeNodeBase<NodeT> *setNewRoot(NodeT *BB) { + assert(getNode(BB) == nullptr && "Block already in dominator tree!"); + assert(!this->isPostDominator() && + "Cannot change root of post-dominator tree"); + DFSInfoValid = false; + auto &Roots = DominatorBase<NodeT>::Roots; + DomTreeNodeBase<NodeT> *NewNode = (DomTreeNodes[BB] = + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr)).get(); + if (Roots.empty()) { + addRoot(BB); + } else { + assert(Roots.size() == 1); + NodeT *OldRoot = Roots.front(); + DomTreeNodes[OldRoot] = + NewNode->addChild(std::move(DomTreeNodes[OldRoot])); + Roots[0] = BB; + } + return RootNode = NewNode; + } + /// changeImmediateDominator - This method is used to update the dominator /// tree information when a node's immediate dominator changes. /// diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index fb43ef19a6450..3728a7a8cb179 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -23,66 +23,80 @@ #ifndef LLVM_TARGET_TARGETLOWERING_H #define LLVM_TARGET_TARGETLOWERING_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/DAGCombine.h" +#include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/AtomicOrdering.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" +#include <algorithm> +#include <cassert> #include <climits> +#include <cstdint> +#include <iterator> #include <map> +#include <string> +#include <utility> #include <vector> namespace llvm { - class BranchProbability; - class CallInst; - class CCState; - class CCValAssign; - class FastISel; - class FunctionLoweringInfo; - class ImmutableCallSite; - class IntrinsicInst; - class MachineBasicBlock; - class MachineFunction; - class MachineInstr; - class MachineJumpTableInfo; - class MachineLoop; - class MachineRegisterInfo; - class Mangler; - class MCContext; - class MCExpr; - class MCSymbol; - template<typename T> class SmallVectorImpl; - class DataLayout; - class TargetRegisterClass; - class TargetLibraryInfo; - class TargetLoweringObjectFile; - class Value; - - namespace Sched { - enum Preference { - None, // No preference - Source, // Follow source order. - RegPressure, // Scheduling for lowest register pressure. - Hybrid, // Scheduling for both latency and register pressure. - ILP, // Scheduling for ILP in low register pressure mode. - VLIW // Scheduling for VLIW targets. - }; - } + +class BranchProbability; +class CCState; +class CCValAssign; +class FastISel; +class FunctionLoweringInfo; +class IntrinsicInst; +class MachineBasicBlock; +class MachineFunction; +class MachineInstr; +class MachineJumpTableInfo; +class MachineLoop; +class MachineRegisterInfo; +class MCContext; +class MCExpr; +class TargetRegisterClass; +class TargetLibraryInfo; +class TargetRegisterInfo; +class Value; + +namespace Sched { + + enum Preference { + None, // No preference + Source, // Follow source order. + RegPressure, // Scheduling for lowest register pressure. + Hybrid, // Scheduling for both latency and register pressure. + ILP, // Scheduling for ILP in low register pressure mode. + VLIW // Scheduling for VLIW targets. + }; + +} // end namespace Sched /// This base class for TargetLowering contains the SelectionDAG-independent /// parts that can be used from the rest of CodeGen. class TargetLoweringBase { - TargetLoweringBase(const TargetLoweringBase&) = delete; - void operator=(const TargetLoweringBase&) = delete; - public: /// This enum indicates whether operations are valid for a target, and if not, /// what action should be used to make them valid. @@ -166,7 +180,9 @@ public: /// NOTE: The TargetMachine owns TLOF. explicit TargetLoweringBase(const TargetMachine &TM); - virtual ~TargetLoweringBase() {} + TargetLoweringBase(const TargetLoweringBase&) = delete; + void operator=(const TargetLoweringBase&) = delete; + virtual ~TargetLoweringBase() = default; protected: /// \brief Initialize all of the actions to default values. @@ -599,19 +615,18 @@ public: MVT &RegisterVT) const; struct IntrinsicInfo { - unsigned opc; // target opcode - EVT memVT; // memory VT - const Value* ptrVal; // value representing memory location - int offset; // offset off of ptrVal - unsigned size; // the size of the memory location - // (taken from memVT if zero) - unsigned align; // alignment - bool vol; // is volatile? - bool readMem; // reads memory? - bool writeMem; // writes memory? - - IntrinsicInfo() : opc(0), ptrVal(nullptr), offset(0), size(0), align(1), - vol(false), readMem(false), writeMem(false) {} + unsigned opc = 0; // target opcode + EVT memVT; // memory VT + const Value* ptrVal = nullptr; // value representing memory location + int offset = 0; // offset off of ptrVal + unsigned size = 0; // the size of the memory location + // (taken from memVT if zero) + unsigned align = 1; // alignment + bool vol = false; // is volatile? + bool readMem = false; // reads memory? + bool writeMem = false; // writes memory? + + IntrinsicInfo() = default; }; /// Given an intrinsic, checks if on the target the intrinsic will need to map @@ -823,7 +838,6 @@ public: getCondCodeAction(CC, VT) == Custom; } - /// If the action for this operation is to promote, this method returns the /// ValueType to promote to. MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { @@ -1643,11 +1657,11 @@ public: /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with /// no scale. struct AddrMode { - GlobalValue *BaseGV; - int64_t BaseOffs; - bool HasBaseReg; - int64_t Scale; - AddrMode() : BaseGV(nullptr), BaseOffs(0), HasBaseReg(false), Scale(0) {} + GlobalValue *BaseGV = nullptr; + int64_t BaseOffs = 0; + bool HasBaseReg = false; + int64_t Scale = 0; + AddrMode() = default; }; /// Return true if the addressing mode represented by AM is legal for this @@ -2093,8 +2107,6 @@ protected: private: LegalizeKind getTypeConversion(LLVMContext &Context, EVT VT) const; -private: - /// Targets can specify ISD nodes that they would like PerformDAGCombine /// callbacks for by calling setTargetDAGCombine(), which sets a bit in this /// array. @@ -2192,7 +2204,6 @@ protected: /// \see enableExtLdPromotion. bool EnableExtLdPromotion; -protected: /// Return true if the value types that can be represented by the specified /// register class are all legal. bool isLegalRC(const TargetRegisterClass *RC) const; @@ -2209,12 +2220,12 @@ protected: /// This class also defines callbacks that targets must implement to lower /// target-specific constructs to SelectionDAG operators. class TargetLowering : public TargetLoweringBase { - TargetLowering(const TargetLowering&) = delete; - void operator=(const TargetLowering&) = delete; - public: struct DAGCombinerInfo; + TargetLowering(const TargetLowering&) = delete; + void operator=(const TargetLowering&) = delete; + /// NOTE: The TargetMachine owns TLOF. explicit TargetLowering(const TargetMachine &TM); @@ -2376,6 +2387,7 @@ public: void *DC; // The DAG Combiner object. CombineLevel Level; bool CalledByLegalizer; + public: SelectionDAG &DAG; @@ -2542,7 +2554,7 @@ public: ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), isSRet(false), isNest(false), isByVal(false), isInAlloca(false), isReturned(false), isSwiftSelf(false), isSwiftError(false), - Alignment(0) { } + Alignment(0) {} void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; @@ -2681,7 +2693,6 @@ public: ArgListTy &getArgs() { return Args; } - }; /// This function lowers an abstract call to a function into an actual call. @@ -3118,6 +3129,13 @@ public: EVT DataVT, SelectionDAG &DAG, bool IsCompressedMemory) const; + /// Get a pointer to vector element \p Idx located in memory for a vector of + /// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of + /// bounds the returned pointer is unspecified, but will be within the vector + /// bounds. + SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, + SDValue Idx) const; + //===--------------------------------------------------------------------===// // Instruction Emitting Hooks // @@ -3169,6 +3187,6 @@ void GetReturnInfo(Type *ReturnType, AttributeSet attr, SmallVectorImpl<ISD::OutputArg> &Outs, const TargetLowering &TLI, const DataLayout &DL); -} // end llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_TARGET_TARGETLOWERING_H diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index f5493283eee6f..b1d8f8f1e9173 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -20,36 +20,26 @@ #include "llvm/Pass.h" #include "llvm/Support/CodeGen.h" #include "llvm/Target/TargetOptions.h" -#include <cassert> #include <string> namespace llvm { -class InstrItineraryData; class GlobalValue; -class Mangler; class MachineFunctionInitializer; -class MachineModuleInfo; +class Mangler; class MCAsmInfo; class MCContext; class MCInstrInfo; class MCRegisterInfo; class MCSubtargetInfo; class MCSymbol; +class raw_pwrite_stream; class Target; -class TargetLibraryInfo; -class TargetFrameLowering; -class TargetIRAnalysis; class TargetIntrinsicInfo; -class TargetLowering; +class TargetIRAnalysis; +class TargetLoweringObjectFile; class TargetPassConfig; -class TargetRegisterInfo; class TargetSubtargetInfo; -class TargetTransformInfo; -class formatted_raw_ostream; -class raw_ostream; -class raw_pwrite_stream; -class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. namespace legacy { @@ -64,8 +54,6 @@ using legacy::PassManagerBase; /// interface. /// class TargetMachine { - TargetMachine(const TargetMachine &) = delete; - void operator=(const TargetMachine &) = delete; protected: // Can only create subclasses. TargetMachine(const Target &T, StringRef DataLayoutString, const Triple &TargetTriple, StringRef CPU, StringRef FS, @@ -103,8 +91,11 @@ protected: // Can only create subclasses. unsigned O0WantsFastISel : 1; public: + const TargetOptions DefaultOptions; mutable TargetOptions Options; + TargetMachine(const TargetMachine &) = delete; + void operator=(const TargetMachine &) = delete; virtual ~TargetMachine(); const Target &getTarget() const { return TheTarget; } @@ -310,6 +301,6 @@ public: bool DisableVerify = true) override; }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_TARGET_TARGETMACHINE_H diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 4ddf7d77a23af..55e2c2bce3db9 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -575,9 +575,6 @@ def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; -// Do not use cvt directly. Use cvt forms below -def cvt : SDNode<"ISD::CONVERT_RNDSAT", SDTConvertOp>; - def SDT_assertext : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>; def assertsext : SDNode<"ISD::AssertSext", SDT_assertext>; @@ -1085,54 +1082,6 @@ def atomic_load_64 : }]>; //===----------------------------------------------------------------------===// -// Selection DAG CONVERT_RNDSAT patterns - -def cvtff : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_FF; - }]>; - -def cvtss : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_SS; - }]>; - -def cvtsu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_SU; - }]>; - -def cvtus : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_US; - }]>; - -def cvtuu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_UU; - }]>; - -def cvtsf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_SF; - }]>; - -def cvtuf : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_UF; - }]>; - -def cvtfs : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_FS; - }]>; - -def cvtfu : PatFrag<(ops node:$val, node:$dty, node:$sty, node:$rd, node:$sat), - (cvt node:$val, node:$dty, node:$sty, node:$rd, node:$sat), [{ - return cast<CvtRndSatSDNode>(N)->getCvtCode() == ISD::CVT_FU; - }]>; - -//===----------------------------------------------------------------------===// // Selection DAG Pattern Support. // // Patterns are what are actually matched against by the target-flavored diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index bf4331383cb0d..0b43515960216 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -14,23 +14,26 @@ #ifndef LLVM_TARGET_TARGETSUBTARGETINFO_H #define LLVM_TARGET_TARGETSUBTARGETINFO_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/PBQPRAConstraint.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/ScheduleDAGMutation.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/CodeGen.h" +#include <memory> #include <vector> namespace llvm { class CallLowering; -class DataLayout; class InstructionSelector; class LegalizerInfo; -class MachineFunction; class MachineInstr; class RegisterBankInfo; class SDep; +class SelectionDAGTargetInfo; class SUnit; class TargetFrameLowering; class TargetInstrInfo; @@ -38,9 +41,7 @@ class TargetLowering; class TargetRegisterClass; class TargetRegisterInfo; class TargetSchedModel; -class SelectionDAGTargetInfo; struct MachineSchedPolicy; -template <typename T> class SmallVectorImpl; //===----------------------------------------------------------------------===// /// @@ -49,10 +50,6 @@ template <typename T> class SmallVectorImpl; /// be exposed through a TargetSubtargetInfo-derived class. /// class TargetSubtargetInfo : public MCSubtargetInfo { - TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; - void operator=(const TargetSubtargetInfo &) = delete; - TargetSubtargetInfo() = delete; - protected: // Can only create subclasses... TargetSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF, @@ -69,6 +66,9 @@ public: typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; typedef SmallVectorImpl<const TargetRegisterClass *> RegClassVector; + TargetSubtargetInfo() = delete; + TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; + void operator=(const TargetSubtargetInfo &) = delete; virtual ~TargetSubtargetInfo(); virtual bool isXRaySupported() const { return false; } @@ -229,6 +229,6 @@ public: virtual bool enableSubRegLiveness() const { return false; } }; -} // End llvm namespace +} // end namespace llvm -#endif +#endif // LLVM_TARGET_TARGETSUBTARGETINFO_H diff --git a/include/llvm/Transforms/Scalar/IVUsersPrinter.h b/include/llvm/Transforms/Scalar/IVUsersPrinter.h new file mode 100644 index 0000000000000..fad00d86a95f1 --- /dev/null +++ b/include/llvm/Transforms/Scalar/IVUsersPrinter.h @@ -0,0 +1,30 @@ +//===- IVUsersPrinter.h - Induction Variable Users Printing -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_IVUSERSPRINTER_H +#define LLVM_TRANSFORMS_SCALAR_IVUSERSPRINTER_H + +#include "llvm/Analysis/IVUsers.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" + +namespace llvm { + +/// Printer pass for the \c IVUsers for a loop. +class IVUsersPrinterPass : public PassInfoMixin<IVUsersPrinterPass> { + raw_ostream &OS; + +public: + explicit IVUsersPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; +} + +#endif diff --git a/include/llvm/Transforms/Scalar/IndVarSimplify.h b/include/llvm/Transforms/Scalar/IndVarSimplify.h index 24a31594b1530..4a4683f1a07df 100644 --- a/include/llvm/Transforms/Scalar/IndVarSimplify.h +++ b/include/llvm/Transforms/Scalar/IndVarSimplify.h @@ -16,14 +16,15 @@ #define LLVM_TRANSFORMS_SCALAR_INDVARSIMPLIFY_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { class IndVarSimplifyPass : public PassInfoMixin<IndVarSimplifyPass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } diff --git a/include/llvm/Transforms/Scalar/LICM.h b/include/llvm/Transforms/Scalar/LICM.h index 39bbc72f8cb4c..68ad190c7647d 100644 --- a/include/llvm/Transforms/Scalar/LICM.h +++ b/include/llvm/Transforms/Scalar/LICM.h @@ -34,15 +34,16 @@ #define LLVM_TRANSFORMS_SCALAR_LICM_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { /// Performs Loop Invariant Code Motion Pass. class LICMPass : public PassInfoMixin<LICMPass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h b/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h new file mode 100644 index 0000000000000..5eddd5fdc7e7e --- /dev/null +++ b/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h @@ -0,0 +1,31 @@ +//===- llvm/Analysis/LoopAccessAnalysisPrinter.h ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOOPACCESSANALYSISPRINTER_H +#define LLVM_TRANSFORMS_SCALAR_LOOPACCESSANALYSISPRINTER_H + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" + +namespace llvm { + +/// \brief Printer pass for the \c LoopAccessInfo results. +class LoopAccessInfoPrinterPass + : public PassInfoMixin<LoopAccessInfoPrinterPass> { + raw_ostream &OS; + +public: + explicit LoopAccessInfoPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Scalar/LoopDeletion.h b/include/llvm/Transforms/Scalar/LoopDeletion.h index 891f08faa48a9..b44f823a82cac 100644 --- a/include/llvm/Transforms/Scalar/LoopDeletion.h +++ b/include/llvm/Transforms/Scalar/LoopDeletion.h @@ -15,16 +15,17 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPDELETION_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { class LoopDeletionPass : public PassInfoMixin<LoopDeletionPass> { public: LoopDeletionPass() {} - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); bool runImpl(Loop *L, DominatorTree &DT, ScalarEvolution &SE, LoopInfo &loopInfo); diff --git a/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h index 0c052ddd2fe7b..40349e8f7fe06 100644 --- a/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h +++ b/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h @@ -17,15 +17,16 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPIDIOMRECOGNIZE_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { /// Performs Loop Idiom Recognize Pass. class LoopIdiomRecognizePass : public PassInfoMixin<LoopIdiomRecognizePass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Scalar/LoopInstSimplify.h b/include/llvm/Transforms/Scalar/LoopInstSimplify.h index e30f4a97b78e0..bb8bc29577a2d 100644 --- a/include/llvm/Transforms/Scalar/LoopInstSimplify.h +++ b/include/llvm/Transforms/Scalar/LoopInstSimplify.h @@ -15,15 +15,16 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPINSTSIMPLIFY_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { /// Performs Loop Inst Simplify Pass. class LoopInstSimplifyPass : public PassInfoMixin<LoopInstSimplifyPass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Scalar/LoopPassManager.h b/include/llvm/Transforms/Scalar/LoopPassManager.h new file mode 100644 index 0000000000000..b0e6dd6f4c081 --- /dev/null +++ b/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -0,0 +1,363 @@ +//===- LoopPassManager.h - Loop pass management -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides classes for managing a pipeline of passes over loops +/// in LLVM IR. +/// +/// The primary loop pass pipeline is managed in a very particular way to +/// provide a set of core guarantees: +/// 1) Loops are, where possible, in simplified form. +/// 2) Loops are *always* in LCSSA form. +/// 3) A collection of Loop-specific analysis results are available: +/// - LoopInfo +/// - DominatorTree +/// - ScalarEvolution +/// - AAManager +/// 4) All loop passes preserve #1 (where possible), #2, and #3. +/// 5) Loop passes run over each loop in the loop nest from the innermost to +/// the outermost. Specifically, all inner loops are processed before +/// passes run over outer loops. When running the pipeline across an inner +/// loop creates new inner loops, those are added and processed in this +/// order as well. +/// +/// This process is designed to facilitate transformations which simplify, +/// reduce, and remove loops. For passes which are more oriented towards +/// optimizing loops, especially optimizing loop *nests* instead of single +/// loops in isolation, this framework is less interesting. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H +#define LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H + +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/PriorityWorklist.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +// Forward declarations of an update tracking API used in the pass manager. +class LPMUpdater; + +// Explicit specialization and instantiation declarations for the pass manager. +// See the comments on the definition of the specialization for details on how +// it differs from the primary template. +template <> +PreservedAnalyses +PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, + LPMUpdater &>::run(Loop &InitialL, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AnalysisResults, + LPMUpdater &U); +extern template class PassManager<Loop, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &>; + +/// \brief The Loop pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequence of Loop passes over each Loop that the manager is run over. This +/// typedef serves as a convenient way to refer to this construct. +typedef PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, + LPMUpdater &> + LoopPassManager; + +/// A partial specialization of the require analysis template pass to forward +/// the extra parameters from a transformation's run method to the +/// AnalysisManager's getResult. +template <typename AnalysisT> +struct RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &> + : PassInfoMixin< + RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &>> { + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &) { + (void)AM.template getResult<AnalysisT>(L, AR); + return PreservedAnalyses::all(); + } +}; + +/// An alias template to easily name a require analysis loop pass. +template <typename AnalysisT> +using RequireAnalysisLoopPass = + RequireAnalysisPass<AnalysisT, Loop, LoopAnalysisManager, + LoopStandardAnalysisResults &, LPMUpdater &>; + +namespace internal { +/// Helper to implement appending of loops onto a worklist. +/// +/// We want to process loops in postorder, but the worklist is a LIFO data +/// structure, so we append to it in *reverse* postorder. +/// +/// For trees, a preorder traversal is a viable reverse postorder, so we +/// actually append using a preorder walk algorithm. +template <typename RangeT> +inline void appendLoopsToWorklist(RangeT &&Loops, + SmallPriorityWorklist<Loop *, 4> &Worklist) { + // We use an internal worklist to build up the preorder traversal without + // recursion. + SmallVector<Loop *, 4> PreOrderLoops, PreOrderWorklist; + + // We walk the initial sequence of loops in reverse because we generally want + // to visit defs before uses and the worklist is LIFO. + for (Loop *RootL : reverse(Loops)) { + assert(PreOrderLoops.empty() && "Must start with an empty preorder walk."); + assert(PreOrderWorklist.empty() && + "Must start with an empty preorder walk worklist."); + PreOrderWorklist.push_back(RootL); + do { + Loop *L = PreOrderWorklist.pop_back_val(); + PreOrderWorklist.append(L->begin(), L->end()); + PreOrderLoops.push_back(L); + } while (!PreOrderWorklist.empty()); + + Worklist.insert(std::move(PreOrderLoops)); + PreOrderLoops.clear(); + } +} +} + +template <typename LoopPassT> class FunctionToLoopPassAdaptor; + +/// This class provides an interface for updating the loop pass manager based +/// on mutations to the loop nest. +/// +/// A reference to an instance of this class is passed as an argument to each +/// Loop pass, and Loop passes should use it to update LPM infrastructure if +/// they modify the loop nest structure. +class LPMUpdater { +public: + /// This can be queried by loop passes which run other loop passes (like pass + /// managers) to know whether the loop needs to be skipped due to updates to + /// the loop nest. + /// + /// If this returns true, the loop object may have been deleted, so passes + /// should take care not to touch the object. + bool skipCurrentLoop() const { return SkipCurrentLoop; } + + /// Loop passes should use this method to indicate they have deleted a loop + /// from the nest. + /// + /// Note that this loop must either be the current loop or a subloop of the + /// current loop. This routine must be called prior to removing the loop from + /// the loop nest. + /// + /// If this is called for the current loop, in addition to clearing any + /// state, this routine will mark that the current loop should be skipped by + /// the rest of the pass management infrastructure. + void markLoopAsDeleted(Loop &L) { + LAM.clear(L); + assert(CurrentL->contains(&L) && "Cannot delete a loop outside of the " + "subloop tree currently being processed."); + if (&L == CurrentL) + SkipCurrentLoop = true; + } + + /// Loop passes should use this method to indicate they have added new child + /// loops of the current loop. + /// + /// \p NewChildLoops must contain only the immediate children. Any nested + /// loops within them will be visited in postorder as usual for the loop pass + /// manager. + void addChildLoops(ArrayRef<Loop *> NewChildLoops) { + // Insert ourselves back into the worklist first, as this loop should be + // revisited after all the children have been processed. + Worklist.insert(CurrentL); + +#ifndef NDEBUG + for (Loop *NewL : NewChildLoops) + assert(NewL->getParentLoop() == CurrentL && "All of the new loops must " + "be immediate children of " + "the current loop!"); +#endif + + internal::appendLoopsToWorklist(NewChildLoops, Worklist); + + // Also skip further processing of the current loop--it will be revisited + // after all of its newly added children are accounted for. + SkipCurrentLoop = true; + } + + /// Loop passes should use this method to indicate they have added new + /// sibling loops to the current loop. + /// + /// \p NewSibLoops must only contain the immediate sibling loops. Any nested + /// loops within them will be visited in postorder as usual for the loop pass + /// manager. + void addSiblingLoops(ArrayRef<Loop *> NewSibLoops) { +#ifndef NDEBUG + for (Loop *NewL : NewSibLoops) + assert(NewL->getParentLoop() == ParentL && + "All of the new loops must be siblings of the current loop!"); +#endif + + internal::appendLoopsToWorklist(NewSibLoops, Worklist); + + // No need to skip the current loop or revisit it, as sibling loops + // shouldn't impact anything. + } + +private: + template <typename LoopPassT> friend class llvm::FunctionToLoopPassAdaptor; + + /// The \c FunctionToLoopPassAdaptor's worklist of loops to process. + SmallPriorityWorklist<Loop *, 4> &Worklist; + + /// The analysis manager for use in the current loop nest. + LoopAnalysisManager &LAM; + + Loop *CurrentL; + bool SkipCurrentLoop; + +#ifndef NDEBUG + // In debug builds we also track the parent loop to implement asserts even in + // the face of loop deletion. + Loop *ParentL; +#endif + + LPMUpdater(SmallPriorityWorklist<Loop *, 4> &Worklist, + LoopAnalysisManager &LAM) + : Worklist(Worklist), LAM(LAM) {} +}; + +/// \brief Adaptor that maps from a function to its loops. +/// +/// Designed to allow composition of a LoopPass(Manager) and a +/// FunctionPassManager. Note that if this pass is constructed with a \c +/// FunctionAnalysisManager it will run the \c LoopAnalysisManagerFunctionProxy +/// analysis prior to running the loop passes over the function to enable a \c +/// LoopAnalysisManager to be used within this run safely. +template <typename LoopPassT> +class FunctionToLoopPassAdaptor + : public PassInfoMixin<FunctionToLoopPassAdaptor<LoopPassT>> { +public: + explicit FunctionToLoopPassAdaptor(LoopPassT Pass) : Pass(std::move(Pass)) {} + + /// \brief Runs the loop passes across every loop in the function. + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + // Setup the loop analysis manager from its proxy. + LoopAnalysisManager &LAM = + AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager(); + // Get the loop structure for this function + LoopInfo &LI = AM.getResult<LoopAnalysis>(F); + + // If there are no loops, there is nothing to do here. + if (LI.empty()) + return PreservedAnalyses::all(); + + // Get the analysis results needed by loop passes. + LoopStandardAnalysisResults LAR = {AM.getResult<AAManager>(F), + AM.getResult<AssumptionAnalysis>(F), + AM.getResult<DominatorTreeAnalysis>(F), + AM.getResult<LoopAnalysis>(F), + AM.getResult<ScalarEvolutionAnalysis>(F), + AM.getResult<TargetLibraryAnalysis>(F), + AM.getResult<TargetIRAnalysis>(F)}; + + PreservedAnalyses PA = PreservedAnalyses::all(); + + // A postorder worklist of loops to process. + SmallPriorityWorklist<Loop *, 4> Worklist; + + // Register the worklist and loop analysis manager so that loop passes can + // update them when they mutate the loop nest structure. + LPMUpdater Updater(Worklist, LAM); + + // Add the loop nests in the reverse order of LoopInfo. For some reason, + // they are stored in RPO w.r.t. the control flow graph in LoopInfo. For + // the purpose of unrolling, loop deletion, and LICM, we largely want to + // work forward across the CFG so that we visit defs before uses and can + // propagate simplifications from one loop nest into the next. + // FIXME: Consider changing the order in LoopInfo. + internal::appendLoopsToWorklist(reverse(LI), Worklist); + + do { + Loop *L = Worklist.pop_back_val(); + + // Reset the update structure for this loop. + Updater.CurrentL = L; + Updater.SkipCurrentLoop = false; +#ifndef NDEBUG + Updater.ParentL = L->getParentLoop(); +#endif + + PreservedAnalyses PassPA = Pass.run(*L, LAM, LAR, Updater); + // FIXME: We should verify the set of analyses relevant to Loop passes + // are preserved. + + // If the loop hasn't been deleted, we need to handle invalidation here. + if (!Updater.skipCurrentLoop()) + // We know that the loop pass couldn't have invalidated any other + // loop's analyses (that's the contract of a loop pass), so directly + // handle the loop analysis manager's invalidation here. + LAM.invalidate(*L, PassPA); + + // Then intersect the preserved set so that invalidation of module + // analyses will eventually occur when the module pass completes. + PA.intersect(std::move(PassPA)); + } while (!Worklist.empty()); + + // By definition we preserve the proxy. We also preserve all analyses on + // Loops. This precludes *any* invalidation of loop analyses by the proxy, + // but that's OK because we've taken care to invalidate analyses in the + // loop analysis manager incrementally above. + PA.preserveSet<AllAnalysesOn<Loop>>(); + PA.preserve<LoopAnalysisManagerFunctionProxy>(); + // We also preserve the set of standard analyses. + PA.preserve<AssumptionAnalysis>(); + PA.preserve<DominatorTreeAnalysis>(); + PA.preserve<LoopAnalysis>(); + PA.preserve<ScalarEvolutionAnalysis>(); + // FIXME: What we really want to do here is preserve an AA category, but + // that concept doesn't exist yet. + PA.preserve<AAManager>(); + PA.preserve<BasicAA>(); + PA.preserve<GlobalsAA>(); + PA.preserve<SCEVAA>(); + return PA; + } + +private: + LoopPassT Pass; +}; + +/// \brief A function to deduce a loop pass type and wrap it in the templated +/// adaptor. +template <typename LoopPassT> +FunctionToLoopPassAdaptor<LoopPassT> +createFunctionToLoopPassAdaptor(LoopPassT Pass) { + return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass)); +} + +/// \brief Pass for printing a loop's contents as textual IR. +class PrintLoopPass : public PassInfoMixin<PrintLoopPass> { + raw_ostream &OS; + std::string Banner; + +public: + PrintLoopPass(); + PrintLoopPass(raw_ostream &OS, const std::string &Banner = ""); + + PreservedAnalyses run(Loop &L, LoopAnalysisManager &, + LoopStandardAnalysisResults &, LPMUpdater &); +}; +} + +#endif // LLVM_TRANSFORMS_SCALAR_LOOPPASSMANAGER_H diff --git a/include/llvm/Transforms/Scalar/LoopRotation.h b/include/llvm/Transforms/Scalar/LoopRotation.h index 54b8ec545ed2b..ea8d5618e6f7d 100644 --- a/include/llvm/Transforms/Scalar/LoopRotation.h +++ b/include/llvm/Transforms/Scalar/LoopRotation.h @@ -15,8 +15,8 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPROTATION_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { @@ -24,7 +24,8 @@ namespace llvm { class LoopRotatePass : public PassInfoMixin<LoopRotatePass> { public: LoopRotatePass(bool EnableHeaderDuplication = true); - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); private: const bool EnableHeaderDuplication; diff --git a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h index 2f06782052c5e..7628c7413eac5 100644 --- a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h +++ b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h @@ -18,15 +18,16 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { /// Performs basic CFG simplifications to assist other loop passes. class LoopSimplifyCFGPass : public PassInfoMixin<LoopSimplifyCFGPass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Scalar/LoopStrengthReduce.h b/include/llvm/Transforms/Scalar/LoopStrengthReduce.h index 11c0d9bce85b1..ebcb32125262b 100644 --- a/include/llvm/Transforms/Scalar/LoopStrengthReduce.h +++ b/include/llvm/Transforms/Scalar/LoopStrengthReduce.h @@ -23,15 +23,16 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPSTRENGTHREDUCE_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { /// Performs Loop Strength Reduce Pass. class LoopStrengthReducePass : public PassInfoMixin<LoopStrengthReducePass> { public: - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Scalar/LoopUnrollPass.h b/include/llvm/Transforms/Scalar/LoopUnrollPass.h index 74a7258df5fc3..9da95ef81fad4 100644 --- a/include/llvm/Transforms/Scalar/LoopUnrollPass.h +++ b/include/llvm/Transforms/Scalar/LoopUnrollPass.h @@ -11,8 +11,8 @@ #define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLPASS_H #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" namespace llvm { @@ -23,7 +23,8 @@ struct LoopUnrollPass : public PassInfoMixin<LoopUnrollPass> { Optional<bool> ProvidedRuntime; Optional<bool> ProvidedUpperBound; - PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM); + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); }; } // end namespace llvm diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 845069d4260a4..27b45c4fa9416 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -29,6 +29,7 @@ class DataLayout; class DominatorTree; class Loop; class LoopInfo; +class OptimizationRemarkEmitter; class Pass; class PredicatedScalarEvolution; class PredIteratorCache; @@ -404,11 +405,11 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, /// uses before definitions, allowing us to sink a loop body in one pass without /// iteration. Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, /// DataLayout, TargetLibraryInfo, Loop, AliasSet information for all -/// instructions of the loop and loop safety information as arguments. -/// It returns changed status. +/// instructions of the loop and loop safety information as +/// arguments. Diagnostics is emitted via \p ORE. It returns changed status. bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, Loop *, AliasSetTracker *, - LoopSafetyInfo *); + LoopSafetyInfo *, OptimizationRemarkEmitter *ORE); /// \brief Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in depth @@ -416,10 +417,11 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, /// before uses, allowing us to hoist a loop body in one pass without iteration. /// Takes DomTreeNode, AliasAnalysis, LoopInfo, DominatorTree, DataLayout, /// TargetLibraryInfo, Loop, AliasSet information for all instructions of the -/// loop and loop safety information as arguments. It returns changed status. +/// loop and loop safety information as arguments. Diagnostics is emitted via \p +/// ORE. It returns changed status. bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, Loop *, AliasSetTracker *, - LoopSafetyInfo *); + LoopSafetyInfo *, OptimizationRemarkEmitter *ORE); /// \brief Try to promote memory values to scalars by sinking stores out of /// the loop and moving loads to before the loop. We do this by looping over @@ -427,12 +429,14 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, /// loop invariant. It takes AliasSet, Loop exit blocks vector, loop exit blocks /// insertion point vector, PredIteratorCache, LoopInfo, DominatorTree, Loop, /// AliasSet information for all instructions of the loop and loop safety -/// information as arguments. It returns changed status. +/// information as arguments. Diagnostics is emitted via \p ORE. It returns +/// changed status. bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock *> &, SmallVectorImpl<Instruction *> &, PredIteratorCache &, LoopInfo *, DominatorTree *, const TargetLibraryInfo *, - Loop *, AliasSetTracker *, LoopSafetyInfo *); + Loop *, AliasSetTracker *, LoopSafetyInfo *, + OptimizationRemarkEmitter *); /// \brief Computes safety information for a loop /// checks loop body & header for the possibility of may throw @@ -478,11 +482,12 @@ void getLoopAnalysisUsage(AnalysisUsage &AU); /// preheader to loop body (no speculation). /// If SafetyInfo is not null, we are checking for hoisting/sinking /// instructions from loop body to preheader/exit. Check if the instruction -/// can execute specultatively. -/// +/// can execute speculatively. +/// If \p ORE is set use it to emit optimization remarks. bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, Loop *CurLoop, AliasSetTracker *CurAST, - LoopSafetyInfo *SafetyInfo); + LoopSafetyInfo *SafetyInfo, + OptimizationRemarkEmitter *ORE = nullptr); } #endif diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index 2ea28f2d4e136..f322bea7aa2e8 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -33,6 +33,12 @@ class Pass; class OptimizationRemarkEmitter; class ScalarEvolution; +typedef SmallDenseMap<const Loop *, Loop *, 4> NewLoopsMap; + +const Loop* addClonedBlockToLoopInfo(BasicBlock *OriginalBB, + BasicBlock *ClonedBB, LoopInfo *LI, + NewLoopsMap &NewLoops); + bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool Force, bool AllowRuntime, bool AllowExpensiveTripCount, bool PreserveCondBr, bool PreserveOnlyFirst, diff --git a/include/llvm/Transforms/Vectorize/LoopVectorize.h b/include/llvm/Transforms/Vectorize/LoopVectorize.h index 2efc7ca4f8a1d..73d1f264c37b5 100644 --- a/include/llvm/Transforms/Vectorize/LoopVectorize.h +++ b/include/llvm/Transforms/Vectorize/LoopVectorize.h @@ -57,12 +57,12 @@ #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/LoopPassManager.h" #include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" #include <functional> namespace llvm { diff --git a/include/llvm/XRay/Trace.h b/include/llvm/XRay/Trace.h new file mode 100644 index 0000000000000..6b033d686b062 --- /dev/null +++ b/include/llvm/XRay/Trace.h @@ -0,0 +1,71 @@ +//===- Trace.h - XRay Trace Abstraction -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines the XRay Trace class representing records in an XRay trace file. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_XRAY_TRACE_H +#define LLVM_XRAY_TRACE_H + +#include <cstdint> +#include <vector> + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/XRay/XRayRecord.h" + +namespace llvm { +namespace xray { + +/// A Trace object represents the records that have been loaded from XRay +/// log files generated by instrumented binaries. We encapsulate the logic of +/// reading the traces in factory functions that populate the Trace object +/// appropriately. +/// +/// Trace objects provide an accessor to an XRayFileHeader which says more about +/// details of the file from which the XRay trace was loaded from. +/// +/// Usage: +/// +/// if (auto TraceOrErr = loadTraceFile("xray-log.something.xray")) { +/// auto& T = *TraceOrErr; +/// // T.getFileHeader() will provide information from the trace header. +/// for (const XRayRecord &R : T) { +/// // ... do something with R here. +/// } +/// } else { +/// // Handle the error here. +/// } +/// +class Trace { + XRayFileHeader FileHeader; + std::vector<XRayRecord> Records; + + typedef std::vector<XRayRecord>::const_iterator citerator; + + friend Expected<Trace> loadTraceFile(StringRef, bool); + +public: + /// Provides access to the loaded XRay trace file header. + const XRayFileHeader &getFileHeader() const { return FileHeader; } + + citerator begin() const { return Records.begin(); } + citerator end() const { return Records.end(); } + size_t size() const { return Records.size(); } +}; + +/// This function will attempt to load XRay trace records from the provided +/// |Filename|. +Expected<Trace> loadTraceFile(StringRef Filename, bool Sort = false); + +} // namespace xray +} // namespace llvm + +#endif // LLVM_XRAY_TRACE_H diff --git a/include/llvm/XRay/XRayRecord.h b/include/llvm/XRay/XRayRecord.h new file mode 100644 index 0000000000000..a96846136ec33 --- /dev/null +++ b/include/llvm/XRay/XRayRecord.h @@ -0,0 +1,76 @@ +//===- XRayRecord.h - XRay Trace Record -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file replicates the record definition for XRay log entries. This should +// follow the evolution of the log record versions supported in the compiler-rt +// xray project. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_XRAY_XRAY_RECORD_H +#define LLVM_XRAY_XRAY_RECORD_H + +#include <cstdint> + +namespace llvm { +namespace xray { + +/// XRay traces all have a header providing some top-matter information useful +/// to help tools determine how to interpret the information available in the +/// trace. +struct XRayFileHeader { + /// Version of the XRay implementation that produced this file. + uint16_t Version = 0; + + /// A numeric identifier for the type of file this is. Best used in + /// combination with Version. + uint16_t Type = 0; + + /// Whether the CPU that produced the timestamp counters (TSC) move at a + /// constant rate. + bool ConstantTSC; + + /// Whether the CPU that produced the timestamp counters (TSC) do not stop. + bool NonstopTSC; + + /// The number of cycles per second for the CPU that produced the timestamp + /// counter (TSC) values. Useful for estimating the amount of time that + /// elapsed between two TSCs on some platforms. + uint64_t CycleFrequency = 0; +}; + +/// Determines the supported types of records that could be seen in XRay traces. +/// This may or may not correspond to actual record types in the raw trace (as +/// the loader implementation may synthesize this information in the process of +/// of loading). +enum class RecordTypes { ENTER, EXIT }; + +struct XRayRecord { + /// The type of record. + uint16_t RecordType; + + /// The CPU where the thread is running. We assume number of CPUs <= 256. + uint8_t CPU; + + /// Identifies the type of record. + RecordTypes Type; + + /// The function ID for the record. + int32_t FuncId; + + /// Get the full 8 bytes of the TSC when we get the log record. + uint64_t TSC; + + /// The thread ID for the currently running thread. + uint32_t TId; +}; + +} // namespace xray +} // namespace llvm + +#endif // LLVM_XRAY_XRAY_RECORD_H diff --git a/include/llvm/XRay/YAMLXRayRecord.h b/include/llvm/XRay/YAMLXRayRecord.h new file mode 100644 index 0000000000000..f5836b3922421 --- /dev/null +++ b/include/llvm/XRay/YAMLXRayRecord.h @@ -0,0 +1,99 @@ +//===- YAMLXRayRecord.h - XRay Record YAML Support Definitions ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Types and traits specialisations for YAML I/O of XRay log entries. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_XRAY_YAML_XRAY_RECORD_H +#define LLVM_XRAY_YAML_XRAY_RECORD_H + +#include <type_traits> + +#include "llvm/Support/YAMLTraits.h" +#include "llvm/XRay/XRayRecord.h" + +namespace llvm { +namespace xray { + +struct YAMLXRayFileHeader { + uint16_t Version; + uint16_t Type; + bool ConstantTSC; + bool NonstopTSC; + uint64_t CycleFrequency; +}; + +struct YAMLXRayRecord { + uint16_t RecordType; + uint8_t CPU; + RecordTypes Type; + int32_t FuncId; + std::string Function; + uint64_t TSC; + uint32_t TId; +}; + +struct YAMLXRayTrace { + YAMLXRayFileHeader Header; + std::vector<YAMLXRayRecord> Records; +}; + +} // namespace xray + +namespace yaml { + +// YAML Traits +// ----------- +template <> struct ScalarEnumerationTraits<xray::RecordTypes> { + static void enumeration(IO &IO, xray::RecordTypes &Type) { + IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER); + IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT); + } +}; + +template <> struct MappingTraits<xray::YAMLXRayFileHeader> { + static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) { + IO.mapRequired("version", Header.Version); + IO.mapRequired("type", Header.Type); + IO.mapRequired("constant-tsc", Header.ConstantTSC); + IO.mapRequired("nonstop-tsc", Header.NonstopTSC); + IO.mapRequired("cycle-frequency", Header.CycleFrequency); + } +}; + +template <> struct MappingTraits<xray::YAMLXRayRecord> { + static void mapping(IO &IO, xray::YAMLXRayRecord &Record) { + // FIXME: Make this type actually be descriptive + IO.mapRequired("type", Record.RecordType); + IO.mapRequired("func-id", Record.FuncId); + IO.mapOptional("function", Record.Function); + IO.mapRequired("cpu", Record.CPU); + IO.mapRequired("thread", Record.TId); + IO.mapRequired("kind", Record.Type); + IO.mapRequired("tsc", Record.TSC); + } + + static constexpr bool flow = true; +}; + +template <> struct MappingTraits<xray::YAMLXRayTrace> { + static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) { + // A trace file contains two parts, the header and the list of all the + // trace records. + IO.mapRequired("header", Trace.Header); + IO.mapRequired("records", Trace.Records); + } +}; + +} // namespace yaml +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord) + +#endif // LLVM_XRAY_YAML_XRAY_RECORD_H |