summaryrefslogtreecommitdiff
path: root/llvm/lib/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AbstractCallSite.cpp2
-rw-r--r--llvm/lib/IR/AsmWriter.cpp644
-rw-r--r--llvm/lib/IR/Assumptions.cpp85
-rw-r--r--llvm/lib/IR/Attributes.cpp350
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp106
-rw-r--r--llvm/lib/IR/BasicBlock.cpp6
-rw-r--r--llvm/lib/IR/ConstantFold.cpp281
-rw-r--r--llvm/lib/IR/ConstantRange.cpp208
-rw-r--r--llvm/lib/IR/Constants.cpp137
-rw-r--r--llvm/lib/IR/Core.cpp38
-rw-r--r--llvm/lib/IR/DIBuilder.cpp200
-rw-r--r--llvm/lib/IR/DataLayout.cpp111
-rw-r--r--llvm/lib/IR/DebugInfo.cpp68
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp229
-rw-r--r--llvm/lib/IR/DiagnosticHandler.cpp2
-rw-r--r--llvm/lib/IR/DiagnosticInfo.cpp40
-rw-r--r--llvm/lib/IR/DiagnosticPrinter.cpp2
-rw-r--r--llvm/lib/IR/FPEnv.cpp10
-rw-r--r--llvm/lib/IR/Function.cpp229
-rw-r--r--llvm/lib/IR/GCStrategy.cpp18
-rw-r--r--llvm/lib/IR/Globals.cpp115
-rw-r--r--llvm/lib/IR/IRBuilder.cpp19
-rw-r--r--llvm/lib/IR/Instruction.cpp20
-rw-r--r--llvm/lib/IR/Instructions.cpp248
-rw-r--r--llvm/lib/IR/IntrinsicInst.cpp63
-rw-r--r--llvm/lib/IR/LLVMContext.cpp8
-rw-r--r--llvm/lib/IR/LLVMContextImpl.cpp25
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h205
-rw-r--r--llvm/lib/IR/LegacyPassManager.cpp2
-rw-r--r--llvm/lib/IR/Mangler.cpp7
-rw-r--r--llvm/lib/IR/Metadata.cpp11
-rw-r--r--llvm/lib/IR/Module.cpp4
-rw-r--r--llvm/lib/IR/ModuleSummaryIndex.cpp21
-rw-r--r--llvm/lib/IR/Operator.cpp35
-rw-r--r--llvm/lib/IR/OptBisect.cpp18
-rw-r--r--llvm/lib/IR/PassManager.cpp15
-rw-r--r--llvm/lib/IR/ProfileSummary.cpp4
-rw-r--r--llvm/lib/IR/PseudoProbe.cpp8
-rw-r--r--llvm/lib/IR/ReplaceConstant.cpp52
-rw-r--r--llvm/lib/IR/Statepoint.cpp6
-rw-r--r--llvm/lib/IR/Type.cpp48
-rw-r--r--llvm/lib/IR/TypeFinder.cpp8
-rw-r--r--llvm/lib/IR/User.cpp2
-rw-r--r--llvm/lib/IR/Value.cpp27
-rw-r--r--llvm/lib/IR/Verifier.cpp328
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) {