diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-30 16:33:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-30 16:33:32 +0000 |
commit | 51315c45ff5643a27f9c84b816db54ee870ba29b (patch) | |
tree | 1d87443fa0e53d3e6b315ce25787e64be0906bf7 /contrib/llvm/lib/IR | |
parent | 6dfd050075216be8538ae375a22d30db72916f7e (diff) | |
parent | eb11fae6d08f479c0799db45860a98af528fa6e7 (diff) | |
download | src-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')
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()); |