aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/IR
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-30 16:33:32 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-30 16:33:32 +0000
commit51315c45ff5643a27f9c84b816db54ee870ba29b (patch)
tree1d87443fa0e53d3e6b315ce25787e64be0906bf7 /contrib/llvm/lib/IR
parent6dfd050075216be8538ae375a22d30db72916f7e (diff)
parenteb11fae6d08f479c0799db45860a98af528fa6e7 (diff)
downloadsrc-51315c45ff5643a27f9c84b816db54ee870ba29b.tar.gz
src-51315c45ff5643a27f9c84b816db54ee870ba29b.zip
Merge llvm trunk r338150, and resolve conflicts.
Notes
Notes: svn path=/projects/clang700-import/; revision=336916
Diffstat (limited to 'contrib/llvm/lib/IR')
-rw-r--r--contrib/llvm/lib/IR/AsmWriter.cpp835
-rw-r--r--contrib/llvm/lib/IR/AttributeImpl.h18
-rw-r--r--contrib/llvm/lib/IR/Attributes.cpp190
-rw-r--r--contrib/llvm/lib/IR/AutoUpgrade.cpp1504
-rw-r--r--contrib/llvm/lib/IR/BasicBlock.cpp24
-rw-r--r--contrib/llvm/lib/IR/Comdat.cpp58
-rw-r--r--contrib/llvm/lib/IR/ConstantFold.cpp54
-rw-r--r--contrib/llvm/lib/IR/ConstantRange.cpp73
-rw-r--r--contrib/llvm/lib/IR/Constants.cpp191
-rw-r--r--contrib/llvm/lib/IR/ConstantsContext.h4
-rw-r--r--contrib/llvm/lib/IR/Core.cpp341
-rw-r--r--contrib/llvm/lib/IR/DIBuilder.cpp136
-rw-r--r--contrib/llvm/lib/IR/DataLayout.cpp84
-rw-r--r--contrib/llvm/lib/IR/DebugInfo.cpp694
-rw-r--r--contrib/llvm/lib/IR/DebugInfoMetadata.cpp234
-rw-r--r--contrib/llvm/lib/IR/DebugLoc.cpp15
-rw-r--r--contrib/llvm/lib/IR/DiagnosticHandler.cpp2
-rw-r--r--contrib/llvm/lib/IR/DiagnosticInfo.cpp6
-rw-r--r--contrib/llvm/lib/IR/DomTreeUpdater.cpp534
-rw-r--r--contrib/llvm/lib/IR/Dominators.cpp245
-rw-r--r--contrib/llvm/lib/IR/Function.cpp122
-rw-r--r--contrib/llvm/lib/IR/Globals.cpp18
-rw-r--r--contrib/llvm/lib/IR/IRBuilder.cpp224
-rw-r--r--contrib/llvm/lib/IR/IRPrintingPasses.cpp14
-rw-r--r--contrib/llvm/lib/IR/Instruction.cpp16
-rw-r--r--contrib/llvm/lib/IR/Instructions.cpp431
-rw-r--r--contrib/llvm/lib/IR/IntrinsicInst.cpp12
-rw-r--r--contrib/llvm/lib/IR/LLVMContext.cpp8
-rw-r--r--contrib/llvm/lib/IR/LLVMContextImpl.cpp24
-rw-r--r--contrib/llvm/lib/IR/LLVMContextImpl.h152
-rw-r--r--contrib/llvm/lib/IR/LegacyPassManager.cpp94
-rw-r--r--contrib/llvm/lib/IR/MDBuilder.cpp45
-rw-r--r--contrib/llvm/lib/IR/Mangler.cpp22
-rw-r--r--contrib/llvm/lib/IR/Metadata.cpp83
-rw-r--r--contrib/llvm/lib/IR/Module.cpp16
-rw-r--r--contrib/llvm/lib/IR/ModuleSummaryIndex.cpp278
-rw-r--r--contrib/llvm/lib/IR/Operator.cpp4
-rw-r--r--contrib/llvm/lib/IR/OptBisect.cpp37
-rw-r--r--contrib/llvm/lib/IR/Pass.cpp15
-rw-r--r--contrib/llvm/lib/IR/ProfileSummary.cpp36
-rw-r--r--contrib/llvm/lib/IR/SafepointIRVerifier.cpp247
-rw-r--r--contrib/llvm/lib/IR/Type.cpp24
-rw-r--r--contrib/llvm/lib/IR/TypeFinder.cpp50
-rw-r--r--contrib/llvm/lib/IR/Value.cpp61
-rw-r--r--contrib/llvm/lib/IR/ValueSymbolTable.cpp8
-rw-r--r--contrib/llvm/lib/IR/ValueTypes.cpp324
-rw-r--r--contrib/llvm/lib/IR/Verifier.cpp326
47 files changed, 6174 insertions, 1759 deletions
diff --git a/contrib/llvm/lib/IR/AsmWriter.cpp b/contrib/llvm/lib/IR/AsmWriter.cpp
index 0fafe82404e4..99a25a723b4a 100644
--- a/contrib/llvm/lib/IR/AsmWriter.cpp
+++ b/contrib/llvm/lib/IR/AsmWriter.cpp
@@ -7,7 +7,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This library implements the functionality defined in llvm/IR/Writer.h
+// This library implements `print` family of functions in classes like
+// Module, Function, Value, etc. In-memory representation of those classes is
+// converted to IR strings.
//
// Note that these routines must be extremely tolerant of various errors in the
// LLVM code, because it can be used for debugging transformations.
@@ -28,6 +30,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/Attributes.h"
@@ -56,6 +59,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h"
@@ -195,7 +199,7 @@ static void predictValueUseListOrderImpl(const Value *V, const Function *F,
!isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V);
if (auto *BA = dyn_cast<BlockAddress>(V))
ID = OM.lookup(BA->getBasicBlock()).first;
- std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
+ llvm::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
const Use *LU = L.first;
const Use *RU = R.first;
if (LU == RU)
@@ -383,16 +387,6 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
}
}
-void llvm::PrintEscapedString(StringRef Name, raw_ostream &Out) {
- for (unsigned i = 0, e = Name.size(); i != e; ++i) {
- unsigned char C = Name[i];
- if (isprint(C) && C != '\\' && C != '"')
- Out << C;
- else
- Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
- }
-}
-
enum PrefixType {
GlobalPrefix,
ComdatPrefix,
@@ -430,7 +424,7 @@ void llvm::printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name) {
// Okay, we need quotes. Output the quotes and escape any scary characters as
// needed.
OS << '"';
- PrintEscapedString(Name, OS);
+ printEscapedString(Name, OS);
OS << '"';
}
@@ -468,27 +462,73 @@ namespace {
class TypePrinting {
public:
- /// NamedTypes - The named types that are used by the current module.
- TypeFinder NamedTypes;
-
- /// NumberedTypes - The numbered types, along with their value.
- DenseMap<StructType*, unsigned> NumberedTypes;
+ TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
- TypePrinting() = default;
TypePrinting(const TypePrinting &) = delete;
TypePrinting &operator=(const TypePrinting &) = delete;
- void incorporateTypes(const Module &M);
+ /// The named types that are used by the current module.
+ TypeFinder &getNamedTypes();
+
+ /// The numbered types, number to type mapping.
+ std::vector<StructType *> &getNumberedTypes();
+
+ bool empty();
void print(Type *Ty, raw_ostream &OS);
void printStructBody(StructType *Ty, raw_ostream &OS);
+
+private:
+ void incorporateTypes();
+
+ /// A module to process lazily when needed. Set to nullptr as soon as used.
+ const Module *DeferredM;
+
+ TypeFinder NamedTypes;
+
+ // The numbered types, along with their value.
+ DenseMap<StructType *, unsigned> Type2Number;
+
+ std::vector<StructType *> NumberedTypes;
};
} // end anonymous namespace
-void TypePrinting::incorporateTypes(const Module &M) {
- NamedTypes.run(M, false);
+TypeFinder &TypePrinting::getNamedTypes() {
+ incorporateTypes();
+ return NamedTypes;
+}
+
+std::vector<StructType *> &TypePrinting::getNumberedTypes() {
+ incorporateTypes();
+
+ // We know all the numbers that each type is used and we know that it is a
+ // dense assignment. Convert the map to an index table, if it's not done
+ // already (judging from the sizes):
+ if (NumberedTypes.size() == Type2Number.size())
+ return NumberedTypes;
+
+ NumberedTypes.resize(Type2Number.size());
+ for (const auto &P : Type2Number) {
+ assert(P.second < NumberedTypes.size() && "Didn't get a dense numbering?");
+ assert(!NumberedTypes[P.second] && "Didn't get a unique numbering?");
+ NumberedTypes[P.second] = P.first;
+ }
+ return NumberedTypes;
+}
+
+bool TypePrinting::empty() {
+ incorporateTypes();
+ return NamedTypes.empty() && Type2Number.empty();
+}
+
+void TypePrinting::incorporateTypes() {
+ if (!DeferredM)
+ return;
+
+ NamedTypes.run(*DeferredM, false);
+ DeferredM = nullptr;
// The list of struct types we got back includes all the struct types, split
// the unnamed ones out to a numbering and remove the anonymous structs.
@@ -503,7 +543,7 @@ void TypePrinting::incorporateTypes(const Module &M) {
continue;
if (STy->getName().empty())
- NumberedTypes[STy] = NextNumber++;
+ Type2Number[STy] = NextNumber++;
else
*NextToUse++ = STy;
}
@@ -511,9 +551,8 @@ void TypePrinting::incorporateTypes(const Module &M) {
NamedTypes.erase(NextToUse, NamedTypes.end());
}
-
-/// CalcTypeName - Write the specified type to the specified raw_ostream, making
-/// use of type names or up references to shorten the type name where possible.
+/// Write the specified type to the specified raw_ostream, making use of type
+/// names or up references to shorten the type name where possible.
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
case Type::VoidTyID: OS << "void"; return;
@@ -557,8 +596,9 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
if (!STy->getName().empty())
return PrintLLVMName(OS, STy->getName(), LocalPrefix);
- DenseMap<StructType*, unsigned>::iterator I = NumberedTypes.find(STy);
- if (I != NumberedTypes.end())
+ incorporateTypes();
+ const auto I = Type2Number.find(STy);
+ if (I != Type2Number.end())
OS << '%' << I->second;
else // Not enumerated, print the hex address.
OS << "%\"type " << STy << '\"';
@@ -637,6 +677,9 @@ private:
bool FunctionProcessed = false;
bool ShouldInitializeAllMetadata;
+ /// The summary index for which we are holding slot numbers.
+ const ModuleSummaryIndex *TheIndex = nullptr;
+
/// mMap - The slot map for the module level data.
ValueMap mMap;
unsigned mNext = 0;
@@ -653,6 +696,14 @@ private:
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext = 0;
+ /// ModulePathMap - The slot map for Module paths used in the summary index.
+ StringMap<unsigned> ModulePathMap;
+ unsigned ModulePathNext = 0;
+
+ /// GUIDMap - The slot map for GUIDs used in the summary index.
+ DenseMap<GlobalValue::GUID, unsigned> GUIDMap;
+ unsigned GUIDNext = 0;
+
public:
/// Construct from a module.
///
@@ -670,6 +721,9 @@ public:
explicit SlotTracker(const Function *F,
bool ShouldInitializeAllMetadata = false);
+ /// Construct from a module summary index.
+ explicit SlotTracker(const ModuleSummaryIndex *Index);
+
SlotTracker(const SlotTracker &) = delete;
SlotTracker &operator=(const SlotTracker &) = delete;
@@ -679,6 +733,8 @@ public:
int getGlobalSlot(const GlobalValue *V);
int getMetadataSlot(const MDNode *N);
int getAttributeGroupSlot(AttributeSet AS);
+ int getModulePathSlot(StringRef Path);
+ int getGUIDSlot(GlobalValue::GUID GUID);
/// If you'd like to deal with a function instead of just a module, use
/// this method to get its data into the SlotTracker.
@@ -710,8 +766,12 @@ public:
unsigned as_size() const { return asMap.size(); }
bool as_empty() const { return asMap.empty(); }
- /// This function does the actual initialization.
- inline void initialize();
+ /// GUID map iterators.
+ using guid_iterator = DenseMap<GlobalValue::GUID, unsigned>::iterator;
+
+ /// These functions do the actual initialization.
+ inline void initializeIfNeeded();
+ void initializeIndexIfNeeded();
// Implementation Details
private:
@@ -724,12 +784,16 @@ private:
/// CreateFunctionSlot - Insert the specified Value* into the slot table.
void CreateFunctionSlot(const Value *V);
- /// \brief Insert the specified AttributeSet into the slot table.
+ /// Insert the specified AttributeSet into the slot table.
void CreateAttributeSetSlot(AttributeSet AS);
+ inline void CreateModulePathSlot(StringRef Path);
+ void CreateGUIDSlot(GlobalValue::GUID GUID);
+
/// Add all of the module level global variables (and their initializers)
/// and function declarations, but not the contents of those functions.
void processModule();
+ void processIndex();
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();
@@ -830,7 +894,10 @@ SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
: TheModule(F ? F->getParent() : nullptr), TheFunction(F),
ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
-inline void SlotTracker::initialize() {
+SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
+ : TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
+
+inline void SlotTracker::initializeIfNeeded() {
if (TheModule) {
processModule();
TheModule = nullptr; ///< Prevent re-processing next time we're called.
@@ -840,6 +907,13 @@ inline void SlotTracker::initialize() {
processFunction();
}
+void SlotTracker::initializeIndexIfNeeded() {
+ if (!TheIndex)
+ return;
+ processIndex();
+ TheIndex = nullptr; ///< Prevent re-processing next time we're called.
+}
+
// Iterate through all the global variables, functions, and global
// variable initializers and create slots for them.
void SlotTracker::processModule() {
@@ -931,6 +1005,32 @@ void SlotTracker::processFunction() {
ST_DEBUG("end processFunction!\n");
}
+// Iterate through all the GUID in the index and create slots for them.
+void SlotTracker::processIndex() {
+ ST_DEBUG("begin processIndex!\n");
+ assert(TheIndex);
+
+ // The first block of slots are just the module ids, which start at 0 and are
+ // assigned consecutively. Since the StringMap iteration order isn't
+ // guaranteed, use a std::map to order by module ID before assigning slots.
+ std::map<uint64_t, StringRef> ModuleIdToPathMap;
+ for (auto &ModPath : TheIndex->modulePaths())
+ ModuleIdToPathMap[ModPath.second.first] = ModPath.first();
+ for (auto &ModPair : ModuleIdToPathMap)
+ CreateModulePathSlot(ModPair.second);
+
+ // Start numbering the GUIDs after the module ids.
+ GUIDNext = ModulePathNext;
+
+ for (auto &GlobalList : *TheIndex)
+ CreateGUIDSlot(GlobalList.first);
+
+ for (auto &TId : TheIndex->typeIds())
+ CreateGUIDSlot(GlobalValue::getGUID(TId.first));
+
+ ST_DEBUG("end processIndex!\n");
+}
+
void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
GO.getAllMetadata(MDs);
@@ -977,7 +1077,7 @@ void SlotTracker::purgeFunction() {
/// getGlobalSlot - Get the slot number of a global value.
int SlotTracker::getGlobalSlot(const GlobalValue *V) {
// Check for uninitialized state and do lazy initialization.
- initialize();
+ initializeIfNeeded();
// Find the value in the module map
ValueMap::iterator MI = mMap.find(V);
@@ -987,7 +1087,7 @@ int SlotTracker::getGlobalSlot(const GlobalValue *V) {
/// getMetadataSlot - Get the slot number of a MDNode.
int SlotTracker::getMetadataSlot(const MDNode *N) {
// Check for uninitialized state and do lazy initialization.
- initialize();
+ initializeIfNeeded();
// Find the MDNode in the module map
mdn_iterator MI = mdnMap.find(N);
@@ -999,7 +1099,7 @@ int SlotTracker::getLocalSlot(const Value *V) {
assert(!isa<Constant>(V) && "Can't get a constant or global slot with this!");
// Check for uninitialized state and do lazy initialization.
- initialize();
+ initializeIfNeeded();
ValueMap::iterator FI = fMap.find(V);
return FI == fMap.end() ? -1 : (int)FI->second;
@@ -1007,13 +1107,31 @@ int SlotTracker::getLocalSlot(const Value *V) {
int SlotTracker::getAttributeGroupSlot(AttributeSet AS) {
// Check for uninitialized state and do lazy initialization.
- initialize();
+ initializeIfNeeded();
// Find the AttributeSet in the module map.
as_iterator AI = asMap.find(AS);
return AI == asMap.end() ? -1 : (int)AI->second;
}
+int SlotTracker::getModulePathSlot(StringRef Path) {
+ // Check for uninitialized state and do lazy initialization.
+ initializeIndexIfNeeded();
+
+ // Find the Module path in the map
+ auto I = ModulePathMap.find(Path);
+ return I == ModulePathMap.end() ? -1 : (int)I->second;
+}
+
+int SlotTracker::getGUIDSlot(GlobalValue::GUID GUID) {
+ // Check for uninitialized state and do lazy initialization.
+ initializeIndexIfNeeded();
+
+ // Find the GUID in the map
+ guid_iterator I = GUIDMap.find(GUID);
+ return I == GUIDMap.end() ? -1 : (int)I->second;
+}
+
/// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
assert(V && "Can't insert a null Value into SlotTracker!");
@@ -1074,6 +1192,16 @@ void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
asMap[AS] = DestSlot;
}
+/// Create a new slot for the specified Module
+void SlotTracker::CreateModulePathSlot(StringRef Path) {
+ ModulePathMap[Path] = ModulePathNext++;
+}
+
+/// Create a new slot for the specified GUID
+void SlotTracker::CreateGUIDSlot(GlobalValue::GUID GUID) {
+ GUIDMap[GUID] = GUIDNext++;
+}
+
//===----------------------------------------------------------------------===//
// AsmWriter Implementation
//===----------------------------------------------------------------------===//
@@ -1277,7 +1405,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// i8 with ConstantInt values.
if (CA->isString()) {
Out << "c\"";
- PrintEscapedString(CA->getAsString(), Out);
+ printEscapedString(CA->getAsString(), Out);
Out << '"';
return;
}
@@ -1463,7 +1591,7 @@ struct MDFieldPrinter {
void printTag(const DINode *N);
void printMacinfoType(const DIMacroNode *N);
- void printChecksumKind(const DIFile *N);
+ void printChecksum(const DIFile::ChecksumInfo<StringRef> &N);
void printString(StringRef Name, StringRef Value,
bool ShouldSkipEmpty = true);
void printMetadata(StringRef Name, const Metadata *MD,
@@ -1498,11 +1626,10 @@ void MDFieldPrinter::printMacinfoType(const DIMacroNode *N) {
Out << N->getMacinfoType();
}
-void MDFieldPrinter::printChecksumKind(const DIFile *N) {
- if (N->getChecksumKind() == DIFile::CSK_None)
- // Skip CSK_None checksum kind.
- return;
- Out << FS << "checksumkind: " << N->getChecksumKindAsString();
+void MDFieldPrinter::printChecksum(
+ const DIFile::ChecksumInfo<StringRef> &Checksum) {
+ Out << FS << "checksumkind: " << Checksum.getKindAsString();
+ printString("checksum", Checksum.Value, /* ShouldSkipEmpty */ false);
}
void MDFieldPrinter::printString(StringRef Name, StringRef Value,
@@ -1511,7 +1638,7 @@ void MDFieldPrinter::printString(StringRef Name, StringRef Value,
return;
Out << FS << Name << ": \"";
- PrintEscapedString(Value, Out);
+ printEscapedString(Value, Out);
Out << "\"";
}
@@ -1571,7 +1698,7 @@ void MDFieldPrinter::printDIFlags(StringRef Name, DINode::DIFlags Flags) {
void MDFieldPrinter::printEmissionKind(StringRef Name,
DICompileUnit::DebugEmissionKind EK) {
- Out << FS << Name << ": " << DICompileUnit::EmissionKindString(EK);
+ Out << FS << Name << ": " << DICompileUnit::emissionKindString(EK);
}
template <class IntTy, class Stringifier>
@@ -1621,10 +1748,15 @@ static void writeDILocation(raw_ostream &Out, const DILocation *DL,
}
static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
- TypePrinting *, SlotTracker *, const Module *) {
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
Out << "!DISubrange(";
- MDFieldPrinter Printer(Out);
- Printer.printInt("count", N->getCount(), /* ShouldSkipZero */ false);
+ MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
+ if (auto *CE = N->getCount().dyn_cast<ConstantInt*>())
+ Printer.printInt("count", CE->getSExtValue(), /* ShouldSkipZero */ false);
+ else
+ Printer.printMetadata("count", N->getCount().dyn_cast<DIVariable*>(),
+ /*ShouldSkipNull */ false);
Printer.printInt("lowerBound", N->getLowerBound());
Out << ")";
}
@@ -1634,7 +1766,13 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
Out << "!DIEnumerator(";
MDFieldPrinter Printer(Out);
Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
- Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false);
+ if (N->isUnsigned()) {
+ auto Value = static_cast<uint64_t>(N->getValue());
+ Printer.printInt("value", Value, /* ShouldSkipZero */ false);
+ Printer.printBool("isUnsigned", true);
+ } else {
+ Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false);
+ }
Out << ")";
}
@@ -1696,6 +1834,7 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
Printer.printMetadata("vtableHolder", N->getRawVTableHolder());
Printer.printMetadata("templateParams", N->getRawTemplateParams());
Printer.printString("identifier", N->getIdentifier());
+ Printer.printMetadata("discriminator", N->getRawDiscriminator());
Out << ")";
}
@@ -1719,8 +1858,11 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
/* ShouldSkipEmpty */ false);
Printer.printString("directory", N->getDirectory(),
/* ShouldSkipEmpty */ false);
- Printer.printChecksumKind(N);
- Printer.printString("checksum", N->getChecksum(), /* ShouldSkipEmpty */ true);
+ // Print all values for checksum together, or not at all.
+ if (N->getChecksum())
+ Printer.printChecksum(*N->getChecksum());
+ Printer.printString("source", N->getSource().getValueOr(StringRef()),
+ /* ShouldSkipEmpty */ true);
Out << ")";
}
@@ -1778,7 +1920,7 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N,
Printer.printMetadata("unit", N->getRawUnit());
Printer.printMetadata("templateParams", N->getRawTemplateParams());
Printer.printMetadata("declaration", N->getRawDeclaration());
- Printer.printMetadata("variables", N->getRawVariables());
+ Printer.printMetadata("retainedNodes", N->getRawRetainedNodes());
Printer.printMetadata("thrownTypes", N->getRawThrownTypes());
Out << ")";
}
@@ -1918,6 +2060,18 @@ static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N,
Out << ")";
}
+static void writeDILabel(raw_ostream &Out, const DILabel *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!DILabel(";
+ MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
+ Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
+ Printer.printString("name", N->getName());
+ Printer.printMetadata("file", N->getRawFile());
+ Printer.printInt("line", N->getLine());
+ Out << ")";
+}
+
static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
@@ -2028,9 +2182,9 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
if (IA->getDialect() == InlineAsm::AD_Intel)
Out << "inteldialect ";
Out << '"';
- PrintEscapedString(IA->getAsmString(), Out);
+ printEscapedString(IA->getAsmString(), Out);
Out << "\", \"";
- PrintEscapedString(IA->getConstraintString(), Out);
+ printEscapedString(IA->getConstraintString(), Out);
Out << '"';
return;
}
@@ -2109,7 +2263,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
if (const MDString *MDS = dyn_cast<MDString>(MD)) {
Out << "!\"";
- PrintEscapedString(MDS->getString(), Out);
+ printEscapedString(MDS->getString(), Out);
Out << '"';
return;
}
@@ -2128,11 +2282,12 @@ namespace {
class AssemblyWriter {
formatted_raw_ostream &Out;
- const Module *TheModule;
+ const Module *TheModule = nullptr;
+ const ModuleSummaryIndex *TheIndex = nullptr;
std::unique_ptr<SlotTracker> SlotTrackerStorage;
SlotTracker &Machine;
TypePrinting TypePrinter;
- AssemblyAnnotationWriter *AnnotationWriter;
+ AssemblyAnnotationWriter *AnnotationWriter = nullptr;
SetVector<const Comdat *> Comdats;
bool IsForDebug;
bool ShouldPreserveUseListOrder;
@@ -2140,6 +2295,7 @@ class AssemblyWriter {
SmallVector<StringRef, 8> MDNames;
/// Synchronization scope names registered with LLVMContext.
SmallVector<StringRef, 8> SSNs;
+ DenseMap<const GlobalValueSummary *, GlobalValue::GUID> SummaryToGUIDMap;
public:
/// Construct an AssemblyWriter with an external SlotTracker
@@ -2147,6 +2303,9 @@ public:
AssemblyAnnotationWriter *AAW, bool IsForDebug,
bool ShouldPreserveUseListOrder = false);
+ AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
+ const ModuleSummaryIndex *Index, bool IsForDebug);
+
void printMDNodeBody(const MDNode *MD);
void printNamedMDNode(const NamedMDNode *NMD);
@@ -2182,8 +2341,27 @@ public:
void printUseListOrder(const UseListOrder &Order);
void printUseLists(const Function *F);
+ void printModuleSummaryIndex();
+ void printSummaryInfo(unsigned Slot, const ValueInfo &VI);
+ void printSummary(const GlobalValueSummary &Summary);
+ void printAliasSummary(const AliasSummary *AS);
+ void printGlobalVarSummary(const GlobalVarSummary *GS);
+ void printFunctionSummary(const FunctionSummary *FS);
+ void printTypeIdSummary(const TypeIdSummary &TIS);
+ void printTypeTestResolution(const TypeTestResolution &TTRes);
+ void printArgs(const std::vector<uint64_t> &Args);
+ void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
+ void printTypeIdInfo(const FunctionSummary::TypeIdInfo &TIDInfo);
+ void printVFuncId(const FunctionSummary::VFuncId VFId);
+ void
+ printNonConstVCalls(const std::vector<FunctionSummary::VFuncId> VCallList,
+ const char *Tag);
+ void
+ printConstVCalls(const std::vector<FunctionSummary::ConstVCall> VCallList,
+ const char *Tag);
+
private:
- /// \brief Print out metadata attachments.
+ /// Print out metadata attachments.
void printMetadataAttachments(
const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
StringRef Separator);
@@ -2202,17 +2380,21 @@ private:
AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
const Module *M, AssemblyAnnotationWriter *AAW,
bool IsForDebug, bool ShouldPreserveUseListOrder)
- : Out(o), TheModule(M), Machine(Mac), AnnotationWriter(AAW),
+ : Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
IsForDebug(IsForDebug),
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
if (!TheModule)
return;
- TypePrinter.incorporateTypes(*TheModule);
for (const GlobalObject &GO : TheModule->global_objects())
if (const Comdat *C = GO.getComdat())
Comdats.insert(C);
}
+AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
+ const ModuleSummaryIndex *Index, bool IsForDebug)
+ : Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
+ IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false) {}
+
void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
if (!Operand) {
Out << "<null operand!>";
@@ -2236,7 +2418,7 @@ void AssemblyWriter::writeSyncScope(const LLVMContext &Context,
Context.getSyncScopeNames(SSNs);
Out << " syncscope(\"";
- PrintEscapedString(SSNs[SSID], Out);
+ printEscapedString(SSNs[SSID], Out);
Out << "\")";
break;
}
@@ -2297,7 +2479,7 @@ void AssemblyWriter::writeOperandBundles(ImmutableCallSite CS) {
FirstBundle = false;
Out << '"';
- PrintEscapedString(BU.getTagName(), Out);
+ printEscapedString(BU.getTagName(), Out);
Out << '"';
Out << '(';
@@ -2320,7 +2502,7 @@ void AssemblyWriter::writeOperandBundles(ImmutableCallSite CS) {
}
void AssemblyWriter::printModule(const Module *M) {
- Machine.initialize();
+ Machine.initializeIfNeeded();
if (ShouldPreserveUseListOrder)
UseListOrders = predictUseListOrder(M);
@@ -2333,7 +2515,7 @@ void AssemblyWriter::printModule(const Module *M) {
if (!M->getSourceFileName().empty()) {
Out << "source_filename = \"";
- PrintEscapedString(M->getSourceFileName(), Out);
+ printEscapedString(M->getSourceFileName(), Out);
Out << "\"\n";
}
@@ -2355,7 +2537,7 @@ void AssemblyWriter::printModule(const Module *M) {
// We found a newline, print the portion of the asm string from the
// last newline up to this newline.
Out << "module asm \"";
- PrintEscapedString(Front, Out);
+ printEscapedString(Front, Out);
Out << "\"\n";
} while (!Asm.empty());
}
@@ -2414,6 +2596,428 @@ void AssemblyWriter::printModule(const Module *M) {
}
}
+void AssemblyWriter::printModuleSummaryIndex() {
+ assert(TheIndex);
+ Machine.initializeIndexIfNeeded();
+
+ Out << "\n";
+
+ // Print module path entries. To print in order, add paths to a vector
+ // indexed by module slot.
+ std::vector<std::pair<std::string, ModuleHash>> moduleVec;
+ std::string RegularLTOModuleName = "[Regular LTO]";
+ moduleVec.resize(TheIndex->modulePaths().size());
+ for (auto &ModPath : TheIndex->modulePaths())
+ moduleVec[Machine.getModulePathSlot(ModPath.first())] = std::make_pair(
+ // A module id of -1 is a special entry for a regular LTO module created
+ // during the thin link.
+ ModPath.second.first == -1u ? RegularLTOModuleName
+ : (std::string)ModPath.first(),
+ ModPath.second.second);
+
+ unsigned i = 0;
+ for (auto &ModPair : moduleVec) {
+ Out << "^" << i++ << " = module: (";
+ Out << "path: \"";
+ printEscapedString(ModPair.first, Out);
+ Out << "\", hash: (";
+ FieldSeparator FS;
+ for (auto Hash : ModPair.second)
+ Out << FS << Hash;
+ Out << "))\n";
+ }
+
+ // FIXME: Change AliasSummary to hold a ValueInfo instead of summary pointer
+ // for aliasee (then update BitcodeWriter.cpp and remove get/setAliaseeGUID).
+ for (auto &GlobalList : *TheIndex) {
+ auto GUID = GlobalList.first;
+ for (auto &Summary : GlobalList.second.SummaryList)
+ SummaryToGUIDMap[Summary.get()] = GUID;
+ }
+
+ // Print the global value summary entries.
+ for (auto &GlobalList : *TheIndex) {
+ auto GUID = GlobalList.first;
+ auto VI = TheIndex->getValueInfo(GlobalList);
+ printSummaryInfo(Machine.getGUIDSlot(GUID), VI);
+ }
+
+ // Print the TypeIdMap entries.
+ for (auto &TId : TheIndex->typeIds()) {
+ auto GUID = GlobalValue::getGUID(TId.first);
+ Out << "^" << Machine.getGUIDSlot(GUID) << " = typeid: (name: \""
+ << TId.first << "\"";
+ printTypeIdSummary(TId.second);
+ Out << ") ; guid = " << GUID << "\n";
+ }
+}
+
+static const char *
+getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K) {
+ switch (K) {
+ case WholeProgramDevirtResolution::Indir:
+ return "indir";
+ case WholeProgramDevirtResolution::SingleImpl:
+ return "singleImpl";
+ case WholeProgramDevirtResolution::BranchFunnel:
+ return "branchFunnel";
+ }
+ llvm_unreachable("invalid WholeProgramDevirtResolution kind");
+}
+
+static const char *getWholeProgDevirtResByArgKindName(
+ WholeProgramDevirtResolution::ByArg::Kind K) {
+ switch (K) {
+ case WholeProgramDevirtResolution::ByArg::Indir:
+ return "indir";
+ case WholeProgramDevirtResolution::ByArg::UniformRetVal:
+ return "uniformRetVal";
+ case WholeProgramDevirtResolution::ByArg::UniqueRetVal:
+ return "uniqueRetVal";
+ case WholeProgramDevirtResolution::ByArg::VirtualConstProp:
+ return "virtualConstProp";
+ }
+ llvm_unreachable("invalid WholeProgramDevirtResolution::ByArg kind");
+}
+
+static const char *getTTResKindName(TypeTestResolution::Kind K) {
+ switch (K) {
+ case TypeTestResolution::Unsat:
+ return "unsat";
+ case TypeTestResolution::ByteArray:
+ return "byteArray";
+ case TypeTestResolution::Inline:
+ return "inline";
+ case TypeTestResolution::Single:
+ return "single";
+ case TypeTestResolution::AllOnes:
+ return "allOnes";
+ }
+ llvm_unreachable("invalid TypeTestResolution kind");
+}
+
+void AssemblyWriter::printTypeTestResolution(const TypeTestResolution &TTRes) {
+ Out << "typeTestRes: (kind: " << getTTResKindName(TTRes.TheKind)
+ << ", sizeM1BitWidth: " << TTRes.SizeM1BitWidth;
+
+ // The following fields are only used if the target does not support the use
+ // of absolute symbols to store constants. Print only if non-zero.
+ if (TTRes.AlignLog2)
+ Out << ", alignLog2: " << TTRes.AlignLog2;
+ if (TTRes.SizeM1)
+ Out << ", sizeM1: " << TTRes.SizeM1;
+ if (TTRes.BitMask)
+ // BitMask is uint8_t which causes it to print the corresponding char.
+ Out << ", bitMask: " << (unsigned)TTRes.BitMask;
+ if (TTRes.InlineBits)
+ Out << ", inlineBits: " << TTRes.InlineBits;
+
+ Out << ")";
+}
+
+void AssemblyWriter::printTypeIdSummary(const TypeIdSummary &TIS) {
+ Out << ", summary: (";
+ printTypeTestResolution(TIS.TTRes);
+ if (!TIS.WPDRes.empty()) {
+ Out << ", wpdResolutions: (";
+ FieldSeparator FS;
+ for (auto &WPDRes : TIS.WPDRes) {
+ Out << FS;
+ Out << "(offset: " << WPDRes.first << ", ";
+ printWPDRes(WPDRes.second);
+ Out << ")";
+ }
+ Out << ")";
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printArgs(const std::vector<uint64_t> &Args) {
+ Out << "args: (";
+ FieldSeparator FS;
+ for (auto arg : Args) {
+ Out << FS;
+ Out << arg;
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printWPDRes(const WholeProgramDevirtResolution &WPDRes) {
+ Out << "wpdRes: (kind: ";
+ Out << getWholeProgDevirtResKindName(WPDRes.TheKind);
+
+ if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl)
+ Out << ", singleImplName: \"" << WPDRes.SingleImplName << "\"";
+
+ if (!WPDRes.ResByArg.empty()) {
+ Out << ", resByArg: (";
+ FieldSeparator FS;
+ for (auto &ResByArg : WPDRes.ResByArg) {
+ Out << FS;
+ printArgs(ResByArg.first);
+ Out << ", byArg: (kind: ";
+ Out << getWholeProgDevirtResByArgKindName(ResByArg.second.TheKind);
+ if (ResByArg.second.TheKind ==
+ WholeProgramDevirtResolution::ByArg::UniformRetVal ||
+ ResByArg.second.TheKind ==
+ WholeProgramDevirtResolution::ByArg::UniqueRetVal)
+ Out << ", info: " << ResByArg.second.Info;
+
+ // The following fields are only used if the target does not support the
+ // use of absolute symbols to store constants. Print only if non-zero.
+ if (ResByArg.second.Byte || ResByArg.second.Bit)
+ Out << ", byte: " << ResByArg.second.Byte
+ << ", bit: " << ResByArg.second.Bit;
+
+ Out << ")";
+ }
+ Out << ")";
+ }
+ Out << ")";
+}
+
+static const char *getSummaryKindName(GlobalValueSummary::SummaryKind SK) {
+ switch (SK) {
+ case GlobalValueSummary::AliasKind:
+ return "alias";
+ case GlobalValueSummary::FunctionKind:
+ return "function";
+ case GlobalValueSummary::GlobalVarKind:
+ return "variable";
+ }
+ llvm_unreachable("invalid summary kind");
+}
+
+void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
+ Out << ", aliasee: ";
+ // The indexes emitted for distributed backends may not include the
+ // aliasee summary (only if it is being imported directly). Handle
+ // that case by just emitting "null" as the aliasee.
+ if (AS->hasAliasee())
+ Out << "^" << Machine.getGUIDSlot(SummaryToGUIDMap[&AS->getAliasee()]);
+ else
+ Out << "null";
+}
+
+void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
+ // Nothing for now
+}
+
+static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
+ switch (LT) {
+ case GlobalValue::ExternalLinkage:
+ return "external";
+ case GlobalValue::PrivateLinkage:
+ return "private";
+ case GlobalValue::InternalLinkage:
+ return "internal";
+ case GlobalValue::LinkOnceAnyLinkage:
+ return "linkonce";
+ case GlobalValue::LinkOnceODRLinkage:
+ return "linkonce_odr";
+ case GlobalValue::WeakAnyLinkage:
+ return "weak";
+ case GlobalValue::WeakODRLinkage:
+ return "weak_odr";
+ case GlobalValue::CommonLinkage:
+ return "common";
+ case GlobalValue::AppendingLinkage:
+ return "appending";
+ case GlobalValue::ExternalWeakLinkage:
+ return "extern_weak";
+ case GlobalValue::AvailableExternallyLinkage:
+ return "available_externally";
+ }
+ llvm_unreachable("invalid linkage");
+}
+
+// When printing the linkage types in IR where the ExternalLinkage is
+// not printed, and other linkage types are expected to be printed with
+// a space after the name.
+static std::string getLinkageNameWithSpace(GlobalValue::LinkageTypes LT) {
+ if (LT == GlobalValue::ExternalLinkage)
+ return "";
+ return getLinkageName(LT) + " ";
+}
+
+static const char *getHotnessName(CalleeInfo::HotnessType HT) {
+ switch (HT) {
+ case CalleeInfo::HotnessType::Unknown:
+ return "unknown";
+ case CalleeInfo::HotnessType::Cold:
+ return "cold";
+ case CalleeInfo::HotnessType::None:
+ return "none";
+ case CalleeInfo::HotnessType::Hot:
+ return "hot";
+ case CalleeInfo::HotnessType::Critical:
+ return "critical";
+ }
+ llvm_unreachable("invalid hotness");
+}
+
+void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) {
+ Out << ", insts: " << FS->instCount();
+
+ FunctionSummary::FFlags FFlags = FS->fflags();
+ if (FFlags.ReadNone | FFlags.ReadOnly | FFlags.NoRecurse |
+ FFlags.ReturnDoesNotAlias) {
+ Out << ", funcFlags: (";
+ Out << "readNone: " << FFlags.ReadNone;
+ Out << ", readOnly: " << FFlags.ReadOnly;
+ Out << ", noRecurse: " << FFlags.NoRecurse;
+ Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
+ Out << ")";
+ }
+ if (!FS->calls().empty()) {
+ Out << ", calls: (";
+ FieldSeparator IFS;
+ for (auto &Call : FS->calls()) {
+ Out << IFS;
+ Out << "(callee: ^" << Machine.getGUIDSlot(Call.first.getGUID());
+ if (Call.second.getHotness() != CalleeInfo::HotnessType::Unknown)
+ Out << ", hotness: " << getHotnessName(Call.second.getHotness());
+ else if (Call.second.RelBlockFreq)
+ Out << ", relbf: " << Call.second.RelBlockFreq;
+ Out << ")";
+ }
+ Out << ")";
+ }
+
+ if (const auto *TIdInfo = FS->getTypeIdInfo())
+ printTypeIdInfo(*TIdInfo);
+}
+
+void AssemblyWriter::printTypeIdInfo(
+ const FunctionSummary::TypeIdInfo &TIDInfo) {
+ Out << ", typeIdInfo: (";
+ FieldSeparator TIDFS;
+ if (!TIDInfo.TypeTests.empty()) {
+ Out << TIDFS;
+ Out << "typeTests: (";
+ FieldSeparator FS;
+ for (auto &GUID : TIDInfo.TypeTests) {
+ Out << FS;
+ auto Slot = Machine.getGUIDSlot(GUID);
+ if (Slot != -1)
+ Out << "^" << Slot;
+ else
+ Out << GUID;
+ }
+ Out << ")";
+ }
+ if (!TIDInfo.TypeTestAssumeVCalls.empty()) {
+ Out << TIDFS;
+ printNonConstVCalls(TIDInfo.TypeTestAssumeVCalls, "typeTestAssumeVCalls");
+ }
+ if (!TIDInfo.TypeCheckedLoadVCalls.empty()) {
+ Out << TIDFS;
+ printNonConstVCalls(TIDInfo.TypeCheckedLoadVCalls, "typeCheckedLoadVCalls");
+ }
+ if (!TIDInfo.TypeTestAssumeConstVCalls.empty()) {
+ Out << TIDFS;
+ printConstVCalls(TIDInfo.TypeTestAssumeConstVCalls,
+ "typeTestAssumeConstVCalls");
+ }
+ if (!TIDInfo.TypeCheckedLoadConstVCalls.empty()) {
+ Out << TIDFS;
+ printConstVCalls(TIDInfo.TypeCheckedLoadConstVCalls,
+ "typeCheckedLoadConstVCalls");
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printVFuncId(const FunctionSummary::VFuncId VFId) {
+ Out << "vFuncId: (";
+ auto Slot = Machine.getGUIDSlot(VFId.GUID);
+ if (Slot != -1)
+ Out << "^" << Slot;
+ else
+ Out << "guid: " << VFId.GUID;
+ Out << ", offset: " << VFId.Offset;
+ Out << ")";
+}
+
+void AssemblyWriter::printNonConstVCalls(
+ const std::vector<FunctionSummary::VFuncId> VCallList, const char *Tag) {
+ Out << Tag << ": (";
+ FieldSeparator FS;
+ for (auto &VFuncId : VCallList) {
+ Out << FS;
+ printVFuncId(VFuncId);
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printConstVCalls(
+ const std::vector<FunctionSummary::ConstVCall> VCallList, const char *Tag) {
+ Out << Tag << ": (";
+ FieldSeparator FS;
+ for (auto &ConstVCall : VCallList) {
+ Out << FS;
+ printVFuncId(ConstVCall.VFunc);
+ if (!ConstVCall.Args.empty()) {
+ Out << ", ";
+ printArgs(ConstVCall.Args);
+ }
+ }
+ Out << ")";
+}
+
+void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) {
+ GlobalValueSummary::GVFlags GVFlags = Summary.flags();
+ GlobalValue::LinkageTypes LT = (GlobalValue::LinkageTypes)GVFlags.Linkage;
+ Out << getSummaryKindName(Summary.getSummaryKind()) << ": ";
+ Out << "(module: ^" << Machine.getModulePathSlot(Summary.modulePath())
+ << ", flags: (";
+ Out << "linkage: " << getLinkageName(LT);
+ Out << ", notEligibleToImport: " << GVFlags.NotEligibleToImport;
+ Out << ", live: " << GVFlags.Live;
+ Out << ", dsoLocal: " << GVFlags.DSOLocal;
+ Out << ")";
+
+ if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind)
+ printAliasSummary(cast<AliasSummary>(&Summary));
+ else if (Summary.getSummaryKind() == GlobalValueSummary::FunctionKind)
+ printFunctionSummary(cast<FunctionSummary>(&Summary));
+ else
+ printGlobalVarSummary(cast<GlobalVarSummary>(&Summary));
+
+ auto RefList = Summary.refs();
+ if (!RefList.empty()) {
+ Out << ", refs: (";
+ FieldSeparator FS;
+ for (auto &Ref : RefList) {
+ Out << FS;
+ Out << "^" << Machine.getGUIDSlot(Ref.getGUID());
+ }
+ Out << ")";
+ }
+
+ Out << ")";
+}
+
+void AssemblyWriter::printSummaryInfo(unsigned Slot, const ValueInfo &VI) {
+ Out << "^" << Slot << " = gv: (";
+ if (!VI.name().empty())
+ Out << "name: \"" << VI.name() << "\"";
+ else
+ Out << "guid: " << VI.getGUID();
+ if (!VI.getSummaryList().empty()) {
+ Out << ", summaries: (";
+ FieldSeparator FS;
+ for (auto &Summary : VI.getSummaryList()) {
+ Out << FS;
+ printSummary(*Summary);
+ }
+ Out << ")";
+ }
+ Out << ")";
+ if (!VI.name().empty())
+ Out << " ; guid = " << VI.getGUID();
+ Out << "\n";
+}
+
static void printMetadataIdentifier(StringRef Name,
formatted_raw_ostream &Out) {
if (Name.empty()) {
@@ -2460,34 +3064,6 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
Out << "}\n";
}
-static const char *getLinkagePrintName(GlobalValue::LinkageTypes LT) {
- switch (LT) {
- case GlobalValue::ExternalLinkage:
- return "";
- case GlobalValue::PrivateLinkage:
- return "private ";
- case GlobalValue::InternalLinkage:
- return "internal ";
- case GlobalValue::LinkOnceAnyLinkage:
- return "linkonce ";
- case GlobalValue::LinkOnceODRLinkage:
- return "linkonce_odr ";
- case GlobalValue::WeakAnyLinkage:
- return "weak ";
- case GlobalValue::WeakODRLinkage:
- return "weak_odr ";
- case GlobalValue::CommonLinkage:
- return "common ";
- case GlobalValue::AppendingLinkage:
- return "appending ";
- case GlobalValue::ExternalWeakLinkage:
- return "extern_weak ";
- case GlobalValue::AvailableExternallyLinkage:
- return "available_externally ";
- }
- llvm_unreachable("invalid linkage");
-}
-
static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
formatted_raw_ostream &Out) {
switch (Vis) {
@@ -2497,8 +3073,13 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
}
}
-static void PrintDSOLocation(bool IsDSOLocal, formatted_raw_ostream &Out){
- if (IsDSOLocal)
+static void PrintDSOLocation(const GlobalValue &GV,
+ formatted_raw_ostream &Out) {
+ // GVs with local linkage or non default visibility are implicitly dso_local,
+ // so we don't print it.
+ bool Implicit = GV.hasLocalLinkage() ||
+ (!GV.hasExternalWeakLinkage() && !GV.hasDefaultVisibility());
+ if (GV.isDSOLocal() && !Implicit)
Out << "dso_local ";
}
@@ -2571,8 +3152,8 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (!GV->hasInitializer() && GV->hasExternalLinkage())
Out << "external ";
- Out << getLinkagePrintName(GV->getLinkage());
- PrintDSOLocation(GV->isDSOLocal(), Out);
+ Out << getLinkageNameWithSpace(GV->getLinkage());
+ PrintDSOLocation(*GV, Out);
PrintVisibility(GV->getVisibility(), Out);
PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
@@ -2593,7 +3174,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (GV->hasSection()) {
Out << ", section \"";
- PrintEscapedString(GV->getSection(), Out);
+ printEscapedString(GV->getSection(), Out);
Out << '"';
}
maybePrintComdat(Out, *GV);
@@ -2618,8 +3199,8 @@ void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) {
WriteAsOperandInternal(Out, GIS, &TypePrinter, &Machine, GIS->getParent());
Out << " = ";
- Out << getLinkagePrintName(GIS->getLinkage());
- PrintDSOLocation(GIS->isDSOLocal(), Out);
+ Out << getLinkageNameWithSpace(GIS->getLinkage());
+ PrintDSOLocation(*GIS, Out);
PrintVisibility(GIS->getVisibility(), Out);
PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);
PrintThreadLocalModel(GIS->getThreadLocalMode(), Out);
@@ -2656,39 +3237,30 @@ void AssemblyWriter::printComdat(const Comdat *C) {
}
void AssemblyWriter::printTypeIdentities() {
- if (TypePrinter.NumberedTypes.empty() &&
- TypePrinter.NamedTypes.empty())
+ if (TypePrinter.empty())
return;
Out << '\n';
- // We know all the numbers that each type is used and we know that it is a
- // dense assignment. Convert the map to an index table.
- std::vector<StructType*> NumberedTypes(TypePrinter.NumberedTypes.size());
- for (DenseMap<StructType*, unsigned>::iterator I =
- TypePrinter.NumberedTypes.begin(), E = TypePrinter.NumberedTypes.end();
- I != E; ++I) {
- assert(I->second < NumberedTypes.size() && "Didn't get a dense numbering?");
- NumberedTypes[I->second] = I->first;
- }
-
// Emit all numbered types.
- for (unsigned i = 0, e = NumberedTypes.size(); i != e; ++i) {
- Out << '%' << i << " = type ";
+ auto &NumberedTypes = TypePrinter.getNumberedTypes();
+ for (unsigned I = 0, E = NumberedTypes.size(); I != E; ++I) {
+ Out << '%' << I << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %2 = type %2
- TypePrinter.printStructBody(NumberedTypes[i], Out);
+ TypePrinter.printStructBody(NumberedTypes[I], Out);
Out << '\n';
}
- for (unsigned i = 0, e = TypePrinter.NamedTypes.size(); i != e; ++i) {
- PrintLLVMName(Out, TypePrinter.NamedTypes[i]->getName(), LocalPrefix);
+ auto &NamedTypes = TypePrinter.getNamedTypes();
+ for (unsigned I = 0, E = NamedTypes.size(); I != E; ++I) {
+ PrintLLVMName(Out, NamedTypes[I]->getName(), LocalPrefix);
Out << " = type ";
// Make sure we print out at least one level of the type structure, so
// that we do not get %FILE = type %FILE
- TypePrinter.printStructBody(TypePrinter.NamedTypes[i], Out);
+ TypePrinter.printStructBody(NamedTypes[I], Out);
Out << '\n';
}
}
@@ -2730,8 +3302,8 @@ void AssemblyWriter::printFunction(const Function *F) {
} else
Out << "define ";
- Out << getLinkagePrintName(F->getLinkage());
- PrintDSOLocation(F->isDSOLocal(), Out);
+ Out << getLinkageNameWithSpace(F->getLinkage());
+ PrintDSOLocation(*F, Out);
PrintVisibility(F->getVisibility(), Out);
PrintDLLStorageClass(F->getDLLStorageClass(), Out);
@@ -2786,7 +3358,7 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes());
if (F->hasSection()) {
Out << " section \"";
- PrintEscapedString(F->getSection(), Out);
+ printEscapedString(F->getSection(), Out);
Out << '"';
}
maybePrintComdat(Out, *F);
@@ -3558,9 +4130,7 @@ static bool printWithoutType(const Value &V, raw_ostream &O,
static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
ModuleSlotTracker &MST) {
- TypePrinting TypePrinter;
- if (const Module *M = MST.getModule())
- TypePrinter.incorporateTypes(*M);
+ TypePrinting TypePrinter(MST.getModule());
if (PrintType) {
TypePrinter.print(V.getType(), O);
O << ' ';
@@ -3599,9 +4169,7 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
bool OnlyAsOperand) {
formatted_raw_ostream OS(ROS);
- TypePrinting TypePrinter;
- if (M)
- TypePrinter.incorporateTypes(*M);
+ TypePrinting TypePrinter(M);
WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M,
/* FromValue */ true);
@@ -3635,6 +4203,13 @@ void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
}
+void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
+ SlotTracker SlotTable(this);
+ formatted_raw_ostream OS(ROS);
+ AssemblyWriter W(OS, SlotTable, this, IsForDebug);
+ W.printModuleSummaryIndex();
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
// Value::dump - allow easy printing of Values from the debugger.
LLVM_DUMP_METHOD
@@ -3651,7 +4226,7 @@ void Module::dump() const {
/*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
}
-// \brief Allow printing of Comdats from the debugger.
+// Allow printing of Comdats from the debugger.
LLVM_DUMP_METHOD
void Comdat::dump() const { print(dbgs(), /*IsForDebug=*/true); }
@@ -3667,4 +4242,8 @@ void Metadata::dump(const Module *M) const {
print(dbgs(), M, /*IsForDebug=*/true);
dbgs() << '\n';
}
+
+// Allow printing of ModuleSummaryIndex from the debugger.
+LLVM_DUMP_METHOD
+void ModuleSummaryIndex::dump() const { print(dbgs(), /*IsForDebug=*/true); }
#endif
diff --git a/contrib/llvm/lib/IR/AttributeImpl.h b/contrib/llvm/lib/IR/AttributeImpl.h
index 9c7b61f67923..bb0c072e4781 100644
--- a/contrib/llvm/lib/IR/AttributeImpl.h
+++ b/contrib/llvm/lib/IR/AttributeImpl.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
///
/// \file
-/// \brief This file defines various helper methods and classes used by
+/// This file defines various helper methods and classes used by
/// LLVMContextImpl for creating and managing attributes.
///
//===----------------------------------------------------------------------===//
@@ -33,7 +33,7 @@ class LLVMContext;
//===----------------------------------------------------------------------===//
/// \class
-/// \brief This class represents a single, uniqued attribute. That attribute
+/// This class represents a single, uniqued attribute. That attribute
/// could be a single enum, a tuple, or a string.
class AttributeImpl : public FoldingSetNode {
unsigned char KindID; ///< Holds the AttrEntryKind of the attribute
@@ -67,7 +67,7 @@ public:
StringRef getKindAsString() const;
StringRef getValueAsString() const;
- /// \brief Used when sorting the attributes.
+ /// Used when sorting the attributes.
bool operator<(const AttributeImpl &AI) const;
void Profile(FoldingSetNodeID &ID) const {
@@ -93,7 +93,7 @@ public:
//===----------------------------------------------------------------------===//
/// \class
-/// \brief A set of classes that contain the value of the
+/// A set of classes that contain the value of the
/// attribute object. There are three main categories: enum attribute entries,
/// represented by Attribute::AttrKind; alignment attribute entries; and string
/// attribute enties, which are for target-dependent attributes.
@@ -148,7 +148,7 @@ public:
//===----------------------------------------------------------------------===//
/// \class
-/// \brief This class represents a group of attributes that apply to one
+/// This class represents a group of attributes that apply to one
/// element: function, return type, or parameter.
class AttributeSetNode final
: public FoldingSetNode,
@@ -172,7 +172,7 @@ public:
static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
- /// \brief Return the number of attributes this AttributeList contains.
+ /// Return the number of attributes this AttributeList contains.
unsigned getNumAttributes() const { return NumAttrs; }
bool hasAttribute(Attribute::AttrKind Kind) const {
@@ -210,7 +210,7 @@ using IndexAttrPair = std::pair<unsigned, AttributeSet>;
//===----------------------------------------------------------------------===//
/// \class
-/// \brief This class represents a set of attributes that apply to the function,
+/// This class represents a set of attributes that apply to the function,
/// return type, and parameters.
class AttributeListImpl final
: public FoldingSetNode,
@@ -236,10 +236,10 @@ public:
void operator delete(void *p) { ::operator delete(p); }
- /// \brief Get the context that created this AttributeListImpl.
+ /// Get the context that created this AttributeListImpl.
LLVMContext &getContext() { return Context; }
- /// \brief Return true if the AttributeSet or the FunctionIndex has an
+ /// Return true if the AttributeSet or the FunctionIndex has an
/// enum attribute of the given kind.
bool hasFnAttribute(Attribute::AttrKind Kind) const {
return AvailableFunctionAttrs & ((uint64_t)1) << Kind;
diff --git a/contrib/llvm/lib/IR/Attributes.cpp b/contrib/llvm/lib/IR/Attributes.cpp
index 1b19a0474727..9e5f55d49756 100644
--- a/contrib/llvm/lib/IR/Attributes.cpp
+++ b/contrib/llvm/lib/IR/Attributes.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// \file
-// \brief This file implements the Attribute, AttributeImpl, AttrBuilder,
+// This file implements the Attribute, AttributeImpl, AttrBuilder,
// AttributeListImpl, and AttributeList classes.
//
//===----------------------------------------------------------------------===//
@@ -24,6 +24,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
@@ -38,7 +39,6 @@
#include <cstddef>
#include <cstdint>
#include <limits>
-#include <map>
#include <string>
#include <tuple>
#include <utility>
@@ -186,14 +186,14 @@ uint64_t Attribute::getValueAsInt() const {
}
StringRef Attribute::getKindAsString() const {
- if (!pImpl) return StringRef();
+ if (!pImpl) return {};
assert(isStringAttribute() &&
"Invalid attribute type to get the kind as a string!");
return pImpl->getKindAsString();
}
StringRef Attribute::getValueAsString() const {
- if (!pImpl) return StringRef();
+ if (!pImpl) return {};
assert(isStringAttribute() &&
"Invalid attribute type to get the value as a string!");
return pImpl->getValueAsString();
@@ -241,7 +241,7 @@ std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const {
}
std::string Attribute::getAsString(bool InAttrGrp) const {
- if (!pImpl) return "";
+ if (!pImpl) return {};
if (hasAttribute(Attribute::SanitizeAddress))
return "sanitize_address";
@@ -299,10 +299,14 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noredzone";
if (hasAttribute(Attribute::NoReturn))
return "noreturn";
+ if (hasAttribute(Attribute::NoCfCheck))
+ return "nocf_check";
if (hasAttribute(Attribute::NoRecurse))
return "norecurse";
if (hasAttribute(Attribute::NoUnwind))
return "nounwind";
+ if (hasAttribute(Attribute::OptForFuzzing))
+ return "optforfuzzing";
if (hasAttribute(Attribute::OptimizeNone))
return "optnone";
if (hasAttribute(Attribute::OptimizeForSize))
@@ -329,6 +333,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "sspstrong";
if (hasAttribute(Attribute::SafeStack))
return "safestack";
+ if (hasAttribute(Attribute::ShadowCallStack))
+ return "shadowcallstack";
if (hasAttribute(Attribute::StrictFP))
return "strictfp";
if (hasAttribute(Attribute::StructRet))
@@ -413,7 +419,7 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
{
raw_string_ostream OS(Result);
OS << "=\"";
- PrintEscapedString(AttrVal, OS);
+ printEscapedString(AttrVal, OS);
OS << "\"";
}
return Result;
@@ -534,7 +540,7 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
return *this;
AttrBuilder B(AS);
- for (Attribute I : *this)
+ for (const auto I : *this)
B.addAttribute(I);
return get(C, B);
@@ -543,26 +549,21 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, B);
+ AttrBuilder B(*this);
+ B.removeAttribute(Kind);
+ return get(C, B);
}
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
StringRef Kind) const {
if (!hasAttribute(Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, B);
+ AttrBuilder B(*this);
+ B.removeAttribute(Kind);
+ return get(C, B);
}
AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
const AttrBuilder &Attrs) const {
-
- // FIXME it is not obvious how this should work for alignment.
- // For now, say we can't pass in alignment, which no current use does.
- assert(!Attrs.hasAlignmentAttr() && "Attempt to change alignment!");
-
AttrBuilder B(*this);
B.remove(Attrs);
return get(C, B);
@@ -638,7 +639,7 @@ AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
// There's memory after the node where we can store the entries in.
std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());
- for (Attribute I : *this) {
+ for (const auto I : *this) {
if (!I.isStringAttribute()) {
AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
}
@@ -655,9 +656,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C,
FoldingSetNodeID ID;
SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end());
- std::sort(SortedAttrs.begin(), SortedAttrs.end());
+ llvm::sort(SortedAttrs.begin(), SortedAttrs.end());
- for (Attribute Attr : SortedAttrs)
+ for (const auto Attr : SortedAttrs)
Attr.Profile(ID);
void *InsertPoint;
@@ -720,7 +721,7 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
}
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return true;
return false;
@@ -728,43 +729,43 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const {
Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
if (hasAttribute(Kind)) {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return I;
}
- return Attribute();
+ return {};
}
Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Kind))
return I;
- return Attribute();
+ return {};
}
unsigned AttributeSetNode::getAlignment() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::Alignment))
return I.getAlignment();
return 0;
}
unsigned AttributeSetNode::getStackAlignment() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::StackAlignment))
return I.getStackAlignment();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableBytes() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::Dereferenceable))
return I.getDereferenceableBytes();
return 0;
}
uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::DereferenceableOrNull))
return I.getDereferenceableOrNullBytes();
return 0;
@@ -772,7 +773,7 @@ uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
std::pair<unsigned, Optional<unsigned>>
AttributeSetNode::getAllocSizeArgs() const {
- for (Attribute I : *this)
+ for (const auto I : *this)
if (I.hasAttribute(Attribute::AllocSize))
return I.getAllocSizeArgs();
return std::make_pair(0, 0);
@@ -814,7 +815,7 @@ AttributeListImpl::AttributeListImpl(LLVMContext &C,
"Too many attributes");
static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
"function should be stored in slot 0");
- for (Attribute I : Sets[0]) {
+ for (const auto I : Sets[0]) {
if (!I.isStringAttribute())
AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum();
}
@@ -871,17 +872,17 @@ AttributeList::get(LLVMContext &C,
ArrayRef<std::pair<unsigned, Attribute>> Attrs) {
// If there are no attributes then return a null AttributesList pointer.
if (Attrs.empty())
- return AttributeList();
+ return {};
assert(std::is_sorted(Attrs.begin(), Attrs.end(),
[](const std::pair<unsigned, Attribute> &LHS,
const std::pair<unsigned, Attribute> &RHS) {
return LHS.first < RHS.first;
}) && "Misordered Attributes list!");
- assert(none_of(Attrs,
- [](const std::pair<unsigned, Attribute> &Pair) {
- return Pair.second.hasAttribute(Attribute::None);
- }) &&
+ assert(llvm::none_of(Attrs,
+ [](const std::pair<unsigned, Attribute> &Pair) {
+ return Pair.second.hasAttribute(Attribute::None);
+ }) &&
"Pointless attribute!");
// Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes
@@ -907,7 +908,7 @@ AttributeList::get(LLVMContext &C,
ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) {
// If there are no attributes then return a null AttributesList pointer.
if (Attrs.empty())
- return AttributeList();
+ return {};
assert(std::is_sorted(Attrs.begin(), Attrs.end(),
[](const std::pair<unsigned, AttributeSet> &LHS,
@@ -915,16 +916,20 @@ AttributeList::get(LLVMContext &C,
return LHS.first < RHS.first;
}) &&
"Misordered Attributes list!");
- assert(none_of(Attrs,
- [](const std::pair<unsigned, AttributeSet> &Pair) {
- return !Pair.second.hasAttributes();
- }) &&
+ assert(llvm::none_of(Attrs,
+ [](const std::pair<unsigned, AttributeSet> &Pair) {
+ return !Pair.second.hasAttributes();
+ }) &&
"Pointless attribute!");
unsigned MaxIndex = Attrs.back().first;
+ // If the MaxIndex is FunctionIndex and there are other indices in front
+ // of it, we need to use the largest of those to get the right size.
+ if (MaxIndex == FunctionIndex && Attrs.size() > 1)
+ MaxIndex = Attrs[Attrs.size() - 2].first;
SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1);
- for (auto Pair : Attrs)
+ for (const auto Pair : Attrs)
AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second;
return getImpl(C, AttrVec);
@@ -954,7 +959,7 @@ AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
// If all attribute sets were empty, we can use the empty attribute list.
if (NumSets == 0)
- return AttributeList();
+ return {};
SmallVector<AttributeSet, 8> AttrSets;
AttrSets.reserve(NumSets);
@@ -974,7 +979,7 @@ AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
const AttrBuilder &B) {
if (!B.hasAttributes())
- return AttributeList();
+ return {};
Index = attrIdxToArrayIdx(Index);
SmallVector<AttributeSet, 8> AttrSets(Index + 1);
AttrSets[Index] = AttributeSet::get(C, B);
@@ -984,7 +989,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
ArrayRef<Attribute::AttrKind> Kinds) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (Attribute::AttrKind K : Kinds)
+ for (const auto K : Kinds)
Attrs.emplace_back(Index, Attribute::get(C, K));
return get(C, Attrs);
}
@@ -992,7 +997,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
ArrayRef<StringRef> Kinds) {
SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
- for (StringRef K : Kinds)
+ for (const auto K : Kinds)
Attrs.emplace_back(Index, Attribute::get(C, K));
return get(C, Attrs);
}
@@ -1000,22 +1005,22 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
AttributeList AttributeList::get(LLVMContext &C,
ArrayRef<AttributeList> Attrs) {
if (Attrs.empty())
- return AttributeList();
+ return {};
if (Attrs.size() == 1)
return Attrs[0];
unsigned MaxSize = 0;
- for (AttributeList List : Attrs)
+ for (const auto List : Attrs)
MaxSize = std::max(MaxSize, List.getNumAttrSets());
// If every list was empty, there is no point in merging the lists.
if (MaxSize == 0)
- return AttributeList();
+ return {};
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
for (unsigned I = 0; I < MaxSize; ++I) {
AttrBuilder CurBuilder;
- for (AttributeList List : Attrs)
+ for (const auto List : Attrs)
CurBuilder.merge(List.getAttributes(I - 1));
NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
}
@@ -1098,37 +1103,41 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C,
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Index, Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, Index, B);
+
+ Index = attrIdxToArrayIdx(Index);
+ SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
+ assert(Index < AttrSets.size());
+
+ AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
+
+ return getImpl(C, AttrSets);
}
AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
StringRef Kind) const {
if (!hasAttribute(Index, Kind)) return *this;
- AttrBuilder B;
- B.addAttribute(Kind);
- return removeAttributes(C, Index, B);
+
+ Index = attrIdxToArrayIdx(Index);
+ SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
+ assert(Index < AttrSets.size());
+
+ AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind);
+
+ return getImpl(C, AttrSets);
}
AttributeList
AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
const AttrBuilder &AttrsToRemove) const {
if (!pImpl)
- return AttributeList();
-
- // FIXME it is not obvious how this should work for alignment.
- // For now, say we can't pass in alignment, which no current use does.
- assert(!AttrsToRemove.hasAlignmentAttr() && "Attempt to change alignment!");
+ return {};
Index = attrIdxToArrayIdx(Index);
SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end());
if (Index >= AttrSets.size())
AttrSets.resize(Index + 1);
- AttrBuilder B(AttrSets[Index]);
- B.remove(AttrsToRemove);
- AttrSets[Index] = AttributeSet::get(C, B);
+ AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove);
return getImpl(C, AttrSets);
}
@@ -1136,7 +1145,7 @@ AttributeList::removeAttributes(LLVMContext &C, unsigned Index,
AttributeList AttributeList::removeAttributes(LLVMContext &C,
unsigned WithoutIndex) const {
if (!pImpl)
- return AttributeList();
+ return {};
WithoutIndex = attrIdxToArrayIdx(WithoutIndex);
if (WithoutIndex >= getNumAttrSets())
return *this;
@@ -1270,7 +1279,7 @@ std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
AttributeSet AttributeList::getAttributes(unsigned Index) const {
Index = attrIdxToArrayIdx(Index);
if (!pImpl || Index >= getNumAttrSets())
- return AttributeSet();
+ return {};
return pImpl->begin()[Index];
}
@@ -1310,12 +1319,12 @@ LLVM_DUMP_METHOD void AttributeList::dump() const {
// FIXME: Remove this ctor, use AttributeSet.
AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
AttributeSet AS = AL.getAttributes(Index);
- for (const Attribute &A : AS)
+ for (const auto &A : AS)
addAttribute(A);
}
AttrBuilder::AttrBuilder(AttributeSet AS) {
- for (const Attribute &A : AS)
+ for (const auto &A : AS)
addAttribute(A);
}
@@ -1386,7 +1395,7 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
}
AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
- std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A);
+ auto I = TargetDepAttrs.find(A);
if (I != TargetDepAttrs.end())
TargetDepAttrs.erase(I);
return *this;
@@ -1526,7 +1535,7 @@ bool AttrBuilder::hasAttributes() const {
bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
AttributeSet AS = AL.getAttributes(Index);
- for (Attribute Attr : AS) {
+ for (const auto Attr : AS) {
if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
if (contains(Attr.getKindAsEnum()))
return true;
@@ -1560,7 +1569,7 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
// AttributeFuncs Function Defintions
//===----------------------------------------------------------------------===//
-/// \brief Which attributes cannot be applied to a type.
+/// Which attributes cannot be applied to a type.
AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
AttrBuilder Incompatible;
@@ -1592,7 +1601,7 @@ static bool isEqual(const Function &Caller, const Function &Callee) {
Callee.getFnAttribute(AttrClass::getKind());
}
-/// \brief Compute the logical AND of the attributes of the caller and the
+/// Compute the logical AND of the attributes of the caller and the
/// callee.
///
/// This function sets the caller's attribute to false if the callee's attribute
@@ -1604,7 +1613,7 @@ static void setAND(Function &Caller, const Function &Callee) {
AttrClass::set(Caller, AttrClass::getKind(), false);
}
-/// \brief Compute the logical OR of the attributes of the caller and the
+/// Compute the logical OR of the attributes of the caller and the
/// callee.
///
/// This function sets the caller's attribute to true if the callee's attribute
@@ -1616,7 +1625,7 @@ static void setOR(Function &Caller, const Function &Callee) {
AttrClass::set(Caller, AttrClass::getKind(), true);
}
-/// \brief If the inlined function had a higher stack protection level than the
+/// If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
// If upgrading the SSP attribute, clear out the old SSP Attributes first.
@@ -1640,7 +1649,7 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
Caller.addFnAttr(Attribute::StackProtect);
}
-/// \brief If the inlined function required stack probes, then ensure that
+/// If the inlined function required stack probes, then ensure that
/// the calling function has those too.
static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
if (!Caller.hasFnAttribute("probe-stack") &&
@@ -1649,7 +1658,7 @@ static void adjustCallerStackProbes(Function &Caller, const Function &Callee) {
}
}
-/// \brief If the inlined function defines the size of guard region
+/// If the inlined function defines the size of guard region
/// on the stack, then ensure that the calling function defines a guard region
/// that is no larger.
static void
@@ -1673,6 +1682,33 @@ adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
}
}
+/// If the inlined function defines a min legal vector width, then ensure
+/// the calling function has the same or larger min legal vector width. This
+/// function is called after the inlining decision has been made so we have to
+/// merge the attribute this way. Heuristics that would use
+/// min-legal-vector-width to determine inline compatibility would need to be
+/// handled as part of inline cost analysis.
+static void
+adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
+ if (Callee.hasFnAttribute("min-legal-vector-width")) {
+ uint64_t CalleeVectorWidth;
+ Callee.getFnAttribute("min-legal-vector-width")
+ .getValueAsString()
+ .getAsInteger(0, CalleeVectorWidth);
+ if (Caller.hasFnAttribute("min-legal-vector-width")) {
+ uint64_t CallerVectorWidth;
+ Caller.getFnAttribute("min-legal-vector-width")
+ .getValueAsString()
+ .getAsInteger(0, CallerVectorWidth);
+ if (CallerVectorWidth < CalleeVectorWidth) {
+ Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
+ }
+ } else {
+ Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width"));
+ }
+ }
+}
+
#define GET_ATTR_COMPAT_FUNC
#include "AttributesCompatFunc.inc"
diff --git a/contrib/llvm/lib/IR/AutoUpgrade.cpp b/contrib/llvm/lib/IR/AutoUpgrade.cpp
index c56a022c6705..ef62a23b5358 100644
--- a/contrib/llvm/lib/IR/AutoUpgrade.cpp
+++ b/contrib/llvm/lib/IR/AutoUpgrade.cpp
@@ -22,6 +22,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
@@ -73,11 +74,36 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
if (Name=="ssse3.pabs.b.128" || // Added in 6.0
Name=="ssse3.pabs.w.128" || // Added in 6.0
Name=="ssse3.pabs.d.128" || // Added in 6.0
+ Name.startswith("fma4.vfmadd.s") || // Added in 7.0
+ Name.startswith("fma.vfmadd.") || // Added in 7.0
+ Name.startswith("fma.vfmsub.") || // Added in 7.0
+ Name.startswith("fma.vfmaddsub.") || // Added in 7.0
+ Name.startswith("fma.vfmsubadd.") || // Added in 7.0
+ Name.startswith("fma.vfnmadd.") || // Added in 7.0
+ Name.startswith("fma.vfnmsub.") || // Added in 7.0
+ Name.startswith("avx512.mask.vfmadd.") || // Added in 7.0
+ Name.startswith("avx512.mask.vfnmadd.") || // Added in 7.0
+ Name.startswith("avx512.mask.vfnmsub.") || // Added in 7.0
+ Name.startswith("avx512.mask3.vfmadd.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vfmadd.") || // Added in 7.0
+ Name.startswith("avx512.mask3.vfmsub.") || // Added in 7.0
+ Name.startswith("avx512.mask3.vfnmsub.") || // Added in 7.0
+ Name.startswith("avx512.mask.vfmaddsub.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vfmaddsub.") || // Added in 7.0
+ Name.startswith("avx512.mask3.vfmaddsub.") || // Added in 7.0
+ Name.startswith("avx512.mask3.vfmsubadd.") || // Added in 7.0
Name.startswith("avx512.mask.shuf.i") || // Added in 6.0
Name.startswith("avx512.mask.shuf.f") || // Added in 6.0
+ Name.startswith("avx512.kunpck") || //added in 6.0
Name.startswith("avx2.pabs.") || // Added in 6.0
Name.startswith("avx512.mask.pabs.") || // Added in 6.0
Name.startswith("avx512.broadcastm") || // Added in 6.0
+ Name == "sse.sqrt.ss" || // Added in 7.0
+ Name == "sse2.sqrt.sd" || // Added in 7.0
+ Name.startswith("avx512.mask.sqrt.p") || // Added in 7.0
+ Name.startswith("avx.sqrt.p") || // Added in 7.0
+ Name.startswith("sse2.sqrt.p") || // Added in 7.0
+ Name.startswith("sse.sqrt.p") || // Added in 7.0
Name.startswith("avx512.mask.pbroadcast") || // Added in 6.0
Name.startswith("sse2.pcmpeq.") || // Added in 3.1
Name.startswith("sse2.pcmpgt.") || // Added in 3.1
@@ -107,6 +133,14 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
Name == "sse2.pminu.b" || // Added in 3.9
Name == "sse41.pminuw" || // Added in 3.9
Name == "sse41.pminud" || // Added in 3.9
+ Name == "avx512.kand.w" || // Added in 7.0
+ Name == "avx512.kandn.w" || // Added in 7.0
+ Name == "avx512.knot.w" || // Added in 7.0
+ Name == "avx512.kor.w" || // Added in 7.0
+ Name == "avx512.kxor.w" || // Added in 7.0
+ Name == "avx512.kxnor.w" || // Added in 7.0
+ Name == "avx512.kortestc.w" || // Added in 7.0
+ Name == "avx512.kortestz.w" || // Added in 7.0
Name.startswith("avx512.mask.pshuf.b.") || // Added in 4.0
Name.startswith("avx2.pmax") || // Added in 3.9
Name.startswith("avx2.pmin") || // Added in 3.9
@@ -145,8 +179,37 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
Name.startswith("avx512.mask.pmull.") || // Added in 4.0
Name.startswith("avx512.mask.cvtdq2pd.") || // Added in 4.0
Name.startswith("avx512.mask.cvtudq2pd.") || // Added in 4.0
+ Name == "avx512.mask.cvtudq2ps.128" || // Added in 7.0
+ Name == "avx512.mask.cvtudq2ps.256" || // Added in 7.0
+ Name == "avx512.mask.cvtqq2pd.128" || // Added in 7.0
+ Name == "avx512.mask.cvtqq2pd.256" || // Added in 7.0
+ Name == "avx512.mask.cvtuqq2pd.128" || // Added in 7.0
+ Name == "avx512.mask.cvtuqq2pd.256" || // Added in 7.0
+ Name == "avx512.mask.cvtdq2ps.128" || // Added in 7.0
+ Name == "avx512.mask.cvtdq2ps.256" || // Added in 7.0
+ Name == "avx512.mask.cvtpd2dq.256" || // Added in 7.0
+ Name == "avx512.mask.cvtpd2ps.256" || // Added in 7.0
+ Name == "avx512.mask.cvttpd2dq.256" || // Added in 7.0
+ Name == "avx512.mask.cvttps2dq.128" || // Added in 7.0
+ Name == "avx512.mask.cvttps2dq.256" || // Added in 7.0
+ Name == "avx512.mask.cvtps2pd.128" || // Added in 7.0
+ Name == "avx512.mask.cvtps2pd.256" || // Added in 7.0
+ Name == "avx512.cvtusi2sd" || // Added in 7.0
+ Name.startswith("avx512.mask.permvar.") || // Added in 7.0
+ Name.startswith("avx512.mask.permvar.") || // Added in 7.0
+ Name == "sse2.pmulu.dq" || // Added in 7.0
+ Name == "sse41.pmuldq" || // Added in 7.0
+ Name == "avx2.pmulu.dq" || // Added in 7.0
+ Name == "avx2.pmul.dq" || // Added in 7.0
+ Name == "avx512.pmulu.dq.512" || // Added in 7.0
+ Name == "avx512.pmul.dq.512" || // Added in 7.0
Name.startswith("avx512.mask.pmul.dq.") || // Added in 4.0
Name.startswith("avx512.mask.pmulu.dq.") || // Added in 4.0
+ Name.startswith("avx512.mask.pmul.hr.sw.") || // Added in 7.0
+ Name.startswith("avx512.mask.pmulh.w.") || // Added in 7.0
+ Name.startswith("avx512.mask.pmulhu.w.") || // Added in 7.0
+ Name.startswith("avx512.mask.pmaddw.d.") || // Added in 7.0
+ Name.startswith("avx512.mask.pmaddubs.w.") || // Added in 7.0
Name.startswith("avx512.mask.packsswb.") || // Added in 5.0
Name.startswith("avx512.mask.packssdw.") || // Added in 5.0
Name.startswith("avx512.mask.packuswb.") || // Added in 5.0
@@ -155,31 +218,12 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
Name.startswith("avx512.mask.cmp.d") || // Added in 5.0
Name.startswith("avx512.mask.cmp.q") || // Added in 5.0
Name.startswith("avx512.mask.cmp.w") || // Added in 5.0
+ Name.startswith("avx512.mask.cmp.p") || // Added in 7.0
Name.startswith("avx512.mask.ucmp.") || // Added in 5.0
- Name == "avx512.mask.add.pd.128" || // Added in 4.0
- Name == "avx512.mask.add.pd.256" || // Added in 4.0
- Name == "avx512.mask.add.ps.128" || // Added in 4.0
- Name == "avx512.mask.add.ps.256" || // Added in 4.0
- Name == "avx512.mask.div.pd.128" || // Added in 4.0
- Name == "avx512.mask.div.pd.256" || // Added in 4.0
- Name == "avx512.mask.div.ps.128" || // Added in 4.0
- Name == "avx512.mask.div.ps.256" || // Added in 4.0
- Name == "avx512.mask.mul.pd.128" || // Added in 4.0
- Name == "avx512.mask.mul.pd.256" || // Added in 4.0
- Name == "avx512.mask.mul.ps.128" || // Added in 4.0
- Name == "avx512.mask.mul.ps.256" || // Added in 4.0
- Name == "avx512.mask.sub.pd.128" || // Added in 4.0
- Name == "avx512.mask.sub.pd.256" || // Added in 4.0
- Name == "avx512.mask.sub.ps.128" || // Added in 4.0
- Name == "avx512.mask.sub.ps.256" || // Added in 4.0
- Name == "avx512.mask.max.pd.128" || // Added in 5.0
- Name == "avx512.mask.max.pd.256" || // Added in 5.0
- Name == "avx512.mask.max.ps.128" || // Added in 5.0
- Name == "avx512.mask.max.ps.256" || // Added in 5.0
- Name == "avx512.mask.min.pd.128" || // Added in 5.0
- Name == "avx512.mask.min.pd.256" || // Added in 5.0
- Name == "avx512.mask.min.ps.128" || // Added in 5.0
- Name == "avx512.mask.min.ps.256" || // Added in 5.0
+ Name.startswith("avx512.cvtb2mask.") || // Added in 7.0
+ Name.startswith("avx512.cvtw2mask.") || // Added in 7.0
+ Name.startswith("avx512.cvtd2mask.") || // Added in 7.0
+ Name.startswith("avx512.cvtq2mask.") || // Added in 7.0
Name.startswith("avx512.mask.vpermilvar.") || // Added in 4.0
Name.startswith("avx512.mask.psll.d") || // Added in 4.0
Name.startswith("avx512.mask.psll.q") || // Added in 4.0
@@ -203,9 +247,45 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
Name.startswith("avx512.mask.pmovsx") || // Added in 4.0
Name.startswith("avx512.mask.pmovzx") || // Added in 4.0
Name.startswith("avx512.mask.lzcnt.") || // Added in 5.0
+ Name.startswith("avx512.mask.pternlog.") || // Added in 7.0
+ Name.startswith("avx512.maskz.pternlog.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpmadd52") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpmadd52") || // Added in 7.0
+ Name.startswith("avx512.mask.vpermi2var.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpermt2var.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpermt2var.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpdpbusd.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpdpbusd.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpdpbusds.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpdpbusds.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpdpwssd.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpdpwssd.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpdpwssds.") || // Added in 7.0
+ Name.startswith("avx512.maskz.vpdpwssds.") || // Added in 7.0
+ Name.startswith("avx512.mask.dbpsadbw.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpshld.") || // Added in 7.0
+ Name.startswith("avx512.mask.vpshrd.") || // Added in 7.0
+ Name.startswith("avx512.mask.add.p") || // Added in 7.0. 128/256 in 4.0
+ Name.startswith("avx512.mask.sub.p") || // Added in 7.0. 128/256 in 4.0
+ Name.startswith("avx512.mask.mul.p") || // Added in 7.0. 128/256 in 4.0
+ Name.startswith("avx512.mask.div.p") || // Added in 7.0. 128/256 in 4.0
+ Name.startswith("avx512.mask.max.p") || // Added in 7.0. 128/256 in 5.0
+ Name.startswith("avx512.mask.min.p") || // Added in 7.0. 128/256 in 5.0
+ Name.startswith("avx512.mask.fpclass.p") || // Added in 7.0
+ Name.startswith("avx512.mask.prorv.") || // Added in 7.0
+ Name.startswith("avx512.mask.pror.") || // Added in 7.0
+ Name.startswith("avx512.mask.prolv.") || // Added in 7.0
+ Name.startswith("avx512.mask.prol.") || // Added in 7.0
+ Name == "sse.cvtsi2ss" || // Added in 7.0
+ Name == "sse.cvtsi642ss" || // Added in 7.0
+ Name == "sse2.cvtsi2sd" || // Added in 7.0
+ Name == "sse2.cvtsi642sd" || // Added in 7.0
+ Name == "sse2.cvtss2sd" || // Added in 7.0
Name == "sse2.cvtdq2pd" || // Added in 3.9
+ Name == "sse2.cvtdq2ps" || // Added in 7.0
Name == "sse2.cvtps2pd" || // Added in 3.9
Name == "avx.cvtdq2.pd.256" || // Added in 3.9
+ Name == "avx.cvtdq2.ps.256" || // Added in 7.0
Name == "avx.cvt.ps2.pd.256" || // Added in 3.9
Name.startswith("avx.vinsertf128.") || // Added in 3.7
Name == "avx2.vinserti128" || // Added in 3.7
@@ -229,10 +309,14 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {
Name.startswith("avx512.mask.store.w.") || // Added in 3.9
Name.startswith("avx512.mask.store.d.") || // Added in 3.9
Name.startswith("avx512.mask.store.q.") || // Added in 3.9
+ Name == "avx512.mask.store.ss" || // Added in 7.0
Name.startswith("avx512.mask.loadu.") || // Added in 3.9
Name.startswith("avx512.mask.load.") || // Added in 3.9
+ Name.startswith("avx512.mask.expand.load.") || // Added in 7.0
+ Name.startswith("avx512.mask.compress.store.") || // Added in 7.0
Name == "sse42.crc32.64.8" || // Added in 3.4
Name.startswith("avx.vbroadcast.s") || // Added in 3.5
+ Name.startswith("avx512.vbroadcast.s") || // Added in 7.0
Name.startswith("avx512.mask.palignr.") || // Added in 3.9
Name.startswith("avx512.mask.valign.") || // Added in 4.0
Name.startswith("sse2.psll.dq") || // Added in 3.7
@@ -472,6 +556,17 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
return true;
}
}
+ if (Name.startswith("invariant.group.barrier")) {
+ // Rename invariant.group.barrier to launder.invariant.group
+ auto Args = F->getFunctionType()->params();
+ Type* ObjectPtr[1] = {Args[0]};
+ rename(F);
+ NewFn = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::launder_invariant_group, ObjectPtr);
+ return true;
+
+ }
+
break;
}
case 'm': {
@@ -517,6 +612,37 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
return true;
}
}
+ // Updating the memory intrinsics (memcpy/memmove/memset) that have an
+ // alignment parameter to embedding the alignment as an attribute of
+ // the pointer args.
+ if (Name.startswith("memcpy.") && F->arg_size() == 5) {
+ rename(F);
+ // Get the types of dest, src, and len
+ ArrayRef<Type *> ParamTypes = F->getFunctionType()->params().slice(0, 3);
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memcpy,
+ ParamTypes);
+ return true;
+ }
+ if (Name.startswith("memmove.") && F->arg_size() == 5) {
+ rename(F);
+ // Get the types of dest, src, and len
+ ArrayRef<Type *> ParamTypes = F->getFunctionType()->params().slice(0, 3);
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memmove,
+ ParamTypes);
+ return true;
+ }
+ if (Name.startswith("memset.") && F->arg_size() == 5) {
+ rename(F);
+ // Get the types of dest, and len
+ const auto *FT = F->getFunctionType();
+ Type *ParamTypes[2] = {
+ FT->getParamType(0), // Dest
+ FT->getParamType(2) // len
+ };
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::memset,
+ ParamTypes);
+ return true;
+ }
break;
}
case 'n': {
@@ -700,7 +826,7 @@ static Value *getX86MaskVec(IRBuilder<> &Builder, Value *Mask,
static Value *EmitX86Select(IRBuilder<> &Builder, Value *Mask,
Value *Op0, Value *Op1) {
- // If the mask is all ones just emit the align operation.
+ // If the mask is all ones just emit the first operation.
if (const auto *C = dyn_cast<Constant>(Mask))
if (C->isAllOnesValue())
return Op0;
@@ -709,6 +835,21 @@ static Value *EmitX86Select(IRBuilder<> &Builder, Value *Mask,
return Builder.CreateSelect(Mask, Op0, Op1);
}
+static Value *EmitX86ScalarSelect(IRBuilder<> &Builder, Value *Mask,
+ Value *Op0, Value *Op1) {
+ // If the mask is all ones just emit the first operation.
+ if (const auto *C = dyn_cast<Constant>(Mask))
+ if (C->isAllOnesValue())
+ return Op0;
+
+ llvm::VectorType *MaskTy =
+ llvm::VectorType::get(Builder.getInt1Ty(),
+ Mask->getType()->getIntegerBitWidth());
+ Mask = Builder.CreateBitCast(Mask, MaskTy);
+ Mask = Builder.CreateExtractElement(Mask, (uint64_t)0);
+ return Builder.CreateSelect(Mask, Op0, Op1);
+}
+
// Handle autoupgrade for masked PALIGNR and VALIGND/Q intrinsics.
// PALIGNR handles large immediates by shifting while VALIGN masks the immediate
// so we need to handle both cases. VALIGN also doesn't have 128-bit lanes.
@@ -825,12 +966,44 @@ static Value *upgradeIntMinMax(IRBuilder<> &Builder, CallInst &CI,
return Res;
}
+static Value *upgradePMULDQ(IRBuilder<> &Builder, CallInst &CI, bool IsSigned) {
+ Type *Ty = CI.getType();
+
+ // Arguments have a vXi32 type so cast to vXi64.
+ Value *LHS = Builder.CreateBitCast(CI.getArgOperand(0), Ty);
+ Value *RHS = Builder.CreateBitCast(CI.getArgOperand(1), Ty);
+
+ if (IsSigned) {
+ // Shift left then arithmetic shift right.
+ Constant *ShiftAmt = ConstantInt::get(Ty, 32);
+ LHS = Builder.CreateShl(LHS, ShiftAmt);
+ LHS = Builder.CreateAShr(LHS, ShiftAmt);
+ RHS = Builder.CreateShl(RHS, ShiftAmt);
+ RHS = Builder.CreateAShr(RHS, ShiftAmt);
+ } else {
+ // Clear the upper bits.
+ Constant *Mask = ConstantInt::get(Ty, 0xffffffff);
+ LHS = Builder.CreateAnd(LHS, Mask);
+ RHS = Builder.CreateAnd(RHS, Mask);
+ }
+
+ Value *Res = Builder.CreateMul(LHS, RHS);
+
+ if (CI.getNumArgOperands() == 4)
+ Res = EmitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2));
+
+ return Res;
+}
+
// Applying mask on vector of i1's and make sure result is at least 8 bits wide.
-static Value *ApplyX86MaskOn1BitsVec(IRBuilder<> &Builder,Value *Vec, Value *Mask,
- unsigned NumElts) {
- const auto *C = dyn_cast<Constant>(Mask);
- if (!C || !C->isAllOnesValue())
- Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
+static Value *ApplyX86MaskOn1BitsVec(IRBuilder<> &Builder, Value *Vec,
+ Value *Mask) {
+ unsigned NumElts = Vec->getType()->getVectorNumElements();
+ if (Mask) {
+ const auto *C = dyn_cast<Constant>(Mask);
+ if (!C || !C->isAllOnesValue())
+ Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts));
+ }
if (NumElts < 8) {
uint32_t Indices[8];
@@ -871,14 +1044,13 @@ static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallInst &CI,
Value *Mask = CI.getArgOperand(CI.getNumArgOperands() - 1);
- return ApplyX86MaskOn1BitsVec(Builder, Cmp, Mask, NumElts);
+ return ApplyX86MaskOn1BitsVec(Builder, Cmp, Mask);
}
// Replace a masked intrinsic with an older unmasked intrinsic.
static Value *UpgradeX86MaskedShift(IRBuilder<> &Builder, CallInst &CI,
Intrinsic::ID IID) {
- Function *F = CI.getCalledFunction();
- Function *Intrin = Intrinsic::getDeclaration(F->getParent(), IID);
+ Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID);
Value *Rep = Builder.CreateCall(Intrin,
{ CI.getArgOperand(0), CI.getArgOperand(1) });
return EmitX86Select(Builder, CI.getArgOperand(3), Rep, CI.getArgOperand(2));
@@ -907,6 +1079,321 @@ static Value* UpgradeMaskToInt(IRBuilder<> &Builder, CallInst &CI) {
return Builder.CreateSExt(Mask, ReturnOp, "vpmovm2");
}
+// Replace intrinsic with unmasked version and a select.
+static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder,
+ CallInst &CI, Value *&Rep) {
+ Name = Name.substr(12); // Remove avx512.mask.
+
+ unsigned VecWidth = CI.getType()->getPrimitiveSizeInBits();
+ unsigned EltWidth = CI.getType()->getScalarSizeInBits();
+ Intrinsic::ID IID;
+ if (Name.startswith("max.p")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_sse_max_ps;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_sse2_max_pd;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx_max_ps_256;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx_max_pd_256;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("min.p")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_sse_min_ps;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_sse2_min_pd;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx_min_ps_256;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx_min_pd_256;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pshuf.b.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_ssse3_pshuf_b_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pshuf_b;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pshuf_b_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pmul.hr.sw.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_ssse3_pmul_hr_sw_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pmul_hr_sw;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pmul_hr_sw_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pmulh.w.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_pmulh_w;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pmulh_w;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pmulh_w_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pmulhu.w.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_pmulhu_w;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pmulhu_w;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pmulhu_w_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pmaddw.d.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_pmadd_wd;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pmadd_wd;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pmaddw_d_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pmaddubs.w.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_ssse3_pmadd_ub_sw_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_pmadd_ub_sw;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_pmaddubs_w_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("packsswb.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_packsswb_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_packsswb;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_packsswb_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("packssdw.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_packssdw_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_packssdw;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_packssdw_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("packuswb.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse2_packuswb_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_packuswb;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_packuswb_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("packusdw.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_sse41_packusdw;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx2_packusdw;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_packusdw_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("vpermilvar.")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx_vpermilvar_ps;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx_vpermilvar_pd;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx_vpermilvar_ps_256;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx_vpermilvar_pd_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name == "cvtpd2dq.256") {
+ IID = Intrinsic::x86_avx_cvt_pd2dq_256;
+ } else if (Name == "cvtpd2ps.256") {
+ IID = Intrinsic::x86_avx_cvt_pd2_ps_256;
+ } else if (Name == "cvttpd2dq.256") {
+ IID = Intrinsic::x86_avx_cvtt_pd2dq_256;
+ } else if (Name == "cvttps2dq.128") {
+ IID = Intrinsic::x86_sse2_cvttps2dq;
+ } else if (Name == "cvttps2dq.256") {
+ IID = Intrinsic::x86_avx_cvtt_ps2dq_256;
+ } else if (Name.startswith("permvar.")) {
+ bool IsFloat = CI.getType()->isFPOrFPVectorTy();
+ if (VecWidth == 256 && EltWidth == 32 && IsFloat)
+ IID = Intrinsic::x86_avx2_permps;
+ else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
+ IID = Intrinsic::x86_avx2_permd;
+ else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_df_256;
+ else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_di_256;
+ else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_sf_512;
+ else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_si_512;
+ else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_df_512;
+ else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
+ IID = Intrinsic::x86_avx512_permvar_di_512;
+ else if (VecWidth == 128 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_permvar_hi_128;
+ else if (VecWidth == 256 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_permvar_hi_256;
+ else if (VecWidth == 512 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_permvar_hi_512;
+ else if (VecWidth == 128 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_permvar_qi_128;
+ else if (VecWidth == 256 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_permvar_qi_256;
+ else if (VecWidth == 512 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_permvar_qi_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("dbpsadbw.")) {
+ if (VecWidth == 128)
+ IID = Intrinsic::x86_avx512_dbpsadbw_128;
+ else if (VecWidth == 256)
+ IID = Intrinsic::x86_avx512_dbpsadbw_256;
+ else if (VecWidth == 512)
+ IID = Intrinsic::x86_avx512_dbpsadbw_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("vpshld.")) {
+ if (VecWidth == 128 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshld_q_128;
+ else if (VecWidth == 128 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshld_d_128;
+ else if (VecWidth == 128 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshld_w_128;
+ else if (VecWidth == 256 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshld_q_256;
+ else if (VecWidth == 256 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshld_d_256;
+ else if (VecWidth == 256 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshld_w_256;
+ else if (VecWidth == 512 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshld_q_512;
+ else if (VecWidth == 512 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshld_d_512;
+ else if (VecWidth == 512 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshld_w_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("vpshrd.")) {
+ if (VecWidth == 128 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshrd_q_128;
+ else if (VecWidth == 128 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshrd_d_128;
+ else if (VecWidth == 128 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshrd_w_128;
+ else if (VecWidth == 256 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshrd_q_256;
+ else if (VecWidth == 256 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshrd_d_256;
+ else if (VecWidth == 256 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshrd_w_256;
+ else if (VecWidth == 512 && Name[7] == 'q')
+ IID = Intrinsic::x86_avx512_vpshrd_q_512;
+ else if (VecWidth == 512 && Name[7] == 'd')
+ IID = Intrinsic::x86_avx512_vpshrd_d_512;
+ else if (VecWidth == 512 && Name[7] == 'w')
+ IID = Intrinsic::x86_avx512_vpshrd_w_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("prorv.")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prorv_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prorv_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prorv_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prorv_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prorv_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prorv_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("prolv.")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prolv_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prolv_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prolv_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prolv_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prolv_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prolv_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("pror.")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pror_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pror_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pror_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pror_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pror_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pror_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else if (Name.startswith("prol.")) {
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prol_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prol_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_prol_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prol_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prol_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_prol_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+ } else
+ return false;
+
+ SmallVector<Value *, 4> Args(CI.arg_operands().begin(),
+ CI.arg_operands().end());
+ Args.pop_back();
+ Args.pop_back();
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID),
+ Args);
+ unsigned NumArgs = CI.getNumArgOperands();
+ Rep = EmitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep,
+ CI.getArgOperand(NumArgs - 2));
+ return true;
+}
+
+/// Upgrade comment in call to inline asm that represents an objc retain release
+/// marker.
+void llvm::UpgradeInlineAsmString(std::string *AsmStr) {
+ size_t Pos;
+ if (AsmStr->find("mov\tfp") == 0 &&
+ AsmStr->find("objc_retainAutoreleaseReturnValue") != std::string::npos &&
+ (Pos = AsmStr->find("# marker")) != std::string::npos) {
+ AsmStr->replace(Pos, 1, ";");
+ }
+ return;
+}
+
/// Upgrade a call to an old intrinsic. All argument and return casting must be
/// provided to seamlessly integrate with existing context.
void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
@@ -1015,6 +1502,16 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
return;
}
+ if (IsX86 && Name == "avx512.mask.store.ss") {
+ Value *Mask = Builder.CreateAnd(CI->getArgOperand(2), Builder.getInt8(1));
+ UpgradeMaskedStore(Builder, CI->getArgOperand(0), CI->getArgOperand(1),
+ Mask, false);
+
+ // Remove intrinsic.
+ CI->eraseFromParent();
+ return;
+ }
+
if (IsX86 && (Name.startswith("avx512.mask.store"))) {
// "avx512.mask.storeu." or "avx512.mask.store."
bool Aligned = Name[17] != 'u'; // "avx512.mask.storeu".
@@ -1043,6 +1540,39 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
ExtTy->getPrimitiveSizeInBits();
Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy);
Rep = Builder.CreateVectorSplat(NumElts, Rep);
+ } else if (IsX86 && (Name == "sse.sqrt.ss" ||
+ Name == "sse2.sqrt.sd")) {
+ Value *Vec = CI->getArgOperand(0);
+ Value *Elt0 = Builder.CreateExtractElement(Vec, (uint64_t)0);
+ Function *Intr = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::sqrt, Elt0->getType());
+ Elt0 = Builder.CreateCall(Intr, Elt0);
+ Rep = Builder.CreateInsertElement(Vec, Elt0, (uint64_t)0);
+ } else if (IsX86 && (Name.startswith("avx.sqrt.p") ||
+ Name.startswith("sse2.sqrt.p") ||
+ Name.startswith("sse.sqrt.p"))) {
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::sqrt,
+ CI->getType()),
+ {CI->getArgOperand(0)});
+ } else if (IsX86 && (Name.startswith("avx512.mask.sqrt.p"))) {
+ if (CI->getNumArgOperands() == 4 &&
+ (!isa<ConstantInt>(CI->getArgOperand(3)) ||
+ cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) {
+ Intrinsic::ID IID = Name[18] == 's' ? Intrinsic::x86_avx512_sqrt_ps_512
+ : Intrinsic::x86_avx512_sqrt_pd_512;
+
+ Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(3) };
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
+ IID), Args);
+ } else {
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::sqrt,
+ CI->getType()),
+ {CI->getArgOperand(0)});
+ }
+ Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
+ CI->getArgOperand(1));
} else if (IsX86 && (Name.startswith("avx512.ptestm") ||
Name.startswith("avx512.ptestnm"))) {
Value *Op0 = CI->getArgOperand(0);
@@ -1054,14 +1584,76 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
ICmpInst::Predicate Pred =
Name.startswith("avx512.ptestm") ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ;
Rep = Builder.CreateICmp(Pred, Rep, Zero);
- unsigned NumElts = Op0->getType()->getVectorNumElements();
- Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, Mask, NumElts);
+ Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, Mask);
} else if (IsX86 && (Name.startswith("avx512.mask.pbroadcast"))){
unsigned NumElts =
CI->getArgOperand(1)->getType()->getVectorNumElements();
Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0));
Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
CI->getArgOperand(1));
+ } else if (IsX86 && (Name.startswith("avx512.kunpck"))) {
+ unsigned NumElts = CI->getType()->getScalarSizeInBits();
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), NumElts);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), NumElts);
+ uint32_t Indices[64];
+ for (unsigned i = 0; i != NumElts; ++i)
+ Indices[i] = i;
+
+ // First extract half of each vector. This gives better codegen than
+ // doing it in a single shuffle.
+ LHS = Builder.CreateShuffleVector(LHS, LHS,
+ makeArrayRef(Indices, NumElts / 2));
+ RHS = Builder.CreateShuffleVector(RHS, RHS,
+ makeArrayRef(Indices, NumElts / 2));
+ // Concat the vectors.
+ // NOTE: Operands have to be swapped to match intrinsic definition.
+ Rep = Builder.CreateShuffleVector(RHS, LHS,
+ makeArrayRef(Indices, NumElts));
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.kand.w") {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ Rep = Builder.CreateAnd(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.kandn.w") {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ LHS = Builder.CreateNot(LHS);
+ Rep = Builder.CreateAnd(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.kor.w") {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ Rep = Builder.CreateOr(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.kxor.w") {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ Rep = Builder.CreateXor(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.kxnor.w") {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ LHS = Builder.CreateNot(LHS);
+ Rep = Builder.CreateXor(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 && Name == "avx512.knot.w") {
+ Rep = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Rep = Builder.CreateNot(Rep);
+ Rep = Builder.CreateBitCast(Rep, CI->getType());
+ } else if (IsX86 &&
+ (Name == "avx512.kortestz.w" || Name == "avx512.kortestc.w")) {
+ Value *LHS = getX86MaskVec(Builder, CI->getArgOperand(0), 16);
+ Value *RHS = getX86MaskVec(Builder, CI->getArgOperand(1), 16);
+ Rep = Builder.CreateOr(LHS, RHS);
+ Rep = Builder.CreateBitCast(Rep, Builder.getInt16Ty());
+ Value *C;
+ if (Name[14] == 'c')
+ C = ConstantInt::getAllOnesValue(Builder.getInt16Ty());
+ else
+ C = ConstantInt::getNullValue(Builder.getInt16Ty());
+ Rep = Builder.CreateICmpEQ(Rep, C);
+ Rep = Builder.CreateZExt(Rep, Builder.getInt32Ty());
} else if (IsX86 && (Name == "sse.add.ss" || Name == "sse2.add.sd")) {
Type *I32Ty = Type::getInt32Ty(C);
Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0),
@@ -1102,12 +1694,75 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
// "avx512.mask.pcmpeq." or "avx512.mask.pcmpgt."
bool CmpEq = Name[16] == 'e';
Rep = upgradeMaskedCompare(Builder, *CI, CmpEq ? 0 : 6, true);
- } else if (IsX86 && Name.startswith("avx512.mask.cmp")) {
+ } else if (IsX86 && Name.startswith("avx512.mask.fpclass.p")) {
+ Type *OpTy = CI->getArgOperand(0)->getType();
+ unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
+ unsigned EltWidth = OpTy->getScalarSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_fpclass_ps_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_fpclass_ps_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_fpclass_ps_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_fpclass_pd_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_fpclass_pd_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_fpclass_pd_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { CI->getOperand(0), CI->getArgOperand(1) });
+ Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2));
+ } else if (IsX86 && Name.startswith("avx512.mask.cmp.p")) {
+ Type *OpTy = CI->getArgOperand(0)->getType();
+ unsigned VecWidth = OpTy->getPrimitiveSizeInBits();
+ unsigned EltWidth = OpTy->getScalarSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_cmp_ps_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_cmp_ps_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_cmp_ps_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_cmp_pd_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_cmp_pd_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_cmp_pd_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ SmallVector<Value *, 4> Args;
+ Args.push_back(CI->getArgOperand(0));
+ Args.push_back(CI->getArgOperand(1));
+ Args.push_back(CI->getArgOperand(2));
+ if (CI->getNumArgOperands() == 5)
+ Args.push_back(CI->getArgOperand(4));
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ Args);
+ Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(3));
+ } else if (IsX86 && Name.startswith("avx512.mask.cmp.") &&
+ Name[16] != 'p') {
+ // Integer compare intrinsics.
unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
Rep = upgradeMaskedCompare(Builder, *CI, Imm, true);
- } else if (IsX86 && Name.startswith("avx512.mask.ucmp")) {
+ } else if (IsX86 && Name.startswith("avx512.mask.ucmp.")) {
unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
Rep = upgradeMaskedCompare(Builder, *CI, Imm, false);
+ } else if (IsX86 && (Name.startswith("avx512.cvtb2mask.") ||
+ Name.startswith("avx512.cvtw2mask.") ||
+ Name.startswith("avx512.cvtd2mask.") ||
+ Name.startswith("avx512.cvtq2mask."))) {
+ Value *Op = CI->getArgOperand(0);
+ Value *Zero = llvm::Constant::getNullValue(Op->getType());
+ Rep = Builder.CreateICmp(ICmpInst::ICMP_SLT, Op, Zero);
+ Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, nullptr);
} else if(IsX86 && (Name == "ssse3.pabs.b.128" ||
Name == "ssse3.pabs.w.128" ||
Name == "ssse3.pabs.d.128" ||
@@ -1138,35 +1793,67 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Name.startswith("avx2.pminu") ||
Name.startswith("avx512.mask.pminu"))) {
Rep = upgradeIntMinMax(Builder, *CI, ICmpInst::ICMP_ULT);
+ } else if (IsX86 && (Name == "sse2.pmulu.dq" ||
+ Name == "avx2.pmulu.dq" ||
+ Name == "avx512.pmulu.dq.512" ||
+ Name.startswith("avx512.mask.pmulu.dq."))) {
+ Rep = upgradePMULDQ(Builder, *CI, /*Signed*/false);
+ } else if (IsX86 && (Name == "sse41.pmuldq" ||
+ Name == "avx2.pmul.dq" ||
+ Name == "avx512.pmul.dq.512" ||
+ Name.startswith("avx512.mask.pmul.dq."))) {
+ Rep = upgradePMULDQ(Builder, *CI, /*Signed*/true);
+ } else if (IsX86 && (Name == "sse.cvtsi2ss" ||
+ Name == "sse2.cvtsi2sd" ||
+ Name == "sse.cvtsi642ss" ||
+ Name == "sse2.cvtsi642sd")) {
+ Rep = Builder.CreateSIToFP(CI->getArgOperand(1),
+ CI->getType()->getVectorElementType());
+ Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
+ } else if (IsX86 && Name == "avx512.cvtusi2sd") {
+ Rep = Builder.CreateUIToFP(CI->getArgOperand(1),
+ CI->getType()->getVectorElementType());
+ Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
+ } else if (IsX86 && Name == "sse2.cvtss2sd") {
+ Rep = Builder.CreateExtractElement(CI->getArgOperand(1), (uint64_t)0);
+ Rep = Builder.CreateFPExt(Rep, CI->getType()->getVectorElementType());
+ Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep, (uint64_t)0);
} else if (IsX86 && (Name == "sse2.cvtdq2pd" ||
- Name == "sse2.cvtps2pd" ||
+ Name == "sse2.cvtdq2ps" ||
Name == "avx.cvtdq2.pd.256" ||
- Name == "avx.cvt.ps2.pd.256" ||
+ Name == "avx.cvtdq2.ps.256" ||
Name.startswith("avx512.mask.cvtdq2pd.") ||
- Name.startswith("avx512.mask.cvtudq2pd."))) {
- // Lossless i32/float to double conversion.
- // Extract the bottom elements if necessary and convert to double vector.
- Value *Src = CI->getArgOperand(0);
- VectorType *SrcTy = cast<VectorType>(Src->getType());
- VectorType *DstTy = cast<VectorType>(CI->getType());
+ Name.startswith("avx512.mask.cvtudq2pd.") ||
+ Name == "avx512.mask.cvtdq2ps.128" ||
+ Name == "avx512.mask.cvtdq2ps.256" ||
+ Name == "avx512.mask.cvtudq2ps.128" ||
+ Name == "avx512.mask.cvtudq2ps.256" ||
+ Name == "avx512.mask.cvtqq2pd.128" ||
+ Name == "avx512.mask.cvtqq2pd.256" ||
+ Name == "avx512.mask.cvtuqq2pd.128" ||
+ Name == "avx512.mask.cvtuqq2pd.256" ||
+ Name == "sse2.cvtps2pd" ||
+ Name == "avx.cvt.ps2.pd.256" ||
+ Name == "avx512.mask.cvtps2pd.128" ||
+ Name == "avx512.mask.cvtps2pd.256")) {
+ Type *DstTy = CI->getType();
Rep = CI->getArgOperand(0);
- unsigned NumDstElts = DstTy->getNumElements();
- if (NumDstElts < SrcTy->getNumElements()) {
+ unsigned NumDstElts = DstTy->getVectorNumElements();
+ if (NumDstElts < Rep->getType()->getVectorNumElements()) {
assert(NumDstElts == 2 && "Unexpected vector size");
uint32_t ShuffleMask[2] = { 0, 1 };
- Rep = Builder.CreateShuffleVector(Rep, UndefValue::get(SrcTy),
- ShuffleMask);
+ Rep = Builder.CreateShuffleVector(Rep, Rep, ShuffleMask);
}
- bool SInt2Double = (StringRef::npos != Name.find("cvtdq2"));
- bool UInt2Double = (StringRef::npos != Name.find("cvtudq2"));
- if (SInt2Double)
- Rep = Builder.CreateSIToFP(Rep, DstTy, "cvtdq2pd");
- else if (UInt2Double)
- Rep = Builder.CreateUIToFP(Rep, DstTy, "cvtudq2pd");
- else
+ bool IsPS2PD = (StringRef::npos != Name.find("ps2"));
+ bool IsUnsigned = (StringRef::npos != Name.find("cvtu"));
+ if (IsPS2PD)
Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd");
+ else if (IsUnsigned)
+ Rep = Builder.CreateUIToFP(Rep, DstTy, "cvt");
+ else
+ Rep = Builder.CreateSIToFP(Rep, DstTy, "cvt");
if (CI->getNumArgOperands() == 3)
Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
@@ -1179,6 +1866,36 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Rep = UpgradeMaskedLoad(Builder, CI->getArgOperand(0),
CI->getArgOperand(1),CI->getArgOperand(2),
/*Aligned*/true);
+ } else if (IsX86 && Name.startswith("avx512.mask.expand.load.")) {
+ Type *ResultTy = CI->getType();
+ Type *PtrTy = ResultTy->getVectorElementType();
+
+ // Cast the pointer to element type.
+ Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
+ llvm::PointerType::getUnqual(PtrTy));
+
+ Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
+ ResultTy->getVectorNumElements());
+
+ Function *ELd = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::masked_expandload,
+ ResultTy);
+ Rep = Builder.CreateCall(ELd, { Ptr, MaskVec, CI->getOperand(1) });
+ } else if (IsX86 && Name.startswith("avx512.mask.compress.store.")) {
+ Type *ResultTy = CI->getArgOperand(1)->getType();
+ Type *PtrTy = ResultTy->getVectorElementType();
+
+ // Cast the pointer to element type.
+ Value *Ptr = Builder.CreateBitCast(CI->getOperand(0),
+ llvm::PointerType::getUnqual(PtrTy));
+
+ Value *MaskVec = getX86MaskVec(Builder, CI->getArgOperand(2),
+ ResultTy->getVectorNumElements());
+
+ Function *CSt = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::masked_compressstore,
+ ResultTy);
+ Rep = Builder.CreateCall(CSt, { CI->getArgOperand(1), Ptr, MaskVec });
} else if (IsX86 && Name.startswith("xop.vpcom")) {
Intrinsic::ID intID;
if (Name.endswith("ub"))
@@ -1237,7 +1954,8 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
Rep = Builder.CreateCall(CRC32, {Trunc0, CI->getArgOperand(1)});
Rep = Builder.CreateZExt(Rep, CI->getType(), "");
- } else if (IsX86 && Name.startswith("avx.vbroadcast.s")) {
+ } else if (IsX86 && (Name.startswith("avx.vbroadcast.s") ||
+ Name.startswith("avx512.vbroadcast.s"))) {
// Replace broadcasts with a series of insertelements.
Type *VecTy = CI->getType();
Type *EltTy = VecTy->getVectorElementType();
@@ -1720,135 +2438,103 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Rep = Builder.CreateMul(CI->getArgOperand(0), CI->getArgOperand(1));
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
- } else if (IsX86 && (Name.startswith("avx512.mask.add.p"))) {
- Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
+ } else if (IsX86 && Name.startswith("avx512.mask.add.p")) {
+ if (Name.endswith(".512")) {
+ Intrinsic::ID IID;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_add_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_add_pd_512;
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
+ } else {
+ Rep = Builder.CreateFAdd(CI->getArgOperand(0), CI->getArgOperand(1));
+ }
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
} else if (IsX86 && Name.startswith("avx512.mask.div.p")) {
- Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
+ if (Name.endswith(".512")) {
+ Intrinsic::ID IID;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_div_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_div_pd_512;
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
+ } else {
+ Rep = Builder.CreateFDiv(CI->getArgOperand(0), CI->getArgOperand(1));
+ }
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
} else if (IsX86 && Name.startswith("avx512.mask.mul.p")) {
- Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
- Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
- CI->getArgOperand(2));
- } else if (IsX86 && Name.startswith("avx512.mask.sub.p")) {
- Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
- Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
- CI->getArgOperand(2));
- } else if (IsX86 && Name.startswith("avx512.mask.lzcnt.")) {
- Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
- Intrinsic::ctlz,
- CI->getType()),
- { CI->getArgOperand(0), Builder.getInt1(false) });
- Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
- CI->getArgOperand(1));
- } else if (IsX86 && (Name.startswith("avx512.mask.max.p") ||
- Name.startswith("avx512.mask.min.p"))) {
- bool IsMin = Name[13] == 'i';
- VectorType *VecTy = cast<VectorType>(CI->getType());
- unsigned VecWidth = VecTy->getPrimitiveSizeInBits();
- unsigned EltWidth = VecTy->getScalarSizeInBits();
- Intrinsic::ID IID;
- if (!IsMin && VecWidth == 128 && EltWidth == 32)
- IID = Intrinsic::x86_sse_max_ps;
- else if (!IsMin && VecWidth == 128 && EltWidth == 64)
- IID = Intrinsic::x86_sse2_max_pd;
- else if (!IsMin && VecWidth == 256 && EltWidth == 32)
- IID = Intrinsic::x86_avx_max_ps_256;
- else if (!IsMin && VecWidth == 256 && EltWidth == 64)
- IID = Intrinsic::x86_avx_max_pd_256;
- else if (IsMin && VecWidth == 128 && EltWidth == 32)
- IID = Intrinsic::x86_sse_min_ps;
- else if (IsMin && VecWidth == 128 && EltWidth == 64)
- IID = Intrinsic::x86_sse2_min_pd;
- else if (IsMin && VecWidth == 256 && EltWidth == 32)
- IID = Intrinsic::x86_avx_min_ps_256;
- else if (IsMin && VecWidth == 256 && EltWidth == 64)
- IID = Intrinsic::x86_avx_min_pd_256;
- else
- llvm_unreachable("Unexpected intrinsic");
+ if (Name.endswith(".512")) {
+ Intrinsic::ID IID;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_mul_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_mul_pd_512;
- Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
- { CI->getArgOperand(0), CI->getArgOperand(1) });
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
+ } else {
+ Rep = Builder.CreateFMul(CI->getArgOperand(0), CI->getArgOperand(1));
+ }
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
- } else if (IsX86 && Name.startswith("avx512.mask.pshuf.b.")) {
- VectorType *VecTy = cast<VectorType>(CI->getType());
- Intrinsic::ID IID;
- if (VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_ssse3_pshuf_b_128;
- else if (VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_pshuf_b;
- else if (VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_pshuf_b_512;
- else
- llvm_unreachable("Unexpected intrinsic");
+ } else if (IsX86 && Name.startswith("avx512.mask.sub.p")) {
+ if (Name.endswith(".512")) {
+ Intrinsic::ID IID;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_sub_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_sub_pd_512;
- Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
- { CI->getArgOperand(0), CI->getArgOperand(1) });
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
+ } else {
+ Rep = Builder.CreateFSub(CI->getArgOperand(0), CI->getArgOperand(1));
+ }
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
- } else if (IsX86 && (Name.startswith("avx512.mask.pmul.dq.") ||
- Name.startswith("avx512.mask.pmulu.dq."))) {
- bool IsUnsigned = Name[16] == 'u';
- VectorType *VecTy = cast<VectorType>(CI->getType());
+ } else if (IsX86 && Name.startswith("avx512.mask.max.p") &&
+ Name.drop_front(18) == ".512") {
Intrinsic::ID IID;
- if (!IsUnsigned && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse41_pmuldq;
- else if (!IsUnsigned && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_pmul_dq;
- else if (!IsUnsigned && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_pmul_dq_512;
- else if (IsUnsigned && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse2_pmulu_dq;
- else if (IsUnsigned && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_pmulu_dq;
- else if (IsUnsigned && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_pmulu_dq_512;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_max_ps_512;
else
- llvm_unreachable("Unexpected intrinsic");
+ IID = Intrinsic::x86_avx512_max_pd_512;
Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
- { CI->getArgOperand(0), CI->getArgOperand(1) });
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
- } else if (IsX86 && Name.startswith("avx512.mask.pack")) {
- bool IsUnsigned = Name[16] == 'u';
- bool IsDW = Name[18] == 'd';
- VectorType *VecTy = cast<VectorType>(CI->getType());
+ } else if (IsX86 && Name.startswith("avx512.mask.min.p") &&
+ Name.drop_front(18) == ".512") {
Intrinsic::ID IID;
- if (!IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse2_packsswb_128;
- else if (!IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_packsswb;
- else if (!IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_packsswb_512;
- else if (!IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse2_packssdw_128;
- else if (!IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_packssdw;
- else if (!IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_packssdw_512;
- else if (IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse2_packuswb_128;
- else if (IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_packuswb;
- else if (IsUnsigned && !IsDW && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_packuswb_512;
- else if (IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 128)
- IID = Intrinsic::x86_sse41_packusdw;
- else if (IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 256)
- IID = Intrinsic::x86_avx2_packusdw;
- else if (IsUnsigned && IsDW && VecTy->getPrimitiveSizeInBits() == 512)
- IID = Intrinsic::x86_avx512_packusdw_512;
+ if (Name[17] == 's')
+ IID = Intrinsic::x86_avx512_min_ps_512;
else
- llvm_unreachable("Unexpected intrinsic");
+ IID = Intrinsic::x86_avx512_min_pd_512;
Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
- { CI->getArgOperand(0), CI->getArgOperand(1) });
+ { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(4) });
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
+ } else if (IsX86 && Name.startswith("avx512.mask.lzcnt.")) {
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::ctlz,
+ CI->getType()),
+ { CI->getArgOperand(0), Builder.getInt1(false) });
+ Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep,
+ CI->getArgOperand(1));
} else if (IsX86 && Name.startswith("avx512.mask.psll")) {
bool IsImmediate = Name[16] == 'i' ||
(Name.size() > 18 && Name[18] == 'i');
@@ -2055,28 +2741,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Rep = upgradeMaskedMove(Builder, *CI);
} else if (IsX86 && Name.startswith("avx512.cvtmask2")) {
Rep = UpgradeMaskToInt(Builder, *CI);
- } else if (IsX86 && Name.startswith("avx512.mask.vpermilvar.")) {
- Intrinsic::ID IID;
- if (Name.endswith("ps.128"))
- IID = Intrinsic::x86_avx_vpermilvar_ps;
- else if (Name.endswith("pd.128"))
- IID = Intrinsic::x86_avx_vpermilvar_pd;
- else if (Name.endswith("ps.256"))
- IID = Intrinsic::x86_avx_vpermilvar_ps_256;
- else if (Name.endswith("pd.256"))
- IID = Intrinsic::x86_avx_vpermilvar_pd_256;
- else if (Name.endswith("ps.512"))
- IID = Intrinsic::x86_avx512_vpermilvar_ps_512;
- else if (Name.endswith("pd.512"))
- IID = Intrinsic::x86_avx512_vpermilvar_pd_512;
- else
- llvm_unreachable("Unexpected vpermilvar intrinsic");
-
- Function *Intrin = Intrinsic::getDeclaration(F->getParent(), IID);
- Rep = Builder.CreateCall(Intrin,
- { CI->getArgOperand(0), CI->getArgOperand(1) });
- Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
- CI->getArgOperand(2));
} else if (IsX86 && Name.endswith(".movntdqa")) {
Module *M = F->getParent();
MDNode *Node = MDNode::get(
@@ -2110,6 +2774,416 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,
CI->getArgOperand(2));
}
+ } else if (IsX86 && (Name.startswith("fma.vfmadd.") ||
+ Name.startswith("fma.vfmsub.") ||
+ Name.startswith("fma.vfnmadd.") ||
+ Name.startswith("fma.vfnmsub."))) {
+ bool NegMul = Name[6] == 'n';
+ bool NegAcc = NegMul ? Name[8] == 's' : Name[7] == 's';
+ bool IsScalar = NegMul ? Name[12] == 's' : Name[11] == 's';
+
+ Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+
+ if (IsScalar) {
+ Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
+ Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
+ }
+
+ if (NegMul && !IsScalar)
+ Ops[0] = Builder.CreateFNeg(Ops[0]);
+ if (NegMul && IsScalar)
+ Ops[1] = Builder.CreateFNeg(Ops[1]);
+ if (NegAcc)
+ Ops[2] = Builder.CreateFNeg(Ops[2]);
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
+ Intrinsic::fma,
+ Ops[0]->getType()),
+ Ops);
+
+ if (IsScalar)
+ Rep = Builder.CreateInsertElement(CI->getArgOperand(0), Rep,
+ (uint64_t)0);
+ } else if (IsX86 && Name.startswith("fma4.vfmadd.s")) {
+ Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+
+ Ops[0] = Builder.CreateExtractElement(Ops[0], (uint64_t)0);
+ Ops[1] = Builder.CreateExtractElement(Ops[1], (uint64_t)0);
+ Ops[2] = Builder.CreateExtractElement(Ops[2], (uint64_t)0);
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(),
+ Intrinsic::fma,
+ Ops[0]->getType()),
+ Ops);
+
+ Rep = Builder.CreateInsertElement(Constant::getNullValue(CI->getType()),
+ Rep, (uint64_t)0);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vfmadd.s") ||
+ Name.startswith("avx512.maskz.vfmadd.s") ||
+ Name.startswith("avx512.mask3.vfmadd.s") ||
+ Name.startswith("avx512.mask3.vfmsub.s") ||
+ Name.startswith("avx512.mask3.vfnmsub.s"))) {
+ bool IsMask3 = Name[11] == '3';
+ bool IsMaskZ = Name[11] == 'z';
+ // Drop the "avx512.mask." to make it easier.
+ Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
+ bool NegMul = Name[2] == 'n';
+ bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
+
+ Value *A = CI->getArgOperand(0);
+ Value *B = CI->getArgOperand(1);
+ Value *C = CI->getArgOperand(2);
+
+ if (NegMul && (IsMask3 || IsMaskZ))
+ A = Builder.CreateFNeg(A);
+ if (NegMul && !(IsMask3 || IsMaskZ))
+ B = Builder.CreateFNeg(B);
+ if (NegAcc)
+ C = Builder.CreateFNeg(C);
+
+ A = Builder.CreateExtractElement(A, (uint64_t)0);
+ B = Builder.CreateExtractElement(B, (uint64_t)0);
+ C = Builder.CreateExtractElement(C, (uint64_t)0);
+
+ if (!isa<ConstantInt>(CI->getArgOperand(4)) ||
+ cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4) {
+ Value *Ops[] = { A, B, C, CI->getArgOperand(4) };
+
+ Intrinsic::ID IID;
+ if (Name.back() == 'd')
+ IID = Intrinsic::x86_avx512_vfmadd_f64;
+ else
+ IID = Intrinsic::x86_avx512_vfmadd_f32;
+ Function *FMA = Intrinsic::getDeclaration(CI->getModule(), IID);
+ Rep = Builder.CreateCall(FMA, Ops);
+ } else {
+ Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
+ Intrinsic::fma,
+ A->getType());
+ Rep = Builder.CreateCall(FMA, { A, B, C });
+ }
+
+ Value *PassThru = IsMaskZ ? Constant::getNullValue(Rep->getType()) :
+ IsMask3 ? C : A;
+
+ // For Mask3 with NegAcc, we need to create a new extractelement that
+ // avoids the negation above.
+ if (NegAcc && IsMask3)
+ PassThru = Builder.CreateExtractElement(CI->getArgOperand(2),
+ (uint64_t)0);
+
+ Rep = EmitX86ScalarSelect(Builder, CI->getArgOperand(3),
+ Rep, PassThru);
+ Rep = Builder.CreateInsertElement(CI->getArgOperand(IsMask3 ? 2 : 0),
+ Rep, (uint64_t)0);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vfmadd.p") ||
+ Name.startswith("avx512.mask.vfnmadd.p") ||
+ Name.startswith("avx512.mask.vfnmsub.p") ||
+ Name.startswith("avx512.mask3.vfmadd.p") ||
+ Name.startswith("avx512.mask3.vfmsub.p") ||
+ Name.startswith("avx512.mask3.vfnmsub.p") ||
+ Name.startswith("avx512.maskz.vfmadd.p"))) {
+ bool IsMask3 = Name[11] == '3';
+ bool IsMaskZ = Name[11] == 'z';
+ // Drop the "avx512.mask." to make it easier.
+ Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
+ bool NegMul = Name[2] == 'n';
+ bool NegAcc = NegMul ? Name[4] == 's' : Name[3] == 's';
+
+ Value *A = CI->getArgOperand(0);
+ Value *B = CI->getArgOperand(1);
+ Value *C = CI->getArgOperand(2);
+
+ if (NegMul && (IsMask3 || IsMaskZ))
+ A = Builder.CreateFNeg(A);
+ if (NegMul && !(IsMask3 || IsMaskZ))
+ B = Builder.CreateFNeg(B);
+ if (NegAcc)
+ C = Builder.CreateFNeg(C);
+
+ if (CI->getNumArgOperands() == 5 &&
+ (!isa<ConstantInt>(CI->getArgOperand(4)) ||
+ cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
+ Intrinsic::ID IID;
+ // Check the character before ".512" in string.
+ if (Name[Name.size()-5] == 's')
+ IID = Intrinsic::x86_avx512_vfmadd_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_vfmadd_pd_512;
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ { A, B, C, CI->getArgOperand(4) });
+ } else {
+ Function *FMA = Intrinsic::getDeclaration(CI->getModule(),
+ Intrinsic::fma,
+ A->getType());
+ Rep = Builder.CreateCall(FMA, { A, B, C });
+ }
+
+ Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
+ IsMask3 ? CI->getArgOperand(2) :
+ CI->getArgOperand(0);
+
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("fma.vfmaddsub.p") ||
+ Name.startswith("fma.vfmsubadd.p"))) {
+ bool IsSubAdd = Name[7] == 's';
+ int NumElts = CI->getType()->getVectorNumElements();
+
+ Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+
+ Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
+ Ops[0]->getType());
+ Value *Odd = Builder.CreateCall(FMA, Ops);
+ Ops[2] = Builder.CreateFNeg(Ops[2]);
+ Value *Even = Builder.CreateCall(FMA, Ops);
+
+ if (IsSubAdd)
+ std::swap(Even, Odd);
+
+ SmallVector<uint32_t, 32> Idxs(NumElts);
+ for (int i = 0; i != NumElts; ++i)
+ Idxs[i] = i + (i % 2) * NumElts;
+
+ Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vfmaddsub.p") ||
+ Name.startswith("avx512.mask3.vfmaddsub.p") ||
+ Name.startswith("avx512.maskz.vfmaddsub.p") ||
+ Name.startswith("avx512.mask3.vfmsubadd.p"))) {
+ bool IsMask3 = Name[11] == '3';
+ bool IsMaskZ = Name[11] == 'z';
+ // Drop the "avx512.mask." to make it easier.
+ Name = Name.drop_front(IsMask3 || IsMaskZ ? 13 : 12);
+ bool IsSubAdd = Name[3] == 's';
+ if (CI->getNumArgOperands() == 5 &&
+ (!isa<ConstantInt>(CI->getArgOperand(4)) ||
+ cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) {
+ Intrinsic::ID IID;
+ // Check the character before ".512" in string.
+ if (Name[Name.size()-5] == 's')
+ IID = Intrinsic::x86_avx512_vfmaddsub_ps_512;
+ else
+ IID = Intrinsic::x86_avx512_vfmaddsub_pd_512;
+
+ Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2), CI->getArgOperand(4) };
+ if (IsSubAdd)
+ Ops[2] = Builder.CreateFNeg(Ops[2]);
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(F->getParent(), IID),
+ {CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2), CI->getArgOperand(4)});
+ } else {
+ int NumElts = CI->getType()->getVectorNumElements();
+
+ Value *Ops[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+
+ Function *FMA = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::fma,
+ Ops[0]->getType());
+ Value *Odd = Builder.CreateCall(FMA, Ops);
+ Ops[2] = Builder.CreateFNeg(Ops[2]);
+ Value *Even = Builder.CreateCall(FMA, Ops);
+
+ if (IsSubAdd)
+ std::swap(Even, Odd);
+
+ SmallVector<uint32_t, 32> Idxs(NumElts);
+ for (int i = 0; i != NumElts; ++i)
+ Idxs[i] = i + (i % 2) * NumElts;
+
+ Rep = Builder.CreateShuffleVector(Even, Odd, Idxs);
+ }
+
+ Value *PassThru = IsMaskZ ? llvm::Constant::getNullValue(CI->getType()) :
+ IsMask3 ? CI->getArgOperand(2) :
+ CI->getArgOperand(0);
+
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("avx512.mask.pternlog.") ||
+ Name.startswith("avx512.maskz.pternlog."))) {
+ bool ZeroMask = Name[11] == 'z';
+ unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
+ unsigned EltWidth = CI->getType()->getScalarSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_128;
+ else if (VecWidth == 256 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_256;
+ else if (VecWidth == 512 && EltWidth == 32)
+ IID = Intrinsic::x86_avx512_pternlog_d_512;
+ else if (VecWidth == 128 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_128;
+ else if (VecWidth == 256 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_256;
+ else if (VecWidth == 512 && EltWidth == 64)
+ IID = Intrinsic::x86_avx512_pternlog_q_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
+ CI->getArgOperand(2), CI->getArgOperand(3) };
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
+ Args);
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
+ : CI->getArgOperand(0);
+ Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vpmadd52") ||
+ Name.startswith("avx512.maskz.vpmadd52"))) {
+ bool ZeroMask = Name[11] == 'z';
+ bool High = Name[20] == 'h' || Name[21] == 'h';
+ unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && !High)
+ IID = Intrinsic::x86_avx512_vpmadd52l_uq_128;
+ else if (VecWidth == 256 && !High)
+ IID = Intrinsic::x86_avx512_vpmadd52l_uq_256;
+ else if (VecWidth == 512 && !High)
+ IID = Intrinsic::x86_avx512_vpmadd52l_uq_512;
+ else if (VecWidth == 128 && High)
+ IID = Intrinsic::x86_avx512_vpmadd52h_uq_128;
+ else if (VecWidth == 256 && High)
+ IID = Intrinsic::x86_avx512_vpmadd52h_uq_256;
+ else if (VecWidth == 512 && High)
+ IID = Intrinsic::x86_avx512_vpmadd52h_uq_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
+ Args);
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
+ : CI->getArgOperand(0);
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vpermi2var.") ||
+ Name.startswith("avx512.mask.vpermt2var.") ||
+ Name.startswith("avx512.maskz.vpermt2var."))) {
+ bool ZeroMask = Name[11] == 'z';
+ bool IndexForm = Name[17] == 'i';
+ unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
+ unsigned EltWidth = CI->getType()->getScalarSizeInBits();
+ bool IsFloat = CI->getType()->isFPOrFPVectorTy();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && EltWidth == 32 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_ps_128;
+ else if (VecWidth == 128 && EltWidth == 32 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_d_128;
+ else if (VecWidth == 128 && EltWidth == 64 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_pd_128;
+ else if (VecWidth == 128 && EltWidth == 64 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_q_128;
+ else if (VecWidth == 256 && EltWidth == 32 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_ps_256;
+ else if (VecWidth == 256 && EltWidth == 32 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_d_256;
+ else if (VecWidth == 256 && EltWidth == 64 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_pd_256;
+ else if (VecWidth == 256 && EltWidth == 64 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_q_256;
+ else if (VecWidth == 512 && EltWidth == 32 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_ps_512;
+ else if (VecWidth == 512 && EltWidth == 32 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_d_512;
+ else if (VecWidth == 512 && EltWidth == 64 && IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_pd_512;
+ else if (VecWidth == 512 && EltWidth == 64 && !IsFloat)
+ IID = Intrinsic::x86_avx512_vpermi2var_q_512;
+ else if (VecWidth == 128 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_vpermi2var_hi_128;
+ else if (VecWidth == 256 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_vpermi2var_hi_256;
+ else if (VecWidth == 512 && EltWidth == 16)
+ IID = Intrinsic::x86_avx512_vpermi2var_hi_512;
+ else if (VecWidth == 128 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_vpermi2var_qi_128;
+ else if (VecWidth == 256 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_vpermi2var_qi_256;
+ else if (VecWidth == 512 && EltWidth == 8)
+ IID = Intrinsic::x86_avx512_vpermi2var_qi_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Args[] = { CI->getArgOperand(0) , CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+
+ // If this isn't index form we need to swap operand 0 and 1.
+ if (!IndexForm)
+ std::swap(Args[0], Args[1]);
+
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
+ Args);
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
+ : Builder.CreateBitCast(CI->getArgOperand(1),
+ CI->getType());
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vpdpbusd.") ||
+ Name.startswith("avx512.maskz.vpdpbusd.") ||
+ Name.startswith("avx512.mask.vpdpbusds.") ||
+ Name.startswith("avx512.maskz.vpdpbusds."))) {
+ bool ZeroMask = Name[11] == 'z';
+ bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
+ unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusd_128;
+ else if (VecWidth == 256 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusd_256;
+ else if (VecWidth == 512 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusd_512;
+ else if (VecWidth == 128 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusds_128;
+ else if (VecWidth == 256 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusds_256;
+ else if (VecWidth == 512 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpbusds_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
+ Args);
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
+ : CI->getArgOperand(0);
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && (Name.startswith("avx512.mask.vpdpwssd.") ||
+ Name.startswith("avx512.maskz.vpdpwssd.") ||
+ Name.startswith("avx512.mask.vpdpwssds.") ||
+ Name.startswith("avx512.maskz.vpdpwssds."))) {
+ bool ZeroMask = Name[11] == 'z';
+ bool IsSaturating = Name[ZeroMask ? 21 : 20] == 's';
+ unsigned VecWidth = CI->getType()->getPrimitiveSizeInBits();
+ Intrinsic::ID IID;
+ if (VecWidth == 128 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssd_128;
+ else if (VecWidth == 256 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssd_256;
+ else if (VecWidth == 512 && !IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssd_512;
+ else if (VecWidth == 128 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssds_128;
+ else if (VecWidth == 256 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssds_256;
+ else if (VecWidth == 512 && IsSaturating)
+ IID = Intrinsic::x86_avx512_vpdpwssds_512;
+ else
+ llvm_unreachable("Unexpected intrinsic");
+
+ Value *Args[] = { CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2) };
+ Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI->getModule(), IID),
+ Args);
+ Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
+ : CI->getArgOperand(0);
+ Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, PassThru);
+ } else if (IsX86 && Name.startswith("avx512.mask.") &&
+ upgradeAVX512MaskToSelect(Name, Builder, *CI, Rep)) {
+ // Rep will be updated by the call in the condition.
} else if (IsNVVM && (Name == "abs.i" || Name == "abs.ll")) {
Value *Arg = CI->getArgOperand(0);
Value *Neg = Builder.CreateNeg(Arg, "neg");
@@ -2164,14 +3238,17 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
return;
}
- CallInst *NewCall = nullptr;
- switch (NewFn->getIntrinsicID()) {
- default: {
+ const auto &DefaultCase = [&NewFn, &CI]() -> void {
// Handle generic mangling change, but nothing else
assert(
(CI->getCalledFunction()->getName() != NewFn->getName()) &&
"Unknown function for CallInst upgrade and isn't just a name change");
CI->setCalledFunction(NewFn);
+ };
+ CallInst *NewCall = nullptr;
+ switch (NewFn->getIntrinsicID()) {
+ default: {
+ DefaultCase();
return;
}
@@ -2312,6 +3389,35 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
NewCall = Builder.CreateCall(NewFn, Args);
break;
}
+
+ case Intrinsic::memcpy:
+ case Intrinsic::memmove:
+ case Intrinsic::memset: {
+ // We have to make sure that the call signature is what we're expecting.
+ // We only want to change the old signatures by removing the alignment arg:
+ // @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i32, i1)
+ // -> @llvm.mem[cpy|move]...(i8*, i8*, i[32|i64], i1)
+ // @llvm.memset...(i8*, i8, i[32|64], i32, i1)
+ // -> @llvm.memset...(i8*, i8, i[32|64], i1)
+ // Note: i8*'s in the above can be any pointer type
+ if (CI->getNumArgOperands() != 5) {
+ DefaultCase();
+ return;
+ }
+ // Remove alignment argument (3), and add alignment attributes to the
+ // dest/src pointers.
+ Value *Args[4] = {CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2), CI->getArgOperand(4)};
+ NewCall = Builder.CreateCall(NewFn, Args);
+ auto *MemCI = cast<MemIntrinsic>(NewCall);
+ // All mem intrinsics support dest alignment.
+ const ConstantInt *Align = cast<ConstantInt>(CI->getArgOperand(3));
+ MemCI->setDestAlignment(Align->getZExtValue());
+ // Memcpy/Memmove also support source alignment.
+ if (auto *MTI = dyn_cast<MemTransferInst>(MemCI))
+ MTI->setSourceAlignment(Align->getZExtValue());
+ break;
+ }
}
assert(NewCall && "Should have either set this variable or returned through "
"the default case");
@@ -2432,6 +3538,30 @@ bool llvm::UpgradeDebugInfo(Module &M) {
return Modified;
}
+bool llvm::UpgradeRetainReleaseMarker(Module &M) {
+ bool Changed = false;
+ NamedMDNode *ModRetainReleaseMarker =
+ M.getNamedMetadata("clang.arc.retainAutoreleasedReturnValueMarker");
+ if (ModRetainReleaseMarker) {
+ MDNode *Op = ModRetainReleaseMarker->getOperand(0);
+ if (Op) {
+ MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(0));
+ if (ID) {
+ SmallVector<StringRef, 4> ValueComp;
+ ID->getString().split(ValueComp, "#");
+ if (ValueComp.size() == 2) {
+ std::string NewValue = ValueComp[0].str() + ";" + ValueComp[1].str();
+ Metadata *Ops[1] = {MDString::get(M.getContext(), NewValue)};
+ ModRetainReleaseMarker->setOperand(0,
+ MDNode::get(M.getContext(), Ops));
+ Changed = true;
+ }
+ }
+ }
+ }
+ return Changed;
+}
+
bool llvm::UpgradeModuleFlags(Module &M) {
NamedMDNode *ModFlags = M.getModuleFlagsMetadata();
if (!ModFlags)
diff --git a/contrib/llvm/lib/IR/BasicBlock.cpp b/contrib/llvm/lib/IR/BasicBlock.cpp
index 938c40182b92..7c3e5862d1cd 100644
--- a/contrib/llvm/lib/IR/BasicBlock.cpp
+++ b/contrib/llvm/lib/IR/BasicBlock.cpp
@@ -90,6 +90,24 @@ void BasicBlock::setParent(Function *parent) {
InstList.setSymTabObject(&Parent, parent);
}
+iterator_range<filter_iterator<BasicBlock::const_iterator,
+ std::function<bool(const Instruction &)>>>
+BasicBlock::instructionsWithoutDebug() const {
+ std::function<bool(const Instruction &)> Fn = [](const Instruction &I) {
+ return !isa<DbgInfoIntrinsic>(I);
+ };
+ return make_filter_range(*this, Fn);
+}
+
+iterator_range<filter_iterator<BasicBlock::iterator,
+ std::function<bool(Instruction &)>>>
+BasicBlock::instructionsWithoutDebug() {
+ std::function<bool(Instruction &)> Fn = [](Instruction &I) {
+ return !isa<DbgInfoIntrinsic>(I);
+ };
+ return make_filter_range(*this, Fn);
+}
+
void BasicBlock::removeFromParent() {
getParent()->getBasicBlockList().remove(getIterator());
}
@@ -461,3 +479,9 @@ Optional<uint64_t> BasicBlock::getIrrLoopHeaderWeight() const {
}
return Optional<uint64_t>();
}
+
+BasicBlock::iterator llvm::skipDebugIntrinsics(BasicBlock::iterator It) {
+ while (isa<DbgInfoIntrinsic>(It))
+ ++It;
+ return It;
+}
diff --git a/contrib/llvm/lib/IR/Comdat.cpp b/contrib/llvm/lib/IR/Comdat.cpp
index c735f9b2eb1e..3b1f7d62cdae 100644
--- a/contrib/llvm/lib/IR/Comdat.cpp
+++ b/contrib/llvm/lib/IR/Comdat.cpp
@@ -7,13 +7,16 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the Comdat class.
+// This file implements the Comdat class (including the C bindings).
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/Comdat.h"
+#include "llvm-c/Comdat.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Comdat.h"
+#include "llvm/IR/GlobalObject.h"
+#include "llvm/IR/Module.h"
using namespace llvm;
@@ -22,3 +25,54 @@ Comdat::Comdat(Comdat &&C) : Name(C.Name), SK(C.SK) {}
Comdat::Comdat() = default;
StringRef Comdat::getName() const { return Name->first(); }
+
+LLVMComdatRef LLVMGetOrInsertComdat(LLVMModuleRef M, const char *Name) {
+ return wrap(unwrap(M)->getOrInsertComdat(Name));
+}
+
+LLVMComdatRef LLVMGetComdat(LLVMValueRef V) {
+ GlobalObject *G = unwrap<GlobalObject>(V);
+ return wrap(G->getComdat());
+}
+
+void LLVMSetComdat(LLVMValueRef V, LLVMComdatRef C) {
+ GlobalObject *G = unwrap<GlobalObject>(V);
+ G->setComdat(unwrap(C));
+}
+
+LLVMComdatSelectionKind LLVMGetComdatSelectionKind(LLVMComdatRef C) {
+ switch (unwrap(C)->getSelectionKind()) {
+ case Comdat::Any:
+ return LLVMAnyComdatSelectionKind;
+ case Comdat::ExactMatch:
+ return LLVMExactMatchComdatSelectionKind;
+ case Comdat::Largest:
+ return LLVMLargestComdatSelectionKind;
+ case Comdat::NoDuplicates:
+ return LLVMNoDuplicatesComdatSelectionKind;
+ case Comdat::SameSize:
+ return LLVMSameSizeComdatSelectionKind;
+ }
+ llvm_unreachable("Invalid Comdat SelectionKind!");
+}
+
+void LLVMSetComdatSelectionKind(LLVMComdatRef C, LLVMComdatSelectionKind kind) {
+ Comdat *Cd = unwrap(C);
+ switch (kind) {
+ case LLVMAnyComdatSelectionKind:
+ Cd->setSelectionKind(Comdat::Any);
+ break;
+ case LLVMExactMatchComdatSelectionKind:
+ Cd->setSelectionKind(Comdat::ExactMatch);
+ break;
+ case LLVMLargestComdatSelectionKind:
+ Cd->setSelectionKind(Comdat::Largest);
+ break;
+ case LLVMNoDuplicatesComdatSelectionKind:
+ Cd->setSelectionKind(Comdat::NoDuplicates);
+ break;
+ case LLVMSameSizeComdatSelectionKind:
+ Cd->setSelectionKind(Comdat::SameSize);
+ break;
+ }
+}
diff --git a/contrib/llvm/lib/IR/ConstantFold.cpp b/contrib/llvm/lib/IR/ConstantFold.cpp
index adb6724fc9c0..90a8366d1696 100644
--- a/contrib/llvm/lib/IR/ConstantFold.cpp
+++ b/contrib/llvm/lib/IR/ConstantFold.cpp
@@ -71,7 +71,7 @@ static Constant *BitCastConstantVector(Constant *CV, VectorType *DstTy) {
/// This function determines which opcode to use to fold two constant cast
/// expressions together. It uses CastInst::isEliminableCastPair to determine
/// the opcode. Consequently its just a wrapper around that function.
-/// @brief Determine if it is valid to fold a cast of a cast
+/// Determine if it is valid to fold a cast of a cast
static unsigned
foldConstantCastPair(
unsigned opc, ///< opcode of the second cast constant expression
@@ -321,7 +321,7 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
if (ByteStart == 0 && ByteSize*8 == SrcBitSize)
return CE->getOperand(0);
- // If extracting something completely in the input, if if the input is a
+ // If extracting something completely in the input, if the input is a
// multiple of 8 bits, recurse.
if ((SrcBitSize&7) == 0 && (ByteStart+ByteSize)*8 <= SrcBitSize)
return ExtractConstantBytes(CE->getOperand(0), ByteStart, ByteSize);
@@ -545,7 +545,11 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
opc != Instruction::AddrSpaceCast &&
// Do not fold bitcast (gep) with inrange index, as this loses
// information.
- !cast<GEPOperator>(CE)->getInRangeIndex().hasValue()) {
+ !cast<GEPOperator>(CE)->getInRangeIndex().hasValue() &&
+ // Do not fold if the gep type is a vector, as bitcasting
+ // operand 0 of a vector gep will result in a bitcast between
+ // different sizes.
+ !CE->getType()->isVectorTy()) {
// If all of the indexes in the GEP are null values, there is no pointer
// adjustment going on. We might as well cast the source pointer.
bool isAllNull = true;
@@ -678,13 +682,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
const APInt &api = CI->getValue();
APFloat apf(DestTy->getFltSemantics(),
APInt::getNullValue(DestTy->getPrimitiveSizeInBits()));
- if (APFloat::opOverflow &
- apf.convertFromAPInt(api, opc==Instruction::SIToFP,
- APFloat::rmNearestTiesToEven)) {
- // Undefined behavior invoked - the destination type can't represent
- // the input constant.
- return UndefValue::get(DestTy);
- }
+ apf.convertFromAPInt(api, opc==Instruction::SIToFP,
+ APFloat::rmNearestTiesToEven);
return ConstantFP::get(V->getContext(), apf);
}
return nullptr;
@@ -1009,8 +1008,17 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
case Instruction::FMul:
case Instruction::FDiv:
case Instruction::FRem:
- // TODO: UNDEF handling for binary float instructions.
- return nullptr;
+ // [any flop] undef, undef -> undef
+ if (isa<UndefValue>(C1) && isa<UndefValue>(C2))
+ return C1;
+ // [any flop] C, undef -> NaN
+ // [any flop] undef, C -> NaN
+ // We could potentially specialize NaN/Inf constants vs. 'normal'
+ // constants (possibly differently depending on opcode and operand). This
+ // would allow returning undef sometimes. But it is always safe to fold to
+ // NaN because we can choose the undef operand as NaN, and any FP opcode
+ // with a NaN operand will propagate NaN.
+ return ConstantFP::getNaN(C1->getType());
case Instruction::BinaryOpsEnd:
llvm_unreachable("Invalid BinaryOp");
}
@@ -1219,9 +1227,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
Constant *RHS = ConstantExpr::getExtractElement(C2, ExtractIdx);
// If any element of a divisor vector is zero, the whole op is undef.
- if ((Opcode == Instruction::SDiv || Opcode == Instruction::UDiv ||
- Opcode == Instruction::SRem || Opcode == Instruction::URem) &&
- RHS->isNullValue())
+ if (Instruction::isIntDivRem(Opcode) && RHS->isNullValue())
return UndefValue::get(VTy);
Result.push_back(ConstantExpr::get(Opcode, LHS, RHS));
@@ -1494,7 +1500,12 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2,
assert(isa<ConstantPointerNull>(V2) && "Canonicalization guarantee!");
// GlobalVals can never be null unless they have external weak linkage.
// We don't try to evaluate aliases here.
- if (!GV->hasExternalWeakLinkage() && !isa<GlobalAlias>(GV))
+ // NOTE: We should not be doing this constant folding if null pointer
+ // is considered valid for the function. But currently there is no way to
+ // query it from the Constant type.
+ if (!GV->hasExternalWeakLinkage() && !isa<GlobalAlias>(GV) &&
+ !NullPointerIsDefined(nullptr /* F */,
+ GV->getType()->getAddressSpace()))
return ICmpInst::ICMP_NE;
}
} else if (const BlockAddress *BA = dyn_cast<BlockAddress>(V1)) {
@@ -1546,8 +1557,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2,
// If the cast is not actually changing bits, and the second operand is a
// null pointer, do the comparison with the pre-casted value.
- if (V2->isNullValue() &&
- (CE1->getType()->isPointerTy() || CE1->getType()->isIntegerTy())) {
+ if (V2->isNullValue() && CE1->getType()->isIntOrPtrTy()) {
if (CE1->getOpcode() == Instruction::ZExt) isSigned = false;
if (CE1->getOpcode() == Instruction::SExt) isSigned = true;
return evaluateICmpRelation(CE1Op0,
@@ -1724,7 +1734,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
if (C1->isNullValue()) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C2))
// Don't try to evaluate aliases. External weak GV can be null.
- if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage()) {
+ if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage() &&
+ !NullPointerIsDefined(nullptr /* F */,
+ GV->getType()->getAddressSpace())) {
if (pred == ICmpInst::ICMP_EQ)
return ConstantInt::getFalse(C1->getContext());
else if (pred == ICmpInst::ICMP_NE)
@@ -1734,7 +1746,9 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
} else if (C2->isNullValue()) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(C1))
// Don't try to evaluate aliases. External weak GV can be null.
- if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage()) {
+ if (!isa<GlobalAlias>(GV) && !GV->hasExternalWeakLinkage() &&
+ !NullPointerIsDefined(nullptr /* F */,
+ GV->getType()->getAddressSpace())) {
if (pred == ICmpInst::ICMP_EQ)
return ConstantInt::getFalse(C1->getContext());
else if (pred == ICmpInst::ICMP_NE)
diff --git a/contrib/llvm/lib/IR/ConstantRange.cpp b/contrib/llvm/lib/IR/ConstantRange.cpp
index 48d16f334ba3..39a0b13c4e0c 100644
--- a/contrib/llvm/lib/IR/ConstantRange.cpp
+++ b/contrib/llvm/lib/IR/ConstantRange.cpp
@@ -22,6 +22,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/APInt.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/InstrTypes.h"
@@ -190,8 +191,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
return CR0.inverse().unionWith(CR1.inverse()).inverse();
};
- assert(BinOp >= Instruction::BinaryOpsBegin &&
- BinOp < Instruction::BinaryOpsEnd && "Binary operators only!");
+ assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
assert((NoWrapKind == OBO::NoSignedWrap ||
NoWrapKind == OBO::NoUnsignedWrap ||
@@ -255,6 +255,64 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,
APInt::getSignedMinValue(BitWidth) + SignedMin));
}
return Result;
+ case Instruction::Mul: {
+ if (NoWrapKind == (OBO::NoSignedWrap | OBO::NoUnsignedWrap)) {
+ return SubsetIntersect(
+ makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoSignedWrap),
+ makeGuaranteedNoWrapRegion(BinOp, Other, OBO::NoUnsignedWrap));
+ }
+
+ // Equivalent to calling makeGuaranteedNoWrapRegion() on [V, V+1).
+ const bool Unsigned = NoWrapKind == OBO::NoUnsignedWrap;
+ const auto makeSingleValueRegion = [Unsigned,
+ BitWidth](APInt V) -> ConstantRange {
+ // Handle special case for 0, -1 and 1. See the last for reason why we
+ // specialize -1 and 1.
+ if (V == 0 || V.isOneValue())
+ return ConstantRange(BitWidth, true);
+
+ APInt MinValue, MaxValue;
+ if (Unsigned) {
+ MinValue = APInt::getMinValue(BitWidth);
+ MaxValue = APInt::getMaxValue(BitWidth);
+ } else {
+ MinValue = APInt::getSignedMinValue(BitWidth);
+ MaxValue = APInt::getSignedMaxValue(BitWidth);
+ }
+ // e.g. Returning [-127, 127], represented as [-127, -128).
+ if (!Unsigned && V.isAllOnesValue())
+ return ConstantRange(-MaxValue, MinValue);
+
+ APInt Lower, Upper;
+ if (!Unsigned && V.isNegative()) {
+ Lower = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::UP);
+ Upper = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::DOWN);
+ } else if (Unsigned) {
+ Lower = APIntOps::RoundingUDiv(MinValue, V, APInt::Rounding::UP);
+ Upper = APIntOps::RoundingUDiv(MaxValue, V, APInt::Rounding::DOWN);
+ } else {
+ Lower = APIntOps::RoundingSDiv(MinValue, V, APInt::Rounding::UP);
+ Upper = APIntOps::RoundingSDiv(MaxValue, V, APInt::Rounding::DOWN);
+ }
+ if (Unsigned) {
+ Lower = Lower.zextOrSelf(BitWidth);
+ Upper = Upper.zextOrSelf(BitWidth);
+ } else {
+ Lower = Lower.sextOrSelf(BitWidth);
+ Upper = Upper.sextOrSelf(BitWidth);
+ }
+ // ConstantRange ctor take a half inclusive interval [Lower, Upper + 1).
+ // Upper + 1 is guanranteed not to overflow, because |divisor| > 1. 0, -1,
+ // and 1 are already handled as special cases.
+ return ConstantRange(Lower, Upper + 1);
+ };
+
+ if (Unsigned)
+ return makeSingleValueRegion(Other.getUnsignedMax());
+
+ return SubsetIntersect(makeSingleValueRegion(Other.getSignedMin()),
+ makeSingleValueRegion(Other.getSignedMax()));
+ }
}
}
@@ -358,7 +416,7 @@ bool ConstantRange::contains(const ConstantRange &Other) const {
ConstantRange ConstantRange::subtract(const APInt &Val) const {
assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width");
// If the set is empty or full, don't modify the endpoints.
- if (Lower == Upper)
+ if (Lower == Upper)
return *this;
return ConstantRange(Lower - Val, Upper - Val);
}
@@ -368,7 +426,7 @@ ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
}
ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
- assert(getBitWidth() == CR.getBitWidth() &&
+ assert(getBitWidth() == CR.getBitWidth() &&
"ConstantRange types don't agree!");
// Handle common cases.
@@ -442,7 +500,7 @@ ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
}
ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
- assert(getBitWidth() == CR.getBitWidth() &&
+ assert(getBitWidth() == CR.getBitWidth() &&
"ConstantRange types don't agree!");
if ( isFullSet() || CR.isEmptySet()) return *this;
@@ -664,8 +722,7 @@ ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const {
ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,
const ConstantRange &Other) const {
- assert(BinOp >= Instruction::BinaryOpsBegin &&
- BinOp < Instruction::BinaryOpsEnd && "Binary operators only!");
+ assert(Instruction::isBinaryOp(BinOp) && "Binary operators only!");
switch (BinOp) {
case Instruction::Add:
@@ -797,7 +854,7 @@ ConstantRange::multiply(const ConstantRange &Other) const {
this_max = getSignedMax().sext(getBitWidth() * 2);
Other_min = Other.getSignedMin().sext(getBitWidth() * 2);
Other_max = Other.getSignedMax().sext(getBitWidth() * 2);
-
+
auto L = {this_min * Other_min, this_min * Other_max,
this_max * Other_min, this_max * Other_max};
auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); };
diff --git a/contrib/llvm/lib/IR/Constants.cpp b/contrib/llvm/lib/IR/Constants.cpp
index dccba779deb3..2351e7e4a389 100644
--- a/contrib/llvm/lib/IR/Constants.cpp
+++ b/contrib/llvm/lib/IR/Constants.cpp
@@ -202,6 +202,68 @@ bool Constant::isNotMinSignedValue() const {
return false;
}
+bool Constant::isFiniteNonZeroFP() const {
+ if (auto *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->getValueAPF().isFiniteNonZero();
+ if (!getType()->isVectorTy())
+ return false;
+ for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
+ auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
+ if (!CFP || !CFP->getValueAPF().isFiniteNonZero())
+ return false;
+ }
+ return true;
+}
+
+bool Constant::isNormalFP() const {
+ if (auto *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->getValueAPF().isNormal();
+ if (!getType()->isVectorTy())
+ return false;
+ for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
+ auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
+ if (!CFP || !CFP->getValueAPF().isNormal())
+ return false;
+ }
+ return true;
+}
+
+bool Constant::hasExactInverseFP() const {
+ if (auto *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->getValueAPF().getExactInverse(nullptr);
+ if (!getType()->isVectorTy())
+ return false;
+ for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
+ auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
+ if (!CFP || !CFP->getValueAPF().getExactInverse(nullptr))
+ return false;
+ }
+ return true;
+}
+
+bool Constant::isNaN() const {
+ if (auto *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->isNaN();
+ if (!getType()->isVectorTy())
+ return false;
+ for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i) {
+ auto *CFP = dyn_cast_or_null<ConstantFP>(this->getAggregateElement(i));
+ if (!CFP || !CFP->isNaN())
+ return false;
+ }
+ return true;
+}
+
+bool Constant::containsUndefElement() const {
+ if (!getType()->isVectorTy())
+ return false;
+ for (unsigned i = 0, e = getType()->getVectorNumElements(); i != e; ++i)
+ if (isa<UndefValue>(getAggregateElement(i)))
+ return true;
+
+ return false;
+}
+
/// Constructor to create a '0' constant of arbitrary type.
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
@@ -635,6 +697,17 @@ Constant *ConstantFP::get(Type *Ty, double V) {
return C;
}
+Constant *ConstantFP::get(Type *Ty, const APFloat &V) {
+ ConstantFP *C = get(Ty->getContext(), V);
+ assert(C->getType() == Ty->getScalarType() &&
+ "ConstantFP type doesn't match the type implied by its value!");
+
+ // For vectors, broadcast the value.
+ if (auto *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getNumElements(), C);
+
+ return C;
+}
Constant *ConstantFP::get(Type *Ty, StringRef Str) {
LLVMContext &Context = Ty->getContext();
@@ -646,7 +719,7 @@ Constant *ConstantFP::get(Type *Ty, StringRef Str) {
if (VectorType *VTy = dyn_cast<VectorType>(Ty))
return ConstantVector::getSplat(VTy->getNumElements(), C);
- return C;
+ return C;
}
Constant *ConstantFP::getNaN(Type *Ty, bool Negative, unsigned Type) {
@@ -699,7 +772,7 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) {
else if (&V.getSemantics() == &APFloat::IEEEquad())
Ty = Type::getFP128Ty(Context);
else {
- assert(&V.getSemantics() == &APFloat::PPCDoubleDouble() &&
+ assert(&V.getSemantics() == &APFloat::PPCDoubleDouble() &&
"Unknown FP format");
Ty = Type::getPPC_FP128Ty(Context);
}
@@ -952,7 +1025,7 @@ Constant *ConstantStruct::get(StructType *ST, ArrayRef<Constant*> V) {
// Create a ConstantAggregateZero value if all elements are zeros.
bool isZero = true;
bool isUndef = false;
-
+
if (!V.empty()) {
isUndef = isa<UndefValue>(V[0]);
isZero = V[0]->isNullValue();
@@ -1213,17 +1286,17 @@ bool ConstantFP::isValueValidForType(Type *Ty, const APFloat& Val) {
}
case Type::X86_FP80TyID:
return &Val2.getSemantics() == &APFloat::IEEEhalf() ||
- &Val2.getSemantics() == &APFloat::IEEEsingle() ||
+ &Val2.getSemantics() == &APFloat::IEEEsingle() ||
&Val2.getSemantics() == &APFloat::IEEEdouble() ||
&Val2.getSemantics() == &APFloat::x87DoubleExtended();
case Type::FP128TyID:
return &Val2.getSemantics() == &APFloat::IEEEhalf() ||
- &Val2.getSemantics() == &APFloat::IEEEsingle() ||
+ &Val2.getSemantics() == &APFloat::IEEEsingle() ||
&Val2.getSemantics() == &APFloat::IEEEdouble() ||
&Val2.getSemantics() == &APFloat::IEEEquad();
case Type::PPC_FP128TyID:
return &Val2.getSemantics() == &APFloat::IEEEhalf() ||
- &Val2.getSemantics() == &APFloat::IEEEsingle() ||
+ &Val2.getSemantics() == &APFloat::IEEEsingle() ||
&Val2.getSemantics() == &APFloat::IEEEdouble() ||
&Val2.getSemantics() == &APFloat::PPCDoubleDouble();
}
@@ -1710,8 +1783,7 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
unsigned Flags, Type *OnlyIfReducedTy) {
// Check the operands for consistency first.
- assert(Opcode >= Instruction::BinaryOpsBegin &&
- Opcode < Instruction::BinaryOpsEnd &&
+ assert(Instruction::isBinaryOp(Opcode) &&
"Invalid opcode in binary constant expression");
assert(C1->getType() == C2->getType() &&
"Operand types in binary constant expression should match");
@@ -1733,8 +1805,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
"Tried to create a floating-point operation on a "
"non-floating-point type!");
break;
- case Instruction::UDiv:
- case Instruction::SDiv:
+ case Instruction::UDiv:
+ case Instruction::SDiv:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert(C1->getType()->isIntOrIntVectorTy() &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
@@ -1744,8 +1816,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
assert(C1->getType()->isFPOrFPVectorTy() &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
break;
- case Instruction::URem:
- case Instruction::SRem:
+ case Instruction::URem:
+ case Instruction::SRem:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert(C1->getType()->isIntOrIntVectorTy() &&
"Tried to create an arithmetic operation on a non-arithmetic type!");
@@ -1793,7 +1865,7 @@ Constant *ConstantExpr::getSizeOf(Type* Ty) {
Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
Constant *GEP = getGetElementPtr(
Ty, Constant::getNullValue(PointerType::getUnqual(Ty)), GEPIdx);
- return getPtrToInt(GEP,
+ return getPtrToInt(GEP,
Type::getInt64Ty(Ty->getContext()));
}
@@ -2199,22 +2271,49 @@ Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) {
isExact ? PossiblyExactOperator::IsExact : 0);
}
-Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty) {
- switch (Opcode) {
- default:
- // Doesn't have an identity.
- return nullptr;
-
- case Instruction::Add:
- case Instruction::Or:
- case Instruction::Xor:
- return Constant::getNullValue(Ty);
+Constant *ConstantExpr::getBinOpIdentity(unsigned Opcode, Type *Ty,
+ bool AllowRHSConstant) {
+ assert(Instruction::isBinaryOp(Opcode) && "Only binops allowed");
+
+ // Commutative opcodes: it does not matter if AllowRHSConstant is set.
+ if (Instruction::isCommutative(Opcode)) {
+ switch (Opcode) {
+ case Instruction::Add: // X + 0 = X
+ case Instruction::Or: // X | 0 = X
+ case Instruction::Xor: // X ^ 0 = X
+ return Constant::getNullValue(Ty);
+ case Instruction::Mul: // X * 1 = X
+ return ConstantInt::get(Ty, 1);
+ case Instruction::And: // X & -1 = X
+ return Constant::getAllOnesValue(Ty);
+ case Instruction::FAdd: // X + -0.0 = X
+ // TODO: If the fadd has 'nsz', should we return +0.0?
+ return ConstantFP::getNegativeZero(Ty);
+ case Instruction::FMul: // X * 1.0 = X
+ return ConstantFP::get(Ty, 1.0);
+ default:
+ llvm_unreachable("Every commutative binop has an identity constant");
+ }
+ }
- case Instruction::Mul:
- return ConstantInt::get(Ty, 1);
+ // Non-commutative opcodes: AllowRHSConstant must be set.
+ if (!AllowRHSConstant)
+ return nullptr;
- case Instruction::And:
- return Constant::getAllOnesValue(Ty);
+ switch (Opcode) {
+ case Instruction::Sub: // X - 0 = X
+ case Instruction::Shl: // X << 0 = X
+ case Instruction::LShr: // X >>u 0 = X
+ case Instruction::AShr: // X >> 0 = X
+ case Instruction::FSub: // X - 0.0 = X
+ return Constant::getNullValue(Ty);
+ case Instruction::SDiv: // X / 1 = X
+ case Instruction::UDiv: // X /u 1 = X
+ return ConstantInt::get(Ty, 1);
+ case Instruction::FDiv: // X / 1.0 = X
+ return ConstantFP::get(Ty, 1.0);
+ default:
+ return nullptr;
}
}
@@ -2354,7 +2453,7 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) {
void ConstantDataSequential::destroyConstantImpl() {
// Remove the constant from the StringMap.
- StringMap<ConstantDataSequential*> &CDSConstants =
+ StringMap<ConstantDataSequential*> &CDSConstants =
getType()->getContext().pImpl->CDSConstants;
StringMap<ConstantDataSequential*>::iterator Slot =
@@ -2371,7 +2470,7 @@ void ConstantDataSequential::destroyConstantImpl() {
assert((*Entry) == this && "Hash mismatch in ConstantDataSequential");
getContext().pImpl->CDSConstants.erase(Slot);
} else {
- // Otherwise, there are multiple entries linked off the bucket, unlink the
+ // Otherwise, there are multiple entries linked off the bucket, unlink the
// node we care about but keep the bucket around.
for (ConstantDataSequential *Node = *Entry; ;
Entry = &Node->Next, Node = *Entry) {
@@ -2389,40 +2488,6 @@ void ConstantDataSequential::destroyConstantImpl() {
Next = nullptr;
}
-/// get() constructors - Return a constant with array type with an element
-/// count and element type matching the ArrayRef passed in. Note that this
-/// can return a ConstantAggregateZero object.
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint8_t> Elts) {
- Type *Ty = ArrayType::get(Type::getInt8Ty(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 1), Ty);
-}
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint16_t> Elts){
- Type *Ty = ArrayType::get(Type::getInt16Ty(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 2), Ty);
-}
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint32_t> Elts){
- Type *Ty = ArrayType::get(Type::getInt32Ty(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 4), Ty);
-}
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<uint64_t> Elts){
- Type *Ty = ArrayType::get(Type::getInt64Ty(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 8), Ty);
-}
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<float> Elts) {
- Type *Ty = ArrayType::get(Type::getFloatTy(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 4), Ty);
-}
-Constant *ConstantDataArray::get(LLVMContext &Context, ArrayRef<double> Elts) {
- Type *Ty = ArrayType::get(Type::getDoubleTy(Context), Elts.size());
- const char *Data = reinterpret_cast<const char *>(Elts.data());
- return getImpl(StringRef(Data, Elts.size() * 8), Ty);
-}
-
/// getFP() constructors - Return a constant with array type with an element
/// count and element type of float with precision matching the number of
/// bits in the ArrayRef passed in. (i.e. half for 16bits, float for 32bits,
diff --git a/contrib/llvm/lib/IR/ConstantsContext.h b/contrib/llvm/lib/IR/ConstantsContext.h
index 6585304e7674..e9f31e4ded68 100644
--- a/contrib/llvm/lib/IR/ConstantsContext.h
+++ b/contrib/llvm/lib/IR/ConstantsContext.h
@@ -695,7 +695,9 @@ public:
return nullptr;
}
- void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); }
+ void dump() const {
+ LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+ }
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/IR/Core.cpp b/contrib/llvm/lib/IR/Core.cpp
index 743e3710fd68..bea4dee15c13 100644
--- a/contrib/llvm/lib/IR/Core.cpp
+++ b/contrib/llvm/lib/IR/Core.cpp
@@ -234,6 +234,15 @@ void LLVMSetModuleIdentifier(LLVMModuleRef M, const char *Ident, size_t Len) {
unwrap(M)->setModuleIdentifier(StringRef(Ident, Len));
}
+const char *LLVMGetSourceFileName(LLVMModuleRef M, size_t *Len) {
+ auto &Str = unwrap(M)->getSourceFileName();
+ *Len = Str.length();
+ return Str.c_str();
+}
+
+void LLVMSetSourceFileName(LLVMModuleRef M, const char *Name, size_t Len) {
+ unwrap(M)->setSourceFileName(StringRef(Name, Len));
+}
/*--.. Data layout .........................................................--*/
const char *LLVMGetDataLayoutStr(LLVMModuleRef M) {
@@ -257,6 +266,111 @@ void LLVMSetTarget(LLVMModuleRef M, const char *Triple) {
unwrap(M)->setTargetTriple(Triple);
}
+/*--.. Module flags ........................................................--*/
+struct LLVMOpaqueModuleFlagEntry {
+ LLVMModuleFlagBehavior Behavior;
+ const char *Key;
+ size_t KeyLen;
+ LLVMMetadataRef Metadata;
+};
+
+static Module::ModFlagBehavior
+map_to_llvmModFlagBehavior(LLVMModuleFlagBehavior Behavior) {
+ switch (Behavior) {
+ case LLVMModuleFlagBehaviorError:
+ return Module::ModFlagBehavior::Error;
+ case LLVMModuleFlagBehaviorWarning:
+ return Module::ModFlagBehavior::Warning;
+ case LLVMModuleFlagBehaviorRequire:
+ return Module::ModFlagBehavior::Require;
+ case LLVMModuleFlagBehaviorOverride:
+ return Module::ModFlagBehavior::Override;
+ case LLVMModuleFlagBehaviorAppend:
+ return Module::ModFlagBehavior::Append;
+ case LLVMModuleFlagBehaviorAppendUnique:
+ return Module::ModFlagBehavior::AppendUnique;
+ }
+ llvm_unreachable("Unknown LLVMModuleFlagBehavior");
+}
+
+static LLVMModuleFlagBehavior
+map_from_llvmModFlagBehavior(Module::ModFlagBehavior Behavior) {
+ switch (Behavior) {
+ case Module::ModFlagBehavior::Error:
+ return LLVMModuleFlagBehaviorError;
+ case Module::ModFlagBehavior::Warning:
+ return LLVMModuleFlagBehaviorWarning;
+ case Module::ModFlagBehavior::Require:
+ return LLVMModuleFlagBehaviorRequire;
+ case Module::ModFlagBehavior::Override:
+ return LLVMModuleFlagBehaviorOverride;
+ case Module::ModFlagBehavior::Append:
+ return LLVMModuleFlagBehaviorAppend;
+ case Module::ModFlagBehavior::AppendUnique:
+ return LLVMModuleFlagBehaviorAppendUnique;
+ default:
+ llvm_unreachable("Unhandled Flag Behavior");
+ }
+}
+
+LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len) {
+ SmallVector<Module::ModuleFlagEntry, 8> MFEs;
+ unwrap(M)->getModuleFlagsMetadata(MFEs);
+
+ LLVMOpaqueModuleFlagEntry *Result = static_cast<LLVMOpaqueModuleFlagEntry *>(
+ safe_malloc(MFEs.size() * sizeof(LLVMOpaqueModuleFlagEntry)));
+ for (unsigned i = 0; i < MFEs.size(); ++i) {
+ const auto &ModuleFlag = MFEs[i];
+ Result[i].Behavior = map_from_llvmModFlagBehavior(ModuleFlag.Behavior);
+ Result[i].Key = ModuleFlag.Key->getString().data();
+ Result[i].KeyLen = ModuleFlag.Key->getString().size();
+ Result[i].Metadata = wrap(ModuleFlag.Val);
+ }
+ *Len = MFEs.size();
+ return Result;
+}
+
+void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries) {
+ free(Entries);
+}
+
+LLVMModuleFlagBehavior
+LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries,
+ unsigned Index) {
+ LLVMOpaqueModuleFlagEntry MFE =
+ static_cast<LLVMOpaqueModuleFlagEntry>(Entries[Index]);
+ return MFE.Behavior;
+}
+
+const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries,
+ unsigned Index, size_t *Len) {
+ LLVMOpaqueModuleFlagEntry MFE =
+ static_cast<LLVMOpaqueModuleFlagEntry>(Entries[Index]);
+ *Len = MFE.KeyLen;
+ return MFE.Key;
+}
+
+LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries,
+ unsigned Index) {
+ LLVMOpaqueModuleFlagEntry MFE =
+ static_cast<LLVMOpaqueModuleFlagEntry>(Entries[Index]);
+ return MFE.Metadata;
+}
+
+LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M,
+ const char *Key, size_t KeyLen) {
+ return wrap(unwrap(M)->getModuleFlag({Key, KeyLen}));
+}
+
+void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior,
+ const char *Key, size_t KeyLen,
+ LLVMMetadataRef Val) {
+ unwrap(M)->addModuleFlag(map_to_llvmModFlagBehavior(Behavior),
+ {Key, KeyLen}, unwrap(Val));
+}
+
+/*--.. Printing modules ....................................................--*/
+
void LLVMDumpModule(LLVMModuleRef M) {
unwrap(M)->print(errs(), nullptr,
/*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
@@ -295,10 +409,44 @@ char *LLVMPrintModuleToString(LLVMModuleRef M) {
}
/*--.. Operations on inline assembler ......................................--*/
+void LLVMSetModuleInlineAsm2(LLVMModuleRef M, const char *Asm, size_t Len) {
+ unwrap(M)->setModuleInlineAsm(StringRef(Asm, Len));
+}
+
void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
unwrap(M)->setModuleInlineAsm(StringRef(Asm));
}
+void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len) {
+ unwrap(M)->appendModuleInlineAsm(StringRef(Asm, Len));
+}
+
+const char *LLVMGetModuleInlineAsm(LLVMModuleRef M, size_t *Len) {
+ auto &Str = unwrap(M)->getModuleInlineAsm();
+ *Len = Str.length();
+ return Str.c_str();
+}
+
+LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty,
+ char *AsmString, size_t AsmStringSize,
+ char *Constraints, size_t ConstraintsSize,
+ LLVMBool HasSideEffects, LLVMBool IsAlignStack,
+ LLVMInlineAsmDialect Dialect) {
+ InlineAsm::AsmDialect AD;
+ switch (Dialect) {
+ case LLVMInlineAsmDialectATT:
+ AD = InlineAsm::AD_ATT;
+ break;
+ case LLVMInlineAsmDialectIntel:
+ AD = InlineAsm::AD_Intel;
+ break;
+ }
+ return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
+ StringRef(AsmString, AsmStringSize),
+ StringRef(Constraints, ConstraintsSize),
+ HasSideEffects, IsAlignStack, AD));
+}
+
/*--.. Operations on module contexts ......................................--*/
LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M) {
@@ -648,6 +796,16 @@ LLVMValueKind LLVMGetValueKind(LLVMValueRef Val) {
}
}
+const char *LLVMGetValueName2(LLVMValueRef Val, size_t *Length) {
+ auto *V = unwrap(Val);
+ *Length = V->getName().size();
+ return V->getName().data();
+}
+
+void LLVMSetValueName2(LLVMValueRef Val, const char *Name, size_t NameLen) {
+ unwrap(Val)->setName(StringRef(Name, NameLen));
+}
+
const char *LLVMGetValueName(LLVMValueRef Val) {
return unwrap(Val)->getName().data();
}
@@ -1521,8 +1679,9 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) {
GV->setLinkage(GlobalValue::LinkOnceODRLinkage);
break;
case LLVMLinkOnceODRAutoHideLinkage:
- DEBUG(errs() << "LLVMSetLinkage(): LLVMLinkOnceODRAutoHideLinkage is no "
- "longer supported.");
+ LLVM_DEBUG(
+ errs() << "LLVMSetLinkage(): LLVMLinkOnceODRAutoHideLinkage is no "
+ "longer supported.");
break;
case LLVMWeakAnyLinkage:
GV->setLinkage(GlobalValue::WeakAnyLinkage);
@@ -1546,19 +1705,21 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) {
GV->setLinkage(GlobalValue::PrivateLinkage);
break;
case LLVMDLLImportLinkage:
- DEBUG(errs()
- << "LLVMSetLinkage(): LLVMDLLImportLinkage is no longer supported.");
+ LLVM_DEBUG(
+ errs()
+ << "LLVMSetLinkage(): LLVMDLLImportLinkage is no longer supported.");
break;
case LLVMDLLExportLinkage:
- DEBUG(errs()
- << "LLVMSetLinkage(): LLVMDLLExportLinkage is no longer supported.");
+ LLVM_DEBUG(
+ errs()
+ << "LLVMSetLinkage(): LLVMDLLExportLinkage is no longer supported.");
break;
case LLVMExternalWeakLinkage:
GV->setLinkage(GlobalValue::ExternalWeakLinkage);
break;
case LLVMGhostLinkage:
- DEBUG(errs()
- << "LLVMSetLinkage(): LLVMGhostLinkage is no longer supported.");
+ LLVM_DEBUG(
+ errs() << "LLVMSetLinkage(): LLVMGhostLinkage is no longer supported.");
break;
case LLVMCommonLinkage:
GV->setLinkage(GlobalValue::CommonLinkage);
@@ -1596,6 +1757,31 @@ void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class) {
static_cast<GlobalValue::DLLStorageClassTypes>(Class));
}
+LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global) {
+ switch (unwrap<GlobalValue>(Global)->getUnnamedAddr()) {
+ case GlobalVariable::UnnamedAddr::None:
+ return LLVMNoUnnamedAddr;
+ case GlobalVariable::UnnamedAddr::Local:
+ return LLVMLocalUnnamedAddr;
+ case GlobalVariable::UnnamedAddr::Global:
+ return LLVMGlobalUnnamedAddr;
+ }
+ llvm_unreachable("Unknown UnnamedAddr kind!");
+}
+
+void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr) {
+ GlobalValue *GV = unwrap<GlobalValue>(Global);
+
+ switch (UnnamedAddr) {
+ case LLVMNoUnnamedAddr:
+ return GV->setUnnamedAddr(GlobalVariable::UnnamedAddr::None);
+ case LLVMLocalUnnamedAddr:
+ return GV->setUnnamedAddr(GlobalVariable::UnnamedAddr::Local);
+ case LLVMGlobalUnnamedAddr:
+ return GV->setUnnamedAddr(GlobalVariable::UnnamedAddr::Global);
+ }
+}
+
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global) {
return unwrap<GlobalValue>(Global)->hasGlobalUnnamedAddr();
}
@@ -1779,6 +1965,51 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
unwrap<Constant>(Aliasee), unwrap(M)));
}
+LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M,
+ const char *Name, size_t NameLen) {
+ return wrap(unwrap(M)->getNamedAlias(Name));
+}
+
+LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M) {
+ Module *Mod = unwrap(M);
+ Module::alias_iterator I = Mod->alias_begin();
+ if (I == Mod->alias_end())
+ return nullptr;
+ return wrap(&*I);
+}
+
+LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M) {
+ Module *Mod = unwrap(M);
+ Module::alias_iterator I = Mod->alias_end();
+ if (I == Mod->alias_begin())
+ return nullptr;
+ return wrap(&*--I);
+}
+
+LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA) {
+ GlobalAlias *Alias = unwrap<GlobalAlias>(GA);
+ Module::alias_iterator I(Alias);
+ if (++I == Alias->getParent()->alias_end())
+ return nullptr;
+ return wrap(&*I);
+}
+
+LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA) {
+ GlobalAlias *Alias = unwrap<GlobalAlias>(GA);
+ Module::alias_iterator I(Alias);
+ if (I == Alias->getParent()->alias_begin())
+ return nullptr;
+ return wrap(&*--I);
+}
+
+LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias) {
+ return wrap(unwrap<GlobalAlias>(Alias)->getAliasee());
+}
+
+void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee) {
+ unwrap<GlobalAlias>(Alias)->setAliasee(unwrap<Constant>(Aliasee));
+}
+
/*--.. Operations on functions .............................................--*/
LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name,
@@ -2160,12 +2391,15 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) {
return nullptr;
}
-/*--.. Call and invoke instructions ........................................--*/
-
unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) {
+ if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) {
+ return FPI->getNumArgOperands();
+ }
return CallSite(unwrap<Instruction>(Instr)).getNumArgOperands();
}
+/*--.. Call and invoke instructions ........................................--*/
+
unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) {
return CallSite(unwrap<Instruction>(Instr)).getCallingConv();
}
@@ -2248,6 +2482,11 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef Invoke) {
}
LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef Invoke) {
+ if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
+ return wrap(CRI->getUnwindDest());
+ } else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
+ return wrap(CSI->getUnwindDest());
+ }
return wrap(unwrap<InvokeInst>(Invoke)->getUnwindDest());
}
@@ -2256,6 +2495,11 @@ void LLVMSetNormalDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
}
void LLVMSetUnwindDest(LLVMValueRef Invoke, LLVMBasicBlockRef B) {
+ if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(unwrap(Invoke))) {
+ return CRI->setUnwindDest(unwrap(B));
+ } else if (CatchSwitchInst *CSI = dyn_cast<CatchSwitchInst>(unwrap(Invoke))) {
+ return CSI->setUnwindDest(unwrap(B));
+ }
unwrap<InvokeInst>(Invoke)->setUnwindDest(unwrap(B));
}
@@ -2477,10 +2721,53 @@ LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
return wrap(unwrap(B)->CreateLandingPad(unwrap(Ty), NumClauses, Name));
}
+LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMValueRef *Args, unsigned NumArgs,
+ const char *Name) {
+ return wrap(unwrap(B)->CreateCatchPad(unwrap(ParentPad),
+ makeArrayRef(unwrap(Args), NumArgs),
+ Name));
+}
+
+LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMValueRef *Args, unsigned NumArgs,
+ const char *Name) {
+ if (ParentPad == nullptr) {
+ Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
+ ParentPad = wrap(Constant::getNullValue(Ty));
+ }
+ return wrap(unwrap(B)->CreateCleanupPad(unwrap(ParentPad),
+ makeArrayRef(unwrap(Args), NumArgs),
+ Name));
+}
+
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn) {
return wrap(unwrap(B)->CreateResume(unwrap(Exn)));
}
+LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad,
+ LLVMBasicBlockRef UnwindBB,
+ unsigned NumHandlers, const char *Name) {
+ if (ParentPad == nullptr) {
+ Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
+ ParentPad = wrap(Constant::getNullValue(Ty));
+ }
+ return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(UnwindBB),
+ NumHandlers, Name));
+}
+
+LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
+ LLVMBasicBlockRef BB) {
+ return wrap(unwrap(B)->CreateCatchRet(unwrap<CatchPadInst>(CatchPad),
+ unwrap(BB)));
+}
+
+LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad,
+ LLVMBasicBlockRef BB) {
+ return wrap(unwrap(B)->CreateCleanupRet(unwrap<CleanupPadInst>(CatchPad),
+ unwrap(BB)));
+}
+
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef B) {
return wrap(unwrap(B)->CreateUnreachable());
}
@@ -2515,6 +2802,40 @@ void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val) {
unwrap<LandingPadInst>(LandingPad)->setCleanup(Val);
}
+void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest) {
+ unwrap<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Dest));
+}
+
+unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch) {
+ return unwrap<CatchSwitchInst>(CatchSwitch)->getNumHandlers();
+}
+
+void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers) {
+ CatchSwitchInst *CSI = unwrap<CatchSwitchInst>(CatchSwitch);
+ for (CatchSwitchInst::handler_iterator I = CSI->handler_begin(),
+ E = CSI->handler_end(); I != E; ++I)
+ *Handlers++ = wrap(*I);
+}
+
+LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad) {
+ return wrap(unwrap<CatchPadInst>(CatchPad)->getCatchSwitch());
+}
+
+void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch) {
+ unwrap<CatchPadInst>(CatchPad)
+ ->setCatchSwitch(unwrap<CatchSwitchInst>(CatchSwitch));
+}
+
+/*--.. Funclets ...........................................................--*/
+
+LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i) {
+ return wrap(unwrap<FuncletPadInst>(Funclet)->getArgOperand(i));
+}
+
+void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value) {
+ unwrap<FuncletPadInst>(Funclet)->setArgOperand(i, unwrap(value));
+}
+
/*--.. Arithmetic ..........................................................--*/
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS,
diff --git a/contrib/llvm/lib/IR/DIBuilder.cpp b/contrib/llvm/lib/IR/DIBuilder.cpp
index a00c595d01c5..5c5477f4f40f 100644
--- a/contrib/llvm/lib/IR/DIBuilder.cpp
+++ b/contrib/llvm/lib/IR/DIBuilder.cpp
@@ -14,6 +14,7 @@
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "LLVMContextImpl.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Constants.h"
@@ -30,9 +31,9 @@ cl::opt<bool>
llvm::cl::desc("Use llvm.dbg.addr for all local variables"),
cl::init(false), cl::Hidden);
-DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
- : M(m), VMContext(M.getContext()), CUNode(nullptr),
- DeclareFn(nullptr), ValueFn(nullptr),
+DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU)
+ : M(m), VMContext(M.getContext()), CUNode(CU),
+ DeclareFn(nullptr), ValueFn(nullptr), LabelFn(nullptr),
AllowUnresolvedNodes(AllowUnresolvedNodes) {}
void DIBuilder::trackIfUnresolved(MDNode *N) {
@@ -46,18 +47,23 @@ void DIBuilder::trackIfUnresolved(MDNode *N) {
}
void DIBuilder::finalizeSubprogram(DISubprogram *SP) {
- MDTuple *Temp = SP->getVariables().get();
+ MDTuple *Temp = SP->getRetainedNodes().get();
if (!Temp || !Temp->isTemporary())
return;
- SmallVector<Metadata *, 4> Variables;
+ SmallVector<Metadata *, 16> RetainedNodes;
auto PV = PreservedVariables.find(SP);
if (PV != PreservedVariables.end())
- Variables.append(PV->second.begin(), PV->second.end());
+ RetainedNodes.append(PV->second.begin(), PV->second.end());
- DINodeArray AV = getOrCreateArray(Variables);
- TempMDTuple(Temp)->replaceAllUsesWith(AV.get());
+ auto PL = PreservedLabels.find(SP);
+ if (PL != PreservedLabels.end())
+ RetainedNodes.append(PL->second.begin(), PL->second.end());
+
+ DINodeArray Node = getOrCreateArray(RetainedNodes);
+
+ TempMDTuple(Temp)->replaceAllUsesWith(Node.get());
}
void DIBuilder::finalize() {
@@ -204,8 +210,9 @@ DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
}
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,
- DIFile::ChecksumKind CSKind, StringRef Checksum) {
- return DIFile::get(VMContext, Filename, Directory, CSKind, Checksum);
+ Optional<DIFile::ChecksumInfo<StringRef>> CS,
+ Optional<StringRef> Source) {
+ return DIFile::get(VMContext, Filename, Directory, CS, Source);
}
DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber,
@@ -233,9 +240,10 @@ DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent,
return MF;
}
-DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val) {
+DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val,
+ bool IsUnsigned) {
assert(!Name.empty() && "Unable to create enumerator without name");
- return DIEnumerator::get(VMContext, Val, Name);
+ return DIEnumerator::get(VMContext, Val, IsUnsigned, Name);
}
DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) {
@@ -310,10 +318,14 @@ DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy,
uint64_t BaseOffset,
+ uint32_t VBPtrOffset,
DINode::DIFlags Flags) {
assert(Ty && "Unable to create inheritance");
+ Metadata *ExtraData = ConstantAsMetadata::get(
+ ConstantInt::get(IntegerType::get(VMContext, 32), VBPtrOffset));
return DIDerivedType::get(VMContext, dwarf::DW_TAG_inheritance, "", nullptr,
- 0, Ty, BaseTy, 0, 0, BaseOffset, None, Flags);
+ 0, Ty, BaseTy, 0, 0, BaseOffset, None,
+ Flags, ExtraData);
}
DIDerivedType *DIBuilder::createMemberType(DIScope *Scope, StringRef Name,
@@ -333,6 +345,19 @@ static ConstantAsMetadata *getConstantOrNull(Constant *C) {
return nullptr;
}
+DIDerivedType *DIBuilder::createVariantMemberType(DIScope *Scope, StringRef Name,
+ DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint32_t AlignInBits,
+ uint64_t OffsetInBits,
+ Constant *Discriminant,
+ DINode::DIFlags Flags, DIType *Ty) {
+ return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File,
+ LineNumber, getNonCompileUnitScope(Scope), Ty,
+ SizeInBits, AlignInBits, OffsetInBits, None, Flags,
+ getConstantOrNull(Discriminant));
+}
+
DIDerivedType *DIBuilder::createBitFieldMemberType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits,
@@ -458,6 +483,18 @@ DICompositeType *DIBuilder::createUnionType(
return R;
}
+DICompositeType *DIBuilder::createVariantPart(
+ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
+ DIDerivedType *Discriminator, DINodeArray Elements, StringRef UniqueIdentifier) {
+ auto *R = DICompositeType::get(
+ VMContext, dwarf::DW_TAG_variant_part, Name, File, LineNumber,
+ getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
+ Elements, 0, nullptr, nullptr, UniqueIdentifier, Discriminator);
+ trackIfUnresolved(R);
+ return R;
+}
+
DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
DINode::DIFlags Flags,
unsigned CC) {
@@ -467,11 +504,12 @@ DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
DICompositeType *DIBuilder::createEnumerationType(
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
- DIType *UnderlyingType, StringRef UniqueIdentifier) {
+ DIType *UnderlyingType, StringRef UniqueIdentifier, bool IsFixed) {
auto *CTy = DICompositeType::get(
VMContext, dwarf::DW_TAG_enumeration_type, Name, File, LineNumber,
getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0,
- DINode::FlagZero, Elements, 0, nullptr, nullptr, UniqueIdentifier);
+ IsFixed ? DINode::FlagFixedEnum : DINode::FlagZero, Elements, 0, nullptr,
+ nullptr, UniqueIdentifier);
AllEnumTypes.push_back(CTy);
trackIfUnresolved(CTy);
return CTy;
@@ -497,10 +535,14 @@ DICompositeType *DIBuilder::createVectorType(uint64_t Size,
return R;
}
-static DIType *createTypeWithFlags(LLVMContext &Context, DIType *Ty,
+DISubprogram *DIBuilder::createArtificialSubprogram(DISubprogram *SP) {
+ auto NewSP = SP->cloneWithFlags(SP->getFlags() | DINode::FlagArtificial);
+ return MDNode::replaceWithDistinct(std::move(NewSP));
+}
+
+static DIType *createTypeWithFlags(const DIType *Ty,
DINode::DIFlags FlagsToSet) {
- auto NewTy = Ty->clone();
- NewTy->setFlags(NewTy->getFlags() | FlagsToSet);
+ auto NewTy = Ty->cloneWithFlags(Ty->getFlags() | FlagsToSet);
return MDNode::replaceWithUniqued(std::move(NewTy));
}
@@ -508,7 +550,7 @@ DIType *DIBuilder::createArtificialType(DIType *Ty) {
// FIXME: Restrict this to the nodes where it's valid.
if (Ty->isArtificial())
return Ty;
- return createTypeWithFlags(VMContext, Ty, DINode::FlagArtificial);
+ return createTypeWithFlags(Ty, DINode::FlagArtificial);
}
DIType *DIBuilder::createObjectPointerType(DIType *Ty) {
@@ -516,7 +558,7 @@ DIType *DIBuilder::createObjectPointerType(DIType *Ty) {
if (Ty->isObjectPointer())
return Ty;
DINode::DIFlags Flags = DINode::FlagObjectPointer | DINode::FlagArtificial;
- return createTypeWithFlags(VMContext, Ty, Flags);
+ return createTypeWithFlags(Ty, Flags);
}
void DIBuilder::retainType(DIScope *T) {
@@ -582,6 +624,10 @@ DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
return DISubrange::get(VMContext, Count, Lo);
}
+DISubrange *DIBuilder::getOrCreateSubrange(int64_t Lo, Metadata *CountNode) {
+ return DISubrange::get(VMContext, CountNode, Lo);
+}
+
static void checkGlobalVariableScope(DIScope *Context) {
#ifndef NDEBUG
if (auto *CT =
@@ -666,6 +712,26 @@ DILocalVariable *DIBuilder::createParameterVariable(
/* AlignInBits */0);
}
+DILabel *DIBuilder::createLabel(
+ DIScope *Scope, StringRef Name, DIFile *File,
+ unsigned LineNo, bool AlwaysPreserve) {
+ DIScope *Context = getNonCompileUnitScope(Scope);
+
+ auto *Node =
+ DILabel::get(VMContext, cast_or_null<DILocalScope>(Context), Name,
+ File, LineNo);
+
+ if (AlwaysPreserve) {
+ /// The optimizer may remove labels. If there is an interest
+ /// to preserve label info in such situation then append it to
+ /// the list of retained nodes of the DISubprogram.
+ DISubprogram *Fn = getDISubprogram(Scope);
+ assert(Fn && "Missing subprogram for label");
+ PreservedLabels[Fn].emplace_back(Node);
+ }
+ return Node;
+}
+
DIExpression *DIBuilder::createExpression(ArrayRef<uint64_t> Addr) {
return DIExpression::get(VMContext, Addr);
}
@@ -788,6 +854,18 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
return insertDeclare(Storage, VarInfo, Expr, DL, InsertAtEnd, InsertBefore);
}
+Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
+ Instruction *InsertBefore) {
+ return insertLabel(
+ LabelInfo, DL, InsertBefore ? InsertBefore->getParent() : nullptr,
+ InsertBefore);
+}
+
+Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL,
+ BasicBlock *InsertAtEnd) {
+ return insertLabel(LabelInfo, DL, InsertAtEnd, nullptr);
+}
+
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V,
DILocalVariable *VarInfo,
DIExpression *Expr,
@@ -873,6 +951,24 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(
return B.CreateCall(ValueFn, Args);
}
+Instruction *DIBuilder::insertLabel(
+ DILabel *LabelInfo, const DILocation *DL,
+ BasicBlock *InsertBB, Instruction *InsertBefore) {
+ assert(LabelInfo && "empty or invalid DILabel* passed to dbg.label");
+ assert(DL && "Expected debug loc");
+ assert(DL->getScope()->getSubprogram() ==
+ LabelInfo->getScope()->getSubprogram() &&
+ "Expected matching subprograms");
+ if (!LabelFn)
+ LabelFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_label);
+
+ trackIfUnresolved(LabelInfo);
+ Value *Args[] = {MetadataAsValue::get(VMContext, LabelInfo)};
+
+ IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore);
+ return B.CreateCall(LabelFn, Args);
+}
+
void DIBuilder::replaceVTableHolder(DICompositeType *&T,
DIType *VTableHolder) {
{
diff --git a/contrib/llvm/lib/IR/DataLayout.cpp b/contrib/llvm/lib/IR/DataLayout.cpp
index f4dddeb30d0b..62c67127276e 100644
--- a/contrib/llvm/lib/IR/DataLayout.cpp
+++ b/contrib/llvm/lib/IR/DataLayout.cpp
@@ -129,13 +129,15 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
PointerAlignElem
PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth) {
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth) {
assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
PointerAlignElem retval;
retval.AddressSpace = AddressSpace;
retval.ABIAlign = ABIAlign;
retval.PrefAlign = PrefAlign;
retval.TypeByteWidth = TypeByteWidth;
+ retval.IndexWidth = IndexWidth;
return retval;
}
@@ -144,7 +146,8 @@ PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
return (ABIAlign == rhs.ABIAlign
&& AddressSpace == rhs.AddressSpace
&& PrefAlign == rhs.PrefAlign
- && TypeByteWidth == rhs.TypeByteWidth);
+ && TypeByteWidth == rhs.TypeByteWidth
+ && IndexWidth == rhs.IndexWidth);
}
//===----------------------------------------------------------------------===//
@@ -181,6 +184,7 @@ void DataLayout::reset(StringRef Desc) {
BigEndian = false;
AllocaAddrSpace = 0;
StackNaturalAlign = 0;
+ ProgramAddrSpace = 0;
ManglingMode = MM_None;
NonIntegralAddressSpaces.clear();
@@ -189,7 +193,7 @@ void DataLayout::reset(StringRef Desc) {
setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
E.TypeBitWidth);
}
- setPointerAlignment(0, 8, 8, 8);
+ setPointerAlignment(0, 8, 8, 8, 8);
parseSpecifier(Desc);
}
@@ -221,6 +225,13 @@ static unsigned inBytes(unsigned Bits) {
return Bits / 8;
}
+static unsigned getAddrSpace(StringRef R) {
+ unsigned AddrSpace = getInt(R);
+ if (!isUInt<24>(AddrSpace))
+ report_fatal_error("Invalid address space, must be a 24-bit integer");
+ return AddrSpace;
+}
+
void DataLayout::parseSpecifier(StringRef Desc) {
StringRepresentation = Desc;
while (!Desc.empty()) {
@@ -287,6 +298,10 @@ void DataLayout::parseSpecifier(StringRef Desc) {
report_fatal_error(
"Pointer ABI alignment must be a power of 2");
+ // Size of index used in GEP for address calculation.
+ // The parameter is optional. By default it is equal to size of pointer.
+ unsigned IndexSize = PointerMemSize;
+
// Preferred alignment.
unsigned PointerPrefAlign = PointerABIAlign;
if (!Rest.empty()) {
@@ -295,10 +310,17 @@ void DataLayout::parseSpecifier(StringRef Desc) {
if (!isPowerOf2_64(PointerPrefAlign))
report_fatal_error(
"Pointer preferred alignment must be a power of 2");
- }
+ // Now read the index. It is the second optional parameter here.
+ if (!Rest.empty()) {
+ Split = split(Rest, ':');
+ IndexSize = inBytes(getInt(Tok));
+ if (!IndexSize)
+ report_fatal_error("Invalid index size of 0 bytes");
+ }
+ }
setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign,
- PointerMemSize);
+ PointerMemSize, IndexSize);
break;
}
case 'i':
@@ -358,10 +380,12 @@ void DataLayout::parseSpecifier(StringRef Desc) {
StackNaturalAlign = inBytes(getInt(Tok));
break;
}
+ case 'P': { // Function address space.
+ ProgramAddrSpace = getAddrSpace(Tok);
+ break;
+ }
case 'A': { // Default stack/alloca address space.
- AllocaAddrSpace = getInt(Tok);
- if (!isUInt<24>(AllocaAddrSpace))
- report_fatal_error("Invalid address space, must be a 24bit integer");
+ AllocaAddrSpace = getAddrSpace(Tok);
break;
}
case 'm':
@@ -408,6 +432,7 @@ bool DataLayout::operator==(const DataLayout &Other) const {
bool Ret = BigEndian == Other.BigEndian &&
AllocaAddrSpace == Other.AllocaAddrSpace &&
StackNaturalAlign == Other.StackNaturalAlign &&
+ ProgramAddrSpace == Other.ProgramAddrSpace &&
ManglingMode == Other.ManglingMode &&
LegalIntWidths == Other.LegalIntWidths &&
Alignments == Other.Alignments && Pointers == Other.Pointers;
@@ -467,8 +492,8 @@ DataLayout::findPointerLowerBound(uint32_t AddressSpace) {
}
void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
- unsigned PrefAlign,
- uint32_t TypeByteWidth) {
+ unsigned PrefAlign, uint32_t TypeByteWidth,
+ uint32_t IndexWidth) {
if (PrefAlign < ABIAlign)
report_fatal_error(
"Preferred alignment cannot be less than the ABI alignment");
@@ -476,11 +501,12 @@ void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
PointersTy::iterator I = findPointerLowerBound(AddrSpace);
if (I == Pointers.end() || I->AddressSpace != AddrSpace) {
Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign,
- TypeByteWidth));
+ TypeByteWidth, IndexWidth));
} else {
I->ABIAlign = ABIAlign;
I->PrefAlign = PrefAlign;
I->TypeByteWidth = TypeByteWidth;
+ I->IndexWidth = IndexWidth;
}
}
@@ -570,10 +596,8 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
// Otherwise, create the struct layout. Because it is variable length, we
// malloc it, then use placement new.
int NumElts = Ty->getNumElements();
- StructLayout *L =
- (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
- if (L == nullptr)
- report_bad_alloc_error("Allocation of StructLayout elements failed.");
+ StructLayout *L = (StructLayout *)
+ safe_malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
// Set SL before calling StructLayout's ctor. The ctor could cause other
// entries to be added to TheMap, invalidating our reference.
@@ -618,6 +642,22 @@ unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
}
+unsigned DataLayout::getIndexSize(unsigned AS) const {
+ PointersTy::const_iterator I = findPointerLowerBound(AS);
+ if (I == Pointers.end() || I->AddressSpace != AS) {
+ I = findPointerLowerBound(0);
+ assert(I->AddressSpace == 0);
+ }
+ return I->IndexWidth;
+}
+
+unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "This should only be called with a pointer or pointer vector type");
+ Ty = Ty->getScalarType();
+ return getIndexSizeInBits(cast<PointerType>(Ty)->getAddressSpace());
+}
+
/*!
\param abi_or_pref Flag that determines which alignment is returned. true
returns the ABI alignment, false returns the preferred alignment.
@@ -701,13 +741,13 @@ unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
unsigned AddressSpace) const {
- return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
+ return IntegerType::get(C, getIndexSizeInBits(AddressSpace));
}
Type *DataLayout::getIntPtrType(Type *Ty) const {
assert(Ty->isPtrOrPtrVectorTy() &&
"Expected a pointer or pointer vector type.");
- unsigned NumBits = getPointerTypeSizeInBits(Ty);
+ unsigned NumBits = getIndexTypeSizeInBits(Ty);
IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
return VectorType::get(IntTy, VecTy->getNumElements());
@@ -726,6 +766,16 @@ unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const {
return Max != LegalIntWidths.end() ? *Max : 0;
}
+Type *DataLayout::getIndexType(Type *Ty) const {
+ assert(Ty->isPtrOrPtrVectorTy() &&
+ "Expected a pointer or pointer vector type.");
+ unsigned NumBits = getIndexTypeSizeInBits(Ty);
+ IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits);
+ if (VectorType *VecTy = dyn_cast<VectorType>(Ty))
+ return VectorType::get(IntTy, VecTy->getNumElements());
+ return IntTy;
+}
+
int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy,
ArrayRef<Value *> Indices) const {
int64_t Result = 0;
diff --git a/contrib/llvm/lib/IR/DebugInfo.cpp b/contrib/llvm/lib/IR/DebugInfo.cpp
index 7fff7526b926..77585ee30cd8 100644
--- a/contrib/llvm/lib/IR/DebugInfo.cpp
+++ b/contrib/llvm/lib/IR/DebugInfo.cpp
@@ -61,49 +61,60 @@ void DebugInfoFinder::reset() {
}
void DebugInfoFinder::processModule(const Module &M) {
- for (auto *CU : M.debug_compile_units()) {
- addCompileUnit(CU);
- for (auto DIG : CU->getGlobalVariables()) {
- if (!addGlobalVariable(DIG))
- continue;
- auto *GV = DIG->getVariable();
- processScope(GV->getScope());
- processType(GV->getType().resolve());
- }
- for (auto *ET : CU->getEnumTypes())
- processType(ET);
- for (auto *RT : CU->getRetainedTypes())
- if (auto *T = dyn_cast<DIType>(RT))
- processType(T);
- else
- processSubprogram(cast<DISubprogram>(RT));
- for (auto *Import : CU->getImportedEntities()) {
- auto *Entity = Import->getEntity().resolve();
- if (auto *T = dyn_cast<DIType>(Entity))
- processType(T);
- else if (auto *SP = dyn_cast<DISubprogram>(Entity))
- processSubprogram(SP);
- else if (auto *NS = dyn_cast<DINamespace>(Entity))
- processScope(NS->getScope());
- else if (auto *M = dyn_cast<DIModule>(Entity))
- processScope(M->getScope());
- }
- }
+ for (auto *CU : M.debug_compile_units())
+ processCompileUnit(CU);
for (auto &F : M.functions()) {
if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram()))
processSubprogram(SP);
// There could be subprograms from inlined functions referenced from
// instructions only. Walk the function to find them.
- for (const BasicBlock &BB : F) {
- for (const Instruction &I : BB) {
- if (!I.getDebugLoc())
- continue;
- processLocation(M, I.getDebugLoc().get());
- }
- }
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ processInstruction(M, I);
}
}
+void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
+ if (!addCompileUnit(CU))
+ return;
+ for (auto DIG : CU->getGlobalVariables()) {
+ if (!addGlobalVariable(DIG))
+ continue;
+ auto *GV = DIG->getVariable();
+ processScope(GV->getScope());
+ processType(GV->getType().resolve());
+ }
+ for (auto *ET : CU->getEnumTypes())
+ processType(ET);
+ for (auto *RT : CU->getRetainedTypes())
+ if (auto *T = dyn_cast<DIType>(RT))
+ processType(T);
+ else
+ processSubprogram(cast<DISubprogram>(RT));
+ for (auto *Import : CU->getImportedEntities()) {
+ auto *Entity = Import->getEntity().resolve();
+ if (auto *T = dyn_cast<DIType>(Entity))
+ processType(T);
+ else if (auto *SP = dyn_cast<DISubprogram>(Entity))
+ processSubprogram(SP);
+ else if (auto *NS = dyn_cast<DINamespace>(Entity))
+ processScope(NS->getScope());
+ else if (auto *M = dyn_cast<DIModule>(Entity))
+ processScope(M->getScope());
+ }
+}
+
+void DebugInfoFinder::processInstruction(const Module &M,
+ const Instruction &I) {
+ if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
+ processDeclare(M, DDI);
+ else if (auto *DVI = dyn_cast<DbgValueInst>(&I))
+ processValue(M, DVI);
+
+ if (auto DbgLoc = I.getDebugLoc())
+ processLocation(M, DbgLoc.get());
+}
+
void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
if (!Loc)
return;
@@ -165,6 +176,15 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
if (!addSubprogram(SP))
return;
processScope(SP->getScope().resolve());
+ // Some of the users, e.g. CloneFunctionInto / CloneModule, need to set up a
+ // ValueMap containing identity mappings for all of the DICompileUnit's, not
+ // just DISubprogram's, referenced from anywhere within the Function being
+ // cloned prior to calling MapMetadata / RemapInstruction to avoid their
+ // duplication later as DICompileUnit's are also directly referenced by
+ // llvm.dbg.cu list. Thefore we need to collect DICompileUnit's here as well.
+ // Also, DICompileUnit's may reference DISubprogram's too and therefore need
+ // to be at least looked through.
+ processCompileUnit(SP->getUnit());
processType(SP->getType());
for (auto *Element : SP->getTemplateParams()) {
if (auto *TType = dyn_cast<DITemplateTypeParameter>(Element)) {
@@ -293,7 +313,7 @@ static MDNode *stripDebugLocFromLoopID(MDNode *N) {
bool llvm::stripDebugInfo(Function &F) {
bool Changed = false;
- if (F.getMetadata(LLVMContext::MD_dbg)) {
+ if (F.hasMetadata(LLVMContext::MD_dbg)) {
Changed = true;
F.setSubprogram(nullptr);
}
@@ -349,12 +369,7 @@ bool llvm::StripDebugInfo(Module &M) {
Changed |= stripDebugInfo(F);
for (auto &GV : M.globals()) {
- SmallVector<MDNode *, 1> MDs;
- GV.getMetadata(LLVMContext::MD_dbg, MDs);
- if (!MDs.empty()) {
- GV.eraseMetadata(LLVMContext::MD_dbg);
- Changed = true;
- }
+ Changed |= GV.eraseMetadata(LLVMContext::MD_dbg);
}
if (GVMaterializer *Materializer = M.getMaterializer())
@@ -548,7 +563,7 @@ void DebugTypeInfoRemoval::traverse(MDNode *N) {
// parts of the graph.
auto prune = [](MDNode *Parent, MDNode *Child) {
if (auto *MDS = dyn_cast<DISubprogram>(Parent))
- return Child == MDS->getVariables().get();
+ return Child == MDS->getRetainedNodes().get();
return false;
};
@@ -654,10 +669,10 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) {
SmallVector<MDNode *, 8> Ops;
for (MDNode *Op : NMD.operands())
Ops.push_back(remap(Op));
-
+
if (!Changed)
continue;
-
+
NMD.clearOperands();
for (auto *Op : Ops)
if (Op)
@@ -675,7 +690,8 @@ unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
void Instruction::applyMergedLocation(const DILocation *LocA,
const DILocation *LocB) {
- setDebugLoc(DILocation::getMergedLocation(LocA, LocB, this));
+ setDebugLoc(DILocation::getMergedLocation(LocA, LocB,
+ DILocation::WithGeneratedLocation));
}
//===----------------------------------------------------------------------===//
@@ -692,6 +708,18 @@ case LLVMDWARFSourceLanguage##NAME: return ID;
llvm_unreachable("Unhandled Tag");
}
+template <typename DIT> DIT *unwrapDI(LLVMMetadataRef Ref) {
+ return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
+}
+
+static DINode::DIFlags map_from_llvmDIFlags(LLVMDIFlags Flags) {
+ return static_cast<DINode::DIFlags>(Flags);
+}
+
+static LLVMDIFlags map_to_llvmDIFlags(DINode::DIFlags Flags) {
+ return static_cast<LLVMDIFlags>(Flags);
+}
+
unsigned LLVMDebugMetadataVersion() {
return DEBUG_METADATA_VERSION;
}
@@ -727,7 +755,7 @@ LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
unsigned RuntimeVer, const char *SplitName, size_t SplitNameLen,
LLVMDWARFEmissionKind Kind, unsigned DWOId, LLVMBool SplitDebugInlining,
LLVMBool DebugInfoForProfiling) {
- auto File = unwrap<DIFile>(FileRef);
+ auto File = unwrapDI<DIFile>(FileRef);
return wrap(unwrap(Builder)->createCompileUnit(
map_from_llvmDWARFsourcelanguage(Lang), File,
@@ -747,9 +775,581 @@ LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
}
LLVMMetadataRef
+LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope,
+ const char *Name, size_t NameLen,
+ const char *ConfigMacros, size_t ConfigMacrosLen,
+ const char *IncludePath, size_t IncludePathLen,
+ const char *ISysRoot, size_t ISysRootLen) {
+ return wrap(unwrap(Builder)->createModule(
+ unwrapDI<DIScope>(ParentScope), StringRef(Name, NameLen),
+ StringRef(ConfigMacros, ConfigMacrosLen),
+ StringRef(IncludePath, IncludePathLen),
+ StringRef(ISysRoot, ISysRootLen)));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef ParentScope,
+ const char *Name, size_t NameLen,
+ LLVMBool ExportSymbols) {
+ return wrap(unwrap(Builder)->createNameSpace(
+ unwrapDI<DIScope>(ParentScope), StringRef(Name, NameLen), ExportSymbols));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateFunction(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, const char *LinkageName, size_t LinkageNameLen,
+ LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
+ LLVMBool IsLocalToUnit, LLVMBool IsDefinition,
+ unsigned ScopeLine, LLVMDIFlags Flags, LLVMBool IsOptimized) {
+ return wrap(unwrap(Builder)->createFunction(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, {LinkageName, LinkageNameLen},
+ unwrapDI<DIFile>(File), LineNo, unwrapDI<DISubroutineType>(Ty),
+ IsLocalToUnit, IsDefinition, ScopeLine, map_from_llvmDIFlags(Flags),
+ IsOptimized, nullptr, nullptr, nullptr));
+}
+
+
+LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope,
+ LLVMMetadataRef File, unsigned Line, unsigned Col) {
+ return wrap(unwrap(Builder)->createLexicalBlock(unwrapDI<DIScope>(Scope),
+ unwrapDI<DIFile>(File),
+ Line, Col));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef File,
+ unsigned Discriminator) {
+ return wrap(unwrap(Builder)->createLexicalBlockFile(unwrapDI<DIScope>(Scope),
+ unwrapDI<DIFile>(File),
+ Discriminator));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromNamespace(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef NS,
+ LLVMMetadataRef File,
+ unsigned Line) {
+ return wrap(unwrap(Builder)->createImportedModule(unwrapDI<DIScope>(Scope),
+ unwrapDI<DINamespace>(NS),
+ unwrapDI<DIFile>(File),
+ Line));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromAlias(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef ImportedEntity,
+ LLVMMetadataRef File,
+ unsigned Line) {
+ return wrap(unwrap(Builder)->createImportedModule(
+ unwrapDI<DIScope>(Scope),
+ unwrapDI<DIImportedEntity>(ImportedEntity),
+ unwrapDI<DIFile>(File), Line));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedModuleFromModule(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef M,
+ LLVMMetadataRef File,
+ unsigned Line) {
+ return wrap(unwrap(Builder)->createImportedModule(unwrapDI<DIScope>(Scope),
+ unwrapDI<DIModule>(M),
+ unwrapDI<DIFile>(File),
+ Line));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateImportedDeclaration(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ LLVMMetadataRef Decl,
+ LLVMMetadataRef File,
+ unsigned Line,
+ const char *Name, size_t NameLen) {
+ return wrap(unwrap(Builder)->createImportedDeclaration(
+ unwrapDI<DIScope>(Scope),
+ unwrapDI<DINode>(Decl),
+ unwrapDI<DIFile>(File), Line, {Name, NameLen}));
+}
+
+LLVMMetadataRef
LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line,
unsigned Column, LLVMMetadataRef Scope,
LLVMMetadataRef InlinedAt) {
return wrap(DILocation::get(*unwrap(Ctx), Line, Column, unwrap(Scope),
unwrap(InlinedAt)));
}
+
+unsigned LLVMDILocationGetLine(LLVMMetadataRef Location) {
+ return unwrapDI<DILocation>(Location)->getLine();
+}
+
+unsigned LLVMDILocationGetColumn(LLVMMetadataRef Location) {
+ return unwrapDI<DILocation>(Location)->getColumn();
+}
+
+LLVMMetadataRef LLVMDILocationGetScope(LLVMMetadataRef Location) {
+ return wrap(unwrapDI<DILocation>(Location)->getScope());
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef *Elements,
+ unsigned NumElements, LLVMMetadataRef ClassTy) {
+auto Elts = unwrap(Builder)->getOrCreateArray({unwrap(Elements),
+ NumElements});
+return wrap(unwrap(Builder)->createEnumerationType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File),
+ LineNumber, SizeInBits, AlignInBits, Elts, unwrapDI<DIType>(ClassTy)));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateUnionType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef *Elements, unsigned NumElements, unsigned RunTimeLang,
+ const char *UniqueId, size_t UniqueIdLen) {
+ auto Elts = unwrap(Builder)->getOrCreateArray({unwrap(Elements),
+ NumElements});
+ return wrap(unwrap(Builder)->createUnionType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File),
+ LineNumber, SizeInBits, AlignInBits, map_from_llvmDIFlags(Flags),
+ Elts, RunTimeLang, {UniqueId, UniqueIdLen}));
+}
+
+
+LLVMMetadataRef
+LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size,
+ uint32_t AlignInBits, LLVMMetadataRef Ty,
+ LLVMMetadataRef *Subscripts,
+ unsigned NumSubscripts) {
+ auto Subs = unwrap(Builder)->getOrCreateArray({unwrap(Subscripts),
+ NumSubscripts});
+ return wrap(unwrap(Builder)->createArrayType(Size, AlignInBits,
+ unwrapDI<DIType>(Ty), Subs));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size,
+ uint32_t AlignInBits, LLVMMetadataRef Ty,
+ LLVMMetadataRef *Subscripts,
+ unsigned NumSubscripts) {
+ auto Subs = unwrap(Builder)->getOrCreateArray({unwrap(Subscripts),
+ NumSubscripts});
+ return wrap(unwrap(Builder)->createVectorType(Size, AlignInBits,
+ unwrapDI<DIType>(Ty), Subs));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name,
+ size_t NameLen, uint64_t SizeInBits,
+ LLVMDWARFTypeEncoding Encoding) {
+ return wrap(unwrap(Builder)->createBasicType({Name, NameLen},
+ SizeInBits, Encoding));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreatePointerType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
+ uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
+ const char *Name, size_t NameLen) {
+ return wrap(unwrap(Builder)->createPointerType(unwrapDI<DIType>(PointeeTy),
+ SizeInBits, AlignInBits,
+ AddressSpace, {Name, NameLen}));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateStructType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef DerivedFrom, LLVMMetadataRef *Elements,
+ unsigned NumElements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
+ const char *UniqueId, size_t UniqueIdLen) {
+ auto Elts = unwrap(Builder)->getOrCreateArray({unwrap(Elements),
+ NumElements});
+ return wrap(unwrap(Builder)->createStructType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File),
+ LineNumber, SizeInBits, AlignInBits, map_from_llvmDIFlags(Flags),
+ unwrapDI<DIType>(DerivedFrom), Elts, RunTimeLang,
+ unwrapDI<DIType>(VTableHolder), {UniqueId, UniqueIdLen}));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateMemberType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
+ uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef Ty) {
+ return wrap(unwrap(Builder)->createMemberType(unwrapDI<DIScope>(Scope),
+ {Name, NameLen}, unwrapDI<DIFile>(File), LineNo, SizeInBits, AlignInBits,
+ OffsetInBits, map_from_llvmDIFlags(Flags), unwrapDI<DIType>(Ty)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name,
+ size_t NameLen) {
+ return wrap(unwrap(Builder)->createUnspecifiedType({Name, NameLen}));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateStaticMemberType(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
+ LLVMMetadataRef Type, LLVMDIFlags Flags, LLVMValueRef ConstantVal,
+ uint32_t AlignInBits) {
+ return wrap(unwrap(Builder)->createStaticMemberType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen},
+ unwrapDI<DIFile>(File), LineNumber, unwrapDI<DIType>(Type),
+ map_from_llvmDIFlags(Flags), unwrap<Constant>(ConstantVal),
+ AlignInBits));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateObjCIVar(LLVMDIBuilderRef Builder,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ uint64_t SizeInBits, uint32_t AlignInBits,
+ uint64_t OffsetInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef Ty, LLVMMetadataRef PropertyNode) {
+ return wrap(unwrap(Builder)->createObjCIVar(
+ {Name, NameLen}, unwrapDI<DIFile>(File), LineNo,
+ SizeInBits, AlignInBits, OffsetInBits,
+ map_from_llvmDIFlags(Flags), unwrapDI<DIType>(Ty),
+ unwrapDI<MDNode>(PropertyNode)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateObjCProperty(LLVMDIBuilderRef Builder,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ const char *GetterName, size_t GetterNameLen,
+ const char *SetterName, size_t SetterNameLen,
+ unsigned PropertyAttributes,
+ LLVMMetadataRef Ty) {
+ return wrap(unwrap(Builder)->createObjCProperty(
+ {Name, NameLen}, unwrapDI<DIFile>(File), LineNo,
+ {GetterName, GetterNameLen}, {SetterName, SetterNameLen},
+ PropertyAttributes, unwrapDI<DIType>(Ty)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateObjectPointerType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Type) {
+ return wrap(unwrap(Builder)->createObjectPointerType(unwrapDI<DIType>(Type)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNo,
+ LLVMMetadataRef Scope) {
+ return wrap(unwrap(Builder)->createTypedef(
+ unwrapDI<DIType>(Type), {Name, NameLen},
+ unwrapDI<DIFile>(File), LineNo,
+ unwrapDI<DIScope>(Scope)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateInheritance(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Ty, LLVMMetadataRef BaseTy,
+ uint64_t BaseOffset, uint32_t VBPtrOffset,
+ LLVMDIFlags Flags) {
+ return wrap(unwrap(Builder)->createInheritance(
+ unwrapDI<DIType>(Ty), unwrapDI<DIType>(BaseTy),
+ BaseOffset, VBPtrOffset, map_from_llvmDIFlags(Flags)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateForwardDecl(
+ LLVMDIBuilderRef Builder, unsigned Tag, const char *Name,
+ size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line,
+ unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
+ const char *UniqueIdentifier, size_t UniqueIdentifierLen) {
+ return wrap(unwrap(Builder)->createForwardDecl(
+ Tag, {Name, NameLen}, unwrapDI<DIScope>(Scope),
+ unwrapDI<DIFile>(File), Line, RuntimeLang, SizeInBits,
+ AlignInBits, {UniqueIdentifier, UniqueIdentifierLen}));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateReplaceableCompositeType(
+ LLVMDIBuilderRef Builder, unsigned Tag, const char *Name,
+ size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line,
+ unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
+ LLVMDIFlags Flags, const char *UniqueIdentifier,
+ size_t UniqueIdentifierLen) {
+ return wrap(unwrap(Builder)->createReplaceableCompositeType(
+ Tag, {Name, NameLen}, unwrapDI<DIScope>(Scope),
+ unwrapDI<DIFile>(File), Line, RuntimeLang, SizeInBits,
+ AlignInBits, map_from_llvmDIFlags(Flags),
+ {UniqueIdentifier, UniqueIdentifierLen}));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag,
+ LLVMMetadataRef Type) {
+ return wrap(unwrap(Builder)->createQualifiedType(Tag,
+ unwrapDI<DIType>(Type)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateReferenceType(LLVMDIBuilderRef Builder, unsigned Tag,
+ LLVMMetadataRef Type) {
+ return wrap(unwrap(Builder)->createReferenceType(Tag,
+ unwrapDI<DIType>(Type)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateNullPtrType(LLVMDIBuilderRef Builder) {
+ return wrap(unwrap(Builder)->createNullPtrType());
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateMemberPointerType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef PointeeType,
+ LLVMMetadataRef ClassType,
+ uint64_t SizeInBits,
+ uint32_t AlignInBits,
+ LLVMDIFlags Flags) {
+ return wrap(unwrap(Builder)->createMemberPointerType(
+ unwrapDI<DIType>(PointeeType),
+ unwrapDI<DIType>(ClassType), AlignInBits, SizeInBits,
+ map_from_llvmDIFlags(Flags)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateBitFieldMemberType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t OffsetInBits,
+ uint64_t StorageOffsetInBits,
+ LLVMDIFlags Flags, LLVMMetadataRef Type) {
+ return wrap(unwrap(Builder)->createBitFieldMemberType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen},
+ unwrapDI<DIFile>(File), LineNumber,
+ SizeInBits, OffsetInBits, StorageOffsetInBits,
+ map_from_llvmDIFlags(Flags), unwrapDI<DIType>(Type)));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateClassType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope, const char *Name, size_t NameLen,
+ LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
+ uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags,
+ LLVMMetadataRef DerivedFrom,
+ LLVMMetadataRef *Elements, unsigned NumElements,
+ LLVMMetadataRef VTableHolder, LLVMMetadataRef TemplateParamsNode,
+ const char *UniqueIdentifier, size_t UniqueIdentifierLen) {
+ auto Elts = unwrap(Builder)->getOrCreateArray({unwrap(Elements),
+ NumElements});
+ return wrap(unwrap(Builder)->createClassType(
+ unwrapDI<DIScope>(Scope), {Name, NameLen},
+ unwrapDI<DIFile>(File), LineNumber,
+ SizeInBits, AlignInBits, OffsetInBits,
+ map_from_llvmDIFlags(Flags), unwrapDI<DIType>(DerivedFrom),
+ Elts, unwrapDI<DIType>(VTableHolder),
+ unwrapDI<MDNode>(TemplateParamsNode),
+ {UniqueIdentifier, UniqueIdentifierLen}));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateArtificialType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Type) {
+ return wrap(unwrap(Builder)->createArtificialType(unwrapDI<DIType>(Type)));
+}
+
+const char *LLVMDITypeGetName(LLVMMetadataRef DType, size_t *Length) {
+ StringRef Str = unwrap<DIType>(DType)->getName();
+ *Length = Str.size();
+ return Str.data();
+}
+
+uint64_t LLVMDITypeGetSizeInBits(LLVMMetadataRef DType) {
+ return unwrapDI<DIType>(DType)->getSizeInBits();
+}
+
+uint64_t LLVMDITypeGetOffsetInBits(LLVMMetadataRef DType) {
+ return unwrapDI<DIType>(DType)->getOffsetInBits();
+}
+
+uint32_t LLVMDITypeGetAlignInBits(LLVMMetadataRef DType) {
+ return unwrapDI<DIType>(DType)->getAlignInBits();
+}
+
+unsigned LLVMDITypeGetLine(LLVMMetadataRef DType) {
+ return unwrapDI<DIType>(DType)->getLine();
+}
+
+LLVMDIFlags LLVMDITypeGetFlags(LLVMMetadataRef DType) {
+ return map_to_llvmDIFlags(unwrapDI<DIType>(DType)->getFlags());
+}
+
+LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef *Types,
+ size_t Length) {
+ return wrap(
+ unwrap(Builder)->getOrCreateTypeArray({unwrap(Types), Length}).get());
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef File,
+ LLVMMetadataRef *ParameterTypes,
+ unsigned NumParameterTypes,
+ LLVMDIFlags Flags) {
+ auto Elts = unwrap(Builder)->getOrCreateTypeArray({unwrap(ParameterTypes),
+ NumParameterTypes});
+ return wrap(unwrap(Builder)->createSubroutineType(
+ Elts, map_from_llvmDIFlags(Flags)));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Builder,
+ int64_t *Addr, size_t Length) {
+ return wrap(unwrap(Builder)->createExpression(ArrayRef<int64_t>(Addr,
+ Length)));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder,
+ int64_t Value) {
+ return wrap(unwrap(Builder)->createConstantValueExpression(Value));
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ const char *Linkage, size_t LinkLen,
+ LLVMMetadataRef File,
+ unsigned LineNo,
+ LLVMMetadataRef Ty,
+ LLVMBool LocalToUnit,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef Decl,
+ uint32_t AlignInBits) {
+ return wrap(unwrap(Builder)->createGlobalVariableExpression(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, {Linkage, LinkLen},
+ unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty),
+ LocalToUnit, unwrap<DIExpression>(Expr),
+ unwrapDI<MDNode>(Decl), AlignInBits));
+}
+
+LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef Ctx, LLVMMetadataRef *Data,
+ size_t Count) {
+ return wrap(
+ MDTuple::getTemporary(*unwrap(Ctx), {unwrap(Data), Count}).release());
+}
+
+void LLVMDisposeTemporaryMDNode(LLVMMetadataRef TempNode) {
+ MDNode::deleteTemporary(unwrapDI<MDNode>(TempNode));
+}
+
+void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TargetMetadata,
+ LLVMMetadataRef Replacement) {
+ auto *Node = unwrapDI<MDNode>(TargetMetadata);
+ Node->replaceAllUsesWith(unwrap<Metadata>(Replacement));
+ MDNode::deleteTemporary(Node);
+}
+
+LLVMMetadataRef
+LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef Scope,
+ const char *Name, size_t NameLen,
+ const char *Linkage, size_t LnkLen,
+ LLVMMetadataRef File,
+ unsigned LineNo,
+ LLVMMetadataRef Ty,
+ LLVMBool LocalToUnit,
+ LLVMMetadataRef Decl,
+ uint32_t AlignInBits) {
+ return wrap(unwrap(Builder)->createTempGlobalVariableFwdDecl(
+ unwrapDI<DIScope>(Scope), {Name, NameLen}, {Linkage, LnkLen},
+ unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty),
+ LocalToUnit, unwrapDI<MDNode>(Decl), AlignInBits));
+}
+
+LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
+ LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) {
+ return wrap(unwrap(Builder)->insertDeclare(
+ unwrap(Storage), unwrap<DILocalVariable>(VarInfo),
+ unwrap<DIExpression>(Expr), unwrap<DILocation>(DL),
+ unwrap<Instruction>(Instr)));
+}
+
+LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
+ LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) {
+ return wrap(unwrap(Builder)->insertDeclare(
+ unwrap(Storage), unwrap<DILocalVariable>(VarInfo),
+ unwrap<DIExpression>(Expr), unwrap<DILocation>(DL),
+ unwrap(Block)));
+}
+
+LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder,
+ LLVMValueRef Val,
+ LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef DebugLoc,
+ LLVMValueRef Instr) {
+ return wrap(unwrap(Builder)->insertDbgValueIntrinsic(
+ unwrap(Val), unwrap<DILocalVariable>(VarInfo),
+ unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc),
+ unwrap<Instruction>(Instr)));
+}
+
+LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder,
+ LLVMValueRef Val,
+ LLVMMetadataRef VarInfo,
+ LLVMMetadataRef Expr,
+ LLVMMetadataRef DebugLoc,
+ LLVMBasicBlockRef Block) {
+ return wrap(unwrap(Builder)->insertDbgValueIntrinsic(
+ unwrap(Val), unwrap<DILocalVariable>(VarInfo),
+ unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc),
+ unwrap(Block)));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateAutoVariable(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty,
+ LLVMBool AlwaysPreserve, LLVMDIFlags Flags, uint32_t AlignInBits) {
+ return wrap(unwrap(Builder)->createAutoVariable(
+ unwrap<DIScope>(Scope), {Name, NameLen}, unwrap<DIFile>(File),
+ LineNo, unwrap<DIType>(Ty), AlwaysPreserve,
+ map_from_llvmDIFlags(Flags), AlignInBits));
+}
+
+LLVMMetadataRef LLVMDIBuilderCreateParameterVariable(
+ LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
+ size_t NameLen, unsigned ArgNo, LLVMMetadataRef File, unsigned LineNo,
+ LLVMMetadataRef Ty, LLVMBool AlwaysPreserve, LLVMDIFlags Flags) {
+ return wrap(unwrap(Builder)->createParameterVariable(
+ unwrap<DIScope>(Scope), Name, ArgNo, unwrap<DIFile>(File),
+ LineNo, unwrap<DIType>(Ty), AlwaysPreserve,
+ map_from_llvmDIFlags(Flags)));
+}
+
+LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder,
+ int64_t Lo, int64_t Count) {
+ return wrap(unwrap(Builder)->getOrCreateSubrange(Lo, Count));
+}
+
+LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder,
+ LLVMMetadataRef *Data,
+ size_t Length) {
+ Metadata **DataValue = unwrap(Data);
+ return wrap(unwrap(Builder)->getOrCreateArray({DataValue, Length}).get());
+}
+
+LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func) {
+ return wrap(unwrap<Function>(Func)->getSubprogram());
+}
+
+void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP) {
+ unwrap<Function>(Func)->setSubprogram(unwrap<DISubprogram>(SP));
+}
diff --git a/contrib/llvm/lib/IR/DebugInfoMetadata.cpp b/contrib/llvm/lib/IR/DebugInfoMetadata.cpp
index 75ddd47b2591..910e8c2fb74f 100644
--- a/contrib/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/contrib/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -68,16 +68,16 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
Storage, Context.pImpl->DILocations);
}
-const DILocation *
-DILocation::getMergedLocation(const DILocation *LocA, const DILocation *LocB,
- const Instruction *ForInst) {
+const DILocation *DILocation::getMergedLocation(const DILocation *LocA,
+ const DILocation *LocB,
+ bool GenerateLocation) {
if (!LocA || !LocB)
return nullptr;
if (LocA == LocB || !LocA->canDiscriminate(*LocB))
return LocA;
- if (!dyn_cast_or_null<CallInst>(ForInst))
+ if (!GenerateLocation)
return nullptr;
SmallPtrSet<DILocation *, 5> InlinedLocationsA;
@@ -249,17 +249,26 @@ void GenericDINode::recalculateHash() {
DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
StorageType Storage, bool ShouldCreate) {
- DEFINE_GETIMPL_LOOKUP(DISubrange, (Count, Lo));
- DEFINE_GETIMPL_STORE_NO_OPS(DISubrange, (Count, Lo));
+ auto *CountNode = ConstantAsMetadata::get(
+ ConstantInt::getSigned(Type::getInt64Ty(Context), Count));
+ return getImpl(Context, CountNode, Lo, Storage, ShouldCreate);
+}
+
+DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
+ int64_t Lo, StorageType Storage,
+ bool ShouldCreate) {
+ DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, Lo));
+ Metadata *Ops[] = { CountNode };
+ DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops);
}
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value,
- MDString *Name, StorageType Storage,
- bool ShouldCreate) {
+ bool IsUnsigned, MDString *Name,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, Name));
+ DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));
Metadata *Ops[] = {Name};
- DEFINE_GETIMPL_STORE(DIEnumerator, (Value), Ops);
+ DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);
}
DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
@@ -274,6 +283,19 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
Ops);
}
+Optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {
+ switch (getEncoding()) {
+ case dwarf::DW_ATE_signed:
+ case dwarf::DW_ATE_signed_char:
+ return Signedness::Signed;
+ case dwarf::DW_ATE_unsigned:
+ case dwarf::DW_ATE_unsigned_char:
+ return Signedness::Unsigned;
+ default:
+ return None;
+ }
+}
+
DIDerivedType *DIDerivedType::getImpl(
LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
@@ -296,17 +318,18 @@ DICompositeType *DICompositeType::getImpl(
unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
- Metadata *TemplateParams, MDString *Identifier, StorageType Storage,
- bool ShouldCreate) {
+ Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
DEFINE_GETIMPL_LOOKUP(
DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ VTableHolder, TemplateParams, Identifier, Discriminator));
Metadata *Ops[] = {File, Scope, Name, BaseType,
- Elements, VTableHolder, TemplateParams, Identifier};
+ Elements, VTableHolder, TemplateParams, Identifier,
+ Discriminator};
DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
AlignInBits, OffsetInBits, Flags),
Ops);
@@ -317,7 +340,7 @@ DICompositeType *DICompositeType::buildODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
- Metadata *VTableHolder, Metadata *TemplateParams) {
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -326,7 +349,7 @@ DICompositeType *DICompositeType::buildODRType(
return CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, &Identifier);
+ VTableHolder, TemplateParams, &Identifier, Discriminator);
// Only mutate CT if it's a forward declaration and the new operands aren't.
assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@@ -337,7 +360,8 @@ DICompositeType *DICompositeType::buildODRType(
CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType,
- Elements, VTableHolder, TemplateParams, &Identifier};
+ Elements, VTableHolder, TemplateParams, &Identifier,
+ Discriminator};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@@ -351,7 +375,7 @@ DICompositeType *DICompositeType::getODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
- Metadata *VTableHolder, Metadata *TemplateParams) {
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -360,7 +384,7 @@ DICompositeType *DICompositeType::getODRType(
CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
- TemplateParams, &Identifier);
+ TemplateParams, &Identifier, Discriminator);
return CT;
}
@@ -383,34 +407,39 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
// FIXME: Implement this string-enum correspondence with a .def file and macros,
// so that the association is explicit rather than implied.
-static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
- "CSK_None",
+static const char *ChecksumKindName[DIFile::CSK_Last] = {
"CSK_MD5",
"CSK_SHA1"
};
-DIFile::ChecksumKind DIFile::getChecksumKind(StringRef CSKindStr) {
- return StringSwitch<DIFile::ChecksumKind>(CSKindStr)
- .Case("CSK_MD5", DIFile::CSK_MD5)
- .Case("CSK_SHA1", DIFile::CSK_SHA1)
- .Default(DIFile::CSK_None);
+StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {
+ assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
+ // The first space was originally the CSK_None variant, which is now
+ // obsolete, but the space is still reserved in ChecksumKind, so we account
+ // for it here.
+ return ChecksumKindName[CSKind - 1];
}
-StringRef DIFile::getChecksumKindAsString() const {
- assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
- return ChecksumKindName[CSKind];
+Optional<DIFile::ChecksumKind> DIFile::getChecksumKind(StringRef CSKindStr) {
+ return StringSwitch<Optional<DIFile::ChecksumKind>>(CSKindStr)
+ .Case("CSK_MD5", DIFile::CSK_MD5)
+ .Case("CSK_SHA1", DIFile::CSK_SHA1)
+ .Default(None);
}
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
- MDString *Directory, DIFile::ChecksumKind CSKind,
- MDString *Checksum, StorageType Storage,
+ MDString *Directory,
+ Optional<DIFile::ChecksumInfo<MDString *>> CS,
+ Optional<MDString *> Source, StorageType Storage,
bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString");
- assert(isCanonical(Checksum) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CSKind, Checksum));
- Metadata *Ops[] = {Filename, Directory, Checksum};
- DEFINE_GETIMPL_STORE(DIFile, (CSKind), Ops);
+ assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
+ assert((!Source || isCanonical(*Source)) && "Expected canonical MDString");
+ DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
+ Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr,
+ Source.getValueOr(nullptr)};
+ DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
}
DICompileUnit *DICompileUnit::getImpl(
@@ -446,7 +475,7 @@ DICompileUnit::getEmissionKind(StringRef Str) {
.Default(None);
}
-const char *DICompileUnit::EmissionKindString(DebugEmissionKind EK) {
+const char *DICompileUnit::emissionKindString(DebugEmissionKind EK) {
switch (EK) {
case NoDebug: return "NoDebug";
case FullDebug: return "FullDebug";
@@ -473,7 +502,7 @@ DISubprogram *DISubprogram::getImpl(
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit,
- Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+ Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
assert(isCanonical(LinkageName) && "Expected canonical MDString");
@@ -481,10 +510,10 @@ DISubprogram *DISubprogram::getImpl(
DISubprogram, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, ScopeLine, ContainingType, Virtuality,
VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
- TemplateParams, Declaration, Variables, ThrownTypes));
+ TemplateParams, Declaration, RetainedNodes, ThrownTypes));
SmallVector<Metadata *, 11> Ops = {
- File, Scope, Name, LinkageName, Type, Unit,
- Declaration, Variables, ContainingType, TemplateParams, ThrownTypes};
+ File, Scope, Name, LinkageName, Type, Unit,
+ Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes};
if (!ThrownTypes) {
Ops.pop_back();
if (!TemplateParams) {
@@ -637,6 +666,18 @@ Optional<uint64_t> DIVariable::getSizeInBits() const {
return None;
}
+DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope,
+ MDString *Name, Metadata *File, unsigned Line,
+ StorageType Storage,
+ bool ShouldCreate) {
+ assert(Scope && "Expected scope");
+ assert(isCanonical(Name) && "Expected canonical MDString");
+ DEFINE_GETIMPL_LOOKUP(DILabel,
+ (Scope, Name, File, Line));
+ Metadata *Ops[] = {Scope, Name, File};
+ DEFINE_GETIMPL_STORE(DILabel, (Line), Ops);
+}
+
DIExpression *DIExpression::getImpl(LLVMContext &Context,
ArrayRef<uint64_t> Elements,
StorageType Storage, bool ShouldCreate) {
@@ -695,8 +736,19 @@ bool DIExpression::isValid() const {
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
case dwarf::DW_OP_mul:
+ case dwarf::DW_OP_div:
+ case dwarf::DW_OP_mod:
+ case dwarf::DW_OP_or:
+ case dwarf::DW_OP_and:
+ case dwarf::DW_OP_xor:
+ case dwarf::DW_OP_shl:
+ case dwarf::DW_OP_shr:
+ case dwarf::DW_OP_shra:
case dwarf::DW_OP_deref:
case dwarf::DW_OP_xderef:
+ case dwarf::DW_OP_lit0:
+ case dwarf::DW_OP_not:
+ case dwarf::DW_OP_dup:
break;
}
}
@@ -756,31 +808,94 @@ DIExpression *DIExpression::prepend(const DIExpression *Expr, bool DerefBefore,
SmallVector<uint64_t, 8> Ops;
if (DerefBefore)
Ops.push_back(dwarf::DW_OP_deref);
-
+
appendOffset(Ops, Offset);
if (DerefAfter)
Ops.push_back(dwarf::DW_OP_deref);
- if (Expr)
- for (auto Op : Expr->expr_ops()) {
- // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
- if (StackValue) {
- if (Op.getOp() == dwarf::DW_OP_stack_value)
- StackValue = false;
- else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
- Ops.push_back(dwarf::DW_OP_stack_value);
- StackValue = false;
- }
+ return prependOpcodes(Expr, Ops, StackValue);
+}
+
+DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
+ SmallVectorImpl<uint64_t> &Ops,
+ bool StackValue) {
+ assert(Expr && "Can't prepend ops to this expression");
+
+ // If there are no ops to prepend, do not even add the DW_OP_stack_value.
+ if (Ops.empty())
+ StackValue = false;
+ for (auto Op : Expr->expr_ops()) {
+ // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
+ if (StackValue) {
+ if (Op.getOp() == dwarf::DW_OP_stack_value)
+ StackValue = false;
+ else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
+ Ops.push_back(dwarf::DW_OP_stack_value);
+ StackValue = false;
}
- Ops.push_back(Op.getOp());
- for (unsigned I = 0; I < Op.getNumArgs(); ++I)
- Ops.push_back(Op.getArg(I));
}
+ Op.appendToVector(Ops);
+ }
if (StackValue)
Ops.push_back(dwarf::DW_OP_stack_value);
return DIExpression::get(Expr->getContext(), Ops);
}
+DIExpression *DIExpression::append(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops) {
+ assert(Expr && !Ops.empty() && "Can't append ops to this expression");
+
+ // Copy Expr's current op list.
+ SmallVector<uint64_t, 16> NewOps;
+ for (auto Op : Expr->expr_ops()) {
+ // Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.
+ if (Op.getOp() == dwarf::DW_OP_stack_value ||
+ Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
+ NewOps.append(Ops.begin(), Ops.end());
+
+ // Ensure that the new opcodes are only appended once.
+ Ops = None;
+ }
+ Op.appendToVector(NewOps);
+ }
+
+ NewOps.append(Ops.begin(), Ops.end());
+ return DIExpression::get(Expr->getContext(), NewOps);
+}
+
+DIExpression *DIExpression::appendToStack(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops) {
+ assert(Expr && !Ops.empty() && "Can't append ops to this expression");
+ assert(none_of(Ops,
+ [](uint64_t Op) {
+ return Op == dwarf::DW_OP_stack_value ||
+ Op == dwarf::DW_OP_LLVM_fragment;
+ }) &&
+ "Can't append this op");
+
+ // Append a DW_OP_deref after Expr's current op list if it's non-empty and
+ // has no DW_OP_stack_value.
+ //
+ // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?.
+ Optional<FragmentInfo> FI = Expr->getFragmentInfo();
+ unsigned DropUntilStackValue = FI.hasValue() ? 3 : 0;
+ ArrayRef<uint64_t> ExprOpsBeforeFragment =
+ Expr->getElements().drop_back(DropUntilStackValue);
+ bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) &&
+ (ExprOpsBeforeFragment.back() != dwarf::DW_OP_stack_value);
+ bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.empty();
+
+ // Append a DW_OP_deref after Expr's current op list if needed, then append
+ // the new ops, and finally ensure that a single DW_OP_stack_value is present.
+ SmallVector<uint64_t, 16> NewOps;
+ if (NeedsDeref)
+ NewOps.push_back(dwarf::DW_OP_deref);
+ NewOps.append(Ops.begin(), Ops.end());
+ if (NeedsStackValue)
+ NewOps.push_back(dwarf::DW_OP_stack_value);
+ return DIExpression::append(Expr, NewOps);
+}
+
Optional<DIExpression *> DIExpression::createFragmentExpression(
const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) {
SmallVector<uint64_t, 8> Ops;
@@ -800,17 +915,15 @@ Optional<DIExpression *> DIExpression::createFragmentExpression(
case dwarf::DW_OP_LLVM_fragment: {
// Make the new offset point into the existing fragment.
uint64_t FragmentOffsetInBits = Op.getArg(0);
- // Op.getArg(0) is FragmentOffsetInBits.
- // Op.getArg(1) is FragmentSizeInBits.
- assert((OffsetInBits + SizeInBits <= Op.getArg(0) + Op.getArg(1)) &&
+ uint64_t FragmentSizeInBits = Op.getArg(1);
+ (void)FragmentSizeInBits;
+ assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
"new fragment outside of original fragment");
OffsetInBits += FragmentOffsetInBits;
continue;
}
}
- Ops.push_back(Op.getOp());
- for (unsigned I = 0; I < Op.getNumArgs(); ++I)
- Ops.push_back(Op.getArg(I));
+ Op.appendToVector(Ops);
}
}
Ops.push_back(dwarf::DW_OP_LLVM_fragment);
@@ -883,4 +996,3 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
Metadata *Ops[] = { File, Elements };
DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);
}
-
diff --git a/contrib/llvm/lib/IR/DebugLoc.cpp b/contrib/llvm/lib/IR/DebugLoc.cpp
index 0a494119c3fe..36f3e179a2c0 100644
--- a/contrib/llvm/lib/IR/DebugLoc.cpp
+++ b/contrib/llvm/lib/IR/DebugLoc.cpp
@@ -9,6 +9,7 @@
#include "llvm/IR/DebugLoc.h"
#include "LLVMContextImpl.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfo.h"
using namespace llvm;
@@ -99,19 +100,7 @@ DebugLoc DebugLoc::appendInlinedAt(DebugLoc DL, DILocation *InlinedAt,
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void DebugLoc::dump() const {
- if (!Loc)
- return;
-
- dbgs() << getLine();
- if (getCol() != 0)
- dbgs() << ',' << getCol();
- if (DebugLoc InlinedAtDL = DebugLoc(getInlinedAt())) {
- dbgs() << " @ ";
- InlinedAtDL.dump();
- } else
- dbgs() << "\n";
-}
+LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); }
#endif
void DebugLoc::print(raw_ostream &OS) const {
diff --git a/contrib/llvm/lib/IR/DiagnosticHandler.cpp b/contrib/llvm/lib/IR/DiagnosticHandler.cpp
index fb1ac438ffbe..8f972785cf91 100644
--- a/contrib/llvm/lib/IR/DiagnosticHandler.cpp
+++ b/contrib/llvm/lib/IR/DiagnosticHandler.cpp
@@ -17,7 +17,7 @@ using namespace llvm;
namespace {
-/// \brief Regular expression corresponding to the value given in one of the
+/// Regular expression corresponding to the value given in one of the
/// -pass-remarks* command line flags. Passes whose name matches this regexp
/// will emit a diagnostic when calling the associated diagnostic function
/// (emitOptimizationRemark, emitOptimizationRemarkMissed or
diff --git a/contrib/llvm/lib/IR/DiagnosticInfo.cpp b/contrib/llvm/lib/IR/DiagnosticInfo.cpp
index 946df1a836ce..5ddb1196b072 100644
--- a/contrib/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/contrib/llvm/lib/IR/DiagnosticInfo.cpp
@@ -35,6 +35,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ScopedPrinter.h"
#include <atomic>
#include <cassert>
#include <memory>
@@ -144,7 +145,7 @@ DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Value *V
else if (auto *I = dyn_cast<Instruction>(V))
Loc = I->getDebugLoc();
- // Only include names that correspond to user variables. FIXME: we should use
+ // Only include names that correspond to user variables. FIXME: We should use
// debug info if available to get the name of the user variable.
if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
Val = GlobalValue::dropLLVMManglingEscape(V->getName());
@@ -167,6 +168,9 @@ DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
: Key(Key), Val(itostr(N)) {}
+DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
+ : Key(Key), Val(llvm::to_string(N)) {}
+
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
: Key(Key), Val(itostr(N)) {}
diff --git a/contrib/llvm/lib/IR/DomTreeUpdater.cpp b/contrib/llvm/lib/IR/DomTreeUpdater.cpp
new file mode 100644
index 000000000000..f035a86eddae
--- /dev/null
+++ b/contrib/llvm/lib/IR/DomTreeUpdater.cpp
@@ -0,0 +1,534 @@
+//===- DomTreeUpdater.cpp - DomTree/Post DomTree Updater --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DomTreeUpdater class, which provides a uniform way
+// to update dominator tree related data structures.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/DomTreeUpdater.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/Support/GenericDomTree.h"
+#include <algorithm>
+#include <functional>
+
+namespace llvm {
+
+bool DomTreeUpdater::isUpdateValid(
+ const DominatorTree::UpdateType Update) const {
+ const auto *From = Update.getFrom();
+ const auto *To = Update.getTo();
+ const auto Kind = Update.getKind();
+
+ // Discard updates by inspecting the current state of successors of From.
+ // Since isUpdateValid() must be called *after* the Terminator of From is
+ // altered we can determine if the update is unnecessary for batch updates
+ // or invalid for a single update.
+ const bool HasEdge = llvm::any_of(
+ successors(From), [To](const BasicBlock *B) { return B == To; });
+
+ // If the IR does not match the update,
+ // 1. In batch updates, this update is unnecessary.
+ // 2. When called by insertEdge*()/deleteEdge*(), this update is invalid.
+ // Edge does not exist in IR.
+ if (Kind == DominatorTree::Insert && !HasEdge)
+ return false;
+
+ // Edge exists in IR.
+ if (Kind == DominatorTree::Delete && HasEdge)
+ return false;
+
+ return true;
+}
+
+bool DomTreeUpdater::isSelfDominance(
+ const DominatorTree::UpdateType Update) const {
+ // Won't affect DomTree and PostDomTree.
+ return Update.getFrom() == Update.getTo();
+}
+
+bool DomTreeUpdater::applyLazyUpdate(DominatorTree::UpdateKind Kind,
+ BasicBlock *From, BasicBlock *To) {
+ assert((DT || PDT) &&
+ "Call applyLazyUpdate() when both DT and PDT are nullptrs.");
+ assert(Strategy == DomTreeUpdater::UpdateStrategy::Lazy &&
+ "Call applyLazyUpdate() with Eager strategy error");
+ // Analyze pending updates to determine if the update is unnecessary.
+ const DominatorTree::UpdateType Update = {Kind, From, To};
+ const DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
+ ? DominatorTree::Insert
+ : DominatorTree::Delete,
+ From, To};
+ // Only check duplicates in updates that are not applied by both trees.
+ auto I =
+ PendUpdates.begin() + std::max(PendDTUpdateIndex, PendPDTUpdateIndex);
+ const auto E = PendUpdates.end();
+
+ assert(I <= E && "Iterator out of range.");
+
+ for (; I != E; ++I) {
+ if (Update == *I)
+ return false; // Discard duplicate updates.
+
+ if (Invert == *I) {
+ // Update and Invert are both valid (equivalent to a no-op). Remove
+ // Invert from PendUpdates and discard the Update.
+ PendUpdates.erase(I);
+ return false;
+ }
+ }
+
+ PendUpdates.push_back(Update); // Save the valid update.
+ return true;
+}
+
+void DomTreeUpdater::applyDomTreeUpdates() {
+ // No pending DomTreeUpdates.
+ if (Strategy != UpdateStrategy::Lazy || !DT)
+ return;
+
+ // Only apply updates not are applied by DomTree.
+ if (hasPendingDomTreeUpdates()) {
+ const auto I = PendUpdates.begin() + PendDTUpdateIndex;
+ const auto E = PendUpdates.end();
+ assert(I < E && "Iterator range invalid; there should be DomTree updates.");
+ DT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
+ PendDTUpdateIndex = PendUpdates.size();
+ }
+}
+
+void DomTreeUpdater::flush() {
+ applyDomTreeUpdates();
+ applyPostDomTreeUpdates();
+ dropOutOfDateUpdates();
+}
+
+void DomTreeUpdater::applyPostDomTreeUpdates() {
+ // No pending PostDomTreeUpdates.
+ if (Strategy != UpdateStrategy::Lazy || !PDT)
+ return;
+
+ // Only apply updates not are applied by PostDomTree.
+ if (hasPendingPostDomTreeUpdates()) {
+ const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
+ const auto E = PendUpdates.end();
+ assert(I < E &&
+ "Iterator range invalid; there should be PostDomTree updates.");
+ PDT->applyUpdates(ArrayRef<DominatorTree::UpdateType>(I, E));
+ PendPDTUpdateIndex = PendUpdates.size();
+ }
+}
+
+void DomTreeUpdater::tryFlushDeletedBB() {
+ if (!hasPendingUpdates())
+ forceFlushDeletedBB();
+}
+
+bool DomTreeUpdater::forceFlushDeletedBB() {
+ if (DeletedBBs.empty())
+ return false;
+
+ for (auto *BB : DeletedBBs) {
+ // After calling deleteBB or callbackDeleteBB under Lazy UpdateStrategy,
+ // validateDeleteBB() removes all instructions of DelBB and adds an
+ // UnreachableInst as its terminator. So we check whether the BasicBlock to
+ // delete only has an UnreachableInst inside.
+ assert(BB->getInstList().size() == 1 &&
+ isa<UnreachableInst>(BB->getTerminator()) &&
+ "DelBB has been modified while awaiting deletion.");
+ BB->removeFromParent();
+ eraseDelBBNode(BB);
+ delete BB;
+ }
+ DeletedBBs.clear();
+ Callbacks.clear();
+ return true;
+}
+
+bool DomTreeUpdater::recalculate(Function &F) {
+ if (!DT && !PDT)
+ return false;
+
+ if (Strategy == UpdateStrategy::Eager) {
+ if (DT)
+ DT->recalculate(F);
+ if (PDT)
+ PDT->recalculate(F);
+ return true;
+ }
+
+ // Prevent forceFlushDeletedBB() from erasing DomTree or PostDomTree nodes.
+ IsRecalculatingDomTree = IsRecalculatingPostDomTree = true;
+
+ // Because all trees are going to be up-to-date after recalculation,
+ // flush awaiting deleted BasicBlocks.
+ if (forceFlushDeletedBB() || hasPendingUpdates()) {
+ if (DT)
+ DT->recalculate(F);
+ if (PDT)
+ PDT->recalculate(F);
+
+ // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
+ IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
+ PendDTUpdateIndex = PendPDTUpdateIndex = PendUpdates.size();
+ dropOutOfDateUpdates();
+ return true;
+ }
+
+ // Resume forceFlushDeletedBB() to erase DomTree or PostDomTree nodes.
+ IsRecalculatingDomTree = IsRecalculatingPostDomTree = false;
+ return false;
+}
+
+bool DomTreeUpdater::hasPendingUpdates() const {
+ return hasPendingDomTreeUpdates() || hasPendingPostDomTreeUpdates();
+}
+
+bool DomTreeUpdater::hasPendingDomTreeUpdates() const {
+ if (!DT)
+ return false;
+ return PendUpdates.size() != PendDTUpdateIndex;
+}
+
+bool DomTreeUpdater::hasPendingPostDomTreeUpdates() const {
+ if (!PDT)
+ return false;
+ return PendUpdates.size() != PendPDTUpdateIndex;
+}
+
+bool DomTreeUpdater::isBBPendingDeletion(llvm::BasicBlock *DelBB) const {
+ if (Strategy == UpdateStrategy::Eager || DeletedBBs.empty())
+ return false;
+ return DeletedBBs.count(DelBB) != 0;
+}
+
+// The DT and PDT require the nodes related to updates
+// are not deleted when update functions are called.
+// So BasicBlock deletions must be pended when the
+// UpdateStrategy is Lazy. When the UpdateStrategy is
+// Eager, the BasicBlock will be deleted immediately.
+void DomTreeUpdater::deleteBB(BasicBlock *DelBB) {
+ validateDeleteBB(DelBB);
+ if (Strategy == UpdateStrategy::Lazy) {
+ DeletedBBs.insert(DelBB);
+ return;
+ }
+
+ DelBB->removeFromParent();
+ eraseDelBBNode(DelBB);
+ delete DelBB;
+}
+
+void DomTreeUpdater::callbackDeleteBB(
+ BasicBlock *DelBB, std::function<void(BasicBlock *)> Callback) {
+ validateDeleteBB(DelBB);
+ if (Strategy == UpdateStrategy::Lazy) {
+ Callbacks.push_back(CallBackOnDeletion(DelBB, Callback));
+ DeletedBBs.insert(DelBB);
+ return;
+ }
+
+ DelBB->removeFromParent();
+ eraseDelBBNode(DelBB);
+ Callback(DelBB);
+ delete DelBB;
+}
+
+void DomTreeUpdater::eraseDelBBNode(BasicBlock *DelBB) {
+ if (DT && !IsRecalculatingDomTree)
+ if (DT->getNode(DelBB))
+ DT->eraseNode(DelBB);
+
+ if (PDT && !IsRecalculatingPostDomTree)
+ if (PDT->getNode(DelBB))
+ PDT->eraseNode(DelBB);
+}
+
+void DomTreeUpdater::validateDeleteBB(BasicBlock *DelBB) {
+ assert(DelBB && "Invalid push_back of nullptr DelBB.");
+ assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
+ // DelBB is unreachable and all its instructions are dead.
+ while (!DelBB->empty()) {
+ Instruction &I = DelBB->back();
+ // Replace used instructions with an arbitrary value (undef).
+ if (!I.use_empty())
+ I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
+ DelBB->getInstList().pop_back();
+ }
+ // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
+ // Child of Function F it must contain valid IR.
+ new UnreachableInst(DelBB->getContext(), DelBB);
+}
+
+void DomTreeUpdater::applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates,
+ bool ForceRemoveDuplicates) {
+ if (!DT && !PDT)
+ return;
+
+ if (Strategy == UpdateStrategy::Lazy || ForceRemoveDuplicates) {
+ SmallVector<DominatorTree::UpdateType, 8> Seen;
+ for (const auto U : Updates)
+ // For Lazy UpdateStrategy, avoid duplicates to applyLazyUpdate() to save
+ // on analysis.
+ if (llvm::none_of(
+ Seen,
+ [U](const DominatorTree::UpdateType S) { return S == U; }) &&
+ isUpdateValid(U) && !isSelfDominance(U)) {
+ Seen.push_back(U);
+ if (Strategy == UpdateStrategy::Lazy)
+ applyLazyUpdate(U.getKind(), U.getFrom(), U.getTo());
+ }
+ if (Strategy == UpdateStrategy::Lazy)
+ return;
+
+ if (DT)
+ DT->applyUpdates(Seen);
+ if (PDT)
+ PDT->applyUpdates(Seen);
+ return;
+ }
+
+ if (DT)
+ DT->applyUpdates(Updates);
+ if (PDT)
+ PDT->applyUpdates(Updates);
+}
+
+DominatorTree &DomTreeUpdater::getDomTree() {
+ assert(DT && "Invalid acquisition of a null DomTree");
+ applyDomTreeUpdates();
+ dropOutOfDateUpdates();
+ return *DT;
+}
+
+PostDominatorTree &DomTreeUpdater::getPostDomTree() {
+ assert(PDT && "Invalid acquisition of a null PostDomTree");
+ applyPostDomTreeUpdates();
+ dropOutOfDateUpdates();
+ return *PDT;
+}
+
+void DomTreeUpdater::insertEdge(BasicBlock *From, BasicBlock *To) {
+
+#ifndef NDEBUG
+ assert(isUpdateValid({DominatorTree::Insert, From, To}) &&
+ "Inserted edge does not appear in the CFG");
+#endif
+
+ if (!DT && !PDT)
+ return;
+
+ // Won't affect DomTree and PostDomTree; discard update.
+ if (From == To)
+ return;
+
+ if (Strategy == UpdateStrategy::Eager) {
+ if (DT)
+ DT->insertEdge(From, To);
+ if (PDT)
+ PDT->insertEdge(From, To);
+ return;
+ }
+
+ applyLazyUpdate(DominatorTree::Insert, From, To);
+}
+
+void DomTreeUpdater::insertEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
+ if (From == To)
+ return;
+
+ if (!DT && !PDT)
+ return;
+
+ if (!isUpdateValid({DominatorTree::Insert, From, To}))
+ return;
+
+ if (Strategy == UpdateStrategy::Eager) {
+ if (DT)
+ DT->insertEdge(From, To);
+ if (PDT)
+ PDT->insertEdge(From, To);
+ return;
+ }
+
+ applyLazyUpdate(DominatorTree::Insert, From, To);
+}
+
+void DomTreeUpdater::deleteEdge(BasicBlock *From, BasicBlock *To) {
+
+#ifndef NDEBUG
+ assert(isUpdateValid({DominatorTree::Delete, From, To}) &&
+ "Deleted edge still exists in the CFG!");
+#endif
+
+ if (!DT && !PDT)
+ return;
+
+ // Won't affect DomTree and PostDomTree; discard update.
+ if (From == To)
+ return;
+
+ if (Strategy == UpdateStrategy::Eager) {
+ if (DT)
+ DT->deleteEdge(From, To);
+ if (PDT)
+ PDT->deleteEdge(From, To);
+ return;
+ }
+
+ applyLazyUpdate(DominatorTree::Delete, From, To);
+}
+
+void DomTreeUpdater::deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To) {
+ if (From == To)
+ return;
+
+ if (!DT && !PDT)
+ return;
+
+ if (!isUpdateValid({DominatorTree::Delete, From, To}))
+ return;
+
+ if (Strategy == UpdateStrategy::Eager) {
+ if (DT)
+ DT->deleteEdge(From, To);
+ if (PDT)
+ PDT->deleteEdge(From, To);
+ return;
+ }
+
+ applyLazyUpdate(DominatorTree::Delete, From, To);
+}
+
+void DomTreeUpdater::dropOutOfDateUpdates() {
+ if (Strategy == DomTreeUpdater::UpdateStrategy::Eager)
+ return;
+
+ tryFlushDeletedBB();
+
+ // Drop all updates applied by both trees.
+ if (!DT)
+ PendDTUpdateIndex = PendUpdates.size();
+ if (!PDT)
+ PendPDTUpdateIndex = PendUpdates.size();
+
+ const size_t dropIndex = std::min(PendDTUpdateIndex, PendPDTUpdateIndex);
+ const auto B = PendUpdates.begin();
+ const auto E = PendUpdates.begin() + dropIndex;
+ assert(B <= E && "Iterator out of range.");
+ PendUpdates.erase(B, E);
+ // Calculate current index.
+ PendDTUpdateIndex -= dropIndex;
+ PendPDTUpdateIndex -= dropIndex;
+}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void DomTreeUpdater::dump() const {
+ raw_ostream &OS = llvm::dbgs();
+
+ OS << "Available Trees: ";
+ if (DT || PDT) {
+ if (DT)
+ OS << "DomTree ";
+ if (PDT)
+ OS << "PostDomTree ";
+ OS << "\n";
+ } else
+ OS << "None\n";
+
+ OS << "UpdateStrategy: ";
+ if (Strategy == UpdateStrategy::Eager) {
+ OS << "Eager\n";
+ return;
+ } else
+ OS << "Lazy\n";
+ int Index = 0;
+
+ auto printUpdates =
+ [&](ArrayRef<DominatorTree::UpdateType>::const_iterator begin,
+ ArrayRef<DominatorTree::UpdateType>::const_iterator end) {
+ if (begin == end)
+ OS << " None\n";
+ Index = 0;
+ for (auto It = begin, ItEnd = end; It != ItEnd; ++It) {
+ auto U = *It;
+ OS << " " << Index << " : ";
+ ++Index;
+ if (U.getKind() == DominatorTree::Insert)
+ OS << "Insert, ";
+ else
+ OS << "Delete, ";
+ BasicBlock *From = U.getFrom();
+ if (From) {
+ auto S = From->getName();
+ if (!From->hasName())
+ S = "(no name)";
+ OS << S << "(" << From << "), ";
+ } else {
+ OS << "(badref), ";
+ }
+ BasicBlock *To = U.getTo();
+ if (To) {
+ auto S = To->getName();
+ if (!To->hasName())
+ S = "(no_name)";
+ OS << S << "(" << To << ")\n";
+ } else {
+ OS << "(badref)\n";
+ }
+ }
+ };
+
+ if (DT) {
+ const auto I = PendUpdates.begin() + PendDTUpdateIndex;
+ assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
+ "Iterator out of range.");
+ OS << "Applied but not cleared DomTreeUpdates:\n";
+ printUpdates(PendUpdates.begin(), I);
+ OS << "Pending DomTreeUpdates:\n";
+ printUpdates(I, PendUpdates.end());
+ }
+
+ if (PDT) {
+ const auto I = PendUpdates.begin() + PendPDTUpdateIndex;
+ assert(PendUpdates.begin() <= I && I <= PendUpdates.end() &&
+ "Iterator out of range.");
+ OS << "Applied but not cleared PostDomTreeUpdates:\n";
+ printUpdates(PendUpdates.begin(), I);
+ OS << "Pending PostDomTreeUpdates:\n";
+ printUpdates(I, PendUpdates.end());
+ }
+
+ OS << "Pending DeletedBBs:\n";
+ Index = 0;
+ for (auto BB : DeletedBBs) {
+ OS << " " << Index << " : ";
+ ++Index;
+ if (BB->hasName())
+ OS << BB->getName() << "(";
+ else
+ OS << "(no_name)(";
+ OS << BB << ")\n";
+ }
+
+ OS << "Pending Callbacks:\n";
+ Index = 0;
+ for (auto BB : Callbacks) {
+ OS << " " << Index << " : ";
+ ++Index;
+ if (BB->hasName())
+ OS << BB->getName() << "(";
+ else
+ OS << "(no_name)(";
+ OS << BB << ")\n";
+ }
+}
+#endif
+} // namespace llvm
diff --git a/contrib/llvm/lib/IR/Dominators.cpp b/contrib/llvm/lib/IR/Dominators.cpp
index ad448a3f240c..d8971e05f476 100644
--- a/contrib/llvm/lib/IR/Dominators.cpp
+++ b/contrib/llvm/lib/IR/Dominators.cpp
@@ -17,7 +17,9 @@
#include "llvm/IR/Dominators.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/CFG.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/CommandLine.h"
@@ -27,16 +29,17 @@
#include <algorithm>
using namespace llvm;
-// Always verify dominfo if expensive checking is enabled.
-#ifdef EXPENSIVE_CHECKS
-bool llvm::VerifyDomInfo = true;
-#else
bool llvm::VerifyDomInfo = false;
-#endif
static cl::opt<bool, true>
VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), cl::Hidden,
cl::desc("Verify dominator info (time consuming)"));
+#ifdef EXPENSIVE_CHECKS
+static constexpr bool ExpensiveChecksEnabled = true;
+#else
+static constexpr bool ExpensiveChecksEnabled = false;
+#endif
+
bool BasicBlockEdge::isSingleEdge() const {
const TerminatorInst *TI = Start->getTerminator();
unsigned NumEdgesToEnd = 0;
@@ -87,9 +90,11 @@ template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBPostDomTree>(
DomTreeBuilder::BBPostDomTree &DT, DomTreeBuilder::BBUpdates);
template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBDomTree>(
- const DomTreeBuilder::BBDomTree &DT);
+ const DomTreeBuilder::BBDomTree &DT,
+ DomTreeBuilder::BBDomTree::VerificationLevel VL);
template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBPostDomTree>(
- const DomTreeBuilder::BBPostDomTree &DT);
+ const DomTreeBuilder::BBPostDomTree &DT,
+ DomTreeBuilder::BBPostDomTree::VerificationLevel VL);
bool DominatorTree::invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
@@ -302,31 +307,6 @@ bool DominatorTree::isReachableFromEntry(const Use &U) const {
return isReachableFromEntry(I->getParent());
}
-void DominatorTree::verifyDomTree() const {
- // Perform the expensive checks only when VerifyDomInfo is set.
- if (VerifyDomInfo && !verify()) {
- errs() << "\n~~~~~~~~~~~\n\t\tDomTree verification failed!\n~~~~~~~~~~~\n";
- print(errs());
- abort();
- }
-
- Function &F = *getRoot()->getParent();
-
- DominatorTree OtherDT;
- OtherDT.recalculate(F);
- if (compare(OtherDT)) {
- errs() << "DominatorTree for function " << F.getName()
- << " is not up to date!\nComputed:\n";
- print(errs());
- errs() << "\nActual:\n";
- OtherDT.print(errs());
- errs() << "\nCFG:\n";
- F.print(errs());
- errs().flush();
- abort();
- }
-}
-
//===----------------------------------------------------------------------===//
// DominatorTreeAnalysis and related pass implementations
//===----------------------------------------------------------------------===//
@@ -357,8 +337,9 @@ PreservedAnalyses DominatorTreePrinterPass::run(Function &F,
PreservedAnalyses DominatorTreeVerifierPass::run(Function &F,
FunctionAnalysisManager &AM) {
- AM.getResult<DominatorTreeAnalysis>(F).verifyDomTree();
-
+ auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
+ assert(DT.verify());
+ (void)DT;
return PreservedAnalyses::all();
}
@@ -381,11 +362,203 @@ bool DominatorTreeWrapperPass::runOnFunction(Function &F) {
}
void DominatorTreeWrapperPass::verifyAnalysis() const {
- if (VerifyDomInfo)
- DT.verifyDomTree();
+ if (VerifyDomInfo)
+ assert(DT.verify(DominatorTree::VerificationLevel::Full));
+ else if (ExpensiveChecksEnabled)
+ assert(DT.verify(DominatorTree::VerificationLevel::Basic));
}
void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
DT.print(OS);
}
+//===----------------------------------------------------------------------===//
+// DeferredDominance Implementation
+//===----------------------------------------------------------------------===//
+//
+// The implementation details of the DeferredDominance class which allows
+// one to queue updates to a DominatorTree.
+//
+//===----------------------------------------------------------------------===//
+
+/// Queues multiple updates and discards duplicates.
+void DeferredDominance::applyUpdates(
+ ArrayRef<DominatorTree::UpdateType> Updates) {
+ SmallVector<DominatorTree::UpdateType, 8> Seen;
+ for (auto U : Updates)
+ // Avoid duplicates to applyUpdate() to save on analysis.
+ if (std::none_of(Seen.begin(), Seen.end(),
+ [U](DominatorTree::UpdateType S) { return S == U; })) {
+ Seen.push_back(U);
+ applyUpdate(U.getKind(), U.getFrom(), U.getTo());
+ }
+}
+
+/// Helper method for a single edge insertion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single insertion needed to update
+/// Dominators.
+void DeferredDominance::insertEdge(BasicBlock *From, BasicBlock *To) {
+ applyUpdate(DominatorTree::Insert, From, To);
+}
+
+/// Helper method for a single edge deletion. It's almost always better
+/// to batch updates and call applyUpdates to quickly remove duplicate edges.
+/// This is best used when there is only a single deletion needed to update
+/// Dominators.
+void DeferredDominance::deleteEdge(BasicBlock *From, BasicBlock *To) {
+ applyUpdate(DominatorTree::Delete, From, To);
+}
+
+/// Delays the deletion of a basic block until a flush() event.
+void DeferredDominance::deleteBB(BasicBlock *DelBB) {
+ assert(DelBB && "Invalid push_back of nullptr DelBB.");
+ assert(pred_empty(DelBB) && "DelBB has one or more predecessors.");
+ // DelBB is unreachable and all its instructions are dead.
+ while (!DelBB->empty()) {
+ Instruction &I = DelBB->back();
+ // Replace used instructions with an arbitrary value (undef).
+ if (!I.use_empty())
+ I.replaceAllUsesWith(llvm::UndefValue::get(I.getType()));
+ DelBB->getInstList().pop_back();
+ }
+ // Make sure DelBB has a valid terminator instruction. As long as DelBB is a
+ // Child of Function F it must contain valid IR.
+ new UnreachableInst(DelBB->getContext(), DelBB);
+ DeletedBBs.insert(DelBB);
+}
+
+/// Returns true if DelBB is awaiting deletion at a flush() event.
+bool DeferredDominance::pendingDeletedBB(BasicBlock *DelBB) {
+ if (DeletedBBs.empty())
+ return false;
+ return DeletedBBs.count(DelBB) != 0;
+}
+
+/// Returns true if pending DT updates are queued for a flush() event.
+bool DeferredDominance::pending() { return !PendUpdates.empty(); }
+
+/// Flushes all pending updates and block deletions. Returns a
+/// correct DominatorTree reference to be used by the caller for analysis.
+DominatorTree &DeferredDominance::flush() {
+ // Updates to DT must happen before blocks are deleted below. Otherwise the
+ // DT traversal will encounter badref blocks and assert.
+ if (!PendUpdates.empty()) {
+ DT.applyUpdates(PendUpdates);
+ PendUpdates.clear();
+ }
+ flushDelBB();
+ return DT;
+}
+
+/// Drops all internal state and forces a (slow) recalculation of the
+/// DominatorTree based on the current state of the LLVM IR in F. This should
+/// only be used in corner cases such as the Entry block of F being deleted.
+void DeferredDominance::recalculate(Function &F) {
+ // flushDelBB must be flushed before the recalculation. The state of the IR
+ // must be consistent before the DT traversal algorithm determines the
+ // actual DT.
+ if (flushDelBB() || !PendUpdates.empty()) {
+ DT.recalculate(F);
+ PendUpdates.clear();
+ }
+}
+
+/// Debug method to help view the state of pending updates.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void DeferredDominance::dump() const {
+ raw_ostream &OS = llvm::dbgs();
+ OS << "PendUpdates:\n";
+ int I = 0;
+ for (auto U : PendUpdates) {
+ OS << " " << I << " : ";
+ ++I;
+ if (U.getKind() == DominatorTree::Insert)
+ OS << "Insert, ";
+ else
+ OS << "Delete, ";
+ BasicBlock *From = U.getFrom();
+ if (From) {
+ auto S = From->getName();
+ if (!From->hasName())
+ S = "(no name)";
+ OS << S << "(" << From << "), ";
+ } else {
+ OS << "(badref), ";
+ }
+ BasicBlock *To = U.getTo();
+ if (To) {
+ auto S = To->getName();
+ if (!To->hasName())
+ S = "(no_name)";
+ OS << S << "(" << To << ")\n";
+ } else {
+ OS << "(badref)\n";
+ }
+ }
+ OS << "DeletedBBs:\n";
+ I = 0;
+ for (auto BB : DeletedBBs) {
+ OS << " " << I << " : ";
+ ++I;
+ if (BB->hasName())
+ OS << BB->getName() << "(";
+ else
+ OS << "(no_name)(";
+ OS << BB << ")\n";
+ }
+}
+#endif
+
+/// Apply an update (Kind, From, To) to the internal queued updates. The
+/// update is only added when determined to be necessary. Checks for
+/// self-domination, unnecessary updates, duplicate requests, and balanced
+/// pairs of requests are all performed. Returns true if the update is
+/// queued and false if it is discarded.
+bool DeferredDominance::applyUpdate(DominatorTree::UpdateKind Kind,
+ BasicBlock *From, BasicBlock *To) {
+ if (From == To)
+ return false; // Cannot dominate self; discard update.
+
+ // Discard updates by inspecting the current state of successors of From.
+ // Since applyUpdate() must be called *after* the Terminator of From is
+ // altered we can determine if the update is unnecessary.
+ bool HasEdge = std::any_of(succ_begin(From), succ_end(From),
+ [To](BasicBlock *B) { return B == To; });
+ if (Kind == DominatorTree::Insert && !HasEdge)
+ return false; // Unnecessary Insert: edge does not exist in IR.
+ if (Kind == DominatorTree::Delete && HasEdge)
+ return false; // Unnecessary Delete: edge still exists in IR.
+
+ // Analyze pending updates to determine if the update is unnecessary.
+ DominatorTree::UpdateType Update = {Kind, From, To};
+ DominatorTree::UpdateType Invert = {Kind != DominatorTree::Insert
+ ? DominatorTree::Insert
+ : DominatorTree::Delete,
+ From, To};
+ for (auto I = PendUpdates.begin(), E = PendUpdates.end(); I != E; ++I) {
+ if (Update == *I)
+ return false; // Discard duplicate updates.
+ if (Invert == *I) {
+ // Update and Invert are both valid (equivalent to a no-op). Remove
+ // Invert from PendUpdates and discard the Update.
+ PendUpdates.erase(I);
+ return false;
+ }
+ }
+ PendUpdates.push_back(Update); // Save the valid update.
+ return true;
+}
+
+/// Performs all pending basic block deletions. We have to defer the deletion
+/// of these blocks until after the DominatorTree updates are applied. The
+/// internal workings of the DominatorTree code expect every update's From
+/// and To blocks to exist and to be a member of the same Function.
+bool DeferredDominance::flushDelBB() {
+ if (DeletedBBs.empty())
+ return false;
+ for (auto *BB : DeletedBBs)
+ BB->eraseFromParent();
+ DeletedBBs.clear();
+ return true;
+}
diff --git a/contrib/llvm/lib/IR/Function.cpp b/contrib/llvm/lib/IR/Function.cpp
index 7063f6f40a30..aba329b80508 100644
--- a/contrib/llvm/lib/IR/Function.cpp
+++ b/contrib/llvm/lib/IR/Function.cpp
@@ -21,7 +21,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
@@ -56,6 +55,7 @@
#include <string>
using namespace llvm;
+using ProfileCount = Function::ProfileCount;
// Explicit instantiations of SymbolTableListTraits since some of the methods
// are not in the public header file...
@@ -79,7 +79,8 @@ bool Argument::hasNonNullAttr() const {
if (getParent()->hasParamAttribute(getArgNo(), Attribute::NonNull))
return true;
else if (getDereferenceableBytes() > 0 &&
- getType()->getPointerAddressSpace() == 0)
+ !NullPointerIsDefined(getParent(),
+ getType()->getPointerAddressSpace()))
return true;
return false;
}
@@ -194,6 +195,14 @@ LLVMContext &Function::getContext() const {
return getType()->getContext();
}
+unsigned Function::getInstructionCount() {
+ unsigned NumInstrs = 0;
+ for (BasicBlock &BB : BasicBlocks)
+ NumInstrs += std::distance(BB.instructionsWithoutDebug().begin(),
+ BB.instructionsWithoutDebug().end());
+ return NumInstrs;
+}
+
void Function::removeFromParent() {
getParent()->getFunctionList().remove(getIterator());
}
@@ -479,13 +488,13 @@ void Function::copyAttributesFrom(const Function *Src) {
static const char * const IntrinsicNameTable[] = {
"not_intrinsic",
#define GET_INTRINSIC_NAME_TABLE
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_INTRINSIC_NAME_TABLE
};
/// Table of per-target intrinsic name tables.
#define GET_INTRINSIC_TARGET_DATA
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_INTRINSIC_TARGET_DATA
/// Find the segment of \c IntrinsicNameTable for intrinsics with the same
@@ -508,7 +517,7 @@ static ArrayRef<const char *> findTargetSubtable(StringRef Name) {
return makeArrayRef(&IntrinsicNameTable[1] + TI.Offset, TI.Count);
}
-/// \brief This does the actual lookup of an intrinsic ID which
+/// This does the actual lookup of an intrinsic ID which
/// matches the given function name.
Intrinsic::ID Function::lookupIntrinsicID(StringRef Name) {
ArrayRef<const char *> NameTable = findTargetSubtable(Name);
@@ -522,9 +531,11 @@ Intrinsic::ID Function::lookupIntrinsicID(StringRef Name) {
Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + Adjust);
// If the intrinsic is not overloaded, require an exact match. If it is
- // overloaded, require a prefix match.
- bool IsPrefixMatch = Name.size() > strlen(NameTable[Idx]);
- return IsPrefixMatch == isOverloaded(ID) ? ID : Intrinsic::not_intrinsic;
+ // overloaded, require either exact or prefix match.
+ const auto MatchSize = strlen(NameTable[Idx]);
+ assert(Name.size() >= MatchSize && "Expected either exact or prefix match");
+ bool IsExactMatch = Name.size() == MatchSize;
+ return IsExactMatch || isOverloaded(ID) ? ID : Intrinsic::not_intrinsic;
}
void Function::recalculateIntrinsicID() {
@@ -548,10 +559,7 @@ void Function::recalculateIntrinsicID() {
/// which can't be confused with it's prefix. This ensures we don't have
/// collisions between two unrelated function types. Otherwise, you might
/// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.)
-/// Manglings of integers, floats, and vectors ('i', 'f', and 'v' prefix in most
-/// cases) fall back to the MVT codepath, where they could be mangled to
-/// 'x86mmx', for example; matching on derived types is not sufficient to mangle
-/// everything.
+///
static std::string getMangledTypeStr(Type* Ty) {
std::string Result;
if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
@@ -579,11 +587,26 @@ static std::string getMangledTypeStr(Type* Ty) {
Result += "vararg";
// Ensure nested function types are distinguishable.
Result += "f";
- } else if (isa<VectorType>(Ty))
+ } else if (isa<VectorType>(Ty)) {
Result += "v" + utostr(Ty->getVectorNumElements()) +
getMangledTypeStr(Ty->getVectorElementType());
- else if (Ty)
- Result += EVT::getEVT(Ty).getEVTString();
+ } else if (Ty) {
+ switch (Ty->getTypeID()) {
+ default: llvm_unreachable("Unhandled type");
+ case Type::VoidTyID: Result += "isVoid"; break;
+ case Type::MetadataTyID: Result += "Metadata"; break;
+ case Type::HalfTyID: Result += "f16"; break;
+ case Type::FloatTyID: Result += "f32"; break;
+ case Type::DoubleTyID: Result += "f64"; break;
+ case Type::X86_FP80TyID: Result += "f80"; break;
+ case Type::FP128TyID: Result += "f128"; break;
+ case Type::PPC_FP128TyID: Result += "ppcf128"; break;
+ case Type::X86_MMXTyID: Result += "x86mmx"; break;
+ case Type::IntegerTyID:
+ Result += "i" + utostr(cast<IntegerType>(Ty)->getBitWidth());
+ break;
+ }
+ }
return Result;
}
@@ -651,7 +674,8 @@ enum IIT_Info {
IIT_V1024 = 37,
IIT_STRUCT6 = 38,
IIT_STRUCT7 = 39,
- IIT_STRUCT8 = 40
+ IIT_STRUCT8 = 40,
+ IIT_F128 = 41
};
static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
@@ -686,6 +710,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
case IIT_F64:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));
return;
+ case IIT_F128:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0));
+ return;
case IIT_I1:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));
return;
@@ -818,7 +845,7 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
}
#define GET_INTRINSIC_GENERATOR_GLOBAL
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_INTRINSIC_GENERATOR_GLOBAL
void Intrinsic::getIntrinsicInfoTableEntries(ID id,
@@ -870,6 +897,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
case IITDescriptor::Half: return Type::getHalfTy(Context);
case IITDescriptor::Float: return Type::getFloatTy(Context);
case IITDescriptor::Double: return Type::getDoubleTy(Context);
+ case IITDescriptor::Quad: return Type::getFP128Ty(Context);
case IITDescriptor::Integer:
return IntegerType::get(Context, D.Integer_Width);
@@ -955,7 +983,7 @@ FunctionType *Intrinsic::getType(LLVMContext &Context,
bool Intrinsic::isOverloaded(ID id) {
#define GET_INTRINSIC_OVERLOAD_TABLE
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_INTRINSIC_OVERLOAD_TABLE
}
@@ -973,7 +1001,7 @@ bool Intrinsic::isLeaf(ID id) {
/// This defines the "Intrinsic::getAttributes(ID id)" method.
#define GET_INTRINSIC_ATTRIBUTES
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_INTRINSIC_ATTRIBUTES
Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
@@ -986,12 +1014,12 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
// This defines the "Intrinsic::getIntrinsicForGCCBuiltin()" method.
#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
// This defines the "Intrinsic::getIntrinsicForMSBuiltin()" method.
#define GET_LLVM_INTRINSIC_FOR_MS_BUILTIN
-#include "llvm/IR/Intrinsics.gen"
+#include "llvm/IR/IntrinsicImpl.inc"
#undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN
bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
@@ -1012,6 +1040,7 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
case IITDescriptor::Half: return !Ty->isHalfTy();
case IITDescriptor::Float: return !Ty->isFloatTy();
case IITDescriptor::Double: return !Ty->isDoubleTy();
+ case IITDescriptor::Quad: return !Ty->isFP128Ty();
case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width);
case IITDescriptor::Vector: {
VectorType *VT = dyn_cast<VectorType>(Ty);
@@ -1320,26 +1349,43 @@ void Function::setValueSubclassDataBit(unsigned Bit, bool On) {
setValueSubclassData(getSubclassDataFromValue() & ~(1 << Bit));
}
-void Function::setEntryCount(uint64_t Count,
+void Function::setEntryCount(ProfileCount Count,
const DenseSet<GlobalValue::GUID> *S) {
+ assert(Count.hasValue());
+#if !defined(NDEBUG)
+ auto PrevCount = getEntryCount();
+ assert(!PrevCount.hasValue() || PrevCount.getType() == Count.getType());
+#endif
MDBuilder MDB(getContext());
- setMetadata(LLVMContext::MD_prof, MDB.createFunctionEntryCount(Count, S));
+ setMetadata(
+ LLVMContext::MD_prof,
+ MDB.createFunctionEntryCount(Count.getCount(), Count.isSynthetic(), S));
}
-Optional<uint64_t> Function::getEntryCount() const {
+void Function::setEntryCount(uint64_t Count, Function::ProfileCountType Type,
+ const DenseSet<GlobalValue::GUID> *Imports) {
+ setEntryCount(ProfileCount(Count, Type), Imports);
+}
+
+ProfileCount Function::getEntryCount() const {
MDNode *MD = getMetadata(LLVMContext::MD_prof);
if (MD && MD->getOperand(0))
- if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0)))
+ if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0))) {
if (MDS->getString().equals("function_entry_count")) {
ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(1));
uint64_t Count = CI->getValue().getZExtValue();
// A value of -1 is used for SamplePGO when there were no samples.
// Treat this the same as unknown.
if (Count == (uint64_t)-1)
- return None;
- return Count;
+ return ProfileCount::getInvalid();
+ return ProfileCount(Count, PCT_Real);
+ } else if (MDS->getString().equals("synthetic_function_entry_count")) {
+ ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(1));
+ uint64_t Count = CI->getValue().getZExtValue();
+ return ProfileCount(Count, PCT_Synthetic);
}
- return None;
+ }
+ return ProfileCount::getInvalid();
}
DenseSet<GlobalValue::GUID> Function::getImportGUIDs() const {
@@ -1362,11 +1408,27 @@ void Function::setSectionPrefix(StringRef Prefix) {
Optional<StringRef> Function::getSectionPrefix() const {
if (MDNode *MD = getMetadata(LLVMContext::MD_section_prefix)) {
- assert(dyn_cast<MDString>(MD->getOperand(0))
+ assert(cast<MDString>(MD->getOperand(0))
->getString()
.equals("function_section_prefix") &&
"Metadata not match");
- return dyn_cast<MDString>(MD->getOperand(1))->getString();
+ return cast<MDString>(MD->getOperand(1))->getString();
}
return None;
}
+
+bool Function::nullPointerIsDefined() const {
+ return getFnAttribute("null-pointer-is-valid")
+ .getValueAsString()
+ .equals("true");
+}
+
+bool llvm::NullPointerIsDefined(const Function *F, unsigned AS) {
+ if (F && F->nullPointerIsDefined())
+ return true;
+
+ if (AS != 0)
+ return true;
+
+ return false;
+}
diff --git a/contrib/llvm/lib/IR/Globals.cpp b/contrib/llvm/lib/IR/Globals.cpp
index da1b6c5e0c91..20b2334a626f 100644
--- a/contrib/llvm/lib/IR/Globals.cpp
+++ b/contrib/llvm/lib/IR/Globals.cpp
@@ -281,6 +281,24 @@ Optional<ConstantRange> GlobalValue::getAbsoluteSymbolRange() const {
return getConstantRangeFromMetadata(*MD);
}
+bool GlobalValue::canBeOmittedFromSymbolTable() const {
+ if (!hasLinkOnceODRLinkage())
+ return false;
+
+ // We assume that anyone who sets global unnamed_addr on a non-constant
+ // knows what they're doing.
+ if (hasGlobalUnnamedAddr())
+ return true;
+
+ // If it is a non constant variable, it needs to be uniqued across shared
+ // objects.
+ if (auto *Var = dyn_cast<GlobalVariable>(this))
+ if (!Var->isConstant())
+ return false;
+
+ return hasAtLeastLocalUnnamedAddr();
+}
+
//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/lib/IR/IRBuilder.cpp b/contrib/llvm/lib/IR/IRBuilder.cpp
index 027c0255bcec..405a56bfb31d 100644
--- a/contrib/llvm/lib/IR/IRBuilder.cpp
+++ b/contrib/llvm/lib/IR/IRBuilder.cpp
@@ -1,4 +1,4 @@
-//===---- IRBuilder.cpp - Builder for LLVM Instrs -------------------------===//
+//===- IRBuilder.cpp - Builder for LLVM Instrs ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,11 +13,27 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/IRBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/Statepoint.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
using namespace llvm;
/// CreateGlobalString - Make a new global variable with an initializer that
@@ -29,11 +45,10 @@ GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str,
unsigned AddressSpace) {
Constant *StrConstant = ConstantDataArray::getString(Context, Str);
Module &M = *BB->getParent()->getParent();
- GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(),
- true, GlobalValue::PrivateLinkage,
- StrConstant, Name, nullptr,
- GlobalVariable::NotThreadLocal,
- AddressSpace);
+ auto *GV = new GlobalVariable(M, StrConstant->getType(), true,
+ GlobalValue::PrivateLinkage, StrConstant, Name,
+ nullptr, GlobalVariable::NotThreadLocal,
+ AddressSpace);
GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return GV;
}
@@ -44,10 +59,10 @@ Type *IRBuilderBase::getCurrentFunctionReturnType() const {
}
Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) {
- PointerType *PT = cast<PointerType>(Ptr->getType());
+ auto *PT = cast<PointerType>(Ptr->getType());
if (PT->getElementType()->isIntegerTy(8))
return Ptr;
-
+
// Otherwise, we need to insert a bitcast.
PT = getInt8PtrTy(PT->getAddressSpace());
BitCastInst *BCI = new BitCastInst(Ptr, PT, "");
@@ -58,11 +73,14 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) {
static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops,
IRBuilderBase *Builder,
- const Twine& Name="") {
+ const Twine &Name = "",
+ Instruction *FMFSource = nullptr) {
CallInst *CI = CallInst::Create(Callee, Ops, Name);
+ if (FMFSource)
+ CI->copyFastMathFlags(FMFSource);
Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),CI);
Builder->SetInstDebugLocation(CI);
- return CI;
+ return CI;
}
static InvokeInst *createInvokeHelper(Value *Invokee, BasicBlock *NormalDest,
@@ -83,40 +101,81 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
MDNode *NoAliasTag) {
Ptr = getCastedInt8PtrValue(Ptr);
- Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) };
+ Value *Ops[] = {Ptr, Val, Size, getInt1(isVolatile)};
Type *Tys[] = { Ptr->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys);
-
+
+ CallInst *CI = createCallHelper(TheFn, Ops, this);
+
+ if (Align > 0)
+ cast<MemSetInst>(CI)->setDestAlignment(Align);
+
+ // Set the TBAA info if present.
+ if (TBAATag)
+ CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
+
+ if (ScopeTag)
+ CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
+
+ if (NoAliasTag)
+ CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
+
+ return CI;
+}
+
+CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemSet(
+ Value *Ptr, Value *Val, Value *Size, unsigned Align, uint32_t ElementSize,
+ MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) {
+ assert(Align >= ElementSize &&
+ "Pointer alignment must be at least element size.");
+
+ Ptr = getCastedInt8PtrValue(Ptr);
+ Value *Ops[] = {Ptr, Val, Size, getInt32(ElementSize)};
+ Type *Tys[] = {Ptr->getType(), Size->getType()};
+ Module *M = BB->getParent()->getParent();
+ Value *TheFn = Intrinsic::getDeclaration(
+ M, Intrinsic::memset_element_unordered_atomic, Tys);
+
CallInst *CI = createCallHelper(TheFn, Ops, this);
-
+
+ cast<AtomicMemSetInst>(CI)->setDestAlignment(Align);
+
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
if (ScopeTag)
CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
-
+
if (NoAliasTag)
CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
-
+
return CI;
}
CallInst *IRBuilderBase::
-CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag,
- MDNode *ScopeTag, MDNode *NoAliasTag) {
+CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
+ Value *Size, bool isVolatile, MDNode *TBAATag,
+ MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {
+ assert((DstAlign == 0 || isPowerOf2_32(DstAlign)) && "Must be 0 or a power of 2");
+ assert((SrcAlign == 0 || isPowerOf2_32(SrcAlign)) && "Must be 0 or a power of 2");
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
- Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) };
+ Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)};
Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys);
-
+
CallInst *CI = createCallHelper(TheFn, Ops, this);
-
+
+ auto* MCI = cast<MemCpyInst>(CI);
+ if (DstAlign > 0)
+ MCI->setDestAlignment(DstAlign);
+ if (SrcAlign > 0)
+ MCI->setSourceAlignment(SrcAlign);
+
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
@@ -124,14 +183,14 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
// Set the TBAA Struct info if present.
if (TBAAStructTag)
CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);
-
+
if (ScopeTag)
CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
-
+
if (NoAliasTag)
CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
-
- return CI;
+
+ return CI;
}
CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
@@ -154,8 +213,9 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
CallInst *CI = createCallHelper(TheFn, Ops, this);
// Set the alignment of the pointer args.
- CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign));
- CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign));
+ auto *AMCI = cast<AtomicMemCpyInst>(CI);
+ AMCI->setDestAlignment(DstAlign);
+ AMCI->setSourceAlignment(SrcAlign);
// Set the TBAA info if present.
if (TBAATag)
@@ -175,30 +235,78 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
}
CallInst *IRBuilderBase::
-CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
+CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign,
+ Value *Size, bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
MDNode *NoAliasTag) {
+ assert((DstAlign == 0 || isPowerOf2_32(DstAlign)) && "Must be 0 or a power of 2");
+ assert((SrcAlign == 0 || isPowerOf2_32(SrcAlign)) && "Must be 0 or a power of 2");
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
-
- Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) };
+
+ Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)};
Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() };
Module *M = BB->getParent()->getParent();
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys);
-
+
CallInst *CI = createCallHelper(TheFn, Ops, this);
-
+
+ auto *MMI = cast<MemMoveInst>(CI);
+ if (DstAlign > 0)
+ MMI->setDestAlignment(DstAlign);
+ if (SrcAlign > 0)
+ MMI->setSourceAlignment(SrcAlign);
+
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
-
+
if (ScopeTag)
CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
-
+
if (NoAliasTag)
CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
-
- return CI;
+
+ return CI;
+}
+
+CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemMove(
+ Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size,
+ uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag,
+ MDNode *ScopeTag, MDNode *NoAliasTag) {
+ assert(DstAlign >= ElementSize &&
+ "Pointer alignment must be at least element size");
+ assert(SrcAlign >= ElementSize &&
+ "Pointer alignment must be at least element size");
+ Dst = getCastedInt8PtrValue(Dst);
+ Src = getCastedInt8PtrValue(Src);
+
+ Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)};
+ Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()};
+ Module *M = BB->getParent()->getParent();
+ Value *TheFn = Intrinsic::getDeclaration(
+ M, Intrinsic::memmove_element_unordered_atomic, Tys);
+
+ CallInst *CI = createCallHelper(TheFn, Ops, this);
+
+ // Set the alignment of the pointer args.
+ CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign));
+ CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign));
+
+ // Set the TBAA info if present.
+ if (TBAATag)
+ CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
+
+ // Set the TBAA Struct info if present.
+ if (TBAAStructTag)
+ CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);
+
+ if (ScopeTag)
+ CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
+
+ if (NoAliasTag)
+ CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
+
+ return CI;
}
static CallInst *getReductionIntrinsic(IRBuilderBase *Builder, Intrinsic::ID ID,
@@ -351,7 +459,7 @@ CallInst *IRBuilderBase::CreateAssumption(Value *Cond) {
return createCallHelper(FnAssume, Ops, this);
}
-/// \brief Create a call to a Masked Load intrinsic.
+/// Create a call to a Masked Load intrinsic.
/// \p Ptr - base pointer for the load
/// \p Align - alignment of the source location
/// \p Mask - vector of booleans which indicates what vector lanes should
@@ -362,7 +470,7 @@ CallInst *IRBuilderBase::CreateAssumption(Value *Cond) {
CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align,
Value *Mask, Value *PassThru,
const Twine &Name) {
- PointerType *PtrTy = cast<PointerType>(Ptr->getType());
+ auto *PtrTy = cast<PointerType>(Ptr->getType());
Type *DataTy = PtrTy->getElementType();
assert(DataTy->isVectorTy() && "Ptr should point to a vector");
assert(Mask && "Mask should not be all-ones (null)");
@@ -374,7 +482,7 @@ CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align,
OverloadedTypes, Name);
}
-/// \brief Create a call to a Masked Store intrinsic.
+/// Create a call to a Masked Store intrinsic.
/// \p Val - data to be stored,
/// \p Ptr - base pointer for the store
/// \p Align - alignment of the destination location
@@ -382,7 +490,7 @@ CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align,
/// be accessed in memory
CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr,
unsigned Align, Value *Mask) {
- PointerType *PtrTy = cast<PointerType>(Ptr->getType());
+ auto *PtrTy = cast<PointerType>(Ptr->getType());
Type *DataTy = PtrTy->getElementType();
assert(DataTy->isVectorTy() && "Ptr should point to a vector");
assert(Mask && "Mask should not be all-ones (null)");
@@ -403,7 +511,7 @@ CallInst *IRBuilderBase::CreateMaskedIntrinsic(Intrinsic::ID Id,
return createCallHelper(TheFn, Ops, this, Name);
}
-/// \brief Create a call to a Masked Gather intrinsic.
+/// Create a call to a Masked Gather intrinsic.
/// \p Ptrs - vector of pointers for loading
/// \p Align - alignment for one element
/// \p Mask - vector of booleans which indicates what vector lanes should
@@ -435,7 +543,7 @@ CallInst *IRBuilderBase::CreateMaskedGather(Value *Ptrs, unsigned Align,
Name);
}
-/// \brief Create a call to a Masked Scatter intrinsic.
+/// Create a call to a Masked Scatter intrinsic.
/// \p Data - data to be stored,
/// \p Ptrs - the vector of pointers, where the \p Data elements should be
/// stored
@@ -496,7 +604,7 @@ static CallInst *CreateGCStatepointCallCommon(
ArrayRef<T1> TransitionArgs, ArrayRef<T2> DeoptArgs, ArrayRef<T3> GCArgs,
const Twine &Name) {
// Extract out the type of the callee.
- PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType());
+ auto *FuncPtrType = cast<PointerType>(ActualCallee->getType());
assert(isa<FunctionType>(FuncPtrType->getElementType()) &&
"actual callee must be a callable value");
@@ -507,7 +615,7 @@ static CallInst *CreateGCStatepointCallCommon(
Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint,
ArgTypes);
- std::vector<llvm::Value *> Args =
+ std::vector<Value *> Args =
getStatepointArgs(*Builder, ID, NumPatchBytes, ActualCallee, Flags,
CallArgs, TransitionArgs, DeoptArgs, GCArgs);
return createCallHelper(FnStatepoint, Args, Builder, Name);
@@ -547,7 +655,7 @@ static InvokeInst *CreateGCStatepointInvokeCommon(
uint32_t Flags, ArrayRef<T0> InvokeArgs, ArrayRef<T1> TransitionArgs,
ArrayRef<T2> DeoptArgs, ArrayRef<T3> GCArgs, const Twine &Name) {
// Extract out the type of the callee.
- PointerType *FuncPtrType = cast<PointerType>(ActualInvokee->getType());
+ auto *FuncPtrType = cast<PointerType>(ActualInvokee->getType());
assert(isa<FunctionType>(FuncPtrType->getElementType()) &&
"actual callee must be a callable value");
@@ -556,7 +664,7 @@ static InvokeInst *CreateGCStatepointInvokeCommon(
Function *FnStatepoint = Intrinsic::getDeclaration(
M, Intrinsic::experimental_gc_statepoint, {FuncPtrType});
- std::vector<llvm::Value *> Args =
+ std::vector<Value *> Args =
getStatepointArgs(*Builder, ID, NumPatchBytes, ActualInvokee, Flags,
InvokeArgs, TransitionArgs, DeoptArgs, GCArgs);
return createInvokeHelper(FnStatepoint, NormalDest, UnwindDest, Args, Builder,
@@ -625,7 +733,25 @@ CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint,
CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID,
Value *LHS, Value *RHS,
const Twine &Name) {
- Module *M = BB->getParent()->getParent();
- Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });
+ Module *M = BB->getModule();
+ Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() });
return createCallHelper(Fn, { LHS, RHS }, this, Name);
}
+
+CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
+ Instruction *FMFSource,
+ const Twine &Name) {
+ Module *M = BB->getModule();
+ Function *Fn = Intrinsic::getDeclaration(M, ID);
+ return createCallHelper(Fn, {}, this, Name);
+}
+
+CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
+ ArrayRef<Value *> Args,
+ Instruction *FMFSource,
+ const Twine &Name) {
+ assert(!Args.empty() && "Expected at least one argument to intrinsic");
+ Module *M = BB->getModule();
+ Function *Fn = Intrinsic::getDeclaration(M, ID, { Args.front()->getType() });
+ return createCallHelper(Fn, Args, this, Name, FMFSource);
+}
diff --git a/contrib/llvm/lib/IR/IRPrintingPasses.cpp b/contrib/llvm/lib/IR/IRPrintingPasses.cpp
index 3b32814bed5c..befe1d9ffb1c 100644
--- a/contrib/llvm/lib/IR/IRPrintingPasses.cpp
+++ b/contrib/llvm/lib/IR/IRPrintingPasses.cpp
@@ -127,13 +127,13 @@ public:
char PrintModulePassWrapper::ID = 0;
INITIALIZE_PASS(PrintModulePassWrapper, "print-module",
- "Print module to stderr", false, false)
+ "Print module to stderr", false, true)
char PrintFunctionPassWrapper::ID = 0;
INITIALIZE_PASS(PrintFunctionPassWrapper, "print-function",
- "Print function to stderr", false, false)
+ "Print function to stderr", false, true)
char PrintBasicBlockPass::ID = 0;
INITIALIZE_PASS(PrintBasicBlockPass, "print-bb", "Print BB to stderr", false,
- false)
+ true)
ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
const std::string &Banner,
@@ -150,3 +150,11 @@ BasicBlockPass *llvm::createPrintBasicBlockPass(llvm::raw_ostream &OS,
const std::string &Banner) {
return new PrintBasicBlockPass(OS, Banner);
}
+
+bool llvm::isIRPrintingPass(Pass *P) {
+ const char *PID = (const char*)P->getPassID();
+
+ return (PID == &PrintModulePassWrapper::ID)
+ || (PID == &PrintFunctionPassWrapper::ID)
+ || (PID == &PrintBasicBlockPass::ID);
+}
diff --git a/contrib/llvm/lib/IR/Instruction.cpp b/contrib/llvm/lib/IR/Instruction.cpp
index 5f2a6146ad81..508db9bcaf19 100644
--- a/contrib/llvm/lib/IR/Instruction.cpp
+++ b/contrib/llvm/lib/IR/Instruction.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Instruction.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
@@ -589,6 +590,18 @@ bool Instruction::mayThrow() const {
return isa<ResumeInst>(this);
}
+bool Instruction::isSafeToRemove() const {
+ return (!isa<CallInst>(this) || !this->mayHaveSideEffects()) &&
+ !isa<TerminatorInst>(this);
+}
+
+const Instruction *Instruction::getNextNonDebugInstruction() const {
+ for (const Instruction *I = getNextNode(); I; I = I->getNextNode())
+ if (!isa<DbgInfoIntrinsic>(I))
+ return I;
+ return nullptr;
+}
+
bool Instruction::isAssociative() const {
unsigned Opcode = getOpcode();
if (isAssociative(Opcode))
@@ -597,7 +610,8 @@ bool Instruction::isAssociative() const {
switch (Opcode) {
case FMul:
case FAdd:
- return cast<FPMathOperator>(this)->isFast();
+ return cast<FPMathOperator>(this)->hasAllowReassoc() &&
+ cast<FPMathOperator>(this)->hasNoSignedZeros();
default:
return false;
}
diff --git a/contrib/llvm/lib/IR/Instructions.cpp b/contrib/llvm/lib/IR/Instructions.cpp
index 490fcbce7439..e0ad0d1ea1f1 100644
--- a/contrib/llvm/lib/IR/Instructions.cpp
+++ b/contrib/llvm/lib/IR/Instructions.cpp
@@ -45,6 +45,22 @@
using namespace llvm;
//===----------------------------------------------------------------------===//
+// AllocaInst Class
+//===----------------------------------------------------------------------===//
+
+Optional<uint64_t>
+AllocaInst::getAllocationSizeInBits(const DataLayout &DL) const {
+ uint64_t Size = DL.getTypeAllocSizeInBits(getAllocatedType());
+ if (isArrayAllocation()) {
+ auto C = dyn_cast<ConstantInt>(getArraySize());
+ if (!C)
+ return None;
+ Size *= C->getZExtValue();
+ }
+ return Size;
+}
+
+//===----------------------------------------------------------------------===//
// CallSite Class
//===----------------------------------------------------------------------===//
@@ -319,31 +335,32 @@ void CallInst::init(Value *Func, const Twine &NameStr) {
setName(NameStr);
}
-CallInst::CallInst(Value *Func, const Twine &Name,
- Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 1,
- 1, InsertBefore) {
+CallInst::CallInst(Value *Func, const Twine &Name, Instruction *InsertBefore)
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1,
+ InsertBefore) {
init(Func, Name);
}
-CallInst::CallInst(Value *Func, const Twine &Name,
- BasicBlock *InsertAtEnd)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - 1,
- 1, InsertAtEnd) {
+CallInst::CallInst(Value *Func, const Twine &Name, BasicBlock *InsertAtEnd)
+ : CallBase<CallInst>(
+ cast<FunctionType>(
+ cast<PointerType>(Func->getType())->getElementType())
+ ->getReturnType(),
+ Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1, InsertAtEnd) {
init(Func, Name);
}
CallInst::CallInst(const CallInst &CI)
- : Instruction(CI.getType(), Instruction::Call,
- OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
- CI.getNumOperands()),
- Attrs(CI.Attrs), FTy(CI.FTy) {
+ : CallBase<CallInst>(CI.Attrs, CI.FTy, CI.getType(), Instruction::Call,
+ OperandTraits<CallBase<CallInst>>::op_end(this) -
+ CI.getNumOperands(),
+ CI.getNumOperands()) {
setTailCallKind(CI.getTailCallKind());
setCallingConv(CI.getCallingConv());
@@ -367,125 +384,14 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
return NewCI;
}
-Value *CallInst::getReturnedArgOperand() const {
- unsigned Index;
-
- if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
- return getArgOperand(Index - AttributeList::FirstArgIndex);
- if (const Function *F = getCalledFunction())
- if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
- Index)
- return getArgOperand(Index - AttributeList::FirstArgIndex);
-
- return nullptr;
-}
-
-void CallInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-
-void CallInst::addAttribute(unsigned i, Attribute Attr) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addAttribute(getContext(), i, Attr);
- setAttributes(PAL);
-}
-
-void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- assert(ArgNo < getNumArgOperands() && "Out of bounds");
- AttributeList PAL = getAttributes();
- PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
- setAttributes(PAL);
-}
-
-void CallInst::addParamAttr(unsigned ArgNo, Attribute Attr) {
- assert(ArgNo < getNumArgOperands() && "Out of bounds");
- AttributeList PAL = getAttributes();
- PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr);
- setAttributes(PAL);
-}
-
-void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.removeAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-
-void CallInst::removeAttribute(unsigned i, StringRef Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.removeAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- assert(ArgNo < getNumArgOperands() && "Out of bounds");
- AttributeList PAL = getAttributes();
- PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
- setAttributes(PAL);
-}
-void CallInst::removeParamAttr(unsigned ArgNo, StringRef Kind) {
- assert(ArgNo < getNumArgOperands() && "Out of bounds");
- AttributeList PAL = getAttributes();
- PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
- setAttributes(PAL);
-}
-void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
- setAttributes(PAL);
-}
-void CallInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
- setAttributes(PAL);
-}
-bool CallInst::hasRetAttr(Attribute::AttrKind Kind) const {
- if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind))
- return true;
- // Look at the callee, if available.
- if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind);
- return false;
-}
-bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
- assert(i < getNumArgOperands() && "Param index out of bounds!");
- if (Attrs.hasParamAttribute(i, Kind))
- return true;
- if (const Function *F = getCalledFunction())
- return F->getAttributes().hasParamAttribute(i, Kind);
- return false;
-}
-
-bool CallInst::dataOperandHasImpliedAttr(unsigned i,
- Attribute::AttrKind Kind) const {
- // There are getNumOperands() - 1 data operands. The last operand is the
- // callee.
- assert(i < getNumOperands() && "Data operand index out of bounds!");
-
- // The attribute A can either be directly specified, if the operand in
- // question is a call argument; or be indirectly implied by the kind of its
- // containing operand bundle, if the operand is a bundle operand.
-
- if (i == AttributeList::ReturnIndex)
- return hasRetAttr(Kind);
-
- // FIXME: Avoid these i - 1 calculations and update the API to use zero-based
- // indices.
- if (i < (getNumArgOperands() + 1))
- return paramHasAttr(i - 1, Kind);
-
- assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
- "Must be either a call argument or an operand bundle!");
- return bundleOperandHasAttr(i - 1, Kind);
-}
/// IsConstantOne - Return true only if val is constant int 1
static bool IsConstantOne(Value *val) {
@@ -721,11 +627,10 @@ void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal,
}
InvokeInst::InvokeInst(const InvokeInst &II)
- : TerminatorInst(II.getType(), Instruction::Invoke,
- OperandTraits<InvokeInst>::op_end(this) -
- II.getNumOperands(),
- II.getNumOperands()),
- Attrs(II.Attrs), FTy(II.FTy) {
+ : CallBase<InvokeInst>(II.Attrs, II.FTy, II.getType(), Instruction::Invoke,
+ OperandTraits<CallBase<InvokeInst>>::op_end(this) -
+ II.getNumOperands(),
+ II.getNumOperands()) {
setCallingConv(II.getCallingConv());
std::copy(II.op_begin(), II.op_end(), op_begin());
std::copy(II.bundle_op_info_begin(), II.bundle_op_info_end(),
@@ -747,109 +652,6 @@ InvokeInst *InvokeInst::Create(InvokeInst *II, ArrayRef<OperandBundleDef> OpB,
return NewII;
}
-Value *InvokeInst::getReturnedArgOperand() const {
- unsigned Index;
-
- if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
- return getArgOperand(Index - AttributeList::FirstArgIndex);
- if (const Function *F = getCalledFunction())
- if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
- Index)
- return getArgOperand(Index - AttributeList::FirstArgIndex);
-
- return nullptr;
-}
-
-bool InvokeInst::hasRetAttr(Attribute::AttrKind Kind) const {
- if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind))
- return true;
-
- // Look at the callee, if available.
- if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind);
- return false;
-}
-
-bool InvokeInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
- assert(i < getNumArgOperands() && "Param index out of bounds!");
-
- if (Attrs.hasParamAttribute(i, Kind))
- return true;
- if (const Function *F = getCalledFunction())
- return F->getAttributes().hasParamAttribute(i, Kind);
- return false;
-}
-
-bool InvokeInst::dataOperandHasImpliedAttr(unsigned i,
- Attribute::AttrKind Kind) const {
- // There are getNumOperands() - 3 data operands. The last three operands are
- // the callee and the two successor basic blocks.
- assert(i < (getNumOperands() - 2) && "Data operand index out of bounds!");
-
- // The attribute A can either be directly specified, if the operand in
- // question is an invoke argument; or be indirectly implied by the kind of its
- // containing operand bundle, if the operand is a bundle operand.
-
- if (i == AttributeList::ReturnIndex)
- return hasRetAttr(Kind);
-
- // FIXME: Avoid these i - 1 calculations and update the API to use zero-based
- // indices.
- if (i < (getNumArgOperands() + 1))
- return paramHasAttr(i - 1, Kind);
-
- assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
- "Must be either an invoke argument or an operand bundle!");
- return bundleOperandHasAttr(i - 1, Kind);
-}
-
-void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-
-void InvokeInst::addAttribute(unsigned i, Attribute Attr) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addAttribute(getContext(), i, Attr);
- setAttributes(PAL);
-}
-
-void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
- setAttributes(PAL);
-}
-
-void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.removeAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-
-void InvokeInst::removeAttribute(unsigned i, StringRef Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.removeAttribute(getContext(), i, Kind);
- setAttributes(PAL);
-}
-
-void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
- AttributeList PAL = getAttributes();
- PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
- setAttributes(PAL);
-}
-
-void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
- setAttributes(PAL);
-}
-
-void InvokeInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
- AttributeList PAL = getAttributes();
- PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
- setAttributes(PAL);
-}
LandingPadInst *InvokeInst::getLandingPadInst() const {
return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
@@ -1872,7 +1674,7 @@ bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
return false;
}
-int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
+int ShuffleVectorInst::getMaskValue(const Constant *Mask, unsigned i) {
assert(i < Mask->getType()->getVectorNumElements() && "Index out of range");
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask))
return CDS->getElementAsInteger(i);
@@ -1882,7 +1684,7 @@ int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
return cast<ConstantInt>(C)->getZExtValue();
}
-void ShuffleVectorInst::getShuffleMask(Constant *Mask,
+void ShuffleVectorInst::getShuffleMask(const Constant *Mask,
SmallVectorImpl<int> &Result) {
unsigned NumElts = Mask->getType()->getVectorNumElements();
@@ -1898,6 +1700,108 @@ void ShuffleVectorInst::getShuffleMask(Constant *Mask,
}
}
+bool ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) {
+ assert(!Mask.empty() && "Shuffle mask must contain elements");
+ bool UsesLHS = false;
+ bool UsesRHS = false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ assert(Mask[i] >= 0 && Mask[i] < (NumElts * 2) &&
+ "Out-of-bounds shuffle mask element");
+ UsesLHS |= (Mask[i] < NumElts);
+ UsesRHS |= (Mask[i] >= NumElts);
+ if (UsesLHS && UsesRHS)
+ return false;
+ }
+ assert((UsesLHS ^ UsesRHS) && "Should have selected from exactly 1 source");
+ return true;
+}
+
+bool ShuffleVectorInst::isIdentityMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != i && Mask[i] != (NumElts + i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isReverseMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != (NumElts - 1 - i) && Mask[i] != (NumElts + NumElts - 1 - i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isZeroEltSplatMask(ArrayRef<int> Mask) {
+ if (!isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != 0 && Mask[i] != NumElts)
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isSelectMask(ArrayRef<int> Mask) {
+ // Select is differentiated from identity. It requires using both sources.
+ if (isSingleSourceMask(Mask))
+ return false;
+ for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) {
+ if (Mask[i] == -1)
+ continue;
+ if (Mask[i] != i && Mask[i] != (NumElts + i))
+ return false;
+ }
+ return true;
+}
+
+bool ShuffleVectorInst::isTransposeMask(ArrayRef<int> Mask) {
+ // Example masks that will return true:
+ // v1 = <a, b, c, d>
+ // v2 = <e, f, g, h>
+ // trn1 = shufflevector v1, v2 <0, 4, 2, 6> = <a, e, c, g>
+ // trn2 = shufflevector v1, v2 <1, 5, 3, 7> = <b, f, d, h>
+
+ // 1. The number of elements in the mask must be a power-of-2 and at least 2.
+ int NumElts = Mask.size();
+ if (NumElts < 2 || !isPowerOf2_32(NumElts))
+ return false;
+
+ // 2. The first element of the mask must be either a 0 or a 1.
+ if (Mask[0] != 0 && Mask[0] != 1)
+ return false;
+
+ // 3. The difference between the first 2 elements must be equal to the
+ // number of elements in the mask.
+ if ((Mask[1] - Mask[0]) != NumElts)
+ return false;
+
+ // 4. The difference between consecutive even-numbered and odd-numbered
+ // elements must be equal to 2.
+ for (int i = 2; i < NumElts; ++i) {
+ int MaskEltVal = Mask[i];
+ if (MaskEltVal == -1)
+ return false;
+ int MaskEltPrevVal = Mask[i - 2];
+ if (MaskEltVal - MaskEltPrevVal != 2)
+ return false;
+ }
+ return true;
+}
+
+
//===----------------------------------------------------------------------===//
// InsertValueInst Class
//===----------------------------------------------------------------------===//
@@ -2295,7 +2199,7 @@ bool CastInst::isLosslessCast() const {
/// # bitcast i32* %x to i8*
/// # bitcast <2 x i32> %x to <4 x i16>
/// # ptrtoint i32* %x to i32 ; on 32-bit plaforms only
-/// @brief Determine if the described cast is a no-op.
+/// Determine if the described cast is a no-op.
bool CastInst::isNoopCast(Instruction::CastOps Opcode,
Type *SrcTy,
Type *DestTy,
@@ -2387,7 +2291,7 @@ unsigned CastInst::isEliminableCastPair(
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc |
- { 99,99,99, 2, 2,99,99,10, 2,99,99, 4, 0}, // FPExt |
+ { 99,99,99, 2, 2,99,99, 8, 2,99,99, 4, 0}, // FPExt |
{ 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt |
{ 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr |
{ 5, 5, 5, 6, 6, 5, 5, 6, 6,16, 5, 1,14}, // BitCast |
@@ -2481,12 +2385,6 @@ unsigned CastInst::isEliminableCastPair(
case 9:
// zext, sext -> zext, because sext can't sign extend after zext
return Instruction::ZExt;
- case 10:
- // fpext followed by ftrunc is allowed if the bit size returned to is
- // the same as the original, in which case its just a bitcast
- if (SrcTy == DstTy)
- return Instruction::BitCast;
- return 0; // If the types are not the same we can't eliminate it.
case 11: {
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
if (!MidIntPtrTy)
@@ -2669,7 +2567,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertAtEnd);
}
-/// @brief Create a BitCast or a PtrToInt cast instruction
+/// Create a BitCast or a PtrToInt cast instruction
CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
@@ -3437,6 +3335,29 @@ ICmpInst::Predicate ICmpInst::getUnsignedPredicate(Predicate pred) {
}
}
+CmpInst::Predicate CmpInst::getFlippedStrictnessPredicate(Predicate pred) {
+ switch (pred) {
+ default: llvm_unreachable("Unknown or unsupported cmp predicate!");
+ case ICMP_SGT: return ICMP_SGE;
+ case ICMP_SLT: return ICMP_SLE;
+ case ICMP_SGE: return ICMP_SGT;
+ case ICMP_SLE: return ICMP_SLT;
+ case ICMP_UGT: return ICMP_UGE;
+ case ICMP_ULT: return ICMP_ULE;
+ case ICMP_UGE: return ICMP_UGT;
+ case ICMP_ULE: return ICMP_ULT;
+
+ case FCMP_OGT: return FCMP_OGE;
+ case FCMP_OLT: return FCMP_OLE;
+ case FCMP_OGE: return FCMP_OGT;
+ case FCMP_OLE: return FCMP_OLT;
+ case FCMP_UGT: return FCMP_UGE;
+ case FCMP_ULT: return FCMP_ULE;
+ case FCMP_UGE: return FCMP_UGT;
+ case FCMP_ULE: return FCMP_ULT;
+ }
+}
+
CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown cmp predicate!");
@@ -3467,6 +3388,20 @@ CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
}
}
+CmpInst::Predicate CmpInst::getNonStrictPredicate(Predicate pred) {
+ switch (pred) {
+ case ICMP_SGT: return ICMP_SGE;
+ case ICMP_SLT: return ICMP_SLE;
+ case ICMP_UGT: return ICMP_UGE;
+ case ICMP_ULT: return ICMP_ULE;
+ case FCMP_OGT: return FCMP_OGE;
+ case FCMP_OLT: return FCMP_OLE;
+ case FCMP_UGT: return FCMP_UGE;
+ case FCMP_ULT: return FCMP_ULE;
+ default: return pred;
+ }
+}
+
CmpInst::Predicate CmpInst::getSignedPredicate(Predicate pred) {
assert(CmpInst::isUnsigned(pred) && "Call only with signed predicates!");
diff --git a/contrib/llvm/lib/IR/IntrinsicInst.cpp b/contrib/llvm/lib/IR/IntrinsicInst.cpp
index 67bd5b69bb0f..787889934d82 100644
--- a/contrib/llvm/lib/IR/IntrinsicInst.cpp
+++ b/contrib/llvm/lib/IR/IntrinsicInst.cpp
@@ -24,6 +24,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
@@ -44,10 +45,19 @@ Value *DbgInfoIntrinsic::getVariableLocation(bool AllowNullOp) const {
return V->getValue();
// When the value goes to null, it gets replaced by an empty MDNode.
- assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
+ assert((isa<DbgLabelInst>(this)
+ || !cast<MDNode>(MD)->getNumOperands())
+ && "DbgValueInst Expected an empty MDNode");
+
return nullptr;
}
+Optional<uint64_t> DbgInfoIntrinsic::getFragmentSizeInBits() const {
+ if (auto Fragment = getExpression()->getFragmentInfo())
+ return Fragment->SizeInBits;
+ return getVariable()->getSizeInBits();
+}
+
int llvm::Intrinsic::lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
StringRef Name) {
assert(Name.startswith("llvm."));
diff --git a/contrib/llvm/lib/IR/LLVMContext.cpp b/contrib/llvm/lib/IR/LLVMContext.cpp
index c8b7c10a9a41..62d9e387162e 100644
--- a/contrib/llvm/lib/IR/LLVMContext.cpp
+++ b/contrib/llvm/lib/IR/LLVMContext.cpp
@@ -332,8 +332,12 @@ void LLVMContext::setDiscardValueNames(bool Discard) {
pImpl->DiscardValueNames = Discard;
}
-OptBisect &LLVMContext::getOptBisect() {
- return pImpl->getOptBisect();
+OptPassGate &LLVMContext::getOptPassGate() const {
+ return pImpl->getOptPassGate();
+}
+
+void LLVMContext::setOptPassGate(OptPassGate& OPG) {
+ pImpl->setOptPassGate(OPG);
}
const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {
diff --git a/contrib/llvm/lib/IR/LLVMContextImpl.cpp b/contrib/llvm/lib/IR/LLVMContextImpl.cpp
index 4b44a6b69cad..3c34ca55c224 100644
--- a/contrib/llvm/lib/IR/LLVMContextImpl.cpp
+++ b/contrib/llvm/lib/IR/LLVMContextImpl.cpp
@@ -48,6 +48,14 @@ LLVMContextImpl::~LLVMContextImpl() {
while (!OwnedModules.empty())
delete *OwnedModules.begin();
+#ifndef NDEBUG
+ // Check for metadata references from leaked Instructions.
+ for (auto &Pair : InstructionMetadata)
+ Pair.first->dump();
+ assert(InstructionMetadata.empty() &&
+ "Instructions with metadata have been leaked");
+#endif
+
// Drop references for MDNodes. Do this before Values get deleted to avoid
// unnecessary RAUW when nodes are still unresolved.
for (auto *I : DistinctMDNodes)
@@ -155,7 +163,7 @@ void Module::dropTriviallyDeadConstantArrays() {
namespace llvm {
-/// \brief Make MDOperand transparent for hashing.
+/// Make MDOperand transparent for hashing.
///
/// This overload of an implementation detail of the hashing library makes
/// MDOperand hash to the same value as a \a Metadata pointer.
@@ -222,8 +230,8 @@ void LLVMContextImpl::getSyncScopeNames(
/// Singleton instance of the OptBisect class.
///
-/// This singleton is accessed via the LLVMContext::getOptBisect() function. It
-/// provides a mechanism to disable passes and individual optimizations at
+/// This singleton is accessed via the LLVMContext::getOptPassGate() function.
+/// It provides a mechanism to disable passes and individual optimizations at
/// compile time based on a command line option (-opt-bisect-limit) in order to
/// perform a bisecting search for optimization-related problems.
///
@@ -233,6 +241,12 @@ void LLVMContextImpl::getSyncScopeNames(
/// enabled in order to enable a consistent bisect count.
static ManagedStatic<OptBisect> OptBisector;
-OptBisect &LLVMContextImpl::getOptBisect() {
- return *OptBisector;
+OptPassGate &LLVMContextImpl::getOptPassGate() const {
+ if (!OPG)
+ OPG = &(*OptBisector);
+ return *OPG;
+}
+
+void LLVMContextImpl::setOptPassGate(OptPassGate& OPG) {
+ this->OPG = &OPG;
}
diff --git a/contrib/llvm/lib/IR/LLVMContextImpl.h b/contrib/llvm/lib/IR/LLVMContextImpl.h
index f41acfa8ea9c..d5046d644187 100644
--- a/contrib/llvm/lib/IR/LLVMContextImpl.h
+++ b/contrib/llvm/lib/IR/LLVMContextImpl.h
@@ -202,7 +202,7 @@ struct FunctionTypeKeyInfo {
}
};
-/// \brief Structure for hashing arbitrary MDNode operands.
+/// Structure for hashing arbitrary MDNode operands.
class MDNodeOpsKey {
ArrayRef<Metadata *> RawOps;
ArrayRef<MDOperand> Ops;
@@ -257,7 +257,7 @@ template <class NodeTy> struct MDNodeSubsetEqualImpl {
}
};
-/// \brief DenseMapInfo for MDTuple.
+/// DenseMapInfo for MDTuple.
///
/// Note that we don't need the is-function-local bit, since that's implicit in
/// the operands.
@@ -274,7 +274,7 @@ template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {
}
};
-/// \brief DenseMapInfo for DILocation.
+/// DenseMapInfo for DILocation.
template <> struct MDNodeKeyImpl<DILocation> {
unsigned Line;
unsigned Column;
@@ -298,7 +298,7 @@ template <> struct MDNodeKeyImpl<DILocation> {
}
};
-/// \brief DenseMapInfo for GenericDINode.
+/// DenseMapInfo for GenericDINode.
template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey {
unsigned Tag;
MDString *Header;
@@ -321,31 +321,50 @@ template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey {
};
template <> struct MDNodeKeyImpl<DISubrange> {
- int64_t Count;
+ Metadata *CountNode;
int64_t LowerBound;
- MDNodeKeyImpl(int64_t Count, int64_t LowerBound)
- : Count(Count), LowerBound(LowerBound) {}
+ MDNodeKeyImpl(Metadata *CountNode, int64_t LowerBound)
+ : CountNode(CountNode), LowerBound(LowerBound) {}
MDNodeKeyImpl(const DISubrange *N)
- : Count(N->getCount()), LowerBound(N->getLowerBound()) {}
+ : CountNode(N->getRawCountNode()),
+ LowerBound(N->getLowerBound()) {}
bool isKeyOf(const DISubrange *RHS) const {
- return Count == RHS->getCount() && LowerBound == RHS->getLowerBound();
+ if (LowerBound != RHS->getLowerBound())
+ return false;
+
+ if (auto *RHSCount = RHS->getCount().dyn_cast<ConstantInt*>())
+ if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
+ if (RHSCount->getSExtValue() ==
+ cast<ConstantInt>(MD->getValue())->getSExtValue())
+ return true;
+
+ return CountNode == RHS->getRawCountNode();
}
- unsigned getHashValue() const { return hash_combine(Count, LowerBound); }
+ unsigned getHashValue() const {
+ if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
+ return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
+ LowerBound);
+ return hash_combine(CountNode, LowerBound);
+ }
};
template <> struct MDNodeKeyImpl<DIEnumerator> {
int64_t Value;
MDString *Name;
+ bool IsUnsigned;
- MDNodeKeyImpl(int64_t Value, MDString *Name) : Value(Value), Name(Name) {}
+ MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
+ : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
MDNodeKeyImpl(const DIEnumerator *N)
- : Value(N->getValue()), Name(N->getRawName()) {}
+ : Value(N->getValue()), Name(N->getRawName()),
+ IsUnsigned(N->isUnsigned()) {}
bool isKeyOf(const DIEnumerator *RHS) const {
- return Value == RHS->getValue() && Name == RHS->getRawName();
+ return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&
+ Name == RHS->getRawName();
}
unsigned getHashValue() const { return hash_combine(Value, Name); }
@@ -484,18 +503,20 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *VTableHolder;
Metadata *TemplateParams;
MDString *Identifier;
+ Metadata *Discriminator;
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
Metadata *Elements, unsigned RuntimeLang,
Metadata *VTableHolder, Metadata *TemplateParams,
- MDString *Identifier)
+ MDString *Identifier, Metadata *Discriminator)
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
- TemplateParams(TemplateParams), Identifier(Identifier) {}
+ TemplateParams(TemplateParams), Identifier(Identifier),
+ Discriminator(Discriminator) {}
MDNodeKeyImpl(const DICompositeType *N)
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
Line(N->getLine()), Scope(N->getRawScope()),
@@ -504,7 +525,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Flags(N->getFlags()), Elements(N->getRawElements()),
RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
TemplateParams(N->getRawTemplateParams()),
- Identifier(N->getRawIdentifier()) {}
+ Identifier(N->getRawIdentifier()),
+ Discriminator(N->getRawDiscriminator()) {}
bool isKeyOf(const DICompositeType *RHS) const {
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
@@ -517,7 +539,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
RuntimeLang == RHS->getRuntimeLang() &&
VTableHolder == RHS->getRawVTableHolder() &&
TemplateParams == RHS->getRawTemplateParams() &&
- Identifier == RHS->getRawIdentifier();
+ Identifier == RHS->getRawIdentifier() &&
+ Discriminator == RHS->getRawDiscriminator();
}
unsigned getHashValue() const {
@@ -551,26 +574,29 @@ template <> struct MDNodeKeyImpl<DISubroutineType> {
template <> struct MDNodeKeyImpl<DIFile> {
MDString *Filename;
MDString *Directory;
- DIFile::ChecksumKind CSKind;
- MDString *Checksum;
+ Optional<DIFile::ChecksumInfo<MDString *>> Checksum;
+ Optional<MDString *> Source;
MDNodeKeyImpl(MDString *Filename, MDString *Directory,
- DIFile::ChecksumKind CSKind, MDString *Checksum)
- : Filename(Filename), Directory(Directory), CSKind(CSKind),
- Checksum(Checksum) {}
+ Optional<DIFile::ChecksumInfo<MDString *>> Checksum,
+ Optional<MDString *> Source)
+ : Filename(Filename), Directory(Directory), Checksum(Checksum),
+ Source(Source) {}
MDNodeKeyImpl(const DIFile *N)
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
- CSKind(N->getChecksumKind()), Checksum(N->getRawChecksum()) {}
+ Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
bool isKeyOf(const DIFile *RHS) const {
return Filename == RHS->getRawFilename() &&
Directory == RHS->getRawDirectory() &&
- CSKind == RHS->getChecksumKind() &&
- Checksum == RHS->getRawChecksum();
+ Checksum == RHS->getRawChecksum() &&
+ Source == RHS->getRawSource();
}
unsigned getHashValue() const {
- return hash_combine(Filename, Directory, CSKind, Checksum);
+ return hash_combine(
+ Filename, Directory, Checksum ? Checksum->Kind : 0,
+ Checksum ? Checksum->Value : nullptr, Source.getValueOr(nullptr));
}
};
@@ -593,7 +619,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
Metadata *Unit;
Metadata *TemplateParams;
Metadata *Declaration;
- Metadata *Variables;
+ Metadata *RetainedNodes;
Metadata *ThrownTypes;
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
@@ -602,7 +628,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
Metadata *ContainingType, unsigned Virtuality,
unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
bool IsOptimized, Metadata *Unit, Metadata *TemplateParams,
- Metadata *Declaration, Metadata *Variables,
+ Metadata *Declaration, Metadata *RetainedNodes,
Metadata *ThrownTypes)
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
@@ -611,7 +637,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment),
Flags(Flags), IsOptimized(IsOptimized), Unit(Unit),
TemplateParams(TemplateParams), Declaration(Declaration),
- Variables(Variables), ThrownTypes(ThrownTypes) {}
+ RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {}
MDNodeKeyImpl(const DISubprogram *N)
: Scope(N->getRawScope()), Name(N->getRawName()),
LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
@@ -622,7 +648,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),
IsOptimized(N->isOptimized()), Unit(N->getRawUnit()),
TemplateParams(N->getRawTemplateParams()),
- Declaration(N->getRawDeclaration()), Variables(N->getRawVariables()),
+ Declaration(N->getRawDeclaration()), RetainedNodes(N->getRawRetainedNodes()),
ThrownTypes(N->getRawThrownTypes()) {}
bool isKeyOf(const DISubprogram *RHS) const {
@@ -640,7 +666,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> {
Unit == RHS->getUnit() &&
TemplateParams == RHS->getRawTemplateParams() &&
Declaration == RHS->getRawDeclaration() &&
- Variables == RHS->getRawVariables() &&
+ RetainedNodes == RHS->getRawRetainedNodes() &&
ThrownTypes == RHS->getRawThrownTypes();
}
@@ -922,6 +948,29 @@ template <> struct MDNodeKeyImpl<DILocalVariable> {
}
};
+template <> struct MDNodeKeyImpl<DILabel> {
+ Metadata *Scope;
+ MDString *Name;
+ Metadata *File;
+ unsigned Line;
+
+ MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line)
+ : Scope(Scope), Name(Name), File(File), Line(Line) {}
+ MDNodeKeyImpl(const DILabel *N)
+ : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
+ Line(N->getLine()) {}
+
+ bool isKeyOf(const DILabel *RHS) const {
+ return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
+ File == RHS->getRawFile() && Line == RHS->getLine();
+ }
+
+ /// Using name and line to get hash value. It should already be mostly unique.
+ unsigned getHashValue() const {
+ return hash_combine(Scope, Name, Line);
+ }
+};
+
template <> struct MDNodeKeyImpl<DIExpression> {
ArrayRef<uint64_t> Elements;
@@ -1058,7 +1107,7 @@ template <> struct MDNodeKeyImpl<DIMacroFile> {
}
};
-/// \brief DenseMapInfo for MDNode subclasses.
+/// DenseMapInfo for MDNode subclasses.
template <class NodeTy> struct MDNodeInfo {
using KeyTy = MDNodeKeyImpl<NodeTy>;
using SubsetEqualTy = MDNodeSubsetEqualImpl<NodeTy>;
@@ -1095,7 +1144,7 @@ template <class NodeTy> struct MDNodeInfo {
#define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;
#include "llvm/IR/Metadata.def"
-/// \brief Map-like storage for metadata attachments.
+/// Map-like storage for metadata attachments.
class MDAttachmentMap {
SmallVector<std::pair<unsigned, TrackingMDNodeRef>, 2> Attachments;
@@ -1103,27 +1152,27 @@ public:
bool empty() const { return Attachments.empty(); }
size_t size() const { return Attachments.size(); }
- /// \brief Get a particular attachment (if any).
+ /// Get a particular attachment (if any).
MDNode *lookup(unsigned ID) const;
- /// \brief Set an attachment to a particular node.
+ /// Set an attachment to a particular node.
///
/// Set the \c ID attachment to \c MD, replacing the current attachment at \c
/// ID (if anyway).
void set(unsigned ID, MDNode &MD);
- /// \brief Remove an attachment.
+ /// Remove an attachment.
///
/// Remove the attachment at \c ID, if any.
- void erase(unsigned ID);
+ bool erase(unsigned ID);
- /// \brief Copy out all the attachments.
+ /// Copy out all the attachments.
///
/// Copies all the current attachments into \c Result, sorting by attachment
/// ID. This function does \em not clear \c Result.
void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
- /// \brief Erase matching attachments.
+ /// Erase matching attachments.
///
/// Erases all attachments matching the \c shouldRemove predicate.
template <class PredTy> void remove_if(PredTy shouldRemove) {
@@ -1148,10 +1197,14 @@ public:
/// Appends all attachments with the given ID to \c Result in insertion order.
/// If the global has no attachments with the given ID, or if ID is invalid,
/// leaves Result unchanged.
- void get(unsigned ID, SmallVectorImpl<MDNode *> &Result);
+ void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;
+
+ /// Returns the first attachment with the given ID or nullptr if no such
+ /// attachment exists.
+ MDNode *lookup(unsigned ID) const;
void insert(unsigned ID, MDNode &MD);
- void erase(unsigned ID);
+ bool erase(unsigned ID);
/// Appends all attachments for the global to \c Result, sorting by attachment
/// ID. Attachments with the same ID appear in insertion order. This function
@@ -1288,7 +1341,7 @@ public:
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
- /// \brief A set of interned tags for operand bundles. The StringMap maps
+ /// A set of interned tags for operand bundles. The StringMap maps
/// bundle tags to their IDs.
///
/// \see LLVMContext::getOperandBundleTagID
@@ -1329,9 +1382,18 @@ public:
/// Destroy the ConstantArrays if they are not used.
void dropTriviallyDeadConstantArrays();
- /// \brief Access the object which manages optimization bisection for failure
- /// analysis.
- OptBisect &getOptBisect();
+ mutable OptPassGate *OPG = nullptr;
+
+ /// Access the object which can disable optional passes and individual
+ /// optimizations at compile time.
+ OptPassGate &getOptPassGate() const;
+
+ /// Set the object which can disable optional passes and individual
+ /// optimizations at compile time.
+ ///
+ /// The lifetime of the object must be guaranteed to extend as long as the
+ /// LLVMContext is used by compilation.
+ void setOptPassGate(OptPassGate&);
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/IR/LegacyPassManager.cpp b/contrib/llvm/lib/IR/LegacyPassManager.cpp
index 8bd9ed6ef0fa..54d602d926e5 100644
--- a/contrib/llvm/lib/IR/LegacyPassManager.cpp
+++ b/contrib/llvm/lib/IR/LegacyPassManager.cpp
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManagers.h"
@@ -28,7 +30,6 @@
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
-#include <map>
#include <unordered_set>
using namespace llvm;
using namespace llvm::legacy;
@@ -86,7 +87,7 @@ static cl::opt<bool>
PrintModuleScope("print-module-scope",
cl::desc("When printing IR for print-[before|after]{-all} "
"always print a module IR"),
- cl::init(false));
+ cl::init(false), cl::Hidden);
static cl::list<std::string>
PrintFuncsList("filter-print-funcs", cl::value_desc("function names"),
@@ -134,8 +135,60 @@ bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
return PassDebugging >= Executions;
}
+unsigned PMDataManager::initSizeRemarkInfo(Module &M) {
+ // Only calculate getInstructionCount if the size-info remark is requested.
+ return M.getInstructionCount();
+}
+
+void PMDataManager::emitInstrCountChangedRemark(Pass *P, Module &M,
+ unsigned CountBefore) {
+ // We need a function containing at least one basic block in order to output
+ // remarks. Since it's possible that the first function in the module doesn't
+ // actually contain a basic block, we have to go and find one that's suitable
+ // for emitting remarks.
+ auto It = std::find_if(M.begin(), M.end(),
+ [](const Function &Fn) { return !Fn.empty(); });
+
+ // Didn't find a function. Quit.
+ if (It == M.end())
+ return;
+
+ // We found a function containing at least one basic block.
+ Function *F = &*It;
+
+ // How many instructions are in the module now?
+ unsigned CountAfter = M.getInstructionCount();
+
+ // If there was no change, don't emit a remark.
+ if (CountBefore == CountAfter)
+ return;
+ // If it's a pass manager, don't emit a remark. (This hinges on the assumption
+ // that the only passes that return non-null with getAsPMDataManager are pass
+ // managers.) The reason we have to do this is to avoid emitting remarks for
+ // CGSCC passes.
+ if (P->getAsPMDataManager())
+ return;
+ // Compute a possibly negative delta between the instruction count before
+ // running P, and after running P.
+ int64_t Delta =
+ static_cast<int64_t>(CountAfter) - static_cast<int64_t>(CountBefore);
+
+ BasicBlock &BB = *F->begin();
+ OptimizationRemarkAnalysis R("size-info", "IRSizeChange",
+ DiagnosticLocation(), &BB);
+ // FIXME: Move ore namespace to DiagnosticInfo so that we can use it. This
+ // would let us use NV instead of DiagnosticInfoOptimizationBase::Argument.
+ R << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName())
+ << ": IR instruction count changed from "
+ << DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", CountBefore)
+ << " to "
+ << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", CountAfter)
+ << "; Delta: "
+ << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", Delta);
+ F->getContext().diagnose(R); // Not using ORE for layering reasons.
+}
void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
if (!V && !M)
@@ -355,8 +408,8 @@ public:
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
MP->dumpPassStructure(Offset + 1);
- std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
- OnTheFlyManagers.find(MP);
+ MapVector<Pass *, FunctionPassManagerImpl *>::const_iterator I =
+ OnTheFlyManagers.find(MP);
if (I != OnTheFlyManagers.end())
I->second->dumpPassStructure(Offset + 2);
dumpLastUses(MP, Offset+1);
@@ -375,7 +428,7 @@ public:
private:
/// Collection of on the fly FPPassManagers. These managers manage
/// function passes that are required by module passes.
- std::map<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
+ MapVector<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
};
char MPPassManager::ID = 0;
@@ -486,7 +539,11 @@ public:
Timer *&T = TimingData[P];
if (!T) {
StringRef PassName = P->getPassName();
- T = new Timer(PassName, PassName, TG);
+ StringRef PassArgument;
+ if (const PassInfo *PI = Pass::lookupPassInfo(P->getPassID()))
+ PassArgument = PI->getPassArgument();
+ T = new Timer(PassArgument.empty() ? PassName : PassArgument, PassName,
+ TG);
}
return T;
}
@@ -585,7 +642,7 @@ AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
// of dependencies.
AnalysisUsage AU;
P->getAnalysisUsage(AU);
-
+
AUFoldingSetNode* Node = nullptr;
FoldingSetNodeID ID;
AUFoldingSetNode::Profile(ID, AU);
@@ -1284,7 +1341,10 @@ bool BBPassManager::runOnFunction(Function &F) {
return false;
bool Changed = doInitialization(F);
+ Module &M = *F.getParent();
+ unsigned InstrCount = 0;
+ bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
for (BasicBlock &BB : F)
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
BasicBlockPass *BP = getContainedPass(Index);
@@ -1299,8 +1359,11 @@ bool BBPassManager::runOnFunction(Function &F) {
// If the pass crashes, remember this.
PassManagerPrettyStackEntry X(BP, BB);
TimeRegion PassTimer(getPassTimer(BP));
-
+ if (EmitICRemark)
+ InstrCount = initSizeRemarkInfo(M);
LocalChanged |= BP->runOnBasicBlock(BB);
+ if (EmitICRemark)
+ emitInstrCountChangedRemark(BP, M, InstrCount);
}
Changed |= LocalChanged;
@@ -1500,10 +1563,12 @@ bool FPPassManager::runOnFunction(Function &F) {
return false;
bool Changed = false;
-
+ Module &M = *F.getParent();
// Collect inherited analysis from Module level pass manager.
populateInheritedAnalysis(TPM->activeStack);
+ unsigned InstrCount = 0;
+ bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
FunctionPass *FP = getContainedPass(Index);
bool LocalChanged = false;
@@ -1516,8 +1581,11 @@ bool FPPassManager::runOnFunction(Function &F) {
{
PassManagerPrettyStackEntry X(FP, F);
TimeRegion PassTimer(getPassTimer(FP));
-
+ if (EmitICRemark)
+ InstrCount = initSizeRemarkInfo(M);
LocalChanged |= FP->runOnFunction(F);
+ if (EmitICRemark)
+ emitInstrCountChangedRemark(FP, M, InstrCount);
}
Changed |= LocalChanged;
@@ -1581,6 +1649,8 @@ MPPassManager::runOnModule(Module &M) {
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
Changed |= getContainedPass(Index)->doInitialization(M);
+ unsigned InstrCount = 0;
+ bool EmitICRemark = M.shouldEmitInstrCountChangedRemark();
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
bool LocalChanged = false;
@@ -1594,7 +1664,11 @@ MPPassManager::runOnModule(Module &M) {
PassManagerPrettyStackEntry X(MP, M);
TimeRegion PassTimer(getPassTimer(MP));
+ if (EmitICRemark)
+ InstrCount = initSizeRemarkInfo(M);
LocalChanged |= MP->runOnModule(M);
+ if (EmitICRemark)
+ emitInstrCountChangedRemark(MP, M, InstrCount);
}
Changed |= LocalChanged;
diff --git a/contrib/llvm/lib/IR/MDBuilder.cpp b/contrib/llvm/lib/IR/MDBuilder.cpp
index 6d77a8f2d601..1bb23c0330f3 100644
--- a/contrib/llvm/lib/IR/MDBuilder.cpp
+++ b/contrib/llvm/lib/IR/MDBuilder.cpp
@@ -58,10 +58,14 @@ MDNode *MDBuilder::createUnpredictable() {
}
MDNode *MDBuilder::createFunctionEntryCount(
- uint64_t Count, const DenseSet<GlobalValue::GUID> *Imports) {
+ uint64_t Count, bool Synthetic,
+ const DenseSet<GlobalValue::GUID> *Imports) {
Type *Int64Ty = Type::getInt64Ty(Context);
SmallVector<Metadata *, 8> Ops;
- Ops.push_back(createString("function_entry_count"));
+ if (Synthetic)
+ Ops.push_back(createString("synthetic_function_entry_count"));
+ else
+ Ops.push_back(createString("function_entry_count"));
Ops.push_back(createConstant(ConstantInt::get(Int64Ty, Count)));
if (Imports) {
SmallVector<GlobalValue::GUID, 2> OrderID(Imports->begin(), Imports->end());
@@ -129,7 +133,7 @@ MDNode *MDBuilder::createTBAARoot(StringRef Name) {
return MDNode::get(Context, createString(Name));
}
-/// \brief Return metadata for a non-root TBAA node with the given name,
+/// Return metadata for a non-root TBAA node with the given name,
/// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
MDNode *MDBuilder::createTBAANode(StringRef Name, MDNode *Parent,
bool isConstant) {
@@ -149,7 +153,7 @@ MDNode *MDBuilder::createAliasScope(StringRef Name, MDNode *Domain) {
return MDNode::get(Context, {createString(Name), Domain});
}
-/// \brief Return metadata for a tbaa.struct node with the given
+/// Return metadata for a tbaa.struct node with the given
/// struct field descriptions.
MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) {
SmallVector<Metadata *, 4> Vals(Fields.size() * 3);
@@ -162,7 +166,7 @@ MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) {
return MDNode::get(Context, Vals);
}
-/// \brief Return metadata for a TBAA struct node in the type DAG
+/// Return metadata for a TBAA struct node in the type DAG
/// with the given name, a list of pairs (offset, field type in the type DAG).
MDNode *MDBuilder::createTBAAStructTypeNode(
StringRef Name, ArrayRef<std::pair<MDNode *, uint64_t>> Fields) {
@@ -176,7 +180,7 @@ MDNode *MDBuilder::createTBAAStructTypeNode(
return MDNode::get(Context, Ops);
}
-/// \brief Return metadata for a TBAA scalar type node with the
+/// Return metadata for a TBAA scalar type node with the
/// given name, an offset and a parent in the TBAA type DAG.
MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent,
uint64_t Offset) {
@@ -185,7 +189,7 @@ MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent,
{createString(Name), Parent, createConstant(Off)});
}
-/// \brief Return metadata for a TBAA tag node with the given
+/// Return metadata for a TBAA tag node with the given
/// base type, access type and offset relative to the base type.
MDNode *MDBuilder::createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,
uint64_t Offset, bool IsConstant) {
@@ -228,6 +232,33 @@ MDNode *MDBuilder::createTBAAAccessTag(MDNode *BaseType, MDNode *AccessType,
return MDNode::get(Context, {BaseType, AccessType, OffsetNode, SizeNode});
}
+MDNode *MDBuilder::createMutableTBAAAccessTag(MDNode *Tag) {
+ MDNode *BaseType = cast<MDNode>(Tag->getOperand(0));
+ MDNode *AccessType = cast<MDNode>(Tag->getOperand(1));
+ Metadata *OffsetNode = Tag->getOperand(2);
+ uint64_t Offset = mdconst::extract<ConstantInt>(OffsetNode)->getZExtValue();
+
+ bool NewFormat = isa<MDNode>(AccessType->getOperand(0));
+
+ // See if the tag is already mutable.
+ unsigned ImmutabilityFlagOp = NewFormat ? 4 : 3;
+ if (Tag->getNumOperands() <= ImmutabilityFlagOp)
+ return Tag;
+
+ // If Tag is already mutable then return it.
+ Metadata *ImmutabilityFlagNode = Tag->getOperand(ImmutabilityFlagOp);
+ if (!mdconst::extract<ConstantInt>(ImmutabilityFlagNode)->getValue())
+ return Tag;
+
+ // Otherwise, create another node.
+ if (!NewFormat)
+ return createTBAAStructTagNode(BaseType, AccessType, Offset);
+
+ Metadata *SizeNode = Tag->getOperand(3);
+ uint64_t Size = mdconst::extract<ConstantInt>(SizeNode)->getZExtValue();
+ return createTBAAAccessTag(BaseType, AccessType, Offset, Size);
+}
+
MDNode *MDBuilder::createIrrLoopHeaderWeight(uint64_t Weight) {
SmallVector<Metadata *, 2> Vals(2);
Vals[0] = createString("loop_header_weight");
diff --git a/contrib/llvm/lib/IR/Mangler.cpp b/contrib/llvm/lib/IR/Mangler.cpp
index 03723bfd2ddb..be3086cfcf05 100644
--- a/contrib/llvm/lib/IR/Mangler.cpp
+++ b/contrib/llvm/lib/IR/Mangler.cpp
@@ -44,6 +44,9 @@ static void getNameWithPrefixImpl(raw_ostream &OS, const Twine &GVName,
return;
}
+ if (DL.doNotMangleLeadingQuestionMark() && Name[0] == '?')
+ Prefix = '\0';
+
if (PrefixTy == Private)
OS << DL.getPrivateGlobalPrefix();
else if (PrefixTy == LinkerPrivate)
@@ -135,8 +138,13 @@ void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV,
// Mangle functions with Microsoft calling conventions specially. Only do
// this mangling for x86_64 vectorcall and 32-bit x86.
const Function *MSFunc = dyn_cast<Function>(GV);
- if (Name.startswith("\01"))
- MSFunc = nullptr; // Don't mangle when \01 is present.
+
+ // Don't add byte count suffixes when '\01' or '?' are in the first
+ // character.
+ if (Name.startswith("\01") ||
+ (DL.doNotMangleLeadingQuestionMark() && Name.startswith("?")))
+ MSFunc = nullptr;
+
CallingConv::ID CC =
MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C;
if (!DL.hasMicrosoftFastStdCallMangling() &&
@@ -204,3 +212,13 @@ void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
OS << ",data";
}
}
+
+void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV,
+ const Triple &T, Mangler &M) {
+ if (!T.isKnownWindowsMSVCEnvironment())
+ return;
+
+ OS << " /INCLUDE:";
+ M.getNameWithPrefix(OS, GV, false);
+}
+
diff --git a/contrib/llvm/lib/IR/Metadata.cpp b/contrib/llvm/lib/IR/Metadata.cpp
index a148ab65fc83..83a22d95bd81 100644
--- a/contrib/llvm/lib/IR/Metadata.cpp
+++ b/contrib/llvm/lib/IR/Metadata.cpp
@@ -237,7 +237,7 @@ void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
// Copy out uses since UseMap will get touched below.
using UseTy = std::pair<void *, std::pair<OwnerTy, uint64_t>>;
SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
- std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
+ llvm::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
return L.second.second < R.second.second;
});
for (const auto &Pair : Uses) {
@@ -290,7 +290,7 @@ void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
// Copy out uses since UseMap could get touched below.
using UseTy = std::pair<void *, std::pair<OwnerTy, uint64_t>>;
SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
- std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
+ llvm::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
return L.second.second < R.second.second;
});
UseMap.clear();
@@ -329,12 +329,20 @@ bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) {
return dyn_cast<ValueAsMetadata>(&MD);
}
-static Function *getLocalFunction(Value *V) {
+static DISubprogram *getLocalFunctionMetadata(Value *V) {
assert(V && "Expected value");
- if (auto *A = dyn_cast<Argument>(V))
- return A->getParent();
- if (BasicBlock *BB = cast<Instruction>(V)->getParent())
- return BB->getParent();
+ if (auto *A = dyn_cast<Argument>(V)) {
+ if (auto *Fn = A->getParent())
+ return Fn->getSubprogram();
+ return nullptr;
+ }
+
+ if (BasicBlock *BB = cast<Instruction>(V)->getParent()) {
+ if (auto *Fn = BB->getParent())
+ return Fn->getSubprogram();
+ return nullptr;
+ }
+
return nullptr;
}
@@ -410,9 +418,9 @@ void ValueAsMetadata::handleRAUW(Value *From, Value *To) {
delete MD;
return;
}
- if (getLocalFunction(From) && getLocalFunction(To) &&
- getLocalFunction(From) != getLocalFunction(To)) {
- // Function changed.
+ if (getLocalFunctionMetadata(From) && getLocalFunctionMetadata(To) &&
+ getLocalFunctionMetadata(From) != getLocalFunctionMetadata(To)) {
+ // DISubprogram changed.
MD->replaceAllUsesWith(nullptr);
delete MD;
return;
@@ -1102,14 +1110,14 @@ void MDAttachmentMap::set(unsigned ID, MDNode &MD) {
std::make_tuple(&MD));
}
-void MDAttachmentMap::erase(unsigned ID) {
+bool MDAttachmentMap::erase(unsigned ID) {
if (empty())
- return;
+ return false;
// Common case is one/last value.
if (Attachments.back().first == ID) {
Attachments.pop_back();
- return;
+ return true;
}
for (auto I = Attachments.begin(), E = std::prev(Attachments.end()); I != E;
@@ -1117,8 +1125,10 @@ void MDAttachmentMap::erase(unsigned ID) {
if (I->first == ID) {
*I = std::move(Attachments.back());
Attachments.pop_back();
- return;
+ return true;
}
+
+ return false;
}
MDNode *MDAttachmentMap::lookup(unsigned ID) const {
@@ -1141,29 +1151,31 @@ void MDGlobalAttachmentMap::insert(unsigned ID, MDNode &MD) {
Attachments.push_back({ID, TrackingMDNodeRef(&MD)});
}
+MDNode *MDGlobalAttachmentMap::lookup(unsigned ID) const {
+ for (const auto &A : Attachments)
+ if (A.MDKind == ID)
+ return A.Node;
+ return nullptr;
+}
+
void MDGlobalAttachmentMap::get(unsigned ID,
- SmallVectorImpl<MDNode *> &Result) {
- for (auto A : Attachments)
+ SmallVectorImpl<MDNode *> &Result) const {
+ for (const auto &A : Attachments)
if (A.MDKind == ID)
Result.push_back(A.Node);
}
-void MDGlobalAttachmentMap::erase(unsigned ID) {
- auto Follower = Attachments.begin();
- for (auto Leader = Attachments.begin(), E = Attachments.end(); Leader != E;
- ++Leader) {
- if (Leader->MDKind != ID) {
- if (Follower != Leader)
- *Follower = std::move(*Leader);
- ++Follower;
- }
- }
- Attachments.resize(Follower - Attachments.begin());
+bool MDGlobalAttachmentMap::erase(unsigned ID) {
+ auto I = std::remove_if(Attachments.begin(), Attachments.end(),
+ [ID](const Attachment &A) { return A.MDKind == ID; });
+ bool Changed = I != Attachments.end();
+ Attachments.erase(I, Attachments.end());
+ return Changed;
}
void MDGlobalAttachmentMap::getAll(
SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
- for (auto &A : Attachments)
+ for (const auto &A : Attachments)
Result.emplace_back(A.MDKind, A.Node);
// Sort the resulting array so it is stable with respect to metadata IDs. We
@@ -1390,15 +1402,16 @@ void GlobalObject::addMetadata(StringRef Kind, MDNode &MD) {
addMetadata(getContext().getMDKindID(Kind), MD);
}
-void GlobalObject::eraseMetadata(unsigned KindID) {
+bool GlobalObject::eraseMetadata(unsigned KindID) {
// Nothing to unset.
if (!hasMetadata())
- return;
+ return false;
auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
- Store.erase(KindID);
+ bool Changed = Store.erase(KindID);
if (Store.empty())
clearMetadata();
+ return Changed;
}
void GlobalObject::getAllMetadata(
@@ -1429,11 +1442,9 @@ void GlobalObject::setMetadata(StringRef Kind, MDNode *N) {
}
MDNode *GlobalObject::getMetadata(unsigned KindID) const {
- SmallVector<MDNode *, 1> MDs;
- getMetadata(KindID, MDs);
- if (MDs.empty())
- return nullptr;
- return MDs[0];
+ if (hasMetadata())
+ return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID);
+ return nullptr;
}
MDNode *GlobalObject::getMetadata(StringRef Kind) const {
diff --git a/contrib/llvm/lib/IR/Module.cpp b/contrib/llvm/lib/IR/Module.cpp
index c230a50044c7..f18024063533 100644
--- a/contrib/llvm/lib/IR/Module.cpp
+++ b/contrib/llvm/lib/IR/Module.cpp
@@ -464,6 +464,13 @@ unsigned Module::getCodeViewFlag() const {
return cast<ConstantInt>(Val->getValue())->getZExtValue();
}
+unsigned Module::getInstructionCount() {
+ unsigned NumInstrs = 0;
+ for (Function &F : FunctionList)
+ NumInstrs += F.getInstructionCount();
+ return NumInstrs;
+}
+
Comdat *Module::getOrInsertComdat(StringRef Name) {
auto &Entry = *ComdatSymTab.insert(std::make_pair(Name, Comdat())).first;
Entry.second.Name = &Entry;
@@ -510,6 +517,15 @@ void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
OwnedMemoryBuffer = std::move(MB);
}
+bool Module::getRtLibUseGOT() const {
+ auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("RtLibUseGOT"));
+ return Val && (cast<ConstantInt>(Val->getValue())->getZExtValue() > 0);
+}
+
+void Module::setRtLibUseGOT() {
+ addModuleFlag(ModFlagBehavior::Max, "RtLibUseGOT", 1);
+}
+
GlobalVariable *llvm::collectUsedGlobalVariables(
const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) {
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
diff --git a/contrib/llvm/lib/IR/ModuleSummaryIndex.cpp b/contrib/llvm/lib/IR/ModuleSummaryIndex.cpp
index 51c4bae3332e..4c4466f9a902 100644
--- a/contrib/llvm/lib/IR/ModuleSummaryIndex.cpp
+++ b/contrib/llvm/lib/IR/ModuleSummaryIndex.cpp
@@ -13,9 +13,23 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+FunctionSummary FunctionSummary::ExternalNode =
+ FunctionSummary::makeDummyFunctionSummary({});
+bool ValueInfo::isDSOLocal() const {
+ // Need to check all summaries are local in case of hash collisions.
+ return getSummaryList().size() &&
+ llvm::all_of(getSummaryList(),
+ [](const std::unique_ptr<GlobalValueSummary> &Summary) {
+ return Summary->isDSOLocal();
+ });
+}
+
// Collect for the given module the list of function it defines
// (GUID -> Summary).
void ModuleSummaryIndex::collectDefinedFunctionsForModule(
@@ -69,3 +83,267 @@ bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
return true;
return false;
}
+
+// TODO: write a graphviz dumper for SCCs (see ModuleSummaryIndex::exportToDot)
+// then delete this function and update its tests
+LLVM_DUMP_METHOD
+void ModuleSummaryIndex::dumpSCCs(raw_ostream &O) {
+ for (scc_iterator<ModuleSummaryIndex *> I =
+ scc_begin<ModuleSummaryIndex *>(this);
+ !I.isAtEnd(); ++I) {
+ O << "SCC (" << utostr(I->size()) << " node" << (I->size() == 1 ? "" : "s")
+ << ") {\n";
+ for (const ValueInfo V : *I) {
+ FunctionSummary *F = nullptr;
+ if (V.getSummaryList().size())
+ F = cast<FunctionSummary>(V.getSummaryList().front().get());
+ O << " " << (F == nullptr ? "External" : "") << " " << utostr(V.getGUID())
+ << (I.hasLoop() ? " (has loop)" : "") << "\n";
+ }
+ O << "}\n";
+ }
+}
+
+namespace {
+struct Attributes {
+ void add(const Twine &Name, const Twine &Value,
+ const Twine &Comment = Twine());
+ std::string getAsString() const;
+
+ std::vector<std::string> Attrs;
+ std::string Comments;
+};
+
+struct Edge {
+ uint64_t SrcMod;
+ int Hotness;
+ GlobalValue::GUID Src;
+ GlobalValue::GUID Dst;
+};
+}
+
+void Attributes::add(const Twine &Name, const Twine &Value,
+ const Twine &Comment) {
+ std::string A = Name.str();
+ A += "=\"";
+ A += Value.str();
+ A += "\"";
+ Attrs.push_back(A);
+ if (!Comment.isTriviallyEmpty()) {
+ if (Comments.empty())
+ Comments = " // ";
+ else
+ Comments += ", ";
+ Comments += Comment.str();
+ }
+}
+
+std::string Attributes::getAsString() const {
+ if (Attrs.empty())
+ return "";
+
+ std::string Ret = "[";
+ for (auto &A : Attrs)
+ Ret += A + ",";
+ Ret.pop_back();
+ Ret += "];";
+ Ret += Comments;
+ return Ret;
+}
+
+static std::string linkageToString(GlobalValue::LinkageTypes LT) {
+ switch (LT) {
+ case GlobalValue::ExternalLinkage:
+ return "extern";
+ case GlobalValue::AvailableExternallyLinkage:
+ return "av_ext";
+ case GlobalValue::LinkOnceAnyLinkage:
+ return "linkonce";
+ case GlobalValue::LinkOnceODRLinkage:
+ return "linkonce_odr";
+ case GlobalValue::WeakAnyLinkage:
+ return "weak";
+ case GlobalValue::WeakODRLinkage:
+ return "weak_odr";
+ case GlobalValue::AppendingLinkage:
+ return "appending";
+ case GlobalValue::InternalLinkage:
+ return "internal";
+ case GlobalValue::PrivateLinkage:
+ return "private";
+ case GlobalValue::ExternalWeakLinkage:
+ return "extern_weak";
+ case GlobalValue::CommonLinkage:
+ return "common";
+ }
+
+ return "<unknown>";
+}
+
+static std::string fflagsToString(FunctionSummary::FFlags F) {
+ auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };
+ char FlagRep[] = {FlagValue(F.ReadNone), FlagValue(F.ReadOnly),
+ FlagValue(F.NoRecurse), FlagValue(F.ReturnDoesNotAlias), 0};
+
+ return FlagRep;
+}
+
+// Get string representation of function instruction count and flags.
+static std::string getSummaryAttributes(GlobalValueSummary* GVS) {
+ auto *FS = dyn_cast_or_null<FunctionSummary>(GVS);
+ if (!FS)
+ return "";
+
+ return std::string("inst: ") + std::to_string(FS->instCount()) +
+ ", ffl: " + fflagsToString(FS->fflags());
+}
+
+static std::string getNodeVisualName(const ValueInfo &VI) {
+ return VI.name().empty() ? std::string("@") + std::to_string(VI.getGUID())
+ : VI.name().str();
+}
+
+static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS) {
+ if (isa<AliasSummary>(GVS))
+ return getNodeVisualName(VI);
+
+ std::string Attrs = getSummaryAttributes(GVS);
+ std::string Label =
+ getNodeVisualName(VI) + "|" + linkageToString(GVS->linkage());
+ if (!Attrs.empty())
+ Label += std::string(" (") + Attrs + ")";
+ Label += "}";
+
+ return Label;
+}
+
+// Write definition of external node, which doesn't have any
+// specific module associated with it. Typically this is function
+// or variable defined in native object or library.
+static void defineExternalNode(raw_ostream &OS, const char *Pfx,
+ const ValueInfo &VI) {
+ auto StrId = std::to_string(VI.getGUID());
+ OS << " " << StrId << " [label=\"" << getNodeVisualName(VI)
+ << "\"]; // defined externally\n";
+}
+
+void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const {
+ std::vector<Edge> CrossModuleEdges;
+ DenseMap<GlobalValue::GUID, std::vector<uint64_t>> NodeMap;
+ StringMap<GVSummaryMapTy> ModuleToDefinedGVS;
+ collectDefinedGVSummariesPerModule(ModuleToDefinedGVS);
+
+ // Get node identifier in form MXXX_<GUID>. The MXXX prefix is required,
+ // because we may have multiple linkonce functions summaries.
+ auto NodeId = [](uint64_t ModId, GlobalValue::GUID Id) {
+ return ModId == (uint64_t)-1 ? std::to_string(Id)
+ : std::string("M") + std::to_string(ModId) +
+ "_" + std::to_string(Id);
+ };
+
+ auto DrawEdge = [&](const char *Pfx, int SrcMod, GlobalValue::GUID SrcId,
+ int DstMod, GlobalValue::GUID DstId, int TypeOrHotness) {
+ // 0 corresponds to alias edge, 1 to ref edge, 2 to call with unknown
+ // hotness, ...
+ TypeOrHotness += 2;
+ static const char *EdgeAttrs[] = {
+ " [style=dotted]; // alias",
+ " [style=dashed]; // ref",
+ " // call (hotness : Unknown)",
+ " [color=blue]; // call (hotness : Cold)",
+ " // call (hotness : None)",
+ " [color=brown]; // call (hotness : Hot)",
+ " [style=bold,color=red]; // call (hotness : Critical)"};
+
+ assert(static_cast<size_t>(TypeOrHotness) <
+ sizeof(EdgeAttrs) / sizeof(EdgeAttrs[0]));
+ OS << Pfx << NodeId(SrcMod, SrcId) << " -> " << NodeId(DstMod, DstId)
+ << EdgeAttrs[TypeOrHotness] << "\n";
+ };
+
+ OS << "digraph Summary {\n";
+ for (auto &ModIt : ModuleToDefinedGVS) {
+ auto ModId = getModuleId(ModIt.first());
+ OS << " // Module: " << ModIt.first() << "\n";
+ OS << " subgraph cluster_" << std::to_string(ModId) << " {\n";
+ OS << " style = filled;\n";
+ OS << " color = lightgrey;\n";
+ OS << " label = \"" << sys::path::filename(ModIt.first()) << "\";\n";
+ OS << " node [style=filled,fillcolor=lightblue];\n";
+
+ auto &GVSMap = ModIt.second;
+ auto Draw = [&](GlobalValue::GUID IdFrom, GlobalValue::GUID IdTo, int Hotness) {
+ if (!GVSMap.count(IdTo)) {
+ CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo});
+ return;
+ }
+ DrawEdge(" ", ModId, IdFrom, ModId, IdTo, Hotness);
+ };
+
+ for (auto &SummaryIt : GVSMap) {
+ NodeMap[SummaryIt.first].push_back(ModId);
+ auto Flags = SummaryIt.second->flags();
+ Attributes A;
+ if (isa<FunctionSummary>(SummaryIt.second)) {
+ A.add("shape", "record", "function");
+ } else if (isa<AliasSummary>(SummaryIt.second)) {
+ A.add("style", "dotted,filled", "alias");
+ A.add("shape", "box");
+ } else {
+ A.add("shape", "Mrecord", "variable");
+ }
+
+ auto VI = getValueInfo(SummaryIt.first);
+ A.add("label", getNodeLabel(VI, SummaryIt.second));
+ if (!Flags.Live)
+ A.add("fillcolor", "red", "dead");
+ else if (Flags.NotEligibleToImport)
+ A.add("fillcolor", "yellow", "not eligible to import");
+
+ OS << " " << NodeId(ModId, SummaryIt.first) << " " << A.getAsString()
+ << "\n";
+ }
+ OS << " // Edges:\n";
+
+ for (auto &SummaryIt : GVSMap) {
+ auto *GVS = SummaryIt.second;
+ for (auto &R : GVS->refs())
+ Draw(SummaryIt.first, R.getGUID(), -1);
+
+ if (auto *AS = dyn_cast_or_null<AliasSummary>(SummaryIt.second)) {
+ auto AliaseeOrigId = AS->getAliasee().getOriginalName();
+ auto AliaseeId = getGUIDFromOriginalID(AliaseeOrigId);
+
+ Draw(SummaryIt.first, AliaseeId ? AliaseeId : AliaseeOrigId, -2);
+ continue;
+ }
+
+ if (auto *FS = dyn_cast_or_null<FunctionSummary>(SummaryIt.second))
+ for (auto &CGEdge : FS->calls())
+ Draw(SummaryIt.first, CGEdge.first.getGUID(),
+ static_cast<int>(CGEdge.second.Hotness));
+ }
+ OS << " }\n";
+ }
+
+ OS << " // Cross-module edges:\n";
+ for (auto &E : CrossModuleEdges) {
+ auto &ModList = NodeMap[E.Dst];
+ if (ModList.empty()) {
+ defineExternalNode(OS, " ", getValueInfo(E.Dst));
+ // Add fake module to the list to draw an edge to an external node
+ // in the loop below.
+ ModList.push_back(-1);
+ }
+ for (auto DstMod : ModList)
+ // The edge representing call or ref is drawn to every module where target
+ // symbol is defined. When target is a linkonce symbol there can be
+ // multiple edges representing a single call or ref, both intra-module and
+ // cross-module. As we've already drawn all intra-module edges before we
+ // skip it here.
+ if (DstMod != E.SrcMod)
+ DrawEdge(" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness);
+ }
+
+ OS << "}";
+}
diff --git a/contrib/llvm/lib/IR/Operator.cpp b/contrib/llvm/lib/IR/Operator.cpp
index 7d819f3aae8d..5b4c7524b672 100644
--- a/contrib/llvm/lib/IR/Operator.cpp
+++ b/contrib/llvm/lib/IR/Operator.cpp
@@ -35,8 +35,8 @@ Type *GEPOperator::getResultElementType() const {
bool GEPOperator::accumulateConstantOffset(const DataLayout &DL,
APInt &Offset) const {
assert(Offset.getBitWidth() ==
- DL.getPointerSizeInBits(getPointerAddressSpace()) &&
- "The offset must have exactly as many bits as our pointer.");
+ DL.getIndexSizeInBits(getPointerAddressSpace()) &&
+ "The offset bit width does not match DL specification.");
for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
GTI != GTE; ++GTI) {
diff --git a/contrib/llvm/lib/IR/OptBisect.cpp b/contrib/llvm/lib/IR/OptBisect.cpp
index dc7dcd2e4a97..c79e1fc2b0b4 100644
--- a/contrib/llvm/lib/IR/OptBisect.cpp
+++ b/contrib/llvm/lib/IR/OptBisect.cpp
@@ -36,7 +36,7 @@ static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
cl::Optional,
cl::desc("Maximum optimization to perform"));
-OptBisect::OptBisect() {
+OptBisect::OptBisect() : OptPassGate() {
BisectEnabled = OptBisectLimit != std::numeric_limits<int>::max();
}
@@ -92,19 +92,28 @@ static std::string getDescription(const CallGraphSCC &SCC) {
return Desc;
}
-// Force instantiations.
-template bool OptBisect::shouldRunPass(const Pass *, const Module &);
-template bool OptBisect::shouldRunPass(const Pass *, const Function &);
-template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
-template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
-template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);
-template bool OptBisect::shouldRunPass(const Pass *, const Region &);
-
-template <class UnitT>
-bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
- if (!BisectEnabled)
- return true;
- return checkPass(P->getPassName(), getDescription(U));
+bool OptBisect::shouldRunPass(const Pass *P, const Module &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
+}
+
+bool OptBisect::shouldRunPass(const Pass *P, const Function &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
+}
+
+bool OptBisect::shouldRunPass(const Pass *P, const BasicBlock &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
+}
+
+bool OptBisect::shouldRunPass(const Pass *P, const Region &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
+}
+
+bool OptBisect::shouldRunPass(const Pass *P, const Loop &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
+}
+
+bool OptBisect::shouldRunPass(const Pass *P, const CallGraphSCC &U) {
+ return !BisectEnabled || checkPass(P->getPassName(), getDescription(U));
}
bool OptBisect::checkPass(const StringRef PassName,
diff --git a/contrib/llvm/lib/IR/Pass.cpp b/contrib/llvm/lib/IR/Pass.cpp
index 5e0b59476c4b..a1dc17882493 100644
--- a/contrib/llvm/lib/IR/Pass.cpp
+++ b/contrib/llvm/lib/IR/Pass.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
@@ -56,7 +57,7 @@ PassManagerType ModulePass::getPotentialPassManagerType() const {
}
bool ModulePass::skipModule(Module &M) const {
- return !M.getContext().getOptBisect().shouldRunPass(this, M);
+ return !M.getContext().getOptPassGate().shouldRunPass(this, M);
}
bool Pass::mustPreserveAnalysisID(char &AID) const {
@@ -155,12 +156,12 @@ PassManagerType FunctionPass::getPotentialPassManagerType() const {
}
bool FunctionPass::skipFunction(const Function &F) const {
- if (!F.getContext().getOptBisect().shouldRunPass(this, F))
+ if (!F.getContext().getOptPassGate().shouldRunPass(this, F))
return true;
if (F.hasFnAttribute(Attribute::OptimizeNone)) {
- DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function "
- << F.getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function "
+ << F.getName() << "\n");
return true;
}
return false;
@@ -189,13 +190,13 @@ bool BasicBlockPass::skipBasicBlock(const BasicBlock &BB) const {
const Function *F = BB.getParent();
if (!F)
return false;
- if (!F->getContext().getOptBisect().shouldRunPass(this, BB))
+ if (!F->getContext().getOptPassGate().shouldRunPass(this, BB))
return true;
if (F->hasFnAttribute(Attribute::OptimizeNone)) {
// Report this only once per function.
if (&BB == &F->getEntryBlock())
- DEBUG(dbgs() << "Skipping pass '" << getPassName()
- << "' on function " << F->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName()
+ << "' on function " << F->getName() << "\n");
return true;
}
return false;
diff --git a/contrib/llvm/lib/IR/ProfileSummary.cpp b/contrib/llvm/lib/IR/ProfileSummary.cpp
index 2b24d1251121..491fe834df9a 100644
--- a/contrib/llvm/lib/IR/ProfileSummary.cpp
+++ b/contrib/llvm/lib/IR/ProfileSummary.cpp
@@ -69,18 +69,16 @@ Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) {
// "SampleProfile"). The rest of the elements of the outer MDTuple are specific
// to the kind of profile summary as returned by getFormatSpecificMD.
Metadata *ProfileSummary::getMD(LLVMContext &Context) {
- std::vector<Metadata *> Components;
- Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK]));
-
- Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount()));
- Components.push_back(getKeyValMD(Context, "MaxCount", getMaxCount()));
- Components.push_back(
- getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()));
- Components.push_back(
- getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()));
- Components.push_back(getKeyValMD(Context, "NumCounts", getNumCounts()));
- Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions()));
- Components.push_back(getDetailedSummaryMD(Context));
+ Metadata *Components[] = {
+ getKeyValMD(Context, "ProfileFormat", KindStr[PSK]),
+ getKeyValMD(Context, "TotalCount", getTotalCount()),
+ getKeyValMD(Context, "MaxCount", getMaxCount()),
+ getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()),
+ getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()),
+ getKeyValMD(Context, "NumCounts", getNumCounts()),
+ getKeyValMD(Context, "NumFunctions", getNumFunctions()),
+ getDetailedSummaryMD(Context),
+ };
return MDTuple::get(Context, Components);
}
@@ -144,12 +142,8 @@ static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) {
}
ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
- if (!MD)
- return nullptr;
- if (!isa<MDTuple>(MD))
- return nullptr;
- MDTuple *Tuple = cast<MDTuple>(MD);
- if (Tuple->getNumOperands() != 8)
+ MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD);
+ if (!Tuple || Tuple->getNumOperands() != 8)
return nullptr;
auto &FormatMD = Tuple->getOperand(0);
@@ -185,7 +179,7 @@ ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
SummaryEntryVector Summary;
if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(7)), Summary))
return nullptr;
- return new ProfileSummary(SummaryKind, Summary, TotalCount, MaxCount,
- MaxInternalCount, MaxFunctionCount, NumCounts,
- NumFunctions);
+ return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount,
+ MaxCount, MaxInternalCount, MaxFunctionCount,
+ NumCounts, NumFunctions);
}
diff --git a/contrib/llvm/lib/IR/SafepointIRVerifier.cpp b/contrib/llvm/lib/IR/SafepointIRVerifier.cpp
index 04deb434cec2..6f73126be738 100644
--- a/contrib/llvm/lib/IR/SafepointIRVerifier.cpp
+++ b/contrib/llvm/lib/IR/SafepointIRVerifier.cpp
@@ -59,23 +59,162 @@ using namespace llvm;
static cl::opt<bool> PrintOnly("safepoint-ir-verifier-print-only",
cl::init(false));
-static void Verify(const Function &F, const DominatorTree &DT);
+namespace {
+
+/// This CFG Deadness finds dead blocks and edges. Algorithm starts with a set
+/// of blocks unreachable from entry then propagates deadness using foldable
+/// conditional branches without modifying CFG. So GVN does but it changes CFG
+/// by splitting critical edges. In most cases passes rely on SimplifyCFG to
+/// clean up dead blocks, but in some cases, like verification or loop passes
+/// it's not possible.
+class CFGDeadness {
+ const DominatorTree *DT = nullptr;
+ SetVector<const BasicBlock *> DeadBlocks;
+ SetVector<const Use *> DeadEdges; // Contains all dead edges from live blocks.
+
+public:
+ /// Return the edge that coresponds to the predecessor.
+ static const Use& getEdge(const_pred_iterator &PredIt) {
+ auto &PU = PredIt.getUse();
+ return PU.getUser()->getOperandUse(PU.getOperandNo());
+ }
+
+ /// Return true if there is at least one live edge that corresponds to the
+ /// basic block InBB listed in the phi node.
+ bool hasLiveIncomingEdge(const PHINode *PN, const BasicBlock *InBB) const {
+ assert(!isDeadBlock(InBB) && "block must be live");
+ const BasicBlock* BB = PN->getParent();
+ bool Listed = false;
+ for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
+ if (InBB == *PredIt) {
+ if (!isDeadEdge(&getEdge(PredIt)))
+ return true;
+ Listed = true;
+ }
+ }
+ assert(Listed && "basic block is not found among incoming blocks");
+ return false;
+ }
+
+
+ bool isDeadBlock(const BasicBlock *BB) const {
+ return DeadBlocks.count(BB);
+ }
+
+ bool isDeadEdge(const Use *U) const {
+ assert(dyn_cast<Instruction>(U->getUser())->isTerminator() &&
+ "edge must be operand of terminator");
+ assert(cast_or_null<BasicBlock>(U->get()) &&
+ "edge must refer to basic block");
+ assert(!isDeadBlock(dyn_cast<Instruction>(U->getUser())->getParent()) &&
+ "isDeadEdge() must be applied to edge from live block");
+ return DeadEdges.count(U);
+ }
+
+ bool hasLiveIncomingEdges(const BasicBlock *BB) const {
+ // Check if all incoming edges are dead.
+ for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
+ auto &PU = PredIt.getUse();
+ const Use &U = PU.getUser()->getOperandUse(PU.getOperandNo());
+ if (!isDeadBlock(*PredIt) && !isDeadEdge(&U))
+ return true; // Found a live edge.
+ }
+ return false;
+ }
+
+ void processFunction(const Function &F, const DominatorTree &DT) {
+ this->DT = &DT;
+
+ // Start with all blocks unreachable from entry.
+ for (const BasicBlock &BB : F)
+ if (!DT.isReachableFromEntry(&BB))
+ DeadBlocks.insert(&BB);
+
+ // Top-down walk of the dominator tree
+ ReversePostOrderTraversal<const Function *> RPOT(&F);
+ for (const BasicBlock *BB : RPOT) {
+ const TerminatorInst *TI = BB->getTerminator();
+ assert(TI && "blocks must be well formed");
+
+ // For conditional branches, we can perform simple conditional propagation on
+ // the condition value itself.
+ const BranchInst *BI = dyn_cast<BranchInst>(TI);
+ if (!BI || !BI->isConditional() || !isa<Constant>(BI->getCondition()))
+ continue;
+
+ // If a branch has two identical successors, we cannot declare either dead.
+ if (BI->getSuccessor(0) == BI->getSuccessor(1))
+ continue;
+
+ ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
+ if (!Cond)
+ continue;
+
+ addDeadEdge(BI->getOperandUse(Cond->getZExtValue() ? 1 : 2));
+ }
+ }
+
+protected:
+ void addDeadBlock(const BasicBlock *BB) {
+ SmallVector<const BasicBlock *, 4> NewDead;
+ SmallSetVector<const BasicBlock *, 4> DF;
+
+ NewDead.push_back(BB);
+ while (!NewDead.empty()) {
+ const BasicBlock *D = NewDead.pop_back_val();
+ if (isDeadBlock(D))
+ continue;
+
+ // All blocks dominated by D are dead.
+ SmallVector<BasicBlock *, 8> Dom;
+ DT->getDescendants(const_cast<BasicBlock*>(D), Dom);
+ // Do not need to mark all in and out edges dead
+ // because BB is marked dead and this is enough
+ // to run further.
+ DeadBlocks.insert(Dom.begin(), Dom.end());
+
+ // Figure out the dominance-frontier(D).
+ for (BasicBlock *B : Dom)
+ for (BasicBlock *S : successors(B))
+ if (!isDeadBlock(S) && !hasLiveIncomingEdges(S))
+ NewDead.push_back(S);
+ }
+ }
+
+ void addDeadEdge(const Use &DeadEdge) {
+ if (!DeadEdges.insert(&DeadEdge))
+ return;
+
+ BasicBlock *BB = cast_or_null<BasicBlock>(DeadEdge.get());
+ if (hasLiveIncomingEdges(BB))
+ return;
+
+ addDeadBlock(BB);
+ }
+};
+} // namespace
+
+static void Verify(const Function &F, const DominatorTree &DT,
+ const CFGDeadness &CD);
namespace {
+
struct SafepointIRVerifier : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
- DominatorTree DT;
SafepointIRVerifier() : FunctionPass(ID) {
initializeSafepointIRVerifierPass(*PassRegistry::getPassRegistry());
}
bool runOnFunction(Function &F) override {
- DT.recalculate(F);
- Verify(F, DT);
+ auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+ CFGDeadness CD;
+ CD.processFunction(F, DT);
+ Verify(F, DT, CD);
return false; // no modifications
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequiredID(DominatorTreeWrapperPass::ID);
AU.setPreservesAll();
}
@@ -95,9 +234,10 @@ FunctionPass *llvm::createSafepointIRVerifierPass() {
}
INITIALIZE_PASS_BEGIN(SafepointIRVerifier, "verify-safepoint-ir",
- "Safepoint IR Verifier", false, true)
+ "Safepoint IR Verifier", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_END(SafepointIRVerifier, "verify-safepoint-ir",
- "Safepoint IR Verifier", false, true)
+ "Safepoint IR Verifier", false, false)
static bool isGCPointerType(Type *T) {
if (auto *PT = dyn_cast<PointerType>(T))
@@ -292,6 +432,7 @@ class InstructionVerifier;
/// considered to be unrelocated and no false alarm will happen.
class GCPtrTracker {
const Function &F;
+ const CFGDeadness &CD;
SpecificBumpPtrAllocator<BasicBlockState> BSAllocator;
DenseMap<const BasicBlock *, BasicBlockState *> BlockMap;
// This set contains defs of unrelocated pointers that are proved to be legal
@@ -302,7 +443,12 @@ class GCPtrTracker {
DenseSet<const Value *> PoisonedDefs;
public:
- GCPtrTracker(const Function &F, const DominatorTree &DT);
+ GCPtrTracker(const Function &F, const DominatorTree &DT,
+ const CFGDeadness &CD);
+
+ bool hasLiveIncomingEdge(const PHINode *PN, const BasicBlock *InBB) const {
+ return CD.hasLiveIncomingEdge(PN, InBB);
+ }
BasicBlockState *getBasicBlockState(const BasicBlock *BB);
const BasicBlockState *getBasicBlockState(const BasicBlock *BB) const;
@@ -318,6 +464,11 @@ public:
static void verifyFunction(GCPtrTracker &&Tracker,
InstructionVerifier &Verifier);
+ /// Returns true for reachable and live blocks.
+ bool isMapped(const BasicBlock *BB) const {
+ return BlockMap.find(BB) != BlockMap.end();
+ }
+
private:
/// Returns true if the instruction may be safely skipped during verification.
bool instructionMayBeSkipped(const Instruction *I) const;
@@ -372,14 +523,17 @@ private:
};
} // end anonymous namespace
-GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT) : F(F) {
- // First, calculate Contribution of each BB.
- for (const BasicBlock &BB : F) {
- BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState;
- for (const auto &I : BB)
- transferInstruction(I, BBS->Cleared, BBS->Contribution);
- BlockMap[&BB] = BBS;
- }
+GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT,
+ const CFGDeadness &CD) : F(F), CD(CD) {
+ // Calculate Contribution of each live BB.
+ // Allocate BB states for live blocks.
+ for (const BasicBlock &BB : F)
+ if (!CD.isDeadBlock(&BB)) {
+ BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState;
+ for (const auto &I : BB)
+ transferInstruction(I, BBS->Cleared, BBS->Contribution);
+ BlockMap[&BB] = BBS;
+ }
// Initialize AvailableIn/Out sets of each BB using only information about
// dominating BBs.
@@ -396,9 +550,7 @@ GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT) : F(F) {
BasicBlockState *GCPtrTracker::getBasicBlockState(const BasicBlock *BB) {
auto it = BlockMap.find(BB);
- assert(it != BlockMap.end() &&
- "No such BB in BlockMap! Probably BB from another function");
- return it->second;
+ return it != BlockMap.end() ? it->second : nullptr;
}
const BasicBlockState *GCPtrTracker::getBasicBlockState(
@@ -419,6 +571,9 @@ void GCPtrTracker::verifyFunction(GCPtrTracker &&Tracker,
ReversePostOrderTraversal<const Function *> RPOT(&Tracker.F);
for (const BasicBlock *BB : RPOT) {
BasicBlockState *BBS = Tracker.getBasicBlockState(BB);
+ if (!BBS)
+ continue;
+
// We destructively modify AvailableIn as we traverse the block instruction
// by instruction.
AvailableValueSet &AvailableSet = BBS->AvailableIn;
@@ -448,11 +603,17 @@ void GCPtrTracker::recalculateBBsStates() {
// The AvailableIn and AvailableOut sets decrease as we iterate.
while (!Worklist.empty()) {
const BasicBlock *BB = Worklist.pop_back_val();
- BasicBlockState *BBS = BlockMap[BB];
+ BasicBlockState *BBS = getBasicBlockState(BB);
+ if (!BBS)
+ continue; // Ignore dead successors.
size_t OldInCount = BBS->AvailableIn.size();
- for (const BasicBlock *PBB : predecessors(BB))
- set_intersect(BBS->AvailableIn, BlockMap[PBB]->AvailableOut);
+ for (const_pred_iterator PredIt(BB), End(BB, true); PredIt != End; ++PredIt) {
+ const BasicBlock *PBB = *PredIt;
+ BasicBlockState *PBBS = getBasicBlockState(PBB);
+ if (PBBS && !CD.isDeadEdge(&CFGDeadness::getEdge(PredIt)))
+ set_intersect(BBS->AvailableIn, PBBS->AvailableOut);
+ }
assert(OldInCount >= BBS->AvailableIn.size() && "invariant!");
@@ -491,6 +652,10 @@ bool GCPtrTracker::removeValidUnrelocatedDefs(const BasicBlock *BB,
bool HasUnrelocatedInputs = false;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
const BasicBlock *InBB = PN->getIncomingBlock(i);
+ if (!isMapped(InBB) ||
+ !CD.hasLiveIncomingEdge(PN, InBB))
+ continue; // Skip dead block or dead edge.
+
const Value *InValue = PN->getIncomingValue(i);
if (isNotExclusivelyConstantDerived(InValue)) {
@@ -535,16 +700,16 @@ bool GCPtrTracker::removeValidUnrelocatedDefs(const BasicBlock *BB,
Contribution.erase(&I);
PoisonedDefs.erase(&I);
ValidUnrelocatedDefs.insert(&I);
- DEBUG(dbgs() << "Removing urelocated " << I << " from Contribution of "
- << BB->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Removing urelocated " << I
+ << " from Contribution of " << BB->getName() << "\n");
ContributionChanged = true;
} else if (PoisonedPointerDef) {
// Mark pointer as poisoned, remove its def from Contribution and trigger
// update of all successors.
Contribution.erase(&I);
PoisonedDefs.insert(&I);
- DEBUG(dbgs() << "Removing poisoned " << I << " from Contribution of "
- << BB->getName() << "\n");
+ LLVM_DEBUG(dbgs() << "Removing poisoned " << I << " from Contribution of "
+ << BB->getName() << "\n");
ContributionChanged = true;
} else {
bool Cleared = false;
@@ -560,15 +725,18 @@ void GCPtrTracker::gatherDominatingDefs(const BasicBlock *BB,
const DominatorTree &DT) {
DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)];
+ assert(DTN && "Unreachable blocks are ignored");
while (DTN->getIDom()) {
DTN = DTN->getIDom();
- const auto &Defs = BlockMap[DTN->getBlock()]->Contribution;
+ auto BBS = getBasicBlockState(DTN->getBlock());
+ assert(BBS && "immediate dominator cannot be dead for a live block");
+ const auto &Defs = BBS->Contribution;
Result.insert(Defs.begin(), Defs.end());
// If this block is 'Cleared', then nothing LiveIn to this block can be
// available after this block completes. Note: This turns out to be
// really important for reducing memory consuption of the initial available
// sets and thus peak memory usage by this verifier.
- if (BlockMap[DTN->getBlock()]->Cleared)
+ if (BBS->Cleared)
return;
}
@@ -594,11 +762,11 @@ void GCPtrTracker::transferBlock(const BasicBlock *BB, BasicBlockState &BBS,
AvailableOut = std::move(Temp);
}
- DEBUG(dbgs() << "Transfered block " << BB->getName() << " from ";
- PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end());
- dbgs() << " to ";
- PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end());
- dbgs() << "\n";);
+ LLVM_DEBUG(dbgs() << "Transfered block " << BB->getName() << " from ";
+ PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end());
+ dbgs() << " to ";
+ PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end());
+ dbgs() << "\n";);
}
void GCPtrTracker::transferInstruction(const Instruction &I, bool &Cleared,
@@ -617,10 +785,15 @@ void InstructionVerifier::verifyInstruction(
if (containsGCPtrType(PN->getType()))
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
const BasicBlock *InBB = PN->getIncomingBlock(i);
+ const BasicBlockState *InBBS = Tracker->getBasicBlockState(InBB);
+ if (!InBBS ||
+ !Tracker->hasLiveIncomingEdge(PN, InBB))
+ continue; // Skip dead block or dead edge.
+
const Value *InValue = PN->getIncomingValue(i);
if (isNotExclusivelyConstantDerived(InValue) &&
- !Tracker->getBasicBlockState(InBB)->AvailableOut.count(InValue))
+ !InBBS->AvailableOut.count(InValue))
reportInvalidUse(*InValue, *PN);
}
} else if (isa<CmpInst>(I) &&
@@ -697,12 +870,14 @@ void InstructionVerifier::reportInvalidUse(const Value &V,
AnyInvalidUses = true;
}
-static void Verify(const Function &F, const DominatorTree &DT) {
- DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n");
+static void Verify(const Function &F, const DominatorTree &DT,
+ const CFGDeadness &CD) {
+ LLVM_DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName()
+ << "\n");
if (PrintOnly)
dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n";
- GCPtrTracker Tracker(F, DT);
+ GCPtrTracker Tracker(F, DT, CD);
// We now have all the information we need to decide if the use of a heap
// reference is legal or not, given our safepoint semantics.
diff --git a/contrib/llvm/lib/IR/Type.cpp b/contrib/llvm/lib/IR/Type.cpp
index 20e9c2b5fff2..83016496ff7e 100644
--- a/contrib/llvm/lib/IR/Type.cpp
+++ b/contrib/llvm/lib/IR/Type.cpp
@@ -60,9 +60,9 @@ bool Type::isIntegerTy(unsigned Bitwidth) const {
bool Type::canLosslesslyBitCastTo(Type *Ty) const {
// Identity cast means no change so return true
- if (this == Ty)
+ if (this == Ty)
return true;
-
+
// They are not convertible unless they are at least first class types
if (!this->isFirstClassType() || !Ty->isFirstClassType())
return false;
@@ -240,7 +240,7 @@ PointerType *Type::getInt64PtrTy(LLVMContext &C, unsigned AS) {
IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
assert(NumBits >= MIN_INT_BITS && "bitwidth too small");
assert(NumBits <= MAX_INT_BITS && "bitwidth too large");
-
+
// Check for the built-in integer types
switch (NumBits) {
case 1: return cast<IntegerType>(Type::getInt1Ty(C));
@@ -252,12 +252,12 @@ IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) {
default:
break;
}
-
+
IntegerType *&Entry = C.pImpl->IntegerTypes[NumBits];
if (!Entry)
Entry = new (C.pImpl->TypeAllocator) IntegerType(C, NumBits);
-
+
return Entry;
}
@@ -333,7 +333,7 @@ bool FunctionType::isValidArgumentType(Type *ArgTy) {
// Primitive Constructors.
-StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes,
+StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes,
bool isPacked) {
LLVMContextImpl *pImpl = Context.pImpl;
AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked);
@@ -355,7 +355,7 @@ StructType *StructType::get(LLVMContext &Context, ArrayRef<Type*> ETypes,
void StructType::setBody(ArrayRef<Type*> Elements, bool isPacked) {
assert(isOpaque() && "Struct body already set!");
-
+
setSubclassData(getSubclassData() | SCDB_HasBody);
if (isPacked)
setSubclassData(getSubclassData() | SCDB_Packed);
@@ -391,7 +391,7 @@ void StructType::setName(StringRef Name) {
}
return;
}
-
+
// Look up the entry for the name.
auto IterBool =
getContext().pImpl->NamedStructTypes.insert(std::make_pair(Name, this));
@@ -402,7 +402,7 @@ void StructType::setName(StringRef Name) {
TempStr.push_back('.');
raw_svector_ostream TmpStream(TempStr);
unsigned NameSize = Name.size();
-
+
do {
TempStr.resize(NameSize + 1);
TmpStream << getContext().pImpl->NamedStructTypesUniqueID++;
@@ -569,7 +569,7 @@ ArrayType *ArrayType::get(Type *ElementType, uint64_t NumElements) {
assert(isValidElementType(ElementType) && "Invalid type for array element!");
LLVMContextImpl *pImpl = ElementType->getContext().pImpl;
- ArrayType *&Entry =
+ ArrayType *&Entry =
pImpl->ArrayTypes[std::make_pair(ElementType, NumElements)];
if (!Entry)
@@ -617,9 +617,9 @@ bool VectorType::isValidElementType(Type *ElemTy) {
PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) {
assert(EltTy && "Can't get a pointer to <null> type!");
assert(isValidElementType(EltTy) && "Invalid type for pointer element!");
-
+
LLVMContextImpl *CImpl = EltTy->getContext().pImpl;
-
+
// Since AddressSpace #0 is the common case, we special case it.
PointerType *&Entry = AddressSpace == 0 ? CImpl->PointerTypes[EltTy]
: CImpl->ASPointerTypes[std::make_pair(EltTy, AddressSpace)];
diff --git a/contrib/llvm/lib/IR/TypeFinder.cpp b/contrib/llvm/lib/IR/TypeFinder.cpp
index b39678a013fb..e9af78c71bfd 100644
--- a/contrib/llvm/lib/IR/TypeFinder.cpp
+++ b/contrib/llvm/lib/IR/TypeFinder.cpp
@@ -33,18 +33,16 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
OnlyNamed = onlyNamed;
// Get types from global variables.
- for (Module::const_global_iterator I = M.global_begin(),
- E = M.global_end(); I != E; ++I) {
- incorporateType(I->getType());
- if (I->hasInitializer())
- incorporateValue(I->getInitializer());
+ for (const auto &G : M.globals()) {
+ incorporateType(G.getType());
+ if (G.hasInitializer())
+ incorporateValue(G.getInitializer());
}
// Get types from aliases.
- for (Module::const_alias_iterator I = M.alias_begin(),
- E = M.alias_end(); I != E; ++I) {
- incorporateType(I->getType());
- if (const Value *Aliasee = I->getAliasee())
+ for (const auto &A : M.aliases()) {
+ incorporateType(A.getType());
+ if (const Value *Aliasee = A.getAliasee())
incorporateValue(Aliasee);
}
@@ -57,9 +55,8 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
incorporateValue(U.get());
// First incorporate the arguments.
- for (Function::const_arg_iterator AI = FI.arg_begin(), AE = FI.arg_end();
- AI != AE; ++AI)
- incorporateValue(&*AI);
+ for (const auto &A : FI.args())
+ incorporateValue(&A);
for (const BasicBlock &BB : FI)
for (const Instruction &I : BB) {
@@ -68,26 +65,21 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
// Incorporate non-instruction operand types. (We are incorporating all
// instructions with this loop.)
- for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
- OI != OE; ++OI)
- if (*OI && !isa<Instruction>(OI))
- incorporateValue(*OI);
+ for (const auto &O : I.operands())
+ if (&*O && !isa<Instruction>(&*O))
+ incorporateValue(&*O);
// Incorporate types hiding in metadata.
I.getAllMetadataOtherThanDebugLoc(MDForInst);
- for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
- incorporateMDNode(MDForInst[i].second);
-
+ for (const auto &MD : MDForInst)
+ incorporateMDNode(MD.second);
MDForInst.clear();
}
}
- for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
- E = M.named_metadata_end(); I != E; ++I) {
- const NamedMDNode *NMD = &*I;
- for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
- incorporateMDNode(NMD->getOperand(i));
- }
+ for (const auto &NMD : M.named_metadata())
+ for (const auto &MDOp : NMD.operands())
+ incorporateMDNode(MDOp);
}
void TypeFinder::clear() {
@@ -150,9 +142,8 @@ void TypeFinder::incorporateValue(const Value *V) {
// Look in operands for types.
const User *U = cast<User>(V);
- for (Constant::const_op_iterator I = U->op_begin(),
- E = U->op_end(); I != E;++I)
- incorporateValue(*I);
+ for (const auto &I : U->operands())
+ incorporateValue(&*I);
}
/// incorporateMDNode - This method is used to walk the operands of an MDNode to
@@ -163,8 +154,7 @@ void TypeFinder::incorporateMDNode(const MDNode *V) {
return;
// Look in operands for types.
- for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) {
- Metadata *Op = V->getOperand(i);
+ for (Metadata *Op : V->operands()) {
if (!Op)
continue;
if (auto *N = dyn_cast<MDNode>(Op)) {
diff --git a/contrib/llvm/lib/IR/Value.cpp b/contrib/llvm/lib/IR/Value.cpp
index 163c785f5d76..295d6ecf0db0 100644
--- a/contrib/llvm/lib/IR/Value.cpp
+++ b/contrib/llvm/lib/IR/Value.cpp
@@ -39,6 +39,10 @@
using namespace llvm;
+static cl::opt<unsigned> NonGlobalValueMaxNameSize(
+ "non-global-value-max-name-size", cl::Hidden, cl::init(1024),
+ cl::desc("Maximum size for the name of non-global values."));
+
//===----------------------------------------------------------------------===//
// Value Class
//===----------------------------------------------------------------------===//
@@ -244,6 +248,11 @@ void Value::setNameImpl(const Twine &NewName) {
if (getName() == NameRef)
return;
+ // Cap the size of non-GlobalValue names.
+ if (NameRef.size() > NonGlobalValueMaxNameSize && !isa<GlobalValue>(this))
+ NameRef =
+ NameRef.substr(0, std::max(1u, (unsigned)NonGlobalValueMaxNameSize));
+
assert(!getType()->isVoidTy() && "Cannot assign a name to void values!");
// Get the symbol table to update for this object.
@@ -456,41 +465,12 @@ void Value::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) {
}
}
-void Value::replaceUsesExceptBlockAddr(Value *New) {
- SmallSetVector<Constant *, 4> Constants;
- use_iterator UI = use_begin(), E = use_end();
- for (; UI != E;) {
- Use &U = *UI;
- ++UI;
-
- if (isa<BlockAddress>(U.getUser()))
- continue;
-
- // Must handle Constants specially, we cannot call replaceUsesOfWith on a
- // constant because they are uniqued.
- if (auto *C = dyn_cast<Constant>(U.getUser())) {
- if (!isa<GlobalValue>(C)) {
- // Save unique users to avoid processing operand replacement
- // more than once.
- Constants.insert(C);
- continue;
- }
- }
-
- U.set(New);
- }
-
- // Process operand replacement of saved constants.
- for (auto *C : Constants)
- C->handleOperandChange(this, New);
-}
-
namespace {
// Various metrics for how much to strip off of pointers.
enum PointerStripKind {
PSK_ZeroIndices,
PSK_ZeroIndicesAndAliases,
- PSK_ZeroIndicesAndAliasesAndBarriers,
+ PSK_ZeroIndicesAndAliasesAndInvariantGroups,
PSK_InBoundsConstantIndices,
PSK_InBounds
};
@@ -509,7 +489,7 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
if (auto *GEP = dyn_cast<GEPOperator>(V)) {
switch (StripKind) {
case PSK_ZeroIndicesAndAliases:
- case PSK_ZeroIndicesAndAliasesAndBarriers:
+ case PSK_ZeroIndicesAndAliasesAndInvariantGroups:
case PSK_ZeroIndices:
if (!GEP->hasAllZeroIndices())
return V;
@@ -537,11 +517,12 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) {
V = RV;
continue;
}
- // The result of invariant.group.barrier must alias it's argument,
+ // The result of launder.invariant.group must alias it's argument,
// but it can't be marked with returned attribute, that's why it needs
// special case.
- if (StripKind == PSK_ZeroIndicesAndAliasesAndBarriers &&
- CS.getIntrinsicID() == Intrinsic::invariant_group_barrier) {
+ if (StripKind == PSK_ZeroIndicesAndAliasesAndInvariantGroups &&
+ (CS.getIntrinsicID() == Intrinsic::launder_invariant_group ||
+ CS.getIntrinsicID() == Intrinsic::strip_invariant_group)) {
V = CS.getArgOperand(0);
continue;
}
@@ -567,8 +548,8 @@ const Value *Value::stripInBoundsConstantOffsets() const {
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
}
-const Value *Value::stripPointerCastsAndBarriers() const {
- return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndBarriers>(
+const Value *Value::stripPointerCastsAndInvariantGroups() const {
+ return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndInvariantGroups>(
this);
}
@@ -578,9 +559,9 @@ Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
if (!getType()->isPointerTy())
return this;
- assert(Offset.getBitWidth() == DL.getPointerSizeInBits(cast<PointerType>(
+ assert(Offset.getBitWidth() == DL.getIndexSizeInBits(cast<PointerType>(
getType())->getAddressSpace()) &&
- "The offset must have exactly as many bits as our pointer.");
+ "The offset bit width does not match the DL specification.");
// Even though we don't look through PHI nodes, we could be called on an
// instruction in an unreachable block, which may be on a cycle.
@@ -676,6 +657,10 @@ unsigned Value::getPointerAlignment(const DataLayout &DL) const {
unsigned Align = 0;
if (auto *GO = dyn_cast<GlobalObject>(this)) {
+ // Don't make any assumptions about function pointer alignment. Some
+ // targets use the LSBs to store additional information.
+ if (isa<Function>(GO))
+ return 0;
Align = GO->getAlignment();
if (Align == 0) {
if (auto *GVar = dyn_cast<GlobalVariable>(GO)) {
diff --git a/contrib/llvm/lib/IR/ValueSymbolTable.cpp b/contrib/llvm/lib/IR/ValueSymbolTable.cpp
index 0da1990c3a3f..0a7f2803cd4c 100644
--- a/contrib/llvm/lib/IR/ValueSymbolTable.cpp
+++ b/contrib/llvm/lib/IR/ValueSymbolTable.cpp
@@ -14,6 +14,7 @@
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
@@ -74,7 +75,8 @@ void ValueSymbolTable::reinsertValue(Value* V) {
// Try inserting the name, assuming it won't conflict.
if (vmap.insert(V->getValueName())) {
- //DEBUG(dbgs() << " Inserted value: " << V->getValueName() << ": " << *V << "\n");
+ // LLVM_DEBUG(dbgs() << " Inserted value: " << V->getValueName() << ": " <<
+ // *V << "\n");
return;
}
@@ -89,7 +91,7 @@ void ValueSymbolTable::reinsertValue(Value* V) {
}
void ValueSymbolTable::removeValueName(ValueName *V) {
- //DEBUG(dbgs() << " Removing Value: " << V->getKeyData() << "\n");
+ // LLVM_DEBUG(dbgs() << " Removing Value: " << V->getKeyData() << "\n");
// Remove the value from the symbol table.
vmap.remove(V);
}
@@ -101,7 +103,7 @@ ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) {
// In the common case, the name is not already in the symbol table.
auto IterBool = vmap.insert(std::make_pair(Name, V));
if (IterBool.second) {
- //DEBUG(dbgs() << " Inserted value: " << Entry.getKeyData() << ": "
+ // LLVM_DEBUG(dbgs() << " Inserted value: " << Entry.getKeyData() << ": "
// << *V << "\n");
return &*IterBool.first;
}
diff --git a/contrib/llvm/lib/IR/ValueTypes.cpp b/contrib/llvm/lib/IR/ValueTypes.cpp
deleted file mode 100644
index 22f9fe7a66d7..000000000000
--- a/contrib/llvm/lib/IR/ValueTypes.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-//===----------- ValueTypes.cpp - Implementation of EVT methods -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements methods in the CodeGen/ValueTypes.h header.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/IR/DerivedTypes.h"
-#include "llvm/IR/Type.h"
-#include "llvm/Support/ErrorHandling.h"
-using namespace llvm;
-
-EVT EVT::changeExtendedTypeToInteger() const {
- LLVMContext &Context = LLVMTy->getContext();
- return getIntegerVT(Context, getSizeInBits());
-}
-
-EVT EVT::changeExtendedVectorElementTypeToInteger() const {
- LLVMContext &Context = LLVMTy->getContext();
- EVT IntTy = getIntegerVT(Context, getScalarSizeInBits());
- return getVectorVT(Context, IntTy, getVectorNumElements());
-}
-
-EVT EVT::getExtendedIntegerVT(LLVMContext &Context, unsigned BitWidth) {
- EVT VT;
- VT.LLVMTy = IntegerType::get(Context, BitWidth);
- assert(VT.isExtended() && "Type is not extended!");
- return VT;
-}
-
-EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT,
- unsigned NumElements) {
- EVT ResultVT;
- ResultVT.LLVMTy = VectorType::get(VT.getTypeForEVT(Context), NumElements);
- assert(ResultVT.isExtended() && "Type is not extended!");
- return ResultVT;
-}
-
-bool EVT::isExtendedFloatingPoint() const {
- assert(isExtended() && "Type is not extended!");
- return LLVMTy->isFPOrFPVectorTy();
-}
-
-bool EVT::isExtendedInteger() const {
- assert(isExtended() && "Type is not extended!");
- return LLVMTy->isIntOrIntVectorTy();
-}
-
-bool EVT::isExtendedScalarInteger() const {
- assert(isExtended() && "Type is not extended!");
- return LLVMTy->isIntegerTy();
-}
-
-bool EVT::isExtendedVector() const {
- assert(isExtended() && "Type is not extended!");
- return LLVMTy->isVectorTy();
-}
-
-bool EVT::isExtended16BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 16;
-}
-
-bool EVT::isExtended32BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 32;
-}
-
-bool EVT::isExtended64BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 64;
-}
-
-bool EVT::isExtended128BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 128;
-}
-
-bool EVT::isExtended256BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 256;
-}
-
-bool EVT::isExtended512BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 512;
-}
-
-bool EVT::isExtended1024BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 1024;
-}
-
-bool EVT::isExtended2048BitVector() const {
- return isExtendedVector() && getExtendedSizeInBits() == 2048;
-}
-
-EVT EVT::getExtendedVectorElementType() const {
- assert(isExtended() && "Type is not extended!");
- return EVT::getEVT(cast<VectorType>(LLVMTy)->getElementType());
-}
-
-unsigned EVT::getExtendedVectorNumElements() const {
- assert(isExtended() && "Type is not extended!");
- return cast<VectorType>(LLVMTy)->getNumElements();
-}
-
-unsigned EVT::getExtendedSizeInBits() const {
- assert(isExtended() && "Type is not extended!");
- if (IntegerType *ITy = dyn_cast<IntegerType>(LLVMTy))
- return ITy->getBitWidth();
- if (VectorType *VTy = dyn_cast<VectorType>(LLVMTy))
- return VTy->getBitWidth();
- llvm_unreachable("Unrecognized extended type!");
-}
-
-/// getEVTString - This function returns value type as a string, e.g. "i32".
-std::string EVT::getEVTString() const {
- switch (V.SimpleTy) {
- default:
- if (isVector())
- return "v" + utostr(getVectorNumElements()) +
- getVectorElementType().getEVTString();
- if (isInteger())
- return "i" + utostr(getSizeInBits());
- llvm_unreachable("Invalid EVT!");
- case MVT::i1: return "i1";
- case MVT::i8: return "i8";
- case MVT::i16: return "i16";
- case MVT::i32: return "i32";
- case MVT::i64: return "i64";
- case MVT::i128: return "i128";
- case MVT::f16: return "f16";
- case MVT::f32: return "f32";
- case MVT::f64: return "f64";
- case MVT::f80: return "f80";
- case MVT::f128: return "f128";
- case MVT::ppcf128: return "ppcf128";
- case MVT::isVoid: return "isVoid";
- case MVT::Other: return "ch";
- case MVT::Glue: return "glue";
- case MVT::x86mmx: return "x86mmx";
- case MVT::v1i1: return "v1i1";
- case MVT::v2i1: return "v2i1";
- case MVT::v4i1: return "v4i1";
- case MVT::v8i1: return "v8i1";
- case MVT::v16i1: return "v16i1";
- case MVT::v32i1: return "v32i1";
- case MVT::v64i1: return "v64i1";
- case MVT::v128i1: return "v128i1";
- case MVT::v512i1: return "v512i1";
- case MVT::v1024i1: return "v1024i1";
- case MVT::v1i8: return "v1i8";
- case MVT::v2i8: return "v2i8";
- case MVT::v4i8: return "v4i8";
- case MVT::v8i8: return "v8i8";
- case MVT::v16i8: return "v16i8";
- case MVT::v32i8: return "v32i8";
- case MVT::v64i8: return "v64i8";
- case MVT::v128i8: return "v128i8";
- case MVT::v256i8: return "v256i8";
- case MVT::v1i16: return "v1i16";
- case MVT::v2i16: return "v2i16";
- case MVT::v4i16: return "v4i16";
- case MVT::v8i16: return "v8i16";
- case MVT::v16i16: return "v16i16";
- case MVT::v32i16: return "v32i16";
- case MVT::v64i16: return "v64i16";
- case MVT::v128i16: return "v128i16";
- case MVT::v1i32: return "v1i32";
- case MVT::v2i32: return "v2i32";
- case MVT::v4i32: return "v4i32";
- case MVT::v8i32: return "v8i32";
- case MVT::v16i32: return "v16i32";
- case MVT::v32i32: return "v32i32";
- case MVT::v64i32: return "v64i32";
- case MVT::v1i64: return "v1i64";
- case MVT::v2i64: return "v2i64";
- case MVT::v4i64: return "v4i64";
- case MVT::v8i64: return "v8i64";
- case MVT::v16i64: return "v16i64";
- case MVT::v32i64: return "v32i64";
- case MVT::v1i128: return "v1i128";
- case MVT::v1f32: return "v1f32";
- case MVT::v2f32: return "v2f32";
- case MVT::v2f16: return "v2f16";
- case MVT::v4f16: return "v4f16";
- case MVT::v8f16: return "v8f16";
- case MVT::v4f32: return "v4f32";
- case MVT::v8f32: return "v8f32";
- case MVT::v16f32: return "v16f32";
- case MVT::v1f64: return "v1f64";
- case MVT::v2f64: return "v2f64";
- case MVT::v4f64: return "v4f64";
- case MVT::v8f64: return "v8f64";
- case MVT::Metadata:return "Metadata";
- case MVT::Untyped: return "Untyped";
- }
-}
-
-/// getTypeForEVT - This method returns an LLVM type corresponding to the
-/// specified EVT. For integer types, this returns an unsigned type. Note
-/// that this will abort for types that cannot be represented.
-Type *EVT::getTypeForEVT(LLVMContext &Context) const {
- switch (V.SimpleTy) {
- default:
- assert(isExtended() && "Type is not extended!");
- return LLVMTy;
- case MVT::isVoid: return Type::getVoidTy(Context);
- case MVT::i1: return Type::getInt1Ty(Context);
- case MVT::i8: return Type::getInt8Ty(Context);
- case MVT::i16: return Type::getInt16Ty(Context);
- case MVT::i32: return Type::getInt32Ty(Context);
- case MVT::i64: return Type::getInt64Ty(Context);
- case MVT::i128: return IntegerType::get(Context, 128);
- case MVT::f16: return Type::getHalfTy(Context);
- case MVT::f32: return Type::getFloatTy(Context);
- case MVT::f64: return Type::getDoubleTy(Context);
- case MVT::f80: return Type::getX86_FP80Ty(Context);
- case MVT::f128: return Type::getFP128Ty(Context);
- case MVT::ppcf128: return Type::getPPC_FP128Ty(Context);
- case MVT::x86mmx: return Type::getX86_MMXTy(Context);
- case MVT::v1i1: return VectorType::get(Type::getInt1Ty(Context), 1);
- case MVT::v2i1: return VectorType::get(Type::getInt1Ty(Context), 2);
- case MVT::v4i1: return VectorType::get(Type::getInt1Ty(Context), 4);
- case MVT::v8i1: return VectorType::get(Type::getInt1Ty(Context), 8);
- case MVT::v16i1: return VectorType::get(Type::getInt1Ty(Context), 16);
- case MVT::v32i1: return VectorType::get(Type::getInt1Ty(Context), 32);
- case MVT::v64i1: return VectorType::get(Type::getInt1Ty(Context), 64);
- case MVT::v128i1: return VectorType::get(Type::getInt1Ty(Context), 128);
- case MVT::v512i1: return VectorType::get(Type::getInt1Ty(Context), 512);
- case MVT::v1024i1: return VectorType::get(Type::getInt1Ty(Context), 1024);
- case MVT::v1i8: return VectorType::get(Type::getInt8Ty(Context), 1);
- case MVT::v2i8: return VectorType::get(Type::getInt8Ty(Context), 2);
- case MVT::v4i8: return VectorType::get(Type::getInt8Ty(Context), 4);
- case MVT::v8i8: return VectorType::get(Type::getInt8Ty(Context), 8);
- case MVT::v16i8: return VectorType::get(Type::getInt8Ty(Context), 16);
- case MVT::v32i8: return VectorType::get(Type::getInt8Ty(Context), 32);
- case MVT::v64i8: return VectorType::get(Type::getInt8Ty(Context), 64);
- case MVT::v128i8: return VectorType::get(Type::getInt8Ty(Context), 128);
- case MVT::v256i8: return VectorType::get(Type::getInt8Ty(Context), 256);
- case MVT::v1i16: return VectorType::get(Type::getInt16Ty(Context), 1);
- case MVT::v2i16: return VectorType::get(Type::getInt16Ty(Context), 2);
- case MVT::v4i16: return VectorType::get(Type::getInt16Ty(Context), 4);
- case MVT::v8i16: return VectorType::get(Type::getInt16Ty(Context), 8);
- case MVT::v16i16: return VectorType::get(Type::getInt16Ty(Context), 16);
- case MVT::v32i16: return VectorType::get(Type::getInt16Ty(Context), 32);
- case MVT::v64i16: return VectorType::get(Type::getInt16Ty(Context), 64);
- case MVT::v128i16: return VectorType::get(Type::getInt16Ty(Context), 128);
- case MVT::v1i32: return VectorType::get(Type::getInt32Ty(Context), 1);
- case MVT::v2i32: return VectorType::get(Type::getInt32Ty(Context), 2);
- case MVT::v4i32: return VectorType::get(Type::getInt32Ty(Context), 4);
- case MVT::v8i32: return VectorType::get(Type::getInt32Ty(Context), 8);
- case MVT::v16i32: return VectorType::get(Type::getInt32Ty(Context), 16);
- case MVT::v32i32: return VectorType::get(Type::getInt32Ty(Context), 32);
- case MVT::v64i32: return VectorType::get(Type::getInt32Ty(Context), 64);
- case MVT::v1i64: return VectorType::get(Type::getInt64Ty(Context), 1);
- case MVT::v2i64: return VectorType::get(Type::getInt64Ty(Context), 2);
- case MVT::v4i64: return VectorType::get(Type::getInt64Ty(Context), 4);
- case MVT::v8i64: return VectorType::get(Type::getInt64Ty(Context), 8);
- case MVT::v16i64: return VectorType::get(Type::getInt64Ty(Context), 16);
- case MVT::v32i64: return VectorType::get(Type::getInt64Ty(Context), 32);
- case MVT::v1i128: return VectorType::get(Type::getInt128Ty(Context), 1);
- case MVT::v2f16: return VectorType::get(Type::getHalfTy(Context), 2);
- case MVT::v4f16: return VectorType::get(Type::getHalfTy(Context), 4);
- case MVT::v8f16: return VectorType::get(Type::getHalfTy(Context), 8);
- case MVT::v1f32: return VectorType::get(Type::getFloatTy(Context), 1);
- case MVT::v2f32: return VectorType::get(Type::getFloatTy(Context), 2);
- case MVT::v4f32: return VectorType::get(Type::getFloatTy(Context), 4);
- case MVT::v8f32: return VectorType::get(Type::getFloatTy(Context), 8);
- case MVT::v16f32: return VectorType::get(Type::getFloatTy(Context), 16);
- case MVT::v1f64: return VectorType::get(Type::getDoubleTy(Context), 1);
- case MVT::v2f64: return VectorType::get(Type::getDoubleTy(Context), 2);
- case MVT::v4f64: return VectorType::get(Type::getDoubleTy(Context), 4);
- case MVT::v8f64: return VectorType::get(Type::getDoubleTy(Context), 8);
- case MVT::Metadata: return Type::getMetadataTy(Context);
- }
-}
-
-/// Return the value type corresponding to the specified type. This returns all
-/// pointers as MVT::iPTR. If HandleUnknown is true, unknown types are returned
-/// as Other, otherwise they are invalid.
-MVT MVT::getVT(Type *Ty, bool HandleUnknown){
- switch (Ty->getTypeID()) {
- default:
- if (HandleUnknown) return MVT(MVT::Other);
- llvm_unreachable("Unknown type!");
- case Type::VoidTyID:
- return MVT::isVoid;
- case Type::IntegerTyID:
- return getIntegerVT(cast<IntegerType>(Ty)->getBitWidth());
- case Type::HalfTyID: return MVT(MVT::f16);
- case Type::FloatTyID: return MVT(MVT::f32);
- case Type::DoubleTyID: return MVT(MVT::f64);
- case Type::X86_FP80TyID: return MVT(MVT::f80);
- case Type::X86_MMXTyID: return MVT(MVT::x86mmx);
- case Type::FP128TyID: return MVT(MVT::f128);
- case Type::PPC_FP128TyID: return MVT(MVT::ppcf128);
- case Type::PointerTyID: return MVT(MVT::iPTR);
- case Type::VectorTyID: {
- VectorType *VTy = cast<VectorType>(Ty);
- return getVectorVT(
- getVT(VTy->getElementType(), false), VTy->getNumElements());
- }
- }
-}
-
-/// getEVT - Return the value type corresponding to the specified type. This
-/// returns all pointers as MVT::iPTR. If HandleUnknown is true, unknown types
-/// are returned as Other, otherwise they are invalid.
-EVT EVT::getEVT(Type *Ty, bool HandleUnknown){
- switch (Ty->getTypeID()) {
- default:
- return MVT::getVT(Ty, HandleUnknown);
- case Type::IntegerTyID:
- return getIntegerVT(Ty->getContext(), cast<IntegerType>(Ty)->getBitWidth());
- case Type::VectorTyID: {
- VectorType *VTy = cast<VectorType>(Ty);
- return getVectorVT(Ty->getContext(), getEVT(VTy->getElementType(), false),
- VTy->getNumElements());
- }
- }
-}
diff --git a/contrib/llvm/lib/IR/Verifier.cpp b/contrib/llvm/lib/IR/Verifier.cpp
index 1754f7d45011..e5231bb78a36 100644
--- a/contrib/llvm/lib/IR/Verifier.cpp
+++ b/contrib/llvm/lib/IR/Verifier.cpp
@@ -55,6 +55,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -206,7 +207,7 @@ private:
template <typename... Ts> void WriteTs() {}
public:
- /// \brief A check failed, so printout out the condition and the message.
+ /// A check failed, so printout out the condition and the message.
///
/// This provides a nice place to put a breakpoint if you want to see why
/// something is not correct.
@@ -216,7 +217,7 @@ public:
Broken = true;
}
- /// \brief A check failed (with values to print).
+ /// A check failed (with values to print).
///
/// This calls the Message-only version so that the above is easier to set a
/// breakpoint on.
@@ -254,14 +255,14 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
DominatorTree DT;
- /// \brief When verifying a basic block, keep track of all of the
+ /// When verifying a basic block, keep track of all of the
/// instructions we have seen so far.
///
/// This allows us to do efficient dominance checks for the case when an
/// instruction has an operand that is an instruction in the same block.
SmallPtrSet<Instruction *, 16> InstsInThisBlock;
- /// \brief Keep track of the metadata nodes that have been checked already.
+ /// Keep track of the metadata nodes that have been checked already.
SmallPtrSet<const Metadata *, 32> MDNodes;
/// Keep track which DISubprogram is attached to which function.
@@ -270,10 +271,10 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// Track all DICompileUnits visited.
SmallPtrSet<const Metadata *, 2> CUVisited;
- /// \brief The result type for a landingpad.
+ /// The result type for a landingpad.
Type *LandingPadResultTy;
- /// \brief Whether we've seen a call to @llvm.localescape in this function
+ /// Whether we've seen a call to @llvm.localescape in this function
/// already.
bool SawFrameEscape;
@@ -408,6 +409,7 @@ private:
void visitModuleFlag(const MDNode *Op,
DenseMap<const MDString *, const MDNode *> &SeenIDs,
SmallVectorImpl<const MDNode *> &Requirements);
+ void visitModuleFlagCGProfileEntry(const MDOperand &MDO);
void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
@@ -466,6 +468,7 @@ private:
void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS);
void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI);
void visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII);
+ void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI);
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
void visitAtomicRMWInst(AtomicRMWInst &RMWI);
void visitFenceInst(FenceInst &FI);
@@ -565,10 +568,24 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
if (GV.isDeclarationForLinker())
Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV);
- if (GV.hasDLLImportStorageClass())
+ if (GV.hasDLLImportStorageClass()) {
Assert(!GV.isDSOLocal(),
"GlobalValue with DLLImport Storage is dso_local!", &GV);
+ Assert((GV.isDeclaration() && GV.hasExternalLinkage()) ||
+ GV.hasAvailableExternallyLinkage(),
+ "Global is marked as dllimport, but not external", &GV);
+ }
+
+ if (GV.hasLocalLinkage())
+ Assert(GV.isDSOLocal(),
+ "GlobalValue with private or internal linkage must be dso_local!",
+ &GV);
+
+ if (!GV.hasDefaultVisibility() && !GV.hasExternalWeakLinkage())
+ Assert(GV.isDSOLocal(),
+ "GlobalValue with non default visibility must be dso_local!", &GV);
+
forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {
if (const Instruction *I = dyn_cast<Instruction>(V)) {
if (!I->getParent() || !I->getParent()->getParent())
@@ -655,11 +672,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
}
}
- Assert(!GV.hasDLLImportStorageClass() ||
- (GV.isDeclaration() && GV.hasExternalLinkage()) ||
- GV.hasAvailableExternallyLinkage(),
- "Global is marked as dllimport, but not external", &GV);
-
// Visit any debug info attachments.
SmallVector<MDNode *, 1> MDs;
GV.getMetadata(LLVMContext::MD_dbg, MDs);
@@ -858,7 +870,12 @@ void Verifier::visitDIScope(const DIScope &N) {
void Verifier::visitDISubrange(const DISubrange &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
- AssertDI(N.getCount() >= -1, "invalid subrange count", &N);
+ auto Count = N.getCount();
+ AssertDI(Count, "Count must either be a signed constant or a DIVariable",
+ &N);
+ AssertDI(!Count.is<ConstantInt*>() ||
+ Count.get<ConstantInt*>()->getSExtValue() >= -1,
+ "invalid subrange count", &N);
}
void Verifier::visitDIEnumerator(const DIEnumerator &N) {
@@ -905,9 +922,12 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
}
}
+/// Detect mutually exclusive flags.
static bool hasConflictingReferenceFlags(unsigned Flags) {
- return (Flags & DINode::FlagLValueReference) &&
- (Flags & DINode::FlagRValueReference);
+ return ((Flags & DINode::FlagLValueReference) &&
+ (Flags & DINode::FlagRValueReference)) ||
+ ((Flags & DINode::FlagTypePassByValue) &&
+ (Flags & DINode::FlagTypePassByReference));
}
void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) {
@@ -927,7 +947,8 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getTag() == dwarf::DW_TAG_structure_type ||
N.getTag() == dwarf::DW_TAG_union_type ||
N.getTag() == dwarf::DW_TAG_enumeration_type ||
- N.getTag() == dwarf::DW_TAG_class_type,
+ N.getTag() == dwarf::DW_TAG_class_type ||
+ N.getTag() == dwarf::DW_TAG_variant_part,
"invalid tag", &N);
AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope());
@@ -940,6 +961,14 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
N.getRawVTableHolder());
AssertDI(!hasConflictingReferenceFlags(N.getFlags()),
"invalid reference flags", &N);
+
+ if (N.isVector()) {
+ const DINodeArray Elements = N.getElements();
+ AssertDI(Elements.size() == 1 &&
+ Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,
+ "invalid vector, expected one element of type subrange", &N);
+ }
+
if (auto *Params = N.getRawTemplateParams())
visitTemplateParams(N, *Params);
@@ -948,6 +977,11 @@ void Verifier::visitDICompositeType(const DICompositeType &N) {
AssertDI(N.getFile() && !N.getFile()->getFilename().empty(),
"class/union requires a filename", &N, N.getFile());
}
+
+ if (auto *D = N.getRawDiscriminator()) {
+ AssertDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,
+ "discriminator can only appear on variant part");
+ }
}
void Verifier::visitDISubroutineType(const DISubroutineType &N) {
@@ -964,8 +998,23 @@ void Verifier::visitDISubroutineType(const DISubroutineType &N) {
void Verifier::visitDIFile(const DIFile &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N);
- AssertDI((N.getChecksumKind() != DIFile::CSK_None ||
- N.getChecksum().empty()), "invalid checksum kind", &N);
+ Optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum();
+ if (Checksum) {
+ AssertDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,
+ "invalid checksum kind", &N);
+ size_t Size;
+ switch (Checksum->Kind) {
+ case DIFile::CSK_MD5:
+ Size = 32;
+ break;
+ case DIFile::CSK_SHA1:
+ Size = 40;
+ break;
+ }
+ AssertDI(Checksum->Value.size() == Size, "invalid checksum length", &N);
+ AssertDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,
+ "invalid checksum", &N);
+ }
}
void Verifier::visitDICompileUnit(const DICompileUnit &N) {
@@ -1038,12 +1087,13 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
if (auto *S = N.getRawDeclaration())
AssertDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),
"invalid subprogram declaration", &N, S);
- if (auto *RawVars = N.getRawVariables()) {
- auto *Vars = dyn_cast<MDTuple>(RawVars);
- AssertDI(Vars, "invalid variable list", &N, RawVars);
- for (Metadata *Op : Vars->operands()) {
- AssertDI(Op && isa<DILocalVariable>(Op), "invalid local variable", &N,
- Vars, Op);
+ if (auto *RawNode = N.getRawRetainedNodes()) {
+ auto *Node = dyn_cast<MDTuple>(RawNode);
+ AssertDI(Node, "invalid retained nodes list", &N, RawNode);
+ for (Metadata *Op : Node->operands()) {
+ AssertDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),
+ "invalid retained nodes, expected DILocalVariable or DILabel",
+ &N, Node, Op);
}
}
AssertDI(!hasConflictingReferenceFlags(N.getFlags()),
@@ -1175,6 +1225,17 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) {
"local variable requires a valid scope", &N, N.getRawScope());
}
+void Verifier::visitDILabel(const DILabel &N) {
+ if (auto *S = N.getRawScope())
+ AssertDI(isa<DIScope>(S), "invalid scope", &N, S);
+ if (auto *F = N.getRawFile())
+ AssertDI(isa<DIFile>(F), "invalid file", &N, F);
+
+ AssertDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N);
+ AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
+ "label requires a valid scope", &N, N.getRawScope());
+}
+
void Verifier::visitDIExpression(const DIExpression &N) {
AssertDI(N.isValid(), "invalid expression", &N);
}
@@ -1351,12 +1412,35 @@ Verifier::visitModuleFlag(const MDNode *Op,
Assert(M.getNamedMetadata("llvm.linker.options"),
"'Linker Options' named metadata no longer supported");
}
+
+ if (ID->getString() == "CG Profile") {
+ for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands())
+ visitModuleFlagCGProfileEntry(MDO);
+ }
+}
+
+void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) {
+ auto CheckFunction = [&](const MDOperand &FuncMDO) {
+ if (!FuncMDO)
+ return;
+ auto F = dyn_cast<ValueAsMetadata>(FuncMDO);
+ Assert(F && isa<Function>(F->getValue()), "expected a Function or null",
+ FuncMDO);
+ };
+ auto Node = dyn_cast_or_null<MDNode>(MDO);
+ Assert(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO);
+ CheckFunction(Node->getOperand(0));
+ CheckFunction(Node->getOperand(1));
+ auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2));
+ Assert(Count && Count->getType()->isIntegerTy(),
+ "expected an integer constant", Node->getOperand(2));
}
/// Return true if this attribute kind only applies to functions.
static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
switch (Kind) {
case Attribute::NoReturn:
+ case Attribute::NoCfCheck:
case Attribute::NoUnwind:
case Attribute::NoInline:
case Attribute::AlwaysInline:
@@ -1365,6 +1449,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::StackProtectReq:
case Attribute::StackProtectStrong:
case Attribute::SafeStack:
+ case Attribute::ShadowCallStack:
case Attribute::NoRedZone:
case Attribute::NoImplicitFloat:
case Attribute::Naked:
@@ -1382,6 +1467,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
case Attribute::Builtin:
case Attribute::NoBuiltin:
case Attribute::Cold:
+ case Attribute::OptForFuzzing:
case Attribute::OptimizeNone:
case Attribute::JumpTable:
case Attribute::Convergent:
@@ -1692,8 +1778,11 @@ void Verifier::verifyFunctionMetadata(
"expected string with name of the !prof annotation", MD);
MDString *MDS = cast<MDString>(MD->getOperand(0));
StringRef ProfName = MDS->getString();
- Assert(ProfName.equals("function_entry_count"),
- "first operand should be 'function_entry_count'", MD);
+ Assert(ProfName.equals("function_entry_count") ||
+ ProfName.equals("synthetic_function_entry_count"),
+ "first operand should be 'function_entry_count'"
+ " or 'synthetic_function_entry_count'",
+ MD);
// Check second operand.
Assert(MD->getOperand(1) != nullptr, "second operand should not be null",
@@ -2151,11 +2240,6 @@ void Verifier::visitFunction(const Function &F) {
Assert(false, "Invalid user of intrinsic instruction!", U);
}
- Assert(!F.hasDLLImportStorageClass() ||
- (F.isDeclaration() && F.hasExternalLinkage()) ||
- F.hasAvailableExternallyLinkage(),
- "Function is marked as dllimport, but not external.", &F);
-
auto *N = F.getSubprogram();
HasDebugInfo = (N != nullptr);
if (!HasDebugInfo)
@@ -2209,7 +2293,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
if (isa<PHINode>(BB.front())) {
SmallVector<BasicBlock*, 8> Preds(pred_begin(&BB), pred_end(&BB));
SmallVector<std::pair<BasicBlock*, Value*>, 8> Values;
- std::sort(Preds.begin(), Preds.end());
+ llvm::sort(Preds.begin(), Preds.end());
for (const PHINode &PN : BB.phis()) {
// Ensure that PHI nodes have at least one entry!
Assert(PN.getNumIncomingValues() != 0,
@@ -2227,7 +2311,7 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
Values.push_back(
std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i)));
- std::sort(Values.begin(), Values.end());
+ llvm::sort(Values.begin(), Values.end());
for (unsigned i = 0, e = Values.size(); i != e; ++i) {
// Check to make sure that if there is more than one entry for a
@@ -2819,17 +2903,20 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
Function *F = CI.getParent()->getParent();
FunctionType *CallerTy = F->getFunctionType();
FunctionType *CalleeTy = CI.getFunctionType();
- Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),
- "cannot guarantee tail call due to mismatched parameter counts", &CI);
+ if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) {
+ Assert(CallerTy->getNumParams() == CalleeTy->getNumParams(),
+ "cannot guarantee tail call due to mismatched parameter counts",
+ &CI);
+ for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
+ Assert(
+ isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),
+ "cannot guarantee tail call due to mismatched parameter types", &CI);
+ }
+ }
Assert(CallerTy->isVarArg() == CalleeTy->isVarArg(),
"cannot guarantee tail call due to mismatched varargs", &CI);
Assert(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()),
"cannot guarantee tail call due to mismatched return types", &CI);
- for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) {
- Assert(
- isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),
- "cannot guarantee tail call due to mismatched parameter types", &CI);
- }
// - The calling conventions of the caller and callee must match.
Assert(F->getCallingConv() == CI.getCallingConv(),
@@ -2865,7 +2952,7 @@ void Verifier::verifyMustTailCall(CallInst &CI) {
// Check the return.
ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next);
- Assert(Ret, "musttail call must be precede a ret with an optional bitcast",
+ Assert(Ret, "musttail call must precede a ret with an optional bitcast",
&CI);
Assert(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal,
"musttail call result must be returned", Ret);
@@ -3119,8 +3206,7 @@ void Verifier::visitLoadInst(LoadInst &LI) {
"Load cannot have Release ordering", &LI);
Assert(LI.getAlignment() != 0,
"Atomic load must specify explicit alignment", &LI);
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
- ElTy->isFloatingPointTy(),
+ Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),
"atomic load operand must have integer, pointer, or floating point "
"type!",
ElTy, &LI);
@@ -3148,8 +3234,7 @@ void Verifier::visitStoreInst(StoreInst &SI) {
"Store cannot have Acquire ordering", &SI);
Assert(SI.getAlignment() != 0,
"Atomic store must specify explicit alignment", &SI);
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy() ||
- ElTy->isFloatingPointTy(),
+ Assert(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),
"atomic store operand must have integer, pointer, or floating point "
"type!",
ElTy, &SI);
@@ -3240,9 +3325,8 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType());
Assert(PTy, "First cmpxchg operand must be a pointer.", &CXI);
Type *ElTy = PTy->getElementType();
- Assert(ElTy->isIntegerTy() || ElTy->isPointerTy(),
- "cmpxchg operand must have integer or pointer type",
- ElTy, &CXI);
+ Assert(ElTy->isIntOrPtrTy(),
+ "cmpxchg operand must have integer or pointer type", ElTy, &CXI);
checkAtomicMemAccessSize(ElTy, &CXI);
Assert(ElTy == CXI.getOperand(1)->getType(),
"Expected value type does not match pointer operand type!", &CXI,
@@ -4014,96 +4098,36 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;
+ case Intrinsic::dbg_label: // llvm.dbg.label
+ visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(*CS.getInstruction()));
+ break;
case Intrinsic::memcpy:
case Intrinsic::memmove:
case Intrinsic::memset: {
- ConstantInt *AlignCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
- Assert(AlignCI,
- "alignment argument of memory intrinsics must be a constant int",
- CS);
- const APInt &AlignVal = AlignCI->getValue();
- Assert(AlignCI->isZero() || AlignVal.isPowerOf2(),
- "alignment argument of memory intrinsics must be a power of 2", CS);
- Assert(isa<ConstantInt>(CS.getArgOperand(4)),
- "isvolatile argument of memory intrinsics must be a constant int",
- CS);
- break;
- }
- case Intrinsic::memcpy_element_unordered_atomic: {
- const AtomicMemCpyInst *MI = cast<AtomicMemCpyInst>(CS.getInstruction());
-
- ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
- Assert(ElementSizeCI,
- "element size of the element-wise unordered atomic memory "
- "intrinsic must be a constant int",
- CS);
- const APInt &ElementSizeVal = ElementSizeCI->getValue();
- Assert(ElementSizeVal.isPowerOf2(),
- "element size of the element-wise atomic memory intrinsic "
- "must be a power of 2",
- CS);
-
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
- uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
- Assert((Length % ElementSize) == 0,
- "constant length must be a multiple of the element size in the "
- "element-wise atomic memory intrinsic",
- CS);
- }
-
- auto IsValidAlignment = [&](uint64_t Alignment) {
- return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
+ const auto *MI = cast<MemIntrinsic>(CS.getInstruction());
+ auto IsValidAlignment = [&](unsigned Alignment) -> bool {
+ return Alignment == 0 || isPowerOf2_32(Alignment);
};
- uint64_t DstAlignment = CS.getParamAlignment(0),
- SrcAlignment = CS.getParamAlignment(1);
- Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument", CS);
- Assert(IsValidAlignment(SrcAlignment),
- "incorrect alignment of the source argument", CS);
- break;
- }
- case Intrinsic::memmove_element_unordered_atomic: {
- auto *MI = cast<AtomicMemMoveInst>(CS.getInstruction());
-
- ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
- Assert(ElementSizeCI,
- "element size of the element-wise unordered atomic memory "
- "intrinsic must be a constant int",
- CS);
- const APInt &ElementSizeVal = ElementSizeCI->getValue();
- Assert(ElementSizeVal.isPowerOf2(),
- "element size of the element-wise atomic memory intrinsic "
- "must be a power of 2",
+ Assert(IsValidAlignment(MI->getDestAlignment()),
+ "alignment of arg 0 of memory intrinsic must be 0 or a power of 2",
CS);
-
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
- uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
- Assert((Length % ElementSize) == 0,
- "constant length must be a multiple of the element size in the "
- "element-wise atomic memory intrinsic",
+ if (const auto *MTI = dyn_cast<MemTransferInst>(MI)) {
+ Assert(IsValidAlignment(MTI->getSourceAlignment()),
+ "alignment of arg 1 of memory intrinsic must be 0 or a power of 2",
CS);
}
-
- auto IsValidAlignment = [&](uint64_t Alignment) {
- return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
- };
- uint64_t DstAlignment = CS.getParamAlignment(0),
- SrcAlignment = CS.getParamAlignment(1);
- Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument", CS);
- Assert(IsValidAlignment(SrcAlignment),
- "incorrect alignment of the source argument", CS);
+ Assert(isa<ConstantInt>(CS.getArgOperand(3)),
+ "isvolatile argument of memory intrinsics must be a constant int",
+ CS);
break;
}
+ case Intrinsic::memcpy_element_unordered_atomic:
+ case Intrinsic::memmove_element_unordered_atomic:
case Intrinsic::memset_element_unordered_atomic: {
- auto *MI = cast<AtomicMemSetInst>(CS.getInstruction());
+ const auto *AMI = cast<AtomicMemIntrinsic>(CS.getInstruction());
ConstantInt *ElementSizeCI =
- dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
+ dyn_cast<ConstantInt>(AMI->getRawElementSizeInBytes());
Assert(ElementSizeCI,
"element size of the element-wise unordered atomic memory "
"intrinsic must be a constant int",
@@ -4114,9 +4138,9 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"must be a power of 2",
CS);
- if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
+ if (auto *LengthCI = dyn_cast<ConstantInt>(AMI->getLength())) {
uint64_t Length = LengthCI->getZExtValue();
- uint64_t ElementSize = MI->getElementSizeInBytes();
+ uint64_t ElementSize = AMI->getElementSizeInBytes();
Assert((Length % ElementSize) == 0,
"constant length must be a multiple of the element size in the "
"element-wise atomic memory intrinsic",
@@ -4126,9 +4150,14 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
auto IsValidAlignment = [&](uint64_t Alignment) {
return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
};
- uint64_t DstAlignment = CS.getParamAlignment(0);
+ uint64_t DstAlignment = AMI->getDestAlignment();
Assert(IsValidAlignment(DstAlignment),
"incorrect alignment of the destination argument", CS);
+ if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) {
+ uint64_t SrcAlignment = AMT->getSourceAlignment();
+ Assert(IsValidAlignment(SrcAlignment),
+ "incorrect alignment of the source argument", CS);
+ }
break;
}
case Intrinsic::gcroot:
@@ -4428,7 +4457,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
};
}
-/// \brief Carefully grab the subprogram from a local scope.
+/// Carefully grab the subprogram from a local scope.
///
/// This carefully grabs the subprogram from a local scope, avoiding the
/// built-in assertions that would typically fire.
@@ -4485,8 +4514,8 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) {
// The scopes for variables and !dbg attachments must agree.
DILocalVariable *Var = DII.getVariable();
DILocation *Loc = DII.getDebugLoc();
- Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
- &DII, BB, F);
+ AssertDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
+ &DII, BB, F);
DISubprogram *VarSP = getSubprogram(Var->getRawScope());
DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
@@ -4501,7 +4530,40 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) {
verifyFnArgs(DII);
}
+void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) {
+ AssertDI(isa<DILabel>(DLI.getRawVariable()),
+ "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,
+ DLI.getRawVariable());
+
+ // Ignore broken !dbg attachments; they're checked elsewhere.
+ if (MDNode *N = DLI.getDebugLoc().getAsMDNode())
+ if (!isa<DILocation>(N))
+ return;
+
+ BasicBlock *BB = DLI.getParent();
+ Function *F = BB ? BB->getParent() : nullptr;
+
+ // The scopes for variables and !dbg attachments must agree.
+ DILabel *Label = DLI.getLabel();
+ DILocation *Loc = DLI.getDebugLoc();
+ Assert(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",
+ &DLI, BB, F);
+
+ DISubprogram *LabelSP = getSubprogram(Label->getRawScope());
+ DISubprogram *LocSP = getSubprogram(Loc->getRawScope());
+ if (!LabelSP || !LocSP)
+ return;
+
+ AssertDI(LabelSP == LocSP, "mismatched subprogram between llvm.dbg." + Kind +
+ " label and !dbg attachment",
+ &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,
+ Loc->getScope()->getSubprogram());
+}
+
void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {
+ if (dyn_cast<DbgLabelInst>(&I))
+ return;
+
DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable());
DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());