diff options
Diffstat (limited to 'include')
24 files changed, 516 insertions, 244 deletions
diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 54ef1a688d37..6fbe532112b2 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -128,7 +128,7 @@ extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, /// \brief The CGSCC pass manager. /// /// See the documentation for the PassManager template for details. It runs -/// a sequency of SCC passes over each SCC that the manager is run over. This +/// a sequence of SCC passes over each SCC that the manager is run over. This /// typedef serves as a convenient way to refer to this construct. typedef PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, CGSCCUpdateResult &> diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index d583614284ff..b4a6c5c2fae0 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -36,6 +36,8 @@ namespace llvm { class Function; class GlobalValue; class Loop; +class ScalarEvolution; +class SCEV; class Type; class User; class Value; @@ -613,10 +615,11 @@ public: /// merged into the instruction indexing mode. Some targets might want to /// distinguish between address computation for memory operations on vector /// types and scalar types. Such targets should override this function. - /// The 'IsComplex' parameter is a hint that the address computation is likely - /// to involve multiple instructions and as such unlikely to be merged into - /// the address indexing mode. - int getAddressComputationCost(Type *Ty, bool IsComplex = false) const; + /// The 'SE' parameter holds pointer for the scalar evolution object which + /// is used in order to get the Ptr step value in case of constant stride. + /// The 'Ptr' parameter holds SCEV of the access pointer. + int getAddressComputationCost(Type *Ty, ScalarEvolution *SE = nullptr, + const SCEV *Ptr = nullptr) const; /// \returns The cost, if any, of keeping values of the given types alive /// over a callsite. @@ -795,7 +798,8 @@ public: virtual int getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) = 0; virtual unsigned getNumberOfParts(Type *Tp) = 0; - virtual int getAddressComputationCost(Type *Ty, bool IsComplex) = 0; + virtual int getAddressComputationCost(Type *Ty, ScalarEvolution *SE, + const SCEV *Ptr) = 0; virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0; virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) = 0; @@ -1044,8 +1048,9 @@ public: unsigned getNumberOfParts(Type *Tp) override { return Impl.getNumberOfParts(Tp); } - int getAddressComputationCost(Type *Ty, bool IsComplex) override { - return Impl.getAddressComputationCost(Ty, IsComplex); + int getAddressComputationCost(Type *Ty, ScalarEvolution *SE, + const SCEV *Ptr) override { + return Impl.getAddressComputationCost(Ty, SE, Ptr); } unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) override { return Impl.getCostOfKeepingLiveOverCall(Tys); diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 68b38a7fa538..1d7edbaf7df0 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -15,6 +15,7 @@ #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H +#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" @@ -370,7 +371,10 @@ public: unsigned getNumberOfParts(Type *Tp) { return 0; } - unsigned getAddressComputationCost(Type *Tp, bool) { return 0; } + unsigned getAddressComputationCost(Type *Tp, ScalarEvolution *, + const SCEV *) { + return 0; + } unsigned getReductionCost(unsigned, Type *, bool) { return 1; } @@ -422,6 +426,30 @@ public: VectorType *VecTy) const { return VF; } +protected: + bool isStridedAccess(const SCEV *Ptr) { + return Ptr && isa<SCEVAddRecExpr>(Ptr); + } + + const SCEVConstant *getConstantStrideStep(ScalarEvolution *SE, + const SCEV *Ptr) { + if (!isStridedAccess(Ptr)) + return nullptr; + const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ptr); + return dyn_cast<SCEVConstant>(AddRec->getStepRecurrence(*SE)); + } + + bool isConstantStridedAccessLessThan(ScalarEvolution *SE, const SCEV *Ptr, + int64_t MergeDistance) { + const SCEVConstant *Step = getConstantStrideStep(SE, Ptr); + if (!Step) + return false; + APInt StrideVal = Step->getAPInt(); + if (StrideVal.getBitWidth() > 64) + return false; + // FIXME: need to take absolute value for negtive stride case + return StrideVal.getSExtValue() < MergeDistance; + } }; /// \brief CRTP base class for use as a mix-in that aids implementing diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index cfc7a1d7d6bd..bf21e146e771 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -18,7 +18,6 @@ #ifndef LLVM_BITCODE_BITCODES_H #define LLVM_BITCODE_BITCODES_H -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -166,11 +165,8 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; }; /// BitCodeAbbrev - This class represents an abbreviation record. An /// abbreviation allows a complex record that has redundancy to be stored in a /// specialized format instead of the fully-general, fully-vbr, format. -class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> { +class BitCodeAbbrev { SmallVector<BitCodeAbbrevOp, 32> OperandList; - // Only RefCountedBase is allowed to delete. - ~BitCodeAbbrev() = default; - friend class RefCountedBase<BitCodeAbbrev>; public: unsigned getNumOperandInfos() const { diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 4d95a6ce8a16..fc06eeefbf26 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -16,7 +16,6 @@ #define LLVM_BITCODE_BITSTREAMREADER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/Endian.h" @@ -42,7 +41,7 @@ public: /// describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; std::string Name; std::vector<std::pair<unsigned, std::string> > RecordNames; }; @@ -316,11 +315,11 @@ class BitstreamCursor : SimpleBitstreamCursor { unsigned CurCodeSize = 2; /// Abbrevs installed at in this block. - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; struct Block { unsigned PrevCodeSize; - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} }; @@ -478,8 +477,8 @@ public: return CurAbbrevs[AbbrevNo].get(); } - /// Read the current record and discard it. - void skipRecord(unsigned AbbrevID); + /// Read the current record and discard it, returning the code for the record. + unsigned skipRecord(unsigned AbbrevID); unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, StringRef *Blob = nullptr); diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 8eb6e8aef7a2..e276db5f92f6 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -43,12 +43,12 @@ class BitstreamWriter { unsigned BlockInfoCurBID; /// CurAbbrevs - Abbrevs installed at in this block. - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; struct Block { unsigned PrevCodeSize; size_t StartSizeWord; - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; @@ -59,7 +59,7 @@ class BitstreamWriter { /// These describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; + std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; }; std::vector<BlockInfo> BlockInfoRecords; @@ -469,12 +469,12 @@ public: private: // Emit the abbreviation as a DEFINE_ABBREV record. - void EncodeAbbrev(BitCodeAbbrev *Abbv) { + void EncodeAbbrev(const BitCodeAbbrev &Abbv) { EmitCode(bitc::DEFINE_ABBREV); - EmitVBR(Abbv->getNumOperandInfos(), 5); - for (unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); + EmitVBR(Abbv.getNumOperandInfos(), 5); + for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos()); i != e; ++i) { - const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i); Emit(Op.isLiteral(), 1); if (Op.isLiteral()) { EmitVBR64(Op.getLiteralValue(), 8); @@ -489,10 +489,10 @@ public: /// EmitAbbrev - This emits an abbreviation to the stream. Note that this /// method takes ownership of the specified abbrev. - unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) { // Emit the abbreviation as a record. - EncodeAbbrev(Abbv); - CurAbbrevs.push_back(Abbv); + EncodeAbbrev(*Abbv); + CurAbbrevs.push_back(std::move(Abbv)); return static_cast<unsigned>(CurAbbrevs.size())-1 + bitc::FIRST_APPLICATION_ABBREV; } @@ -532,13 +532,13 @@ public: /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified /// BlockID. - unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) { + unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) { SwitchToBlockID(BlockID); - EncodeAbbrev(Abbv); + EncodeAbbrev(*Abbv); // Add the abbrev to the specified block record. BlockInfo &Info = getOrCreateBlockInfo(BlockID); - Info.Abbrevs.push_back(Abbv); + Info.Abbrevs.push_back(std::move(Abbv)); return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; } diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index be8822df3dba..f0be955110fb 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -140,6 +140,9 @@ private: /// If the target supports dwarf debug info, this pointer is non-null. DwarfDebug *DD; + /// If the current module uses dwarf CFI annotations strictly for debugging. + bool isCFIMoveForDebugging; + protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); @@ -262,6 +265,10 @@ public: enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); + /// Returns false if needsCFIMoves() == CFI_M_EH for any function + /// in the module. + bool needsOnlyDebugCFIMoves() const { return isCFIMoveForDebugging; } + bool needsSEHMoves(); /// Print to the current output stream assembly representations of the diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index df0dc1a38ae7..8e96336b981f 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -925,7 +925,10 @@ public: return LT.first; } - unsigned getAddressComputationCost(Type *Ty, bool IsComplex) { return 0; } + unsigned getAddressComputationCost(Type *Ty, ScalarEvolution *, + const SCEV *) { + return 0; + } unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwise) { assert(Ty->isVectorTy() && "Expect a vector type"); diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index 1e3476cd8395..09c3bf6a1b56 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -651,6 +651,9 @@ class DIE : IntrusiveBackListNode, public DIEValueList { unsigned AbbrevNumber = ~0u; /// Dwarf tag code. dwarf::Tag Tag = (dwarf::Tag)0; + /// Set to true to force a DIE to emit an abbreviation that says it has + /// children even when it doesn't. This is used for unit testing purposes. + bool ForceChildren; /// Children DIEs. IntrusiveBackList<DIE> Children; @@ -659,7 +662,8 @@ class DIE : IntrusiveBackListNode, public DIEValueList { PointerUnion<DIE *, DIEUnit *> Owner; DIE() = delete; - explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag) {} + explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag), + ForceChildren(false) {} public: static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) { @@ -677,7 +681,8 @@ public: /// Get the compile/type unit relative offset of this DIE. unsigned getOffset() const { return Offset; } unsigned getSize() const { return Size; } - bool hasChildren() const { return !Children.empty(); } + bool hasChildren() const { return ForceChildren || !Children.empty(); } + void setForceChildren(bool B) { ForceChildren = B; } typedef IntrusiveBackList<DIE>::iterator child_iterator; typedef IntrusiveBackList<DIE>::const_iterator const_child_iterator; diff --git a/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 76e0d47ceea3..26ba5c67beb5 100644 --- a/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -180,6 +180,8 @@ private: /// \pre \p U is a branch instruction. bool translateBr(const User &U, MachineIRBuilder &MIRBuilder); + bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder); + bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder); bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder); @@ -292,12 +294,8 @@ private: return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder); } - // Stubs to keep the compiler happy while we implement the rest of the // translation. - bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) { return false; } diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index be811c6fe437..92a9896d7a18 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -308,7 +308,7 @@ public: // Iteration support for live in sets. These sets are kept in sorted // order by their register number. typedef LiveInVector::const_iterator livein_iterator; - livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_begin() const; livein_iterator livein_end() const { return LiveIns.end(); } bool livein_empty() const { return LiveIns.empty(); } iterator_range<livein_iterator> liveins() const { diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h index f33758de6a55..5a24b7c87299 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -10,6 +10,8 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFDIE_H #define LLVM_LIB_DEBUGINFO_DWARFDIE_H +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" @@ -40,9 +42,6 @@ public: bool isValid() const { return U && Die; } explicit operator bool() const { return isValid(); } - bool operator ==(const DWARFDie &RHS) const { - return Die == RHS.Die && U == RHS.U; - } const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } DWARFUnit *getDwarfUnit() const { return U; } @@ -361,8 +360,61 @@ public: getInlinedChainForAddress(const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const; + class iterator; + + iterator begin() const; + iterator end() const; + iterator_range<iterator> children() const; }; + +inline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { + return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && + LHS.getDwarfUnit() == RHS.getDwarfUnit(); +} + +inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { + return !(LHS == RHS); +} + +class DWARFDie::iterator : public iterator_facade_base<iterator, + std::forward_iterator_tag, + const DWARFDie> { + DWARFDie Die; + void skipNull() { + if (Die && Die.isNULL()) + Die = DWARFDie(); + } +public: + iterator() = default; + explicit iterator(DWARFDie D) : Die(D) { + // If we start out with only a Null DIE then invalidate. + skipNull(); + } + iterator &operator++() { + Die = Die.getSibling(); + // Don't include the NULL die when iterating. + skipNull(); + return *this; + } + explicit operator bool() const { return Die.isValid(); } + const DWARFDie &operator*() const { return Die; } + bool operator==(const iterator &X) const { return Die == X.Die; } +}; + +// These inline functions must follow the DWARFDie::iterator definition above +// as they use functions from that class. +inline DWARFDie::iterator DWARFDie::begin() const { + return iterator(getFirstChild()); +} + +inline DWARFDie::iterator DWARFDie::end() const { + return iterator(); +} + +inline iterator_range<DWARFDie::iterator> DWARFDie::children() const { + return make_range(begin(), end()); +} } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h index 43b597de000f..83a7b9a844f2 100644 --- a/include/llvm/ExecutionEngine/Orc/RawByteChannel.h +++ b/include/llvm/ExecutionEngine/Orc/RawByteChannel.h @@ -47,9 +47,9 @@ public: /// Locks the channel for writing. template <typename FunctionIdT, typename SequenceIdT> Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) { + writeLock.lock(); if (auto Err = serializeSeq(*this, FnId, SeqNo)) return Err; - writeLock.lock(); return Error::success(); } diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index 2cfe673d970f..ecb0435a1e11 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -28,6 +28,10 @@ namespace llvm { +namespace yaml { +template <typename T> struct MappingTraits; +} + /// \brief Class to accumulate and hold information about a callee. struct CalleeInfo { enum class HotnessType : uint8_t { Unknown = 0, Cold = 1, None = 2, Hot = 3 }; @@ -102,7 +106,7 @@ public: /// \brief Sububclass discriminator (for dyn_cast<> et al.) enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind }; - /// Group flags (Linkage, noRename, isOptSize, etc.) as a bitfield. + /// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield. struct GVFlags { /// \brief The linkage type of the associated global value. /// @@ -113,39 +117,20 @@ public: /// types based on global summary-based analysis. unsigned Linkage : 4; - /// Indicate if the global value cannot be renamed (in a specific section, - /// possibly referenced from inline assembly, etc). - unsigned NoRename : 1; - - /// Indicate if a function contains inline assembly (which is opaque), - /// that may reference a local value. This is used to prevent importing - /// of this function, since we can't promote and rename the uses of the - /// local in the inline assembly. Use a flag rather than bloating the - /// summary with references to every possible local value in the - /// llvm.used set. - unsigned HasInlineAsmMaybeReferencingInternal : 1; + /// Indicate if the global value cannot be imported (e.g. it cannot + /// be renamed or references something that can't be renamed). + unsigned NotEligibleToImport : 1; - /// Indicate if the function is not viable to inline. - unsigned IsNotViableToInline : 1; + /// Indicate that the global value must be considered a live root for + /// index-based liveness analysis. Used for special LLVM values such as + /// llvm.global_ctors that the linker does not know about. + unsigned LiveRoot : 1; /// Convenience Constructors - explicit GVFlags(GlobalValue::LinkageTypes Linkage, bool NoRename, - bool HasInlineAsmMaybeReferencingInternal, - bool IsNotViableToInline) - : Linkage(Linkage), NoRename(NoRename), - HasInlineAsmMaybeReferencingInternal( - HasInlineAsmMaybeReferencingInternal), - IsNotViableToInline(IsNotViableToInline) {} - - GVFlags(const GlobalValue &GV) - : Linkage(GV.getLinkage()), NoRename(GV.hasSection()), - HasInlineAsmMaybeReferencingInternal(false) { - IsNotViableToInline = false; - if (const auto *F = dyn_cast<Function>(&GV)) - // Inliner doesn't handle variadic functions. - // FIXME: refactor this to use the same code that inliner is using. - IsNotViableToInline = F->isVarArg(); - } + explicit GVFlags(GlobalValue::LinkageTypes Linkage, + bool NotEligibleToImport, bool LiveRoot) + : Linkage(Linkage), NotEligibleToImport(NotEligibleToImport), + LiveRoot(LiveRoot) {} }; private: @@ -213,31 +198,19 @@ public: Flags.Linkage = Linkage; } - bool isNotViableToInline() const { return Flags.IsNotViableToInline; } - - /// Return true if this summary is for a GlobalValue that needs promotion - /// to be referenced from another module. - bool needsRenaming() const { return GlobalValue::isLocalLinkage(linkage()); } + /// Return true if this global value can't be imported. + bool notEligibleToImport() const { return Flags.NotEligibleToImport; } - /// Return true if this global value cannot be renamed (in a specific section, - /// possibly referenced from inline assembly, etc). - bool noRename() const { return Flags.NoRename; } + /// Return true if this global value must be considered a root for live + /// value analysis on the index. + bool liveRoot() const { return Flags.LiveRoot; } - /// Flag that this global value cannot be renamed (in a specific section, - /// possibly referenced from inline assembly, etc). - void setNoRename() { Flags.NoRename = true; } + /// Flag that this global value must be considered a root for live + /// value analysis on the index. + void setLiveRoot() { Flags.LiveRoot = true; } - /// Return true if this global value possibly references another value - /// that can't be renamed. - bool hasInlineAsmMaybeReferencingInternal() const { - return Flags.HasInlineAsmMaybeReferencingInternal; - } - - /// Flag that this global value possibly references another value that - /// can't be renamed. - void setHasInlineAsmMaybeReferencingInternal() { - Flags.HasInlineAsmMaybeReferencingInternal = true; - } + /// Flag that this global value cannot be imported. + void setNotEligibleToImport() { Flags.NotEligibleToImport = true; } /// Return the list of values referenced by this global value definition. ArrayRef<ValueInfo> refs() const { return RefEdgeList; } @@ -330,6 +303,30 @@ public: } }; +struct TypeTestResolution { + /// Specifies which kind of type check we should emit for this byte array. + /// See http://clang.llvm.org/docs/ControlFlowIntegrityDesign.html for full + /// details on each kind of check; the enumerators are described with + /// reference to that document. + enum Kind { + Unsat, ///< Unsatisfiable type (i.e. no global has this type metadata) + ByteArray, ///< Test a byte array (first example) + Inline, ///< Inlined bit vector ("Short Inline Bit Vectors") + Single, ///< Single element (last example in "Short Inline Bit Vectors") + AllOnes, ///< All-ones bit vector ("Eliminating Bit Vector Checks for + /// 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 + /// instruction sequences. + unsigned SizeBitWidth = 0; +}; + +struct TypeIdSummary { + TypeTestResolution TTRes; +}; + /// 160 bits SHA1 typedef std::array<uint32_t, 5> ModuleHash; @@ -370,11 +367,20 @@ private: /// Holds strings for combined index, mapping to the corresponding module ID. ModulePathStringTableTy ModulePathStringTable; + /// Mapping from type identifiers to summary information for that type + /// identifier. + // FIXME: Add bitcode read/write support for this field. + std::map<std::string, TypeIdSummary> TypeIdMap; + + // YAML I/O support. + friend yaml::MappingTraits<ModuleSummaryIndex>; + public: gvsummary_iterator begin() { return GlobalValueMap.begin(); } const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } gvsummary_iterator end() { return GlobalValueMap.end(); } const_gvsummary_iterator end() const { return GlobalValueMap.end(); } + size_t size() const { return GlobalValueMap.size(); } /// Get the list of global value summary objects for a given value name. const GlobalValueSummaryList &getGlobalValueSummaryList(StringRef ValueName) { diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h new file mode 100644 index 000000000000..a8c8ff9ef2eb --- /dev/null +++ b/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -0,0 +1,111 @@ +//===-- llvm/ModuleSummaryIndexYAML.h - YAML I/O for summary ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_MODULESUMMARYINDEXYAML_H +#define LLVM_IR_MODULESUMMARYINDEXYAML_H + +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace yaml { + +template <> struct ScalarEnumerationTraits<TypeTestResolution::Kind> { + static void enumeration(IO &io, TypeTestResolution::Kind &value) { + io.enumCase(value, "Unsat", TypeTestResolution::Unsat); + io.enumCase(value, "ByteArray", TypeTestResolution::ByteArray); + io.enumCase(value, "Inline", TypeTestResolution::Inline); + io.enumCase(value, "Single", TypeTestResolution::Single); + io.enumCase(value, "AllOnes", TypeTestResolution::AllOnes); + } +}; + +template <> struct MappingTraits<TypeTestResolution> { + static void mapping(IO &io, TypeTestResolution &res) { + io.mapRequired("Kind", res.TheKind); + io.mapRequired("SizeBitWidth", res.SizeBitWidth); + } +}; + +template <> struct MappingTraits<TypeIdSummary> { + static void mapping(IO &io, TypeIdSummary& summary) { + io.mapRequired("TTRes", summary.TTRes); + } +}; + +struct FunctionSummaryYaml { + std::vector<uint64_t> TypeTests; +}; + +} // End yaml namespace +} // End llvm namespace + +LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits<FunctionSummaryYaml> { + static void mapping(IO &io, FunctionSummaryYaml& summary) { + io.mapRequired("TypeTests", summary.TypeTests); + } +}; + +} // End yaml namespace +} // End llvm namespace + +LLVM_YAML_IS_STRING_MAP(TypeIdSummary) +LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml) + +namespace llvm { +namespace yaml { + +// FIXME: Add YAML mappings for the rest of the module summary. +template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { + static void inputOne(IO &io, StringRef Key, GlobalValueSummaryMapTy &V) { + std::vector<FunctionSummaryYaml> FSums; + io.mapRequired(Key.str().c_str(), FSums); + uint64_t KeyInt; + if (Key.getAsInteger(0, KeyInt)) { + io.setError("key not an integer"); + return; + } + auto &Elem = V[KeyInt]; + for (auto &FSum : FSums) { + GlobalValueSummary::GVFlags GVFlags(GlobalValue::ExternalLinkage, false, + false); + Elem.push_back(llvm::make_unique<FunctionSummary>( + GVFlags, 0, ArrayRef<ValueInfo>{}, + ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests))); + } + } + static void output(IO &io, GlobalValueSummaryMapTy &V) { + for (auto &P : V) { + std::vector<FunctionSummaryYaml> FSums; + for (auto &Sum : P.second) { + if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) + FSums.push_back(FunctionSummaryYaml{FSum->type_tests()}); + } + if (!FSums.empty()) + io.mapRequired(llvm::utostr(P.first).c_str(), FSums); + } + } +}; + +template <> struct MappingTraits<ModuleSummaryIndex> { + static void mapping(IO &io, ModuleSummaryIndex& index) { + io.mapRequired("GlobalValueMap", index.GlobalValueMap); + io.mapRequired("TypeIdMap", index.TypeIdMap); + } +}; + +} // End yaml namespace +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 3e4edd893d3c..7a63956f1cdb 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -64,32 +64,31 @@ namespace llvm { struct alignas(8) AnalysisKey {}; /// A special type used to provide an address that identifies a set of related -/// analyses. +/// analyses. These sets are primarily used below to mark sets of analyses as +/// preserved. /// -/// These sets are primarily used below to mark sets of analyses as preserved. -/// An example would be analyses depending only on the CFG of a function. -/// A transformation can mark that it is preserving the CFG of a function and -/// then analyses can check for this rather than each transform having to fully -/// enumerate every analysis preserved. +/// For example, a transformation can indicate that it preserves the CFG of a +/// function by preserving the appropriate AnalysisSetKey. An analysis that +/// depends only on the CFG can then check if that AnalysisSetKey is preserved; +/// if it is, the analysis knows that it itself is preserved. struct alignas(8) AnalysisSetKey {}; -/// Class for tracking what analyses are preserved after a transformation pass -/// runs over some unit of IR. +/// A set of analyses that are preserved following a run of a transformation +/// pass. /// -/// Transformation passes build and return these objects when run over the IR -/// to communicate which analyses remain valid afterward. For most passes this -/// is fairly simple: if they don't change anything all analyses are preserved, +/// Transformation passes build and return these objects to communicate which +/// analyses are still valid after the transformation. For most passes this is +/// fairly simple: if they don't change anything all analyses are preserved, /// otherwise only a short list of analyses that have been explicitly updated /// are preserved. /// -/// This class also provides the ability to mark abstract *sets* of analyses as -/// preserved. These sets allow passes to indicate that they preserve broad -/// aspects of the IR (such as its CFG) and analyses to opt in to that being -/// sufficient without the passes having to fully enumerate such analyses. +/// This class also lets transformation passes mark abstract *sets* of analyses +/// as preserved. A transformation that (say) does not alter the CFG can +/// indicate such by marking a particular AnalysisSetKey as preserved, and +/// then analyses can query whether that AnalysisSetKey is preserved. /// -/// Finally, this class can represent "abandoning" an analysis, which marks it -/// as not-preserved even if it would be covered by some abstract set of -/// analyses. +/// Finally, this class can represent an "abandoned" analysis, which is +/// not preserved even if it would be covered by some abstract set of analyses. /// /// Given a `PreservedAnalyses` object, an analysis will typically want to /// figure out whether it is preserved. In the example below, MyAnalysisType is @@ -120,7 +119,8 @@ public: /// Mark an analysis as preserved. template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); } - /// Mark an analysis as preserved using its ID. + /// \brief Given an analysis's ID, mark the analysis as preserved, adding it + /// to the set. void preserve(AnalysisKey *ID) { // Clear this ID from the explicit not-preserved set if present. NotPreservedAnalysisIDs.erase(ID); @@ -224,17 +224,17 @@ public: : PA(PA), ID(ID), IsAbandoned(PA.NotPreservedAnalysisIDs.count(ID)) {} public: - /// Returns true if the checker's analysis was not abandoned and the - /// analysis is either is explicitly preserved or all analyses are - /// preserved. + /// Returns true if the checker's analysis was not abandoned and either + /// - the analysis is explicitly preserved or + /// - all analyses are preserved. bool preserved() { return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || PA.PreservedIDs.count(ID)); } - /// Returns true if the checker's analysis was not abandoned and either the - /// provided set type is either explicitly preserved or all analyses are - /// preserved. + /// Returns true if the checker's analysis was not abandoned and either + /// - \p AnalysisSetT is explicitly preserved or + /// - all analyses are preserved. template <typename AnalysisSetT> bool preservedSet() { AnalysisSetKey *SetID = AnalysisSetT::ID(); return !IsAbandoned && (PA.PreservedIDs.count(&AllAnalysesKey) || @@ -262,8 +262,8 @@ public: /// Test whether all analyses are preserved (and none are abandoned). /// - /// This lets analyses optimize for the common case where a transformation - /// made no changes to the IR. + /// This is used primarily to optimize for the common case of a transformation + /// which makes no changes to the IR. bool areAllPreserved() const { return NotPreservedAnalysisIDs.empty() && PreservedIDs.count(&AllAnalysesKey); @@ -307,9 +307,9 @@ template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; /// A CRTP mix-in to automatically provide informational APIs needed for /// passes. /// -/// This provides some boiler plate for types that are passes. +/// This provides some boilerplate for types that are passes. template <typename DerivedT> struct PassInfoMixin { - /// Returns the name of the derived pass type. + /// Gets the name of the pass we are mixed into. static StringRef name() { StringRef Name = getTypeName<DerivedT>(); if (Name.startswith("llvm::")) @@ -318,41 +318,35 @@ template <typename DerivedT> struct PassInfoMixin { } }; -/// A CRTP mix-in to automatically provide informational APIs needed for -/// analysis passes. +/// A CRTP mix-in that provides informational APIs needed for analysis passes. /// -/// This provides some boiler plate for types that are analysis passes. It -/// automatically mixes in \c PassInfoMixin and adds informational APIs -/// specifically used for analyses. +/// This provides some boilerplate for types that are analysis passes. It +/// automatically mixes in \c PassInfoMixin. template <typename DerivedT> struct AnalysisInfoMixin : PassInfoMixin<DerivedT> { /// Returns an opaque, unique ID for this analysis type. /// - /// This ID is a pointer type that is guaranteed to be 8-byte aligned and - /// thus suitable for use in sets, maps, and other data structures optimized - /// for pointer-like types using the alignment-provided low bits. + /// This ID is a pointer type that is guaranteed to be 8-byte aligned and thus + /// suitable for use in sets, maps, and other data structures that use the low + /// bits of pointers. /// /// Note that this requires the derived type provide a static \c AnalysisKey /// member called \c Key. /// - /// FIXME: The only reason the derived type needs to provide this rather than - /// this mixin providing it is due to broken implementations which cannot - /// correctly unique a templated static so that they have the same addresses - /// for each instantiation and are definitively emitted once for each - /// instantiation. The only currently known platform with this limitation are - /// Windows DLL builds, specifically building each part of LLVM as a DLL. If - /// we ever remove that build configuration, this mixin can provide the - /// static key as well. + /// FIXME: The only reason the mixin type itself can't declare the Key value + /// is that some compilers cannot correctly unique a templated static variable + /// so it has the same addresses in each instantiation. The only currently + /// known platform with this limitation is Windows DLL builds, specifically + /// building each part of LLVM as a DLL. If we ever remove that build + /// configuration, this mixin can provide the static key as well. static AnalysisKey *ID() { return &DerivedT::Key; } }; -/// A class template to provide analysis sets for IR units. +/// This templated class represents "all analyses that operate over \<a +/// particular IR unit\>" (e.g. a Function or a Module) in instances of +/// PreservedAnalysis. /// -/// Analyses operate on units of IR. It is useful to be able to talk about -/// preservation of all analyses for a given unit of IR as a set. This class -/// template can be used with the \c PreservedAnalyses API for that purpose and -/// the \c AnalysisManager will automatically check and use this set to skip -/// invalidation events. +/// This lets a transformation say e.g. "I preserved all function analyses". /// /// Note that you must provide an explicit instantiation declaration and /// definition for this template in order to get the correct behavior on @@ -371,17 +365,18 @@ template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey; extern template class AllAnalysesOn<Module>; extern template class AllAnalysesOn<Function>; -/// \brief Manages a sequence of passes over units of IR. +/// \brief Manages a sequence of passes over a particular unit of IR. /// -/// A pass manager contains a sequence of passes to run over units of IR. It is -/// itself a valid pass over that unit of IR, and when over some given IR will -/// run each pass in sequence. This is the primary and most basic building -/// block of a pass pipeline. +/// A pass manager contains a sequence of passes to run over a particular unit +/// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of +/// IR, and when run over some given IR will run each of its contained passes in +/// sequence. Pass managers are the primary and most basic building block of a +/// pass pipeline. /// -/// If it is run with an \c AnalysisManager<IRUnitT> argument, it will propagate -/// that analysis manager to each pass it runs, as well as calling the analysis -/// manager's invalidation routine with the PreservedAnalyses of each pass it -/// runs. +/// When you run a pass manager, you provide an \c AnalysisManager<IRUnitT> +/// argument. The pass manager will propagate that analysis manager to each +/// pass it runs, and will call the analysis manager's invalidation routine with +/// the PreservedAnalyses of each pass it runs. template <typename IRUnitT, typename AnalysisManagerT = AnalysisManager<IRUnitT>, typename... ExtraArgTs> @@ -390,7 +385,7 @@ class PassManager : public PassInfoMixin< public: /// \brief Construct a pass manager. /// - /// It can be passed a flag to get debug logging as the passes are run. + /// If \p DebugLogging is true, we'll log our progress to llvm::dbgs(). explicit PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // FIXME: These are equivalent to the default move constructor/move @@ -400,13 +395,15 @@ public: PassManager(PassManager &&Arg) : Passes(std::move(Arg.Passes)), DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { Passes = std::move(RHS.Passes); DebugLogging = std::move(RHS.DebugLogging); return *this; } - /// \brief Run all of the passes in this manager over the IR. + /// \brief Run all of the passes in this manager over the given unit of IR. + /// ExtraArgs are passed to each pass. PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) { PreservedAnalyses PA = PreservedAnalyses::all(); @@ -425,7 +422,7 @@ public: // invalidates analyses. AM.invalidate(IR, PassPA); - // Finally, we intersect the preserved analyses to compute the aggregate + // Finally, intersect the preserved analyses to compute the aggregate // preserved set for this pass manager. PA.intersect(std::move(PassPA)); @@ -473,30 +470,29 @@ extern template class PassManager<Function>; /// \brief Convenience typedef for a pass manager over functions. typedef PassManager<Function> FunctionPassManager; -/// \brief A generic analysis pass manager with lazy running and caching of +/// \brief A container for analyses that lazily runs them and caches their /// results. /// -/// This analysis manager can be used for any IR unit where the address of the -/// IR unit sufficies as its identity. It manages the cache for a unit of IR via -/// the address of each unit of IR cached. +/// This class can manage analyses for any IR unit where the address of the IR +/// unit sufficies as its identity. template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager { public: class Invalidator; private: - // Now that we've defined our invalidator, we can build types for the concept - // types. + // Now that we've defined our invalidator, we can define the concept types. typedef detail::AnalysisResultConcept<IRUnitT, PreservedAnalyses, Invalidator> ResultConceptT; typedef detail::AnalysisPassConcept<IRUnitT, PreservedAnalyses, Invalidator, ExtraArgTs...> PassConceptT; - /// \brief List of function analysis pass IDs and associated concept pointers. + /// \brief List of analysis pass IDs and associated concept pointers. /// /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides the analysis ID to enable finding iterators to a given entry - /// in maps below, and provides the storage for the actual result concept. + /// erases. Provides the analysis ID to enable finding iterators to a given + /// entry in maps below, and provides the storage for the actual result + /// concept. typedef std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>> AnalysisResultListT; @@ -504,8 +500,8 @@ private: typedef DenseMap<IRUnitT *, AnalysisResultListT> AnalysisResultListMapT; /// \brief Map type from a pair of analysis ID and IRUnitT pointer to an - /// iterator into a particular result list which is where the actual result - /// is stored. + /// iterator into a particular result list (which is where the actual analysis + /// result is stored). typedef DenseMap<std::pair<AnalysisKey *, IRUnitT *>, typename AnalysisResultListT::iterator> AnalysisResultMapT; @@ -515,28 +511,28 @@ public: /// /// When an analysis result embeds handles to other analysis results, it /// needs to be invalidated both when its own information isn't preserved and - /// if any of those embedded analysis results end up invalidated. We pass in - /// an \c Invalidator object from the analysis manager in order to let the - /// analysis results themselves define the dependency graph on the fly. This - /// avoids building an explicit data structure representation of the + /// when any of its embedded analysis results end up invalidated. We pass an + /// \c Invalidator object as an argument to \c invalidate() in order to let + /// the analysis results themselves define the dependency graph on the fly. + /// This lets us avoid building building an explicit representation of the /// dependencies between analysis results. class Invalidator { public: /// Trigger the invalidation of some other analysis pass if not already - /// handled and return whether it will in fact be invalidated. + /// handled and return whether it was in fact invalidated. /// /// This is expected to be called from within a given analysis result's \c /// invalidate method to trigger a depth-first walk of all inter-analysis /// dependencies. The same \p IR unit and \p PA passed to that result's \c /// invalidate method should in turn be provided to this routine. /// - /// The first time this is called for a given analysis pass, it will - /// trigger the corresponding result's \c invalidate method to be called. - /// Subsequent calls will use a cache of the results of that initial call. - /// It is an error to form cyclic dependencies between analysis results. + /// The first time this is called for a given analysis pass, it will call + /// the corresponding result's \c invalidate method. Subsequent calls will + /// use a cache of the results of that initial call. It is an error to form + /// cyclic dependencies between analysis results. /// - /// This returns true if the given analysis pass's result is invalid and - /// any dependecies on it will become invalid as a result. + /// This returns true if the given analysis's result is invalid. Any + /// dependecies on it will become invalid as a result. template <typename PassT> bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) { typedef detail::AnalysisResultModel<IRUnitT, PassT, @@ -577,10 +573,10 @@ public: auto &Result = static_cast<ResultT &>(*RI->second->second); - // Insert into the map whether the result should be invalidated and - // return that. Note that we cannot re-use IMapI and must do a fresh - // insert here as calling the invalidate routine could (recursively) - // insert things into the map making any iterator or reference invalid. + // Insert into the map whether the result should be invalidated and return + // that. Note that we cannot reuse IMapI and must do a fresh insert here, + // as calling invalidate could (recursively) insert things into the map, + // making any iterator or reference invalid. bool Inserted; std::tie(IMapI, Inserted) = IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, *this)}); @@ -600,8 +596,7 @@ public: /// \brief Construct an empty analysis manager. /// - /// A flag can be passed to indicate that the manager should perform debug - /// logging. + /// If \p DebugLogging is true, we'll log our progress to llvm::dbgs(). AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} AnalysisManager(AnalysisManager &&) = default; AnalysisManager &operator=(AnalysisManager &&) = default; @@ -614,11 +609,11 @@ public: return AnalysisResults.empty(); } - /// \brief Clear any results for a single unit of IR. + /// \brief Clear any cached analysis results for a single unit of IR. /// - /// This doesn't invalidate but directly clears the results. It is useful - /// when the IR is being removed and we want to clear out all the memory - /// pinned for it. + /// This doesn't invalidate, but instead simply deletes, the relevant results. + /// It is useful when the IR is being removed and we want to clear out all the + /// memory pinned for it. void clear(IRUnitT &IR) { if (DebugLogging) dbgs() << "Clearing all analysis results for: " << IR.getName() << "\n"; @@ -626,7 +621,7 @@ public: auto ResultsListI = AnalysisResultLists.find(&IR); if (ResultsListI == AnalysisResultLists.end()) return; - // Clear the map pointing into the results list. + // Delete the map entries that point into the results list. for (auto &IDAndResult : ResultsListI->second) AnalysisResults.erase({IDAndResult.first, &IR}); @@ -634,21 +629,20 @@ public: AnalysisResultLists.erase(ResultsListI); } - /// \brief Clear the analysis result cache. + /// \brief Clear all analysis results cached by this AnalysisManager. /// - /// This routine allows cleaning up when the set of IR units itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. + /// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply + /// deletes them. This lets you clean up the AnalysisManager when the set of + /// IR units itself has potentially changed, and thus we can't even look up a + /// a result and invalidate/clear it directly. void clear() { AnalysisResults.clear(); AnalysisResultLists.clear(); } - /// \brief Get the result of an analysis pass for this module. + /// \brief Get the result of an analysis pass for a given IR unit. /// - /// If there is not a valid cached result in the manager already, this will - /// re-run the analysis to produce a valid result. + /// Runs the analysis if a cached result is not available. template <typename PassT> typename PassT::Result &getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs) { assert(AnalysisPasses.count(PassT::ID()) && @@ -661,7 +655,7 @@ public: return static_cast<ResultModelT &>(ResultConcept).Result; } - /// \brief Get the cached result of an analysis pass for this module. + /// \brief Get the cached result of an analysis pass for a given IR unit. /// /// This method never runs the analysis. /// @@ -683,22 +677,21 @@ public: /// \brief Register an analysis pass with the manager. /// - /// The argument is a callable whose result is a pass. This allows passing in - /// a lambda to construct the pass. + /// The parameter is a callable whose result is an analysis pass. This allows + /// passing in a lambda to construct the analysis. /// - /// The pass type registered is the result type of calling the argument. If - /// that pass has already been registered, then the argument will not be - /// called and this function will return false. Otherwise, the pass type - /// becomes registered, with the instance provided by calling the argument - /// once, and this function returns true. + /// The analysis type to register is the type returned by calling the \c + /// PassBuilder argument. If that type has already been registered, then the + /// argument will not be called and this function will return false. + /// Otherwise, we register the analysis returned by calling \c PassBuilder(), + /// and this function returns true. /// - /// While this returns whether or not the pass type was already registered, - /// there in't an independent way to query that as that would be prone to - /// risky use when *querying* the analysis manager. Instead, the only - /// supported use case is avoiding duplicate registry of an analysis. This - /// interface also lends itself to minimizing the number of times we have to - /// do lookups for analyses or construct complex passes only to throw them - /// away. + /// (Note: Although the return value of this function indicates whether or not + /// an analysis was previously registered, there intentionally isn't a way to + /// query this directly. Instead, you should just register all the analyses + /// you might want and let this class run them lazily. This idiom lets us + /// minimize the number of times we have to look up analyses in our + /// hashtable.) template <typename PassBuilderT> bool registerPass(PassBuilderT &&PassBuilder) { typedef decltype(PassBuilder()) PassT; @@ -718,17 +711,18 @@ public: /// \brief Invalidate a specific analysis pass for an IR module. /// - /// Note that the analysis result can disregard invalidation. + /// Note that the analysis result can disregard invalidation, if it determines + /// it is in fact still valid. template <typename PassT> void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); invalidateImpl(PassT::ID(), IR); } - /// \brief Invalidate analyses cached for an IR unit. + /// \brief Invalidate cached analyses for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and - /// invalidate them unless they are preserved by the PreservedAnalyses set. + /// invalidate them, unless they are preserved by the PreservedAnalyses set. void invalidate(IRUnitT &IR, const PreservedAnalyses &PA) { // We're done if all analyses on this IR unit are preserved. if (PA.allAnalysesInSetPreserved<AllAnalysesOn<IRUnitT>>()) @@ -738,8 +732,8 @@ public: dbgs() << "Invalidating all non-preserved analyses for: " << IR.getName() << "\n"; - // Track whether each pass's result is invalidated. Memoize the results - // using the IsResultInvalidated map. + // Track whether each analysis's result is invalidated in + // IsResultInvalidated. SmallDenseMap<AnalysisKey *, bool, 8> IsResultInvalidated; Invalidator Inv(IsResultInvalidated, AnalysisResults); AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; @@ -758,9 +752,9 @@ public: // Try to invalidate the result, giving it the Invalidator so it can // recursively query for any dependencies it has and record the result. - // Note that we cannot re-use 'IMapI' here or pre-insert the ID as the - // invalidate method may insert things into the map as well, invalidating - // any iterator or pointer. + // Note that we cannot reuse 'IMapI' here or pre-insert the ID, as + // Result.invalidate may insert things into the map, invalidating our + // iterator. bool Inserted = IsResultInvalidated.insert({ID, Result.invalidate(IR, PA, Inv)}) .second; @@ -873,7 +867,7 @@ private: /// analysis result. AnalysisResultMapT AnalysisResults; - /// \brief A flag indicating whether debug logging is enabled. + /// \brief Indicates whether we log to \c llvm::dbgs(). bool DebugLogging; }; diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h index bc435702157e..78ac73a7418c 100644 --- a/include/llvm/LTO/LTO.h +++ b/include/llvm/LTO/LTO.h @@ -382,6 +382,10 @@ private: /// The unmangled name of the global. std::string IRName; + /// Keep track if the symbol is visible outside of ThinLTO (i.e. in + /// either a regular object or the regular LTO partition). + bool VisibleOutsideThinLTO = false; + bool UnnamedAddr = true; /// This field keeps track of the partition number of this global. The @@ -405,6 +409,9 @@ private: /// This global is either used by more than one partition or has an /// external reference, and therefore cannot be internalized. External = -2u, + + /// The RegularLTO partition + RegularLTO = 0, }; }; diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index a300c4f6fb00..25642379ac9f 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCTARGETOPTIONS_H #include <string> +#include <vector> namespace llvm { @@ -51,11 +52,17 @@ public: bool PreserveAsmComments : 1; int DwarfVersion; + /// getABIName - If this returns a non-empty string this represents the /// textual name of the ABI that we want the backend to use, e.g. o32, or /// aapcs-linux. StringRef getABIName() const; std::string ABIName; + + /// Additional paths to search for `.include` directives when using the + /// integrated assembler. + std::vector<std::string> IASSearchPaths; + MCTargetOptions(); }; @@ -75,7 +82,8 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && ARE_EQUAL(DwarfVersion) && - ARE_EQUAL(ABIName)); + ARE_EQUAL(ABIName) && + ARE_EQUAL(IASSearchPaths)); #undef ARE_EQUAL } diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 586999794d50..ad21d8af66e9 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -27,7 +27,6 @@ #ifndef LLVM_SUPPORT_FILESYSTEM_H #define LLVM_SUPPORT_FILESYSTEM_H -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -37,6 +36,7 @@ #include <cassert> #include <cstdint> #include <ctime> +#include <memory> #include <stack> #include <string> #include <system_error> @@ -829,28 +829,23 @@ public: }; namespace detail { - /// RecDirIterState - Keeps state for the recursive_directory_iterator. It is - /// reference counted in order to preserve InputIterator semantics on copy. - struct RecDirIterState : public RefCountedBase<RecDirIterState> { - RecDirIterState() - : Level(0) - , HasNoPushRequest(false) {} - + /// Keeps state for the recursive_directory_iterator. + struct RecDirIterState { std::stack<directory_iterator, std::vector<directory_iterator>> Stack; - uint16_t Level; - bool HasNoPushRequest; + uint16_t Level = 0; + bool HasNoPushRequest = false; }; } // end namespace detail /// recursive_directory_iterator - Same as directory_iterator except for it /// recurses down into child directories. class recursive_directory_iterator { - IntrusiveRefCntPtr<detail::RecDirIterState> State; + std::shared_ptr<detail::RecDirIterState> State; public: recursive_directory_iterator() = default; explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) - : State(new detail::RecDirIterState) { + : State(std::make_shared<detail::RecDirIterState>()) { State->Stack.push(directory_iterator(path, ec)); if (State->Stack.top() == directory_iterator()) State.reset(); diff --git a/include/llvm/Support/TarWriter.h b/include/llvm/Support/TarWriter.h new file mode 100644 index 000000000000..44bdcaf2c465 --- /dev/null +++ b/include/llvm/Support/TarWriter.h @@ -0,0 +1,32 @@ +//===-- llvm/Support/TarWriter.h - Tar archive file creator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TAR_WRITER_H +#define LLVM_SUPPORT_TAR_WRITER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +class TarWriter { +public: + static Expected<std::unique_ptr<TarWriter>> create(StringRef OutputPath, + StringRef BaseDir); + + void append(StringRef Path, StringRef Data); + +private: + TarWriter(int FD, StringRef BaseDir); + raw_fd_ostream OS; + std::string BaseDir; +}; +} + +#endif diff --git a/include/llvm/Transforms/IPO/FunctionImport.h b/include/llvm/Transforms/IPO/FunctionImport.h index d7acbe883c5d..eaea092c9179 100644 --- a/include/llvm/Transforms/IPO/FunctionImport.h +++ b/include/llvm/Transforms/IPO/FunctionImport.h @@ -86,11 +86,15 @@ public: /// \p ExportLists contains for each Module the set of globals (GUID) that will /// be imported by another module, or referenced by such a function. I.e. this /// is the set of globals that need to be promoted/renamed appropriately. +/// +/// \p DeadSymbols (optional) contains a list of GUID that are deemed "dead" and +/// will be ignored for the purpose of importing. void ComputeCrossModuleImport( const ModuleSummaryIndex &Index, const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries, StringMap<FunctionImporter::ImportMapTy> &ImportLists, - StringMap<FunctionImporter::ExportSetTy> &ExportLists); + StringMap<FunctionImporter::ExportSetTy> &ExportLists, + const DenseSet<GlobalValue::GUID> *DeadSymbols = nullptr); /// Compute all the imports for the given module using the Index. /// @@ -100,6 +104,13 @@ void ComputeCrossModuleImportForModule( StringRef ModulePath, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList); +/// Compute all the symbols that are "dead": i.e these that can't be reached +/// in the graph from any of the given symbols listed in +/// \p GUIDPreservedSymbols. +DenseSet<GlobalValue::GUID> +computeDeadSymbols(const ModuleSummaryIndex &Index, + const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); + /// Compute the set of summaries needed for a ThinLTO backend compilation of /// \p ModulePath. // diff --git a/include/llvm/Transforms/IPO/LowerTypeTests.h b/include/llvm/Transforms/IPO/LowerTypeTests.h index 23c59c199a3b..ca6e1b878dff 100644 --- a/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -60,10 +60,6 @@ struct BitSetInfo { bool containsGlobalOffset(uint64_t Offset) const; - bool containsValue(const DataLayout &DL, - const DenseMap<GlobalObject *, uint64_t> &GlobalLayout, - Value *V, uint64_t COffset = 0) const; - void print(raw_ostream &OS) const; }; diff --git a/include/llvm/Transforms/Utils/FunctionImportUtils.h b/include/llvm/Transforms/Utils/FunctionImportUtils.h index 57b7d0fcd7cc..f18cd92310b4 100644 --- a/include/llvm/Transforms/Utils/FunctionImportUtils.h +++ b/include/llvm/Transforms/Utils/FunctionImportUtils.h @@ -40,9 +40,20 @@ class FunctionImportGlobalProcessing { /// as part of a different backend compilation process. bool HasExportedFunctions = false; + /// Set of llvm.*used values, in order to validate that we don't try + /// to promote any non-renamable values. + SmallPtrSet<GlobalValue *, 8> Used; + /// Check if we should promote the given local value to global scope. bool shouldPromoteLocalToGlobal(const GlobalValue *SGV); +#ifndef NDEBUG + /// Check if the given value is a local that can't be renamed (promoted). + /// Only used in assertion checking, and disabled under NDEBUG since the Used + /// set will not be populated. + bool isNonRenamableLocal(const GlobalValue &GV) const; +#endif + /// Helper methods to check if we are importing from or potentially /// exporting from the current source module. bool isPerformingImport() const { return GlobalsToImport != nullptr; } @@ -82,6 +93,13 @@ public: // may be exported to another backend compilation. if (!GlobalsToImport) HasExportedFunctions = ImportIndex.hasExportedFunctions(M); + +#ifndef NDEBUG + // First collect those in the llvm.used set. + collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false); + // Next collect those in the llvm.compiler.used set. + collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ true); +#endif } bool run(); diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap index a86bc7e7fcbf..29e6d66b27ff 100644 --- a/include/llvm/module.modulemap +++ b/include/llvm/module.modulemap @@ -151,6 +151,7 @@ module LLVM_intrinsic_gen { module IR_NoFolder { header "IR/NoFolder.h" export * } module IR_Module { header "IR/Module.h" export * } module IR_ModuleSummaryIndex { header "IR/ModuleSummaryIndex.h" export * } + module IR_ModuleSummaryIndexYAML { header "IR/ModuleSummaryIndexYAML.h" export * } module IR_Function { header "IR/Function.h" export * } module IR_InstrTypes { header "IR/InstrTypes.h" export * } module IR_Instructions { header "IR/Instructions.h" export * } |