diff options
Diffstat (limited to 'llvm/lib/IR')
45 files changed, 2402 insertions, 1663 deletions
diff --git a/llvm/lib/IR/AbstractCallSite.cpp b/llvm/lib/IR/AbstractCallSite.cpp index 6504e566ba4b..2e41799e13e9 100644 --- a/llvm/lib/IR/AbstractCallSite.cpp +++ b/llvm/lib/IR/AbstractCallSite.cpp @@ -121,7 +121,7 @@ AbstractCallSite::AbstractCallSite(const Use *U) assert(CallbackEncMD->getNumOperands() >= 2 && "Incomplete !callback metadata"); - unsigned NumCallOperands = CB->getNumArgOperands(); + unsigned NumCallOperands = CB->arg_size(); // Skip the var-arg flag at the end when reading the metadata. for (unsigned u = 0, e = CallbackEncMD->getNumOperands() - 1; u < e; u++) { Metadata *OpAsM = CallbackEncMD->getOperand(u).get(); diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 69e2d85e58fe..7734c0a8de58 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -44,7 +45,6 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalIFunc.h" -#include "llvm/IR/GlobalIndirectSymbol.h" #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" @@ -72,6 +72,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -554,16 +555,13 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) { FunctionType *FTy = cast<FunctionType>(Ty); print(FTy->getReturnType(), OS); OS << " ("; - for (FunctionType::param_iterator I = FTy->param_begin(), - E = FTy->param_end(); I != E; ++I) { - if (I != FTy->param_begin()) - OS << ", "; - print(*I, OS); - } - if (FTy->isVarArg()) { - if (FTy->getNumParams()) OS << ", "; - OS << "..."; + ListSeparator LS; + for (Type *Ty : FTy->params()) { + OS << LS; + print(Ty, OS); } + if (FTy->isVarArg()) + OS << LS << "..."; OS << ')'; return; } @@ -633,12 +631,11 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { if (STy->getNumElements() == 0) { OS << "{}"; } else { - StructType::element_iterator I = STy->element_begin(); OS << "{ "; - print(*I++, OS); - for (StructType::element_iterator E = STy->element_end(); I != E; ++I) { - OS << ", "; - print(*I, OS); + ListSeparator LS; + for (Type *Ty : STy->elements()) { + OS << LS; + print(Ty, OS); } OS << " }"; @@ -988,7 +985,7 @@ void SlotTracker::processModule() { // Add all the function attributes to the table. // FIXME: Add attributes of other objects? - AttributeSet FnAttrs = F.getAttributes().getFnAttributes(); + AttributeSet FnAttrs = F.getAttributes().getFnAttrs(); if (FnAttrs.hasAttributes()) CreateAttributeSetSlot(FnAttrs); } @@ -1029,7 +1026,7 @@ void SlotTracker::processFunction() { // target may not be linked into the optimizer. if (const auto *Call = dyn_cast<CallBase>(&I)) { // Add all the call attributes to the table. - AttributeSet Attrs = Call->getAttributes().getFnAttributes(); + AttributeSet Attrs = Call->getAttributes().getFnAttrs(); if (Attrs.hasAttributes()) CreateAttributeSetSlot(Attrs); } @@ -1277,18 +1274,38 @@ void SlotTracker::CreateTypeIdSlot(StringRef Id) { TypeIdMap[Id] = TypeIdNext++; } +namespace { +/// Common instances used by most of the printer functions. +struct AsmWriterContext { + TypePrinting *TypePrinter = nullptr; + SlotTracker *Machine = nullptr; + const Module *Context = nullptr; + + AsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M = nullptr) + : TypePrinter(TP), Machine(ST), Context(M) {} + + static AsmWriterContext &getEmpty() { + static AsmWriterContext EmptyCtx(nullptr, nullptr); + return EmptyCtx; + } + + /// A callback that will be triggered when the underlying printer + /// prints a Metadata as operand. + virtual void onWriteMetadataAsOperand(const Metadata *) {} + + virtual ~AsmWriterContext() {} +}; +} // end anonymous namespace + //===----------------------------------------------------------------------===// // AsmWriter Implementation //===----------------------------------------------------------------------===// static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context); + AsmWriterContext &WriterCtx); static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context, + AsmWriterContext &WriterCtx, bool FromValue = false); static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { @@ -1331,9 +1348,7 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { } static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, - TypePrinting &TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { if (CI->getType()->isIntegerTy(1)) { Out << (CI->getZExtValue() ? "true" : "false"); @@ -1442,36 +1457,30 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) { Out << "blockaddress("; - WriteAsOperandInternal(Out, BA->getFunction(), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, BA->getFunction(), WriterCtx); Out << ", "; - WriteAsOperandInternal(Out, BA->getBasicBlock(), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, BA->getBasicBlock(), WriterCtx); Out << ")"; return; } if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV)) { Out << "dso_local_equivalent "; - WriteAsOperandInternal(Out, Equiv->getGlobalValue(), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, Equiv->getGlobalValue(), WriterCtx); return; } if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) { Type *ETy = CA->getType()->getElementType(); Out << '['; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(0), - &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, CA->getOperand(0), WriterCtx); for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { Out << ", "; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, CA->getOperand(i), WriterCtx); } Out << ']'; return; @@ -1489,17 +1498,14 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Type *ETy = CA->getType()->getElementType(); Out << '['; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getElementAsConstant(0), - &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, CA->getElementAsConstant(0), WriterCtx); for (unsigned i = 1, e = CA->getNumElements(); i != e; ++i) { Out << ", "; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CA->getElementAsConstant(i), &TypePrinter, - Machine, Context); + WriteAsOperandInternal(Out, CA->getElementAsConstant(i), WriterCtx); } Out << ']'; return; @@ -1512,19 +1518,17 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, unsigned N = CS->getNumOperands(); if (N) { Out << ' '; - TypePrinter.print(CS->getOperand(0)->getType(), Out); + WriterCtx.TypePrinter->print(CS->getOperand(0)->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, CS->getOperand(0), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, CS->getOperand(0), WriterCtx); for (unsigned i = 1; i < N; i++) { Out << ", "; - TypePrinter.print(CS->getOperand(i)->getType(), Out); + WriterCtx.TypePrinter->print(CS->getOperand(i)->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, CS->getOperand(i), &TypePrinter, Machine, - Context); + WriteAsOperandInternal(Out, CS->getOperand(i), WriterCtx); } Out << ' '; } @@ -1539,16 +1543,14 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, auto *CVVTy = cast<FixedVectorType>(CV->getType()); Type *ETy = CVVTy->getElementType(); Out << '<'; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CV->getAggregateElement(0U), &TypePrinter, - Machine, Context); + WriteAsOperandInternal(Out, CV->getAggregateElement(0U), WriterCtx); for (unsigned i = 1, e = CVVTy->getNumElements(); i != e; ++i) { Out << ", "; - TypePrinter.print(ETy, Out); + WriterCtx.TypePrinter->print(ETy, Out); Out << ' '; - WriteAsOperandInternal(Out, CV->getAggregateElement(i), &TypePrinter, - Machine, Context); + WriteAsOperandInternal(Out, CV->getAggregateElement(i), WriterCtx); } Out << '>'; return; @@ -1584,7 +1586,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Optional<unsigned> InRangeOp; if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) { - TypePrinter.print(GEP->getSourceElementType(), Out); + WriterCtx.TypePrinter->print(GEP->getSourceElementType(), Out); Out << ", "; InRangeOp = GEP->getInRangeIndex(); if (InRangeOp) @@ -1594,9 +1596,9 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) { if (InRangeOp && unsigned(OI - CE->op_begin()) == *InRangeOp) Out << "inrange "; - TypePrinter.print((*OI)->getType(), Out); + WriterCtx.TypePrinter->print((*OI)->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, *OI, &TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, *OI, WriterCtx); if (OI+1 != CE->op_end()) Out << ", "; } @@ -1609,7 +1611,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, if (CE->isCast()) { Out << " to "; - TypePrinter.print(CE->getType(), Out); + WriterCtx.TypePrinter->print(CE->getType(), Out); } if (CE->getOpcode() == Instruction::ShuffleVector) @@ -1623,8 +1625,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, } static void writeMDTuple(raw_ostream &Out, const MDTuple *Node, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!{"; for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) { const Metadata *MD = Node->getOperand(mi); @@ -1632,11 +1633,12 @@ static void writeMDTuple(raw_ostream &Out, const MDTuple *Node, Out << "null"; else if (auto *MDV = dyn_cast<ValueAsMetadata>(MD)) { Value *V = MDV->getValue(); - TypePrinter->print(V->getType(), Out); + WriterCtx.TypePrinter->print(V->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, V, WriterCtx); } else { - WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, MD, WriterCtx); + WriterCtx.onWriteMetadataAsOperand(MD); } if (mi + 1 != me) Out << ", "; @@ -1665,15 +1667,12 @@ raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) { struct MDFieldPrinter { raw_ostream &Out; FieldSeparator FS; - TypePrinting *TypePrinter = nullptr; - SlotTracker *Machine = nullptr; - const Module *Context = nullptr; + AsmWriterContext &WriterCtx; - explicit MDFieldPrinter(raw_ostream &Out) : Out(Out) {} - MDFieldPrinter(raw_ostream &Out, TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) - : Out(Out), TypePrinter(TypePrinter), Machine(Machine), Context(Context) { - } + explicit MDFieldPrinter(raw_ostream &Out) + : Out(Out), WriterCtx(AsmWriterContext::getEmpty()) {} + MDFieldPrinter(raw_ostream &Out, AsmWriterContext &Ctx) + : Out(Out), WriterCtx(Ctx) {} void printTag(const DINode *N); void printMacinfoType(const DIMacroNode *N); @@ -1734,14 +1733,13 @@ void MDFieldPrinter::printString(StringRef Name, StringRef Value, } static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { if (!MD) { Out << "null"; return; } - WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, MD, WriterCtx); + WriterCtx.onWriteMetadataAsOperand(MD); } void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD, @@ -1750,7 +1748,7 @@ void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD, return; Out << FS << Name << ": "; - writeMetadataAsOperand(Out, MD, TypePrinter, Machine, Context); + writeMetadataAsOperand(Out, MD, WriterCtx); } template <class IntTy> @@ -1763,7 +1761,7 @@ void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) { void MDFieldPrinter::printAPInt(StringRef Name, const APInt &Int, bool IsUnsigned, bool ShouldSkipZero) { - if (ShouldSkipZero && Int.isNullValue()) + if (ShouldSkipZero && Int.isZero()) return; Out << FS << Name << ": "; @@ -1847,10 +1845,9 @@ void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value, } static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!GenericDINode("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printTag(N); Printer.printString("header", N->getHeader()); if (N->getNumDwarfOperands()) { @@ -1858,7 +1855,7 @@ static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N, FieldSeparator IFS; for (auto &I : N->dwarf_operands()) { Out << IFS; - writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context); + writeMetadataAsOperand(Out, I, WriterCtx); } Out << "}"; } @@ -1866,10 +1863,9 @@ static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N, } static void writeDILocation(raw_ostream &Out, const DILocation *DL, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DILocation("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); // Always output the line, since 0 is a relevant and important value for it. Printer.printInt("line", DL->getLine(), /* ShouldSkipZero */ false); Printer.printInt("column", DL->getColumn()); @@ -1881,10 +1877,9 @@ static void writeDILocation(raw_ostream &Out, const DILocation *DL, } static void writeDISubrange(raw_ostream &Out, const DISubrange *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DISubrange("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); auto *Count = N->getRawCountNode(); if (auto *CE = dyn_cast_or_null<ConstantAsMetadata>(Count)) { @@ -1923,18 +1918,15 @@ static void writeDISubrange(raw_ostream &Out, const DISubrange *N, } static void writeDIGenericSubrange(raw_ostream &Out, const DIGenericSubrange *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIGenericSubrange("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); auto IsConstant = [&](Metadata *Bound) -> bool { if (auto *BE = dyn_cast_or_null<DIExpression>(Bound)) { - return BE->isConstant() - ? DIExpression::SignedOrUnsignedConstant::SignedConstant == - *BE->isConstant() - : false; + return BE->isConstant() && + DIExpression::SignedOrUnsignedConstant::SignedConstant == + *BE->isConstant(); } return false; }; @@ -1977,7 +1969,7 @@ static void writeDIGenericSubrange(raw_ostream &Out, const DIGenericSubrange *N, } static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N, - TypePrinting *, SlotTracker *, const Module *) { + AsmWriterContext &) { Out << "!DIEnumerator("; MDFieldPrinter Printer(Out); Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false); @@ -1989,7 +1981,7 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N, } static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N, - TypePrinting *, SlotTracker *, const Module *) { + AsmWriterContext &) { Out << "!DIBasicType("; MDFieldPrinter Printer(Out); if (N->getTag() != dwarf::DW_TAG_base_type) @@ -2004,10 +1996,9 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N, } static void writeDIStringType(raw_ostream &Out, const DIStringType *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIStringType("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); if (N->getTag() != dwarf::DW_TAG_string_type) Printer.printTag(N); Printer.printString("name", N->getName()); @@ -2021,10 +2012,9 @@ static void writeDIStringType(raw_ostream &Out, const DIStringType *N, } static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIDerivedType("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printTag(N); Printer.printString("name", N->getName()); Printer.printMetadata("scope", N->getRawScope()); @@ -2040,14 +2030,14 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N, if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace, /* ShouldSkipZero */ false); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DICompositeType("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printTag(N); Printer.printString("name", N->getName()); Printer.printMetadata("scope", N->getRawScope()); @@ -2073,14 +2063,14 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N, /* ShouldSkipZero */ false); else Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DISubroutineType("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printDIFlags("flags", N->getFlags()); Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString); Printer.printMetadata("types", N->getRawTypeArray(), @@ -2088,8 +2078,7 @@ static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N, Out << ")"; } -static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *, - SlotTracker *, const Module *) { +static void writeDIFile(raw_ostream &Out, const DIFile *N, AsmWriterContext &) { Out << "!DIFile("; MDFieldPrinter Printer(Out); Printer.printString("filename", N->getFilename(), @@ -2105,10 +2094,9 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *, } static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DICompileUnit("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printDwarfEnum("language", N->getSourceLanguage(), dwarf::LanguageString, /* ShouldSkipZero */ false); Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); @@ -2136,10 +2124,9 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N, } static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DISubprogram("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printString("linkageName", N->getLinkageName()); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); @@ -2159,14 +2146,14 @@ static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N, Printer.printMetadata("declaration", N->getRawDeclaration()); Printer.printMetadata("retainedNodes", N->getRawRetainedNodes()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DILexicalBlock("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); @@ -2176,11 +2163,9 @@ static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N, static void writeDILexicalBlockFile(raw_ostream &Out, const DILexicalBlockFile *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DILexicalBlockFile("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printMetadata("file", N->getRawFile()); Printer.printInt("discriminator", N->getDiscriminator(), @@ -2189,10 +2174,9 @@ static void writeDILexicalBlockFile(raw_ostream &Out, } static void writeDINamespace(raw_ostream &Out, const DINamespace *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DINamespace("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printBool("exportSymbols", N->getExportSymbols(), false); @@ -2200,10 +2184,9 @@ static void writeDINamespace(raw_ostream &Out, const DINamespace *N, } static void writeDICommonBlock(raw_ostream &Out, const DICommonBlock *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DICommonBlock("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("scope", N->getRawScope(), false); Printer.printMetadata("declaration", N->getRawDecl(), false); Printer.printString("name", N->getName()); @@ -2213,10 +2196,9 @@ static void writeDICommonBlock(raw_ostream &Out, const DICommonBlock *N, } static void writeDIMacro(raw_ostream &Out, const DIMacro *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIMacro("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMacinfoType(N); Printer.printInt("line", N->getLine()); Printer.printString("name", N->getName()); @@ -2225,10 +2207,9 @@ static void writeDIMacro(raw_ostream &Out, const DIMacro *N, } static void writeDIMacroFile(raw_ostream &Out, const DIMacroFile *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIMacroFile("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printInt("line", N->getLine()); Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false); Printer.printMetadata("nodes", N->getRawElements()); @@ -2236,10 +2217,9 @@ static void writeDIMacroFile(raw_ostream &Out, const DIMacroFile *N, } static void writeDIModule(raw_ostream &Out, const DIModule *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIModule("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printString("name", N->getName()); Printer.printString("configMacros", N->getConfigurationMacros()); @@ -2251,14 +2231,11 @@ static void writeDIModule(raw_ostream &Out, const DIModule *N, Out << ")"; } - static void writeDITemplateTypeParameter(raw_ostream &Out, const DITemplateTypeParameter *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DITemplateTypeParameter("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false); Printer.printBool("defaulted", N->isDefault(), /* Default= */ false); @@ -2267,11 +2244,9 @@ static void writeDITemplateTypeParameter(raw_ostream &Out, static void writeDITemplateValueParameter(raw_ostream &Out, const DITemplateValueParameter *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DITemplateValueParameter("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); if (N->getTag() != dwarf::DW_TAG_template_value_parameter) Printer.printTag(N); Printer.printString("name", N->getName()); @@ -2282,10 +2257,9 @@ static void writeDITemplateValueParameter(raw_ostream &Out, } static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIGlobalVariable("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printString("linkageName", N->getLinkageName()); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); @@ -2297,14 +2271,14 @@ static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N, Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printInt("align", N->getAlignInBits()); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DILocalVariable("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printInt("arg", N->getArg()); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); @@ -2313,14 +2287,14 @@ static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N, Printer.printMetadata("type", N->getRawType()); Printer.printDIFlags("flags", N->getFlags()); Printer.printInt("align", N->getAlignInBits()); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } static void writeDILabel(raw_ostream &Out, const DILabel *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DILabel("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printString("name", N->getName()); Printer.printMetadata("file", N->getRawFile()); @@ -2329,8 +2303,7 @@ static void writeDILabel(raw_ostream &Out, const DILabel *N, } static void writeDIExpression(raw_ostream &Out, const DIExpression *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIExpression("; FieldSeparator FS; if (N->isValid()) { @@ -2355,37 +2328,34 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N, } static void writeDIArgList(raw_ostream &Out, const DIArgList *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context, bool FromValue = false) { + AsmWriterContext &WriterCtx, + bool FromValue = false) { assert(FromValue && "Unexpected DIArgList metadata outside of value argument"); Out << "!DIArgList("; FieldSeparator FS; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); for (Metadata *Arg : N->getArgs()) { Out << FS; - WriteAsOperandInternal(Out, Arg, TypePrinter, Machine, Context, true); + WriteAsOperandInternal(Out, Arg, WriterCtx, true); } Out << ")"; } static void writeDIGlobalVariableExpression(raw_ostream &Out, const DIGlobalVariableExpression *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIGlobalVariableExpression("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printMetadata("var", N->getVariable()); Printer.printMetadata("expr", N->getExpression()); Out << ")"; } static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N, - TypePrinting *TypePrinter, SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIObjCProperty("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printString("name", N->getName()); Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); @@ -2397,23 +2367,21 @@ static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N, } static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *N, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context) { + AsmWriterContext &WriterCtx) { Out << "!DIImportedEntity("; - MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + MDFieldPrinter Printer(Out, WriterCtx); Printer.printTag(N); Printer.printString("name", N->getName()); Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); Printer.printMetadata("entity", N->getRawEntity()); Printer.printMetadata("file", N->getRawFile()); Printer.printInt("line", N->getLine()); + Printer.printMetadata("elements", N->getRawElements()); Out << ")"; } static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &Ctx) { if (Node->isDistinct()) Out << "distinct "; else if (Node->isTemporary()) @@ -2424,7 +2392,7 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, llvm_unreachable("Expected uniquable MDNode"); #define HANDLE_MDNODE_LEAF(CLASS) \ case Metadata::CLASS##Kind: \ - write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \ + write##CLASS(Out, cast<CLASS>(Node), Ctx); \ break; #include "llvm/IR/Metadata.def" } @@ -2433,9 +2401,7 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, // Full implementation of printing a Value as an operand with support for // TypePrinting, etc. static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { + AsmWriterContext &WriterCtx) { if (V->hasName()) { PrintLLVMName(Out, V); return; @@ -2443,8 +2409,8 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, const Constant *CV = dyn_cast<Constant>(V); if (CV && !isa<GlobalValue>(CV)) { - assert(TypePrinter && "Constants require TypePrinting!"); - WriteConstantInternal(Out, CV, *TypePrinter, Machine, Context); + assert(WriterCtx.TypePrinter && "Constants require TypePrinting!"); + WriteConstantInternal(Out, CV, WriterCtx); return; } @@ -2468,13 +2434,14 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, } if (auto *MD = dyn_cast<MetadataAsValue>(V)) { - WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine, - Context, /* FromValue */ true); + WriteAsOperandInternal(Out, MD->getMetadata(), WriterCtx, + /* FromValue */ true); return; } char Prefix = '%'; int Slot; + auto *Machine = WriterCtx.Machine; // If we have a SlotTracker, use it. if (Machine) { if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { @@ -2513,30 +2480,30 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, } static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, - TypePrinting *TypePrinter, - SlotTracker *Machine, const Module *Context, + AsmWriterContext &WriterCtx, bool FromValue) { // Write DIExpressions and DIArgLists inline when used as a value. Improves // readability of debug info intrinsics. if (const DIExpression *Expr = dyn_cast<DIExpression>(MD)) { - writeDIExpression(Out, Expr, TypePrinter, Machine, Context); + writeDIExpression(Out, Expr, WriterCtx); return; } if (const DIArgList *ArgList = dyn_cast<DIArgList>(MD)) { - writeDIArgList(Out, ArgList, TypePrinter, Machine, Context, FromValue); + writeDIArgList(Out, ArgList, WriterCtx, FromValue); return; } if (const MDNode *N = dyn_cast<MDNode>(MD)) { std::unique_ptr<SlotTracker> MachineStorage; - if (!Machine) { - MachineStorage = std::make_unique<SlotTracker>(Context); - Machine = MachineStorage.get(); + SaveAndRestore<SlotTracker *> SARMachine(WriterCtx.Machine); + if (!WriterCtx.Machine) { + MachineStorage = std::make_unique<SlotTracker>(WriterCtx.Context); + WriterCtx.Machine = MachineStorage.get(); } - int Slot = Machine->getMetadataSlot(N); + int Slot = WriterCtx.Machine->getMetadataSlot(N); if (Slot == -1) { if (const DILocation *Loc = dyn_cast<DILocation>(N)) { - writeDILocation(Out, Loc, TypePrinter, Machine, Context); + writeDILocation(Out, Loc, WriterCtx); return; } // Give the pointer value instead of "badref", since this comes up all @@ -2555,13 +2522,13 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, } auto *V = cast<ValueAsMetadata>(MD); - assert(TypePrinter && "TypePrinter required for metadata values"); + assert(WriterCtx.TypePrinter && "TypePrinter required for metadata values"); assert((FromValue || !isa<LocalAsMetadata>(V)) && "Unexpected function-local metadata outside of value argument"); - TypePrinter->print(V->getValue()->getType(), Out); + WriterCtx.TypePrinter->print(V->getValue()->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, V->getValue(), WriterCtx); } namespace { @@ -2592,6 +2559,10 @@ public: AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, const ModuleSummaryIndex *Index, bool IsForDebug); + AsmWriterContext getContext() { + return AsmWriterContext(&TypePrinter, &Machine, TheModule); + } + void printMDNodeBody(const MDNode *MD); void printNamedMDNode(const NamedMDNode *NMD); @@ -2618,7 +2589,8 @@ public: void printTypeIdentities(); void printGlobal(const GlobalVariable *GV); - void printIndirectSymbol(const GlobalIndirectSymbol *GIS); + void printAlias(const GlobalAlias *GA); + void printIFunc(const GlobalIFunc *GI); void printComdat(const Comdat *C); void printFunction(const Function *F); void printArgument(const Argument *FA, AttributeSet Attrs); @@ -2693,7 +2665,8 @@ void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { TypePrinter.print(Operand->getType(), Out); Out << ' '; } - WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule); + auto WriterCtx = getContext(); + WriteAsOperandInternal(Out, Operand, WriterCtx); } void AssemblyWriter::writeSyncScope(const LLVMContext &Context, @@ -2752,7 +2725,8 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, } Out << ' '; // Print the operand - WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule); + auto WriterCtx = getContext(); + WriteAsOperandInternal(Out, Operand, WriterCtx); } void AssemblyWriter::writeOperandBundles(const CallBase *Call) { @@ -2776,6 +2750,7 @@ void AssemblyWriter::writeOperandBundles(const CallBase *Call) { Out << '('; bool FirstInput = true; + auto WriterCtx = getContext(); for (const auto &Input : BU.Inputs) { if (!FirstInput) Out << ", "; @@ -2783,7 +2758,7 @@ void AssemblyWriter::writeOperandBundles(const CallBase *Call) { TypePrinter.print(Input->getType(), Out); Out << " "; - WriteAsOperandInternal(Out, Input, &TypePrinter, &Machine, TheModule); + WriteAsOperandInternal(Out, Input, WriterCtx); } Out << ')'; @@ -2853,12 +2828,12 @@ void AssemblyWriter::printModule(const Module *M) { // Output all aliases. if (!M->alias_empty()) Out << "\n"; for (const GlobalAlias &GA : M->aliases()) - printIndirectSymbol(&GA); + printAlias(&GA); // Output all ifuncs. if (!M->ifunc_empty()) Out << "\n"; for (const GlobalIFunc &GI : M->ifuncs()) - printIndirectSymbol(&GI); + printIFunc(&GI); // Output all of the functions. for (const Function &F : *M) { @@ -3198,19 +3173,9 @@ static const char *getVisibilityName(GlobalValue::VisibilityTypes Vis) { void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) { Out << ", insts: " << FS->instCount(); + if (FS->fflags().anyFlagSet()) + Out << ", " << FS->fflags(); - FunctionSummary::FFlags FFlags = FS->fflags(); - if (FFlags.ReadNone | FFlags.ReadOnly | FFlags.NoRecurse | - FFlags.ReturnDoesNotAlias | FFlags.NoInline | FFlags.AlwaysInline) { - Out << ", funcFlags: ("; - Out << "readNone: " << FFlags.ReadNone; - Out << ", readOnly: " << FFlags.ReadOnly; - Out << ", noRecurse: " << FFlags.NoRecurse; - Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias; - Out << ", noInline: " << FFlags.NoInline; - Out << ", alwaysInline: " << FFlags.AlwaysInline; - Out << ")"; - } if (!FS->calls().empty()) { Out << ", calls: ("; FieldSeparator IFS; @@ -3453,7 +3418,7 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { assert(!isa<DIArgList>(Op) && "DIArgLists should not appear in NamedMDNodes"); if (auto *Expr = dyn_cast<DIExpression>(Op)) { - writeDIExpression(Out, Expr, nullptr, nullptr, nullptr); + writeDIExpression(Out, Expr, AsmWriterContext::getEmpty()); continue; } @@ -3544,7 +3509,8 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->isMaterializable()) Out << "; Materializable\n"; - WriteAsOperandInternal(Out, GV, &TypePrinter, &Machine, GV->getParent()); + AsmWriterContext WriterCtx(&TypePrinter, &Machine, GV->getParent()); + WriteAsOperandInternal(Out, GV, WriterCtx); Out << " = "; if (!GV->hasInitializer() && GV->hasExternalLinkage()) @@ -3596,49 +3562,76 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { printInfoComment(*GV); } -void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) { - if (GIS->isMaterializable()) +void AssemblyWriter::printAlias(const GlobalAlias *GA) { + if (GA->isMaterializable()) Out << "; Materializable\n"; - WriteAsOperandInternal(Out, GIS, &TypePrinter, &Machine, GIS->getParent()); + AsmWriterContext WriterCtx(&TypePrinter, &Machine, GA->getParent()); + WriteAsOperandInternal(Out, GA, WriterCtx); Out << " = "; - Out << getLinkageNameWithSpace(GIS->getLinkage()); - PrintDSOLocation(*GIS, Out); - PrintVisibility(GIS->getVisibility(), Out); - PrintDLLStorageClass(GIS->getDLLStorageClass(), Out); - PrintThreadLocalModel(GIS->getThreadLocalMode(), Out); - StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr()); + Out << getLinkageNameWithSpace(GA->getLinkage()); + PrintDSOLocation(*GA, Out); + PrintVisibility(GA->getVisibility(), Out); + PrintDLLStorageClass(GA->getDLLStorageClass(), Out); + PrintThreadLocalModel(GA->getThreadLocalMode(), Out); + StringRef UA = getUnnamedAddrEncoding(GA->getUnnamedAddr()); if (!UA.empty()) Out << UA << ' '; - if (isa<GlobalAlias>(GIS)) - Out << "alias "; - else if (isa<GlobalIFunc>(GIS)) - Out << "ifunc "; - else - llvm_unreachable("Not an alias or ifunc!"); - - TypePrinter.print(GIS->getValueType(), Out); + Out << "alias "; + TypePrinter.print(GA->getValueType(), Out); Out << ", "; - const Constant *IS = GIS->getIndirectSymbol(); - - if (!IS) { - TypePrinter.print(GIS->getType(), Out); + if (const Constant *Aliasee = GA->getAliasee()) { + writeOperand(Aliasee, !isa<ConstantExpr>(Aliasee)); + } else { + TypePrinter.print(GA->getType(), Out); Out << " <<NULL ALIASEE>>"; + } + + if (GA->hasPartition()) { + Out << ", partition \""; + printEscapedString(GA->getPartition(), Out); + Out << '"'; + } + + printInfoComment(*GA); + Out << '\n'; +} + +void AssemblyWriter::printIFunc(const GlobalIFunc *GI) { + if (GI->isMaterializable()) + Out << "; Materializable\n"; + + AsmWriterContext WriterCtx(&TypePrinter, &Machine, GI->getParent()); + WriteAsOperandInternal(Out, GI, WriterCtx); + Out << " = "; + + Out << getLinkageNameWithSpace(GI->getLinkage()); + PrintDSOLocation(*GI, Out); + PrintVisibility(GI->getVisibility(), Out); + + Out << "ifunc "; + + TypePrinter.print(GI->getValueType(), Out); + Out << ", "; + + if (const Constant *Resolver = GI->getResolver()) { + writeOperand(Resolver, !isa<ConstantExpr>(Resolver)); } else { - writeOperand(IS, !isa<ConstantExpr>(IS)); + TypePrinter.print(GI->getType(), Out); + Out << " <<NULL RESOLVER>>"; } - if (GIS->hasPartition()) { + if (GI->hasPartition()) { Out << ", partition \""; - printEscapedString(GIS->getPartition(), Out); + printEscapedString(GI->getPartition(), Out); Out << '"'; } - printInfoComment(*GIS); + printInfoComment(*GI); Out << '\n'; } @@ -3683,8 +3676,8 @@ void AssemblyWriter::printFunction(const Function *F) { Out << "; Materializable\n"; const AttributeList &Attrs = F->getAttributes(); - if (Attrs.hasAttributes(AttributeList::FunctionIndex)) { - AttributeSet AS = Attrs.getFnAttributes(); + if (Attrs.hasFnAttrs()) { + AttributeSet AS = Attrs.getFnAttrs(); std::string AttrStr; for (const Attribute &Attr : AS) { @@ -3721,11 +3714,12 @@ void AssemblyWriter::printFunction(const Function *F) { } FunctionType *FT = F->getFunctionType(); - if (Attrs.hasAttributes(AttributeList::ReturnIndex)) + if (Attrs.hasRetAttrs()) Out << Attrs.getAsString(AttributeList::ReturnIndex) << ' '; TypePrinter.print(F->getReturnType(), Out); + AsmWriterContext WriterCtx(&TypePrinter, &Machine, F->getParent()); Out << ' '; - WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent()); + WriteAsOperandInternal(Out, F, WriterCtx); Out << '('; // Loop over the arguments, printing them... @@ -3738,7 +3732,7 @@ void AssemblyWriter::printFunction(const Function *F) { // Output type... TypePrinter.print(FT->getParamType(I), Out); - AttributeSet ArgAttrs = Attrs.getParamAttributes(I); + AttributeSet ArgAttrs = Attrs.getParamAttrs(I); if (ArgAttrs.hasAttributes()) { Out << ' '; writeAttributeSet(ArgAttrs); @@ -3750,7 +3744,7 @@ void AssemblyWriter::printFunction(const Function *F) { // Insert commas as we go... the first arg doesn't get a comma if (Arg.getArgNo() != 0) Out << ", "; - printArgument(&Arg, Attrs.getParamAttributes(Arg.getArgNo())); + printArgument(&Arg, Attrs.getParamAttrs(Arg.getArgNo())); } } @@ -3770,8 +3764,8 @@ void AssemblyWriter::printFunction(const Function *F) { if (F->getAddressSpace() != 0 || !Mod || Mod->getDataLayout().getProgramAddressSpace() != 0) Out << " addrspace(" << F->getAddressSpace() << ")"; - if (Attrs.hasAttributes(AttributeList::FunctionIndex)) - Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes()); + if (Attrs.hasFnAttrs()) + Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttrs()); if (F->hasSection()) { Out << " section \""; printEscapedString(F->getSection(), Out); @@ -4127,7 +4121,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Type *RetTy = FTy->getReturnType(); const AttributeList &PAL = CI->getAttributes(); - if (PAL.hasAttributes(AttributeList::ReturnIndex)) + if (PAL.hasRetAttrs()) Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex); // Only print addrspace(N) if necessary: @@ -4142,10 +4136,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ' '; writeOperand(Operand, false); Out << '('; - for (unsigned op = 0, Eop = CI->getNumArgOperands(); op < Eop; ++op) { + for (unsigned op = 0, Eop = CI->arg_size(); op < Eop; ++op) { if (op > 0) Out << ", "; - writeParamOperand(CI->getArgOperand(op), PAL.getParamAttributes(op)); + writeParamOperand(CI->getArgOperand(op), PAL.getParamAttrs(op)); } // Emit an ellipsis if this is a musttail call in a vararg function. This @@ -4156,8 +4150,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ", ..."; Out << ')'; - if (PAL.hasAttributes(AttributeList::FunctionIndex)) - Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); + if (PAL.hasFnAttrs()) + Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttrs()); writeOperandBundles(CI); } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) { @@ -4172,7 +4166,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { PrintCallingConv(II->getCallingConv(), Out); } - if (PAL.hasAttributes(AttributeList::ReturnIndex)) + if (PAL.hasRetAttrs()) Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex); // Only print addrspace(N) if necessary: @@ -4187,15 +4181,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ' '; writeOperand(Operand, false); Out << '('; - for (unsigned op = 0, Eop = II->getNumArgOperands(); op < Eop; ++op) { + for (unsigned op = 0, Eop = II->arg_size(); op < Eop; ++op) { if (op) Out << ", "; - writeParamOperand(II->getArgOperand(op), PAL.getParamAttributes(op)); + writeParamOperand(II->getArgOperand(op), PAL.getParamAttrs(op)); } Out << ')'; - if (PAL.hasAttributes(AttributeList::FunctionIndex)) - Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); + if (PAL.hasFnAttrs()) + Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttrs()); writeOperandBundles(II); @@ -4215,7 +4209,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { PrintCallingConv(CBI->getCallingConv(), Out); } - if (PAL.hasAttributes(AttributeList::ReturnIndex)) + if (PAL.hasRetAttrs()) Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex); // If possible, print out the short form of the callbr instruction. We can @@ -4227,15 +4221,15 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ' '; writeOperand(Operand, false); Out << '('; - for (unsigned op = 0, Eop = CBI->getNumArgOperands(); op < Eop; ++op) { + for (unsigned op = 0, Eop = CBI->arg_size(); op < Eop; ++op) { if (op) Out << ", "; - writeParamOperand(CBI->getArgOperand(op), PAL.getParamAttributes(op)); + writeParamOperand(CBI->getArgOperand(op), PAL.getParamAttrs(op)); } Out << ')'; - if (PAL.hasAttributes(AttributeList::FunctionIndex)) - Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); + if (PAL.hasFnAttrs()) + Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttrs()); writeOperandBundles(CBI); @@ -4375,6 +4369,7 @@ void AssemblyWriter::printMetadataAttachments( if (MDNames.empty()) MDs[0].second->getContext().getMDKindNames(MDNames); + auto WriterCtx = getContext(); for (const auto &I : MDs) { unsigned Kind = I.first; Out << Separator; @@ -4384,7 +4379,7 @@ void AssemblyWriter::printMetadataAttachments( } else Out << "!<unknown kind #" << Kind << ">"; Out << ' '; - WriteAsOperandInternal(Out, I.second, &TypePrinter, &Machine, TheModule); + WriteAsOperandInternal(Out, I.second, WriterCtx); } } @@ -4406,7 +4401,8 @@ void AssemblyWriter::writeAllMDNodes() { } void AssemblyWriter::printMDNodeBody(const MDNode *Node) { - WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule); + auto WriterCtx = getContext(); + WriteMDNodeBodyInternal(Out, Node, WriterCtx); } void AssemblyWriter::writeAttribute(const Attribute &Attr, bool InAttrGroup) { @@ -4626,15 +4622,20 @@ void Value::print(raw_ostream &ROS, ModuleSlotTracker &MST, W.printGlobal(V); else if (const Function *F = dyn_cast<Function>(GV)) W.printFunction(F); + else if (const GlobalAlias *A = dyn_cast<GlobalAlias>(GV)) + W.printAlias(A); + else if (const GlobalIFunc *I = dyn_cast<GlobalIFunc>(GV)) + W.printIFunc(I); else - W.printIndirectSymbol(cast<GlobalIndirectSymbol>(GV)); + llvm_unreachable("Unknown GlobalValue to print out!"); } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) { V->getMetadata()->print(ROS, MST, getModuleFromVal(V)); } else if (const Constant *C = dyn_cast<Constant>(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); OS << ' '; - WriteConstantInternal(OS, C, TypePrinter, MST.getMachine(), nullptr); + AsmWriterContext WriterCtx(&TypePrinter, MST.getMachine()); + WriteConstantInternal(OS, C, WriterCtx); } else if (isa<InlineAsm>(this) || isa<Argument>(this)) { this->printAsOperand(OS, /* PrintType */ true, MST); } else { @@ -4649,7 +4650,8 @@ static bool printWithoutType(const Value &V, raw_ostream &O, SlotTracker *Machine, const Module *M) { if (V.hasName() || isa<GlobalValue>(V) || (!isa<Constant>(V) && !isa<MetadataAsValue>(V))) { - WriteAsOperandInternal(O, &V, nullptr, Machine, M); + AsmWriterContext WriterCtx(nullptr, Machine, M); + WriteAsOperandInternal(O, &V, WriterCtx); return true; } return false; @@ -4663,8 +4665,8 @@ static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType, O << ' '; } - WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(), - MST.getModule()); + AsmWriterContext WriterCtx(&TypePrinter, MST.getMachine(), MST.getModule()); + WriteAsOperandInternal(O, &V, WriterCtx); } void Value::printAsOperand(raw_ostream &O, bool PrintType, @@ -4691,22 +4693,87 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, printAsOperandImpl(*this, O, PrintType, MST); } +/// Recursive version of printMetadataImpl. +static void printMetadataImplRec(raw_ostream &ROS, const Metadata &MD, + AsmWriterContext &WriterCtx) { + formatted_raw_ostream OS(ROS); + WriteAsOperandInternal(OS, &MD, WriterCtx, /* FromValue */ true); + + auto *N = dyn_cast<MDNode>(&MD); + if (!N || isa<DIExpression>(MD) || isa<DIArgList>(MD)) + return; + + OS << " = "; + WriteMDNodeBodyInternal(OS, N, WriterCtx); +} + +namespace { +struct MDTreeAsmWriterContext : public AsmWriterContext { + unsigned Level; + // {Level, Printed string} + using EntryTy = std::pair<unsigned, std::string>; + SmallVector<EntryTy, 4> Buffer; + + // Used to break the cycle in case there is any. + SmallPtrSet<const Metadata *, 4> Visited; + + raw_ostream &MainOS; + + MDTreeAsmWriterContext(TypePrinting *TP, SlotTracker *ST, const Module *M, + raw_ostream &OS, const Metadata *InitMD) + : AsmWriterContext(TP, ST, M), Level(0U), Visited({InitMD}), MainOS(OS) {} + + void onWriteMetadataAsOperand(const Metadata *MD) override { + if (Visited.count(MD)) + return; + Visited.insert(MD); + + std::string Str; + raw_string_ostream SS(Str); + ++Level; + // A placeholder entry to memorize the correct + // position in buffer. + Buffer.emplace_back(std::make_pair(Level, "")); + unsigned InsertIdx = Buffer.size() - 1; + + printMetadataImplRec(SS, *MD, *this); + Buffer[InsertIdx].second = std::move(SS.str()); + --Level; + } + + ~MDTreeAsmWriterContext() { + for (const auto &Entry : Buffer) { + MainOS << "\n"; + unsigned NumIndent = Entry.first * 2U; + MainOS.indent(NumIndent) << Entry.second; + } + } +}; +} // end anonymous namespace + static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD, ModuleSlotTracker &MST, const Module *M, - bool OnlyAsOperand) { + bool OnlyAsOperand, bool PrintAsTree = false) { formatted_raw_ostream OS(ROS); TypePrinting TypePrinter(M); - WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M, - /* FromValue */ true); + std::unique_ptr<AsmWriterContext> WriterCtx; + if (PrintAsTree && !OnlyAsOperand) + WriterCtx = std::make_unique<MDTreeAsmWriterContext>( + &TypePrinter, MST.getMachine(), M, OS, &MD); + else + WriterCtx = + std::make_unique<AsmWriterContext>(&TypePrinter, MST.getMachine(), M); + + WriteAsOperandInternal(OS, &MD, *WriterCtx, /* FromValue */ true); auto *N = dyn_cast<MDNode>(&MD); if (OnlyAsOperand || !N || isa<DIExpression>(MD) || isa<DIArgList>(MD)) return; OS << " = "; - WriteMDNodeBodyInternal(OS, N, &TypePrinter, MST.getMachine(), M); + WriteMDNodeBodyInternal(OS, N, *WriterCtx); } void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const { @@ -4730,6 +4797,18 @@ void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST, printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false); } +void MDNode::printTree(raw_ostream &OS, const Module *M) const { + ModuleSlotTracker MST(M, true); + printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false, + /*PrintAsTree=*/true); +} + +void MDNode::printTree(raw_ostream &OS, ModuleSlotTracker &MST, + const Module *M) const { + printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false, + /*PrintAsTree=*/true); +} + void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const { SlotTracker SlotTable(this); formatted_raw_ostream OS(ROS); @@ -4781,6 +4860,15 @@ void Metadata::dump(const Module *M) const { dbgs() << '\n'; } +LLVM_DUMP_METHOD +void MDNode::dumpTree() const { dumpTree(nullptr); } + +LLVM_DUMP_METHOD +void MDNode::dumpTree(const Module *M) const { + printTree(dbgs(), M); + dbgs() << '\n'; +} + // Allow printing of ModuleSummaryIndex from the debugger. LLVM_DUMP_METHOD void ModuleSummaryIndex::dump() const { print(dbgs(), /*IsForDebug=*/true); } diff --git a/llvm/lib/IR/Assumptions.cpp b/llvm/lib/IR/Assumptions.cpp index 6498114cd60d..3d24ae062841 100644 --- a/llvm/lib/IR/Assumptions.cpp +++ b/llvm/lib/IR/Assumptions.cpp @@ -6,17 +6,23 @@ // //===----------------------------------------------------------------------===// // +// This file implements helper functions for accessing assumption infomration +// inside of the "llvm.assume" metadata. +// //===----------------------------------------------------------------------===// #include "llvm/IR/Assumptions.h" +#include "llvm/ADT/SetOperations.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" using namespace llvm; -bool llvm::hasAssumption(Function &F, - const KnownAssumptionString &AssumptionStr) { - const Attribute &A = F.getFnAttribute(AssumptionAttrKey); +namespace { +bool hasAssumption(const Attribute &A, + const KnownAssumptionString &AssumptionStr) { if (!A.isValid()) return false; assert(A.isStringAttribute() && "Expected a string attribute!"); @@ -24,9 +30,76 @@ bool llvm::hasAssumption(Function &F, SmallVector<StringRef, 8> Strings; A.getValueAsString().split(Strings, ","); - return llvm::any_of(Strings, [=](StringRef Assumption) { - return Assumption == AssumptionStr; - }); + return llvm::is_contained(Strings, AssumptionStr); +} + +DenseSet<StringRef> getAssumptions(const Attribute &A) { + if (!A.isValid()) + return DenseSet<StringRef>(); + assert(A.isStringAttribute() && "Expected a string attribute!"); + + DenseSet<StringRef> Assumptions; + SmallVector<StringRef, 8> Strings; + A.getValueAsString().split(Strings, ","); + + for (StringRef Str : Strings) + Assumptions.insert(Str); + return Assumptions; +} + +template <typename AttrSite> +bool addAssumptionsImpl(AttrSite &Site, + const DenseSet<StringRef> &Assumptions) { + if (Assumptions.empty()) + return false; + + DenseSet<StringRef> CurAssumptions = getAssumptions(Site); + + if (!set_union(CurAssumptions, Assumptions)) + return false; + + LLVMContext &Ctx = Site.getContext(); + Site.addFnAttr(llvm::Attribute::get( + Ctx, llvm::AssumptionAttrKey, + llvm::join(CurAssumptions.begin(), CurAssumptions.end(), ","))); + + return true; +} +} // namespace + +bool llvm::hasAssumption(const Function &F, + const KnownAssumptionString &AssumptionStr) { + const Attribute &A = F.getFnAttribute(AssumptionAttrKey); + return ::hasAssumption(A, AssumptionStr); +} + +bool llvm::hasAssumption(const CallBase &CB, + const KnownAssumptionString &AssumptionStr) { + if (Function *F = CB.getCalledFunction()) + if (hasAssumption(*F, AssumptionStr)) + return true; + + const Attribute &A = CB.getFnAttr(AssumptionAttrKey); + return ::hasAssumption(A, AssumptionStr); +} + +DenseSet<StringRef> llvm::getAssumptions(const Function &F) { + const Attribute &A = F.getFnAttribute(AssumptionAttrKey); + return ::getAssumptions(A); +} + +DenseSet<StringRef> llvm::getAssumptions(const CallBase &CB) { + const Attribute &A = CB.getFnAttr(AssumptionAttrKey); + return ::getAssumptions(A); +} + +bool llvm::addAssumptions(Function &F, const DenseSet<StringRef> &Assumptions) { + return ::addAssumptionsImpl(F, Assumptions); +} + +bool llvm::addAssumptions(CallBase &CB, + const DenseSet<StringRef> &Assumptions) { + return ::addAssumptionsImpl(CB, Assumptions); } StringSet<> llvm::KnownAssumptionStrings({ diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 5cd1bafccc47..f81a446d6e46 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -812,42 +812,13 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { if (!B.contains(Kind)) continue; - if (Attribute::isTypeAttrKind(Kind)) { - Attrs.push_back(Attribute::get(C, Kind, B.getTypeAttr(Kind))); - continue; - } - Attribute Attr; - switch (Kind) { - case Attribute::Alignment: - assert(B.getAlignment() && "Alignment must be set"); - Attr = Attribute::getWithAlignment(C, *B.getAlignment()); - break; - case Attribute::StackAlignment: - assert(B.getStackAlignment() && "StackAlignment must be set"); - Attr = Attribute::getWithStackAlignment(C, *B.getStackAlignment()); - break; - case Attribute::Dereferenceable: - Attr = Attribute::getWithDereferenceableBytes( - C, B.getDereferenceableBytes()); - break; - case Attribute::DereferenceableOrNull: - Attr = Attribute::getWithDereferenceableOrNullBytes( - C, B.getDereferenceableOrNullBytes()); - break; - case Attribute::AllocSize: { - auto A = B.getAllocSizeArgs(); - Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second); - break; - } - case Attribute::VScaleRange: { - auto A = B.getVScaleRangeArgs(); - Attr = Attribute::getWithVScaleRangeArgs(C, A.first, A.second); - break; - } - default: + if (Attribute::isTypeAttrKind(Kind)) + Attr = Attribute::get(C, Kind, B.getTypeAttr(Kind)); + else if (Attribute::isIntAttrKind(Kind)) + Attr = Attribute::get(C, Kind, B.getRawIntAttr(Kind)); + else Attr = Attribute::get(C, Kind); - } Attrs.push_back(Attr); } @@ -1209,33 +1180,36 @@ AttributeList AttributeList::get(LLVMContext &C, return getImpl(C, NewAttrSets); } -AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, - Attribute::AttrKind Kind) const { - if (hasAttribute(Index, Kind)) return *this; +AttributeList +AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, + Attribute::AttrKind Kind) const { + if (hasAttributeAtIndex(Index, Kind)) + return *this; AttributeSet Attrs = getAttributes(Index); // TODO: Insert at correct position and avoid sort. SmallVector<Attribute, 8> NewAttrs(Attrs.begin(), Attrs.end()); NewAttrs.push_back(Attribute::get(C, Kind)); - return setAttributes(C, Index, AttributeSet::get(C, NewAttrs)); + return setAttributesAtIndex(C, Index, AttributeSet::get(C, NewAttrs)); } -AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, - StringRef Kind, - StringRef Value) const { +AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, + StringRef Kind, + StringRef Value) const { AttrBuilder B; B.addAttribute(Kind, Value); - return addAttributes(C, Index, B); + return addAttributesAtIndex(C, Index, B); } -AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, - Attribute A) const { +AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index, + Attribute A) const { AttrBuilder B; B.addAttribute(A); - return addAttributes(C, Index, B); + return addAttributesAtIndex(C, Index, B); } -AttributeList AttributeList::setAttributes(LLVMContext &C, unsigned Index, - AttributeSet Attrs) const { +AttributeList AttributeList::setAttributesAtIndex(LLVMContext &C, + unsigned Index, + AttributeSet Attrs) const { Index = attrIdxToArrayIdx(Index); SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); if (Index >= AttrSets.size()) @@ -1244,8 +1218,9 @@ AttributeList AttributeList::setAttributes(LLVMContext &C, unsigned Index, return AttributeList::getImpl(C, AttrSets); } -AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, - const AttrBuilder &B) const { +AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C, + unsigned Index, + const AttrBuilder &B) const { if (!B.hasAttributes()) return *this; @@ -1263,7 +1238,7 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, AttrBuilder Merged(getAttributes(Index)); Merged.merge(B); - return setAttributes(C, Index, AttributeSet::get(C, Merged)); + return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged)); } AttributeList AttributeList::addParamAttribute(LLVMContext &C, @@ -1286,9 +1261,11 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C, return getImpl(C, AttrSets); } -AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, - Attribute::AttrKind Kind) const { - if (!hasAttribute(Index, Kind)) return *this; +AttributeList +AttributeList::removeAttributeAtIndex(LLVMContext &C, unsigned Index, + Attribute::AttrKind Kind) const { + if (!hasAttributeAtIndex(Index, Kind)) + return *this; Index = attrIdxToArrayIdx(Index); SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); @@ -1299,9 +1276,11 @@ AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, return getImpl(C, AttrSets); } -AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, - StringRef Kind) const { - if (!hasAttribute(Index, Kind)) return *this; +AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C, + unsigned Index, + StringRef Kind) const { + if (!hasAttributeAtIndex(Index, Kind)) + return *this; Index = attrIdxToArrayIdx(Index); SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); @@ -1313,18 +1292,19 @@ AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, } AttributeList -AttributeList::removeAttributes(LLVMContext &C, unsigned Index, - const AttrBuilder &AttrsToRemove) const { +AttributeList::removeAttributesAtIndex(LLVMContext &C, unsigned Index, + const AttrBuilder &AttrsToRemove) const { AttributeSet Attrs = getAttributes(Index); AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove); // If nothing was removed, return the original list. if (Attrs == NewAttrs) return *this; - return setAttributes(C, Index, NewAttrs); + return setAttributesAtIndex(C, Index, NewAttrs); } -AttributeList AttributeList::removeAttributes(LLVMContext &C, - unsigned WithoutIndex) const { +AttributeList +AttributeList::removeAttributesAtIndex(LLVMContext &C, + unsigned WithoutIndex) const { if (!pImpl) return {}; WithoutIndex = attrIdxToArrayIdx(WithoutIndex); @@ -1335,79 +1315,73 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, return getImpl(C, AttrSets); } -AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C, - unsigned Index, - uint64_t Bytes) const { +AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C, + uint64_t Bytes) const { AttrBuilder B; B.addDereferenceableAttr(Bytes); - return addAttributes(C, Index, B); + return addRetAttributes(C, B); } -AttributeList -AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, - uint64_t Bytes) const { +AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C, + unsigned Index, + uint64_t Bytes) const { AttrBuilder B; - B.addDereferenceableOrNullAttr(Bytes); - return addAttributes(C, Index, B); + B.addDereferenceableAttr(Bytes); + return addParamAttributes(C, Index, B); } AttributeList -AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index, - unsigned ElemSizeArg, - const Optional<unsigned> &NumElemsArg) { +AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const { AttrBuilder B; - B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); - return addAttributes(C, Index, B); + B.addDereferenceableOrNullAttr(Bytes); + return addParamAttributes(C, Index, B); } -AttributeList AttributeList::addVScaleRangeAttr(LLVMContext &C, unsigned Index, - unsigned MinValue, - unsigned MaxValue) { +AttributeList +AttributeList::addAllocSizeParamAttr(LLVMContext &C, unsigned Index, + unsigned ElemSizeArg, + const Optional<unsigned> &NumElemsArg) { AttrBuilder B; - B.addVScaleRangeAttr(MinValue, MaxValue); - return addAttributes(C, Index, B); + B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); + return addParamAttributes(C, Index, B); } //===----------------------------------------------------------------------===// // AttributeList Accessor Methods //===----------------------------------------------------------------------===// -AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const { +AttributeSet AttributeList::getParamAttrs(unsigned ArgNo) const { return getAttributes(ArgNo + FirstArgIndex); } -AttributeSet AttributeList::getRetAttributes() const { +AttributeSet AttributeList::getRetAttrs() const { return getAttributes(ReturnIndex); } -AttributeSet AttributeList::getFnAttributes() const { +AttributeSet AttributeList::getFnAttrs() const { return getAttributes(FunctionIndex); } -bool AttributeList::hasAttribute(unsigned Index, - Attribute::AttrKind Kind) const { +bool AttributeList::hasAttributeAtIndex(unsigned Index, + Attribute::AttrKind Kind) const { return getAttributes(Index).hasAttribute(Kind); } -bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const { +bool AttributeList::hasAttributeAtIndex(unsigned Index, StringRef Kind) const { return getAttributes(Index).hasAttribute(Kind); } -bool AttributeList::hasAttributes(unsigned Index) const { +bool AttributeList::hasAttributesAtIndex(unsigned Index) const { return getAttributes(Index).hasAttributes(); } -bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const { +bool AttributeList::hasFnAttr(Attribute::AttrKind Kind) const { return pImpl && pImpl->hasFnAttribute(Kind); } -bool AttributeList::hasFnAttribute(StringRef Kind) const { - return hasAttribute(AttributeList::FunctionIndex, Kind); -} - -bool AttributeList::hasParamAttribute(unsigned ArgNo, - Attribute::AttrKind Kind) const { - return hasAttribute(ArgNo + FirstArgIndex, Kind); +bool AttributeList::hasFnAttr(StringRef Kind) const { + return hasAttributeAtIndex(AttributeList::FunctionIndex, Kind); } bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, @@ -1415,12 +1389,13 @@ bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, return pImpl && pImpl->hasAttrSomewhere(Attr, Index); } -Attribute AttributeList::getAttribute(unsigned Index, - Attribute::AttrKind Kind) const { +Attribute AttributeList::getAttributeAtIndex(unsigned Index, + Attribute::AttrKind Kind) const { return getAttributes(Index).getAttribute(Kind); } -Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const { +Attribute AttributeList::getAttributeAtIndex(unsigned Index, + StringRef Kind) const { return getAttributes(Index).getAttribute(Kind); } @@ -1460,26 +1435,29 @@ Type *AttributeList::getParamElementType(unsigned Index) const { return getAttributes(Index + FirstArgIndex).getElementType(); } -MaybeAlign AttributeList::getStackAlignment(unsigned Index) const { - return getAttributes(Index).getStackAlignment(); +MaybeAlign AttributeList::getFnStackAlignment() const { + return getFnAttrs().getStackAlignment(); } -uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const { - return getAttributes(Index).getDereferenceableBytes(); +MaybeAlign AttributeList::getRetStackAlignment() const { + return getRetAttrs().getStackAlignment(); } -uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const { - return getAttributes(Index).getDereferenceableOrNullBytes(); +uint64_t AttributeList::getRetDereferenceableBytes() const { + return getRetAttrs().getDereferenceableBytes(); } -std::pair<unsigned, Optional<unsigned>> -AttributeList::getAllocSizeArgs(unsigned Index) const { - return getAttributes(Index).getAllocSizeArgs(); +uint64_t AttributeList::getParamDereferenceableBytes(unsigned Index) const { + return getParamAttrs(Index).getDereferenceableBytes(); } -std::pair<unsigned, unsigned> -AttributeList::getVScaleRangeArgs(unsigned Index) const { - return getAttributes(Index).getVScaleRangeArgs(); +uint64_t AttributeList::getRetDereferenceableOrNullBytes() const { + return getRetAttrs().getDereferenceableOrNullBytes(); +} + +uint64_t +AttributeList::getParamDereferenceableOrNullBytes(unsigned Index) const { + return getParamAttrs(Index).getDereferenceableOrNullBytes(); } std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { @@ -1520,7 +1498,7 @@ unsigned AttributeList::getNumAttrSets() const { void AttributeList::print(raw_ostream &O) const { O << "AttributeList[\n"; - for (unsigned i = index_begin(), e = index_end(); i != e; ++i) { + for (unsigned i : indexes()) { if (!getAttributes(i).hasAttributes()) continue; O << " { "; @@ -1563,15 +1541,18 @@ AttrBuilder::AttrBuilder(AttributeSet AS) { void AttrBuilder::clear() { Attrs.reset(); TargetDepAttrs.clear(); - Alignment.reset(); - StackAlignment.reset(); - DerefBytes = DerefOrNullBytes = 0; - AllocSizeArgs = 0; - VScaleRangeArgs = 0; + IntAttrs = {}; TypeAttrs = {}; } Optional<unsigned> +AttrBuilder::kindToIntIndex(Attribute::AttrKind Kind) const { + if (Attribute::isIntAttrKind(Kind)) + return Kind - Attribute::FirstIntAttr; + return None; +} + +Optional<unsigned> AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const { if (Attribute::isTypeAttrKind(Kind)) return Kind - Attribute::FirstTypeAttr; @@ -1589,18 +1570,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { if (Optional<unsigned> TypeIndex = kindToTypeIndex(Kind)) TypeAttrs[*TypeIndex] = Attr.getValueAsType(); - else if (Kind == Attribute::Alignment) - Alignment = Attr.getAlignment(); - else if (Kind == Attribute::StackAlignment) - StackAlignment = Attr.getStackAlignment(); - else if (Kind == Attribute::Dereferenceable) - DerefBytes = Attr.getDereferenceableBytes(); - else if (Kind == Attribute::DereferenceableOrNull) - DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); - else if (Kind == Attribute::AllocSize) - AllocSizeArgs = Attr.getValueAsInt(); - else if (Kind == Attribute::VScaleRange) - VScaleRangeArgs = Attr.getValueAsInt(); + else if (Optional<unsigned> IntIndex = kindToIntIndex(Kind)) + IntAttrs[*IntIndex] = Attr.getValueAsInt(); return *this; } @@ -1616,18 +1587,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { if (Optional<unsigned> TypeIndex = kindToTypeIndex(Val)) TypeAttrs[*TypeIndex] = nullptr; - else if (Val == Attribute::Alignment) - Alignment.reset(); - else if (Val == Attribute::StackAlignment) - StackAlignment.reset(); - else if (Val == Attribute::Dereferenceable) - DerefBytes = 0; - else if (Val == Attribute::DereferenceableOrNull) - DerefOrNullBytes = 0; - else if (Val == Attribute::AllocSize) - AllocSizeArgs = 0; - else if (Val == Attribute::VScaleRange) - VScaleRangeArgs = 0; + else if (Optional<unsigned> IntIndex = kindToIntIndex(Val)) + IntAttrs[*IntIndex] = 0; return *this; } @@ -1638,18 +1599,32 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) { } AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { - auto I = TargetDepAttrs.find(A); - if (I != TargetDepAttrs.end()) - TargetDepAttrs.erase(I); + TargetDepAttrs.erase(A); + return *this; +} + +uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const { + Optional<unsigned> IntIndex = kindToIntIndex(Kind); + assert(IntIndex && "Not an int attribute"); + return IntAttrs[*IntIndex]; +} + +AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind, + uint64_t Value) { + Optional<unsigned> IntIndex = kindToIntIndex(Kind); + assert(IntIndex && "Not an int attribute"); + assert(Value && "Value cannot be zero"); + Attrs[Kind] = true; + IntAttrs[*IntIndex] = Value; return *this; } std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const { - return unpackAllocSizeArgs(AllocSizeArgs); + return unpackAllocSizeArgs(getRawIntAttr(Attribute::AllocSize)); } std::pair<unsigned, unsigned> AttrBuilder::getVScaleRangeArgs() const { - return unpackVScaleRangeArgs(VScaleRangeArgs); + return unpackVScaleRangeArgs(getRawIntAttr(Attribute::VScaleRange)); } AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) { @@ -1657,10 +1632,7 @@ AttrBuilder &AttrBuilder::addAlignmentAttr(MaybeAlign Align) { return *this; assert(*Align <= llvm::Value::MaximumAlignment && "Alignment too large."); - - Attrs[Attribute::Alignment] = true; - Alignment = Align; - return *this; + return addRawIntAttr(Attribute::Alignment, Align->value()); } AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) { @@ -1669,27 +1641,20 @@ AttrBuilder &AttrBuilder::addStackAlignmentAttr(MaybeAlign Align) { return *this; assert(*Align <= 0x100 && "Alignment too large."); - - Attrs[Attribute::StackAlignment] = true; - StackAlignment = Align; - return *this; + return addRawIntAttr(Attribute::StackAlignment, Align->value()); } AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { if (Bytes == 0) return *this; - Attrs[Attribute::Dereferenceable] = true; - DerefBytes = Bytes; - return *this; + return addRawIntAttr(Attribute::Dereferenceable, Bytes); } AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) { if (Bytes == 0) return *this; - Attrs[Attribute::DereferenceableOrNull] = true; - DerefOrNullBytes = Bytes; - return *this; + return addRawIntAttr(Attribute::DereferenceableOrNull, Bytes); } AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize, @@ -1700,12 +1665,7 @@ AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize, AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) { // (0, 0) is our "not present" value, so we need to check for it here. assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)"); - - Attrs[Attribute::AllocSize] = true; - // Reuse existing machinery to store this as a single 64-bit integer so we can - // save a few bytes over using a pair<unsigned, Optional<unsigned>>. - AllocSizeArgs = RawArgs; - return *this; + return addRawIntAttr(Attribute::AllocSize, RawArgs); } AttrBuilder &AttrBuilder::addVScaleRangeAttr(unsigned MinValue, @@ -1718,11 +1678,7 @@ AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) { if (RawArgs == 0) return *this; - Attrs[Attribute::VScaleRange] = true; - // Reuse existing machinery to store this as a single 64-bit integer so we can - // save a few bytes over using a pair<unsigned, unsigned>. - VScaleRangeArgs = RawArgs; - return *this; + return addRawIntAttr(Attribute::VScaleRange, RawArgs); } Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const { @@ -1760,24 +1716,10 @@ AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) { } AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { - // FIXME: What if both have alignments, but they don't match?! - if (!Alignment) - Alignment = B.Alignment; - - if (!StackAlignment) - StackAlignment = B.StackAlignment; - - if (!DerefBytes) - DerefBytes = B.DerefBytes; - - if (!DerefOrNullBytes) - DerefOrNullBytes = B.DerefOrNullBytes; - - if (!AllocSizeArgs) - AllocSizeArgs = B.AllocSizeArgs; - - if (!VScaleRangeArgs) - VScaleRangeArgs = B.VScaleRangeArgs; + // FIXME: What if both have an int/type attribute, but they don't match?! + for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index) + if (!IntAttrs[Index]) + IntAttrs[Index] = B.IntAttrs[Index]; for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (!TypeAttrs[Index]) @@ -1792,24 +1734,10 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { } AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { - // FIXME: What if both have alignments, but they don't match?! - if (B.Alignment) - Alignment.reset(); - - if (B.StackAlignment) - StackAlignment.reset(); - - if (B.DerefBytes) - DerefBytes = 0; - - if (B.DerefOrNullBytes) - DerefOrNullBytes = 0; - - if (B.AllocSizeArgs) - AllocSizeArgs = 0; - - if (B.VScaleRangeArgs) - VScaleRangeArgs = 0; + // FIXME: What if both have an int/type attribute, but they don't match?! + for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index) + if (B.IntAttrs[Index]) + IntAttrs[Index] = 0; for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index) if (B.TypeAttrs[Index]) @@ -1861,7 +1789,7 @@ bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const { } bool AttrBuilder::hasAlignmentAttr() const { - return Alignment != 0; + return getRawIntAttr(Attribute::Alignment) != 0; } bool AttrBuilder::operator==(const AttrBuilder &B) const { @@ -1872,9 +1800,7 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const { if (B.TargetDepAttrs.find(TDA.first) == B.TargetDepAttrs.end()) return false; - return Alignment == B.Alignment && StackAlignment == B.StackAlignment && - DerefBytes == B.DerefBytes && TypeAttrs == B.TypeAttrs && - VScaleRangeArgs == B.VScaleRangeArgs; + return IntAttrs == B.IntAttrs && TypeAttrs == B.TypeAttrs; } //===----------------------------------------------------------------------===// @@ -1966,11 +1892,11 @@ static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { .addAttribute(Attribute::StackProtectReq); if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { - Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr); + Caller.removeFnAttrs(OldSSPAttr); Caller.addFnAttr(Attribute::StackProtectReq); } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && !Caller.hasFnAttribute(Attribute::StackProtectReq)) { - Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr); + Caller.removeFnAttrs(OldSSPAttr); Caller.addFnAttr(Attribute::StackProtectStrong); } else if (Callee.hasFnAttribute(Attribute::StackProtect) && !Caller.hasFnAttribute(Attribute::StackProtectReq) && diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 6271385183eb..d73d1e9c20b3 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -583,8 +583,10 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { // Can't use Intrinsic::getDeclaration here as the return types might // then only be structurally equal. FunctionType* fType = FunctionType::get(F->getReturnType(), Tys, false); + StringRef Suffix = + F->getContext().supportsTypedPointers() ? "p0i8" : "p0"; NewFn = Function::Create(fType, F->getLinkage(), F->getAddressSpace(), - "llvm." + Name + ".p0i8", F->getParent()); + "llvm." + Name + "." + Suffix, F->getParent()); return true; } static const Regex vstRegex("^arm\\.neon\\.vst([1234]|[234]lane)\\.v[a-z0-9]*$"); @@ -601,7 +603,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { auto fArgs = F->getFunctionType()->params(); Type *Tys[] = {fArgs[0], fArgs[1]}; - if (Name.find("lane") == StringRef::npos) + if (!Name.contains("lane")) NewFn = Intrinsic::getDeclaration(F->getParent(), StoreInts[fArgs.size() - 3], Tys); else @@ -1273,7 +1275,7 @@ static Value *UpgradeX86BinaryIntrinsics(IRBuilder<> &Builder, CallInst &CI, Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty); Value *Res = Builder.CreateCall(Intrin, {Op0, Op1}); - if (CI.getNumArgOperands() == 4) { // For masked intrinsics. + if (CI.arg_size() == 4) { // For masked intrinsics. Value *VecSrc = CI.getOperand(2); Value *Mask = CI.getOperand(3); Res = EmitX86Select(Builder, Mask, Res, VecSrc); @@ -1300,7 +1302,7 @@ static Value *upgradeX86Rotate(IRBuilder<> &Builder, CallInst &CI, Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty); Value *Res = Builder.CreateCall(Intrin, {Src, Src, Amt}); - if (CI.getNumArgOperands() == 4) { // For masked intrinsics. + if (CI.arg_size() == 4) { // For masked intrinsics. Value *VecSrc = CI.getOperand(2); Value *Mask = CI.getOperand(3); Res = EmitX86Select(Builder, Mask, Res, VecSrc); @@ -1370,7 +1372,7 @@ static Value *upgradeX86ConcatShift(IRBuilder<> &Builder, CallInst &CI, Function *Intrin = Intrinsic::getDeclaration(CI.getModule(), IID, Ty); Value *Res = Builder.CreateCall(Intrin, {Op0, Op1, Amt}); - unsigned NumArgs = CI.getNumArgOperands(); + unsigned NumArgs = CI.arg_size(); if (NumArgs >= 4) { // For masked intrinsics. Value *VecSrc = NumArgs == 5 ? CI.getArgOperand(3) : ZeroMask ? ConstantAggregateZero::get(CI.getType()) : @@ -1431,7 +1433,7 @@ static Value *upgradeAbs(IRBuilder<> &Builder, CallInst &CI) { Value *Op0 = CI.getArgOperand(0); Function *F = Intrinsic::getDeclaration(CI.getModule(), Intrinsic::abs, Ty); Value *Res = Builder.CreateCall(F, {Op0, Builder.getInt1(false)}); - if (CI.getNumArgOperands() == 3) + if (CI.arg_size() == 3) Res = EmitX86Select(Builder, CI.getArgOperand(2), Res, CI.getArgOperand(1)); return Res; } @@ -1459,7 +1461,7 @@ static Value *upgradePMULDQ(IRBuilder<> &Builder, CallInst &CI, bool IsSigned) { Value *Res = Builder.CreateMul(LHS, RHS); - if (CI.getNumArgOperands() == 4) + if (CI.arg_size() == 4) Res = EmitX86Select(Builder, CI.getArgOperand(3), Res, CI.getArgOperand(2)); return Res; @@ -1514,7 +1516,7 @@ static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallInst &CI, Cmp = Builder.CreateICmp(Pred, Op0, CI.getArgOperand(1)); } - Value *Mask = CI.getArgOperand(CI.getNumArgOperands() - 1); + Value *Mask = CI.getArgOperand(CI.arg_size() - 1); return ApplyX86MaskOn1BitsVec(Builder, Cmp, Mask); } @@ -1779,13 +1781,12 @@ static bool upgradeAVX512MaskToSelect(StringRef Name, IRBuilder<> &Builder, } else return false; - SmallVector<Value *, 4> Args(CI.arg_operands().begin(), - CI.arg_operands().end()); + SmallVector<Value *, 4> Args(CI.args()); Args.pop_back(); Args.pop_back(); Rep = Builder.CreateCall(Intrinsic::getDeclaration(CI.getModule(), IID), Args); - unsigned NumArgs = CI.getNumArgOperands(); + unsigned NumArgs = CI.arg_size(); Rep = EmitX86Select(Builder, CI.getArgOperand(NumArgs - 1), Rep, CI.getArgOperand(NumArgs - 2)); return true; @@ -1964,7 +1965,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->getType()), {CI->getArgOperand(0)}); } else if (IsX86 && (Name.startswith("avx512.mask.sqrt.p"))) { - if (CI->getNumArgOperands() == 4 && + if (CI->arg_size() == 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 @@ -2124,8 +2125,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { { CI->getOperand(0), CI->getArgOperand(1) }); Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, CI->getArgOperand(2)); } else if (IsX86 && Name.startswith("avx512.cmp.p")) { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); Type *OpTy = Args[0]->getType(); unsigned VecWidth = OpTy->getPrimitiveSizeInBits(); unsigned EltWidth = OpTy->getScalarSizeInBits(); @@ -2257,7 +2257,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { bool IsUnsigned = (StringRef::npos != Name.find("cvtu")); if (IsPS2PD) Rep = Builder.CreateFPExt(Rep, DstTy, "cvtps2pd"); - else if (CI->getNumArgOperands() == 4 && + else if (CI->arg_size() == 4 && (!isa<ConstantInt>(CI->getArgOperand(3)) || cast<ConstantInt>(CI->getArgOperand(3))->getZExtValue() != 4)) { Intrinsic::ID IID = IsUnsigned ? Intrinsic::x86_avx512_uitofp_round @@ -2270,7 +2270,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { : Builder.CreateSIToFP(Rep, DstTy, "cvt"); } - if (CI->getNumArgOperands() >= 3) + if (CI->arg_size() >= 3) Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1)); } else if (IsX86 && (Name.startswith("avx512.mask.vcvtph2ps.") || @@ -2286,7 +2286,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateBitCast( Rep, FixedVectorType::get(Type::getHalfTy(C), NumDstElts)); Rep = Builder.CreateFPExt(Rep, DstTy, "cvtph2ps"); - if (CI->getNumArgOperands() >= 3) + if (CI->arg_size() >= 3) Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1)); } else if (IsX86 && (Name.startswith("avx512.mask.loadu."))) { @@ -2353,7 +2353,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { llvm_unreachable("Unknown suffix"); unsigned Imm; - if (CI->getNumArgOperands() == 3) { + if (CI->arg_size() == 3) { Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue(); } else { Name = Name.substr(9); // strip off "xop.vpcom" @@ -2417,7 +2417,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { EltTy->getPointerTo()); Value *Load = Builder.CreateLoad(EltTy, Cast); Type *I32Ty = Type::getInt32Ty(C); - Rep = UndefValue::get(VecTy); + Rep = PoisonValue::get(VecTy); for (unsigned I = 0; I < EltNum; ++I) Rep = Builder.CreateInsertElement(Rep, Load, ConstantInt::get(I32Ty, I)); @@ -2442,7 +2442,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = DoSext ? Builder.CreateSExt(SV, DstTy) : Builder.CreateZExt(SV, DstTy); // If there are 3 arguments, it's a masked intrinsic so we need a select. - if (CI->getNumArgOperands() == 3) + if (CI->arg_size() == 3) Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1)); } else if (Name == "avx512.mask.pmov.qd.256" || @@ -2518,7 +2518,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { ShuffleVectorInst::getShuffleMask(Constant::getNullValue(MaskTy), M); Rep = Builder.CreateShuffleVector(Op, M); - if (CI->getNumArgOperands() == 3) + if (CI->arg_size() == 3) Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, CI->getArgOperand(1)); } else if (IsX86 && (Name.startswith("sse2.padds.") || @@ -2636,7 +2636,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Rep, Idxs); // If the intrinsic has a mask operand, handle that. - if (CI->getNumArgOperands() == 5) + if (CI->arg_size() == 5) Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep, CI->getArgOperand(3)); } else if (IsX86 && (Name.startswith("avx.vextractf128.") || @@ -2661,7 +2661,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs); // If the intrinsic has a mask operand, handle that. - if (CI->getNumArgOperands() == 4) + if (CI->arg_size() == 4) Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2)); } else if (!IsX86 && Name == "stackprotectorcheck") { @@ -2679,7 +2679,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs); - if (CI->getNumArgOperands() == 4) + if (CI->arg_size() == 4) Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2)); } else if (IsX86 && (Name.startswith("avx.vperm2f128.") || @@ -2739,7 +2739,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs); - if (CI->getNumArgOperands() == 4) + if (CI->arg_size() == 4) Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2)); } else if (IsX86 && (Name == "sse2.pshufl.w" || @@ -2758,7 +2758,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs); - if (CI->getNumArgOperands() == 4) + if (CI->arg_size() == 4) Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2)); } else if (IsX86 && (Name == "sse2.pshufh.w" || @@ -2777,7 +2777,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Rep = Builder.CreateShuffleVector(Op0, Op0, Idxs); - if (CI->getNumArgOperands() == 4) + if (CI->arg_size() == 4) Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, CI->getArgOperand(2)); } else if (IsX86 && Name.startswith("avx512.mask.shuf.p")) { @@ -3346,7 +3346,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { if (NegAcc) C = Builder.CreateFNeg(C); - if (CI->getNumArgOperands() == 5 && + if (CI->arg_size() == 5 && (!isa<ConstantInt>(CI->getArgOperand(4)) || cast<ConstantInt>(CI->getArgOperand(4))->getZExtValue() != 4)) { Intrinsic::ID IID; @@ -3399,7 +3399,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { // 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) { + if (CI->arg_size() == 5) { Intrinsic::ID IID; // Check the character before ".512" in string. if (Name[Name.size()-5] == 's') @@ -3686,8 +3686,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::arm_neon_vst2lane: case Intrinsic::arm_neon_vst3lane: case Intrinsic::arm_neon_vst4lane: { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); NewCall = Builder.CreateCall(NewFn, Args); break; } @@ -3701,14 +3700,14 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::aarch64_neon_bfmlalb: case Intrinsic::aarch64_neon_bfmlalt: { SmallVector<Value *, 3> Args; - assert(CI->getNumArgOperands() == 3 && + assert(CI->arg_size() == 3 && "Mismatch between function args and call args"); size_t OperandWidth = CI->getArgOperand(1)->getType()->getPrimitiveSizeInBits(); assert((OperandWidth == 64 || OperandWidth == 128) && "Unexpected operand width"); Type *NewTy = FixedVectorType::get(Type::getBFloatTy(C), OperandWidth / 16); - auto Iter = CI->arg_operands().begin(); + auto Iter = CI->args().begin(); Args.push_back(*Iter++); Args.push_back(Builder.CreateBitCast(*Iter++, NewTy)); Args.push_back(Builder.CreateBitCast(*Iter++, NewTy)); @@ -3722,18 +3721,17 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::ctlz: case Intrinsic::cttz: - assert(CI->getNumArgOperands() == 1 && + assert(CI->arg_size() == 1 && "Mismatch between function args and call args"); NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0), Builder.getFalse()}); break; case Intrinsic::objectsize: { - Value *NullIsUnknownSize = CI->getNumArgOperands() == 2 - ? Builder.getFalse() - : CI->getArgOperand(2); + Value *NullIsUnknownSize = + CI->arg_size() == 2 ? Builder.getFalse() : CI->getArgOperand(2); Value *Dynamic = - CI->getNumArgOperands() < 4 ? Builder.getFalse() : CI->getArgOperand(3); + CI->arg_size() < 4 ? Builder.getFalse() : CI->getArgOperand(3); NewCall = Builder.CreateCall( NewFn, {CI->getArgOperand(0), CI->getArgOperand(1), NullIsUnknownSize, Dynamic}); break; @@ -3749,7 +3747,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::dbg_value: // Upgrade from the old version that had an extra offset argument. - assert(CI->getNumArgOperands() == 4); + assert(CI->arg_size() == 4); // Drop nonzero offsets instead of attempting to upgrade them. if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1))) if (Offset->isZeroValue()) { @@ -3763,7 +3761,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::ptr_annotation: // Upgrade from versions that lacked the annotation attribute argument. - assert(CI->getNumArgOperands() == 4 && + assert(CI->arg_size() == 4 && "Before LLVM 12.0 this intrinsic took four arguments"); // Create a new call with an added null annotation attribute argument. NewCall = Builder.CreateCall( @@ -3777,7 +3775,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::var_annotation: // Upgrade from versions that lacked the annotation attribute argument. - assert(CI->getNumArgOperands() == 4 && + assert(CI->arg_size() == 4 && "Before LLVM 12.0 this intrinsic took four arguments"); // Create a new call with an added null annotation attribute argument. NewCall = Builder.CreateCall( @@ -3796,8 +3794,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::x86_xop_vpermil2ps: case Intrinsic::x86_xop_vpermil2pd_256: case Intrinsic::x86_xop_vpermil2ps_256: { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); VectorType *FltIdxTy = cast<VectorType>(Args[2]->getType()); VectorType *IntIdxTy = VectorType::getInteger(FltIdxTy); Args[2] = Builder.CreateBitCast(Args[2], IntIdxTy); @@ -3858,8 +3855,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::x86_avx2_mpsadbw: { // Need to truncate the last argument from i32 to i8 -- this argument models // an inherently 8-bit immediate operand to these x86 instructions. - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); // Replace the last argument with a trunc. Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc"); @@ -3873,8 +3869,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::x86_avx512_mask_cmp_ps_128: case Intrinsic::x86_avx512_mask_cmp_ps_256: case Intrinsic::x86_avx512_mask_cmp_ps_512: { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); unsigned NumElts = cast<FixedVectorType>(Args[0]->getType())->getNumElements(); Args[3] = getX86MaskVec(Builder, Args[3], NumElts); @@ -3895,8 +3890,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::invariant_start: case Intrinsic::invariant_end: { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); NewCall = Builder.CreateCall(NewFn, Args); break; } @@ -3904,8 +3898,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { case Intrinsic::masked_store: case Intrinsic::masked_gather: case Intrinsic::masked_scatter: { - SmallVector<Value *, 4> Args(CI->arg_operands().begin(), - CI->arg_operands().end()); + SmallVector<Value *, 4> Args(CI->args()); NewCall = Builder.CreateCall(NewFn, Args); NewCall->copyMetadata(*CI); break; @@ -3921,7 +3914,7 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { // @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) { + if (CI->arg_size() != 5) { DefaultCase(); return; } @@ -4111,7 +4104,7 @@ void llvm::UpgradeARCRuntime(Module &M) { bool InvalidCast = false; - for (unsigned I = 0, E = CI->getNumArgOperands(); I != E; ++I) { + for (unsigned I = 0, E = CI->arg_size(); I != E; ++I) { Value *Arg = CI->getArgOperand(I); // Bitcast argument to the parameter type of the new function if it's @@ -4361,8 +4354,8 @@ struct StrictFPUpgradeVisitor : public InstVisitor<StrictFPUpgradeVisitor> { return; // If we get here, the caller doesn't have the strictfp attribute // but this callsite does. Replace the strictfp attribute with nobuiltin. - Call.removeAttribute(AttributeList::FunctionIndex, Attribute::StrictFP); - Call.addAttribute(AttributeList::FunctionIndex, Attribute::NoBuiltin); + Call.removeFnAttr(Attribute::StrictFP); + Call.addFnAttr(Attribute::NoBuiltin); } }; } // namespace @@ -4383,8 +4376,7 @@ void llvm::UpgradeFunctionAttributes(Function &F) { } // Remove all incompatibile attributes from function. - F.removeAttributes(AttributeList::ReturnIndex, - AttributeFuncs::typeIncompatible(F.getReturnType())); + F.removeRetAttrs(AttributeFuncs::typeIncompatible(F.getReturnType())); for (auto &Arg : F.args()) Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType())); } diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index d14abafdef2e..ed1956e0f7e9 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -12,6 +12,7 @@ #include "llvm/IR/BasicBlock.h" #include "SymbolTableListTraitsImpl.h" +#include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" @@ -23,6 +24,9 @@ using namespace llvm; +#define DEBUG_TYPE "ir" +STATISTIC(NumInstrRenumberings, "Number of renumberings across all blocks"); + ValueSymbolTable *BasicBlock::getValueSymbolTable() { if (Function *F = getParent()) return F->getValueSymbolTable(); @@ -505,6 +509,8 @@ void BasicBlock::renumberInstructions() { BasicBlockBits Bits = getBasicBlockBits(); Bits.InstrOrderValid = true; setBasicBlockBits(Bits); + + NumInstrRenumberings++; } #ifndef NDEBUG diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 5f05aa2e94e7..437fd0558447 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -349,200 +349,6 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart, } } -/// Wrapper around getFoldedSizeOfImpl() that adds caching. -static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded, - DenseMap<Type *, Constant *> &Cache); - -/// Return a ConstantExpr with type DestTy for sizeof on Ty, with any known -/// factors factored out. If Folded is false, return null if no factoring was -/// possible, to avoid endlessly bouncing an unfoldable expression back into the -/// top-level folder. -static Constant *getFoldedSizeOfImpl(Type *Ty, Type *DestTy, bool Folded, - DenseMap<Type *, Constant *> &Cache) { - // This is the actual implementation of getFoldedSizeOf(). To get the caching - // behavior, we need to call getFoldedSizeOf() when we recurse. - - if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { - Constant *N = ConstantInt::get(DestTy, ATy->getNumElements()); - Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true, Cache); - return ConstantExpr::getNUWMul(E, N); - } - - if (StructType *STy = dyn_cast<StructType>(Ty)) - if (!STy->isPacked()) { - unsigned NumElems = STy->getNumElements(); - // An empty struct has size zero. - if (NumElems == 0) - return ConstantExpr::getNullValue(DestTy); - // Check for a struct with all members having the same size. - Constant *MemberSize = - getFoldedSizeOf(STy->getElementType(0), DestTy, true, Cache); - bool AllSame = true; - for (unsigned i = 1; i != NumElems; ++i) - if (MemberSize != - getFoldedSizeOf(STy->getElementType(i), DestTy, true, Cache)) { - AllSame = false; - break; - } - if (AllSame) { - Constant *N = ConstantInt::get(DestTy, NumElems); - return ConstantExpr::getNUWMul(MemberSize, N); - } - } - - // Pointer size doesn't depend on the pointee type, so canonicalize them - // to an arbitrary pointee. - if (PointerType *PTy = dyn_cast<PointerType>(Ty)) - if (!PTy->getElementType()->isIntegerTy(1)) - return getFoldedSizeOf( - PointerType::get(IntegerType::get(PTy->getContext(), 1), - PTy->getAddressSpace()), - DestTy, true, Cache); - - // If there's no interesting folding happening, bail so that we don't create - // a constant that looks like it needs folding but really doesn't. - if (!Folded) - return nullptr; - - // Base case: Get a regular sizeof expression. - Constant *C = ConstantExpr::getSizeOf(Ty); - C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, - DestTy, false), - C, DestTy); - return C; -} - -static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded, - DenseMap<Type *, Constant *> &Cache) { - // Check for previously generated folded size constant. - auto It = Cache.find(Ty); - if (It != Cache.end()) - return It->second; - return Cache[Ty] = getFoldedSizeOfImpl(Ty, DestTy, Folded, Cache); -} - -static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) { - DenseMap<Type *, Constant *> Cache; - return getFoldedSizeOf(Ty, DestTy, Folded, Cache); -} - -/// Return a ConstantExpr with type DestTy for alignof on Ty, with any known -/// factors factored out. If Folded is false, return null if no factoring was -/// possible, to avoid endlessly bouncing an unfoldable expression back into the -/// top-level folder. -static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, bool Folded) { - // The alignment of an array is equal to the alignment of the - // array element. Note that this is not always true for vectors. - if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { - Constant *C = ConstantExpr::getAlignOf(ATy->getElementType()); - C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, - DestTy, - false), - C, DestTy); - return C; - } - - if (StructType *STy = dyn_cast<StructType>(Ty)) { - // Packed structs always have an alignment of 1. - if (STy->isPacked()) - return ConstantInt::get(DestTy, 1); - - // Otherwise, struct alignment is the maximum alignment of any member. - // Without target data, we can't compare much, but we can check to see - // if all the members have the same alignment. - unsigned NumElems = STy->getNumElements(); - // An empty struct has minimal alignment. - if (NumElems == 0) - return ConstantInt::get(DestTy, 1); - // Check for a struct with all members having the same alignment. - Constant *MemberAlign = - getFoldedAlignOf(STy->getElementType(0), DestTy, true); - bool AllSame = true; - for (unsigned i = 1; i != NumElems; ++i) - if (MemberAlign != getFoldedAlignOf(STy->getElementType(i), DestTy, true)) { - AllSame = false; - break; - } - if (AllSame) - return MemberAlign; - } - - // Pointer alignment doesn't depend on the pointee type, so canonicalize them - // to an arbitrary pointee. - if (PointerType *PTy = dyn_cast<PointerType>(Ty)) - if (!PTy->getElementType()->isIntegerTy(1)) - return - getFoldedAlignOf(PointerType::get(IntegerType::get(PTy->getContext(), - 1), - PTy->getAddressSpace()), - DestTy, true); - - // If there's no interesting folding happening, bail so that we don't create - // a constant that looks like it needs folding but really doesn't. - if (!Folded) - return nullptr; - - // Base case: Get a regular alignof expression. - Constant *C = ConstantExpr::getAlignOf(Ty); - C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, - DestTy, false), - C, DestTy); - return C; -} - -/// Return a ConstantExpr with type DestTy for offsetof on Ty and FieldNo, with -/// any known factors factored out. If Folded is false, return null if no -/// factoring was possible, to avoid endlessly bouncing an unfoldable expression -/// back into the top-level folder. -static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, Type *DestTy, - bool Folded) { - if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { - Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false, - DestTy, false), - FieldNo, DestTy); - Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true); - return ConstantExpr::getNUWMul(E, N); - } - - if (StructType *STy = dyn_cast<StructType>(Ty)) - if (!STy->isPacked()) { - unsigned NumElems = STy->getNumElements(); - // An empty struct has no members. - if (NumElems == 0) - return nullptr; - // Check for a struct with all members having the same size. - Constant *MemberSize = - getFoldedSizeOf(STy->getElementType(0), DestTy, true); - bool AllSame = true; - for (unsigned i = 1; i != NumElems; ++i) - if (MemberSize != - getFoldedSizeOf(STy->getElementType(i), DestTy, true)) { - AllSame = false; - break; - } - if (AllSame) { - Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, - false, - DestTy, - false), - FieldNo, DestTy); - return ConstantExpr::getNUWMul(MemberSize, N); - } - } - - // If there's no interesting folding happening, bail so that we don't create - // a constant that looks like it needs folding but really doesn't. - if (!Folded) - return nullptr; - - // Base case: Get a regular offsetof expression. - Constant *C = ConstantExpr::getOffsetOf(Ty, FieldNo); - C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, - DestTy, false), - C, DestTy); - return C; -} - Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, Type *DestTy) { if (isa<PoisonValue>(V)) @@ -666,53 +472,6 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, // Is it a null pointer value? if (V->isNullValue()) return ConstantInt::get(DestTy, 0); - // If this is a sizeof-like expression, pull out multiplications by - // known factors to expose them to subsequent folding. If it's an - // alignof-like expression, factor out known factors. - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - if (CE->getOpcode() == Instruction::GetElementPtr && - CE->getOperand(0)->isNullValue()) { - // FIXME: Looks like getFoldedSizeOf(), getFoldedOffsetOf() and - // getFoldedAlignOf() don't handle the case when DestTy is a vector of - // pointers yet. We end up in asserts in CastInst::getCastOpcode (see - // test/Analysis/ConstantFolding/cast-vector.ll). I've only seen this - // happen in one "real" C-code test case, so it does not seem to be an - // important optimization to handle vectors here. For now, simply bail - // out. - if (DestTy->isVectorTy()) - return nullptr; - GEPOperator *GEPO = cast<GEPOperator>(CE); - Type *Ty = GEPO->getSourceElementType(); - if (CE->getNumOperands() == 2) { - // Handle a sizeof-like expression. - Constant *Idx = CE->getOperand(1); - bool isOne = isa<ConstantInt>(Idx) && cast<ConstantInt>(Idx)->isOne(); - if (Constant *C = getFoldedSizeOf(Ty, DestTy, !isOne)) { - Idx = ConstantExpr::getCast(CastInst::getCastOpcode(Idx, true, - DestTy, false), - Idx, DestTy); - return ConstantExpr::getMul(C, Idx); - } - } else if (CE->getNumOperands() == 3 && - CE->getOperand(1)->isNullValue()) { - // Handle an alignof-like expression. - if (StructType *STy = dyn_cast<StructType>(Ty)) - if (!STy->isPacked()) { - ConstantInt *CI = cast<ConstantInt>(CE->getOperand(2)); - if (CI->isOne() && - STy->getNumElements() == 2 && - STy->getElementType(0)->isIntegerTy(1)) { - return getFoldedAlignOf(STy->getElementType(1), DestTy, false); - } - } - // Handle an offsetof-like expression. - if (Ty->isStructTy() || Ty->isArrayTy()) { - if (Constant *C = getFoldedOffsetOf(Ty, CE->getOperand(2), - DestTy, false)) - return C; - } - } - } // Other pointer types cannot be casted return nullptr; case Instruction::UIToFP: @@ -720,7 +479,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { const APInt &api = CI->getValue(); APFloat apf(DestTy->getFltSemantics(), - APInt::getNullValue(DestTy->getPrimitiveSizeInBits())); + APInt::getZero(DestTy->getPrimitiveSizeInBits())); apf.convertFromAPInt(api, opc==Instruction::SIToFP, APFloat::rmNearestTiesToEven); return ConstantFP::get(V->getContext(), apf); @@ -908,13 +667,16 @@ Constant *llvm::ConstantFoldExtractElementInstruction(Constant *Val, } } + if (Constant *C = Val->getAggregateElement(CIdx)) + return C; + // Lane < Splat minimum vector width => extractelt Splat(x), Lane -> x if (CIdx->getValue().ult(ValVTy->getElementCount().getKnownMinValue())) { if (Constant *SplatVal = Val->getSplatValue()) return SplatVal; } - return Val->getAggregateElement(CIdx); + return nullptr; } Constant *llvm::ConstantFoldInsertElementInstruction(Constant *Val, @@ -969,12 +731,16 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2, // If the mask is all zeros this is a splat, no need to go through all // elements. - if (all_of(Mask, [](int Elt) { return Elt == 0; }) && - !MaskEltCount.isScalable()) { + if (all_of(Mask, [](int Elt) { return Elt == 0; })) { Type *Ty = IntegerType::get(V1->getContext(), 32); Constant *Elt = ConstantExpr::getExtractElement(V1, ConstantInt::get(Ty, 0)); - return ConstantVector::getSplat(MaskEltCount, Elt); + + if (Elt->isNullValue()) { + auto *VTy = VectorType::get(EltTy, MaskEltCount); + return ConstantAggregateZero::get(VTy); + } else if (!MaskEltCount.isScalable()) + return ConstantVector::getSplat(MaskEltCount, Elt); } // Do not iterate on scalable vector. The num of elements is unknown at // compile-time. @@ -1379,7 +1145,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1, return ConstantInt::get(CI1->getContext(), C1V.udiv(C2V)); case Instruction::SDiv: assert(!CI2->isZero() && "Div by zero handled above"); - if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) + if (C2V.isAllOnes() && C1V.isMinSignedValue()) return PoisonValue::get(CI1->getType()); // MIN_INT / -1 -> poison return ConstantInt::get(CI1->getContext(), C1V.sdiv(C2V)); case Instruction::URem: @@ -1387,7 +1153,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1, return ConstantInt::get(CI1->getContext(), C1V.urem(C2V)); case Instruction::SRem: assert(!CI2->isZero() && "Div by zero handled above"); - if (C2V.isAllOnesValue() && C1V.isMinSignedValue()) + if (C2V.isAllOnes() && C1V.isMinSignedValue()) return PoisonValue::get(CI1->getType()); // MIN_INT % -1 -> poison return ConstantInt::get(CI1->getContext(), C1V.srem(C2V)); case Instruction::And: @@ -2030,19 +1796,8 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, if (isa<ConstantInt>(C1) && isa<ConstantInt>(C2)) { const APInt &V1 = cast<ConstantInt>(C1)->getValue(); const APInt &V2 = cast<ConstantInt>(C2)->getValue(); - switch (pred) { - default: llvm_unreachable("Invalid ICmp Predicate"); - case ICmpInst::ICMP_EQ: return ConstantInt::get(ResultTy, V1 == V2); - case ICmpInst::ICMP_NE: return ConstantInt::get(ResultTy, V1 != V2); - case ICmpInst::ICMP_SLT: return ConstantInt::get(ResultTy, V1.slt(V2)); - case ICmpInst::ICMP_SGT: return ConstantInt::get(ResultTy, V1.sgt(V2)); - case ICmpInst::ICMP_SLE: return ConstantInt::get(ResultTy, V1.sle(V2)); - case ICmpInst::ICMP_SGE: return ConstantInt::get(ResultTy, V1.sge(V2)); - case ICmpInst::ICMP_ULT: return ConstantInt::get(ResultTy, V1.ult(V2)); - case ICmpInst::ICMP_UGT: return ConstantInt::get(ResultTy, V1.ugt(V2)); - case ICmpInst::ICMP_ULE: return ConstantInt::get(ResultTy, V1.ule(V2)); - case ICmpInst::ICMP_UGE: return ConstantInt::get(ResultTy, V1.uge(V2)); - } + return ConstantInt::get( + ResultTy, ICmpInst::compare(V1, V2, (ICmpInst::Predicate)pred)); } else if (isa<ConstantFP>(C1) && isa<ConstantFP>(C2)) { const APFloat &C1V = cast<ConstantFP>(C1)->getValueAPF(); const APFloat &C2V = cast<ConstantFP>(C2)->getValueAPF(); @@ -2564,7 +2319,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) // It's in range, skip to the next index. continue; - if (CI->getSExtValue() < 0) { + if (CI->isNegative()) { // It's out of range and negative, don't try to factor it. Unknown = true; continue; @@ -2575,7 +2330,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I)); InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); - if (CI->getSExtValue() < 0) { + if (CI->isNegative()) { Unknown = true; break; } diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 0649776dbc22..a0f2179bddb4 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -110,7 +110,7 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, APInt UMin(CR.getUnsignedMin()); if (UMin.isMaxValue()) return getEmpty(W); - return ConstantRange(std::move(UMin) + 1, APInt::getNullValue(W)); + return ConstantRange(std::move(UMin) + 1, APInt::getZero(W)); } case CmpInst::ICMP_SGT: { APInt SMin(CR.getSignedMin()); @@ -119,7 +119,7 @@ ConstantRange ConstantRange::makeAllowedICmpRegion(CmpInst::Predicate Pred, return ConstantRange(std::move(SMin) + 1, APInt::getSignedMinValue(W)); } case CmpInst::ICMP_UGE: - return getNonEmpty(CR.getUnsignedMin(), APInt::getNullValue(W)); + return getNonEmpty(CR.getUnsignedMin(), APInt::getZero(W)); case CmpInst::ICMP_SGE: return getNonEmpty(CR.getSignedMin(), APInt::getSignedMinValue(W)); } @@ -147,38 +147,77 @@ ConstantRange ConstantRange::makeExactICmpRegion(CmpInst::Predicate Pred, return makeAllowedICmpRegion(Pred, C); } -bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred, - APInt &RHS) const { - bool Success = false; +bool ConstantRange::areInsensitiveToSignednessOfICmpPredicate( + const ConstantRange &CR1, const ConstantRange &CR2) { + if (CR1.isEmptySet() || CR2.isEmptySet()) + return true; + + return (CR1.isAllNonNegative() && CR2.isAllNonNegative()) || + (CR1.isAllNegative() && CR2.isAllNegative()); +} + +bool ConstantRange::areInsensitiveToSignednessOfInvertedICmpPredicate( + const ConstantRange &CR1, const ConstantRange &CR2) { + if (CR1.isEmptySet() || CR2.isEmptySet()) + return true; + + return (CR1.isAllNonNegative() && CR2.isAllNegative()) || + (CR1.isAllNegative() && CR2.isAllNonNegative()); +} + +CmpInst::Predicate ConstantRange::getEquivalentPredWithFlippedSignedness( + CmpInst::Predicate Pred, const ConstantRange &CR1, + const ConstantRange &CR2) { + assert(CmpInst::isIntPredicate(Pred) && CmpInst::isRelational(Pred) && + "Only for relational integer predicates!"); + CmpInst::Predicate FlippedSignednessPred = + CmpInst::getFlippedSignednessPredicate(Pred); + + if (areInsensitiveToSignednessOfICmpPredicate(CR1, CR2)) + return FlippedSignednessPred; + + if (areInsensitiveToSignednessOfInvertedICmpPredicate(CR1, CR2)) + return CmpInst::getInversePredicate(FlippedSignednessPred); + + return CmpInst::Predicate::BAD_ICMP_PREDICATE; +} + +void ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred, + APInt &RHS, APInt &Offset) const { + Offset = APInt(getBitWidth(), 0); if (isFullSet() || isEmptySet()) { Pred = isEmptySet() ? CmpInst::ICMP_ULT : CmpInst::ICMP_UGE; RHS = APInt(getBitWidth(), 0); - Success = true; } else if (auto *OnlyElt = getSingleElement()) { Pred = CmpInst::ICMP_EQ; RHS = *OnlyElt; - Success = true; } else if (auto *OnlyMissingElt = getSingleMissingElement()) { Pred = CmpInst::ICMP_NE; RHS = *OnlyMissingElt; - Success = true; } else if (getLower().isMinSignedValue() || getLower().isMinValue()) { Pred = getLower().isMinSignedValue() ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT; RHS = getUpper(); - Success = true; } else if (getUpper().isMinSignedValue() || getUpper().isMinValue()) { Pred = getUpper().isMinSignedValue() ? CmpInst::ICMP_SGE : CmpInst::ICMP_UGE; RHS = getLower(); - Success = true; + } else { + Pred = CmpInst::ICMP_ULT; + RHS = getUpper() - getLower(); + Offset = -getLower(); } - assert((!Success || ConstantRange::makeExactICmpRegion(Pred, RHS) == *this) && + assert(ConstantRange::makeExactICmpRegion(Pred, RHS) == add(Offset) && "Bad result!"); +} - return Success; +bool ConstantRange::getEquivalentICmp(CmpInst::Predicate &Pred, + APInt &RHS) const { + APInt Offset; + getEquivalentICmp(Pred, RHS, Offset); + return Offset.isZero(); } bool ConstantRange::icmp(CmpInst::Predicate Pred, @@ -204,13 +243,13 @@ static ConstantRange makeExactMulNSWRegion(const APInt &V) { // Handle special case for 0, -1 and 1. See the last for reason why we // specialize -1 and 1. unsigned BitWidth = V.getBitWidth(); - if (V == 0 || V.isOneValue()) + if (V == 0 || V.isOne()) return ConstantRange::getFull(BitWidth); APInt MinValue = APInt::getSignedMinValue(BitWidth); APInt MaxValue = APInt::getSignedMaxValue(BitWidth); // e.g. Returning [-127, 127], represented as [-127, -128). - if (V.isAllOnesValue()) + if (V.isAllOnes()) return ConstantRange(-MaxValue, MinValue); APInt Lower, Upper; @@ -248,8 +287,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, case Instruction::Add: { if (Unsigned) - return getNonEmpty(APInt::getNullValue(BitWidth), - -Other.getUnsignedMax()); + return getNonEmpty(APInt::getZero(BitWidth), -Other.getUnsignedMax()); APInt SignedMinVal = APInt::getSignedMinValue(BitWidth); APInt SMin = Other.getSignedMin(), SMax = Other.getSignedMax(); @@ -291,7 +329,7 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp, // to be at most bitwidth-1, which results in most conservative range. APInt ShAmtUMax = ShAmt.getUnsignedMax(); if (Unsigned) - return getNonEmpty(APInt::getNullValue(BitWidth), + return getNonEmpty(APInt::getZero(BitWidth), APInt::getMaxValue(BitWidth).lshr(ShAmtUMax) + 1); return getNonEmpty(APInt::getSignedMinValue(BitWidth).ashr(ShAmtUMax), APInt::getSignedMaxValue(BitWidth).ashr(ShAmtUMax) + 1); @@ -316,7 +354,7 @@ bool ConstantRange::isEmptySet() const { } bool ConstantRange::isWrappedSet() const { - return Lower.ugt(Upper) && !Upper.isNullValue(); + return Lower.ugt(Upper) && !Upper.isZero(); } bool ConstantRange::isUpperWrapped() const { @@ -343,11 +381,10 @@ ConstantRange::isSizeStrictlySmallerThan(const ConstantRange &Other) const { bool ConstantRange::isSizeLargerThan(uint64_t MaxSize) const { - assert(MaxSize && "MaxSize can't be 0."); // If this a full set, we need special handling to avoid needing an extra bit // to represent the size. if (isFullSet()) - return APInt::getMaxValue(getBitWidth()).ugt(MaxSize - 1); + return MaxSize == 0 || APInt::getMaxValue(getBitWidth()).ugt(MaxSize - 1); return (Upper - Lower).ugt(MaxSize); } @@ -595,7 +632,7 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR, APInt L = CR.Lower.ult(Lower) ? CR.Lower : Lower; APInt U = (CR.Upper - 1).ugt(Upper - 1) ? CR.Upper : Upper; - if (L.isNullValue() && U.isNullValue()) + if (L.isZero() && U.isZero()) return getFull(); return ConstantRange(std::move(L), std::move(U)); @@ -644,6 +681,24 @@ ConstantRange ConstantRange::unionWith(const ConstantRange &CR, return ConstantRange(std::move(L), std::move(U)); } +Optional<ConstantRange> +ConstantRange::exactIntersectWith(const ConstantRange &CR) const { + // TODO: This can be implemented more efficiently. + ConstantRange Result = intersectWith(CR); + if (Result == inverse().unionWith(CR.inverse()).inverse()) + return Result; + return None; +} + +Optional<ConstantRange> +ConstantRange::exactUnionWith(const ConstantRange &CR) const { + // TODO: This can be implemented more efficiently. + ConstantRange Result = unionWith(CR); + if (Result == inverse().intersectWith(CR.inverse()).inverse()) + return Result; + return None; +} + ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp, uint32_t ResultBitWidth) const { switch (CastOp) { @@ -1055,6 +1110,25 @@ ConstantRange::multiply(const ConstantRange &Other) const { return UR.isSizeStrictlySmallerThan(SR) ? UR : SR; } +ConstantRange ConstantRange::smul_fast(const ConstantRange &Other) const { + if (isEmptySet() || Other.isEmptySet()) + return getEmpty(); + + APInt Min = getSignedMin(); + APInt Max = getSignedMax(); + APInt OtherMin = Other.getSignedMin(); + APInt OtherMax = Other.getSignedMax(); + + bool O1, O2, O3, O4; + auto Muls = {Min.smul_ov(OtherMin, O1), Min.smul_ov(OtherMax, O2), + Max.smul_ov(OtherMin, O3), Max.smul_ov(OtherMax, O4)}; + if (O1 || O2 || O3 || O4) + return getFull(); + + auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); }; + return getNonEmpty(std::min(Muls, Compare), std::max(Muls, Compare) + 1); +} + ConstantRange ConstantRange::smax(const ConstantRange &Other) const { // X smax Y is: range(smax(X_smin, Y_smin), @@ -1113,13 +1187,13 @@ ConstantRange::umin(const ConstantRange &Other) const { ConstantRange ConstantRange::udiv(const ConstantRange &RHS) const { - if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue()) + if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isZero()) return getEmpty(); APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax()); APInt RHS_umin = RHS.getUnsignedMin(); - if (RHS_umin.isNullValue()) { + if (RHS_umin.isZero()) { // We want the lowest value in RHS excluding zero. Usually that would be 1 // except for a range in the form of [X, 1) in which case it would be X. if (RHS.getUpper() == 1) @@ -1136,7 +1210,7 @@ ConstantRange ConstantRange::sdiv(const ConstantRange &RHS) const { // We split up the LHS and RHS into positive and negative components // and then also compute the positive and negative components of the result // separately by combining division results with the appropriate signs. - APInt Zero = APInt::getNullValue(getBitWidth()); + APInt Zero = APInt::getZero(getBitWidth()); APInt SignedMin = APInt::getSignedMinValue(getBitWidth()); ConstantRange PosFilter(APInt(getBitWidth(), 1), SignedMin); ConstantRange NegFilter(SignedMin, Zero); @@ -1159,12 +1233,12 @@ ConstantRange ConstantRange::sdiv(const ConstantRange &RHS) const { // (For APInts the operation is well-defined and yields SignedMin.) We // handle this by dropping either SignedMin from the LHS or -1 from the RHS. APInt Lo = (NegL.Upper - 1).sdiv(NegR.Lower); - if (NegL.Lower.isMinSignedValue() && NegR.Upper.isNullValue()) { + if (NegL.Lower.isMinSignedValue() && NegR.Upper.isZero()) { // Remove -1 from the LHS. Skip if it's the only element, as this would // leave us with an empty set. - if (!NegR.Lower.isAllOnesValue()) { + if (!NegR.Lower.isAllOnes()) { APInt AdjNegRUpper; - if (RHS.Lower.isAllOnesValue()) + if (RHS.Lower.isAllOnes()) // Negative part of [-1, X] without -1 is [SignedMin, X]. AdjNegRUpper = RHS.Upper; else @@ -1218,12 +1292,12 @@ ConstantRange ConstantRange::sdiv(const ConstantRange &RHS) const { } ConstantRange ConstantRange::urem(const ConstantRange &RHS) const { - if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isNullValue()) + if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax().isZero()) return getEmpty(); if (const APInt *RHSInt = RHS.getSingleElement()) { // UREM by null is UB. - if (RHSInt->isNullValue()) + if (RHSInt->isZero()) return getEmpty(); // Use APInt's implementation of UREM for single element ranges. if (const APInt *LHSInt = getSingleElement()) @@ -1236,7 +1310,7 @@ ConstantRange ConstantRange::urem(const ConstantRange &RHS) const { // L % R is <= L and < R. APInt Upper = APIntOps::umin(getUnsignedMax(), RHS.getUnsignedMax() - 1) + 1; - return getNonEmpty(APInt::getNullValue(getBitWidth()), std::move(Upper)); + return getNonEmpty(APInt::getZero(getBitWidth()), std::move(Upper)); } ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { @@ -1245,7 +1319,7 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { if (const APInt *RHSInt = RHS.getSingleElement()) { // SREM by null is UB. - if (RHSInt->isNullValue()) + if (RHSInt->isZero()) return getEmpty(); // Use APInt's implementation of SREM for single element ranges. if (const APInt *LHSInt = getSingleElement()) @@ -1257,10 +1331,10 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { APInt MaxAbsRHS = AbsRHS.getUnsignedMax(); // Modulus by zero is UB. - if (MaxAbsRHS.isNullValue()) + if (MaxAbsRHS.isZero()) return getEmpty(); - if (MinAbsRHS.isNullValue()) + if (MinAbsRHS.isZero()) ++MinAbsRHS; APInt MinLHS = getSignedMin(), MaxLHS = getSignedMax(); @@ -1272,7 +1346,7 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { // L % R is <= L and < R. APInt Upper = APIntOps::umin(MaxLHS, MaxAbsRHS - 1) + 1; - return ConstantRange(APInt::getNullValue(getBitWidth()), std::move(Upper)); + return ConstantRange(APInt::getZero(getBitWidth()), std::move(Upper)); } // Same basic logic as above, but the result is negative. @@ -1291,7 +1365,7 @@ ConstantRange ConstantRange::srem(const ConstantRange &RHS) const { } ConstantRange ConstantRange::binaryNot() const { - return ConstantRange(APInt::getAllOnesValue(getBitWidth())).sub(*this); + return ConstantRange(APInt::getAllOnes(getBitWidth())).sub(*this); } ConstantRange @@ -1306,7 +1380,7 @@ ConstantRange::binaryAnd(const ConstantRange &Other) const { // TODO: replace this with something less conservative APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax()); - return getNonEmpty(APInt::getNullValue(getBitWidth()), std::move(umin) + 1); + return getNonEmpty(APInt::getZero(getBitWidth()), std::move(umin) + 1); } ConstantRange @@ -1321,7 +1395,7 @@ ConstantRange::binaryOr(const ConstantRange &Other) const { // TODO: replace this with something less conservative APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin()); - return getNonEmpty(std::move(umax), APInt::getNullValue(getBitWidth())); + return getNonEmpty(std::move(umax), APInt::getZero(getBitWidth())); } ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const { @@ -1333,9 +1407,9 @@ ConstantRange ConstantRange::binaryXor(const ConstantRange &Other) const { return {*getSingleElement() ^ *Other.getSingleElement()}; // Special-case binary complement, since we can give a precise answer. - if (Other.isSingleElement() && Other.getSingleElement()->isAllOnesValue()) + if (Other.isSingleElement() && Other.getSingleElement()->isAllOnes()) return binaryNot(); - if (isSingleElement() && getSingleElement()->isAllOnesValue()) + if (isSingleElement() && getSingleElement()->isAllOnes()) return Other.binaryNot(); // TODO: replace this with something less conservative @@ -1347,24 +1421,33 @@ ConstantRange::shl(const ConstantRange &Other) const { if (isEmptySet() || Other.isEmptySet()) return getEmpty(); - APInt max = getUnsignedMax(); - APInt Other_umax = Other.getUnsignedMax(); + APInt Min = getUnsignedMin(); + APInt Max = getUnsignedMax(); + if (const APInt *RHS = Other.getSingleElement()) { + unsigned BW = getBitWidth(); + if (RHS->uge(BW)) + return getEmpty(); - // If we are shifting by maximum amount of - // zero return return the original range. - if (Other_umax.isNullValue()) - return *this; - // there's overflow! - if (Other_umax.ugt(max.countLeadingZeros())) + unsigned EqualLeadingBits = (Min ^ Max).countLeadingZeros(); + if (RHS->ule(EqualLeadingBits)) + return getNonEmpty(Min << *RHS, (Max << *RHS) + 1); + + return getNonEmpty(APInt::getZero(BW), + APInt::getBitsSetFrom(BW, RHS->getZExtValue()) + 1); + } + + APInt OtherMax = Other.getUnsignedMax(); + + // There's overflow! + if (OtherMax.ugt(Max.countLeadingZeros())) return getFull(); // FIXME: implement the other tricky cases - APInt min = getUnsignedMin(); - min <<= Other.getUnsignedMin(); - max <<= Other_umax; + Min <<= Other.getUnsignedMin(); + Max <<= OtherMax; - return ConstantRange(std::move(min), std::move(max) + 1); + return ConstantRange::getNonEmpty(std::move(Min), std::move(Max) + 1); } ConstantRange @@ -1483,20 +1566,15 @@ ConstantRange ConstantRange::smul_sat(const ConstantRange &Other) const { // [-1,4) * [-2,3) = min(-1*-2, -1*2, 3*-2, 3*2) = -6. // Similarly for the upper bound, swapping min for max. - APInt this_min = getSignedMin().sext(getBitWidth() * 2); - APInt this_max = getSignedMax().sext(getBitWidth() * 2); - APInt Other_min = Other.getSignedMin().sext(getBitWidth() * 2); - APInt Other_max = Other.getSignedMax().sext(getBitWidth() * 2); + APInt Min = getSignedMin(); + APInt Max = getSignedMax(); + APInt OtherMin = Other.getSignedMin(); + APInt OtherMax = Other.getSignedMax(); - auto L = {this_min * Other_min, this_min * Other_max, this_max * Other_min, - this_max * Other_max}; + auto L = {Min.smul_sat(OtherMin), Min.smul_sat(OtherMax), + Max.smul_sat(OtherMin), Max.smul_sat(OtherMax)}; auto Compare = [](const APInt &A, const APInt &B) { return A.slt(B); }; - - // Note that we wanted to perform signed saturating multiplication, - // so since we performed plain multiplication in twice the bitwidth, - // we need to perform signed saturating truncation. - return getNonEmpty(std::min(L, Compare).truncSSat(getBitWidth()), - std::max(L, Compare).truncSSat(getBitWidth()) + 1); + return getNonEmpty(std::min(L, Compare), std::max(L, Compare) + 1); } ConstantRange ConstantRange::ushl_sat(const ConstantRange &Other) const { @@ -1535,7 +1613,7 @@ ConstantRange ConstantRange::abs(bool IntMinIsPoison) const { APInt Lo; // Check whether the range crosses zero. if (Upper.isStrictlyPositive() || !Lower.isStrictlyPositive()) - Lo = APInt::getNullValue(getBitWidth()); + Lo = APInt::getZero(getBitWidth()); else Lo = APIntOps::umin(Lower, -Upper + 1); @@ -1565,7 +1643,7 @@ ConstantRange ConstantRange::abs(bool IntMinIsPoison) const { return ConstantRange(-SMax, -SMin + 1); // Range crosses zero. - return ConstantRange(APInt::getNullValue(getBitWidth()), + return ConstantRange(APInt::getZero(getBitWidth()), APIntOps::umax(-SMin, SMax) + 1); } diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 6c75085a6678..c66cfb6e9ac1 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -95,7 +95,7 @@ bool Constant::isAllOnesValue() const { // Check for FP which are bitcasted from -1 integers if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) - return CFP->getValueAPF().bitcastToAPInt().isAllOnesValue(); + return CFP->getValueAPF().bitcastToAPInt().isAllOnes(); // Check for constant splat vectors of 1 values. if (getType()->isVectorTy()) @@ -112,7 +112,7 @@ bool Constant::isOneValue() const { // Check for FP which are bitcasted from 1 integers if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) - return CFP->getValueAPF().bitcastToAPInt().isOneValue(); + return CFP->getValueAPF().bitcastToAPInt().isOne(); // Check for constant splat vectors of 1 values. if (getType()->isVectorTy()) @@ -129,7 +129,7 @@ bool Constant::isNotOneValue() const { // Check for FP which are bitcasted from 1 integers if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this)) - return !CFP->getValueAPF().bitcastToAPInt().isOneValue(); + return !CFP->getValueAPF().bitcastToAPInt().isOne(); // Check that vectors don't contain 1 if (auto *VTy = dyn_cast<FixedVectorType>(getType())) { @@ -315,9 +315,11 @@ containsUndefinedElement(const Constant *C, return false; for (unsigned i = 0, e = cast<FixedVectorType>(VTy)->getNumElements(); - i != e; ++i) - if (HasFn(C->getAggregateElement(i))) - return true; + i != e; ++i) { + if (Constant *Elem = C->getAggregateElement(i)) + if (HasFn(Elem)) + return true; + } } return false; @@ -366,9 +368,8 @@ Constant *Constant::getNullValue(Type *Ty) { return ConstantFP::get(Ty->getContext(), APFloat::getZero(APFloat::IEEEquad())); case Type::PPC_FP128TyID: - return ConstantFP::get(Ty->getContext(), - APFloat(APFloat::PPCDoubleDouble(), - APInt::getNullValue(128))); + return ConstantFP::get(Ty->getContext(), APFloat(APFloat::PPCDoubleDouble(), + APInt::getZero(128))); case Type::PointerTyID: return ConstantPointerNull::get(cast<PointerType>(Ty)); case Type::StructTyID: @@ -404,11 +405,10 @@ Constant *Constant::getIntegerValue(Type *Ty, const APInt &V) { Constant *Constant::getAllOnesValue(Type *Ty) { if (IntegerType *ITy = dyn_cast<IntegerType>(Ty)) return ConstantInt::get(Ty->getContext(), - APInt::getAllOnesValue(ITy->getBitWidth())); + APInt::getAllOnes(ITy->getBitWidth())); if (Ty->isFloatingPointTy()) { - APFloat FL = APFloat::getAllOnesValue(Ty->getFltSemantics(), - Ty->getPrimitiveSizeInBits()); + APFloat FL = APFloat::getAllOnesValue(Ty->getFltSemantics()); return ConstantFP::get(Ty->getContext(), FL); } @@ -714,29 +714,41 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { return Result; } -/// If the specified constantexpr is dead, remove it. This involves recursively -/// eliminating any dead users of the constantexpr. -static bool removeDeadUsersOfConstant(const Constant *C) { +/// Return true if the specified constantexpr is dead. This involves +/// recursively traversing users of the constantexpr. +/// If RemoveDeadUsers is true, also remove dead users at the same time. +static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) { if (isa<GlobalValue>(C)) return false; // Cannot remove this - while (!C->use_empty()) { - const Constant *User = dyn_cast<Constant>(C->user_back()); + Value::const_user_iterator I = C->user_begin(), E = C->user_end(); + while (I != E) { + const Constant *User = dyn_cast<Constant>(*I); if (!User) return false; // Non-constant usage; - if (!removeDeadUsersOfConstant(User)) + if (!constantIsDead(User, RemoveDeadUsers)) return false; // Constant wasn't dead + + // Just removed User, so the iterator was invalidated. + // Since we return immediately upon finding a live user, we can always + // restart from user_begin(). + if (RemoveDeadUsers) + I = C->user_begin(); + else + ++I; } - // If C is only used by metadata, it should not be preserved but should have - // its uses replaced. - if (C->isUsedByMetadata()) { - const_cast<Constant *>(C)->replaceAllUsesWith( - UndefValue::get(C->getType())); + if (RemoveDeadUsers) { + // If C is only used by metadata, it should not be preserved but should + // have its uses replaced. + if (C->isUsedByMetadata()) { + const_cast<Constant *>(C)->replaceAllUsesWith( + UndefValue::get(C->getType())); + } + const_cast<Constant *>(C)->destroyConstant(); } - const_cast<Constant*>(C)->destroyConstant(); + return true; } - void Constant::removeDeadConstantUsers() const { Value::const_user_iterator I = user_begin(), E = user_end(); Value::const_user_iterator LastNonDeadUser = E; @@ -748,7 +760,7 @@ void Constant::removeDeadConstantUsers() const { continue; } - if (!removeDeadUsersOfConstant(User)) { + if (!constantIsDead(User, /* RemoveDeadUsers= */ true)) { // If the constant wasn't dead, remember that this was the last live use // and move on to the next constant. LastNonDeadUser = I; @@ -764,6 +776,20 @@ void Constant::removeDeadConstantUsers() const { } } +bool Constant::hasOneLiveUse() const { + unsigned NumUses = 0; + for (const Use &use : uses()) { + const Constant *User = dyn_cast<Constant>(use.getUser()); + if (!User || !constantIsDead(User, /* RemoveDeadUsers= */ false)) { + ++NumUses; + + if (NumUses > 1) + return false; + } + } + return NumUses == 1; +} + Constant *Constant::replaceUndefsWith(Constant *C, Constant *Replacement) { assert(C && Replacement && "Expected non-nullptr constant arguments"); Type *Ty = C->getType(); @@ -1430,12 +1456,12 @@ Constant *ConstantVector::getSplat(ElementCount EC, Constant *V) { Type *I32Ty = Type::getInt32Ty(VTy->getContext()); // Move scalar into vector. - Constant *UndefV = UndefValue::get(VTy); - V = ConstantExpr::getInsertElement(UndefV, V, ConstantInt::get(I32Ty, 0)); + Constant *PoisonV = PoisonValue::get(VTy); + V = ConstantExpr::getInsertElement(PoisonV, V, ConstantInt::get(I32Ty, 0)); // Build shuffle mask to perform the splat. SmallVector<int, 8> Zeros(EC.getKnownMinValue(), 0); // Splat. - return ConstantExpr::getShuffleVector(V, UndefV, Zeros); + return ConstantExpr::getShuffleVector(V, PoisonV, Zeros); } ConstantTokenNone *ConstantTokenNone::get(LLVMContext &Context) { @@ -1508,20 +1534,6 @@ Constant *ConstantExpr::getShuffleMaskForBitcode() const { return cast<ShuffleVectorConstantExpr>(this)->ShuffleMaskForBitcode; } -Constant * -ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { - assert(Op->getType() == getOperand(OpNo)->getType() && - "Replacing operand with value of different type!"); - if (getOperand(OpNo) == Op) - return const_cast<ConstantExpr*>(this); - - SmallVector<Constant*, 8> NewOps; - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - NewOps.push_back(i == OpNo ? Op : getOperand(i)); - - return getWithOperands(NewOps); -} - Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, bool OnlyIfReduced, Type *SrcTy) const { assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); @@ -3282,7 +3294,7 @@ bool ConstantDataSequential::isCString() const { if (Str.back() != 0) return false; // Other elements must be non-nul. - return Str.drop_back().find(0) == StringRef::npos; + return !Str.drop_back().contains(0); } bool ConstantDataVector::isSplatData() const { @@ -3480,7 +3492,7 @@ Value *ConstantExpr::handleOperandChangeImpl(Value *From, Value *ToV) { NewOps, this, From, To, NumUpdated, OperandNo); } -Instruction *ConstantExpr::getAsInstruction() const { +Instruction *ConstantExpr::getAsInstruction(Instruction *InsertBefore) const { SmallVector<Value *, 4> ValueOperands(operands()); ArrayRef<Value*> Ops(ValueOperands); @@ -3498,40 +3510,43 @@ Instruction *ConstantExpr::getAsInstruction() const { case Instruction::IntToPtr: case Instruction::BitCast: case Instruction::AddrSpaceCast: - return CastInst::Create((Instruction::CastOps)getOpcode(), - Ops[0], getType()); + return CastInst::Create((Instruction::CastOps)getOpcode(), Ops[0], + getType(), "", InsertBefore); case Instruction::Select: - return SelectInst::Create(Ops[0], Ops[1], Ops[2]); + return SelectInst::Create(Ops[0], Ops[1], Ops[2], "", InsertBefore); case Instruction::InsertElement: - return InsertElementInst::Create(Ops[0], Ops[1], Ops[2]); + return InsertElementInst::Create(Ops[0], Ops[1], Ops[2], "", InsertBefore); case Instruction::ExtractElement: - return ExtractElementInst::Create(Ops[0], Ops[1]); + return ExtractElementInst::Create(Ops[0], Ops[1], "", InsertBefore); case Instruction::InsertValue: - return InsertValueInst::Create(Ops[0], Ops[1], getIndices()); + return InsertValueInst::Create(Ops[0], Ops[1], getIndices(), "", + InsertBefore); case Instruction::ExtractValue: - return ExtractValueInst::Create(Ops[0], getIndices()); + return ExtractValueInst::Create(Ops[0], getIndices(), "", InsertBefore); case Instruction::ShuffleVector: - return new ShuffleVectorInst(Ops[0], Ops[1], getShuffleMask()); + return new ShuffleVectorInst(Ops[0], Ops[1], getShuffleMask(), "", + InsertBefore); case Instruction::GetElementPtr: { const auto *GO = cast<GEPOperator>(this); if (GO->isInBounds()) - return GetElementPtrInst::CreateInBounds(GO->getSourceElementType(), - Ops[0], Ops.slice(1)); + return GetElementPtrInst::CreateInBounds( + GO->getSourceElementType(), Ops[0], Ops.slice(1), "", InsertBefore); return GetElementPtrInst::Create(GO->getSourceElementType(), Ops[0], - Ops.slice(1)); + Ops.slice(1), "", InsertBefore); } case Instruction::ICmp: case Instruction::FCmp: return CmpInst::Create((Instruction::OtherOps)getOpcode(), - (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]); + (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1], + "", InsertBefore); case Instruction::FNeg: - return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0]); + return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0], "", + InsertBefore); default: assert(getNumOperands() == 2 && "Must be binary operator?"); - BinaryOperator *BO = - BinaryOperator::Create((Instruction::BinaryOps)getOpcode(), - Ops[0], Ops[1]); + BinaryOperator *BO = BinaryOperator::Create( + (Instruction::BinaryOps)getOpcode(), Ops[0], Ops[1], "", InsertBefore); if (isa<OverflowingBinaryOperator>(BO)) { BO->setHasNoUnsignedWrap(SubclassOptionalData & OverflowingBinaryOperator::NoUnsignedWrap); diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 8a7060c148c9..905372982dc2 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2460,7 +2460,7 @@ void LLVMSetGC(LLVMValueRef Fn, const char *GC) { void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef A) { - unwrap<Function>(F)->addAttribute(Idx, unwrap(A)); + unwrap<Function>(F)->addAttributeAtIndex(Idx, unwrap(A)); } unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx) { @@ -2478,31 +2478,32 @@ void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef LLVMGetEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, unsigned KindID) { - return wrap(unwrap<Function>(F)->getAttribute(Idx, - (Attribute::AttrKind)KindID)); + return wrap(unwrap<Function>(F)->getAttributeAtIndex( + Idx, (Attribute::AttrKind)KindID)); } LLVMAttributeRef LLVMGetStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - return wrap(unwrap<Function>(F)->getAttribute(Idx, StringRef(K, KLen))); + return wrap( + unwrap<Function>(F)->getAttributeAtIndex(Idx, StringRef(K, KLen))); } void LLVMRemoveEnumAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, unsigned KindID) { - unwrap<Function>(F)->removeAttribute(Idx, (Attribute::AttrKind)KindID); + unwrap<Function>(F)->removeAttributeAtIndex(Idx, (Attribute::AttrKind)KindID); } void LLVMRemoveStringAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - unwrap<Function>(F)->removeAttribute(Idx, StringRef(K, KLen)); + unwrap<Function>(F)->removeAttributeAtIndex(Idx, StringRef(K, KLen)); } void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, const char *V) { Function *Func = unwrap<Function>(Fn); Attribute Attr = Attribute::get(Func->getContext(), A, V); - Func->addAttribute(AttributeList::FunctionIndex, Attr); + Func->addFnAttr(Attr); } /*--.. Operations on parameters ............................................--*/ @@ -2843,7 +2844,7 @@ unsigned LLVMGetNumArgOperands(LLVMValueRef Instr) { if (FuncletPadInst *FPI = dyn_cast<FuncletPadInst>(unwrap(Instr))) { return FPI->getNumArgOperands(); } - return unwrap<CallBase>(Instr)->getNumArgOperands(); + return unwrap<CallBase>(Instr)->arg_size(); } /*--.. Call and invoke instructions ........................................--*/ @@ -2857,17 +2858,17 @@ void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC) { static_cast<CallingConv::ID>(CC)); } -void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index, +void LLVMSetInstrParamAlignment(LLVMValueRef Instr, LLVMAttributeIndex Idx, unsigned align) { auto *Call = unwrap<CallBase>(Instr); Attribute AlignAttr = Attribute::getWithAlignment(Call->getContext(), Align(align)); - Call->addAttribute(index, AlignAttr); + Call->addAttributeAtIndex(Idx, AlignAttr); } void LLVMAddCallSiteAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, LLVMAttributeRef A) { - unwrap<CallBase>(C)->addAttribute(Idx, unwrap(A)); + unwrap<CallBase>(C)->addAttributeAtIndex(Idx, unwrap(A)); } unsigned LLVMGetCallSiteAttributeCount(LLVMValueRef C, @@ -2888,24 +2889,25 @@ void LLVMGetCallSiteAttributes(LLVMValueRef C, LLVMAttributeIndex Idx, LLVMAttributeRef LLVMGetCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, unsigned KindID) { - return wrap( - unwrap<CallBase>(C)->getAttribute(Idx, (Attribute::AttrKind)KindID)); + return wrap(unwrap<CallBase>(C)->getAttributeAtIndex( + Idx, (Attribute::AttrKind)KindID)); } LLVMAttributeRef LLVMGetCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - return wrap(unwrap<CallBase>(C)->getAttribute(Idx, StringRef(K, KLen))); + return wrap( + unwrap<CallBase>(C)->getAttributeAtIndex(Idx, StringRef(K, KLen))); } void LLVMRemoveCallSiteEnumAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, unsigned KindID) { - unwrap<CallBase>(C)->removeAttribute(Idx, (Attribute::AttrKind)KindID); + unwrap<CallBase>(C)->removeAttributeAtIndex(Idx, (Attribute::AttrKind)KindID); } void LLVMRemoveCallSiteStringAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, const char *K, unsigned KLen) { - unwrap<CallBase>(C)->removeAttribute(Idx, StringRef(K, KLen)); + unwrap<CallBase>(C)->removeAttributeAtIndex(Idx, StringRef(K, KLen)); } LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr) { @@ -3131,6 +3133,10 @@ void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst) { unwrap(Builder)->SetInstDebugLocation(unwrap<Instruction>(Inst)); } +void LLVMAddMetadataToInst(LLVMBuilderRef Builder, LLVMValueRef Inst) { + unwrap(Builder)->AddMetadataToInst(unwrap<Instruction>(Inst)); +} + void LLVMBuilderSetDefaultFPMathTag(LLVMBuilderRef Builder, LLVMMetadataRef FPMathTag) { diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 61d3b5e69e9e..ca7dafc814ce 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -32,8 +32,8 @@ static cl::opt<bool> cl::init(false), cl::Hidden); DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU) - : M(m), VMContext(M.getContext()), CUNode(CU), - DeclareFn(nullptr), ValueFn(nullptr), LabelFn(nullptr), + : M(m), VMContext(M.getContext()), CUNode(CU), DeclareFn(nullptr), + ValueFn(nullptr), LabelFn(nullptr), AllowUnresolvedNodes(AllowUnresolvedNodes) {} void DIBuilder::trackIfUnresolved(MDNode *N) { @@ -73,7 +73,8 @@ void DIBuilder::finalize() { return; } - CUNode->replaceEnumTypes(MDTuple::get(VMContext, AllEnumTypes)); + if (!AllEnumTypes.empty()) + CUNode->replaceEnumTypes(MDTuple::get(VMContext, AllEnumTypes)); SmallVector<Metadata *, 16> RetainValues; // Declarations and definitions of the same type may be retained. Some @@ -164,12 +165,13 @@ DICompileUnit *DIBuilder::createCompileUnit( static DIImportedEntity * createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context, Metadata *NS, DIFile *File, unsigned Line, StringRef Name, + DINodeArray Elements, SmallVectorImpl<TrackingMDNodeRef> &AllImportedModules) { if (Line) assert(File && "Source location has line number but no file"); unsigned EntitiesCount = C.pImpl->DIImportedEntitys.size(); auto *M = DIImportedEntity::get(C, Tag, Context, cast_or_null<DINode>(NS), - File, Line, Name); + File, Line, Name, Elements); if (EntitiesCount < C.pImpl->DIImportedEntitys.size()) // A new Imported Entity was just added to the context. // Add it to the Imported Modules list. @@ -179,36 +181,38 @@ createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context, DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DINamespace *NS, DIFile *File, - unsigned Line) { + unsigned Line, + DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, - Context, NS, File, Line, StringRef(), + Context, NS, File, Line, StringRef(), Elements, AllImportedModules); } DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIImportedEntity *NS, - DIFile *File, unsigned Line) { + DIFile *File, unsigned Line, + DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, - Context, NS, File, Line, StringRef(), + Context, NS, File, Line, StringRef(), Elements, AllImportedModules); } DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M, - DIFile *File, unsigned Line) { + DIFile *File, unsigned Line, + DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, - Context, M, File, Line, StringRef(), + Context, M, File, Line, StringRef(), Elements, AllImportedModules); } -DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context, - DINode *Decl, - DIFile *File, - unsigned Line, - StringRef Name) { +DIImportedEntity * +DIBuilder::createImportedDeclaration(DIScope *Context, DINode *Decl, + DIFile *File, unsigned Line, + StringRef Name, DINodeArray Elements) { // Make sure to use the unique identifier based metadata reference for // types that have one. return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, - Context, Decl, File, Line, Name, + Context, Decl, File, Line, Name, Elements, AllImportedModules); } @@ -250,7 +254,7 @@ DIEnumerator *DIBuilder::createEnumerator(StringRef Name, uint64_t Val, Name); } -DIEnumerator *DIBuilder::createEnumerator(StringRef Name, APSInt Value) { +DIEnumerator *DIBuilder::createEnumerator(StringRef Name, const APSInt &Value) { assert(!Name.empty() && "Unable to create enumerator without name"); return DIEnumerator::get(VMContext, APInt(Value), Value.isUnsigned(), Name); } @@ -283,17 +287,16 @@ DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { 0, 0, None, DINode::FlagZero); } -DIDerivedType *DIBuilder::createPointerType( - DIType *PointeeTy, - uint64_t SizeInBits, - uint32_t AlignInBits, - Optional<unsigned> DWARFAddressSpace, - StringRef Name) { +DIDerivedType * +DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits, + uint32_t AlignInBits, + Optional<unsigned> DWARFAddressSpace, + StringRef Name, DINodeArray Annotations) { // FIXME: Why is there a name here? return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name, nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, DWARFAddressSpace, - DINode::FlagZero); + AlignInBits, 0, DWARFAddressSpace, DINode::FlagZero, + nullptr, Annotations); } DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, @@ -306,11 +309,10 @@ DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, AlignInBits, 0, None, Flags, Base); } -DIDerivedType *DIBuilder::createReferenceType( - unsigned Tag, DIType *RTy, - uint64_t SizeInBits, - uint32_t AlignInBits, - Optional<unsigned> DWARFAddressSpace) { +DIDerivedType * +DIBuilder::createReferenceType(unsigned Tag, DIType *RTy, uint64_t SizeInBits, + uint32_t AlignInBits, + Optional<unsigned> DWARFAddressSpace) { assert(RTy && "Unable to create reference type"); return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, RTy, SizeInBits, AlignInBits, 0, DWARFAddressSpace, @@ -319,11 +321,12 @@ DIDerivedType *DIBuilder::createReferenceType( DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, DIFile *File, unsigned LineNo, - DIScope *Context, - uint32_t AlignInBits) { + DIScope *Context, uint32_t AlignInBits, + DINodeArray Annotations) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo, getNonCompileUnitScope(Context), Ty, 0, - AlignInBits, 0, None, DINode::FlagZero); + AlignInBits, 0, None, DINode::FlagZero, nullptr, + Annotations); } DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { @@ -341,19 +344,18 @@ DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, 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, ExtraData); + 0, Ty, BaseTy, 0, 0, BaseOffset, None, Flags, + ExtraData); } -DIDerivedType *DIBuilder::createMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, - uint32_t AlignInBits, - uint64_t OffsetInBits, - DINode::DIFlags Flags, DIType *Ty) { +DIDerivedType *DIBuilder::createMemberType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, - SizeInBits, AlignInBits, OffsetInBits, None, Flags); + SizeInBits, AlignInBits, OffsetInBits, None, Flags, + nullptr, Annotations); } static ConstantAsMetadata *getConstantOrNull(Constant *C) { @@ -375,14 +377,15 @@ DIDerivedType *DIBuilder::createVariantMemberType( DIDerivedType *DIBuilder::createBitFieldMemberType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits, - DINode::DIFlags Flags, DIType *Ty) { + DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { Flags |= DINode::FlagBitField; return DIDerivedType::get( VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, - getNonCompileUnitScope(Scope), Ty, SizeInBits, /* AlignInBits */ 0, + getNonCompileUnitScope(Scope), Ty, SizeInBits, /*AlignInBits=*/0, OffsetInBits, None, Flags, ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(VMContext, 64), - StorageOffsetInBits))); + StorageOffsetInBits)), + Annotations); } DIDerivedType * @@ -498,10 +501,12 @@ 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) { +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, @@ -542,16 +547,17 @@ DIDerivedType *DIBuilder::createSetType(DIScope *Scope, StringRef Name, return R; } -DICompositeType *DIBuilder::createArrayType( - uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts, - PointerUnion<DIExpression *, DIVariable *> DL, - PointerUnion<DIExpression *, DIVariable *> AS, - PointerUnion<DIExpression *, DIVariable *> AL, - PointerUnion<DIExpression *, DIVariable *> RK) { +DICompositeType * +DIBuilder::createArrayType(uint64_t Size, uint32_t AlignInBits, DIType *Ty, + DINodeArray Subscripts, + PointerUnion<DIExpression *, DIVariable *> DL, + PointerUnion<DIExpression *, DIVariable *> AS, + PointerUnion<DIExpression *, DIVariable *> AL, + PointerUnion<DIExpression *, DIVariable *> RK) { auto *R = DICompositeType::get( - VMContext, dwarf::DW_TAG_array_type, "", nullptr, 0, - nullptr, Ty, Size, AlignInBits, 0, DINode::FlagZero, - Subscripts, 0, nullptr, nullptr, "", nullptr, + VMContext, dwarf::DW_TAG_array_type, "", nullptr, 0, nullptr, Ty, Size, + AlignInBits, 0, DINode::FlagZero, Subscripts, 0, nullptr, nullptr, "", + nullptr, DL.is<DIExpression *>() ? (Metadata *)DL.get<DIExpression *>() : (Metadata *)DL.get<DIVariable *>(), AS.is<DIExpression *>() ? (Metadata *)AS.get<DIExpression *>() @@ -628,12 +634,14 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, DICompositeType *DIBuilder::createReplaceableCompositeType( unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, - DINode::DIFlags Flags, StringRef UniqueIdentifier) { + DINode::DIFlags Flags, StringRef UniqueIdentifier, + DINodeArray Annotations) { auto *RetTy = DICompositeType::getTemporary( VMContext, Tag, Name, F, Line, getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags, nullptr, RuntimeLang, nullptr, - nullptr, UniqueIdentifier) + nullptr, UniqueIdentifier, nullptr, nullptr, nullptr, nullptr, + nullptr, Annotations) .release(); trackIfUnresolved(RetTy); return RetTy; @@ -701,15 +709,16 @@ static void checkGlobalVariableScope(DIScope *Context) { DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, - unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, - bool isDefined, DIExpression *Expr, - MDNode *Decl, MDTuple *TemplateParams, uint32_t AlignInBits) { + unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, bool isDefined, + DIExpression *Expr, MDNode *Decl, MDTuple *TemplateParams, + uint32_t AlignInBits, DINodeArray Annotations) { checkGlobalVariableScope(Context); auto *GV = DIGlobalVariable::getDistinct( VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F, - LineNumber, Ty, IsLocalToUnit, isDefined, cast_or_null<DIDerivedType>(Decl), - TemplateParams, AlignInBits); + LineNumber, Ty, IsLocalToUnit, isDefined, + cast_or_null<DIDerivedType>(Decl), TemplateParams, AlignInBits, + Annotations); if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); @@ -726,7 +735,8 @@ DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( return DIGlobalVariable::getTemporary( VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, false, - cast_or_null<DIDerivedType>(Decl), TemplateParams, AlignInBits) + cast_or_null<DIDerivedType>(Decl), TemplateParams, AlignInBits, + nullptr) .release(); } @@ -735,16 +745,16 @@ static DILocalVariable *createLocalVariable( DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> &PreservedVariables, DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, - uint32_t AlignInBits) { + uint32_t AlignInBits, DINodeArray Annotations = nullptr) { // FIXME: Why getNonCompileUnitScope()? // FIXME: Why is "!Context" okay here? // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT // the only valid scopes)? DIScope *Context = getNonCompileUnitScope(Scope); - auto *Node = - DILocalVariable::get(VMContext, cast_or_null<DILocalScope>(Context), Name, - File, LineNo, Ty, ArgNo, Flags, AlignInBits); + auto *Node = DILocalVariable::get( + VMContext, cast_or_null<DILocalScope>(Context), Name, File, LineNo, Ty, + ArgNo, Flags, AlignInBits, Annotations); if (AlwaysPreserve) { // The optimizer may remove local variables. If there is an interest // to preserve variable info in such situation then stash it in a @@ -768,21 +778,20 @@ DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name, DILocalVariable *DIBuilder::createParameterVariable( DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, - unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags) { + unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, + DINodeArray Annotations) { assert(ArgNo && "Expected non-zero argument number for parameter"); return createLocalVariable(VMContext, PreservedVariables, Scope, Name, ArgNo, File, LineNo, Ty, AlwaysPreserve, Flags, - /* AlignInBits */0); + /*AlignInBits=*/0, Annotations); } -DILabel *DIBuilder::createLabel( - DIScope *Scope, StringRef Name, DIFile *File, - unsigned LineNo, bool AlwaysPreserve) { +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); + 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 @@ -806,7 +815,7 @@ DIExpression *DIBuilder::createExpression(ArrayRef<int64_t> Signed) { } template <class... Ts> -static DISubprogram *getSubprogram(bool IsDistinct, Ts &&... Args) { +static DISubprogram *getSubprogram(bool IsDistinct, Ts &&...Args) { if (IsDistinct) return DISubprogram::getDistinct(std::forward<Ts>(Args)...); return DISubprogram::get(std::forward<Ts>(Args)...); @@ -817,13 +826,14 @@ DISubprogram *DIBuilder::createFunction( unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, DISubprogram *Decl, - DITypeArray ThrownTypes) { + DITypeArray ThrownTypes, DINodeArray Annotations) { bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, ScopeLine, nullptr, 0, 0, Flags, SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, - MDTuple::getTemporary(VMContext, None).release(), ThrownTypes); + MDTuple::getTemporary(VMContext, None).release(), ThrownTypes, + Annotations); if (IsDefinition) AllSubprograms.push_back(Node); @@ -869,11 +879,11 @@ DISubprogram *DIBuilder::createMethod( return SP; } -DICommonBlock *DIBuilder::createCommonBlock( - DIScope *Scope, DIGlobalVariable *Decl, StringRef Name, DIFile *File, - unsigned LineNo) { - return DICommonBlock::get( - VMContext, Scope, Decl, Name, File, LineNo); +DICommonBlock *DIBuilder::createCommonBlock(DIScope *Scope, + DIGlobalVariable *Decl, + StringRef Name, DIFile *File, + unsigned LineNo) { + return DICommonBlock::get(VMContext, Scope, Decl, Name, File, LineNo); } DINamespace *DIBuilder::createNameSpace(DIScope *Scope, StringRef Name, @@ -929,9 +939,9 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, Instruction *InsertBefore) { - return insertLabel( - LabelInfo, DL, InsertBefore ? InsertBefore->getParent() : nullptr, - InsertBefore); + return insertLabel(LabelInfo, DL, + InsertBefore ? InsertBefore->getParent() : nullptr, + InsertBefore); } Instruction *DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, @@ -980,7 +990,8 @@ static Function *getDeclareIntrin(Module &M) { Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore) { + BasicBlock *InsertBB, + Instruction *InsertBefore) { assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); assert(DL && "Expected debug loc"); assert(DL->getScope()->getSubprogram() == @@ -1023,9 +1034,9 @@ Instruction *DIBuilder::insertDbgValueIntrinsic( return B.CreateCall(ValueFn, Args); } -Instruction *DIBuilder::insertLabel( - DILabel *LabelInfo, const DILocation *DL, - BasicBlock *InsertBB, Instruction *InsertBefore) { +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() == @@ -1042,8 +1053,7 @@ Instruction *DIBuilder::insertLabel( return B.CreateCall(LabelFn, Args); } -void DIBuilder::replaceVTableHolder(DICompositeType *&T, - DIType *VTableHolder) { +void DIBuilder::replaceVTableHolder(DICompositeType *&T, DIType *VTableHolder) { { TypedTrackingMDRef<DICompositeType> N(T); N->replaceVTableHolder(VTableHolder); diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index ecd74449dc38..2ace18048262 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -151,6 +151,8 @@ PointerAlignElem::operator==(const PointerAlignElem &rhs) const { //===----------------------------------------------------------------------===// const char *DataLayout::getManglingComponent(const Triple &T) { + if (T.isOSBinFormatGOFF()) + return "-m:l"; if (T.isOSBinFormatMachO()) return "-m:o"; if (T.isOSWindows() && T.isOSBinFormatCOFF()) @@ -258,12 +260,12 @@ Error DataLayout::parseSpecifier(StringRef Desc) { while (!Desc.empty()) { // Split at '-'. std::pair<StringRef, StringRef> Split; - if (Error Err = split(Desc, '-', Split)) + if (Error Err = ::split(Desc, '-', Split)) return Err; Desc = Split.second; // Split at ':'. - if (Error Err = split(Split.first, ':', Split)) + if (Error Err = ::split(Split.first, ':', Split)) return Err; // Aliases used below. @@ -272,7 +274,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Tok == "ni") { do { - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; Rest = Split.second; unsigned AS; @@ -313,7 +315,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Rest.empty()) return reportError( "Missing size specification for pointer in datalayout string"); - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; unsigned PointerMemSize; if (Error Err = getIntInBytes(Tok, PointerMemSize)) @@ -325,7 +327,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Rest.empty()) return reportError( "Missing alignment specification for pointer in datalayout string"); - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; unsigned PointerABIAlign; if (Error Err = getIntInBytes(Tok, PointerABIAlign)) @@ -340,7 +342,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { // Preferred alignment. unsigned PointerPrefAlign = PointerABIAlign; if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; if (Error Err = getIntInBytes(Tok, PointerPrefAlign)) return Err; @@ -350,7 +352,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { // Now read the index. It is the second optional parameter here. if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; if (Error Err = getIntInBytes(Tok, IndexSize)) return Err; @@ -391,7 +393,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { if (Rest.empty()) return reportError( "Missing alignment specification in datalayout string"); - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; unsigned ABIAlign; if (Error Err = getIntInBytes(Tok, ABIAlign)) @@ -408,7 +410,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { // Preferred alignment. unsigned PrefAlign = ABIAlign; if (!Rest.empty()) { - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; if (Error Err = getIntInBytes(Tok, PrefAlign)) return Err; @@ -437,7 +439,7 @@ Error DataLayout::parseSpecifier(StringRef Desc) { LegalIntWidths.push_back(Width); if (Rest.empty()) break; - if (Error Err = split(Rest, ':', Split)) + if (Error Err = ::split(Rest, ':', Split)) return Err; } break; @@ -500,6 +502,9 @@ Error DataLayout::parseSpecifier(StringRef Desc) { case 'e': ManglingMode = MM_ELF; break; + case 'l': + ManglingMode = MM_GOFF; + break; case 'o': ManglingMode = MM_MachO; break; @@ -702,12 +707,12 @@ unsigned DataLayout::getPointerSize(unsigned AS) const { return getPointerAlignElem(AS).TypeByteWidth; } -unsigned DataLayout::getMaxPointerSize() const { - unsigned MaxPointerSize = 0; +unsigned DataLayout::getMaxIndexSize() const { + unsigned MaxIndexSize = 0; for (auto &P : Pointers) - MaxPointerSize = std::max(MaxPointerSize, P.TypeByteWidth); + MaxIndexSize = std::max(MaxIndexSize, P.IndexWidth); - return MaxPointerSize; + return MaxIndexSize; } unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const { @@ -800,15 +805,11 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { // By default, use natural alignment for vector types. This is consistent // with what clang and llvm-gcc do. - // TODO: This should probably not be using the alloc size. - unsigned Alignment = - getTypeAllocSize(cast<VectorType>(Ty)->getElementType()); + // // We're only calculating a natural alignment, so it doesn't have to be // based on the full size for scalable vectors. Using the minimum element // count should be enough here. - Alignment *= cast<VectorType>(Ty)->getElementCount().getKnownMinValue(); - Alignment = PowerOf2Ceil(Alignment); - return Align(Alignment); + return Align(PowerOf2Ceil(getTypeStoreSize(Ty).getKnownMinSize())); } case Type::X86_AMXTyID: return Align(64); @@ -818,7 +819,7 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { } /// TODO: Remove this function once the transition to Align is over. -unsigned DataLayout::getABITypeAlignment(Type *Ty) const { +uint64_t DataLayout::getABITypeAlignment(Type *Ty) const { return getABITypeAlign(Ty).value(); } @@ -827,7 +828,7 @@ Align DataLayout::getABITypeAlign(Type *Ty) const { } /// TODO: Remove this function once the transition to Align is over. -unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const { +uint64_t DataLayout::getPrefTypeAlignment(Type *Ty) const { return getPrefTypeAlign(Ty).value(); } @@ -900,6 +901,72 @@ int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy, return Result; } +static void addElementIndex(SmallVectorImpl<APInt> &Indices, TypeSize ElemSize, + APInt &Offset) { + // Skip over scalable or zero size elements. Also skip element sizes larger + // than the positive index space, because the arithmetic below may not be + // correct in that case. + unsigned BitWidth = Offset.getBitWidth(); + if (ElemSize.isScalable() || ElemSize == 0 || + !isUIntN(BitWidth - 1, ElemSize)) { + Indices.push_back(APInt::getZero(BitWidth)); + return; + } + + APInt Index = Offset.sdiv(ElemSize); + Offset -= Index * ElemSize; + if (Offset.isNegative()) { + // Prefer a positive remaining offset to allow struct indexing. + --Index; + Offset += ElemSize; + assert(Offset.isNonNegative() && "Remaining offset shouldn't be negative"); + } + Indices.push_back(Index); +} + +SmallVector<APInt> DataLayout::getGEPIndicesForOffset(Type *&ElemTy, + APInt &Offset) const { + assert(ElemTy->isSized() && "Element type must be sized"); + SmallVector<APInt> Indices; + addElementIndex(Indices, getTypeAllocSize(ElemTy), Offset); + while (Offset != 0) { + if (auto *ArrTy = dyn_cast<ArrayType>(ElemTy)) { + ElemTy = ArrTy->getElementType(); + addElementIndex(Indices, getTypeAllocSize(ElemTy), Offset); + continue; + } + + if (auto *VecTy = dyn_cast<VectorType>(ElemTy)) { + ElemTy = VecTy->getElementType(); + unsigned ElemSizeInBits = getTypeSizeInBits(ElemTy).getFixedSize(); + // GEPs over non-multiple of 8 size vector elements are invalid. + if (ElemSizeInBits % 8 != 0) + break; + + addElementIndex(Indices, TypeSize::Fixed(ElemSizeInBits / 8), Offset); + continue; + } + + if (auto *STy = dyn_cast<StructType>(ElemTy)) { + const StructLayout *SL = getStructLayout(STy); + uint64_t IntOffset = Offset.getZExtValue(); + if (IntOffset >= SL->getSizeInBytes()) + break; + + unsigned Index = SL->getElementContainingOffset(IntOffset); + Offset -= SL->getElementOffset(Index); + ElemTy = STy->getElementType(Index); + Indices.push_back(APInt(32, Index)); + continue; + } + + // Can't index into non-aggregate type. + break; + } + + return Indices; +} + /// getPreferredAlign - Return the preferred alignment of the specified global. /// This includes an explicitly requested alignment (if the global has one). Align DataLayout::getPreferredAlign(const GlobalVariable *GV) const { diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 06c511f8530a..7c69fbf7085d 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -447,8 +447,7 @@ bool llvm::stripDebugInfo(Function &F) { DenseMap<MDNode *, MDNode *> LoopIDsMap; for (BasicBlock &BB : F) { - for (auto II = BB.begin(), End = BB.end(); II != End;) { - Instruction &I = *II++; // We may delete the instruction, increment now. + for (Instruction &I : llvm::make_early_inc_range(BB)) { if (isa<DbgInfoIntrinsic>(&I)) { I.eraseFromParent(); Changed = true; @@ -909,6 +908,11 @@ void LLVMDIBuilderFinalize(LLVMDIBuilderRef Builder) { unwrap(Builder)->finalize(); } +void LLVMDIBuilderFinalizeSubprogram(LLVMDIBuilderRef Builder, + LLVMMetadataRef subprogram) { + unwrap(Builder)->finalizeSubprogram(unwrapDI<DISubprogram>(subprogram)); +} + LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( LLVMDIBuilderRef Builder, LLVMDWARFSourceLanguage Lang, LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, @@ -1003,41 +1007,43 @@ LLVMDIBuilderCreateImportedModuleFromNamespace(LLVMDIBuilderRef Builder, Line)); } -LLVMMetadataRef -LLVMDIBuilderCreateImportedModuleFromAlias(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - LLVMMetadataRef ImportedEntity, - LLVMMetadataRef File, - unsigned Line) { +LLVMMetadataRef LLVMDIBuilderCreateImportedModuleFromAlias( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, + LLVMMetadataRef ImportedEntity, LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef *Elements, unsigned NumElements) { + auto Elts = + (NumElements > 0) + ? unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements}) + : nullptr; return wrap(unwrap(Builder)->createImportedModule( - unwrapDI<DIScope>(Scope), - unwrapDI<DIImportedEntity>(ImportedEntity), - unwrapDI<DIFile>(File), Line)); + unwrapDI<DIScope>(Scope), unwrapDI<DIImportedEntity>(ImportedEntity), + unwrapDI<DIFile>(File), Line, Elts)); } -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 LLVMDIBuilderCreateImportedModuleFromModule( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef M, + LLVMMetadataRef File, unsigned Line, LLVMMetadataRef *Elements, + unsigned NumElements) { + auto Elts = + (NumElements > 0) + ? unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements}) + : nullptr; + return wrap(unwrap(Builder)->createImportedModule( + unwrapDI<DIScope>(Scope), unwrapDI<DIModule>(M), unwrapDI<DIFile>(File), + Line, Elts)); } -LLVMMetadataRef -LLVMDIBuilderCreateImportedDeclaration(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - LLVMMetadataRef Decl, - LLVMMetadataRef File, - unsigned Line, - const char *Name, size_t NameLen) { +LLVMMetadataRef LLVMDIBuilderCreateImportedDeclaration( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, LLVMMetadataRef Decl, + LLVMMetadataRef File, unsigned Line, const char *Name, size_t NameLen, + LLVMMetadataRef *Elements, unsigned NumElements) { + auto Elts = + (NumElements > 0) + ? unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements}) + : nullptr; return wrap(unwrap(Builder)->createImportedDeclaration( - unwrapDI<DIScope>(Scope), - unwrapDI<DINode>(Decl), - unwrapDI<DIFile>(File), Line, {Name, NameLen})); + unwrapDI<DIScope>(Scope), unwrapDI<DINode>(Decl), unwrapDI<DIFile>(File), + Line, {Name, NameLen}, Elts)); } LLVMMetadataRef diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 7b0dab799e1a..b20e581d283a 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -82,8 +82,8 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, Storage, Context.pImpl->DILocations); } -const -DILocation *DILocation::getMergedLocations(ArrayRef<const DILocation *> Locs) { +const DILocation * +DILocation::getMergedLocations(ArrayRef<const DILocation *> Locs) { if (Locs.empty()) return nullptr; if (Locs.size() == 1) @@ -139,7 +139,8 @@ const DILocation *DILocation::getMergedLocation(const DILocation *LocA, return DILocation::get(Result->getContext(), 0, 0, S, L); } -Optional<unsigned> DILocation::encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI) { +Optional<unsigned> DILocation::encodeDiscriminator(unsigned BD, unsigned DF, + unsigned CI) { std::array<unsigned, 3> Components = {BD, DF, CI}; uint64_t RemainingWork = 0U; // We use RemainingWork to figure out if we have no remaining components to @@ -147,7 +148,8 @@ Optional<unsigned> DILocation::encodeDiscriminator(unsigned BD, unsigned DF, uns // encode anything for the latter 2. // Since any of the input components is at most 32 bits, their sum will be // less than 34 bits, and thus RemainingWork won't overflow. - RemainingWork = std::accumulate(Components.begin(), Components.end(), RemainingWork); + RemainingWork = + std::accumulate(Components.begin(), Components.end(), RemainingWork); int I = 0; unsigned Ret = 0; @@ -179,7 +181,6 @@ void DILocation::decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, getNextComponentInDiscriminator(getNextComponentInDiscriminator(D))); } - DINode::DIFlags DINode::getFlag(StringRef Flag) { return StringSwitch<DIFlags>(Flag) #define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME) @@ -546,8 +547,8 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag, DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)); Metadata *Ops[] = {nullptr, nullptr, Name}; - DEFINE_GETIMPL_STORE(DIBasicType, (Tag, SizeInBits, AlignInBits, Encoding, - Flags), Ops); + DEFINE_GETIMPL_STORE(DIBasicType, + (Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops); } Optional<DIBasicType::Signedness> DIBasicType::getSignedness() const { @@ -582,16 +583,17 @@ DIDerivedType *DIDerivedType::getImpl( unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate) { + Metadata *Annotations, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)); - Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; - DEFINE_GETIMPL_STORE( - DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags), Ops); + ExtraData, Annotations)); + Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData, Annotations}; + DEFINE_GETIMPL_STORE(DIDerivedType, + (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, + DWARFAddressSpace, Flags), + Ops); } DICompositeType *DICompositeType::getImpl( @@ -601,22 +603,25 @@ DICompositeType *DICompositeType::getImpl( Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank, StorageType Storage, bool ShouldCreate) { + Metadata *Rank, Metadata *Annotations, 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, Discriminator, DataLocation, Associated, Allocated, Rank)); + DEFINE_GETIMPL_LOOKUP(DICompositeType, + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, + RuntimeLang, VTableHolder, TemplateParams, Identifier, + Discriminator, DataLocation, Associated, Allocated, + Rank, Annotations)); Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation, Associated, Allocated, - Rank}; - DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits, - AlignInBits, OffsetInBits, Flags), - Ops); + Rank, Annotations}; + DEFINE_GETIMPL_STORE( + DICompositeType, + (Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags), + Ops); } DICompositeType *DICompositeType::buildODRType( @@ -626,7 +631,7 @@ DICompositeType *DICompositeType::buildODRType( DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank) { + Metadata *Rank, Metadata *Annotations) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; @@ -636,7 +641,10 @@ DICompositeType *DICompositeType::buildODRType( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier, Discriminator, - DataLocation, Associated, Allocated, Rank); + DataLocation, Associated, Allocated, Rank, Annotations); + + if (CT->getTag() != Tag) + return nullptr; // Only mutate CT if it's a forward declaration and the new operands aren't. assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?"); @@ -649,7 +657,7 @@ DICompositeType *DICompositeType::buildODRType( Metadata *Ops[] = {File, Scope, Name, BaseType, Elements, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, Allocated, - Rank}; + Rank, Annotations}; assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() && "Mismatched number of operands"); for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I) @@ -665,17 +673,21 @@ DICompositeType *DICompositeType::getODRType( DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, - Metadata *Rank) { + Metadata *Rank, Metadata *Annotations) { assert(!Identifier.getString().empty() && "Expected valid identifier"); if (!Context.isODRUniquingDebugTypes()) return nullptr; auto *&CT = (*Context.pImpl->DITypeMap)[&Identifier]; - if (!CT) + if (!CT) { CT = DICompositeType::getDistinct( Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation, Associated, - Allocated, Rank); + Allocated, Rank, Annotations); + } else { + if (CT->getTag() != Tag) + return nullptr; + } return CT; } @@ -789,10 +801,14 @@ DICompileUnit::getNameTableKind(StringRef Str) { const char *DICompileUnit::emissionKindString(DebugEmissionKind EK) { switch (EK) { - case NoDebug: return "NoDebug"; - case FullDebug: return "FullDebug"; - case LineTablesOnly: return "LineTablesOnly"; - case DebugDirectivesOnly: return "DebugDirectivesOnly"; + case NoDebug: + return "NoDebug"; + case FullDebug: + return "FullDebug"; + case LineTablesOnly: + return "LineTablesOnly"; + case DebugDirectivesOnly: + return "DebugDirectivesOnly"; } return nullptr; } @@ -862,23 +878,28 @@ DISubprogram *DISubprogram::getImpl( unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) { + Metadata *ThrownTypes, Metadata *Annotations, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DISubprogram, (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, Declaration, - RetainedNodes, ThrownTypes)); - SmallVector<Metadata *, 11> Ops = { - File, Scope, Name, LinkageName, Type, Unit, - Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes}; - if (!ThrownTypes) { + RetainedNodes, ThrownTypes, Annotations)); + SmallVector<Metadata *, 12> Ops = { + File, Scope, Name, LinkageName, + Type, Unit, Declaration, RetainedNodes, + ContainingType, TemplateParams, ThrownTypes, Annotations}; + if (!Annotations) { Ops.pop_back(); - if (!TemplateParams) { + if (!ThrownTypes) { Ops.pop_back(); - if (!ContainingType) + if (!TemplateParams) { Ops.pop_back(); + if (!ContainingType) + Ops.pop_back(); + } } } DEFINE_GETIMPL_STORE_N( @@ -977,13 +998,14 @@ DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, uint32_t AlignInBits, - StorageType Storage, bool ShouldCreate) { + Metadata *Annotations, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, (Scope, Name, LinkageName, File, Line, - Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, - TemplateParams, AlignInBits)); + DEFINE_GETIMPL_LOOKUP( + DIGlobalVariable, + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, + StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)); Metadata *Ops[] = {Scope, Name, File, @@ -991,27 +1013,26 @@ DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Name, LinkageName, StaticDataMemberDeclaration, - TemplateParams}; + TemplateParams, + Annotations}; DEFINE_GETIMPL_STORE(DIGlobalVariable, (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops); } -DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, Metadata *File, - unsigned Line, Metadata *Type, - unsigned Arg, DIFlags Flags, - uint32_t AlignInBits, - StorageType Storage, - bool ShouldCreate) { +DILocalVariable * +DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, + unsigned Arg, DIFlags Flags, uint32_t AlignInBits, + Metadata *Annotations, StorageType Storage, + bool ShouldCreate) { // 64K ought to be enough for any frontend. assert(Arg <= UINT16_MAX && "Expected argument number to fit in 16-bits"); assert(Scope && "Expected scope"); assert(isCanonical(Name) && "Expected canonical MDString"); - DEFINE_GETIMPL_LOOKUP(DILocalVariable, - (Scope, Name, File, Line, Type, Arg, Flags, - AlignInBits)); - Metadata *Ops[] = {Scope, Name, File, Type}; + DEFINE_GETIMPL_LOOKUP(DILocalVariable, (Scope, Name, File, Line, Type, Arg, + Flags, AlignInBits, Annotations)); + Metadata *Ops[] = {Scope, Name, File, Type, Annotations}; DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops); } @@ -1038,14 +1059,12 @@ Optional<uint64_t> DIVariable::getSizeInBits() const { return None; } -DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, - MDString *Name, Metadata *File, unsigned Line, - StorageType Storage, +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)); + DEFINE_GETIMPL_LOOKUP(DILabel, (Scope, Name, File, Line)); Metadata *Ops[] = {Scope, Name, File}; DEFINE_GETIMPL_STORE(DILabel, (Line), Ops); } @@ -1194,10 +1213,11 @@ bool DIExpression::isComplex() const { // kind of complex computation occurs. for (const auto &It : expr_ops()) { switch (It.getOp()) { - case dwarf::DW_OP_LLVM_tag_offset: - case dwarf::DW_OP_LLVM_fragment: - continue; - default: return true; + case dwarf::DW_OP_LLVM_tag_offset: + case dwarf::DW_OP_LLVM_fragment: + continue; + default: + return true; } } @@ -1346,8 +1366,7 @@ DIExpression *DIExpression::replaceArg(const DIExpression *Expr, DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr, SmallVectorImpl<uint64_t> &Ops, - bool StackValue, - bool EntryValue) { + bool StackValue, bool EntryValue) { assert(Expr && "Can't prepend ops to this expression"); if (EntryValue) { @@ -1442,7 +1461,8 @@ Optional<DIExpression *> DIExpression::createFragmentExpression( if (Expr) { for (auto Op : Expr->expr_ops()) { switch (Op.getOp()) { - default: break; + default: + break; case dwarf::DW_OP_shr: case dwarf::DW_OP_shra: case dwarf::DW_OP_shl: @@ -1476,6 +1496,45 @@ Optional<DIExpression *> DIExpression::createFragmentExpression( return DIExpression::get(Expr->getContext(), Ops); } +std::pair<DIExpression *, const ConstantInt *> +DIExpression::constantFold(const ConstantInt *CI) { + // Copy the APInt so we can modify it. + APInt NewInt = CI->getValue(); + SmallVector<uint64_t, 8> Ops; + + // Fold operators only at the beginning of the expression. + bool First = true; + bool Changed = false; + for (auto Op : expr_ops()) { + switch (Op.getOp()) { + default: + // We fold only the leading part of the expression; if we get to a part + // that we're going to copy unchanged, and haven't done any folding, + // then the entire expression is unchanged and we can return early. + if (!Changed) + return {this, CI}; + First = false; + break; + case dwarf::DW_OP_LLVM_convert: + if (!First) + break; + Changed = true; + if (Op.getArg(1) == dwarf::DW_ATE_signed) + NewInt = NewInt.sextOrTrunc(Op.getArg(0)); + else { + assert(Op.getArg(1) == dwarf::DW_ATE_unsigned && "Unexpected operand"); + NewInt = NewInt.zextOrTrunc(Op.getArg(0)); + } + continue; + } + Op.appendToVector(Ops); + } + if (!Changed) + return {this, CI}; + return {DIExpression::get(getContext(), Ops), + ConstantInt::get(getContext(), NewInt)}; +} + uint64_t DIExpression::getNumLocationOperands() const { uint64_t Result = 0; for (auto ExprOp : expr_ops()) @@ -1552,21 +1611,22 @@ DIObjCProperty *DIObjCProperty::getImpl( DIImportedEntity *DIImportedEntity::getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File, unsigned Line, - MDString *Name, StorageType Storage, + MDString *Name, Metadata *Elements, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIImportedEntity, - (Tag, Scope, Entity, File, Line, Name)); - Metadata *Ops[] = {Scope, Entity, Name, File}; + (Tag, Scope, Entity, File, Line, Name, Elements)); + Metadata *Ops[] = {Scope, Entity, Name, File, Elements}; DEFINE_GETIMPL_STORE(DIImportedEntity, (Tag, Line), Ops); } -DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType, - unsigned Line, MDString *Name, MDString *Value, - StorageType Storage, bool ShouldCreate) { +DIMacro *DIMacro::getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, + MDString *Name, MDString *Value, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIMacro, (MIType, Line, Name, Value)); - Metadata *Ops[] = { Name, Value }; + Metadata *Ops[] = {Name, Value}; DEFINE_GETIMPL_STORE(DIMacro, (MIType, Line), Ops); } @@ -1574,9 +1634,8 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, Metadata *File, Metadata *Elements, StorageType Storage, bool ShouldCreate) { - DEFINE_GETIMPL_LOOKUP(DIMacroFile, - (MIType, Line, File, Elements)); - Metadata *Ops[] = { File, Elements }; + DEFINE_GETIMPL_LOOKUP(DIMacroFile, (MIType, Line, File, Elements)); + Metadata *Ops[] = {File, Elements}; DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops); } @@ -1592,6 +1651,12 @@ void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { assert((!New || isa<ValueAsMetadata>(New)) && "DIArgList must be passed a ValueAsMetadata"); untrack(); + bool Uniq = isUniqued(); + if (Uniq) { + // We need to update the uniqueness once the Args are updated since they + // form the key to the DIArgLists store. + eraseFromStore(); + } ValueAsMetadata *NewVM = cast_or_null<ValueAsMetadata>(New); for (ValueAsMetadata *&VM : Args) { if (&VM == OldVMPtr) { @@ -1601,6 +1666,10 @@ void DIArgList::handleChangedOperand(void *Ref, Metadata *New) { VM = ValueAsMetadata::get(UndefValue::get(VM->getValue()->getType())); } } + if (Uniq) { + if (uniquify() != this) + storeDistinctInContext(); + } track(); } void DIArgList::track() { diff --git a/llvm/lib/IR/DiagnosticHandler.cpp b/llvm/lib/IR/DiagnosticHandler.cpp index 2fe634803894..7b40728a34e8 100644 --- a/llvm/lib/IR/DiagnosticHandler.cpp +++ b/llvm/lib/IR/DiagnosticHandler.cpp @@ -30,7 +30,7 @@ struct PassRemarksOpt { Pattern = std::make_shared<Regex>(Val); std::string RegexError; if (!Pattern->isValid(RegexError)) - report_fatal_error("Invalid regular expression '" + Val + + report_fatal_error(Twine("Invalid regular expression '") + Val + "' in -pass-remarks: " + RegexError, false); } diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp index f92138274801..0a872a81f911 100644 --- a/llvm/lib/IR/DiagnosticInfo.cpp +++ b/llvm/lib/IR/DiagnosticInfo.cpp @@ -1,4 +1,4 @@ -//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===// +//===- llvm/IR/DiagnosticInfo.cpp - Diagnostic Definitions ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -70,10 +70,8 @@ void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const { } void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const { - DP << getResourceName() << " (" << getResourceSize() << ") exceeds limit"; - if (getResourceLimit() != 0) - DP << " (" << getResourceLimit() << ')'; - DP << " in function '" << getFunction() << '\''; + DP << getResourceName() << " (" << getResourceSize() << ") exceeds limit (" + << getResourceLimit() << ") in function '" << getFunction() << '\''; } void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const { @@ -401,3 +399,35 @@ std::string DiagnosticInfoOptimizationBase::getMsg() const { void OptimizationRemarkAnalysisFPCommute::anchor() {} void OptimizationRemarkAnalysisAliasing::anchor() {} + +void llvm::diagnoseDontCall(const CallInst &CI) { + auto *F = CI.getCalledFunction(); + if (!F) + return; + + for (int i = 0; i != 2; ++i) { + auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn"; + auto Sev = i == 0 ? DS_Error : DS_Warning; + + if (F->hasFnAttribute(AttrName)) { + unsigned LocCookie = 0; + auto A = F->getFnAttribute(AttrName); + if (MDNode *MD = CI.getMetadata("srcloc")) + LocCookie = + mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue(); + DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev, + LocCookie); + F->getContext().diagnose(D); + } + } +} + +void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const { + DP << "call to " << getFunctionName() << " marked \"dontcall-"; + if (getSeverity() == DiagnosticSeverity::DS_Error) + DP << "error\""; + else + DP << "warn\""; + if (!getNote().empty()) + DP << ": " << getNote(); +} diff --git a/llvm/lib/IR/DiagnosticPrinter.cpp b/llvm/lib/IR/DiagnosticPrinter.cpp index 496bd18e78e2..49b8bbae53be 100644 --- a/llvm/lib/IR/DiagnosticPrinter.cpp +++ b/llvm/lib/IR/DiagnosticPrinter.cpp @@ -1,4 +1,4 @@ -//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===// +//===- llvm/IR/DiagnosticPrinter.cpp - Diagnostic Printer -------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/lib/IR/FPEnv.cpp b/llvm/lib/IR/FPEnv.cpp index 516c702acec7..c6e0938e71a6 100644 --- a/llvm/lib/IR/FPEnv.cpp +++ b/llvm/lib/IR/FPEnv.cpp @@ -17,7 +17,7 @@ namespace llvm { -Optional<RoundingMode> StrToRoundingMode(StringRef RoundingArg) { +Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) { // For dynamic rounding mode, we use round to nearest but we will set the // 'exact' SDNodeFlag so that the value will not be rounded. return StringSwitch<Optional<RoundingMode>>(RoundingArg) @@ -30,7 +30,7 @@ Optional<RoundingMode> StrToRoundingMode(StringRef RoundingArg) { .Default(None); } -Optional<StringRef> RoundingModeToStr(RoundingMode UseRounding) { +Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) { Optional<StringRef> RoundingStr = None; switch (UseRounding) { case RoundingMode::Dynamic: @@ -57,7 +57,8 @@ Optional<StringRef> RoundingModeToStr(RoundingMode UseRounding) { return RoundingStr; } -Optional<fp::ExceptionBehavior> StrToExceptionBehavior(StringRef ExceptionArg) { +Optional<fp::ExceptionBehavior> +convertStrToExceptionBehavior(StringRef ExceptionArg) { return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg) .Case("fpexcept.ignore", fp::ebIgnore) .Case("fpexcept.maytrap", fp::ebMayTrap) @@ -65,7 +66,8 @@ Optional<fp::ExceptionBehavior> StrToExceptionBehavior(StringRef ExceptionArg) { .Default(None); } -Optional<StringRef> ExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) { +Optional<StringRef> +convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) { Optional<StringRef> ExceptStr = None; switch (UseExcept) { case fp::ebStrict: diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 4034b1505bd0..82b20a8af91b 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -140,25 +140,25 @@ bool Argument::hasPreallocatedAttr() const { bool Argument::hasPassPointeeByValueCopyAttr() const { if (!getType()->isPointerTy()) return false; AttributeList Attrs = getParent()->getAttributes(); - return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) || - Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) || - Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated); + return Attrs.hasParamAttr(getArgNo(), Attribute::ByVal) || + Attrs.hasParamAttr(getArgNo(), Attribute::InAlloca) || + Attrs.hasParamAttr(getArgNo(), Attribute::Preallocated); } bool Argument::hasPointeeInMemoryValueAttr() const { if (!getType()->isPointerTy()) return false; AttributeList Attrs = getParent()->getAttributes(); - return Attrs.hasParamAttribute(getArgNo(), Attribute::ByVal) || - Attrs.hasParamAttribute(getArgNo(), Attribute::StructRet) || - Attrs.hasParamAttribute(getArgNo(), Attribute::InAlloca) || - Attrs.hasParamAttribute(getArgNo(), Attribute::Preallocated) || - Attrs.hasParamAttribute(getArgNo(), Attribute::ByRef); + return Attrs.hasParamAttr(getArgNo(), Attribute::ByVal) || + Attrs.hasParamAttr(getArgNo(), Attribute::StructRet) || + Attrs.hasParamAttr(getArgNo(), Attribute::InAlloca) || + Attrs.hasParamAttr(getArgNo(), Attribute::Preallocated) || + Attrs.hasParamAttr(getArgNo(), Attribute::ByRef); } /// For a byval, sret, inalloca, or preallocated parameter, get the in-memory /// parameter type. -static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) { +static Type *getMemoryParamAllocType(AttributeSet ParamAttrs) { // FIXME: All the type carrying attributes are mutually exclusive, so there // should be a single query to get the stored type that handles any of them. if (Type *ByValTy = ParamAttrs.getByValType()) @@ -177,19 +177,19 @@ static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) { uint64_t Argument::getPassPointeeByValueCopySize(const DataLayout &DL) const { AttributeSet ParamAttrs = - getParent()->getAttributes().getParamAttributes(getArgNo()); - if (Type *MemTy = getMemoryParamAllocType(ParamAttrs, getType())) + getParent()->getAttributes().getParamAttrs(getArgNo()); + if (Type *MemTy = getMemoryParamAllocType(ParamAttrs)) return DL.getTypeAllocSize(MemTy); return 0; } Type *Argument::getPointeeInMemoryValueType() const { AttributeSet ParamAttrs = - getParent()->getAttributes().getParamAttributes(getArgNo()); - return getMemoryParamAllocType(ParamAttrs, getType()); + getParent()->getAttributes().getParamAttrs(getArgNo()); + return getMemoryParamAllocType(ParamAttrs); } -unsigned Argument::getParamAlignment() const { +uint64_t Argument::getParamAlignment() const { assert(getType()->isPointerTy() && "Only pointers have alignments"); return getParent()->getParamAlignment(getArgNo()); } @@ -278,8 +278,8 @@ bool Argument::hasSExtAttr() const { bool Argument::onlyReadsMemory() const { AttributeList Attrs = getParent()->getAttributes(); - return Attrs.hasParamAttribute(getArgNo(), Attribute::ReadOnly) || - Attrs.hasParamAttribute(getArgNo(), Attribute::ReadNone); + return Attrs.hasParamAttr(getArgNo(), Attribute::ReadOnly) || + Attrs.hasParamAttr(getArgNo(), Attribute::ReadNone); } void Argument::addAttrs(AttrBuilder &B) { @@ -354,7 +354,7 @@ Function *Function::createWithDefaultAttr(FunctionType *Ty, B.addAttribute("frame-pointer", "all"); break; } - F->addAttributes(AttributeList::FunctionIndex, B); + F->addFnAttrs(B); return F; } @@ -529,101 +529,144 @@ void Function::dropAllReferences() { clearMetadata(); } -void Function::addAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Kind); - setAttributes(PAL); +void Function::addAttributeAtIndex(unsigned i, Attribute Attr) { + AttributeSets = AttributeSets.addAttributeAtIndex(getContext(), i, Attr); } -void Function::addAttribute(unsigned i, Attribute Attr) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttribute(getContext(), i, Attr); - setAttributes(PAL); +void Function::addFnAttr(Attribute::AttrKind Kind) { + AttributeSets = AttributeSets.addFnAttribute(getContext(), Kind); } -void Function::addAttributes(unsigned i, const AttrBuilder &Attrs) { - AttributeList PAL = getAttributes(); - PAL = PAL.addAttributes(getContext(), i, Attrs); - setAttributes(PAL); +void Function::addFnAttr(StringRef Kind, StringRef Val) { + AttributeSets = AttributeSets.addFnAttribute(getContext(), Kind, Val); +} + +void Function::addFnAttr(Attribute Attr) { + AttributeSets = AttributeSets.addFnAttribute(getContext(), Attr); +} + +void Function::addFnAttrs(const AttrBuilder &Attrs) { + AttributeSets = AttributeSets.addFnAttributes(getContext(), Attrs); +} + +void Function::addRetAttr(Attribute::AttrKind Kind) { + AttributeSets = AttributeSets.addRetAttribute(getContext(), Kind); +} + +void Function::addRetAttr(Attribute Attr) { + AttributeSets = AttributeSets.addRetAttribute(getContext(), Attr); +} + +void Function::addRetAttrs(const AttrBuilder &Attrs) { + AttributeSets = AttributeSets.addRetAttributes(getContext(), Attrs); } void Function::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); + AttributeSets = AttributeSets.addParamAttribute(getContext(), ArgNo, Kind); } void Function::addParamAttr(unsigned ArgNo, Attribute Attr) { - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr); - setAttributes(PAL); + AttributeSets = AttributeSets.addParamAttribute(getContext(), ArgNo, Attr); } void Function::addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs) { - AttributeList PAL = getAttributes(); - PAL = PAL.addParamAttributes(getContext(), ArgNo, Attrs); - setAttributes(PAL); + AttributeSets = AttributeSets.addParamAttributes(getContext(), ArgNo, Attrs); } -void Function::removeAttribute(unsigned i, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); +void Function::removeAttributeAtIndex(unsigned i, Attribute::AttrKind Kind) { + AttributeSets = AttributeSets.removeAttributeAtIndex(getContext(), i, Kind); } -void Function::removeAttribute(unsigned i, StringRef Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttribute(getContext(), i, Kind); - setAttributes(PAL); +void Function::removeAttributeAtIndex(unsigned i, StringRef Kind) { + AttributeSets = AttributeSets.removeAttributeAtIndex(getContext(), i, Kind); } -void Function::removeAttributes(unsigned i, const AttrBuilder &Attrs) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeAttributes(getContext(), i, Attrs); - setAttributes(PAL); +void Function::removeFnAttr(Attribute::AttrKind Kind) { + AttributeSets = AttributeSets.removeFnAttribute(getContext(), Kind); +} + +void Function::removeFnAttr(StringRef Kind) { + AttributeSets = AttributeSets.removeFnAttribute(getContext(), Kind); +} + +void Function::removeFnAttrs(const AttrBuilder &Attrs) { + AttributeSets = AttributeSets.removeFnAttributes(getContext(), Attrs); +} + +void Function::removeRetAttr(Attribute::AttrKind Kind) { + AttributeSets = AttributeSets.removeRetAttribute(getContext(), Kind); +} + +void Function::removeRetAttr(StringRef Kind) { + AttributeSets = AttributeSets.removeRetAttribute(getContext(), Kind); +} + +void Function::removeRetAttrs(const AttrBuilder &Attrs) { + AttributeSets = AttributeSets.removeRetAttributes(getContext(), Attrs); } void Function::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); + AttributeSets = AttributeSets.removeParamAttribute(getContext(), ArgNo, Kind); } void Function::removeParamAttr(unsigned ArgNo, StringRef Kind) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); - setAttributes(PAL); + AttributeSets = AttributeSets.removeParamAttribute(getContext(), ArgNo, Kind); } void Function::removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs) { - AttributeList PAL = getAttributes(); - PAL = PAL.removeParamAttributes(getContext(), ArgNo, Attrs); - setAttributes(PAL); + AttributeSets = + AttributeSets.removeParamAttributes(getContext(), ArgNo, Attrs); +} + +void Function::addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes) { + AttributeSets = + AttributeSets.addDereferenceableParamAttr(getContext(), ArgNo, Bytes); } -void Function::addDereferenceableAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); - setAttributes(PAL); +bool Function::hasFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasFnAttr(Kind); } -void Function::addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableParamAttr(getContext(), ArgNo, Bytes); - setAttributes(PAL); +bool Function::hasFnAttribute(StringRef Kind) const { + return AttributeSets.hasFnAttr(Kind); +} + +bool Function::hasRetAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.hasRetAttr(Kind); +} + +bool Function::hasParamAttribute(unsigned ArgNo, + Attribute::AttrKind Kind) const { + return AttributeSets.hasParamAttr(ArgNo, Kind); +} + +Attribute Function::getAttributeAtIndex(unsigned i, + Attribute::AttrKind Kind) const { + return AttributeSets.getAttributeAtIndex(i, Kind); +} + +Attribute Function::getAttributeAtIndex(unsigned i, StringRef Kind) const { + return AttributeSets.getAttributeAtIndex(i, Kind); } -void Function::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); - setAttributes(PAL); +Attribute Function::getFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getFnAttr(Kind); +} + +Attribute Function::getFnAttribute(StringRef Kind) const { + return AttributeSets.getFnAttr(Kind); +} + +/// gets the specified attribute from the list of attributes. +Attribute Function::getParamAttribute(unsigned ArgNo, + Attribute::AttrKind Kind) const { + return AttributeSets.getParamAttr(ArgNo, Kind); } void Function::addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes) { - AttributeList PAL = getAttributes(); - PAL = PAL.addDereferenceableOrNullParamAttr(getContext(), ArgNo, Bytes); - setAttributes(PAL); + AttributeSets = AttributeSets.addDereferenceableOrNullParamAttr(getContext(), + ArgNo, Bytes); } DenormalMode Function::getDenormalMode(const fltSemantics &FPType) const { @@ -936,7 +979,8 @@ enum IIT_Info { IIT_BF16 = 48, IIT_STRUCT9 = 49, IIT_V256 = 50, - IIT_AMX = 51 + IIT_AMX = 51, + IIT_PPCF128 = 52 }; static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, @@ -983,6 +1027,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, case IIT_F128: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0)); return; + case IIT_PPCF128: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::PPCQuad, 0)); + return; case IIT_I1: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1)); return; @@ -1207,6 +1254,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos, case IITDescriptor::Float: return Type::getFloatTy(Context); case IITDescriptor::Double: return Type::getDoubleTy(Context); case IITDescriptor::Quad: return Type::getFP128Ty(Context); + case IITDescriptor::PPCQuad: return Type::getPPC_FP128Ty(Context); case IITDescriptor::Integer: return IntegerType::get(Context, D.Integer_Width); @@ -1389,6 +1437,7 @@ static bool matchIntrinsicType( case IITDescriptor::Float: return !Ty->isFloatTy(); case IITDescriptor::Double: return !Ty->isDoubleTy(); case IITDescriptor::Quad: return !Ty->isFP128Ty(); + case IITDescriptor::PPCQuad: return !Ty->isPPC_FP128Ty(); case IITDescriptor::Integer: return !Ty->isIntegerTy(D.Integer_Width); case IITDescriptor::Vector: { VectorType *VT = dyn_cast<VectorType>(Ty); @@ -1403,11 +1452,6 @@ static bool matchIntrinsicType( if (!PT->isOpaque()) return matchIntrinsicType(PT->getElementType(), Infos, ArgTys, DeferredChecks, IsDeferredCheck); - // If typed pointers are supported, do not allow using opaque pointer in - // place of fixed pointer type. This would make the intrinsic signature - // non-unique. - if (Ty->getContext().supportsTypedPointers()) - return true; // Consume IIT descriptors relating to the pointer element type. while (Infos.front().Kind == IITDescriptor::Pointer) Infos = Infos.slice(1); @@ -1525,11 +1569,8 @@ static bool matchIntrinsicType( if (!ThisArgType || !ReferenceType) return true; - if (!ThisArgType->isOpaque()) - return ThisArgType->getElementType() != ReferenceType->getElementType(); - // If typed pointers are supported, do not allow opaque pointer to ensure - // uniqueness. - return Ty->getContext().supportsTypedPointers(); + return !ThisArgType->isOpaqueOrPointeeTypeMatches( + ReferenceType->getElementType()); } case IITDescriptor::VecOfAnyPtrsToElt: { unsigned RefArgNumber = D.getRefArgNumber(); @@ -1702,8 +1743,8 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) { /// and llvm.compiler.used variables. bool Function::hasAddressTaken(const User **PutOffender, bool IgnoreCallbackUses, - bool IgnoreAssumeLikeCalls, - bool IgnoreLLVMUsed) const { + bool IgnoreAssumeLikeCalls, bool IgnoreLLVMUsed, + bool IgnoreARCAttachedCall) const { for (const Use &U : uses()) { const User *FU = U.getUser(); if (isa<BlockAddress>(FU)) @@ -1747,6 +1788,11 @@ bool Function::hasAddressTaken(const User **PutOffender, return true; } if (!Call->isCallee(&U)) { + if (IgnoreARCAttachedCall && + Call->isOperandBundleOfType(LLVMContext::OB_clang_arc_attachedcall, + U.getOperandNo())) + continue; + if (PutOffender) *PutOffender = FU; return true; @@ -1846,10 +1892,9 @@ void Function::setValueSubclassDataBit(unsigned Bit, bool On) { 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()); + assert(!PrevCount.hasValue() || PrevCount->getType() == Count.getType()); #endif auto ImportGUIDs = getImportGUIDs(); @@ -1867,7 +1912,7 @@ void Function::setEntryCount(uint64_t Count, Function::ProfileCountType Type, setEntryCount(ProfileCount(Count, Type), Imports); } -ProfileCount Function::getEntryCount(bool AllowSynthetic) const { +Optional<ProfileCount> Function::getEntryCount(bool AllowSynthetic) const { MDNode *MD = getMetadata(LLVMContext::MD_prof); if (MD && MD->getOperand(0)) if (MDString *MDS = dyn_cast<MDString>(MD->getOperand(0))) { @@ -1877,7 +1922,7 @@ ProfileCount Function::getEntryCount(bool AllowSynthetic) const { // 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 ProfileCount::getInvalid(); + return None; return ProfileCount(Count, PCT_Real); } else if (AllowSynthetic && MDS->getString().equals("synthetic_function_entry_count")) { @@ -1886,7 +1931,7 @@ ProfileCount Function::getEntryCount(bool AllowSynthetic) const { return ProfileCount(Count, PCT_Synthetic); } } - return ProfileCount::getInvalid(); + return None; } DenseSet<GlobalValue::GUID> Function::getImportGUIDs() const { diff --git a/llvm/lib/IR/GCStrategy.cpp b/llvm/lib/IR/GCStrategy.cpp index 25dad5bec9ef..f3bc5b74f8fd 100644 --- a/llvm/lib/IR/GCStrategy.cpp +++ b/llvm/lib/IR/GCStrategy.cpp @@ -18,3 +18,21 @@ using namespace llvm; LLVM_INSTANTIATE_REGISTRY(GCRegistry) GCStrategy::GCStrategy() = default; + +std::unique_ptr<GCStrategy> llvm::getGCStrategy(const StringRef Name) { + for (auto &S : GCRegistry::entries()) + if (S.getName() == Name) + return S.instantiate(); + + if (GCRegistry::begin() == GCRegistry::end()) { + // In normal operation, the registry should not be empty. There should + // be the builtin GCs if nothing else. The most likely scenario here is + // that we got here without running the initializers used by the Registry + // itself and it's registration mechanism. + const std::string error = + std::string("unsupported GC: ") + Name.str() + + " (did you remember to link and initialize the library?)"; + report_fatal_error(error); + } else + report_fatal_error(std::string("unsupported GC: ") + Name.str()); +} diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index b1c6dcc6672d..9f38288095e3 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -162,7 +162,7 @@ std::string GlobalValue::getGlobalIdentifier() const { StringRef GlobalValue::getSection() const { if (auto *GA = dyn_cast<GlobalAlias>(this)) { // In general we cannot compute this at the IR level, but we try. - if (const GlobalObject *GO = GA->getBaseObject()) + if (const GlobalObject *GO = GA->getAliaseeObject()) return GO->getSection(); return ""; } @@ -172,7 +172,7 @@ StringRef GlobalValue::getSection() const { const Comdat *GlobalValue::getComdat() const { if (auto *GA = dyn_cast<GlobalAlias>(this)) { // In general we cannot compute this at the IR level, but we try. - if (const GlobalObject *GO = GA->getBaseObject()) + if (const GlobalObject *GO = GA->getAliaseeObject()) return const_cast<GlobalObject *>(GO)->getComdat(); return nullptr; } @@ -235,7 +235,7 @@ bool GlobalValue::isDeclaration() const { return F->empty() && !F->isMaterializable(); // Aliases and ifuncs are always definitions. - assert(isa<GlobalIndirectSymbol>(this)); + assert(isa<GlobalAlias>(this) || isa<GlobalIFunc>(this)); return false; } @@ -280,14 +280,44 @@ bool GlobalObject::canIncreaseAlignment() const { return true; } -const GlobalObject *GlobalValue::getBaseObject() const { - if (auto *GO = dyn_cast<GlobalObject>(this)) +static const GlobalObject * +findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases) { + if (auto *GO = dyn_cast<GlobalObject>(C)) return GO; - if (auto *GA = dyn_cast<GlobalIndirectSymbol>(this)) - return GA->getBaseObject(); + if (auto *GA = dyn_cast<GlobalAlias>(C)) + if (Aliases.insert(GA).second) + return findBaseObject(GA->getOperand(0), Aliases); + if (auto *CE = dyn_cast<ConstantExpr>(C)) { + switch (CE->getOpcode()) { + case Instruction::Add: { + auto *LHS = findBaseObject(CE->getOperand(0), Aliases); + auto *RHS = findBaseObject(CE->getOperand(1), Aliases); + if (LHS && RHS) + return nullptr; + return LHS ? LHS : RHS; + } + case Instruction::Sub: { + if (findBaseObject(CE->getOperand(1), Aliases)) + return nullptr; + return findBaseObject(CE->getOperand(0), Aliases); + } + case Instruction::IntToPtr: + case Instruction::PtrToInt: + case Instruction::BitCast: + case Instruction::GetElementPtr: + return findBaseObject(CE->getOperand(0), Aliases); + default: + break; + } + } return nullptr; } +const GlobalObject *GlobalValue::getAliaseeObject() const { + DenseSet<const GlobalAlias *> Aliases; + return findBaseObject(this, Aliases); +} + bool GlobalValue::isAbsoluteSymbolRef() const { auto *GO = dyn_cast<GlobalObject>(this); if (!GO) @@ -421,63 +451,15 @@ void GlobalVariable::dropAllReferences() { } //===----------------------------------------------------------------------===// -// GlobalIndirectSymbol Implementation -//===----------------------------------------------------------------------===// - -GlobalIndirectSymbol::GlobalIndirectSymbol(Type *Ty, ValueTy VTy, - unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, - Constant *Symbol) - : GlobalValue(Ty, VTy, &Op<0>(), 1, Linkage, Name, AddressSpace) { - Op<0>() = Symbol; -} - -static const GlobalObject * -findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases) { - if (auto *GO = dyn_cast<GlobalObject>(C)) - return GO; - if (auto *GA = dyn_cast<GlobalAlias>(C)) - if (Aliases.insert(GA).second) - return findBaseObject(GA->getOperand(0), Aliases); - if (auto *CE = dyn_cast<ConstantExpr>(C)) { - switch (CE->getOpcode()) { - case Instruction::Add: { - auto *LHS = findBaseObject(CE->getOperand(0), Aliases); - auto *RHS = findBaseObject(CE->getOperand(1), Aliases); - if (LHS && RHS) - return nullptr; - return LHS ? LHS : RHS; - } - case Instruction::Sub: { - if (findBaseObject(CE->getOperand(1), Aliases)) - return nullptr; - return findBaseObject(CE->getOperand(0), Aliases); - } - case Instruction::IntToPtr: - case Instruction::PtrToInt: - case Instruction::BitCast: - case Instruction::GetElementPtr: - return findBaseObject(CE->getOperand(0), Aliases); - default: - break; - } - } - return nullptr; -} - -const GlobalObject *GlobalIndirectSymbol::getBaseObject() const { - DenseSet<const GlobalAlias *> Aliases; - return findBaseObject(getOperand(0), Aliases); -} - -//===----------------------------------------------------------------------===// // GlobalAlias Implementation //===----------------------------------------------------------------------===// GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, const Twine &Name, Constant *Aliasee, Module *ParentModule) - : GlobalIndirectSymbol(Ty, Value::GlobalAliasVal, AddressSpace, Link, Name, - Aliasee) { + : GlobalValue(Ty, Value::GlobalAliasVal, &Op<0>(), 1, Link, Name, + AddressSpace) { + setAliasee(Aliasee); if (ParentModule) ParentModule->getAliasList().push_back(this); } @@ -521,7 +503,12 @@ void GlobalAlias::eraseFromParent() { void GlobalAlias::setAliasee(Constant *Aliasee) { assert((!Aliasee || Aliasee->getType() == getType()) && "Alias and aliasee types should match!"); - setIndirectSymbol(Aliasee); + Op<0>().set(Aliasee); +} + +const GlobalObject *GlobalAlias::getAliaseeObject() const { + DenseSet<const GlobalAlias *> Aliases; + return findBaseObject(getOperand(0), Aliases); } //===----------------------------------------------------------------------===// @@ -531,8 +518,9 @@ void GlobalAlias::setAliasee(Constant *Aliasee) { GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link, const Twine &Name, Constant *Resolver, Module *ParentModule) - : GlobalIndirectSymbol(Ty, Value::GlobalIFuncVal, AddressSpace, Link, Name, - Resolver) { + : GlobalObject(Ty, Value::GlobalIFuncVal, &Op<0>(), 1, Link, Name, + AddressSpace) { + setResolver(Resolver); if (ParentModule) ParentModule->getIFuncList().push_back(this); } @@ -550,3 +538,8 @@ void GlobalIFunc::removeFromParent() { void GlobalIFunc::eraseFromParent() { getParent()->getIFuncList().erase(getIterator()); } + +const Function *GlobalIFunc::getResolverFunction() const { + DenseSet<const GlobalAlias *> Aliases; + return dyn_cast<Function>(findBaseObject(getResolver(), Aliases)); +} diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 0f4945bad5ab..98f6ccf81973 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -94,11 +94,22 @@ Value *IRBuilderBase::CreateVScale(Constant *Scaling, const Twine &Name) { } Value *IRBuilderBase::CreateStepVector(Type *DstType, const Twine &Name) { - if (isa<ScalableVectorType>(DstType)) - return CreateIntrinsic(Intrinsic::experimental_stepvector, {DstType}, {}, - nullptr, Name); - Type *STy = DstType->getScalarType(); + if (isa<ScalableVectorType>(DstType)) { + Type *StepVecType = DstType; + // TODO: We expect this special case (element type < 8 bits) to be + // temporary - once the intrinsic properly supports < 8 bits this code + // can be removed. + if (STy->getScalarSizeInBits() < 8) + StepVecType = + VectorType::get(getInt8Ty(), cast<ScalableVectorType>(DstType)); + Value *Res = CreateIntrinsic(Intrinsic::experimental_stepvector, + {StepVecType}, {}, nullptr, Name); + if (StepVecType != DstType) + Res = CreateTrunc(Res, DstType); + return Res; + } + unsigned NumEls = cast<FixedVectorType>(DstType)->getNumElements(); // Create a vector of consecutive numbers from zero to VF. diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 937dc6957806..a4659da7e807 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -141,6 +141,10 @@ bool Instruction::hasNoSignedWrap() const { return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap(); } +bool Instruction::hasPoisonGeneratingFlags() const { + return cast<Operator>(this)->hasPoisonGeneratingFlags(); +} + void Instruction::dropPoisonGeneratingFlags() { switch (getOpcode()) { case Instruction::Add: @@ -163,6 +167,8 @@ void Instruction::dropPoisonGeneratingFlags() { break; } // TODO: FastMathFlags! + + assert(!hasPoisonGeneratingFlags() && "must be kept in sync"); } void Instruction::dropUndefImplyingAttrsAndUnknownMetadata( @@ -178,9 +184,9 @@ void Instruction::dropUndefImplyingAttrsAndUnknownMetadata( if (AL.isEmpty()) return; AttrBuilder UBImplyingAttributes = AttributeFuncs::getUBImplyingAttributes(); - for (unsigned ArgNo = 0; ArgNo < CB->getNumArgOperands(); ArgNo++) + for (unsigned ArgNo = 0; ArgNo < CB->arg_size(); ArgNo++) CB->removeParamAttrs(ArgNo, UBImplyingAttributes); - CB->removeAttributes(AttributeList::ReturnIndex, UBImplyingAttributes); + CB->removeRetAttrs(UBImplyingAttributes); } bool Instruction::isExact() const { @@ -307,20 +313,20 @@ void Instruction::copyIRFlags(const Value *V, bool IncludeWrapFlags) { if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V)) if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this)) - DestGEP->setIsInBounds(SrcGEP->isInBounds() | DestGEP->isInBounds()); + DestGEP->setIsInBounds(SrcGEP->isInBounds() || DestGEP->isInBounds()); } void Instruction::andIRFlags(const Value *V) { if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) { if (isa<OverflowingBinaryOperator>(this)) { - setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); - setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + setHasNoSignedWrap(hasNoSignedWrap() && OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() && OB->hasNoUnsignedWrap()); } } if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) if (isa<PossiblyExactOperator>(this)) - setIsExact(isExact() & PE->isExact()); + setIsExact(isExact() && PE->isExact()); if (auto *FP = dyn_cast<FPMathOperator>(V)) { if (isa<FPMathOperator>(this)) { @@ -332,7 +338,7 @@ void Instruction::andIRFlags(const Value *V) { if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(V)) if (auto *DestGEP = dyn_cast<GetElementPtrInst>(this)) - DestGEP->setIsInBounds(SrcGEP->isInBounds() & DestGEP->isInBounds()); + DestGEP->setIsInBounds(SrcGEP->isInBounds() && DestGEP->isInBounds()); } const char *Instruction::getOpcodeName(unsigned OpCode) { diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 5b01c70dec8d..c42df49d97ea 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -318,9 +318,8 @@ bool CallBase::isReturnNonNull() const { if (hasRetAttr(Attribute::NonNull)) return true; - if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 && - !NullPointerIsDefined(getCaller(), - getType()->getPointerAddressSpace())) + if (getRetDereferenceableBytes() > 0 && + !NullPointerIsDefined(getCaller(), getType()->getPointerAddressSpace())) return true; return false; @@ -329,11 +328,10 @@ bool CallBase::isReturnNonNull() const { Value *CallBase::getReturnedArgOperand() const { unsigned Index; - if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) + if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index)) return getArgOperand(Index - AttributeList::FirstArgIndex); if (const Function *F = getCalledFunction()) - if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && - Index) + if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index)) return getArgOperand(Index - AttributeList::FirstArgIndex); return nullptr; @@ -341,24 +339,36 @@ Value *CallBase::getReturnedArgOperand() const { /// Determine whether the argument or parameter has the given attribute. bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { - assert(ArgNo < getNumArgOperands() && "Param index out of bounds!"); + assert(ArgNo < arg_size() && "Param index out of bounds!"); - if (Attrs.hasParamAttribute(ArgNo, Kind)) + if (Attrs.hasParamAttr(ArgNo, Kind)) return true; if (const Function *F = getCalledFunction()) - return F->getAttributes().hasParamAttribute(ArgNo, Kind); + return F->getAttributes().hasParamAttr(ArgNo, Kind); return false; } bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttribute(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (auto *F = dyn_cast<Function>(V)) + return F->getAttributes().hasFnAttr(Kind); + return false; } bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const { - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasFnAttribute(Kind); + Value *V = getCalledOperand(); + if (auto *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == BitCast) + V = CE->getOperand(0); + + if (auto *F = dyn_cast<Function>(V)) + return F->getAttributes().hasFnAttr(Kind); + return false; } @@ -933,7 +943,7 @@ void CallBrInst::updateArgBlockAddresses(unsigned i, BasicBlock *B) { if (BasicBlock *OldBB = getIndirectDest(i)) { BlockAddress *Old = BlockAddress::get(OldBB); BlockAddress *New = BlockAddress::get(B); - for (unsigned ArgNo = 0, e = getNumArgOperands(); ArgNo != e; ++ArgNo) + for (unsigned ArgNo = 0, e = arg_size(); ArgNo != e; ++ArgNo) if (dyn_cast<BlockAddress>(getArgOperand(ArgNo)) == Old) setArgOperand(ArgNo, New); } @@ -1909,6 +1919,32 @@ bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt, // ShuffleVectorInst Implementation //===----------------------------------------------------------------------===// +static Value *createPlaceholderForShuffleVector(Value *V) { + assert(V && "Cannot create placeholder of nullptr V"); + return PoisonValue::get(V->getType()); +} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *Mask, const Twine &Name, + Instruction *InsertBefore) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertBefore) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *Mask, const Twine &Name, + BasicBlock *InsertAtEnd) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertAtEnd) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, ArrayRef<int> Mask, + const Twine &Name, + Instruction *InsertBefore) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertBefore) {} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, ArrayRef<int> Mask, + const Twine &Name, BasicBlock *InsertAtEnd) + : ShuffleVectorInst(V1, createPlaceholderForShuffleVector(V1), Mask, Name, + InsertAtEnd) {} + ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, const Twine &Name, Instruction *InsertBefore) @@ -2259,6 +2295,80 @@ bool ShuffleVectorInst::isExtractSubvectorMask(ArrayRef<int> Mask, return false; } +bool ShuffleVectorInst::isInsertSubvectorMask(ArrayRef<int> Mask, + int NumSrcElts, int &NumSubElts, + int &Index) { + int NumMaskElts = Mask.size(); + + // Don't try to match if we're shuffling to a smaller size. + if (NumMaskElts < NumSrcElts) + return false; + + // TODO: We don't recognize self-insertion/widening. + if (isSingleSourceMaskImpl(Mask, NumSrcElts)) + return false; + + // Determine which mask elements are attributed to which source. + APInt UndefElts = APInt::getZero(NumMaskElts); + APInt Src0Elts = APInt::getZero(NumMaskElts); + APInt Src1Elts = APInt::getZero(NumMaskElts); + bool Src0Identity = true; + bool Src1Identity = true; + + for (int i = 0; i != NumMaskElts; ++i) { + int M = Mask[i]; + if (M < 0) { + UndefElts.setBit(i); + continue; + } + if (M < NumSrcElts) { + Src0Elts.setBit(i); + Src0Identity &= (M == i); + continue; + } + Src1Elts.setBit(i); + Src1Identity &= (M == (i + NumSrcElts)); + continue; + } + assert((Src0Elts | Src1Elts | UndefElts).isAllOnes() && + "unknown shuffle elements"); + assert(!Src0Elts.isZero() && !Src1Elts.isZero() && + "2-source shuffle not found"); + + // Determine lo/hi span ranges. + // TODO: How should we handle undefs at the start of subvector insertions? + int Src0Lo = Src0Elts.countTrailingZeros(); + int Src1Lo = Src1Elts.countTrailingZeros(); + int Src0Hi = NumMaskElts - Src0Elts.countLeadingZeros(); + int Src1Hi = NumMaskElts - Src1Elts.countLeadingZeros(); + + // If src0 is in place, see if the src1 elements is inplace within its own + // span. + if (Src0Identity) { + int NumSub1Elts = Src1Hi - Src1Lo; + ArrayRef<int> Sub1Mask = Mask.slice(Src1Lo, NumSub1Elts); + if (isIdentityMaskImpl(Sub1Mask, NumSrcElts)) { + NumSubElts = NumSub1Elts; + Index = Src1Lo; + return true; + } + } + + // If src1 is in place, see if the src0 elements is inplace within its own + // span. + if (Src1Identity) { + int NumSub0Elts = Src0Hi - Src0Lo; + ArrayRef<int> Sub0Mask = Mask.slice(Src0Lo, NumSub0Elts); + if (isIdentityMaskImpl(Sub0Mask, NumSrcElts)) { + NumSubElts = NumSub0Elts; + Index = Src0Lo; + return true; + } + } + + return false; +} + bool ShuffleVectorInst::isIdentityWithPadding() const { if (isa<UndefValue>(Op<2>())) return false; @@ -2326,6 +2436,87 @@ bool ShuffleVectorInst::isConcat() const { return isIdentityMaskImpl(getShuffleMask(), NumMaskElts); } +static bool isReplicationMaskWithParams(ArrayRef<int> Mask, + int ReplicationFactor, int VF) { + assert(Mask.size() == (unsigned)ReplicationFactor * VF && + "Unexpected mask size."); + + for (int CurrElt : seq(0, VF)) { + ArrayRef<int> CurrSubMask = Mask.take_front(ReplicationFactor); + assert(CurrSubMask.size() == (unsigned)ReplicationFactor && + "Run out of mask?"); + Mask = Mask.drop_front(ReplicationFactor); + if (!all_of(CurrSubMask, [CurrElt](int MaskElt) { + return MaskElt == UndefMaskElem || MaskElt == CurrElt; + })) + return false; + } + assert(Mask.empty() && "Did not consume the whole mask?"); + + return true; +} + +bool ShuffleVectorInst::isReplicationMask(ArrayRef<int> Mask, + int &ReplicationFactor, int &VF) { + // undef-less case is trivial. + if (none_of(Mask, [](int MaskElt) { return MaskElt == UndefMaskElem; })) { + ReplicationFactor = + Mask.take_while([](int MaskElt) { return MaskElt == 0; }).size(); + if (ReplicationFactor == 0 || Mask.size() % ReplicationFactor != 0) + return false; + VF = Mask.size() / ReplicationFactor; + return isReplicationMaskWithParams(Mask, ReplicationFactor, VF); + } + + // However, if the mask contains undef's, we have to enumerate possible tuples + // and pick one. There are bounds on replication factor: [1, mask size] + // (where RF=1 is an identity shuffle, RF=mask size is a broadcast shuffle) + // Additionally, mask size is a replication factor multiplied by vector size, + // which further significantly reduces the search space. + + // Before doing that, let's perform basic sanity check first. + int Largest = -1; + for (int MaskElt : Mask) { + if (MaskElt == UndefMaskElem) + continue; + // Elements must be in non-decreasing order. + if (MaskElt < Largest) + return false; + Largest = std::max(Largest, MaskElt); + } + + // Prefer larger replication factor if all else equal. + for (int PossibleReplicationFactor : + reverse(seq_inclusive<unsigned>(1, Mask.size()))) { + if (Mask.size() % PossibleReplicationFactor != 0) + continue; + int PossibleVF = Mask.size() / PossibleReplicationFactor; + if (!isReplicationMaskWithParams(Mask, PossibleReplicationFactor, + PossibleVF)) + continue; + ReplicationFactor = PossibleReplicationFactor; + VF = PossibleVF; + return true; + } + + return false; +} + +bool ShuffleVectorInst::isReplicationMask(int &ReplicationFactor, + int &VF) const { + // Not possible to express a shuffle mask for a scalable vector for this + // case. + if (isa<ScalableVectorType>(getType())) + return false; + + VF = cast<FixedVectorType>(Op<0>()->getType())->getNumElements(); + if (ShuffleMask.size() % VF != 0) + return false; + ReplicationFactor = ShuffleMask.size() / VF; + + return isReplicationMaskWithParams(ShuffleMask, ReplicationFactor, VF); +} + //===----------------------------------------------------------------------===// // InsertValueInst Class //===----------------------------------------------------------------------===// @@ -3945,6 +4136,35 @@ bool CmpInst::isSigned(Predicate predicate) { } } +bool ICmpInst::compare(const APInt &LHS, const APInt &RHS, + ICmpInst::Predicate Pred) { + assert(ICmpInst::isIntPredicate(Pred) && "Only for integer predicates!"); + switch (Pred) { + case ICmpInst::Predicate::ICMP_EQ: + return LHS.eq(RHS); + case ICmpInst::Predicate::ICMP_NE: + return LHS.ne(RHS); + case ICmpInst::Predicate::ICMP_UGT: + return LHS.ugt(RHS); + case ICmpInst::Predicate::ICMP_UGE: + return LHS.uge(RHS); + case ICmpInst::Predicate::ICMP_ULT: + return LHS.ult(RHS); + case ICmpInst::Predicate::ICMP_ULE: + return LHS.ule(RHS); + case ICmpInst::Predicate::ICMP_SGT: + return LHS.sgt(RHS); + case ICmpInst::Predicate::ICMP_SGE: + return LHS.sge(RHS); + case ICmpInst::Predicate::ICMP_SLT: + return LHS.slt(RHS); + case ICmpInst::Predicate::ICMP_SLE: + return LHS.sle(RHS); + default: + llvm_unreachable("Unexpected non-integer predicate."); + }; +} + CmpInst::Predicate CmpInst::getFlippedSignednessPredicate(Predicate pred) { assert(CmpInst::isRelational(pred) && "Call only with non-equality predicates!"); diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index 19942fa187fd..7552906fd07a 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -188,26 +188,26 @@ Value *InstrProfIncrementInst::getStep() const { } Optional<RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const { - unsigned NumOperands = getNumArgOperands(); + unsigned NumOperands = arg_size(); Metadata *MD = nullptr; auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2)); if (MAV) MD = MAV->getMetadata(); if (!MD || !isa<MDString>(MD)) return None; - return StrToRoundingMode(cast<MDString>(MD)->getString()); + return convertStrToRoundingMode(cast<MDString>(MD)->getString()); } Optional<fp::ExceptionBehavior> ConstrainedFPIntrinsic::getExceptionBehavior() const { - unsigned NumOperands = getNumArgOperands(); + unsigned NumOperands = arg_size(); Metadata *MD = nullptr; auto *MAV = dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1)); if (MAV) MD = MAV->getMetadata(); if (!MD || !isa<MDString>(MD)) return None; - return StrToExceptionBehavior(cast<MDString>(MD)->getString()); + return convertStrToExceptionBehavior(cast<MDString>(MD)->getString()); } bool ConstrainedFPIntrinsic::isDefaultFPEnvironment() const { @@ -473,8 +473,17 @@ Function *VPIntrinsic::getDeclarationForParams(Module *M, Intrinsic::ID VPID, assert(isVPIntrinsic(VPID) && "not a VP intrinsic"); Function *VPFunc; switch (VPID) { - default: - VPFunc = Intrinsic::getDeclaration(M, VPID, Params[0]->getType()); + default: { + Type *OverloadTy = Params[0]->getType(); + if (VPReductionIntrinsic::isVPReduction(VPID)) + OverloadTy = + Params[*VPReductionIntrinsic::getVectorParamPos(VPID)]->getType(); + + VPFunc = Intrinsic::getDeclaration(M, VPID, OverloadTy); + break; + } + case Intrinsic::vp_select: + VPFunc = Intrinsic::getDeclaration(M, VPID, {Params[1]->getType()}); break; case Intrinsic::vp_load: VPFunc = Intrinsic::getDeclaration( @@ -504,6 +513,48 @@ Function *VPIntrinsic::getDeclarationForParams(Module *M, Intrinsic::ID VPID, return VPFunc; } +bool VPReductionIntrinsic::isVPReduction(Intrinsic::ID ID) { + switch (ID) { + default: + return false; +#define HANDLE_VP_REDUCTION(VPID, STARTPOS, VECTORPOS) \ + case Intrinsic::VPID: \ + break; +#include "llvm/IR/VPIntrinsics.def" + } + return true; +} + +unsigned VPReductionIntrinsic::getVectorParamPos() const { + return *VPReductionIntrinsic::getVectorParamPos(getIntrinsicID()); +} + +unsigned VPReductionIntrinsic::getStartParamPos() const { + return *VPReductionIntrinsic::getStartParamPos(getIntrinsicID()); +} + +Optional<unsigned> VPReductionIntrinsic::getVectorParamPos(Intrinsic::ID ID) { + switch (ID) { +#define HANDLE_VP_REDUCTION(VPID, STARTPOS, VECTORPOS) \ + case Intrinsic::VPID: \ + return VECTORPOS; +#include "llvm/IR/VPIntrinsics.def" + default: + return None; + } +} + +Optional<unsigned> VPReductionIntrinsic::getStartParamPos(Intrinsic::ID ID) { + switch (ID) { +#define HANDLE_VP_REDUCTION(VPID, STARTPOS, VECTORPOS) \ + case Intrinsic::VPID: \ + return STARTPOS; +#include "llvm/IR/VPIntrinsics.def" + default: + return None; + } +} + Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { switch (getIntrinsicID()) { case Intrinsic::uadd_with_overflow: diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index c4a713db455b..90716d9c81a6 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -348,6 +348,12 @@ std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { return std::move(pImpl->DiagHandler); } +void LLVMContext::enableOpaquePointers() const { + assert(pImpl->PointerTypes.empty() && pImpl->ASPointerTypes.empty() && + "Must be called before creating any pointer types"); + pImpl->setOpaquePointers(true); +} + bool LLVMContext::supportsTypedPointers() const { - return !pImpl->ForceOpaquePointers; + return !pImpl->getOpaquePointers(); } diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 99819602c545..ebbf382aea38 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -23,9 +23,8 @@ using namespace llvm; static cl::opt<bool> - ForceOpaquePointersCL("force-opaque-pointers", - cl::desc("Force all pointers to be opaque pointers"), - cl::init(false)); + OpaquePointersCL("opaque-pointers", cl::desc("Use opaque pointers"), + cl::init(false)); LLVMContextImpl::LLVMContextImpl(LLVMContext &C) : DiagHandler(std::make_unique<DiagnosticHandler>()), @@ -36,8 +35,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) X86_FP80Ty(C, Type::X86_FP80TyID), FP128Ty(C, Type::FP128TyID), PPC_FP128Ty(C, Type::PPC_FP128TyID), X86_MMXTy(C, Type::X86_MMXTyID), X86_AMXTy(C, Type::X86_AMXTyID), Int1Ty(C, 1), Int8Ty(C, 8), - Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128), - ForceOpaquePointers(ForceOpaquePointersCL) {} + Int16Ty(C, 16), Int32Ty(C, 32), Int64Ty(C, 64), Int128Ty(C, 128) {} LLVMContextImpl::~LLVMContextImpl() { // NOTE: We need to delete the contents of OwnedModules, but Module's dtor @@ -55,8 +53,15 @@ LLVMContextImpl::~LLVMContextImpl() { // Drop references for MDNodes. Do this before Values get deleted to avoid // unnecessary RAUW when nodes are still unresolved. - for (auto *I : DistinctMDNodes) + for (auto *I : DistinctMDNodes) { + // We may have DIArgList that were uniqued, and as it has a custom + // implementation of dropAllReferences, it needs to be explicitly invoked. + if (auto *AL = dyn_cast<DIArgList>(I)) { + AL->dropAllReferences(); + continue; + } I->dropAllReferences(); + } #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ for (auto *I : CLASS##s) \ I->dropAllReferences(); @@ -227,3 +232,11 @@ OptPassGate &LLVMContextImpl::getOptPassGate() const { void LLVMContextImpl::setOptPassGate(OptPassGate& OPG) { this->OPG = &OPG; } + +bool LLVMContextImpl::getOpaquePointers() { + if (LLVM_UNLIKELY(!(OpaquePointers.hasValue()))) + OpaquePointers = OpaquePointersCL; + return *OpaquePointers; +} + +void LLVMContextImpl::setOpaquePointers(bool OP) { OpaquePointers = OP; } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 2ae23fdc95a8..b2909c425846 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -61,7 +61,9 @@ using DenseMapAPIntKeyInfo = DenseMapInfo<APInt>; struct DenseMapAPFloatKeyInfo { static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus(), 1); } - static inline APFloat getTombstoneKey() { return APFloat(APFloat::Bogus(), 2); } + static inline APFloat getTombstoneKey() { + return APFloat(APFloat::Bogus(), 2); + } static unsigned getHashValue(const APFloat &Key) { return static_cast<unsigned>(hash_value(Key)); @@ -74,46 +76,42 @@ struct DenseMapAPFloatKeyInfo { struct AnonStructTypeKeyInfo { struct KeyTy { - ArrayRef<Type*> ETypes; + ArrayRef<Type *> ETypes; bool isPacked; - KeyTy(const ArrayRef<Type*>& E, bool P) : - ETypes(E), isPacked(P) {} + KeyTy(const ArrayRef<Type *> &E, bool P) : ETypes(E), isPacked(P) {} KeyTy(const StructType *ST) : ETypes(ST->elements()), isPacked(ST->isPacked()) {} - bool operator==(const KeyTy& that) const { + bool operator==(const KeyTy &that) const { if (isPacked != that.isPacked) return false; if (ETypes != that.ETypes) return false; return true; } - bool operator!=(const KeyTy& that) const { - return !this->operator==(that); - } + bool operator!=(const KeyTy &that) const { return !this->operator==(that); } }; - static inline StructType* getEmptyKey() { - return DenseMapInfo<StructType*>::getEmptyKey(); + static inline StructType *getEmptyKey() { + return DenseMapInfo<StructType *>::getEmptyKey(); } - static inline StructType* getTombstoneKey() { - return DenseMapInfo<StructType*>::getTombstoneKey(); + static inline StructType *getTombstoneKey() { + return DenseMapInfo<StructType *>::getTombstoneKey(); } - static unsigned getHashValue(const KeyTy& Key) { - return hash_combine(hash_combine_range(Key.ETypes.begin(), - Key.ETypes.end()), - Key.isPacked); + static unsigned getHashValue(const KeyTy &Key) { + return hash_combine( + hash_combine_range(Key.ETypes.begin(), Key.ETypes.end()), Key.isPacked); } static unsigned getHashValue(const StructType *ST) { return getHashValue(KeyTy(ST)); } - static bool isEqual(const KeyTy& LHS, const StructType *RHS) { + static bool isEqual(const KeyTy &LHS, const StructType *RHS) { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; return LHS == KeyTy(RHS); @@ -127,16 +125,16 @@ struct AnonStructTypeKeyInfo { struct FunctionTypeKeyInfo { struct KeyTy { const Type *ReturnType; - ArrayRef<Type*> Params; + ArrayRef<Type *> Params; bool isVarArg; - KeyTy(const Type* R, const ArrayRef<Type*>& P, bool V) : - ReturnType(R), Params(P), isVarArg(V) {} + KeyTy(const Type *R, const ArrayRef<Type *> &P, bool V) + : ReturnType(R), Params(P), isVarArg(V) {} KeyTy(const FunctionType *FT) : ReturnType(FT->getReturnType()), Params(FT->params()), isVarArg(FT->isVarArg()) {} - bool operator==(const KeyTy& that) const { + bool operator==(const KeyTy &that) const { if (ReturnType != that.ReturnType) return false; if (isVarArg != that.isVarArg) @@ -145,31 +143,28 @@ struct FunctionTypeKeyInfo { return false; return true; } - bool operator!=(const KeyTy& that) const { - return !this->operator==(that); - } + bool operator!=(const KeyTy &that) const { return !this->operator==(that); } }; - static inline FunctionType* getEmptyKey() { - return DenseMapInfo<FunctionType*>::getEmptyKey(); + static inline FunctionType *getEmptyKey() { + return DenseMapInfo<FunctionType *>::getEmptyKey(); } - static inline FunctionType* getTombstoneKey() { - return DenseMapInfo<FunctionType*>::getTombstoneKey(); + static inline FunctionType *getTombstoneKey() { + return DenseMapInfo<FunctionType *>::getTombstoneKey(); } - static unsigned getHashValue(const KeyTy& Key) { - return hash_combine(Key.ReturnType, - hash_combine_range(Key.Params.begin(), - Key.Params.end()), - Key.isVarArg); + static unsigned getHashValue(const KeyTy &Key) { + return hash_combine( + Key.ReturnType, + hash_combine_range(Key.Params.begin(), Key.Params.end()), Key.isVarArg); } static unsigned getHashValue(const FunctionType *FT) { return getHashValue(KeyTy(FT)); } - static bool isEqual(const KeyTy& LHS, const FunctionType *RHS) { + static bool isEqual(const KeyTy &LHS, const FunctionType *RHS) { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; return LHS == KeyTy(RHS); @@ -412,14 +407,14 @@ template <> struct MDNodeKeyImpl<DIBasicType> { Encoding(Encoding), Flags(Flags) {} MDNodeKeyImpl(const DIBasicType *N) : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()), - AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), Flags(N->getFlags()) {} + AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), + Flags(N->getFlags()) {} bool isKeyOf(const DIBasicType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && SizeInBits == RHS->getSizeInBits() && AlignInBits == RHS->getAlignInBits() && - Encoding == RHS->getEncoding() && - Flags == RHS->getFlags(); + Encoding == RHS->getEncoding() && Flags == RHS->getFlags(); } unsigned getHashValue() const { @@ -471,23 +466,24 @@ template <> struct MDNodeKeyImpl<DIDerivedType> { Optional<unsigned> DWARFAddressSpace; unsigned Flags; Metadata *ExtraData; + Metadata *Annotations; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace, unsigned Flags, - Metadata *ExtraData) + Metadata *ExtraData, Metadata *Annotations) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace), - Flags(Flags), ExtraData(ExtraData) {} + Flags(Flags), ExtraData(ExtraData), Annotations(Annotations) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()), DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()), - ExtraData(N->getRawExtraData()) {} + ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIDerivedType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -497,8 +493,8 @@ template <> struct MDNodeKeyImpl<DIDerivedType> { AlignInBits == RHS->getAlignInBits() && OffsetInBits == RHS->getOffsetInBits() && DWARFAddressSpace == RHS->getDWARFAddressSpace() && - Flags == RHS->getFlags() && - ExtraData == RHS->getRawExtraData(); + Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { @@ -525,7 +521,8 @@ template <> struct MDNodeSubsetEqualImpl<DIDerivedType> { return isODRMember(LHS.Tag, LHS.Scope, LHS.Name, RHS); } - static bool isSubsetEqual(const DIDerivedType *LHS, const DIDerivedType *RHS) { + static bool isSubsetEqual(const DIDerivedType *LHS, + const DIDerivedType *RHS) { return isODRMember(LHS->getTag(), LHS->getRawScope(), LHS->getRawName(), RHS); } @@ -569,6 +566,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> { Metadata *Associated; Metadata *Allocated; Metadata *Rank; + Metadata *Annotations; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, @@ -577,14 +575,15 @@ template <> struct MDNodeKeyImpl<DICompositeType> { Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated, - Metadata *Allocated, Metadata *Rank) + Metadata *Allocated, Metadata *Rank, Metadata *Annotations) : 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), Discriminator(Discriminator), DataLocation(DataLocation), - Associated(Associated), Allocated(Allocated), Rank(Rank) {} + Associated(Associated), Allocated(Allocated), Rank(Rank), + Annotations(Annotations) {} MDNodeKeyImpl(const DICompositeType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), @@ -597,7 +596,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> { Discriminator(N->getRawDiscriminator()), DataLocation(N->getRawDataLocation()), Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()), - Rank(N->getRawRank()) {} + Rank(N->getRawRank()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DICompositeType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -614,7 +613,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> { Discriminator == RHS->getRawDiscriminator() && DataLocation == RHS->getRawDataLocation() && Associated == RHS->getRawAssociated() && - Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank(); + Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { @@ -623,7 +623,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> { // collision "most of the time". There is no correctness issue in case of // collision because of the full check above. return hash_combine(Name, File, Line, BaseType, Scope, Elements, - TemplateParams); + TemplateParams, Annotations); } }; @@ -663,14 +663,13 @@ template <> struct MDNodeKeyImpl<DIFile> { bool isKeyOf(const DIFile *RHS) const { return Filename == RHS->getRawFilename() && Directory == RHS->getRawDirectory() && - Checksum == RHS->getRawChecksum() && - Source == RHS->getRawSource(); + Checksum == RHS->getRawChecksum() && Source == RHS->getRawSource(); } unsigned getHashValue() const { - return hash_combine( - Filename, Directory, Checksum ? Checksum->Kind : 0, - Checksum ? Checksum->Value : nullptr, Source.getValueOr(nullptr)); + return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0, + Checksum ? Checksum->Value : nullptr, + Source.getValueOr(nullptr)); } }; @@ -692,6 +691,7 @@ template <> struct MDNodeKeyImpl<DISubprogram> { Metadata *Declaration; Metadata *RetainedNodes; Metadata *ThrownTypes; + Metadata *Annotations; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, @@ -699,13 +699,14 @@ template <> struct MDNodeKeyImpl<DISubprogram> { unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes) + Metadata *ThrownTypes, Metadata *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), ScopeLine(ScopeLine), ContainingType(ContainingType), VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags), Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), - RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {} + RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes), + Annotations(Annotations) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -717,7 +718,8 @@ template <> struct MDNodeKeyImpl<DISubprogram> { TemplateParams(N->getRawTemplateParams()), Declaration(N->getRawDeclaration()), RetainedNodes(N->getRawRetainedNodes()), - ThrownTypes(N->getRawThrownTypes()) {} + ThrownTypes(N->getRawThrownTypes()), + Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DISubprogram *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -732,7 +734,8 @@ template <> struct MDNodeKeyImpl<DISubprogram> { TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && RetainedNodes == RHS->getRawRetainedNodes() && - ThrownTypes == RHS->getRawThrownTypes(); + ThrownTypes == RHS->getRawThrownTypes() && + Annotations == RHS->getRawAnnotations(); } bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; } @@ -853,9 +856,7 @@ template <> struct MDNodeKeyImpl<DINamespace> { ExportSymbols == RHS->getExportSymbols(); } - unsigned getHashValue() const { - return hash_combine(Scope, Name); - } + unsigned getHashValue() const { return hash_combine(Scope, Name); } }; template <> struct MDNodeKeyImpl<DICommonBlock> { @@ -865,8 +866,8 @@ template <> struct MDNodeKeyImpl<DICommonBlock> { Metadata *File; unsigned LineNo; - MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, - Metadata *File, unsigned LineNo) + MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, Metadata *File, + unsigned LineNo) : Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo) {} MDNodeKeyImpl(const DICommonBlock *N) : Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()), @@ -874,8 +875,8 @@ template <> struct MDNodeKeyImpl<DICommonBlock> { bool isKeyOf(const DICommonBlock *RHS) const { return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() && - Name == RHS->getRawName() && File == RHS->getRawFile() && - LineNo == RHS->getLineNo(); + Name == RHS->getRawName() && File == RHS->getRawFile() && + LineNo == RHS->getLineNo(); } unsigned getHashValue() const { @@ -976,17 +977,19 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { Metadata *StaticDataMemberDeclaration; Metadata *TemplateParams; uint32_t AlignInBits; + Metadata *Annotations; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits) + uint32_t AlignInBits, Metadata *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), StaticDataMemberDeclaration(StaticDataMemberDeclaration), - TemplateParams(TemplateParams), AlignInBits(AlignInBits) {} + TemplateParams(TemplateParams), AlignInBits(AlignInBits), + Annotations(Annotations) {} MDNodeKeyImpl(const DIGlobalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -994,7 +997,7 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()), TemplateParams(N->getRawTemplateParams()), - AlignInBits(N->getAlignInBits()) {} + AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -1005,7 +1008,8 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { StaticDataMemberDeclaration == RHS->getRawStaticDataMemberDeclaration() && TemplateParams == RHS->getRawTemplateParams() && - AlignInBits == RHS->getAlignInBits(); + AlignInBits == RHS->getAlignInBits() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { @@ -1018,7 +1022,7 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> { // TODO: make hashing work fine with such situations return hash_combine(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, /* AlignInBits, */ - StaticDataMemberDeclaration); + StaticDataMemberDeclaration, Annotations); } }; @@ -1031,22 +1035,25 @@ template <> struct MDNodeKeyImpl<DILocalVariable> { unsigned Arg; unsigned Flags; uint32_t AlignInBits; + Metadata *Annotations; MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags, - uint32_t AlignInBits) + uint32_t AlignInBits, Metadata *Annotations) : Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg), - Flags(Flags), AlignInBits(AlignInBits) {} + Flags(Flags), AlignInBits(AlignInBits), Annotations(Annotations) {} MDNodeKeyImpl(const DILocalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()), - Flags(N->getFlags()), AlignInBits(N->getAlignInBits()) {} + Flags(N->getFlags()), AlignInBits(N->getAlignInBits()), + Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DILocalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && File == RHS->getRawFile() && Line == RHS->getLine() && Type == RHS->getRawType() && Arg == RHS->getArg() && - Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits(); + Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { @@ -1057,7 +1064,7 @@ template <> struct MDNodeKeyImpl<DILocalVariable> { // clang/test/CodeGen/debug-info-257-args.c is an example of this problem, // generated IR is random for each run and test fails with Align included. // TODO: make hashing work fine with such situations - return hash_combine(Scope, Name, File, Line, Type, Arg, Flags); + return hash_combine(Scope, Name, File, Line, Type, Arg, Flags, Annotations); } }; @@ -1079,9 +1086,7 @@ template <> struct MDNodeKeyImpl<DILabel> { } /// Using name and line to get hash value. It should already be mostly unique. - unsigned getHashValue() const { - return hash_combine(Scope, Name, Line); - } + unsigned getHashValue() const { return hash_combine(Scope, Name, Line); } }; template <> struct MDNodeKeyImpl<DIExpression> { @@ -1155,23 +1160,26 @@ template <> struct MDNodeKeyImpl<DIImportedEntity> { Metadata *File; unsigned Line; MDString *Name; + Metadata *Elements; MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File, - unsigned Line, MDString *Name) + unsigned Line, MDString *Name, Metadata *Elements) : Tag(Tag), Scope(Scope), Entity(Entity), File(File), Line(Line), - Name(Name) {} + Name(Name), Elements(Elements) {} MDNodeKeyImpl(const DIImportedEntity *N) : Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()), - File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()) {} + File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()), + Elements(N->getRawElements()) {} bool isKeyOf(const DIImportedEntity *RHS) const { return Tag == RHS->getTag() && Scope == RHS->getRawScope() && Entity == RHS->getRawEntity() && File == RHS->getFile() && - Line == RHS->getLine() && Name == RHS->getRawName(); + Line == RHS->getLine() && Name == RHS->getRawName() && + Elements == RHS->getRawElements(); } unsigned getHashValue() const { - return hash_combine(Tag, Scope, Entity, File, Line, Name); + return hash_combine(Tag, Scope, Entity, File, Line, Name, Elements); } }; @@ -1325,7 +1333,7 @@ class LLVMContextImpl { public: /// OwnedModules - The set of modules instantiated in this context, and which /// will be automatically deleted if this context is deleted. - SmallPtrSet<Module*, 4> OwnedModules; + SmallPtrSet<Module *, 4> OwnedModules; /// The main remark streamer used by all the other streamers (e.g. IR, MIR, /// frontends, etc.). This should only be used by the specific streamers, and @@ -1377,7 +1385,7 @@ public: DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata; DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues; - DenseMap<const Value*, ValueName*> ValueNames; + DenseMap<const Value *, ValueName *> ValueNames; #define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \ DenseSet<CLASS *, CLASS##Info> CLASS##s; @@ -1412,7 +1420,7 @@ public: StringMap<std::unique_ptr<ConstantDataSequential>> CDSConstants; DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *> - BlockAddresses; + BlockAddresses; DenseMap<const GlobalValue *, DSOLocalEquivalent *> DSOLocalEquivalents; @@ -1434,22 +1442,19 @@ public: BumpPtrAllocator Alloc; UniqueStringSaver Saver{Alloc}; - DenseMap<unsigned, IntegerType*> IntegerTypes; + DenseMap<unsigned, IntegerType *> IntegerTypes; using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>; FunctionTypeSet FunctionTypes; using StructTypeSet = DenseSet<StructType *, AnonStructTypeKeyInfo>; StructTypeSet AnonStructTypes; - StringMap<StructType*> NamedStructTypes; + StringMap<StructType *> NamedStructTypes; unsigned NamedStructTypesUniqueID = 0; - DenseMap<std::pair<Type *, uint64_t>, ArrayType*> ArrayTypes; - DenseMap<std::pair<Type *, ElementCount>, VectorType*> VectorTypes; - // TODO: clean up the following after we no longer support non-opaque pointer - // types. - bool ForceOpaquePointers; - DenseMap<Type*, PointerType*> PointerTypes; // Pointers in AddrSpace = 0 - DenseMap<std::pair<Type*, unsigned>, PointerType*> ASPointerTypes; + DenseMap<std::pair<Type *, uint64_t>, ArrayType *> ArrayTypes; + DenseMap<std::pair<Type *, ElementCount>, VectorType *> VectorTypes; + DenseMap<Type *, PointerType *> PointerTypes; // Pointers in AddrSpace = 0 + DenseMap<std::pair<Type *, unsigned>, PointerType *> ASPointerTypes; /// ValueHandles - This map keeps track of all of the value handles that are /// watching a Value*. The Value::HasValueHandle bit is used to know @@ -1503,7 +1508,7 @@ public: /// This saves allocating an additional word in Function for programs which /// do not use GC (i.e., most programs) at the cost of increased overhead for /// clients which do use GC. - DenseMap<const Function*, std::string> GCNames; + DenseMap<const Function *, std::string> GCNames; /// Flag to indicate if Value (other than GlobalValue) retains their name or /// not. @@ -1526,7 +1531,15 @@ public: /// /// The lifetime of the object must be guaranteed to extend as long as the /// LLVMContext is used by compilation. - void setOptPassGate(OptPassGate&); + void setOptPassGate(OptPassGate &); + + // TODO: clean up the following after we no longer support non-opaque pointer + // types. + bool getOpaquePointers(); + void setOpaquePointers(bool OP); + +private: + Optional<bool> OpaquePointers; }; } // end namespace llvm diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp index 32840fdeddf7..7bccf09012ca 100644 --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -1351,7 +1351,7 @@ void FunctionPassManager::add(Pass *P) { /// bool FunctionPassManager::run(Function &F) { handleAllErrors(F.materialize(), [&](ErrorInfoBase &EIB) { - report_fatal_error("Error reading bitcode file: " + EIB.message()); + report_fatal_error(Twine("Error reading bitcode file: ") + EIB.message()); }); return FPM->run(F); } diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp index bbdde586e6e0..2399ea27ee9d 100644 --- a/llvm/lib/IR/Mangler.cpp +++ b/llvm/lib/IR/Mangler.cpp @@ -99,6 +99,11 @@ static void addByteCountSuffix(raw_ostream &OS, const Function *F, const unsigned PtrSize = DL.getPointerSize(); for (const Argument &A : F->args()) { + // For the purposes of the byte count suffix, structs returned by pointer + // do not count as function arguments. + if (A.hasStructRetAttr()) + continue; + // 'Dereference' type in case of byval or inalloca parameter attribute. uint64_t AllocSize = A.hasPassPointeeByValueCopyAttr() ? A.getPassPointeeByValueCopySize(DL) : @@ -186,7 +191,7 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, // Check if the name needs quotes to be safe for the linker to interpret. static bool canBeUnquotedInDirective(char C) { - return isAlnum(C) || C == '_' || C == '$' || C == '.' || C == '@'; + return isAlnum(C) || C == '_' || C == '@'; } static bool canBeUnquotedInDirective(StringRef Name) { diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 4f87ef537765..ebcc493407cc 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -345,7 +345,7 @@ ReplaceableMetadataImpl *ReplaceableMetadataImpl::getIfExists(Metadata &MD) { bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) { if (auto *N = dyn_cast<MDNode>(&MD)) return !N->isResolved(); - return dyn_cast<ValueAsMetadata>(&MD); + return isa<ValueAsMetadata>(&MD); } static DISubprogram *getLocalFunctionMetadata(Value *V) { @@ -1367,6 +1367,15 @@ void Instruction::addAnnotationMetadata(StringRef Name) { setMetadata(LLVMContext::MD_annotation, MD); } +AAMDNodes Instruction::getAAMetadata() const { + AAMDNodes Result; + Result.TBAA = getMetadata(LLVMContext::MD_tbaa); + Result.TBAAStruct = getMetadata(LLVMContext::MD_tbaa_struct); + Result.Scope = getMetadata(LLVMContext::MD_alias_scope); + Result.NoAlias = getMetadata(LLVMContext::MD_noalias); + return Result; +} + void Instruction::setAAMetadata(const AAMDNodes &N) { setMetadata(LLVMContext::MD_tbaa, N.TBAA); setMetadata(LLVMContext::MD_tbaa_struct, N.TBAAStruct); diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 7c18dc0ed299..63ea41fba89a 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -114,6 +114,10 @@ GlobalValue *Module::getNamedValue(StringRef Name) const { return cast_or_null<GlobalValue>(getValueSymbolTable().lookup(Name)); } +unsigned Module::getNumNamedValues() const { + return getValueSymbolTable().size(); +} + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. /// This ID is uniqued across modules in the current LLVMContext. unsigned Module::getMDKindID(StringRef Name) const { diff --git a/llvm/lib/IR/ModuleSummaryIndex.cpp b/llvm/lib/IR/ModuleSummaryIndex.cpp index f4ac6caf4f93..31c5cd938d03 100644 --- a/llvm/lib/IR/ModuleSummaryIndex.cpp +++ b/llvm/lib/IR/ModuleSummaryIndex.cpp @@ -251,12 +251,13 @@ void ModuleSummaryIndex::propagateAttributes( bool IsDSOLocal = true; for (auto &S : P.second.SummaryList) { if (!isGlobalValueLive(S.get())) { - // computeDeadSymbols should have marked all copies live. Note that - // it is possible that there is a GUID collision between internal - // symbols with the same name in different files of the same name but - // not enough distinguishing path. Because computeDeadSymbols should - // conservatively mark all copies live we can assert here that all are - // dead if any copy is dead. + // computeDeadSymbolsAndUpdateIndirectCalls should have marked all + // copies live. Note that it is possible that there is a GUID collision + // between internal symbols with the same name in different files of the + // same name but not enough distinguishing path. Because + // computeDeadSymbolsAndUpdateIndirectCalls should conservatively mark + // all copies live we can assert here that all are dead if any copy is + // dead. assert(llvm::none_of( P.second.SummaryList, [&](const std::unique_ptr<GlobalValueSummary> &Summary) { @@ -446,9 +447,11 @@ static std::string linkageToString(GlobalValue::LinkageTypes LT) { 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), - FlagValue(F.NoInline), FlagValue(F.AlwaysInline), 0}; + char FlagRep[] = {FlagValue(F.ReadNone), FlagValue(F.ReadOnly), + FlagValue(F.NoRecurse), FlagValue(F.ReturnDoesNotAlias), + FlagValue(F.NoInline), FlagValue(F.AlwaysInline), + FlagValue(F.NoUnwind), FlagValue(F.MayThrow), + FlagValue(F.HasUnknownCall), 0}; return FlagRep; } diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp index 18a1c84933e0..cf309ffd6212 100644 --- a/llvm/lib/IR/Operator.cpp +++ b/llvm/lib/IR/Operator.cpp @@ -19,6 +19,31 @@ #include "ConstantsContext.h" namespace llvm { +bool Operator::hasPoisonGeneratingFlags() const { + switch (getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + case Instruction::Shl: { + auto *OBO = cast<OverflowingBinaryOperator>(this); + return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap(); + } + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::AShr: + case Instruction::LShr: + return cast<PossiblyExactOperator>(this)->isExact(); + case Instruction::GetElementPtr: { + auto *GEP = cast<GEPOperator>(this); + // Note: inrange exists on constexpr only + return GEP->isInBounds() || GEP->getInRangeIndex() != None; + } + default: + return false; + } + // TODO: FastMathFlags! (On instructions, but not constexpr) +} + Type *GEPOperator::getSourceElementType() const { if (auto *I = dyn_cast<GetElementPtrInst>(this)) return I->getSourceElementType(); @@ -190,12 +215,14 @@ bool GEPOperator::collectOffset( if (STy || ScalableType) return false; - // Insert an initial offset of 0 for V iff none exists already, then - // increment the offset by IndexedSize. - VariableOffsets.insert({V, APInt(BitWidth, 0)}); APInt IndexedSize = APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType())); - VariableOffsets[V] += IndexedSize; + // Insert an initial offset of 0 for V iff none exists already, then + // increment the offset by IndexedSize. + if (!IndexedSize.isZero()) { + VariableOffsets.insert({V, APInt(BitWidth, 0)}); + VariableOffsets[V] += IndexedSize; + } } return true; } diff --git a/llvm/lib/IR/OptBisect.cpp b/llvm/lib/IR/OptBisect.cpp index 2cf2298e0005..55c0dbad5aab 100644 --- a/llvm/lib/IR/OptBisect.cpp +++ b/llvm/lib/IR/OptBisect.cpp @@ -22,14 +22,12 @@ using namespace llvm; static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden, - cl::init(std::numeric_limits<int>::max()), - cl::Optional, + cl::init(OptBisect::Disabled), cl::Optional, + cl::cb<void, int>([](int Limit) { + llvm::OptBisector->setLimit(Limit); + }), cl::desc("Maximum optimization to perform")); -OptBisect::OptBisect() : OptPassGate() { - BisectEnabled = OptBisectLimit != std::numeric_limits<int>::max(); -} - static void printPassMessage(const StringRef &Name, int PassNum, StringRef TargetDesc, bool Running) { StringRef Status = Running ? "" : "NOT "; @@ -38,19 +36,21 @@ static void printPassMessage(const StringRef &Name, int PassNum, } bool OptBisect::shouldRunPass(const Pass *P, StringRef IRDescription) { - assert(BisectEnabled); + assert(isEnabled()); return checkPass(P->getPassName(), IRDescription); } bool OptBisect::checkPass(const StringRef PassName, const StringRef TargetDesc) { - assert(BisectEnabled); + assert(isEnabled()); int CurBisectNum = ++LastBisectNum; - bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit); + bool ShouldRun = (BisectLimit == -1 || CurBisectNum <= BisectLimit); printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun); return ShouldRun; } +const int OptBisect::Disabled; + ManagedStatic<OptBisect> llvm::OptBisector; diff --git a/llvm/lib/IR/PassManager.cpp b/llvm/lib/IR/PassManager.cpp index 4cf7ab2a602b..d933003ccdf7 100644 --- a/llvm/lib/IR/PassManager.cpp +++ b/llvm/lib/IR/PassManager.cpp @@ -10,12 +10,13 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/PassManagerImpl.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +namespace llvm { // Explicit template instantiations and specialization defininitions for core // template typedefs. -namespace llvm { template class AllAnalysesOn<Module>; template class AllAnalysesOn<Function>; template class PassManager<Module>; @@ -91,6 +92,16 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate( } } // namespace llvm +void ModuleToFunctionPassAdaptor::printPipeline( + raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { + OS << "function"; + if (EagerlyInvalidate) + OS << "<eager-inv>"; + OS << "("; + Pass->printPipeline(OS, MapClassName2PassName); + OS << ")"; +} + PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = @@ -122,7 +133,7 @@ PreservedAnalyses ModuleToFunctionPassAdaptor::run(Module &M, // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. - FAM.invalidate(F, PassPA); + FAM.invalidate(F, EagerlyInvalidate ? PreservedAnalyses::none() : PassPA); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. diff --git a/llvm/lib/IR/ProfileSummary.cpp b/llvm/lib/IR/ProfileSummary.cpp index 453a278a7f3f..05d5ac2c5ddf 100644 --- a/llvm/lib/IR/ProfileSummary.cpp +++ b/llvm/lib/IR/ProfileSummary.cpp @@ -249,7 +249,7 @@ ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { PartialProfileRatio); } -void ProfileSummary::printSummary(raw_ostream &OS) { +void ProfileSummary::printSummary(raw_ostream &OS) const { OS << "Total functions: " << NumFunctions << "\n"; OS << "Maximum function count: " << MaxFunctionCount << "\n"; OS << "Maximum block count: " << MaxCount << "\n"; @@ -257,7 +257,7 @@ void ProfileSummary::printSummary(raw_ostream &OS) { OS << "Total count: " << TotalCount << "\n"; } -void ProfileSummary::printDetailedSummary(raw_ostream &OS) { +void ProfileSummary::printDetailedSummary(raw_ostream &OS) const { OS << "Detailed summary:\n"; for (const auto &Entry : DetailedSummary) { OS << Entry.NumCounts << " blocks with count >= " << Entry.MinCount diff --git a/llvm/lib/IR/PseudoProbe.cpp b/llvm/lib/IR/PseudoProbe.cpp index bd92c604da2c..101cada77ff9 100644 --- a/llvm/lib/IR/PseudoProbe.cpp +++ b/llvm/lib/IR/PseudoProbe.cpp @@ -98,12 +98,4 @@ void setProbeDistributionFactor(Instruction &Inst, float Factor) { } } -void addPseudoProbeAttribute(PseudoProbeInst &Inst, - PseudoProbeAttributes Attr) { - IRBuilder<> Builder(&Inst); - uint32_t OldAttr = Inst.getAttributes()->getZExtValue(); - uint32_t NewAttr = OldAttr | (uint32_t)Attr; - if (OldAttr != NewAttr) - Inst.replaceUsesOfWith(Inst.getAttributes(), Builder.getInt32(NewAttr)); -} } // namespace llvm diff --git a/llvm/lib/IR/ReplaceConstant.cpp b/llvm/lib/IR/ReplaceConstant.cpp index fd73a1a8e5af..cfd8deba5a53 100644 --- a/llvm/lib/IR/ReplaceConstant.cpp +++ b/llvm/lib/IR/ReplaceConstant.cpp @@ -15,15 +15,9 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/NoFolder.h" +#include "llvm/IR/ValueMap.h" namespace llvm { -// Replace a constant expression by instructions with equivalent operations at -// a specified location. -Instruction *createReplacementInstr(ConstantExpr *CE, Instruction *Instr) { - auto *CEInstr = CE->getAsInstruction(); - CEInstr->insertBefore(Instr); - return CEInstr; -} void convertConstantExprsToInstructions(Instruction *I, ConstantExpr *CE, SmallPtrSetImpl<Instruction *> *Insts) { @@ -40,7 +34,8 @@ void convertConstantExprsToInstructions( Instruction *I, std::map<Use *, std::vector<std::vector<ConstantExpr *>>> &CEPaths, SmallPtrSetImpl<Instruction *> *Insts) { - SmallPtrSet<ConstantExpr *, 8> Visited; + ValueMap<ConstantExpr *, Instruction *> Visited; + for (Use &U : I->operands()) { // The operand U is either not a constant expression operand or the // constant expression paths do not belong to U, ignore U. @@ -55,24 +50,47 @@ void convertConstantExprsToInstructions( BI = &(*(BB->getFirstInsertionPt())); } - // Go through the paths associated with operand U, and convert all the - // constant expressions along all paths to corresponding instructions. + // Go through all the paths associated with operand U, and convert all the + // constant expressions along all the paths to corresponding instructions. auto *II = I; auto &Paths = CEPaths[&U]; for (auto &Path : Paths) { for (auto *CE : Path) { - if (!Visited.insert(CE).second) - continue; - auto *NI = CE->getAsInstruction(); - NI->insertBefore(BI); + // Instruction which is equivalent to CE. + Instruction *NI = nullptr; + + if (!Visited.count(CE)) { + // CE is encountered first time, convert it into a corresponding + // instruction NI, and appropriately insert NI before the parent + // instruction. + NI = CE->getAsInstruction(BI); + + // Mark CE as visited by mapping CE to NI. + Visited[CE] = NI; + + // If required collect NI. + if (Insts) + Insts->insert(NI); + } else { + // We had already encountered CE, the correponding instruction already + // exist, use it to replace CE. + NI = Visited[CE]; + } + + assert(NI && "Expected an instruction corresponding to constant " + "expression."); + + // Replace all uses of constant expression CE by the corresponding + // instruction NI within the current parent instruction. II->replaceUsesOfWith(CE, NI); - CE->removeDeadConstantUsers(); BI = II = NI; - if (Insts) - Insts->insert(NI); } } } + + // Remove all converted constant expressions which are dead by now. + for (auto Item : Visited) + Item.first->removeDeadConstantUsers(); } void collectConstantExprPaths( diff --git a/llvm/lib/IR/Statepoint.cpp b/llvm/lib/IR/Statepoint.cpp index bbfbbe489bae..b5916e4937c6 100644 --- a/llvm/lib/IR/Statepoint.cpp +++ b/llvm/lib/IR/Statepoint.cpp @@ -26,16 +26,14 @@ StatepointDirectives llvm::parseStatepointDirectivesFromAttrs(AttributeList AS) { StatepointDirectives Result; - Attribute AttrID = - AS.getAttribute(AttributeList::FunctionIndex, "statepoint-id"); + Attribute AttrID = AS.getFnAttr("statepoint-id"); uint64_t StatepointID; if (AttrID.isStringAttribute()) if (!AttrID.getValueAsString().getAsInteger(10, StatepointID)) Result.StatepointID = StatepointID; uint32_t NumPatchBytes; - Attribute AttrNumPatchBytes = AS.getAttribute(AttributeList::FunctionIndex, - "statepoint-num-patch-bytes"); + Attribute AttrNumPatchBytes = AS.getFnAttr("statepoint-num-patch-bytes"); if (AttrNumPatchBytes.isStringAttribute()) if (!AttrNumPatchBytes.getValueAsString().getAsInteger(10, NumPatchBytes)) Result.NumPatchBytes = NumPatchBytes; diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index a21998976066..d59d87ad631b 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -66,6 +66,44 @@ bool Type::isOpaquePointerTy() const { return false; } +const fltSemantics &Type::getFltSemantics() const { + switch (getTypeID()) { + case HalfTyID: return APFloat::IEEEhalf(); + case BFloatTyID: return APFloat::BFloat(); + case FloatTyID: return APFloat::IEEEsingle(); + case DoubleTyID: return APFloat::IEEEdouble(); + case X86_FP80TyID: return APFloat::x87DoubleExtended(); + case FP128TyID: return APFloat::IEEEquad(); + case PPC_FP128TyID: return APFloat::PPCDoubleDouble(); + default: llvm_unreachable("Invalid floating type"); + } +} + +bool Type::isIEEE() const { + return APFloat::getZero(getFltSemantics()).isIEEE(); +} + +Type *Type::getFloatingPointTy(LLVMContext &C, const fltSemantics &S) { + Type *Ty; + if (&S == &APFloat::IEEEhalf()) + Ty = Type::getHalfTy(C); + else if (&S == &APFloat::BFloat()) + Ty = Type::getBFloatTy(C); + else if (&S == &APFloat::IEEEsingle()) + Ty = Type::getFloatTy(C); + else if (&S == &APFloat::IEEEdouble()) + Ty = Type::getDoubleTy(C); + else if (&S == &APFloat::x87DoubleExtended()) + Ty = Type::getX86_FP80Ty(C); + else if (&S == &APFloat::IEEEquad()) + Ty = Type::getFP128Ty(C); + else { + assert(&S == &APFloat::PPCDoubleDouble() && "Unknown FP format"); + Ty = Type::getPPC_FP128Ty(C); + } + return Ty; +} + bool Type::canLosslesslyBitCastTo(Type *Ty) const { // Identity cast means no change so return true if (this == Ty) @@ -296,9 +334,7 @@ IntegerType *IntegerType::get(LLVMContext &C, unsigned NumBits) { return Entry; } -APInt IntegerType::getMask() const { - return APInt::getAllOnesValue(getBitWidth()); -} +APInt IntegerType::getMask() const { return APInt::getAllOnes(getBitWidth()); } //===----------------------------------------------------------------------===// // FunctionType Implementation @@ -696,8 +732,8 @@ PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) { LLVMContextImpl *CImpl = EltTy->getContext().pImpl; - // Create opaque pointer for pointer to opaque pointer. - if (CImpl->ForceOpaquePointers || EltTy->isOpaquePointerTy()) + // Automatically convert typed pointers to opaque pointers. + if (CImpl->getOpaquePointers()) return get(EltTy->getContext(), AddressSpace); // Since AddressSpace #0 is the common case, we special case it. @@ -711,6 +747,8 @@ PointerType *PointerType::get(Type *EltTy, unsigned AddressSpace) { PointerType *PointerType::get(LLVMContext &C, unsigned AddressSpace) { LLVMContextImpl *CImpl = C.pImpl; + assert(CImpl->getOpaquePointers() && + "Can only create opaque pointers in opaque pointer mode"); // Since AddressSpace #0 is the common case, we special case it. PointerType *&Entry = diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index 724b8f6b6ad2..1f757d7dbf4e 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -106,11 +106,9 @@ void TypeFinder::incorporateType(Type *Ty) { StructTypes.push_back(STy); // Add all unvisited subtypes to worklist for processing - for (Type::subtype_reverse_iterator I = Ty->subtype_rbegin(), - E = Ty->subtype_rend(); - I != E; ++I) - if (VisitedTypes.insert(*I).second) - TypeWorklist.push_back(*I); + for (Type *SubTy : llvm::reverse(Ty->subtypes())) + if (VisitedTypes.insert(SubTy).second) + TypeWorklist.push_back(SubTy); } while (!TypeWorklist.empty()); } diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp index 8837151f2e18..68489075cd88 100644 --- a/llvm/lib/IR/User.cpp +++ b/llvm/lib/IR/User.cpp @@ -107,7 +107,7 @@ MutableArrayRef<uint8_t> User::getDescriptor() { } bool User::isDroppable() const { - return isa<AssumeInst>(this); + return isa<AssumeInst>(this) || isa<PseudoProbeInst>(this); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index 1c595651b3d7..b475c8327874 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -176,6 +176,18 @@ Use *Value::getSingleUndroppableUse() { return Result; } +User *Value::getUniqueUndroppableUser() { + User *Result = nullptr; + for (auto *U : users()) { + if (!U->isDroppable()) { + if (Result && Result != U) + return nullptr; + Result = U; + } + } + return Result; +} + bool Value::hasNUndroppableUses(unsigned int N) const { return hasNItems(user_begin(), user_end(), N, isUnDroppableUser); } @@ -534,9 +546,7 @@ void Value::replaceUsesWithIf(Value *New, SmallVector<TrackingVH<Constant>, 8> Consts; SmallPtrSet<Constant *, 8> Visited; - for (use_iterator UI = use_begin(), E = use_end(); UI != E;) { - Use &U = *UI; - ++UI; + for (Use &U : llvm::make_early_inc_range(uses())) { if (!ShouldReplace(U)) continue; // Must handle Constants specially, we cannot call replaceUsesOfWith on a @@ -694,6 +704,7 @@ const Value *Value::stripPointerCastsForAliasAnalysis() const { const Value *Value::stripAndAccumulateConstantOffsets( const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, + bool AllowInvariantGroup, function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { if (!getType()->isPtrOrPtrVectorTy()) return this; @@ -753,6 +764,8 @@ const Value *Value::stripAndAccumulateConstantOffsets( } else if (const auto *Call = dyn_cast<CallBase>(V)) { if (const Value *RV = Call->getReturnedArgOperand()) V = RV; + if (AllowInvariantGroup && Call->isLaunderOrStripInvariantGroup()) + V = Call->getArgOperand(0); } assert(V->getType()->isPtrOrPtrVectorTy() && "Unexpected operand type!"); } while (Visited.insert(V).second); @@ -852,10 +865,9 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, CanBeNull = true; } } else if (const auto *Call = dyn_cast<CallBase>(this)) { - DerefBytes = Call->getDereferenceableBytes(AttributeList::ReturnIndex); + DerefBytes = Call->getRetDereferenceableBytes(); if (DerefBytes == 0) { - DerefBytes = - Call->getDereferenceableOrNullBytes(AttributeList::ReturnIndex); + DerefBytes = Call->getRetDereferenceableOrNullBytes(); CanBeNull = true; } } else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) { @@ -1014,8 +1026,7 @@ bool Value::isTransitiveUsedByMetadataOnly() const { llvm::SmallPtrSet<const User *, 32> Visited; WorkList.insert(WorkList.begin(), user_begin(), user_end()); while (!WorkList.empty()) { - const User *U = WorkList.back(); - WorkList.pop_back(); + const User *U = WorkList.pop_back_val(); Visited.insert(U); // If it is transitively used by a global value or a non-constant value, // it's obviously not only used by metadata. diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 758205a39eb3..dc4370d4b6ed 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -415,15 +415,18 @@ public: for (const GlobalAlias &GA : M.aliases()) visitGlobalAlias(GA); + for (const GlobalIFunc &GI : M.ifuncs()) + visitGlobalIFunc(GI); + for (const NamedMDNode &NMD : M.named_metadata()) visitNamedMDNode(NMD); for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) visitComdat(SMEC.getValue()); - visitModuleFlags(M); - visitModuleIdents(M); - visitModuleCommandLines(M); + visitModuleFlags(); + visitModuleIdents(); + visitModuleCommandLines(); verifyCompileUnits(); @@ -440,6 +443,7 @@ private: void visitGlobalValue(const GlobalValue &GV); void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); + void visitGlobalIFunc(const GlobalIFunc &GI); void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, const GlobalAlias &A, const Constant &C); @@ -448,9 +452,9 @@ private: void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); void visitComdat(const Comdat &C); - void visitModuleIdents(const Module &M); - void visitModuleCommandLines(const Module &M); - void visitModuleFlags(const Module &M); + void visitModuleIdents(); + void visitModuleCommandLines(); + void visitModuleFlags(); void visitModuleFlag(const MDNode *Op, DenseMap<const MDString *, const MDNode *> &SeenIDs, SmallVectorImpl<const MDNode *> &Requirements); @@ -461,6 +465,8 @@ private: void visitDereferenceableMetadata(Instruction &I, MDNode *MD); void visitProfMetadata(Instruction &I, MDNode *MD); void visitAnnotationMetadata(MDNode *Annotation); + void visitAliasScopeMetadata(const MDNode *MD); + void visitAliasScopeListMetadata(const MDNode *MD); template <class Ty> bool isValidMetadataArray(const MDTuple &N); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); @@ -547,6 +553,8 @@ private: void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, const Value *V, bool IsIntrinsic); void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); + template <typename T> + void verifyODRTypeAsScopeOperand(const MDNode &MD, T * = nullptr); void visitConstantExprsRecursively(const Constant *EntryC); void visitConstantExpr(const ConstantExpr *CE); @@ -569,6 +577,9 @@ private: /// declarations share the same calling convention. void verifyDeoptimizeCallingConvs(); + void verifyAttachedCallBundle(const CallBase &Call, + const OperandBundleUse &BU); + /// Verify all-or-nothing property of DIFile source attribute within a CU. void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F); @@ -816,6 +827,21 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) { visitGlobalValue(GA); } +void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) { + // Pierce through ConstantExprs and GlobalAliases and check that the resolver + // has a Function + const Function *Resolver = GI.getResolverFunction(); + Assert(Resolver, "IFunc must have a Function resolver", &GI); + + // Check that the immediate resolver operand (prior to any bitcasts) has the + // correct type + const Type *ResolverTy = GI.getResolver()->getType(); + const Type *ResolverFuncTy = + GlobalIFunc::getResolverFunctionType(GI.getValueType()); + Assert(ResolverTy == ResolverFuncTy->getPointerTo(), + "IFunc resolver has incorrect type", &GI); +} + void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { // There used to be various other llvm.dbg.* nodes, but we don't support // upgrading them and we want to reserve the namespace for future uses. @@ -834,6 +860,19 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { } } +template <typename T> +void Verifier::verifyODRTypeAsScopeOperand(const MDNode &MD, T *) { + if (isa<T>(MD)) { + if (auto *N = dyn_cast_or_null<DICompositeType>(cast<T>(MD).getScope())) + // Of all the supported tags for DICompositeType(see visitDICompositeType) + // we know that enum type cannot be a scope. + AssertDI(N->getTag() != dwarf::DW_TAG_enumeration_type, + "enum type is not a scope; check enum type ODR " + "violation", + N, &MD); + } +} + void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { // Only visit each node once. Metadata can be mutually recursive, so this // avoids infinite recursion here, as well as being an optimization. @@ -843,6 +882,12 @@ void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { Assert(&MD.getContext() == &Context, "MDNode context does not match Module context!", &MD); + // Makes sure when a scope operand is a ODR type, the ODR type uniquing does + // not create invalid debug metadata. + // TODO: check that the non-ODR-type scope operand is valid. + verifyODRTypeAsScopeOperand<DIType>(MD); + verifyODRTypeAsScopeOperand<DILocalScope>(MD); + switch (MD.getMetadataID()) { default: llvm_unreachable("Invalid MDNode subclass"); @@ -1091,7 +1136,8 @@ void Verifier::visitDICompositeType(const DICompositeType &N) { 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_variant_part, + N.getTag() == dwarf::DW_TAG_variant_part || + N.getTag() == dwarf::DW_TAG_namelist, "invalid tag", &N); AssertDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope()); @@ -1470,7 +1516,7 @@ void Verifier::visitComdat(const Comdat &C) { "comdat global value has private linkage", GV); } -void Verifier::visitModuleIdents(const Module &M) { +void Verifier::visitModuleIdents() { const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); if (!Idents) return; @@ -1487,7 +1533,7 @@ void Verifier::visitModuleIdents(const Module &M) { } } -void Verifier::visitModuleCommandLines(const Module &M) { +void Verifier::visitModuleCommandLines() { const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); if (!CommandLines) return; @@ -1505,7 +1551,7 @@ void Verifier::visitModuleCommandLines(const Module &M) { } } -void Verifier::visitModuleFlags(const Module &M) { +void Verifier::visitModuleFlags() { const NamedMDNode *Flags = M.getModuleFlagsMetadata(); if (!Flags) return; @@ -1824,9 +1870,8 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, const Value *V) { - if (Attrs.hasFnAttribute(Attr)) { - StringRef S = Attrs.getAttribute(AttributeList::FunctionIndex, Attr) - .getValueAsString(); + if (Attrs.hasFnAttr(Attr)) { + StringRef S = Attrs.getFnAttr(Attr).getValueAsString(); unsigned N; if (S.getAsInteger(10, N)) CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); @@ -1861,7 +1906,7 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, bool SawSwiftError = false; // Verify return value attributes. - AttributeSet RetAttrs = Attrs.getRetAttributes(); + AttributeSet RetAttrs = Attrs.getRetAttrs(); for (Attribute RetAttr : RetAttrs) Assert(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()), @@ -1874,7 +1919,7 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, // Verify parameter attributes. for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { Type *Ty = FT->getParamType(i); - AttributeSet ArgAttrs = Attrs.getParamAttributes(i); + AttributeSet ArgAttrs = Attrs.getParamAttrs(i); if (!IsIntrinsic) { Assert(!ArgAttrs.hasAttribute(Attribute::ImmArg), @@ -1928,63 +1973,63 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, } } - if (!Attrs.hasAttributes(AttributeList::FunctionIndex)) + if (!Attrs.hasFnAttrs()) return; - verifyAttributeTypes(Attrs.getFnAttributes(), V); - for (Attribute FnAttr : Attrs.getFnAttributes()) + verifyAttributeTypes(Attrs.getFnAttrs(), V); + for (Attribute FnAttr : Attrs.getFnAttrs()) Assert(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()), "Attribute '" + FnAttr.getAsString() + "' does not apply to functions!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) && - Attrs.hasFnAttribute(Attribute::ReadOnly)), + Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) && + Attrs.hasFnAttr(Attribute::ReadOnly)), "Attributes 'readnone and readonly' are incompatible!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) && - Attrs.hasFnAttribute(Attribute::WriteOnly)), + Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) && + Attrs.hasFnAttr(Attribute::WriteOnly)), "Attributes 'readnone and writeonly' are incompatible!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::ReadOnly) && - Attrs.hasFnAttribute(Attribute::WriteOnly)), + Assert(!(Attrs.hasFnAttr(Attribute::ReadOnly) && + Attrs.hasFnAttr(Attribute::WriteOnly)), "Attributes 'readonly and writeonly' are incompatible!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) && - Attrs.hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly)), + Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) && + Attrs.hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly)), "Attributes 'readnone and inaccessiblemem_or_argmemonly' are " "incompatible!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) && - Attrs.hasFnAttribute(Attribute::InaccessibleMemOnly)), + Assert(!(Attrs.hasFnAttr(Attribute::ReadNone) && + Attrs.hasFnAttr(Attribute::InaccessibleMemOnly)), "Attributes 'readnone and inaccessiblememonly' are incompatible!", V); - Assert(!(Attrs.hasFnAttribute(Attribute::NoInline) && - Attrs.hasFnAttribute(Attribute::AlwaysInline)), + Assert(!(Attrs.hasFnAttr(Attribute::NoInline) && + Attrs.hasFnAttr(Attribute::AlwaysInline)), "Attributes 'noinline and alwaysinline' are incompatible!", V); - if (Attrs.hasFnAttribute(Attribute::OptimizeNone)) { - Assert(Attrs.hasFnAttribute(Attribute::NoInline), + if (Attrs.hasFnAttr(Attribute::OptimizeNone)) { + Assert(Attrs.hasFnAttr(Attribute::NoInline), "Attribute 'optnone' requires 'noinline'!", V); - Assert(!Attrs.hasFnAttribute(Attribute::OptimizeForSize), + Assert(!Attrs.hasFnAttr(Attribute::OptimizeForSize), "Attributes 'optsize and optnone' are incompatible!", V); - Assert(!Attrs.hasFnAttribute(Attribute::MinSize), + Assert(!Attrs.hasFnAttr(Attribute::MinSize), "Attributes 'minsize and optnone' are incompatible!", V); } - if (Attrs.hasFnAttribute(Attribute::JumpTable)) { + if (Attrs.hasFnAttr(Attribute::JumpTable)) { const GlobalValue *GV = cast<GlobalValue>(V); Assert(GV->hasGlobalUnnamedAddr(), "Attribute 'jumptable' requires 'unnamed_addr'", V); } - if (Attrs.hasFnAttribute(Attribute::AllocSize)) { + if (Attrs.hasFnAttr(Attribute::AllocSize)) { std::pair<unsigned, Optional<unsigned>> Args = - Attrs.getAllocSizeArgs(AttributeList::FunctionIndex); + Attrs.getFnAttrs().getAllocSizeArgs(); auto CheckParam = [&](StringRef Name, unsigned ParamNo) { if (ParamNo >= FT->getNumParams()) { @@ -2009,17 +2054,16 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, return; } - if (Attrs.hasFnAttribute(Attribute::VScaleRange)) { + if (Attrs.hasFnAttr(Attribute::VScaleRange)) { std::pair<unsigned, unsigned> Args = - Attrs.getVScaleRangeArgs(AttributeList::FunctionIndex); + Attrs.getFnAttrs().getVScaleRangeArgs(); if (Args.first > Args.second && Args.second != 0) CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); } - if (Attrs.hasFnAttribute("frame-pointer")) { - StringRef FP = Attrs.getAttribute(AttributeList::FunctionIndex, - "frame-pointer").getValueAsString(); + if (Attrs.hasFnAttr("frame-pointer")) { + StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString(); if (FP != "all" && FP != "non-leaf" && FP != "none") CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); } @@ -2168,7 +2212,7 @@ void Verifier::verifyStatepoint(const CallBase &Call) { Call); if (TargetFuncType->isVarArg()) { - AttributeSet ArgAttrs = Attrs.getParamAttributes(5 + i); + AttributeSet ArgAttrs = Attrs.getParamAttrs(5 + i); Assert(!ArgAttrs.hasAttribute(Attribute::StructRet), "Attribute 'sret' cannot be used for vararg call arguments!", Call); @@ -2334,7 +2378,7 @@ void Verifier::visitFunction(const Function &F) { // On function declarations/definitions, we do not support the builtin // attribute. We do not check this in VerifyFunctionAttrs since that is // checking for Attributes that can/can not ever be on functions. - Assert(!Attrs.hasFnAttribute(Attribute::Builtin), + Assert(!Attrs.hasFnAttr(Attribute::Builtin), "Attribute 'builtin' can only be applied to a callsite.", &F); Assert(!Attrs.hasAttrSomewhere(Attribute::ElementType), @@ -2348,7 +2392,7 @@ void Verifier::visitFunction(const Function &F) { case CallingConv::C: break; case CallingConv::X86_INTR: { - Assert(F.arg_empty() || Attrs.hasParamAttribute(0, Attribute::ByVal), + Assert(F.arg_empty() || Attrs.hasParamAttr(0, Attribute::ByVal), "Calling convention parameter requires byval", &F); break; } @@ -2368,14 +2412,14 @@ void Verifier::visitFunction(const Function &F) { const unsigned StackAS = DL.getAllocaAddrSpace(); unsigned i = 0; for (const Argument &Arg : F.args()) { - Assert(!Attrs.hasParamAttribute(i, Attribute::ByVal), + Assert(!Attrs.hasParamAttr(i, Attribute::ByVal), "Calling convention disallows byval", &F); - Assert(!Attrs.hasParamAttribute(i, Attribute::Preallocated), + Assert(!Attrs.hasParamAttr(i, Attribute::Preallocated), "Calling convention disallows preallocated", &F); - Assert(!Attrs.hasParamAttribute(i, Attribute::InAlloca), + Assert(!Attrs.hasParamAttr(i, Attribute::InAlloca), "Calling convention disallows inalloca", &F); - if (Attrs.hasParamAttribute(i, Attribute::ByRef)) { + if (Attrs.hasParamAttr(i, Attribute::ByRef)) { // FIXME: Should also disallow LDS and GDS, but we don't have the enum // value here. Assert(Arg.getType()->getPointerAddressSpace() != StackAS, @@ -2416,7 +2460,7 @@ void Verifier::visitFunction(const Function &F) { } // Check that swifterror argument is only used by loads and stores. - if (Attrs.hasParamAttribute(i, Attribute::SwiftError)) { + if (Attrs.hasParamAttr(i, Attribute::SwiftError)) { verifySwiftErrorValue(&Arg); } ++i; @@ -2523,7 +2567,8 @@ void Verifier::visitFunction(const Function &F) { // uses. if (F.isIntrinsic() && F.getParent()->isMaterialized()) { const User *U; - if (F.hasAddressTaken(&U)) + if (F.hasAddressTaken(&U, false, true, false, + /*IgnoreARCAttachedCall=*/true)) Assert(false, "Invalid user of intrinsic instruction!", U); } @@ -2693,6 +2738,7 @@ void Verifier::visitReturnInst(ReturnInst &RI) { } void Verifier::visitSwitchInst(SwitchInst &SI) { + Assert(SI.getType()->isVoidTy(), "Switch must have void result type!", &SI); // Check to make sure that all of the constants in the switch instruction // have the same type as the switched-on value. Type *SwitchTy = SI.getCondition()->getType(); @@ -2726,7 +2772,7 @@ void Verifier::visitCallBrInst(CallBrInst &CBI) { Assert(CBI.getSuccessor(i)->getType()->isLabelTy(), "Callbr successors must all have pointer type!", &CBI); for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) { - Assert(i >= CBI.getNumArgOperands() || !isa<BasicBlock>(CBI.getOperand(i)), + Assert(i >= CBI.arg_size() || !isa<BasicBlock>(CBI.getOperand(i)), "Using an unescaped label as a callbr argument!", &CBI); if (isa<BasicBlock>(CBI.getOperand(i))) for (unsigned j = i + 1; j != e; ++j) @@ -3071,14 +3117,14 @@ void Verifier::visitCallBase(CallBase &Call) { Assert(Callee->getValueType() == FTy, "Intrinsic called with incompatible signature", Call); - if (Attrs.hasFnAttribute(Attribute::Speculatable)) { + if (Attrs.hasFnAttr(Attribute::Speculatable)) { // Don't allow speculatable on call sites, unless the underlying function // declaration is also speculatable. Assert(Callee && Callee->isSpeculatable(), "speculatable attribute may not apply to call sites", Call); } - if (Attrs.hasFnAttribute(Attribute::Preallocated)) { + if (Attrs.hasFnAttr(Attribute::Preallocated)) { Assert(Call.getCalledFunction()->getIntrinsicID() == Intrinsic::call_preallocated_arg, "preallocated as a call site attribute can only be on " @@ -3118,7 +3164,7 @@ void Verifier::visitCallBase(CallBase &Call) { Call); } - if (Attrs.hasParamAttribute(i, Attribute::ImmArg)) { + if (Attrs.hasParamAttr(i, Attribute::ImmArg)) { // Don't allow immarg on call sites, unless the underlying declaration // also has the matching immarg. Assert(Callee && Callee->hasParamAttribute(i, Attribute::ImmArg), @@ -3150,16 +3196,16 @@ void Verifier::visitCallBase(CallBase &Call) { bool SawReturned = false; for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { - if (Attrs.hasParamAttribute(Idx, Attribute::Nest)) + if (Attrs.hasParamAttr(Idx, Attribute::Nest)) SawNest = true; - if (Attrs.hasParamAttribute(Idx, Attribute::Returned)) + if (Attrs.hasParamAttr(Idx, Attribute::Returned)) SawReturned = true; } // Check attributes on the varargs part. for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { Type *Ty = Call.getArgOperand(Idx)->getType(); - AttributeSet ArgAttrs = Attrs.getParamAttributes(Idx); + AttributeSet ArgAttrs = Attrs.getParamAttrs(Idx); verifyParameterAttrs(ArgAttrs, Ty, &Call); if (ArgAttrs.hasAttribute(Attribute::Nest)) { @@ -3265,17 +3311,10 @@ void Verifier::visitCallBase(CallBase &Call) { Assert(!FoundAttachedCallBundle, "Multiple \"clang.arc.attachedcall\" operand bundles", Call); FoundAttachedCallBundle = true; + verifyAttachedCallBundle(Call, BU); } } - if (FoundAttachedCallBundle) - Assert((FTy->getReturnType()->isPointerTy() || - (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())), - "a call with operand bundle \"clang.arc.attachedcall\" must call a " - "function returning a pointer or a non-returning function that has " - "a void return type", - Call); - // Verify that each inlinable callsite of a debug-info-bearing function in a // debug-info-bearing function has a debug location attached to it. Failure to // do so causes assertion failures when the inliner sets up inline scope info. @@ -3315,7 +3354,7 @@ static bool isTypeCongruent(Type *L, Type *R) { return PL->getAddressSpace() == PR->getAddressSpace(); } -static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { +static AttrBuilder getParameterABIAttributes(unsigned I, AttributeList Attrs) { static const Attribute::AttrKind ABIAttrs[] = { Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, @@ -3323,15 +3362,15 @@ static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { Attribute::ByRef}; AttrBuilder Copy; for (auto AK : ABIAttrs) { - Attribute Attr = Attrs.getParamAttributes(I).getAttribute(AK); + Attribute Attr = Attrs.getParamAttrs(I).getAttribute(AK); if (Attr.isValid()) Copy.addAttribute(Attr); } // `align` is ABI-affecting only in combination with `byval` or `byref`. - if (Attrs.hasParamAttribute(I, Attribute::Alignment) && - (Attrs.hasParamAttribute(I, Attribute::ByVal) || - Attrs.hasParamAttribute(I, Attribute::ByRef))) + if (Attrs.hasParamAttr(I, Attribute::Alignment) && + (Attrs.hasParamAttr(I, Attribute::ByVal) || + Attrs.hasParamAttr(I, Attribute::ByRef))) Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); return Copy; } @@ -3383,12 +3422,12 @@ void Verifier::verifyMustTailCall(CallInst &CI) { // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes // are allowed in swifttailcc call - for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { AttrBuilder ABIAttrs = getParameterABIAttributes(I, CallerAttrs); SmallString<32> Context{CCName, StringRef(" musttail caller")}; verifyTailCCMustTailAttrs(ABIAttrs, Context); } - for (int I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { + for (unsigned I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { AttrBuilder ABIAttrs = getParameterABIAttributes(I, CalleeAttrs); SmallString<32> Context{CCName, StringRef(" musttail callee")}; verifyTailCCMustTailAttrs(ABIAttrs, Context); @@ -3406,7 +3445,7 @@ void Verifier::verifyMustTailCall(CallInst &CI) { 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) { + for (unsigned 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); @@ -3415,7 +3454,7 @@ void Verifier::verifyMustTailCall(CallInst &CI) { // - All ABI-impacting function attributes, such as sret, byval, inreg, // returned, preallocated, and inalloca, must match. - for (int I = 0, E = CallerTy->getNumParams(); I != E; ++I) { + for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { AttrBuilder CallerABIAttrs = getParameterABIAttributes(I, CallerAttrs); AttrBuilder CalleeABIAttrs = getParameterABIAttributes(I, CalleeAttrs); Assert(CallerABIAttrs == CalleeABIAttrs, @@ -4347,6 +4386,38 @@ void Verifier::visitAnnotationMetadata(MDNode *Annotation) { Assert(isa<MDString>(Op.get()), "operands must be strings"); } +void Verifier::visitAliasScopeMetadata(const MDNode *MD) { + unsigned NumOps = MD->getNumOperands(); + Assert(NumOps >= 2 && NumOps <= 3, "scope must have two or three operands", + MD); + Assert(MD->getOperand(0).get() == MD || isa<MDString>(MD->getOperand(0)), + "first scope operand must be self-referential or string", MD); + if (NumOps == 3) + Assert(isa<MDString>(MD->getOperand(2)), + "third scope operand must be string (if used)", MD); + + MDNode *Domain = dyn_cast<MDNode>(MD->getOperand(1)); + Assert(Domain != nullptr, "second scope operand must be MDNode", MD); + + unsigned NumDomainOps = Domain->getNumOperands(); + Assert(NumDomainOps >= 1 && NumDomainOps <= 2, + "domain must have one or two operands", Domain); + Assert(Domain->getOperand(0).get() == Domain || + isa<MDString>(Domain->getOperand(0)), + "first domain operand must be self-referential or string", Domain); + if (NumDomainOps == 2) + Assert(isa<MDString>(Domain->getOperand(1)), + "second domain operand must be string (if used)", Domain); +} + +void Verifier::visitAliasScopeListMetadata(const MDNode *MD) { + for (const MDOperand &Op : MD->operands()) { + const MDNode *OpMD = dyn_cast<MDNode>(Op); + Assert(OpMD != nullptr, "scope list must consist of MDNodes", MD); + visitAliasScopeMetadata(OpMD); + } +} + /// verifyInstruction - Verify that an instruction is well formed. /// void Verifier::visitInstruction(Instruction &I) { @@ -4403,10 +4474,21 @@ void Verifier::visitInstruction(Instruction &I) { } if (Function *F = dyn_cast<Function>(I.getOperand(i))) { + // This code checks whether the function is used as the operand of a + // clang_arc_attachedcall operand bundle. + auto IsAttachedCallOperand = [](Function *F, const CallBase *CBI, + int Idx) { + return CBI && CBI->isOperandBundleOfType( + LLVMContext::OB_clang_arc_attachedcall, Idx); + }; + // Check to make sure that the "address of" an intrinsic function is never - // taken. - Assert(!F->isIntrinsic() || - (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)), + // taken. Ignore cases where the address of the intrinsic function is used + // as the argument of operand bundle "clang.arc.attachedcall" as those + // cases are handled in verifyAttachedCallBundle. + Assert((!F->isIntrinsic() || + (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)) || + IsAttachedCallOperand(F, CBI, i)), "Cannot take the address of an intrinsic!", &I); Assert( !F->isIntrinsic() || isa<CallInst>(I) || @@ -4420,9 +4502,10 @@ void Verifier::visitInstruction(Instruction &I) { F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint || - F->getIntrinsicID() == Intrinsic::wasm_rethrow, + F->getIntrinsicID() == Intrinsic::wasm_rethrow || + IsAttachedCallOperand(F, CBI, i), "Cannot invoke an intrinsic other than donothing, patchpoint, " - "statepoint, coro_resume or coro_destroy", + "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall", &I); Assert(F->getParent() == &M, "Referencing function in another module!", &I, &M, F, F->getParent()); @@ -4471,6 +4554,11 @@ void Verifier::visitInstruction(Instruction &I) { visitRangeMetadata(I, Range, I.getType()); } + if (I.hasMetadata(LLVMContext::MD_invariant_group)) { + Assert(isa<LoadInst>(I) || isa<StoreInst>(I), + "invariant.group metadata is only for loads and stores", &I); + } + if (I.getMetadata(LLVMContext::MD_nonnull)) { Assert(I.getType()->isPointerTy(), "nonnull applies only to pointer types", &I); @@ -4489,6 +4577,11 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) + visitAliasScopeListMetadata(MD); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) + visitAliasScopeListMetadata(MD); + if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { Assert(I.getType()->isPointerTy(), "align applies only to pointer types", &I); @@ -4599,33 +4692,34 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { for (auto &Elem : Call.bundle_op_infos()) { Assert(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute(Elem.Tag->getKey()), - "tags must be valid attribute names"); + "tags must be valid attribute names", Call); Attribute::AttrKind Kind = Attribute::getAttrKindFromName(Elem.Tag->getKey()); unsigned ArgCount = Elem.End - Elem.Begin; if (Kind == Attribute::Alignment) { Assert(ArgCount <= 3 && ArgCount >= 2, - "alignment assumptions should have 2 or 3 arguments"); + "alignment assumptions should have 2 or 3 arguments", Call); Assert(Call.getOperand(Elem.Begin)->getType()->isPointerTy(), - "first argument should be a pointer"); + "first argument should be a pointer", Call); Assert(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(), - "second argument should be an integer"); + "second argument should be an integer", Call); if (ArgCount == 3) Assert(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(), - "third argument should be an integer if present"); + "third argument should be an integer if present", Call); return; } - Assert(ArgCount <= 2, "to many arguments"); + Assert(ArgCount <= 2, "too many arguments", Call); if (Kind == Attribute::None) break; if (Attribute::isIntAttrKind(Kind)) { - Assert(ArgCount == 2, "this attribute should have 2 arguments"); + Assert(ArgCount == 2, "this attribute should have 2 arguments", Call); Assert(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)), - "the second argument should be a constant integral value"); + "the second argument should be a constant integral value", Call); } else if (Attribute::canUseAsParamAttr(Kind)) { - Assert((ArgCount) == 1, "this attribute should have one argument"); + Assert((ArgCount) == 1, "this attribute should have one argument", + Call); } else if (Attribute::canUseAsFnAttr(Kind)) { - Assert((ArgCount) == 0, "this attribute has no argument"); + Assert((ArgCount) == 0, "this attribute has no argument", Call); } } break; @@ -4736,7 +4830,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "llvm.call.preallocated.setup"); FoundCall = true; size_t NumPreallocatedArgs = 0; - for (unsigned i = 0; i < UseCall->getNumArgOperands(); i++) { + for (unsigned i = 0; i < UseCall->arg_size(); i++) { if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { ++NumPreallocatedArgs; } @@ -4834,7 +4928,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Assert(AI && AI->isStaticAlloca(), "llvm.localescape only accepts static allocas", Call); } - FrameEscapeInfo[BB->getParent()].first = Call.getNumArgOperands(); + FrameEscapeInfo[BB->getParent()].first = Call.arg_size(); SawFrameEscape = true; break; } @@ -4883,7 +4977,7 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { break; } case Intrinsic::experimental_gc_relocate: { - Assert(Call.getNumArgOperands() == 3, "wrong number of arguments", Call); + Assert(Call.arg_size() == 3, "wrong number of arguments", Call); Assert(isa<PointerType>(Call.getType()->getScalarType()), "gc.relocate must return a pointer or a vector of pointers", Call); @@ -5017,14 +5111,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { case Intrinsic::masked_gather: { const APInt &Alignment = cast<ConstantInt>(Call.getArgOperand(1))->getValue(); - Assert(Alignment.isNullValue() || Alignment.isPowerOf2(), + Assert(Alignment.isZero() || Alignment.isPowerOf2(), "masked_gather: alignment must be 0 or a power of 2", Call); break; } case Intrinsic::masked_scatter: { const APInt &Alignment = cast<ConstantInt>(Call.getArgOperand(2))->getValue(); - Assert(Alignment.isNullValue() || Alignment.isPowerOf2(), + Assert(Alignment.isZero() || Alignment.isPowerOf2(), "masked_scatter: alignment must be 0 or a power of 2", Call); break; } @@ -5340,7 +5434,7 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { // Compare intrinsics carry an extra predicate metadata operand. if (isa<ConstrainedFPCmpIntrinsic>(FPI)) NumOperands += 1; - Assert((FPI.getNumArgOperands() == NumOperands), + Assert((FPI.arg_size() == NumOperands), "invalid arguments for constrained FP intrinsic", &FPI); switch (FPI.getIntrinsicID()) { @@ -5643,6 +5737,41 @@ void Verifier::verifyDeoptimizeCallingConvs() { } } +void Verifier::verifyAttachedCallBundle(const CallBase &Call, + const OperandBundleUse &BU) { + FunctionType *FTy = Call.getFunctionType(); + + Assert((FTy->getReturnType()->isPointerTy() || + (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())), + "a call with operand bundle \"clang.arc.attachedcall\" must call a " + "function returning a pointer or a non-returning function that has a " + "void return type", + Call); + + Assert((BU.Inputs.empty() || + (BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()))), + "operand bundle \"clang.arc.attachedcall\" can take either no " + "arguments or one function as an argument", + Call); + + if (BU.Inputs.empty()) + return; + + auto *Fn = cast<Function>(BU.Inputs.front()); + Intrinsic::ID IID = Fn->getIntrinsicID(); + + if (IID) { + Assert((IID == Intrinsic::objc_retainAutoreleasedReturnValue || + IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue), + "invalid function argument", Call); + } else { + StringRef FnName = Fn->getName(); + Assert((FnName == "objc_retainAutoreleasedReturnValue" || + FnName == "objc_unsafeClaimAutoreleasedReturnValue"), + "invalid function argument", Call); + } +} + void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { bool HasSource = F.getSource().hasValue(); if (!HasSourceDebugInfo.count(&U)) @@ -5671,6 +5800,7 @@ void Verifier::verifyNoAliasScopeDecl() { II); Assert(ScopeListMD->getNumOperands() == 1, "!id.scope.list must point to a list with a single scope", II); + visitAliasScopeListMetadata(ScopeListMD); } // Only check the domination rule when requested. Once all passes have been @@ -6036,11 +6166,7 @@ static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { // In the new format type nodes shall have a reference to the parent type as // its first operand. - MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); - if (!Parent) - return false; - - return true; + return isa_and_nonnull<MDNode>(Type->getOperand(0)); } bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { |
