summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/llvm/Analysis/CGSCCPassManager.h2
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h19
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h30
-rw-r--r--include/llvm/Bitcode/BitCodes.h6
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h11
-rw-r--r--include/llvm/Bitcode/BitstreamWriter.h26
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h7
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h5
-rw-r--r--include/llvm/CodeGen/DIE.h9
-rw-r--r--include/llvm/CodeGen/GlobalISel/IRTranslator.h6
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h58
-rw-r--r--include/llvm/ExecutionEngine/Orc/RawByteChannel.h2
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h112
-rw-r--r--include/llvm/IR/ModuleSummaryIndexYAML.h111
-rw-r--r--include/llvm/IR/PassManager.h250
-rw-r--r--include/llvm/LTO/LTO.h7
-rw-r--r--include/llvm/MC/MCTargetOptions.h10
-rw-r--r--include/llvm/Support/FileSystem.h19
-rw-r--r--include/llvm/Support/TarWriter.h32
-rw-r--r--include/llvm/Transforms/IPO/FunctionImport.h13
-rw-r--r--include/llvm/Transforms/IPO/LowerTypeTests.h4
-rw-r--r--include/llvm/Transforms/Utils/FunctionImportUtils.h18
-rw-r--r--include/llvm/module.modulemap1
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 * }