summaryrefslogtreecommitdiff
path: root/include/llvm/IR
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/IR')
-rw-r--r--include/llvm/IR/Argument.h99
-rw-r--r--include/llvm/IR/Attributes.h294
-rw-r--r--include/llvm/IR/BasicBlock.h87
-rw-r--r--include/llvm/IR/CallSite.h177
-rw-r--r--include/llvm/IR/Comdat.h6
-rw-r--r--include/llvm/IR/Constant.h7
-rw-r--r--include/llvm/IR/ConstantRange.h11
-rw-r--r--include/llvm/IR/Constants.h2
-rw-r--r--include/llvm/IR/DIBuilder.h28
-rw-r--r--include/llvm/IR/DataLayout.h42
-rw-r--r--include/llvm/IR/DebugInfoFlags.def3
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h209
-rw-r--r--include/llvm/IR/DiagnosticInfo.h591
-rw-r--r--include/llvm/IR/Dominators.h45
-rw-r--r--include/llvm/IR/Function.h101
-rw-r--r--include/llvm/IR/GlobalIndirectSymbol.h18
-rw-r--r--include/llvm/IR/GlobalObject.h13
-rw-r--r--include/llvm/IR/GlobalValue.h14
-rw-r--r--include/llvm/IR/IRBuilder.h104
-rw-r--r--include/llvm/IR/InlineAsm.h24
-rw-r--r--include/llvm/IR/InstVisitor.h3
-rw-r--r--include/llvm/IR/InstrTypes.h4
-rw-r--r--include/llvm/IR/Instruction.h51
-rw-r--r--include/llvm/IR/Instructions.h348
-rw-r--r--include/llvm/IR/IntrinsicInst.h65
-rw-r--r--include/llvm/IR/Intrinsics.h4
-rw-r--r--include/llvm/IR/Intrinsics.td82
-rw-r--r--include/llvm/IR/IntrinsicsAMDGPU.td109
-rw-r--r--include/llvm/IR/IntrinsicsARM.td2
-rw-r--r--include/llvm/IR/IntrinsicsHexagon.td870
-rw-r--r--include/llvm/IR/IntrinsicsNVVM.td84
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td32
-rw-r--r--include/llvm/IR/IntrinsicsWebAssembly.td2
-rw-r--r--include/llvm/IR/IntrinsicsX86.td156
-rw-r--r--include/llvm/IR/LLVMContext.h1
-rw-r--r--include/llvm/IR/MDBuilder.h9
-rw-r--r--include/llvm/IR/Mangler.h4
-rw-r--r--include/llvm/IR/Metadata.h15
-rw-r--r--include/llvm/IR/Module.h66
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h222
-rw-r--r--include/llvm/IR/ModuleSummaryIndexYAML.h135
-rw-r--r--include/llvm/IR/Operator.h24
-rw-r--r--include/llvm/IR/OptBisect.h18
-rw-r--r--include/llvm/IR/PassManager.h70
-rw-r--r--include/llvm/IR/PassManagerInternal.h2
-rw-r--r--include/llvm/IR/PatternMatch.h56
-rw-r--r--include/llvm/IR/PredIteratorCache.h14
-rw-r--r--include/llvm/IR/Statepoint.h2
-rw-r--r--include/llvm/IR/SymbolTableListTraits.h28
-rw-r--r--include/llvm/IR/TrackingMDRef.h17
-rw-r--r--include/llvm/IR/Type.h8
-rw-r--r--include/llvm/IR/TypeFinder.h14
-rw-r--r--include/llvm/IR/Use.h4
-rw-r--r--include/llvm/IR/UseListOrder.h7
-rw-r--r--include/llvm/IR/User.h14
-rw-r--r--include/llvm/IR/Value.h57
-rw-r--r--include/llvm/IR/ValueHandle.h136
-rw-r--r--include/llvm/IR/ValueSymbolTable.h45
58 files changed, 3390 insertions, 1265 deletions
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index d8b280a66f18..6fc1dd2f285a 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -21,127 +21,110 @@
namespace llvm {
-template <typename NodeTy> class SymbolTableListTraits;
-
-/// \brief LLVM Argument representation
-///
/// This class represents an incoming formal argument to a Function. A formal
/// argument, since it is ``formal'', does not contain an actual value but
/// instead represents the type, argument number, and attributes of an argument
/// for a specific function. When used in the body of said function, the
/// argument of course represents the value of the actual argument that the
/// function was called with.
-class Argument : public Value, public ilist_node<Argument> {
+class Argument : public Value {
virtual void anchor();
Function *Parent;
+ unsigned ArgNo;
- friend class SymbolTableListTraits<Argument>;
+ friend class Function;
void setParent(Function *parent);
public:
- /// \brief Constructor.
- ///
- /// If \p F is specified, the argument is inserted at the end of the argument
- /// list for \p F.
- explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr);
+ /// Argument constructor.
+ explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr,
+ unsigned ArgNo = 0);
inline const Function *getParent() const { return Parent; }
inline Function *getParent() { return Parent; }
- /// \brief Return the index of this formal argument in its containing
- /// function.
+ /// Return the index of this formal argument in its containing function.
///
/// For example in "void foo(int a, float b)" a is 0 and b is 1.
- unsigned getArgNo() const;
+ unsigned getArgNo() const {
+ assert(Parent && "can't get number of unparented arg");
+ return ArgNo;
+ }
- /// \brief Return true if this argument has the nonnull attribute on it in
- /// its containing function. Also returns true if at least one byte is known
- /// to be dereferenceable and the pointer is in addrspace(0).
+ /// Return true if this argument has the nonnull attribute. Also returns true
+ /// if at least one byte is known to be dereferenceable and the pointer is in
+ /// addrspace(0).
bool hasNonNullAttr() const;
- /// \brief If this argument has the dereferenceable attribute on it in its
- /// containing function, return the number of bytes known to be
- /// dereferenceable. Otherwise, zero is returned.
+ /// If this argument has the dereferenceable attribute, return the number of
+ /// bytes known to be dereferenceable. Otherwise, zero is returned.
uint64_t getDereferenceableBytes() const;
- /// \brief If this argument has the dereferenceable_or_null attribute on
- /// it in its containing function, return the number of bytes known to be
- /// dereferenceable. Otherwise, zero is returned.
+ /// If this argument has the dereferenceable_or_null attribute, return the
+ /// number of bytes known to be dereferenceable. Otherwise, zero is returned.
uint64_t getDereferenceableOrNullBytes() const;
- /// \brief Return true if this argument has the byval attribute on it in its
- /// containing function.
+ /// Return true if this argument has the byval attribute.
bool hasByValAttr() const;
- /// \brief Return true if this argument has the swiftself attribute.
+ /// Return true if this argument has the swiftself attribute.
bool hasSwiftSelfAttr() const;
- /// \brief Return true if this argument has the swifterror attribute.
+ /// Return true if this argument has the swifterror attribute.
bool hasSwiftErrorAttr() const;
- /// \brief Return true if this argument has the byval attribute or inalloca
- /// attribute on it in its containing function. These attributes both
- /// represent arguments being passed by value.
+ /// Return true if this argument has the byval attribute or inalloca
+ /// attribute. These attributes represent arguments being passed by value.
bool hasByValOrInAllocaAttr() const;
- /// \brief If this is a byval or inalloca argument, return its alignment.
+ /// If this is a byval or inalloca argument, return its alignment.
unsigned getParamAlignment() const;
- /// \brief Return true if this argument has the nest attribute on it in its
- /// containing function.
+ /// Return true if this argument has the nest attribute.
bool hasNestAttr() const;
- /// \brief Return true if this argument has the noalias attribute on it in its
- /// containing function.
+ /// Return true if this argument has the noalias attribute.
bool hasNoAliasAttr() const;
- /// \brief Return true if this argument has the nocapture attribute on it in
- /// its containing function.
+ /// Return true if this argument has the nocapture attribute.
bool hasNoCaptureAttr() const;
- /// \brief Return true if this argument has the sret attribute on it in its
- /// containing function.
+ /// Return true if this argument has the sret attribute.
bool hasStructRetAttr() const;
- /// \brief Return true if this argument has the returned attribute on it in
- /// its containing function.
+ /// Return true if this argument has the returned attribute.
bool hasReturnedAttr() const;
- /// \brief Return true if this argument has the readonly or readnone attribute
- /// on it in its containing function.
+ /// Return true if this argument has the readonly or readnone attribute.
bool onlyReadsMemory() const;
- /// \brief Return true if this argument has the inalloca attribute on it in
- /// its containing function.
+ /// Return true if this argument has the inalloca attribute.
bool hasInAllocaAttr() const;
- /// \brief Return true if this argument has the zext attribute on it in its
- /// containing function.
+ /// Return true if this argument has the zext attribute.
bool hasZExtAttr() const;
- /// \brief Return true if this argument has the sext attribute on it in its
- /// containing function.
+ /// Return true if this argument has the sext attribute.
bool hasSExtAttr() const;
- /// \brief Add a Attribute to an argument.
- void addAttr(AttributeSet AS);
+ /// Add attributes to an argument.
+ void addAttr(AttributeList AS);
void addAttr(Attribute::AttrKind Kind) {
- addAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ addAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
- /// \brief Remove a Attribute from an argument.
- void removeAttr(AttributeSet AS);
+ /// Remove attributes from an argument.
+ void removeAttr(AttributeList AS);
void removeAttr(Attribute::AttrKind Kind) {
- removeAttr(AttributeSet::get(getContext(), getArgNo() + 1, Kind));
+ removeAttr(AttributeList::get(getContext(), getArgNo() + 1, Kind));
}
- /// \brief Checks if an argument has a given attribute.
+ /// Check if an argument has a given attribute.
bool hasAttribute(Attribute::AttrKind Kind) const;
- /// \brief Method for support type inquiry through isa, cast, and
- /// dyn_cast.
+ /// Method for support type inquiry through isa, cast, and dyn_cast.
static inline bool classof(const Value *V) {
return V->getValueID() == ArgumentVal;
}
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index 15783858dd32..121f57a433ac 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -1,4 +1,4 @@
-//===-- llvm/Attributes.h - Container for Attributes ------------*- C++ -*-===//
+//===- llvm/Attributes.h - Container for Attributes -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,22 +18,24 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm-c/Types.h"
#include <bitset>
#include <cassert>
+#include <cstdint>
#include <map>
#include <string>
+#include <utility>
namespace llvm {
class AttrBuilder;
class AttributeImpl;
-class AttributeSetImpl;
+class AttributeListImpl;
class AttributeSetNode;
-class Constant;
template<typename T> struct DenseMapInfo;
class Function;
class LLVMContext;
@@ -73,11 +75,12 @@ public:
};
private:
- AttributeImpl *pImpl;
+ AttributeImpl *pImpl = nullptr;
+
Attribute(AttributeImpl *A) : pImpl(A) {}
public:
- Attribute() : pImpl(nullptr) {}
+ Attribute() = default;
//===--------------------------------------------------------------------===//
// Attribute Construction
@@ -194,13 +197,91 @@ inline Attribute unwrap(LLVMAttributeRef Attr) {
//===----------------------------------------------------------------------===//
/// \class
+/// This class holds the attributes for a particular argument, parameter,
+/// function, or return value. It is an immutable value type that is cheap to
+/// copy. Adding and removing enum attributes is intended to be fast, but adding
+/// and removing string or integer attributes involves a FoldingSet lookup.
+class AttributeSet {
+ // TODO: Extract AvailableAttrs from AttributeSetNode and store them here.
+ // This will allow an efficient implementation of addAttribute and
+ // removeAttribute for enum attrs.
+
+ /// Private implementation pointer.
+ AttributeSetNode *SetNode = nullptr;
+
+ friend AttributeListImpl;
+ template <typename Ty> friend struct DenseMapInfo;
+
+private:
+ explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {}
+
+public:
+ /// AttributeSet is a trivially copyable value type.
+ AttributeSet() = default;
+ AttributeSet(const AttributeSet &) = default;
+ ~AttributeSet() = default;
+
+ static AttributeSet get(LLVMContext &C, const AttrBuilder &B);
+ static AttributeSet get(LLVMContext &C, ArrayRef<Attribute> Attrs);
+
+ bool operator==(const AttributeSet &O) { return SetNode == O.SetNode; }
+ bool operator!=(const AttributeSet &O) { return !(*this == O); }
+
+ unsigned getNumAttributes() const;
+
+ bool hasAttributes() const { return SetNode != nullptr; }
+
+ bool hasAttribute(Attribute::AttrKind Kind) const;
+ bool hasAttribute(StringRef Kind) const;
+
+ Attribute getAttribute(Attribute::AttrKind Kind) const;
+ Attribute getAttribute(StringRef Kind) const;
+
+ unsigned getAlignment() const;
+ unsigned getStackAlignment() const;
+ uint64_t getDereferenceableBytes() const;
+ uint64_t getDereferenceableOrNullBytes() const;
+ std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+ std::string getAsString(bool InAttrGrp = false) const;
+
+ typedef const Attribute *iterator;
+ iterator begin() const;
+ iterator end() const;
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief Provide DenseMapInfo for AttributeSet.
+template <> struct DenseMapInfo<AttributeSet> {
+ static inline AttributeSet getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
+ }
+
+ static inline AttributeSet getTombstoneKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable;
+ return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val));
+ }
+
+ static unsigned getHashValue(AttributeSet AS) {
+ return (unsigned((uintptr_t)AS.SetNode) >> 4) ^
+ (unsigned((uintptr_t)AS.SetNode) >> 9);
+ }
+
+ static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
+};
+
+//===----------------------------------------------------------------------===//
+/// \class
/// \brief This class holds the attributes for a function, its return value, and
/// its parameters. You access the attributes for each of them via an index into
-/// the AttributeSet object. The function attributes are at index
-/// `AttributeSet::FunctionIndex', the return value is at index
-/// `AttributeSet::ReturnIndex', and the attributes for the parameters start at
+/// the AttributeList object. The function attributes are at index
+/// `AttributeList::FunctionIndex', the return value is at index
+/// `AttributeList::ReturnIndex', and the attributes for the parameters start at
/// index `1'.
-class AttributeSet {
+class AttributeList {
public:
enum AttrIndex : unsigned {
ReturnIndex = 0U,
@@ -209,115 +290,137 @@ public:
private:
friend class AttrBuilder;
- friend class AttributeSetImpl;
+ friend class AttributeListImpl;
+ friend class AttributeSet;
friend class AttributeSetNode;
+
template <typename Ty> friend struct DenseMapInfo;
/// \brief The attributes that we are managing. This can be null to represent
/// the empty attributes list.
- AttributeSetImpl *pImpl;
-
- /// \brief The attributes for the specified index are returned.
- AttributeSetNode *getAttributes(unsigned Index) const;
-
- /// \brief Create an AttributeSet with the specified parameters in it.
- static AttributeSet get(LLVMContext &C,
- ArrayRef<std::pair<unsigned, Attribute> > Attrs);
- static AttributeSet get(LLVMContext &C,
- ArrayRef<std::pair<unsigned,
- AttributeSetNode*> > Attrs);
+ AttributeListImpl *pImpl = nullptr;
- static AttributeSet getImpl(LLVMContext &C,
- ArrayRef<std::pair<unsigned,
- AttributeSetNode*> > Attrs);
+public:
+ /// \brief Create an AttributeList with the specified parameters in it.
+ static AttributeList get(LLVMContext &C,
+ ArrayRef<std::pair<unsigned, Attribute>> Attrs);
+ static AttributeList
+ get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
+
+ /// \brief Create an AttributeList from attribute sets for a function, its
+ /// return value, and all of its arguments.
+ static AttributeList get(LLVMContext &C, AttributeSet FnAttrs,
+ AttributeSet RetAttrs,
+ ArrayRef<AttributeSet> ArgAttrs);
+
+ static AttributeList
+ getImpl(LLVMContext &C,
+ ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
- explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {}
+private:
+ explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
public:
- AttributeSet() : pImpl(nullptr) {}
+ AttributeList() = default;
//===--------------------------------------------------------------------===//
- // AttributeSet Construction and Mutation
+ // AttributeList Construction and Mutation
//===--------------------------------------------------------------------===//
- /// \brief Return an AttributeSet with the specified parameters in it.
- static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs);
- static AttributeSet get(LLVMContext &C, unsigned Index,
- ArrayRef<Attribute::AttrKind> Kinds);
- static AttributeSet get(LLVMContext &C, unsigned Index,
- ArrayRef<StringRef> Kind);
- static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B);
+ /// \brief Return an AttributeList with the specified parameters in it.
+ static AttributeList get(LLVMContext &C, ArrayRef<AttributeList> Attrs);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ ArrayRef<Attribute::AttrKind> Kinds);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ ArrayRef<StringRef> Kind);
+ static AttributeList get(LLVMContext &C, unsigned Index,
+ const AttrBuilder &B);
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Kind) const;
+ AttributeList addAttribute(LLVMContext &C, unsigned Index,
+ Attribute::AttrKind Kind) const;
/// \brief Add an attribute to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
- StringRef Value = StringRef()) const;
+ AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind,
+ StringRef Value = StringRef()) const;
/// Add an attribute to the attribute set at the given indices. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
- Attribute A) const;
+ AttributeList addAttribute(LLVMContext &C, ArrayRef<unsigned> Indices,
+ Attribute A) const;
/// \brief Add attributes to the attribute set at the given index. Because
/// attribute sets are immutable, this returns a new set.
- AttributeSet addAttributes(LLVMContext &C, unsigned Index,
- AttributeSet Attrs) const;
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ AttributeList Attrs) const;
+
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ AttributeSet AS) const;
+
+ AttributeList addAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &B) const;
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
- Attribute::AttrKind Kind) const;
+ AttributeList removeAttribute(LLVMContext &C, unsigned Index,
+ Attribute::AttrKind Kind) const;
/// \brief Remove the specified attribute at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttribute(LLVMContext &C, unsigned Index,
- StringRef Kind) const;
+ AttributeList removeAttribute(LLVMContext &C, unsigned Index,
+ StringRef Kind) const;
/// \brief Remove the specified attributes at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
- AttributeSet Attrs) const;
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index,
+ AttributeList Attrs) const;
/// \brief Remove the specified attributes at the specified index from this
/// attribute list. Because attribute lists are immutable, this returns the
/// new list.
- AttributeSet removeAttributes(LLVMContext &C, unsigned Index,
- const AttrBuilder &Attrs) const;
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index,
+ const AttrBuilder &Attrs) const;
+
+ /// \brief Remove all attributes at the specified index from this
+ /// attribute list. Because attribute lists are immutable, this returns the
+ /// new list.
+ AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;
/// \brief Add the dereferenceable attribute to the attribute set at the given
/// index. Because attribute sets are immutable, this returns a new set.
- AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index,
- uint64_t Bytes) const;
+ AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
/// \brief Add the dereferenceable_or_null attribute to the attribute set at
/// the given index. Because attribute sets are immutable, this returns a new
/// set.
- AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
- uint64_t Bytes) const;
+ AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index,
+ uint64_t Bytes) const;
/// Add the allocsize attribute to the attribute set at the given index.
/// Because attribute sets are immutable, this returns a new set.
- AttributeSet addAllocSizeAttr(LLVMContext &C, unsigned Index,
- unsigned ElemSizeArg,
- const Optional<unsigned> &NumElemsArg);
+ AttributeList addAllocSizeAttr(LLVMContext &C, unsigned Index,
+ unsigned ElemSizeArg,
+ const Optional<unsigned> &NumElemsArg);
//===--------------------------------------------------------------------===//
- // AttributeSet Accessors
+ // AttributeList Accessors
//===--------------------------------------------------------------------===//
/// \brief Retrieve the LLVM context.
LLVMContext &getContext() const;
/// \brief The attributes for the specified index are returned.
- AttributeSet getParamAttributes(unsigned Index) const;
+ AttributeSet getAttributes(unsigned Index) const;
+
+ /// \brief The attributes for the argument or parameter at the given index are
+ /// returned.
+ AttributeSet getParamAttributes(unsigned ArgNo) const;
/// \brief The attributes for the ret value are returned.
AttributeSet getRetAttributes() const;
@@ -334,14 +437,17 @@ public:
/// \brief Return true if attribute exists at the given index.
bool hasAttributes(unsigned Index) const;
- /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(Attribute::AttrKind Kind) const;
- /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+ /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but
/// may be faster.
bool hasFnAttribute(StringRef Kind) const;
+ /// \brief Equivalent to hasAttribute(ArgNo + 1, Kind).
+ bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const;
+
/// \brief Return true if the specified attribute is set for at least one
/// parameter or for the return value. If Index is not nullptr, the index
/// of a parameter with the specified attribute is provided.
@@ -380,15 +486,11 @@ public:
iterator end(unsigned Slot) const;
/// operator==/!= - Provide equality predicates.
- bool operator==(const AttributeSet &RHS) const {
- return pImpl == RHS.pImpl;
- }
- bool operator!=(const AttributeSet &RHS) const {
- return pImpl != RHS.pImpl;
- }
+ bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; }
+ bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; }
//===--------------------------------------------------------------------===//
- // AttributeSet Introspection
+ // AttributeList Introspection
//===--------------------------------------------------------------------===//
/// \brief Return a raw pointer that uniquely identifies this attribute list.
@@ -410,30 +512,35 @@ public:
unsigned getSlotIndex(unsigned Slot) const;
/// \brief Return the attributes at the given slot.
- AttributeSet getSlotAttributes(unsigned Slot) const;
+ AttributeList getSlotAttributes(unsigned Slot) const;
void dump() const;
};
//===----------------------------------------------------------------------===//
/// \class
-/// \brief Provide DenseMapInfo for AttributeSet.
-template<> struct DenseMapInfo<AttributeSet> {
- static inline AttributeSet getEmptyKey() {
+/// \brief Provide DenseMapInfo for AttributeList.
+template <> struct DenseMapInfo<AttributeList> {
+ static inline AttributeList getEmptyKey() {
uintptr_t Val = static_cast<uintptr_t>(-1);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
- return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+ return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
- static inline AttributeSet getTombstoneKey() {
+
+ static inline AttributeList getTombstoneKey() {
uintptr_t Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable;
- return AttributeSet(reinterpret_cast<AttributeSetImpl*>(Val));
+ return AttributeList(reinterpret_cast<AttributeListImpl *>(Val));
}
- static unsigned getHashValue(AttributeSet AS) {
+
+ static unsigned getHashValue(AttributeList AS) {
return (unsigned((uintptr_t)AS.pImpl) >> 4) ^
(unsigned((uintptr_t)AS.pImpl) >> 9);
}
- static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; }
+
+ static bool isEqual(AttributeList LHS, AttributeList RHS) {
+ return LHS == RHS;
+ }
};
//===----------------------------------------------------------------------===//
@@ -445,22 +552,19 @@ template<> struct DenseMapInfo<AttributeSet> {
class AttrBuilder {
std::bitset<Attribute::EndAttrKinds> Attrs;
std::map<std::string, std::string> TargetDepAttrs;
- uint64_t Alignment;
- uint64_t StackAlignment;
- uint64_t DerefBytes;
- uint64_t DerefOrNullBytes;
- uint64_t AllocSizeArgs;
+ uint64_t Alignment = 0;
+ uint64_t StackAlignment = 0;
+ uint64_t DerefBytes = 0;
+ uint64_t DerefOrNullBytes = 0;
+ uint64_t AllocSizeArgs = 0;
public:
- AttrBuilder()
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0), AllocSizeArgs(0) {}
- AttrBuilder(const Attribute &A)
- : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
- DerefOrNullBytes(0), AllocSizeArgs(0) {
+ AttrBuilder() = default;
+ AttrBuilder(const Attribute &A) {
addAttribute(A);
}
- AttrBuilder(AttributeSet AS, unsigned Idx);
+ AttrBuilder(AttributeList AS, unsigned Idx);
+ AttrBuilder(AttributeSet AS);
void clear();
@@ -477,7 +581,7 @@ public:
AttrBuilder &removeAttribute(Attribute::AttrKind Val);
/// \brief Remove the attributes from the builder.
- AttrBuilder &removeAttributes(AttributeSet A, uint64_t Index);
+ AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
/// \brief Remove the target-dependent attribute to the builder.
AttrBuilder &removeAttribute(StringRef A);
@@ -507,7 +611,7 @@ public:
/// \brief Return true if the builder has any attribute that's in the
/// specified attribute.
- bool hasAttributes(AttributeSet A, uint64_t Index) const;
+ bool hasAttributes(AttributeList A, uint64_t Index) const;
/// \brief Return true if the builder has an alignment attribute.
bool hasAlignmentAttr() const;
@@ -562,8 +666,8 @@ public:
typedef std::pair<std::string, std::string> td_type;
typedef std::map<std::string, std::string>::iterator td_iterator;
typedef std::map<std::string, std::string>::const_iterator td_const_iterator;
- typedef llvm::iterator_range<td_iterator> td_range;
- typedef llvm::iterator_range<td_const_iterator> td_const_range;
+ typedef iterator_range<td_iterator> td_range;
+ typedef iterator_range<td_const_iterator> td_const_range;
td_iterator td_begin() { return TargetDepAttrs.begin(); }
td_iterator td_end() { return TargetDepAttrs.end(); }
@@ -600,4 +704,4 @@ void mergeAttributesForInlining(Function &Caller, const Function &Callee);
} // end llvm namespace
-#endif
+#endif // LLVM_IR_ATTRIBUTES_H
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index 93dbd573ee16..bd210e1abf31 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -105,27 +105,35 @@ public:
///
/// Note: this is undefined behavior if the block does not have a parent.
const Module *getModule() const;
- Module *getModule();
+ Module *getModule() {
+ return const_cast<Module *>(
+ static_cast<const BasicBlock *>(this)->getModule());
+ }
/// \brief Returns the terminator instruction if the block is well formed or
/// null if the block is not well formed.
- TerminatorInst *getTerminator();
- const TerminatorInst *getTerminator() const;
+ const TerminatorInst *getTerminator() const LLVM_READONLY;
+ TerminatorInst *getTerminator() {
+ return const_cast<TerminatorInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminator());
+ }
/// \brief Returns the call instruction calling @llvm.experimental.deoptimize
/// prior to the terminating return instruction of this basic block, if such a
/// call is present. Otherwise, returns null.
- CallInst *getTerminatingDeoptimizeCall();
- const CallInst *getTerminatingDeoptimizeCall() const {
- return const_cast<BasicBlock *>(this)->getTerminatingDeoptimizeCall();
+ const CallInst *getTerminatingDeoptimizeCall() const;
+ CallInst *getTerminatingDeoptimizeCall() {
+ return const_cast<CallInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminatingDeoptimizeCall());
}
/// \brief Returns the call instruction marked 'musttail' prior to the
/// terminating return instruction of this basic block, if such a call is
/// present. Otherwise, returns null.
- CallInst *getTerminatingMustTailCall();
- const CallInst *getTerminatingMustTailCall() const {
- return const_cast<BasicBlock *>(this)->getTerminatingMustTailCall();
+ const CallInst *getTerminatingMustTailCall() const;
+ CallInst *getTerminatingMustTailCall() {
+ return const_cast<CallInst *>(
+ static_cast<const BasicBlock *>(this)->getTerminatingMustTailCall());
}
/// \brief Returns a pointer to the first instruction in this block that is
@@ -134,32 +142,36 @@ public:
/// When adding instructions to the beginning of the basic block, they should
/// be added before the returned value, not before the first instruction,
/// which might be PHI. Returns 0 is there's no non-PHI instruction.
- Instruction* getFirstNonPHI();
- const Instruction* getFirstNonPHI() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHI();
+ const Instruction* getFirstNonPHI() const;
+ Instruction* getFirstNonPHI() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHI());
}
/// \brief Returns a pointer to the first instruction in this block that is not
/// a PHINode or a debug intrinsic.
- Instruction* getFirstNonPHIOrDbg();
- const Instruction* getFirstNonPHIOrDbg() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbg();
+ const Instruction* getFirstNonPHIOrDbg() const;
+ Instruction* getFirstNonPHIOrDbg() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbg());
}
/// \brief Returns a pointer to the first instruction in this block that is not
/// a PHINode, a debug intrinsic, or a lifetime intrinsic.
- Instruction* getFirstNonPHIOrDbgOrLifetime();
- const Instruction* getFirstNonPHIOrDbgOrLifetime() const {
- return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();
+ const Instruction* getFirstNonPHIOrDbgOrLifetime() const;
+ Instruction* getFirstNonPHIOrDbgOrLifetime() {
+ return const_cast<Instruction *>(
+ static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbgOrLifetime());
}
/// \brief Returns an iterator to the first instruction in this block that is
/// suitable for inserting a non-PHI instruction.
///
/// In particular, it skips all PHIs and LandingPad instructions.
- iterator getFirstInsertionPt();
- const_iterator getFirstInsertionPt() const {
- return const_cast<BasicBlock*>(this)->getFirstInsertionPt();
+ const_iterator getFirstInsertionPt() const;
+ iterator getFirstInsertionPt() {
+ return static_cast<const BasicBlock *>(this)
+ ->getFirstInsertionPt().getNonConst();
}
/// \brief Unlink 'this' from the containing function, but do not delete it.
@@ -188,9 +200,10 @@ public:
/// \brief Return the predecessor of this block if it has a single predecessor
/// block. Otherwise return a null pointer.
- BasicBlock *getSinglePredecessor();
- const BasicBlock *getSinglePredecessor() const {
- return const_cast<BasicBlock*>(this)->getSinglePredecessor();
+ const BasicBlock *getSinglePredecessor() const;
+ BasicBlock *getSinglePredecessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getSinglePredecessor());
}
/// \brief Return the predecessor of this block if it has a unique predecessor
@@ -199,27 +212,30 @@ public:
/// Note that unique predecessor doesn't mean single edge, there can be
/// multiple edges from the unique predecessor to this block (for example a
/// switch statement with multiple cases having the same destination).
- BasicBlock *getUniquePredecessor();
- const BasicBlock *getUniquePredecessor() const {
- return const_cast<BasicBlock*>(this)->getUniquePredecessor();
+ const BasicBlock *getUniquePredecessor() const;
+ BasicBlock *getUniquePredecessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getUniquePredecessor());
}
/// \brief Return the successor of this block if it has a single successor.
/// Otherwise return a null pointer.
///
/// This method is analogous to getSinglePredecessor above.
- BasicBlock *getSingleSuccessor();
- const BasicBlock *getSingleSuccessor() const {
- return const_cast<BasicBlock*>(this)->getSingleSuccessor();
+ const BasicBlock *getSingleSuccessor() const;
+ BasicBlock *getSingleSuccessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getSingleSuccessor());
}
/// \brief Return the successor of this block if it has a unique successor.
/// Otherwise return a null pointer.
///
/// This method is analogous to getUniquePredecessor above.
- BasicBlock *getUniqueSuccessor();
- const BasicBlock *getUniqueSuccessor() const {
- return const_cast<BasicBlock*>(this)->getUniqueSuccessor();
+ const BasicBlock *getUniqueSuccessor() const;
+ BasicBlock *getUniqueSuccessor() {
+ return const_cast<BasicBlock *>(
+ static_cast<const BasicBlock *>(this)->getUniqueSuccessor());
}
//===--------------------------------------------------------------------===//
@@ -321,8 +337,11 @@ public:
bool isLandingPad() const;
/// \brief Return the landingpad instruction associated with the landing pad.
- LandingPadInst *getLandingPadInst();
const LandingPadInst *getLandingPadInst() const;
+ LandingPadInst *getLandingPadInst() {
+ return const_cast<LandingPadInst *>(
+ static_cast<const BasicBlock *>(this)->getLandingPadInst());
+ }
private:
/// \brief Increment the internal refcount of the number of BlockAddresses
diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h
index b02c89474146..79f59557a5d6 100644
--- a/include/llvm/IR/CallSite.h
+++ b/include/llvm/IR/CallSite.h
@@ -65,11 +65,9 @@ protected:
explicit CallSiteBase(ValTy *II) { *this = get(II); }
private:
- /// CallSiteBase::get - This static method is sort of like a constructor. It
- /// will create an appropriate call site for a Call or Invoke instruction, but
- /// it can also create a null initialized CallSiteBase object for something
- /// which is NOT a call site.
- ///
+ /// This static method is like a constructor. It will create an appropriate
+ /// call site for a Call or Invoke instruction, but it can also create a null
+ /// initialized CallSiteBase object for something which is NOT a call site.
static CallSiteBase get(ValTy *V) {
if (InstrTy *II = dyn_cast<InstrTy>(V)) {
if (II->getOpcode() == Instruction::Call)
@@ -81,38 +79,47 @@ private:
}
public:
- /// isCall - true if a CallInst is enclosed.
- /// Note that !isCall() does not mean it is an InvokeInst enclosed,
- /// it also could signify a NULL Instruction pointer.
+ /// Return true if a CallInst is enclosed. Note that !isCall() does not mean
+ /// an InvokeInst is enclosed. It may also signify a NULL instruction pointer.
bool isCall() const { return I.getInt(); }
- /// isInvoke - true if a InvokeInst is enclosed.
- ///
+ /// Return true if a InvokeInst is enclosed.
bool isInvoke() const { return getInstruction() && !I.getInt(); }
InstrTy *getInstruction() const { return I.getPointer(); }
InstrTy *operator->() const { return I.getPointer(); }
explicit operator bool() const { return I.getPointer(); }
- /// Get the basic block containing the call site
+ /// Get the basic block containing the call site.
BBTy* getParent() const { return getInstruction()->getParent(); }
- /// getCalledValue - Return the pointer to function that is being called.
- ///
+ /// Return the pointer to function that is being called.
ValTy *getCalledValue() const {
assert(getInstruction() && "Not a call or invoke instruction!");
return *getCallee();
}
- /// getCalledFunction - Return the function being called if this is a direct
- /// call, otherwise return null (if it's an indirect call).
- ///
+ /// Return the function being called if this is a direct call, otherwise
+ /// return null (if it's an indirect call).
FunTy *getCalledFunction() const {
return dyn_cast<FunTy>(getCalledValue());
}
- /// setCalledFunction - Set the callee to the specified value.
- ///
+ /// Return true if the callsite is an indirect call.
+ bool isIndirectCall() const {
+ Value *V = getCalledValue();
+ if (!V)
+ return false;
+ if (isa<FunTy>(V) || isa<Constant>(V))
+ return false;
+ if (CallInst *CI = dyn_cast<CallInst>(getInstruction())) {
+ if (CI->isInlineAsm())
+ return false;
+ }
+ return true;
+ }
+
+ /// Set the callee to the specified value.
void setCalledFunction(Value *V) {
assert(getInstruction() && "Not a call or invoke instruction!");
*getCallee() = V;
@@ -129,8 +136,7 @@ public:
return static_cast<Intrinsic::ID>(0);
}
- /// isCallee - Determine whether the passed iterator points to the
- /// callee operand's Use.
+ /// Determine whether the passed iterator points to the callee operand's Use.
bool isCallee(Value::const_user_iterator UI) const {
return isCallee(&UI.getUse());
}
@@ -138,24 +144,23 @@ public:
/// Determine whether this Use is the callee operand's Use.
bool isCallee(const Use *U) const { return getCallee() == U; }
- /// \brief Determine whether the passed iterator points to an argument
- /// operand.
+ /// Determine whether the passed iterator points to an argument operand.
bool isArgOperand(Value::const_user_iterator UI) const {
return isArgOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to an argument operand.
+ /// Determine whether the passed use points to an argument operand.
bool isArgOperand(const Use *U) const {
assert(getInstruction() == U->getUser());
return arg_begin() <= U && U < arg_end();
}
- /// \brief Determine whether the passed iterator points to a bundle operand.
+ /// Determine whether the passed iterator points to a bundle operand.
bool isBundleOperand(Value::const_user_iterator UI) const {
return isBundleOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to a bundle operand.
+ /// Determine whether the passed use points to a bundle operand.
bool isBundleOperand(const Use *U) const {
assert(getInstruction() == U->getUser());
if (!hasOperandBundles())
@@ -165,12 +170,12 @@ public:
OperandNo < getBundleOperandsEndIndex();
}
- /// \brief Determine whether the passed iterator points to a data operand.
+ /// Determine whether the passed iterator points to a data operand.
bool isDataOperand(Value::const_user_iterator UI) const {
return isDataOperand(&UI.getUse());
}
- /// \brief Determine whether the passed use points to a data operand.
+ /// Determine whether the passed use points to a data operand.
bool isDataOperand(const Use *U) const {
return data_operands_begin() <= U && U < data_operands_end();
}
@@ -200,8 +205,8 @@ public:
return U - arg_begin();
}
- /// arg_iterator - The type of iterator to use when looping over actual
- /// arguments at this call site.
+ /// The type of iterator to use when looping over actual arguments at this
+ /// call site.
typedef IterTy arg_iterator;
iterator_range<IterTy> args() const {
@@ -210,8 +215,7 @@ public:
bool arg_empty() const { return arg_end() == arg_begin(); }
unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); }
- /// Given a value use iterator, returns the data operand that corresponds to
- /// it.
+ /// Given a value use iterator, return the data operand corresponding to it.
/// Iterator must actually correspond to a data operand.
unsigned getDataOperandNo(Value::const_user_iterator UI) const {
return getDataOperandNo(&UI.getUse());
@@ -253,21 +257,19 @@ public:
return std::distance(data_operands_begin(), data_operands_end());
}
- /// getType - Return the type of the instruction that generated this call site
- ///
+ /// Return the type of the instruction that generated this call site.
Type *getType() const { return (*this)->getType(); }
- /// getCaller - Return the caller function for this call site
- ///
+ /// Return the caller function for this call site.
FunTy *getCaller() const { return (*this)->getParent()->getParent(); }
- /// \brief Tests if this call site must be tail call optimized. Only a
- /// CallInst can be tail call optimized.
+ /// Tests if this call site must be tail call optimized. Only a CallInst can
+ /// be tail call optimized.
bool isMustTailCall() const {
return isCall() && cast<CallInst>(getInstruction())->isMustTailCall();
}
- /// \brief Tests if this call site is marked as a tail call.
+ /// Tests if this call site is marked as a tail call.
bool isTailCall() const {
return isCall() && cast<CallInst>(getInstruction())->isTailCall();
}
@@ -303,11 +305,11 @@ public:
return false;
}
- /// getCallingConv/setCallingConv - get or set the calling convention of the
- /// call.
+ /// Get the calling convention of the call.
CallingConv::ID getCallingConv() const {
CALLSITE_DELEGATE_GETTER(getCallingConv());
}
+ /// Set the calling convention of the call.
void setCallingConv(CallingConv::ID CC) {
CALLSITE_DELEGATE_SETTER(setCallingConv(CC));
}
@@ -320,12 +322,12 @@ public:
CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty));
}
- /// getAttributes/setAttributes - get or set the parameter attributes of
- /// the call.
- AttributeSet getAttributes() const {
+ /// Get the parameter attributes of the call.
+ AttributeList getAttributes() const {
CALLSITE_DELEGATE_GETTER(getAttributes());
}
- void setAttributes(AttributeSet PAL) {
+ /// Set the parameter attributes of the call.
+ void setAttributes(AttributeList PAL) {
CALLSITE_DELEGATE_SETTER(setAttributes(PAL));
}
@@ -345,19 +347,24 @@ public:
CALLSITE_DELEGATE_SETTER(removeAttribute(i, Kind));
}
- /// \brief Return true if this function has the given attribute.
+ /// Return true if this function has the given attribute.
bool hasFnAttr(Attribute::AttrKind Kind) const {
CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
- /// \brief Return true if this function has the given attribute.
+ /// Return true if this function has the given attribute.
bool hasFnAttr(StringRef Kind) const {
CALLSITE_DELEGATE_GETTER(hasFnAttr(Kind));
}
- /// \brief Return true if the call or the callee has the given attribute.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
- CALLSITE_DELEGATE_GETTER(paramHasAttr(i, Kind));
+ /// Return true if this return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(hasRetAttr(Kind));
+ }
+
+ /// Return true if the call or the callee has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ CALLSITE_DELEGATE_GETTER(paramHasAttr(ArgNo, Kind));
}
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -368,8 +375,8 @@ public:
CALLSITE_DELEGATE_GETTER(getAttribute(i, Kind));
}
- /// \brief Return true if the data operand at index \p i directly or
- /// indirectly has the attribute \p A.
+ /// Return true if the data operand at index \p i directly or indirectly has
+ /// the attribute \p A.
///
/// Normal call or invoke arguments have per operand attributes, as specified
/// in the attribute set attached to this instruction, while operand bundle
@@ -379,37 +386,36 @@ public:
CALLSITE_DELEGATE_GETTER(dataOperandHasImpliedAttr(i, Kind));
}
- /// @brief Extract the alignment for a call or parameter (0=unknown).
+ /// Extract the alignment for a call or parameter (0=unknown).
uint16_t getParamAlignment(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getParamAlignment(i));
}
- /// @brief Extract the number of dereferenceable bytes for a call or
- /// parameter (0=unknown).
+ /// Extract the number of dereferenceable bytes for a call or parameter
+ /// (0=unknown).
uint64_t getDereferenceableBytes(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i));
}
- /// @brief Extract the number of dereferenceable_or_null bytes for a call or
+ /// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(uint16_t i) const {
CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i));
}
- /// @brief Determine if the parameter or return value is marked with NoAlias
+ /// Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
CALLSITE_DELEGATE_GETTER(doesNotAlias(n));
}
- /// \brief Return true if the call should not be treated as a call to a
- /// builtin.
+ /// Return true if the call should not be treated as a call to a builtin.
bool isNoBuiltin() const {
CALLSITE_DELEGATE_GETTER(isNoBuiltin());
}
- /// @brief Return true if the call should not be inlined.
+ /// Return true if the call should not be inlined.
bool isNoInline() const {
CALLSITE_DELEGATE_GETTER(isNoInline());
}
@@ -417,7 +423,7 @@ public:
CALLSITE_DELEGATE_SETTER(setIsNoInline(Value));
}
- /// @brief Determine if the call does not access memory.
+ /// Determine if the call does not access memory.
bool doesNotAccessMemory() const {
CALLSITE_DELEGATE_GETTER(doesNotAccessMemory());
}
@@ -425,7 +431,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory());
}
- /// @brief Determine if the call does not access or only reads memory.
+ /// Determine if the call does not access or only reads memory.
bool onlyReadsMemory() const {
CALLSITE_DELEGATE_GETTER(onlyReadsMemory());
}
@@ -433,7 +439,7 @@ public:
CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory());
}
- /// @brief Determine if the call does not access or only writes memory.
+ /// Determine if the call does not access or only writes memory.
bool doesNotReadMemory() const {
CALLSITE_DELEGATE_GETTER(doesNotReadMemory());
}
@@ -441,7 +447,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotReadMemory());
}
- /// @brief Determine if the call can access memmory only using pointers based
+ /// Determine if the call can access memmory only using pointers based
/// on its arguments.
bool onlyAccessesArgMemory() const {
CALLSITE_DELEGATE_GETTER(onlyAccessesArgMemory());
@@ -450,7 +456,7 @@ public:
CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory());
}
- /// @brief Determine if the call cannot return.
+ /// Determine if the call cannot return.
bool doesNotReturn() const {
CALLSITE_DELEGATE_GETTER(doesNotReturn());
}
@@ -458,7 +464,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotReturn());
}
- /// @brief Determine if the call cannot unwind.
+ /// Determine if the call cannot unwind.
bool doesNotThrow() const {
CALLSITE_DELEGATE_GETTER(doesNotThrow());
}
@@ -466,7 +472,7 @@ public:
CALLSITE_DELEGATE_SETTER(setDoesNotThrow());
}
- /// @brief Determine if the call can be duplicated.
+ /// Determine if the call can be duplicated.
bool cannotDuplicate() const {
CALLSITE_DELEGATE_GETTER(cannotDuplicate());
}
@@ -474,7 +480,7 @@ public:
CALLSITE_DELEGATE_GETTER(setCannotDuplicate());
}
- /// @brief Determine if the call is convergent.
+ /// Determine if the call is convergent.
bool isConvergent() const {
CALLSITE_DELEGATE_GETTER(isConvergent());
}
@@ -546,31 +552,31 @@ public:
cast<InvokeInst>(II)->getOperandBundlesAsDefs(Defs);
}
- /// @brief Determine whether this data operand is not captured.
+ /// Determine whether this data operand is not captured.
bool doesNotCapture(unsigned OpNo) const {
return dataOperandHasImpliedAttr(OpNo + 1, Attribute::NoCapture);
}
- /// @brief Determine whether this argument is passed by value.
+ /// Determine whether this argument is passed by value.
bool isByValArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ByVal);
+ return paramHasAttr(ArgNo, Attribute::ByVal);
}
- /// @brief Determine whether this argument is passed in an alloca.
+ /// Determine whether this argument is passed in an alloca.
bool isInAllocaArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::InAlloca);
+ return paramHasAttr(ArgNo, Attribute::InAlloca);
}
- /// @brief Determine whether this argument is passed by value or in an alloca.
+ /// Determine whether this argument is passed by value or in an alloca.
bool isByValOrInAllocaArgument(unsigned ArgNo) const {
- return paramHasAttr(ArgNo + 1, Attribute::ByVal) ||
- paramHasAttr(ArgNo + 1, Attribute::InAlloca);
+ return paramHasAttr(ArgNo, Attribute::ByVal) ||
+ paramHasAttr(ArgNo, Attribute::InAlloca);
}
- /// @brief Determine if there are is an inalloca argument. Only the last
- /// argument can have the inalloca attribute.
+ /// Determine if there are is an inalloca argument. Only the last argument can
+ /// have the inalloca attribute.
bool hasInAllocaArgument() const {
- return paramHasAttr(arg_size(), Attribute::InAlloca);
+ return !arg_empty() && paramHasAttr(arg_size() - 1, Attribute::InAlloca);
}
bool doesNotAccessMemory(unsigned OpNo) const {
@@ -582,11 +588,16 @@ public:
dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
}
- /// @brief Return true if the return value is known to be not null.
+ bool doesNotReadMemory(unsigned OpNo) const {
+ return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
+ dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+ }
+
+ /// Return true if the return value is known to be not null.
/// This may be because it has the nonnull attribute, or because at least
/// one byte is dereferenceable and the pointer is in addrspace(0).
bool isReturnNonNull() const {
- if (paramHasAttr(0, Attribute::NonNull))
+ if (hasRetAttr(Attribute::NonNull))
return true;
else if (getDereferenceableBytes(0) > 0 &&
getType()->getPointerAddressSpace() == 0)
@@ -595,8 +606,8 @@ public:
return false;
}
- /// hasArgument - Returns true if this CallSite passes the given Value* as an
- /// argument to the called function.
+ /// Returns true if this CallSite passes the given Value* as an argument to
+ /// the called function.
bool hasArgument(const Value *Arg) const {
for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E;
++AI)
@@ -661,7 +672,7 @@ template <> struct DenseMapInfo<CallSite> {
}
};
-/// ImmutableCallSite - establish a view to a call site for examination
+/// Establish a view to a call site for examination.
class ImmutableCallSite : public CallSiteBase<> {
public:
ImmutableCallSite() = default;
diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h
index f4a391c31ae2..fa87093ca50a 100644
--- a/include/llvm/IR/Comdat.h
+++ b/include/llvm/IR/Comdat.h
@@ -1,4 +1,4 @@
-//===-- llvm/IR/Comdat.h - Comdat definitions -------------------*- C++ -*-===//
+//===- llvm/IR/Comdat.h - Comdat definitions --------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -51,8 +51,8 @@ private:
Comdat();
// Points to the map in Module.
- StringMapEntry<Comdat> *Name;
- SelectionKind SK;
+ StringMapEntry<Comdat> *Name = nullptr;
+ SelectionKind SK = Any;
};
inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) {
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 99c970ebb633..3b3694e7e60d 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -152,12 +152,13 @@ public:
/// hanging off of the globals.
void removeDeadConstantUsers() const;
- Constant *stripPointerCasts() {
+ const Constant *stripPointerCasts() const {
return cast<Constant>(Value::stripPointerCasts());
}
- const Constant *stripPointerCasts() const {
- return const_cast<Constant*>(this)->stripPointerCasts();
+ Constant *stripPointerCasts() {
+ return const_cast<Constant*>(
+ static_cast<const Constant *>(this)->stripPointerCasts());
}
};
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index 27a9b1364448..6d704666933f 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -45,9 +45,6 @@ class MDNode;
class ConstantRange {
APInt Lower, Upper;
- // If we have move semantics, pass APInts by value and move them into place.
- typedef APInt APIntMoveTy;
-
public:
/// Initialize a full (the default) or empty set for the specified bit width.
///
@@ -55,12 +52,12 @@ public:
/// Initialize a range to hold the single specified value.
///
- ConstantRange(APIntMoveTy Value);
+ ConstantRange(APInt Value);
/// @brief Initialize a range of values explicitly. This will assert out if
/// Lower==Upper and Lower != Min or Max value for its type. It will also
/// assert out if the two APInt's are not the same bit width.
- ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
+ ConstantRange(APInt Lower, APInt Upper);
/// Produce the smallest range such that all values that may satisfy the given
/// predicate with any value contained within Other is contained in the
@@ -184,6 +181,10 @@ public:
///
APInt getSetSize() const;
+ /// Compare set size of this range with the range CR.
+ ///
+ bool isSizeStrictlySmallerThanOf(const ConstantRange &CR) const;
+
/// Return the largest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMax() const;
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index cbefa3f05dfc..ad83b21c7bf3 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -138,7 +138,7 @@ public:
static Constant *get(Type* Ty, const APInt& V);
/// Return the constant as an APInt value reference. This allows clients to
- /// obtain a copy of the value, with all its precision in tact.
+ /// obtain a full-precision copy of the value.
/// @brief Return the constant's value.
inline const APInt &getValue() const {
return Val;
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index 48cb7fe5df6f..69bd5c847a8d 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -105,13 +105,17 @@ namespace llvm {
/// out into.
/// \param Kind The kind of debug information to generate.
/// \param DWOId The DWOId if this is a split skeleton compile unit.
+ /// \param SplitDebugInlining Whether to emit inline debug info.
+ /// \param DebugInfoForProfiling Whether to emit extra debug info for
+ /// profile collection.
DICompileUnit *
createCompileUnit(unsigned Lang, DIFile *File, StringRef Producer,
bool isOptimized, StringRef Flags, unsigned RV,
StringRef SplitName = StringRef(),
DICompileUnit::DebugEmissionKind Kind =
DICompileUnit::DebugEmissionKind::FullDebug,
- uint64_t DWOId = 0, bool SplitDebugInlining = true);
+ uint64_t DWOId = 0, bool SplitDebugInlining = true,
+ bool DebugInfoForProfiling = false);
/// Create a file descriptor to hold debugging information for a file.
/// \param Filename File name.
@@ -164,12 +168,15 @@ namespace llvm {
DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy);
/// Create debugging information entry for a pointer.
- /// \param PointeeTy Type pointed by this pointer.
- /// \param SizeInBits Size.
- /// \param AlignInBits Alignment. (optional)
- /// \param Name Pointer type name. (optional)
+ /// \param PointeeTy Type pointed by this pointer.
+ /// \param SizeInBits Size.
+ /// \param AlignInBits Alignment. (optional)
+ /// \param DWARFAddressSpace DWARF address space. (optional)
+ /// \param Name Pointer type name. (optional)
DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
uint32_t AlignInBits = 0,
+ Optional<unsigned> DWARFAddressSpace =
+ None,
StringRef Name = "");
/// Create debugging information entry for a pointer to member.
@@ -186,7 +193,9 @@ namespace llvm {
/// style reference or rvalue reference type.
DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy,
uint64_t SizeInBits = 0,
- uint32_t AlignInBits = 0);
+ uint32_t AlignInBits = 0,
+ Optional<unsigned> DWARFAddressSpace =
+ None);
/// Create debugging information entry for a typedef.
/// \param Ty Original type.
@@ -431,13 +440,6 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
unsigned CC = 0);
- /// Create an external type reference.
- /// \param Tag Dwarf TAG.
- /// \param File File in which the type is defined.
- /// \param UniqueIdentifier A unique identifier for the type.
- DICompositeType *createExternalTypeRef(unsigned Tag, DIFile *File,
- StringRef UniqueIdentifier);
-
/// Create a new DIType* with "artificial" flag set.
DIType *createArtificialType(DIType *Ty);
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index 6f37669f9768..1930d48577d4 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -104,6 +104,7 @@ private:
/// Defaults to false.
bool BigEndian;
+ unsigned AllocaAddrSpace;
unsigned StackNaturalAlign;
enum ManglingModeT {
@@ -118,8 +119,19 @@ private:
SmallVector<unsigned char, 8> LegalIntWidths;
- /// \brief Primitive type alignment data.
- SmallVector<LayoutAlignElem, 16> Alignments;
+ /// \brief Primitive type alignment data. This is sorted by type and bit
+ /// width during construction.
+ typedef SmallVector<LayoutAlignElem, 16> AlignmentsTy;
+ AlignmentsTy Alignments;
+
+ AlignmentsTy::const_iterator
+ findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth) const {
+ return const_cast<DataLayout *>(this)->findAlignmentLowerBound(AlignType,
+ BitWidth);
+ }
+
+ AlignmentsTy::iterator
+ findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth);
/// \brief The string representation used to create this DataLayout
std::string StringRepresentation;
@@ -134,14 +146,6 @@ private:
PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace);
- /// This member is a signal that a requested alignment type and bit width were
- /// not found in the SmallVector.
- static const LayoutAlignElem InvalidAlignmentElem;
-
- /// This member is a signal that a requested pointer type and bit width were
- /// not found in the DenseSet.
- static const PointerAlignElem InvalidPointerElem;
-
// The StructType -> StructLayout map.
mutable void *LayoutMap;
@@ -159,22 +163,6 @@ private:
/// Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
- /// \brief Valid alignment predicate.
- ///
- /// Predicate that tests a LayoutAlignElem reference returned by get() against
- /// InvalidAlignmentElem.
- bool validAlignment(const LayoutAlignElem &align) const {
- return &align != &InvalidAlignmentElem;
- }
-
- /// \brief Valid pointer predicate.
- ///
- /// Predicate that tests a PointerAlignElem reference returned by get()
- /// against \c InvalidPointerElem.
- bool validPointer(const PointerAlignElem &align) const {
- return &align != &InvalidPointerElem;
- }
-
/// Parses a target data specification string. Assert if the string is
/// malformed.
void parseSpecifier(StringRef LayoutDescription);
@@ -199,6 +187,7 @@ public:
clear();
StringRepresentation = DL.StringRepresentation;
BigEndian = DL.isBigEndian();
+ AllocaAddrSpace = DL.AllocaAddrSpace;
StackNaturalAlign = DL.StackNaturalAlign;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
@@ -254,6 +243,7 @@ public:
}
unsigned getStackAlignment() const { return StackNaturalAlign; }
+ unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; }
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WinCOFFX86;
diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def
index 87f3dc9dbdd3..7ea6346998fe 100644
--- a/include/llvm/IR/DebugInfoFlags.def
+++ b/include/llvm/IR/DebugInfoFlags.def
@@ -34,7 +34,8 @@ HANDLE_DI_FLAG((1 << 11), Vector)
HANDLE_DI_FLAG((1 << 12), StaticMember)
HANDLE_DI_FLAG((1 << 13), LValueReference)
HANDLE_DI_FLAG((1 << 14), RValueReference)
-HANDLE_DI_FLAG((1 << 15), ExternalTypeRef)
+// 15 was formerly ExternalTypeRef, but this was never used.
+HANDLE_DI_FLAG((1 << 15), Reserved)
HANDLE_DI_FLAG((1 << 16), SingleInheritance)
HANDLE_DI_FLAG((2 << 16), MultipleInheritance)
HANDLE_DI_FLAG((3 << 16), VirtualInheritance)
diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h
index 187855225c50..8a924b40143a 100644
--- a/include/llvm/IR/DebugInfoMetadata.h
+++ b/include/llvm/IR/DebugInfoMetadata.h
@@ -629,7 +629,6 @@ public:
bool isStaticMember() const { return getFlags() & FlagStaticMember; }
bool isLValueReference() const { return getFlags() & FlagLValueReference; }
bool isRValueReference() const { return getFlags() & FlagRValueReference; }
- bool isExternalTypeRef() const { return getFlags() & FlagExternalTypeRef; }
static bool classof(const Metadata *MD) {
switch (MD->getMetadataID()) {
@@ -710,37 +709,45 @@ class DIDerivedType : public DIType {
friend class LLVMContextImpl;
friend class MDNode;
+ /// \brief The DWARF address space of the memory pointed to or referenced by a
+ /// pointer or reference type respectively.
+ Optional<unsigned> DWARFAddressSpace;
+
DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops)
+ uint64_t OffsetInBits, Optional<unsigned> DWARFAddressSpace,
+ DIFlags Flags, ArrayRef<Metadata *> Ops)
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
- AlignInBits, OffsetInBits, Flags, Ops) {}
+ AlignInBits, OffsetInBits, Flags, Ops),
+ DWARFAddressSpace(DWARFAddressSpace) {}
~DIDerivedType() = default;
static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, DIFile *File, unsigned Line,
DIScopeRef Scope, DITypeRef BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
- Metadata *ExtraData, StorageType Storage,
- bool ShouldCreate = true) {
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace,
+ DIFlags Flags, Metadata *ExtraData,
+ StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
- Flags, ExtraData, Storage, ShouldCreate);
+ DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate);
}
static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line,
Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
- Metadata *ExtraData, StorageType Storage,
- bool ShouldCreate = true);
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace,
+ DIFlags Flags, Metadata *ExtraData,
+ StorageType Storage, bool ShouldCreate = true);
TempDIDerivedType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(),
getScope(), getBaseType(), getSizeInBits(),
- getAlignInBits(), getOffsetInBits(), getFlags(),
- getExtraData());
+ getAlignInBits(), getOffsetInBits(),
+ getDWARFAddressSpace(), getFlags(), getExtraData());
}
public:
@@ -748,24 +755,32 @@ public:
(unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, DIFlags Flags,
+ uint64_t OffsetInBits,
+ Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
Metadata *ExtraData = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, ExtraData))
+ AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
+ ExtraData))
DEFINE_MDNODE_GET(DIDerivedType,
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits,
- DIFlags Flags, Metadata *ExtraData = nullptr),
+ Optional<unsigned> DWARFAddressSpace, DIFlags Flags,
+ Metadata *ExtraData = nullptr),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, ExtraData))
+ AlignInBits, OffsetInBits, DWARFAddressSpace, Flags,
+ ExtraData))
TempDIDerivedType clone() const { return cloneImpl(); }
- //// Get the base type this is derived from.
+ /// Get the base type this is derived from.
DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); }
Metadata *getRawBaseType() const { return getOperand(3); }
+ /// \returns The DWARF address space of the memory pointed to or referenced by
+ /// a pointer or reference type respectively.
+ Optional<unsigned> getDWARFAddressSpace() const { return DWARFAddressSpace; }
+
/// Get extra data associated with this derived type.
///
/// Class type for pointer-to-members, objective-c property node for ivars,
@@ -1044,15 +1059,17 @@ private:
unsigned EmissionKind;
uint64_t DWOId;
bool SplitDebugInlining;
+ bool DebugInfoForProfiling;
DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage,
bool IsOptimized, unsigned RuntimeVersion,
unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining,
- ArrayRef<Metadata *> Ops)
+ bool DebugInfoForProfiling, ArrayRef<Metadata *> Ops)
: DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind),
- DWOId(DWOId), SplitDebugInlining(SplitDebugInlining) {
+ DWOId(DWOId), SplitDebugInlining(SplitDebugInlining),
+ DebugInfoForProfiling(DebugInfoForProfiling) {
assert(Storage != Uniqued);
}
~DICompileUnit() = default;
@@ -1065,15 +1082,16 @@ private:
DIScopeArray RetainedTypes,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
- uint64_t DWOId, bool SplitDebugInlining, StorageType Storage,
- bool ShouldCreate = true) {
+ uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,
+ StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, SourceLanguage, File,
getCanonicalMDString(Context, Producer), IsOptimized,
getCanonicalMDString(Context, Flags), RuntimeVersion,
getCanonicalMDString(Context, SplitDebugFilename),
EmissionKind, EnumTypes.get(), RetainedTypes.get(),
GlobalVariables.get(), ImportedEntities.get(), Macros.get(),
- DWOId, SplitDebugInlining, Storage, ShouldCreate);
+ DWOId, SplitDebugInlining, DebugInfoForProfiling, Storage,
+ ShouldCreate);
}
static DICompileUnit *
getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File,
@@ -1082,7 +1100,8 @@ private:
unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,
Metadata *GlobalVariables, Metadata *ImportedEntities,
Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining,
- StorageType Storage, bool ShouldCreate = true);
+ bool DebugInfoForProfiling, StorageType Storage,
+ bool ShouldCreate = true);
TempDICompileUnit cloneImpl() const {
return getTemporary(getContext(), getSourceLanguage(), getFile(),
@@ -1090,7 +1109,8 @@ private:
getRuntimeVersion(), getSplitDebugFilename(),
getEmissionKind(), getEnumTypes(), getRetainedTypes(),
getGlobalVariables(), getImportedEntities(),
- getMacros(), DWOId, getSplitDebugInlining());
+ getMacros(), DWOId, getSplitDebugInlining(),
+ getDebugInfoForProfiling());
}
public:
@@ -1105,10 +1125,11 @@ public:
DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,
DIGlobalVariableExpressionArray GlobalVariables,
DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,
- uint64_t DWOId, bool SplitDebugInlining),
+ uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
- GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining))
+ GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,
+ DebugInfoForProfiling))
DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(
DICompileUnit,
(unsigned SourceLanguage, Metadata *File, MDString *Producer,
@@ -1116,10 +1137,11 @@ public:
MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,
Metadata *RetainedTypes, Metadata *GlobalVariables,
Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,
- bool SplitDebugInlining),
+ bool SplitDebugInlining, bool DebugInfoForProfiling),
(SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,
SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,
- GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining))
+ GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,
+ DebugInfoForProfiling))
TempDICompileUnit clone() const { return cloneImpl(); }
@@ -1129,6 +1151,7 @@ public:
DebugEmissionKind getEmissionKind() const {
return (DebugEmissionKind)EmissionKind;
}
+ bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; }
StringRef getProducer() const { return getStringOperand(1); }
StringRef getFlags() const { return getStringOperand(2); }
StringRef getSplitDebugFilename() const { return getStringOperand(3); }
@@ -1246,6 +1269,28 @@ class DILocation : public MDNode {
static_cast<Metadata *>(InlinedAt), Storage, ShouldCreate);
}
+ /// With a given unsigned int \p U, use up to 13 bits to represent it.
+ /// old_bit 1~5 --> new_bit 1~5
+ /// old_bit 6~12 --> new_bit 7~13
+ /// new_bit_6 is 0 if higher bits (7~13) are all 0
+ static unsigned getPrefixEncodingFromUnsigned(unsigned U) {
+ U &= 0xfff;
+ return U > 0x1f ? (((U & 0xfe0) << 1) | (U & 0x1f) | 0x20) : U;
+ }
+
+ /// Reverse transformation as getPrefixEncodingFromUnsigned.
+ static unsigned getUnsignedFromPrefixEncoding(unsigned U) {
+ return (U & 0x20) ? (((U >> 1) & 0xfe0) | (U & 0x1f)) : (U & 0x1f);
+ }
+
+ /// Returns the next component stored in discriminator.
+ static unsigned getNextComponentInDiscriminator(unsigned D) {
+ if ((D & 1) == 0)
+ return D >> ((D & 0x40) ? 14 : 7);
+ else
+ return D >> 1;
+ }
+
TempDILocation cloneImpl() const {
// Get the raw scope/inlinedAt since it is possible to invoke this on
// a DILocation containing temporary metadata.
@@ -1307,10 +1352,48 @@ public:
///
/// DWARF discriminators distinguish identical file locations between
/// instructions that are on different basic blocks.
+ ///
+ /// There are 3 components stored in discriminator, from lower bits:
+ ///
+ /// Base discriminator: assigned by AddDiscriminators pass to identify IRs
+ /// that are defined by the same source line, but
+ /// different basic blocks.
+ /// Duplication factor: assigned by optimizations that will scale down
+ /// the execution frequency of the original IR.
+ /// Copy Identifier: assigned by optimizations that clones the IR.
+ /// Each copy of the IR will be assigned an identifier.
+ ///
+ /// Encoding:
+ ///
+ /// The above 3 components are encoded into a 32bit unsigned integer in
+ /// order. If the lowest bit is 1, the current component is empty, and the
+ /// next component will start in the next bit. Otherwise, the the current
+ /// component is non-empty, and its content starts in the next bit. The
+ /// length of each components is either 5 bit or 12 bit: if the 7th bit
+ /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the
+ /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to
+ /// represent the component.
+
inline unsigned getDiscriminator() const;
/// Returns a new DILocation with updated \p Discriminator.
- inline DILocation *cloneWithDiscriminator(unsigned Discriminator) const;
+ inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const;
+
+ /// Returns a new DILocation with updated base discriminator \p BD.
+ inline const DILocation *setBaseDiscriminator(unsigned BD) const;
+
+ /// Returns the duplication factor stored in the discriminator.
+ inline unsigned getDuplicationFactor() const;
+
+ /// Returns the copy identifier stored in the discriminator.
+ inline unsigned getCopyIdentifier() const;
+
+ /// Returns the base discriminator stored in the discriminator.
+ inline unsigned getBaseDiscriminator() const;
+
+ /// Returns a new DILocation with duplication factor \p DF encoded in the
+ /// discriminator.
+ inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const;
/// When two instructions are combined into a single instruction we also
/// need to combine the original locations into a single location.
@@ -1333,6 +1416,30 @@ public:
return nullptr;
}
+ /// Returns the base discriminator for a given encoded discriminator \p D.
+ static unsigned getBaseDiscriminatorFromDiscriminator(unsigned D) {
+ if ((D & 1) == 0)
+ return getUnsignedFromPrefixEncoding(D >> 1);
+ else
+ return 0;
+ }
+
+ /// Returns the duplication factor for a given encoded discriminator \p D.
+ static unsigned getDuplicationFactorFromDiscriminator(unsigned D) {
+ D = getNextComponentInDiscriminator(D);
+ if (D == 0 || (D & 1))
+ return 1;
+ else
+ return getUnsignedFromPrefixEncoding(D >> 1);
+ }
+
+ /// Returns the copy identifier for a given encoded discriminator \p D.
+ static unsigned getCopyIdentifierFromDiscriminator(unsigned D) {
+ return getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator(
+ getNextComponentInDiscriminator(D)));
+ }
+
+
Metadata *getRawScope() const { return getOperand(0); }
Metadata *getRawInlinedAt() const {
if (getNumOperands() == 2)
@@ -1343,6 +1450,7 @@ public:
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DILocationKind;
}
+
};
/// Subprogram description.
@@ -1676,7 +1784,8 @@ unsigned DILocation::getDiscriminator() const {
return 0;
}
-DILocation *DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
+const DILocation *
+DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
DIScope *Scope = getScope();
// Skip all parent DILexicalBlockFile that already have a discriminator
// assigned. We do not want to have nested DILexicalBlockFiles that have
@@ -1692,6 +1801,42 @@ DILocation *DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
getInlinedAt());
}
+unsigned DILocation::getBaseDiscriminator() const {
+ return getBaseDiscriminatorFromDiscriminator(getDiscriminator());
+}
+
+unsigned DILocation::getDuplicationFactor() const {
+ return getDuplicationFactorFromDiscriminator(getDiscriminator());
+}
+
+unsigned DILocation::getCopyIdentifier() const {
+ return getCopyIdentifierFromDiscriminator(getDiscriminator());
+}
+
+const DILocation *DILocation::setBaseDiscriminator(unsigned D) const {
+ if (D == 0)
+ return this;
+ else
+ return cloneWithDiscriminator(getPrefixEncodingFromUnsigned(D) << 1);
+}
+
+const DILocation *DILocation::cloneWithDuplicationFactor(unsigned DF) const {
+ DF *= getDuplicationFactor();
+ if (DF <= 1)
+ return this;
+
+ unsigned BD = getBaseDiscriminator();
+ unsigned CI = getCopyIdentifier() << (DF > 0x1f ? 14 : 7);
+ unsigned D = CI | (getPrefixEncodingFromUnsigned(DF) << 1);
+
+ if (BD == 0)
+ D = (D << 1) | 1;
+ else
+ D = (D << (BD > 0x1f ? 14 : 7)) | (getPrefixEncodingFromUnsigned(BD) << 1);
+
+ return cloneWithDiscriminator(D);
+}
+
class DINamespace : public DIScope {
friend class LLVMContextImpl;
friend class MDNode;
@@ -1918,7 +2063,7 @@ protected:
DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line,
ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0)
: DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line),
- AlignInBits(AlignInBits) {}
+ AlignInBits(AlignInBits) {}
~DIVariable() = default;
public:
@@ -2108,7 +2253,7 @@ public:
/// Retrieve the details of this fragment expression.
static Optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start,
- expr_op_iterator End);
+ expr_op_iterator End);
/// Retrieve the details of this fragment expression.
Optional<FragmentInfo> getFragmentInfo() const {
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index a93c180df1b5..458c3cf29b0d 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -69,6 +69,11 @@ enum DiagnosticKind {
DK_OptimizationFailure,
DK_FirstRemark = DK_OptimizationRemark,
DK_LastRemark = DK_OptimizationFailure,
+ DK_MachineOptimizationRemark,
+ DK_MachineOptimizationRemarkMissed,
+ DK_MachineOptimizationRemarkAnalysis,
+ DK_FirstMachineRemark = DK_MachineOptimizationRemark,
+ DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
DK_MIRParser,
DK_PGOProfile,
DK_Unsupported,
@@ -342,19 +347,34 @@ private:
const Twine &Msg;
};
-/// Common features for diagnostics with an associated DebugLoc
-class DiagnosticInfoWithDebugLocBase : public DiagnosticInfo {
+class DiagnosticLocation {
+ StringRef Filename;
+ unsigned Line = 0;
+ unsigned Column = 0;
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ DiagnosticLocation() {}
+ DiagnosticLocation(const DebugLoc &DL);
+ DiagnosticLocation(const DISubprogram *SP);
+
+ bool isValid() const { return !Filename.empty(); }
+ StringRef getFilename() const { return Filename; }
+ unsigned getLine() const { return Line; }
+ unsigned getColumn() const { return Column; }
+};
+
+/// Common features for diagnostics with an associated location.
+class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
+public:
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic.
- DiagnosticInfoWithDebugLocBase(enum DiagnosticKind Kind,
+ DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
enum DiagnosticSeverity Severity,
const Function &Fn,
- const DebugLoc &DLoc)
- : DiagnosticInfo(Kind, Severity), Fn(Fn), DLoc(DLoc) {}
+ const DiagnosticLocation &Loc)
+ : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
/// Return true if location information is available for this diagnostic.
- bool isLocationAvailable() const;
+ bool isLocationAvailable() const { return Loc.isValid(); }
/// Return a string with the location information for this diagnostic
/// in the format "file:line:col". If location information is not available,
@@ -366,18 +386,19 @@ public:
void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const;
const Function &getFunction() const { return Fn; }
- const DebugLoc &getDebugLoc() const { return DLoc; }
+ DiagnosticLocation getLocation() const { return Loc; }
private:
/// Function where this diagnostic is triggered.
const Function &Fn;
/// Debug location where this diagnostic is triggered.
- DebugLoc DLoc;
+ DiagnosticLocation Loc;
};
-/// Common features for diagnostics dealing with optimization remarks.
-class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithDebugLocBase {
+/// \brief Common features for diagnostics dealing with optimization remarks
+/// that are used by both IR and MIR passes.
+class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
public:
/// \brief Used to set IsVerbose via the stream interface.
struct setIsVerbose {};
@@ -394,66 +415,29 @@ public:
StringRef Key;
std::string Val;
// If set, the debug location corresponding to the value.
- DebugLoc DLoc;
+ DiagnosticLocation Loc;
explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
- Argument(StringRef Key, Value *V);
- Argument(StringRef Key, Type *T);
+ Argument(StringRef Key, const Value *V);
+ Argument(StringRef Key, const Type *T);
Argument(StringRef Key, int N);
Argument(StringRef Key, unsigned N);
Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
};
/// \p PassName is the name of the pass emitting this diagnostic. \p
- /// RemarkName is a textual identifier for the remark. \p Fn is the function
- /// where the diagnostic is being emitted. \p DLoc is the location information
- /// to use in the diagnostic. If line table information is available, the
- /// diagnostic will include the source code location. \p CodeRegion is IR
- /// value (currently basic block) that the optimization operates on. This is
- /// currently used to provide run-time hotness information with PGO.
- DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
- enum DiagnosticSeverity Severity,
- const char *PassName, StringRef RemarkName,
- const Function &Fn, const DebugLoc &DLoc,
- Value *CodeRegion = nullptr)
- : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
- PassName(PassName), RemarkName(RemarkName), CodeRegion(CodeRegion) {}
-
- /// \brief This is ctor variant allows a pass to build an optimization remark
- /// from an existing remark.
- ///
- /// This is useful when a transformation pass (e.g LV) wants to emit a remark
- /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
- /// remark. The string \p Prepend will be emitted before the original
- /// message.
- DiagnosticInfoOptimizationBase(const char *PassName, StringRef Prepend,
- const DiagnosticInfoOptimizationBase &Orig)
- : DiagnosticInfoWithDebugLocBase((DiagnosticKind)Orig.getKind(),
- Orig.getSeverity(), Orig.getFunction(),
- Orig.getDebugLoc()),
- PassName(PassName), RemarkName(Orig.RemarkName),
- CodeRegion(Orig.getCodeRegion()) {
- *this << Prepend;
- std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
- }
-
- /// Legacy interface.
- /// \p PassName is the name of the pass emitting this diagnostic.
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
- /// the location information to use in the diagnostic. If line table
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Fn is the function where the diagnostic is being emitted.
+ /// \p Loc is the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
- /// location. \p Msg is the message to show. Note that this class does not
- /// copy this message, so this reference must be valid for the whole life time
- /// of the diagnostic.
+ /// location.
DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
enum DiagnosticSeverity Severity,
- const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoWithDebugLocBase(Kind, Severity, Fn, DLoc),
- PassName(PassName), Hotness(Hotness) {
- Args.push_back(Argument(Msg.str()));
- }
+ const char *PassName, StringRef RemarkName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc)
+ : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
+ PassName(PassName), RemarkName(RemarkName) {}
DiagnosticInfoOptimizationBase &operator<<(StringRef S);
DiagnosticInfoOptimizationBase &operator<<(Argument A);
@@ -475,33 +459,45 @@ public:
Optional<uint64_t> getHotness() const { return Hotness; }
void setHotness(Optional<uint64_t> H) { Hotness = H; }
- Value *getCodeRegion() const { return CodeRegion; }
-
bool isVerbose() const { return IsVerbose; }
static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() >= DK_FirstRemark &&
- DI->getKind() <= DK_LastRemark;
+ return (DI->getKind() >= DK_FirstRemark &&
+ DI->getKind() <= DK_LastRemark) ||
+ (DI->getKind() >= DK_FirstMachineRemark &&
+ DI->getKind() <= DK_LastMachineRemark);
}
-private:
+ bool isPassed() const {
+ return (getKind() == DK_OptimizationRemark ||
+ getKind() == DK_MachineOptimizationRemark);
+ }
+
+ bool isMissed() const {
+ return (getKind() == DK_OptimizationRemarkMissed ||
+ getKind() == DK_MachineOptimizationRemarkMissed);
+ }
+
+ bool isAnalysis() const {
+ return (getKind() == DK_OptimizationRemarkAnalysis ||
+ getKind() == DK_MachineOptimizationRemarkAnalysis);
+ }
+
+protected:
/// Name of the pass that triggers this report. If this matches the
/// regular expression given in -Rpass=regexp, then the remark will
/// be emitted.
const char *PassName;
- /// Textual identifier for the remark. Can be used by external tools reading
- /// the YAML output file for optimization remarks to identify the remark.
+ /// Textual identifier for the remark (single-word, camel-case). Can be used
+ /// by external tools reading the YAML output file for optimization remarks to
+ /// identify the remark.
StringRef RemarkName;
/// If profile information is available, this is the number of times the
/// corresponding code was executed in a profile instrumentation run.
Optional<uint64_t> Hotness;
- /// The IR value (currently basic block) that the optimization operates on.
- /// This is currently used to provide run-time hotness information with PGO.
- Value *CodeRegion;
-
/// Arguments collected via the streaming interface.
SmallVector<Argument, 4> Args;
@@ -516,106 +512,186 @@ private:
friend struct yaml::MappingTraits<DiagnosticInfoOptimizationBase *>;
};
-/// Diagnostic information for applied optimization remarks.
-class OptimizationRemark : public DiagnosticInfoOptimizationBase {
+/// \brief Common features for diagnostics dealing with optimization remarks
+/// that are used by IR passes.
+class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
public:
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass=, then the
- /// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic
- /// will include the source code location. \p Msg is the message to show.
- /// Note that this class does not copy this message, so this reference
- /// must be valid for the whole life time of the diagnostic.
- OptimizationRemark(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemark, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ /// \p PassName is the name of the pass emitting this diagnostic. \p
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Fn is the function where the diagnostic is being emitted.
+ /// \p Loc is the location information to use in the diagnostic. If line table
+ /// information is available, the diagnostic will include the source code
+ /// location. \p CodeRegion is IR value (currently basic block) that the
+ /// optimization operates on. This is currently used to provide run-time
+ /// hotness information with PGO.
+ DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
+ enum DiagnosticSeverity Severity,
+ const char *PassName, StringRef RemarkName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion = nullptr)
+ : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
+ Loc),
+ CodeRegion(CodeRegion) {}
+ /// \brief This is ctor variant allows a pass to build an optimization remark
+ /// from an existing remark.
+ ///
+ /// This is useful when a transformation pass (e.g LV) wants to emit a remark
+ /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
+ /// remark. The string \p Prepend will be emitted before the original
+ /// message.
+ DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
+ const DiagnosticInfoIROptimization &Orig)
+ : DiagnosticInfoOptimizationBase(
+ (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
+ Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
+ CodeRegion(Orig.getCodeRegion()) {
+ *this << Prepend;
+ std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
+ }
+
+ /// Legacy interface.
+ /// \p PassName is the name of the pass emitting this diagnostic.
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
+ /// the location information to use in the diagnostic. If line table
+ /// information is available, the diagnostic will include the source code
+ /// location. \p Msg is the message to show. Note that this class does not
+ /// copy this message, so this reference must be valid for the whole life time
+ /// of the diagnostic.
+ DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
+ enum DiagnosticSeverity Severity,
+ const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
+ *this << Msg.str();
+ }
+
+ const Value *getCodeRegion() const { return CodeRegion; }
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
+ }
+
+private:
+ /// The IR value (currently basic block) that the optimization operates on.
+ /// This is currently used to provide run-time hotness information with PGO.
+ const Value *CodeRegion;
+};
+
+/// Diagnostic information for applied optimization remarks.
+class OptimizationRemark : public DiagnosticInfoIROptimization {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass=, then the diagnostic will
- /// be emitted. \p RemarkName is a textual identifier for the remark. \p
- /// DLoc is the debug location and \p CodeRegion is the region that the
- /// optimization operates on (currently on block is supported).
+ /// be emitted. \p RemarkName is a textual identifier for the remark (single-
+ /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
+ /// region that the optimization operates on (currently only block is
+ /// supported).
OptimizationRemark(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc, const Value *CodeRegion);
- /// Same as above but the debug location and code region is derived from \p
+ /// Same as above, but the debug location and code region are derived from \p
/// Instr.
OptimizationRemark(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
+
+ /// Same as above, but the debug location and code region are derived from \p
+ /// Func.
+ OptimizationRemark(const char *PassName, StringRef RemarkName,
+ const Function *Func);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemark;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
-};
+ bool isEnabled() const override { return isEnabled(getPassName()); }
-/// Diagnostic information for missed-optimization remarks.
-class OptimizationRemarkMissed : public DiagnosticInfoOptimizationBase {
-public:
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-missed=, then the
+ /// this name matches the regular expression given in -Rpass=, then the
/// diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic
/// will include the source code location. \p Msg is the message to show.
/// Note that this class does not copy this message, so this reference
/// must be valid for the whole life time of the diagnostic.
- OptimizationRemarkMissed(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ OptimizationRemark(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
+ Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
+};
+/// Diagnostic information for missed-optimization remarks.
+class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-missed=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported).
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported).
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
/// \brief Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkMissed;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
+ bool isEnabled() const override { return isEnabled(getPassName()); }
+
+private:
+ /// This is deprecated now and only used by the function API below.
+ /// \p PassName is the name of the pass emitting this diagnostic. If
+ /// this name matches the regular expression given in -Rpass-missed=, then the
+ /// diagnostic will be emitted. \p Fn is the function where the diagnostic
+ /// is being emitted. \p Loc is the location information to use in the
+ /// diagnostic. If line table information is available, the diagnostic
+ /// will include the source code location. \p Msg is the message to show.
+ /// Note that this class does not copy this message, so this reference
+ /// must be valid for the whole life time of the diagnostic.
+ OptimizationRemarkMissed(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
+ PassName, Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemarkMissed(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
};
/// Diagnostic information for optimization analysis remarks.
-class OptimizationRemarkAnalysis : public DiagnosticInfoOptimizationBase {
+class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
public:
- /// \p PassName is the name of the pass emitting this diagnostic. If
- /// this name matches the regular expression given in -Rpass-analysis=, then
- /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
- /// diagnostic. If line table information is available, the diagnostic will
- /// include the source code location. \p Msg is the message to show. Note that
- /// this class does not copy this message, so this reference must be valid for
- /// the whole life time of the diagnostic.
- OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark,
- PassName, Fn, DLoc, Msg, Hotness) {}
-
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported).
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported).
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion);
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
/// \brief This is ctor variant allows a pass to build an optimization remark
/// from an existing remark.
@@ -626,19 +702,23 @@ public:
/// message.
OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
const OptimizationRemarkAnalysis &Orig)
- : DiagnosticInfoOptimizationBase(PassName, Prepend, Orig) {}
+ : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
/// \brief Same as above but \p Inst is used to derive code region and debug
/// location.
OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
- Instruction *Inst);
+ const Instruction *Inst);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationRemarkAnalysis;
}
+ static bool isEnabled(StringRef PassName);
+
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- bool isEnabled() const override;
+ bool isEnabled() const override {
+ return shouldAlwaysPrint() || isEnabled(getPassName());
+ }
static const char *AlwaysPrint;
@@ -646,24 +726,65 @@ public:
protected:
OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
- const Twine &Msg, Optional<uint64_t> Hotness)
- : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, Fn, DLoc, Msg,
- Hotness) {}
+ const Function &Fn, const DiagnosticLocation &Loc,
+ const Twine &Msg)
+ : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
- StringRef RemarkName, const DebugLoc &DLoc,
- Value *CodeRegion);
+ StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
+
+private:
+ /// This is deprecated now and only used by the function API below.
+ /// \p PassName is the name of the pass emitting this diagnostic. If
+ /// this name matches the regular expression given in -Rpass-analysis=, then
+ /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
+ /// is being emitted. \p Loc is the location information to use in the
+ /// diagnostic. If line table information is available, the diagnostic will
+ /// include the source code location. \p Msg is the message to show. Note that
+ /// this class does not copy this message, so this reference must be valid for
+ /// the whole life time of the diagnostic.
+ OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg)
+ : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
+ PassName, Fn, Loc, Msg) {}
+
+ friend void emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
+ const char *PassName,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
+ const Twine &Msg);
};
/// Diagnostic information for optimization analysis remarks related to
/// floating-point non-commutativity.
class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
public:
+ /// \p PassName is the name of the pass emitting this diagnostic. If this name
+ /// matches the regular expression given in -Rpass-analysis=, then the
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported). The front-end will append its own message related to
+ /// options that address floating-point non-commutativity.
+ OptimizationRemarkAnalysisFPCommute(const char *PassName,
+ StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion)
+ : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
+ PassName, RemarkName, Loc, CodeRegion) {}
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
+ }
+
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-analysis=, then
/// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic will
/// include the source code location. \p Msg is the message to show. The
/// front-end will append its own message related to options that address
@@ -671,37 +792,42 @@ public:
/// message, so this reference must be valid for the whole life time of the
/// diagnostic.
OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
+ const DiagnosticLocation &Loc,
+ const Twine &Msg)
: OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, Fn, DLoc, Msg, Hotness) {}
+ PassName, Fn, Loc, Msg) {}
+ friend void emitOptimizationRemarkAnalysisFPCommute(
+ LLVMContext &Ctx, const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg);
+};
+/// Diagnostic information for optimization analysis remarks related to
+/// pointer aliasing.
+class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
+public:
/// \p PassName is the name of the pass emitting this diagnostic. If this name
/// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported). The
- /// front-end will append its own message related to options that address
- /// floating-point non-commutativity.
- OptimizationRemarkAnalysisFPCommute(const char *PassName,
- StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
- PassName, RemarkName, DLoc, CodeRegion) {}
+ /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
+ /// remark (single-word, camel-case). \p Loc is the debug location and \p
+ /// CodeRegion is the region that the optimization operates on (currently only
+ /// block is supported). The front-end will append its own message related to
+ /// options that address pointer aliasing legality.
+ OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion)
+ : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
+ PassName, RemarkName, Loc, CodeRegion) {}
static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
+ return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
}
-};
-/// Diagnostic information for optimization analysis remarks related to
-/// pointer aliasing.
-class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
-public:
+private:
+ /// This is deprecated now and only used by the function API below.
/// \p PassName is the name of the pass emitting this diagnostic. If
/// this name matches the regular expression given in -Rpass-analysis=, then
/// the diagnostic will be emitted. \p Fn is the function where the diagnostic
- /// is being emitted. \p DLoc is the location information to use in the
+ /// is being emitted. \p Loc is the location information to use in the
/// diagnostic. If line table information is available, the diagnostic will
/// include the source code location. \p Msg is the message to show. The
/// front-end will append its own message related to options that address
@@ -709,26 +835,14 @@ public:
/// message, so this reference must be valid for the whole life time of the
/// diagnostic.
OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg,
- Optional<uint64_t> Hotness = None)
- : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, Fn, DLoc, Msg, Hotness) {}
-
- /// \p PassName is the name of the pass emitting this diagnostic. If this name
- /// matches the regular expression given in -Rpass-analysis=, then the
- /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
- /// remark. \p DLoc is the debug location and \p CodeRegion is the region
- /// that the optimization operates on (currently on block is supported). The
- /// front-end will append its own message related to options that address
- /// pointer aliasing legality.
- OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
- const DebugLoc &DLoc, Value *CodeRegion)
+ const DiagnosticLocation &Loc,
+ const Twine &Msg)
: OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
- PassName, RemarkName, DLoc, CodeRegion) {}
+ PassName, Fn, Loc, Msg) {}
- static bool classof(const DiagnosticInfo *DI) {
- return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
- }
+ friend void emitOptimizationRemarkAnalysisAliasing(
+ LLVMContext &Ctx, const char *PassName, const Function &Fn,
+ const DiagnosticLocation &Loc, const Twine &Msg);
};
/// Diagnostic information for machine IR parser.
@@ -771,73 +885,97 @@ public:
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
-/// Emit an optimization-applied message. \p PassName is the name of the pass
-/// emitting the message. If -Rpass= is given and \p PassName matches the
-/// regular expression in -Rpass, then the remark will be emitted. \p Fn is
-/// the function triggering the remark, \p DLoc is the debug location where
-/// the diagnostic is generated. \p Msg is the message string to use.
+/// \brief Legacy interface to emit an optimization-applied message. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If -Rpass= is
+/// given and \p PassName matches the regular expression in -Rpass, then the
+/// remark will be emitted. \p Fn is the function triggering the remark, \p Loc
+/// is the debug location where the diagnostic is generated. \p Msg is the
+/// message string to use.
void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn, const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization-missed message. \p PassName is the name of the
-/// pass emitting the message. If -Rpass-missed= is given and \p PassName
-/// matches the regular expression in -Rpass, then the remark will be
-/// emitted. \p Fn is the function triggering the remark, \p DLoc is the
-/// debug location where the diagnostic is generated. \p Msg is the
+/// \brief Legacy interface to emit an optimization-missed message. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If -Rpass-missed=
+/// is given and \p PassName matches the regular expression in -Rpass, then the
+/// remark will be emitted. \p Fn is the function triggering the remark, \p Loc
+/// is the debug location where the diagnostic is generated. \p Msg is the
/// message string to use.
void emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark message. \p PassName is the name of
-/// the pass emitting the message. If -Rpass-analysis= is given and \p
-/// PassName matches the regular expression in -Rpass, then the remark will be
-/// emitted. \p Fn is the function triggering the remark, \p DLoc is the debug
-/// location where the diagnostic is generated. \p Msg is the message string
-/// to use.
+/// \brief Legacy interface to emit an optimization analysis remark message.
+/// Use (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If
+/// -Rpass-analysis= is given and \p PassName matches the regular expression in
+/// -Rpass, then the remark will be emitted. \p Fn is the function triggering
+/// the remark, \p Loc is the debug location where the diagnostic is
+/// generated. \p Msg is the message string to use.
void emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName,
- const Function &Fn, const DebugLoc &DLoc,
+ const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark related to messages about
-/// floating-point non-commutativity. \p PassName is the name of the pass
-/// emitting the message. If -Rpass-analysis= is given and \p PassName matches
-/// the regular expression in -Rpass, then the remark will be emitted. \p Fn is
-/// the function triggering the remark, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
+/// \brief Legacy interface to emit an optimization analysis remark related to
+/// messages about floating-point non-commutativity. Use
+/// (Machine)OptimizationRemarkEmitter instead.
+///
+/// \p PassName is the name of the pass emitting the message. If
+/// -Rpass-analysis= is given and \p PassName matches the regular expression in
+/// -Rpass, then the remark will be emitted. \p Fn is the function triggering
+/// the remark, \p Loc is the debug location where the diagnostic is
+/// generated. \p Msg is the message string to use.
void emitOptimizationRemarkAnalysisFPCommute(LLVMContext &Ctx,
const char *PassName,
const Function &Fn,
- const DebugLoc &DLoc,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
-/// Emit an optimization analysis remark related to messages about
-/// pointer aliasing. \p PassName is the name of the pass emitting the message.
+/// \brief Legacy interface to emit an optimization analysis remark related to
+/// messages about pointer aliasing. Use (Machine)OptimizationRemarkEmitter
+/// instead.
+///
+/// \p PassName is the name of the pass emitting the message.
/// If -Rpass-analysis= is given and \p PassName matches the regular expression
/// in -Rpass, then the remark will be emitted. \p Fn is the function triggering
-/// the remark, \p DLoc is the debug location where the diagnostic is generated.
+/// the remark, \p Loc is the debug location where the diagnostic is generated.
/// \p Msg is the message string to use.
void emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx,
const char *PassName,
const Function &Fn,
- const DebugLoc &DLoc,
+ const DiagnosticLocation &Loc,
const Twine &Msg);
/// Diagnostic information for optimization failures.
-class DiagnosticInfoOptimizationFailure
- : public DiagnosticInfoOptimizationBase {
+class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
/// location. \p Msg is the message to show. Note that this class does not
/// copy this message, so this reference must be valid for the whole life time
/// of the diagnostic.
- DiagnosticInfoOptimizationFailure(const Function &Fn, const DebugLoc &DLoc,
+ DiagnosticInfoOptimizationFailure(const Function &Fn,
+ const DiagnosticLocation &Loc,
const Twine &Msg)
- : DiagnosticInfoOptimizationBase(DK_OptimizationFailure, DS_Warning,
- nullptr, Fn, DLoc, Msg) {}
+ : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
+ nullptr, Fn, Loc, Msg) {}
+
+ /// \p PassName is the name of the pass emitting this diagnostic. \p
+ /// RemarkName is a textual identifier for the remark (single-word,
+ /// camel-case). \p Loc is the debug location and \p CodeRegion is the
+ /// region that the optimization operates on (currently basic block is
+ /// supported).
+ DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
+ const DiagnosticLocation &Loc,
+ const Value *CodeRegion);
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_OptimizationFailure;
@@ -848,22 +986,22 @@ public:
};
/// Diagnostic information for unsupported feature in backend.
-class DiagnosticInfoUnsupported
- : public DiagnosticInfoWithDebugLocBase {
+class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
private:
Twine Msg;
public:
- /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is
+ /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
/// the location information to use in the diagnostic. If line table
/// information is available, the diagnostic will include the source code
/// location. \p Msg is the message to show. Note that this class does not
/// copy this message, so this reference must be valid for the whole life time
/// of the diagnostic.
- DiagnosticInfoUnsupported(const Function &Fn, const Twine &Msg,
- DebugLoc DLoc = DebugLoc(),
- DiagnosticSeverity Severity = DS_Error)
- : DiagnosticInfoWithDebugLocBase(DK_Unsupported, Severity, Fn, DLoc),
+ DiagnosticInfoUnsupported(
+ const Function &Fn, const Twine &Msg,
+ const DiagnosticLocation &Loc = DiagnosticLocation(),
+ DiagnosticSeverity Severity = DS_Error)
+ : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
Msg(Msg) {}
static bool classof(const DiagnosticInfo *DI) {
@@ -874,19 +1012,6 @@ public:
void print(DiagnosticPrinter &DP) const override;
};
-
-/// Emit a warning when loop vectorization is specified but fails. \p Fn is the
-/// function triggering the warning, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
-void emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg);
-
-/// Emit a warning when loop interleaving is specified but fails. \p Fn is the
-/// function triggering the warning, \p DLoc is the debug location where the
-/// diagnostic is generated. \p Msg is the message string to use.
-void emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn,
- const DebugLoc &DLoc, const Twine &Msg);
-
} // end namespace llvm
#endif // LLVM_IR_DIAGNOSTICINFO_H
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index 7c733bac8da0..cae03d33a7ee 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -16,17 +16,21 @@
#define LLVM_IR_DOMINATORS_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/GenericDomTree.h"
+#include <utility>
namespace llvm {
class Function;
-class BasicBlock;
+class Instruction;
+class Module;
class raw_ostream;
extern template class DomTreeNodeBase<BasicBlock>;
@@ -43,24 +47,37 @@ typedef DomTreeNodeBase<BasicBlock> DomTreeNode;
class BasicBlockEdge {
const BasicBlock *Start;
const BasicBlock *End;
+
public:
BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) :
- Start(Start_), End(End_) { }
+ Start(Start_), End(End_) {}
+
+ BasicBlockEdge(const std::pair<BasicBlock *, BasicBlock *> &Pair)
+ : Start(Pair.first), End(Pair.second) {}
+
+ BasicBlockEdge(const std::pair<const BasicBlock *, const BasicBlock *> &Pair)
+ : Start(Pair.first), End(Pair.second) {}
+
const BasicBlock *getStart() const {
return Start;
}
+
const BasicBlock *getEnd() const {
return End;
}
+
bool isSingleEdge() const;
};
template <> struct DenseMapInfo<BasicBlockEdge> {
- static unsigned getHashValue(const BasicBlockEdge *V);
typedef DenseMapInfo<const BasicBlock *> BBInfo;
+
+ static unsigned getHashValue(const BasicBlockEdge *V);
+
static inline BasicBlockEdge getEmptyKey() {
return BasicBlockEdge(BBInfo::getEmptyKey(), BBInfo::getEmptyKey());
}
+
static inline BasicBlockEdge getTombstoneKey() {
return BasicBlockEdge(BBInfo::getTombstoneKey(), BBInfo::getTombstoneKey());
}
@@ -69,6 +86,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> {
return hash_combine(BBInfo::getHashValue(Edge.getStart()),
BBInfo::getHashValue(Edge.getEnd()));
}
+
static bool isEqual(const BasicBlockEdge &LHS, const BasicBlockEdge &RHS) {
return BBInfo::isEqual(LHS.getStart(), RHS.getStart()) &&
BBInfo::isEqual(LHS.getEnd(), RHS.getEnd());
@@ -102,19 +120,17 @@ public:
recalculate(F);
}
+ /// Handle invalidation explicitly.
+ bool invalidate(Function &F, const PreservedAnalyses &PA,
+ FunctionAnalysisManager::Invalidator &);
+
/// \brief Returns *false* if the other dominator tree matches this dominator
/// tree.
inline bool compare(const DominatorTree &Other) const {
const DomTreeNode *R = getRootNode();
const DomTreeNode *OtherR = Other.getRootNode();
-
- if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
- return true;
-
- if (Base::compare(Other))
- return true;
-
- return false;
+ return !R || !OtherR || R->getBlock() != OtherR->getBlock() ||
+ Base::compare(Other);
}
// Ensure base-class overloads are visible.
@@ -205,6 +221,7 @@ class DominatorTreePrinterPass
public:
explicit DominatorTreePrinterPass(raw_ostream &OS);
+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
@@ -240,6 +257,6 @@ public:
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_DOMINATORS_H
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 1854d413c627..a3762a44ccb6 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -18,6 +18,7 @@
#ifndef LLVM_IR_FUNCTION_H
#define LLVM_IR_FUNCTION_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringRef.h"
@@ -47,23 +48,23 @@ class DISubprogram;
class Function : public GlobalObject, public ilist_node<Function> {
public:
- typedef SymbolTableList<Argument> ArgumentListType;
typedef SymbolTableList<BasicBlock> BasicBlockListType;
// BasicBlock iterators...
typedef BasicBlockListType::iterator iterator;
typedef BasicBlockListType::const_iterator const_iterator;
- typedef ArgumentListType::iterator arg_iterator;
- typedef ArgumentListType::const_iterator const_arg_iterator;
+ typedef Argument *arg_iterator;
+ typedef const Argument *const_arg_iterator;
private:
// Important things that make up a function!
BasicBlockListType BasicBlocks; ///< The basic blocks
- mutable ArgumentListType ArgumentList; ///< The formal arguments
+ mutable Argument *Arguments; ///< The formal arguments
+ size_t NumArgs;
std::unique_ptr<ValueSymbolTable>
SymTab; ///< Symbol table of args/instructions
- AttributeSet AttributeSets; ///< Parameter attributes
+ AttributeList AttributeSets; ///< Parameter attributes
/*
* Value::SubclassData
@@ -102,6 +103,8 @@ private:
void BuildLazyArguments() const;
+ void clearArguments();
+
/// Function ctor - If the (optional) Module argument is specified, the
/// function is automatically inserted into the end of the function list for
/// the module.
@@ -121,10 +124,12 @@ public:
// Provide fast operand accessors.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// Returns the type of the ret val.
- Type *getReturnType() const;
/// Returns the FunctionType for me.
- FunctionType *getFunctionType() const;
+ FunctionType *getFunctionType() const {
+ return cast<FunctionType>(getValueType());
+ }
+ /// Returns the type of the ret val.
+ Type *getReturnType() const { return getFunctionType()->getReturnType(); }
/// getContext - Return a reference to the LLVMContext associated with this
/// function.
@@ -132,10 +137,16 @@ public:
/// isVarArg - Return true if this function takes a variable number of
/// arguments.
- bool isVarArg() const;
+ bool isVarArg() const { return getFunctionType()->isVarArg(); }
- bool isMaterializable() const;
- void setIsMaterializable(bool V);
+ bool isMaterializable() const {
+ return getGlobalObjectSubClassData() & (1 << IsMaterializableBit);
+ }
+ void setIsMaterializable(bool V) {
+ unsigned Mask = 1 << IsMaterializableBit;
+ setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
+ (V ? Mask : 0u));
+ }
/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
@@ -173,42 +184,45 @@ public:
}
/// @brief Return the attribute list for this Function.
- AttributeSet getAttributes() const { return AttributeSets; }
+ AttributeList getAttributes() const { return AttributeSets; }
/// @brief Set the attribute list for this Function.
- void setAttributes(AttributeSet Attrs) { AttributeSets = Attrs; }
+ void setAttributes(AttributeList Attrs) { AttributeSets = Attrs; }
/// @brief Add function attributes to this function.
void addFnAttr(Attribute::AttrKind Kind) {
- addAttribute(AttributeSet::FunctionIndex, Kind);
+ addAttribute(AttributeList::FunctionIndex, Kind);
}
/// @brief Add function attributes to this function.
void addFnAttr(StringRef Kind, StringRef Val = StringRef()) {
- addAttribute(AttributeSet::FunctionIndex,
+ addAttribute(AttributeList::FunctionIndex,
Attribute::get(getContext(), Kind, Val));
}
void addFnAttr(Attribute Attr) {
- addAttribute(AttributeSet::FunctionIndex, Attr);
+ addAttribute(AttributeList::FunctionIndex, Attr);
}
/// @brief Remove function attributes from this function.
void removeFnAttr(Attribute::AttrKind Kind) {
- removeAttribute(AttributeSet::FunctionIndex, Kind);
+ removeAttribute(AttributeList::FunctionIndex, Kind);
}
/// @brief Remove function attribute from this function.
void removeFnAttr(StringRef Kind) {
setAttributes(AttributeSets.removeAttribute(
- getContext(), AttributeSet::FunctionIndex, Kind));
+ getContext(), AttributeList::FunctionIndex, Kind));
}
/// \brief Set the entry count for this function.
///
/// Entry count is the number of times this function was executed based on
- /// pgo data.
- void setEntryCount(uint64_t Count);
+ /// pgo data. \p Imports points to a set of GUIDs that needs to be imported
+ /// by the function for sample PGO, to enable the same inlines as the
+ /// profiled optimized binary.
+ void setEntryCount(uint64_t Count,
+ const DenseSet<GlobalValue::GUID> *Imports = nullptr);
/// \brief Get the entry count for this function.
///
@@ -216,6 +230,10 @@ public:
/// pgo data.
Optional<uint64_t> getEntryCount() const;
+ /// Returns the set of GUIDs that needs to be imported to the function for
+ /// sample PGO, to enable the same inlines as the profiled optimized binary.
+ DenseSet<GlobalValue::GUID> getImportGUIDs() const;
+
/// Set the section prefix for this function.
void setSectionPrefix(StringRef Prefix);
@@ -232,17 +250,17 @@ public:
/// @brief Return the attribute for the given attribute kind.
Attribute getFnAttribute(Attribute::AttrKind Kind) const {
- return getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeList::FunctionIndex, Kind);
}
Attribute getFnAttribute(StringRef Kind) const {
- return getAttribute(AttributeSet::FunctionIndex, Kind);
+ return getAttribute(AttributeList::FunctionIndex, Kind);
}
/// \brief Return the stack alignment for the function.
unsigned getFnStackAlignment() const {
if (!hasFnAttribute(Attribute::StackAlignment))
return 0;
- return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
+ return AttributeSets.getStackAlignment(AttributeList::FunctionIndex);
}
/// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
@@ -261,7 +279,7 @@ public:
void addAttribute(unsigned i, Attribute Attr);
/// @brief adds the attributes to the list of attributes.
- void addAttributes(unsigned i, AttributeSet Attrs);
+ void addAttributes(unsigned i, AttributeList Attrs);
/// @brief removes the attribute from the list of attributes.
void removeAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -270,13 +288,18 @@ public:
void removeAttribute(unsigned i, StringRef Kind);
/// @brief removes the attributes from the list of attributes.
- void removeAttributes(unsigned i, AttributeSet Attrs);
+ void removeAttributes(unsigned i, AttributeList Attrs);
/// @brief check if an attributes is in the list of attributes.
bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const {
return getAttributes().hasAttribute(i, Kind);
}
+ /// @brief check if an attributes is in the list of attributes.
+ bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const {
+ return getAttributes().hasParamAttribute(ArgNo, Kind);
+ }
+
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
return AttributeSets.getAttribute(i, Kind);
}
@@ -496,19 +519,6 @@ public:
/// Get the underlying elements of the Function... the basic block list is
/// empty for external functions.
///
- const ArgumentListType &getArgumentList() const {
- CheckLazyArguments();
- return ArgumentList;
- }
- ArgumentListType &getArgumentList() {
- CheckLazyArguments();
- return ArgumentList;
- }
-
- static ArgumentListType Function::*getSublistAccess(Argument*) {
- return &Function::ArgumentList;
- }
-
const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; }
BasicBlockListType &getBasicBlockList() { return BasicBlocks; }
@@ -549,20 +559,20 @@ public:
arg_iterator arg_begin() {
CheckLazyArguments();
- return ArgumentList.begin();
+ return Arguments;
}
const_arg_iterator arg_begin() const {
CheckLazyArguments();
- return ArgumentList.begin();
+ return Arguments;
}
arg_iterator arg_end() {
CheckLazyArguments();
- return ArgumentList.end();
+ return Arguments + NumArgs;
}
const_arg_iterator arg_end() const {
CheckLazyArguments();
- return ArgumentList.end();
+ return Arguments + NumArgs;
}
iterator_range<arg_iterator> args() {
@@ -574,8 +584,8 @@ public:
/// @}
- size_t arg_size() const;
- bool arg_empty() const;
+ size_t arg_size() const { return NumArgs; }
+ bool arg_empty() const { return arg_size() == 0; }
/// \brief Check whether this function has a personality function.
bool hasPersonalityFn() const {
@@ -671,6 +681,9 @@ public:
/// to \a DISubprogram.
DISubprogram *getSubprogram() const;
+ /// Returns true if we should emit debug info for profiling.
+ bool isDebugInfoForProfiling() const;
+
private:
void allocHungoffUselist();
template<int Idx> void setHungoffOperand(Constant *C);
diff --git a/include/llvm/IR/GlobalIndirectSymbol.h b/include/llvm/IR/GlobalIndirectSymbol.h
index 671309e85d19..212703af7101 100644
--- a/include/llvm/IR/GlobalIndirectSymbol.h
+++ b/include/llvm/IR/GlobalIndirectSymbol.h
@@ -48,27 +48,31 @@ public:
setOperand(0, Symbol);
}
const Constant *getIndirectSymbol() const {
- return const_cast<GlobalIndirectSymbol *>(this)->getIndirectSymbol();
+ return getOperand(0);
}
Constant *getIndirectSymbol() {
- return getOperand(0);
+ return const_cast<Constant *>(
+ static_cast<const GlobalIndirectSymbol *>(this)->getIndirectSymbol());
}
const GlobalObject *getBaseObject() const {
- return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject();
+ return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
}
GlobalObject *getBaseObject() {
- return dyn_cast<GlobalObject>(getIndirectSymbol()->stripInBoundsOffsets());
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalIndirectSymbol *>(this)->getBaseObject());
}
const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const {
- return const_cast<GlobalIndirectSymbol *>(this)->getBaseObject(DL, Offset);
- }
- GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
return dyn_cast<GlobalObject>(
getIndirectSymbol()->stripAndAccumulateInBoundsConstantOffsets(DL,
Offset));
}
+ GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) {
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalIndirectSymbol *>(this)
+ ->getBaseObject(DL, Offset));
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *V) {
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index 1057f564aab3..f3789bafefe3 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -63,8 +63,17 @@ public:
}
void setAlignment(unsigned Align);
- unsigned getGlobalObjectSubClassData() const;
- void setGlobalObjectSubClassData(unsigned Val);
+ unsigned getGlobalObjectSubClassData() const {
+ unsigned ValueData = getGlobalValueSubClassData();
+ return ValueData >> GlobalObjectBits;
+ }
+
+ void setGlobalObjectSubClassData(unsigned Val) {
+ unsigned OldData = getGlobalValueSubClassData();
+ setGlobalValueSubClassData((OldData & GlobalObjectMask) |
+ (Val << GlobalObjectBits));
+ assert(getGlobalObjectSubClassData() == Val && "representation error");
+ }
/// Check if this global has a custom object file section.
///
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index c6398aaa4847..bb30fa8be867 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -211,9 +211,10 @@ public:
}
bool hasComdat() const { return getComdat() != nullptr; }
- Comdat *getComdat();
- const Comdat *getComdat() const {
- return const_cast<GlobalValue *>(this)->getComdat();
+ const Comdat *getComdat() const;
+ Comdat *getComdat() {
+ return const_cast<Comdat *>(
+ static_cast<const GlobalValue *>(this)->getComdat());
}
VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); }
@@ -514,10 +515,11 @@ public:
// increased.
bool canIncreaseAlignment() const;
- const GlobalObject *getBaseObject() const {
- return const_cast<GlobalValue *>(this)->getBaseObject();
+ const GlobalObject *getBaseObject() const;
+ GlobalObject *getBaseObject() {
+ return const_cast<GlobalObject *>(
+ static_cast<const GlobalValue *>(this)->getBaseObject());
}
- GlobalObject *getBaseObject();
/// Returns whether this is a reference to an absolute symbol.
bool isAbsoluteSymbolRef() const;
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index 1d9c16989de9..bc689f3b01d7 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -33,6 +33,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
@@ -75,7 +76,7 @@ class IRBuilderCallbackInserter : IRBuilderDefaultInserter {
public:
IRBuilderCallbackInserter(std::function<void(Instruction *)> Callback)
- : Callback(Callback) {}
+ : Callback(std::move(Callback)) {}
protected:
void InsertHelper(Instruction *I, const Twine &Name,
@@ -560,6 +561,22 @@ public:
Type *ResultType,
const Twine &Name = "");
+ /// Create a call to intrinsic \p ID with 2 operands which is mangled on the
+ /// first type.
+ CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID,
+ Value *LHS, Value *RHS,
+ const Twine &Name = "");
+
+ /// Create call to the minnum intrinsic.
+ CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ }
+
+ /// Create call to the maxnum intrinsic.
+ CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name);
+ }
+
private:
/// \brief Create a call to a masked intrinsic with given Id.
CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops,
@@ -1073,9 +1090,15 @@ public:
// Instruction creation methods: Memory Instructions
//===--------------------------------------------------------------------===//
+ AllocaInst *CreateAlloca(Type *Ty, unsigned AddrSpace,
+ Value *ArraySize = nullptr, const Twine &Name = "") {
+ return Insert(new AllocaInst(Ty, AddrSpace, ArraySize), Name);
+ }
+
AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr,
const Twine &Name = "") {
- return Insert(new AllocaInst(Ty, ArraySize), Name);
+ const DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
+ return Insert(new AllocaInst(Ty, DL.getAllocaAddrSpace(), ArraySize), Name);
}
// \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of
// converting the string to 'bool' for the isVolatile parameter.
@@ -1790,24 +1813,16 @@ public:
return V;
}
- /// \brief Create an assume intrinsic call that represents an alignment
- /// assumption on the provided pointer.
- ///
- /// An optional offset can be provided, and if it is provided, the offset
- /// must be subtracted from the provided pointer to get the pointer with the
- /// specified alignment.
- CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
- unsigned Alignment,
- Value *OffsetValue = nullptr) {
- assert(isa<PointerType>(PtrValue->getType()) &&
- "trying to create an alignment assumption on a non-pointer?");
-
- PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
- Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+private:
+ /// \brief Helper function that creates an assume intrinsic call that
+ /// represents an alignment assumption on the provided Ptr, Mask, Type
+ /// and Offset.
+ CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL,
+ Value *PtrValue, Value *Mask,
+ Type *IntPtrTy,
+ Value *OffsetValue) {
Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint");
- Value *Mask = ConstantInt::get(IntPtrTy,
- Alignment > 0 ? Alignment - 1 : 0);
if (OffsetValue) {
bool IsOffsetZero = false;
if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue))
@@ -1824,9 +1839,60 @@ public:
Value *Zero = ConstantInt::get(IntPtrTy, 0);
Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr");
Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond");
-
return CreateAssumption(InvCond);
}
+
+public:
+ /// \brief Create an assume intrinsic call that represents an alignment
+ /// assumption on the provided pointer.
+ ///
+ /// An optional offset can be provided, and if it is provided, the offset
+ /// must be subtracted from the provided pointer to get the pointer with the
+ /// specified alignment.
+ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
+ unsigned Alignment,
+ Value *OffsetValue = nullptr) {
+ assert(isa<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+ PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+
+ Value *Mask = ConstantInt::get(IntPtrTy, Alignment > 0 ? Alignment - 1 : 0);
+ return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy,
+ OffsetValue);
+ }
+ //
+ /// \brief Create an assume intrinsic call that represents an alignment
+ /// assumption on the provided pointer.
+ ///
+ /// An optional offset can be provided, and if it is provided, the offset
+ /// must be subtracted from the provided pointer to get the pointer with the
+ /// specified alignment.
+ ///
+ /// This overload handles the condition where the Alignment is dependent
+ /// on an existing value rather than a static value.
+ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue,
+ Value *Alignment,
+ Value *OffsetValue = nullptr) {
+ assert(isa<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+ PointerType *PtrTy = cast<PointerType>(PtrValue->getType());
+ Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace());
+
+ if (Alignment->getType() != IntPtrTy)
+ Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ true,
+ "alignmentcast");
+ Value *IsPositive =
+ CreateICmp(CmpInst::ICMP_SGT, Alignment,
+ ConstantInt::get(Alignment->getType(), 0), "ispositive");
+ Value *PositiveMask =
+ CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "positivemask");
+ Value *Mask = CreateSelect(IsPositive, PositiveMask,
+ ConstantInt::get(IntPtrTy, 0), "mask");
+
+ return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy,
+ OffsetValue);
+ }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index f95509b9b09a..5d2f72d211ff 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -1,4 +1,4 @@
-//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===//
+//===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -102,12 +102,14 @@ public:
/// input constraint is required to match it (e.g. "0"). The value is the
/// constraint number that matches this one (for example, if this is
/// constraint #0 and constraint #4 has the value "0", this will be 4).
- signed char MatchingInput;
+ signed char MatchingInput = -1;
+
/// Code - The constraint code, either the register name (in braces) or the
/// constraint letter/number.
ConstraintCodeVector Codes;
+
/// Default constructor.
- SubConstraintInfo() : MatchingInput(-1) {}
+ SubConstraintInfo() = default;
};
typedef std::vector<SubConstraintInfo> SubConstraintInfoVector;
@@ -117,17 +119,17 @@ public:
struct ConstraintInfo {
/// Type - The basic type of the constraint: input/output/clobber
///
- ConstraintPrefix Type;
+ ConstraintPrefix Type = isInput;
/// isEarlyClobber - "&": output operand writes result before inputs are all
/// read. This is only ever set for an output operand.
- bool isEarlyClobber;
+ bool isEarlyClobber = false;
/// MatchingInput - If this is not -1, this is an output constraint where an
/// input constraint is required to match it (e.g. "0"). The value is the
/// constraint number that matches this one (for example, if this is
/// constraint #0 and constraint #4 has the value "0", this will be 4).
- signed char MatchingInput;
+ signed char MatchingInput = -1;
/// hasMatchingInput - Return true if this is an output constraint that has
/// a matching input constraint.
@@ -135,30 +137,30 @@ public:
/// isCommutative - This is set to true for a constraint that is commutative
/// with the next operand.
- bool isCommutative;
+ bool isCommutative = false;
/// isIndirect - True if this operand is an indirect operand. This means
/// that the address of the source or destination is present in the call
/// instruction, instead of it being returned or passed in explicitly. This
/// is represented with a '*' in the asm string.
- bool isIndirect;
+ bool isIndirect = false;
/// Code - The constraint code, either the register name (in braces) or the
/// constraint letter/number.
ConstraintCodeVector Codes;
/// isMultipleAlternative - '|': has multiple-alternative constraints.
- bool isMultipleAlternative;
+ bool isMultipleAlternative = false;
/// multipleAlternatives - If there are multiple alternative constraints,
/// this array will contain them. Otherwise it will be empty.
SubConstraintInfoVector multipleAlternatives;
/// The currently selected alternative constraint index.
- unsigned currentAlternativeIndex;
+ unsigned currentAlternativeIndex = 0;
/// Default constructor.
- ConstraintInfo();
+ ConstraintInfo() = default;
/// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the
/// fields in this structure. If the constraint string is not understood,
diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h
index 088d3e0fbfa5..55579819fd34 100644
--- a/include/llvm/IR/InstVisitor.h
+++ b/include/llvm/IR/InstVisitor.h
@@ -116,6 +116,9 @@ public:
// visit - Finally, code to visit an instruction...
//
RetTy visit(Instruction &I) {
+ static_assert(std::is_base_of<InstVisitor, SubClass>::value,
+ "Must pass the derived type to this template!");
+
switch (I.getOpcode()) {
default: llvm_unreachable("Unknown instruction type encountered!");
// Build the switch statement using the Instruction.def file...
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index f2abbec64fe6..518094735d72 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -1061,13 +1061,13 @@ public:
/// @brief Determine if Pred1 implies Pred2 is true when two compares have
/// matching operands.
- bool isImpliedTrueByMatchingCmp(Predicate Pred2) {
+ bool isImpliedTrueByMatchingCmp(Predicate Pred2) const {
return isImpliedTrueByMatchingCmp(getPredicate(), Pred2);
}
/// @brief Determine if Pred1 implies Pred2 is false when two compares have
/// matching operands.
- bool isImpliedFalseByMatchingCmp(Predicate Pred2) {
+ bool isImpliedFalseByMatchingCmp(Predicate Pred2) const {
return isImpliedFalseByMatchingCmp(getPredicate(), Pred2);
}
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index fd7c54d69b63..90c3175122fd 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -68,14 +68,20 @@ public:
/// Note: this is undefined behavior if the instruction does not have a
/// parent, or the parent basic block does not have a parent function.
const Module *getModule() const;
- Module *getModule();
+ Module *getModule() {
+ return const_cast<Module *>(
+ static_cast<const Instruction *>(this)->getModule());
+ }
/// Return the function this instruction belongs to.
///
/// Note: it is undefined behavior to call this on an instruction not
/// currently inserted into a function.
const Function *getFunction() const;
- Function *getFunction();
+ Function *getFunction() {
+ return const_cast<Function *>(
+ static_cast<const Instruction *>(this)->getFunction());
+ }
/// This method unlinks 'this' from the containing basic block, but does not
/// delete it.
@@ -252,6 +258,12 @@ public:
/// Returns false if no metadata was found.
bool extractProfTotalWeight(uint64_t &TotalVal) const;
+ /// Updates branch_weights metadata by scaling it by \p S / \p T.
+ void updateProfWeight(uint64_t S, uint64_t T);
+
+ /// Sets the branch_weights metadata to \p W for CallInst.
+ void setProfWeight(uint64_t W);
+
/// Set the debug location information for this instruction.
void setDebugLoc(DebugLoc Loc) { DbgLoc = std::move(Loc); }
@@ -276,6 +288,10 @@ public:
/// Determine whether the no signed wrap flag is set.
bool hasNoSignedWrap() const;
+ /// Drops flags that may cause this instruction to evaluate to poison despite
+ /// having non-poison inputs.
+ void dropPoisonGeneratingFlags();
+
/// Determine whether the exact flag is set.
bool isExact() const;
@@ -329,6 +345,9 @@ public:
/// Determine whether the allow-reciprocal flag is set.
bool hasAllowReciprocal() const;
+ /// Determine whether the allow-contract flag is set.
+ bool hasAllowContract() const;
+
/// Convenience function for getting all the fast-math flags, which must be an
/// operator which supports these flags. See LangRef.html for the meaning of
/// these flags.
@@ -372,18 +391,30 @@ public:
///
/// In LLVM, the Add, Mul, And, Or, and Xor operators are associative.
///
- bool isAssociative() const;
- static bool isAssociative(unsigned op);
+ bool isAssociative() const LLVM_READONLY;
+ static bool isAssociative(unsigned Opcode) {
+ return Opcode == And || Opcode == Or || Opcode == Xor ||
+ Opcode == Add || Opcode == Mul;
+ }
/// Return true if the instruction is commutative:
///
/// Commutative operators satisfy: (x op y) === (y op x)
///
- /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when
+ /// In LLVM, these are the commutative operators, plus SetEQ and SetNE, when
/// applied to any type.
///
bool isCommutative() const { return isCommutative(getOpcode()); }
- static bool isCommutative(unsigned op);
+ static bool isCommutative(unsigned Opcode) {
+ switch (Opcode) {
+ case Add: case FAdd:
+ case Mul: case FMul:
+ case And: case Or: case Xor:
+ return true;
+ default:
+ return false;
+ }
+ }
/// Return true if the instruction is idempotent:
///
@@ -392,7 +423,9 @@ public:
/// In LLVM, the And and Or operators are idempotent.
///
bool isIdempotent() const { return isIdempotent(getOpcode()); }
- static bool isIdempotent(unsigned op);
+ static bool isIdempotent(unsigned Opcode) {
+ return Opcode == And || Opcode == Or;
+ }
/// Return true if the instruction is nilpotent:
///
@@ -404,7 +437,9 @@ public:
/// In LLVM, the Xor operator is nilpotent.
///
bool isNilpotent() const { return isNilpotent(getOpcode()); }
- static bool isNilpotent(unsigned op);
+ static bool isNilpotent(unsigned Opcode) {
+ return Opcode == Xor;
+ }
/// Return true if this instruction may modify memory.
bool mayWriteToMemory() const;
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index a5d78a08171a..34dafebe0fc5 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -67,18 +67,21 @@ protected:
AllocaInst *cloneImpl() const;
public:
- explicit AllocaInst(Type *Ty, Value *ArraySize = nullptr,
+ explicit AllocaInst(Type *Ty, unsigned AddrSpace,
+ Value *ArraySize = nullptr,
const Twine &Name = "",
Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, Value *ArraySize,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
const Twine &Name, BasicBlock *InsertAtEnd);
- AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd);
+ AllocaInst(Type *Ty, unsigned AddrSpace,
+ const Twine &Name, Instruction *InsertBefore = nullptr);
+ AllocaInst(Type *Ty, unsigned AddrSpace,
+ const Twine &Name, BasicBlock *InsertAtEnd);
- AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
const Twine &Name = "", Instruction *InsertBefore = nullptr);
- AllocaInst(Type *Ty, Value *ArraySize, unsigned Align,
+ AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize, unsigned Align,
const Twine &Name, BasicBlock *InsertAtEnd);
// Out of line virtual method, so the vtable, etc. has a home.
@@ -958,6 +961,14 @@ public:
inline op_iterator idx_end() { return op_end(); }
inline const_op_iterator idx_end() const { return op_end(); }
+ inline iterator_range<op_iterator> indices() {
+ return make_range(idx_begin(), idx_end());
+ }
+
+ inline iterator_range<const_op_iterator> indices() const {
+ return make_range(idx_begin(), idx_end());
+ }
+
Value *getPointerOperand() {
return getOperand(0);
}
@@ -1354,7 +1365,7 @@ class CallInst : public Instruction,
public OperandBundleUser<CallInst, User::op_iterator> {
friend class OperandBundleUser<CallInst, User::op_iterator>;
- AttributeSet AttributeList; ///< parameter attributes for call
+ AttributeList Attrs; ///< parameter attributes for call
FunctionType *FTy;
CallInst(const CallInst &CI);
@@ -1633,11 +1644,11 @@ public:
/// Return the parameter attributes for this call.
///
- AttributeSet getAttributes() const { return AttributeList; }
+ AttributeList getAttributes() const { return Attrs; }
/// Set the parameter attributes for this call.
///
- void setAttributes(AttributeSet Attrs) { AttributeList = Attrs; }
+ void setAttributes(AttributeList A) { Attrs = A; }
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -1670,8 +1681,11 @@ public:
return hasFnAttrImpl(Kind);
}
- /// Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+ /// Determine whether the return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const;
+
+ /// Determine whether the argument or parameter has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
/// Get the attribute of a given kind at a position.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -1700,26 +1714,26 @@ public:
/// Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
- return AttributeList.getParamAlignment(i);
+ return Attrs.getParamAlignment(i);
}
/// Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
- return AttributeList.getDereferenceableBytes(i);
+ return Attrs.getDereferenceableBytes(i);
}
/// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
- return AttributeList.getDereferenceableOrNullBytes(i);
+ return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
- return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ return Attrs.hasAttribute(n, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a
@@ -1732,7 +1746,7 @@ public:
/// Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attribute::NoInline); }
void setIsNoInline() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
}
/// Return true if the call can return twice
@@ -1740,7 +1754,7 @@ public:
return hasFnAttr(Attribute::ReturnsTwice);
}
void setCanReturnTwice() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReturnsTwice);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice);
}
/// Determine if the call does not access memory.
@@ -1748,7 +1762,7 @@ public:
return hasFnAttr(Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
}
/// Determine if the call does not access or only reads memory.
@@ -1756,7 +1770,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly);
}
/// Determine if the call does not access or only writes memory.
@@ -1764,7 +1778,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
}
void setDoesNotReadMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
}
/// @brief Determine if the call can access memmory only using pointers based
@@ -1773,34 +1787,34 @@ public:
return hasFnAttr(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
}
/// Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
void setDoesNotReturn() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
}
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
/// Determine if the call cannot be duplicated.
bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
void setCannotDuplicate() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
/// Determine if the call is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
void setNotConvergent() {
- removeAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
/// Determine if the call returns a structure through first
@@ -1810,12 +1824,12 @@ public:
return false;
// Be friendly and also check the callee.
- return paramHasAttr(1, Attribute::StructRet);
+ return paramHasAttr(0, Attribute::StructRet);
}
/// Determine if any call argument is an aggregate passed by value.
bool hasByValArgument() const {
- return AttributeList.hasAttrSomewhere(Attribute::ByVal);
+ return Attrs.hasAttrSomewhere(Attribute::ByVal);
}
/// Return the function called, or null if this is an
@@ -1858,7 +1872,7 @@ public:
private:
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
- if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, Kind))
+ if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
// Operand bundles override attributes on the called function, but don't
@@ -1867,7 +1881,8 @@ private:
return false;
if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return F->getAttributes().hasAttribute(AttributeList::FunctionIndex,
+ Kind);
return false;
}
@@ -3084,42 +3099,41 @@ public:
// -2
static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1);
- template <class SwitchInstTy, class ConstantIntTy, class BasicBlockTy>
- class CaseIteratorT {
- protected:
- SwitchInstTy *SI;
- unsigned Index;
+ template <typename CaseHandleT> class CaseIteratorImpl;
- public:
- typedef CaseIteratorT<SwitchInstTy, ConstantIntTy, BasicBlockTy> Self;
+ /// A handle to a particular switch case. It exposes a convenient interface
+ /// to both the case value and the successor block.
+ ///
+ /// We define this as a template and instantiate it to form both a const and
+ /// non-const handle.
+ template <typename SwitchInstT, typename ConstantIntT, typename BasicBlockT>
+ class CaseHandleImpl {
+ // Directly befriend both const and non-const iterators.
+ friend class SwitchInst::CaseIteratorImpl<
+ CaseHandleImpl<SwitchInstT, ConstantIntT, BasicBlockT>>;
- /// Initializes case iterator for given SwitchInst and for given
- /// case number.
- CaseIteratorT(SwitchInstTy *SI, unsigned CaseNum) {
- this->SI = SI;
- Index = CaseNum;
- }
+ protected:
+ // Expose the switch type we're parameterized with to the iterator.
+ typedef SwitchInstT SwitchInstType;
- /// Initializes case iterator for given SwitchInst and for given
- /// TerminatorInst's successor index.
- static Self fromSuccessorIndex(SwitchInstTy *SI, unsigned SuccessorIndex) {
- assert(SuccessorIndex < SI->getNumSuccessors() &&
- "Successor index # out of range!");
- return SuccessorIndex != 0 ?
- Self(SI, SuccessorIndex - 1) :
- Self(SI, DefaultPseudoIndex);
- }
+ SwitchInstT *SI;
+ ptrdiff_t Index;
+
+ CaseHandleImpl() = default;
+ CaseHandleImpl(SwitchInstT *SI, ptrdiff_t Index) : SI(SI), Index(Index) {}
+ public:
/// Resolves case value for current case.
- ConstantIntTy *getCaseValue() {
- assert(Index < SI->getNumCases() && "Index out the number of cases.");
- return reinterpret_cast<ConstantIntTy*>(SI->getOperand(2 + Index*2));
+ ConstantIntT *getCaseValue() const {
+ assert((unsigned)Index < SI->getNumCases() &&
+ "Index out the number of cases.");
+ return reinterpret_cast<ConstantIntT *>(SI->getOperand(2 + Index * 2));
}
/// Resolves successor for current case.
- BasicBlockTy *getCaseSuccessor() {
- assert((Index < SI->getNumCases() ||
- Index == DefaultPseudoIndex) &&
+ BasicBlockT *getCaseSuccessor() const {
+ assert(((unsigned)Index < SI->getNumCases() ||
+ (unsigned)Index == DefaultPseudoIndex) &&
"Index out the number of cases.");
return SI->getSuccessor(getSuccessorIndex());
}
@@ -3129,63 +3143,32 @@ public:
/// Returns TerminatorInst's successor index for current case successor.
unsigned getSuccessorIndex() const {
- assert((Index == DefaultPseudoIndex || Index < SI->getNumCases()) &&
+ assert(((unsigned)Index == DefaultPseudoIndex ||
+ (unsigned)Index < SI->getNumCases()) &&
"Index out the number of cases.");
- return Index != DefaultPseudoIndex ? Index + 1 : 0;
+ return (unsigned)Index != DefaultPseudoIndex ? Index + 1 : 0;
}
- Self operator++() {
- // Check index correctness after increment.
- // Note: Index == getNumCases() means end().
- assert(Index+1 <= SI->getNumCases() && "Index out the number of cases.");
- ++Index;
- return *this;
- }
- Self operator++(int) {
- Self tmp = *this;
- ++(*this);
- return tmp;
- }
- Self operator--() {
- // Check index correctness after decrement.
- // Note: Index == getNumCases() means end().
- // Also allow "-1" iterator here. That will became valid after ++.
- assert((Index == 0 || Index-1 <= SI->getNumCases()) &&
- "Index out the number of cases.");
- --Index;
- return *this;
- }
- Self operator--(int) {
- Self tmp = *this;
- --(*this);
- return tmp;
- }
- bool operator==(const Self& RHS) const {
- assert(RHS.SI == SI && "Incompatible operators.");
- return RHS.Index == Index;
- }
- bool operator!=(const Self& RHS) const {
- assert(RHS.SI == SI && "Incompatible operators.");
- return RHS.Index != Index;
- }
- Self &operator*() {
- return *this;
+ bool operator==(const CaseHandleImpl &RHS) const {
+ assert(SI == RHS.SI && "Incompatible operators.");
+ return Index == RHS.Index;
}
};
- typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock>
- ConstCaseIt;
+ typedef CaseHandleImpl<const SwitchInst, const ConstantInt, const BasicBlock>
+ ConstCaseHandle;
- class CaseIt : public CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> {
- typedef CaseIteratorT<SwitchInst, ConstantInt, BasicBlock> ParentTy;
+ class CaseHandle
+ : public CaseHandleImpl<SwitchInst, ConstantInt, BasicBlock> {
+ friend class SwitchInst::CaseIteratorImpl<CaseHandle>;
public:
- CaseIt(const ParentTy &Src) : ParentTy(Src) {}
- CaseIt(SwitchInst *SI, unsigned CaseNum) : ParentTy(SI, CaseNum) {}
+ CaseHandle(SwitchInst *SI, ptrdiff_t Index) : CaseHandleImpl(SI, Index) {}
/// Sets the new value for current case.
void setValue(ConstantInt *V) {
- assert(Index < SI->getNumCases() && "Index out the number of cases.");
+ assert((unsigned)Index < SI->getNumCases() &&
+ "Index out the number of cases.");
SI->setOperand(2 + Index*2, reinterpret_cast<Value*>(V));
}
@@ -3195,6 +3178,76 @@ public:
}
};
+ template <typename CaseHandleT>
+ class CaseIteratorImpl
+ : public iterator_facade_base<CaseIteratorImpl<CaseHandleT>,
+ std::random_access_iterator_tag,
+ CaseHandleT> {
+ typedef typename CaseHandleT::SwitchInstType SwitchInstT;
+
+ CaseHandleT Case;
+
+ public:
+ /// Default constructed iterator is in an invalid state until assigned to
+ /// a case for a particular switch.
+ CaseIteratorImpl() = default;
+
+ /// Initializes case iterator for given SwitchInst and for given
+ /// case number.
+ CaseIteratorImpl(SwitchInstT *SI, unsigned CaseNum) : Case(SI, CaseNum) {}
+
+ /// Initializes case iterator for given SwitchInst and for given
+ /// TerminatorInst's successor index.
+ static CaseIteratorImpl fromSuccessorIndex(SwitchInstT *SI,
+ unsigned SuccessorIndex) {
+ assert(SuccessorIndex < SI->getNumSuccessors() &&
+ "Successor index # out of range!");
+ return SuccessorIndex != 0 ? CaseIteratorImpl(SI, SuccessorIndex - 1)
+ : CaseIteratorImpl(SI, DefaultPseudoIndex);
+ }
+
+ /// Support converting to the const variant. This will be a no-op for const
+ /// variant.
+ operator CaseIteratorImpl<ConstCaseHandle>() const {
+ return CaseIteratorImpl<ConstCaseHandle>(Case.SI, Case.Index);
+ }
+
+ CaseIteratorImpl &operator+=(ptrdiff_t N) {
+ // Check index correctness after addition.
+ // Note: Index == getNumCases() means end().
+ assert(Case.Index + N >= 0 &&
+ (unsigned)(Case.Index + N) <= Case.SI->getNumCases() &&
+ "Case.Index out the number of cases.");
+ Case.Index += N;
+ return *this;
+ }
+ CaseIteratorImpl &operator-=(ptrdiff_t N) {
+ // Check index correctness after subtraction.
+ // Note: Case.Index == getNumCases() means end().
+ assert(Case.Index - N >= 0 &&
+ (unsigned)(Case.Index - N) <= Case.SI->getNumCases() &&
+ "Case.Index out the number of cases.");
+ Case.Index -= N;
+ return *this;
+ }
+ ptrdiff_t operator-(const CaseIteratorImpl &RHS) const {
+ assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
+ return Case.Index - RHS.Case.Index;
+ }
+ bool operator==(const CaseIteratorImpl &RHS) const {
+ return Case == RHS.Case;
+ }
+ bool operator<(const CaseIteratorImpl &RHS) const {
+ assert(Case.SI == RHS.Case.SI && "Incompatible operators.");
+ return Case.Index < RHS.Case.Index;
+ }
+ CaseHandleT &operator*() { return Case; }
+ const CaseHandleT &operator*() const { return Case; }
+ };
+
+ typedef CaseIteratorImpl<CaseHandle> CaseIt;
+ typedef CaseIteratorImpl<ConstCaseHandle> ConstCaseIt;
+
static SwitchInst *Create(Value *Value, BasicBlock *Default,
unsigned NumCases,
Instruction *InsertBefore = nullptr) {
@@ -3278,30 +3331,40 @@ public:
/// default case iterator to indicate that it is handled by the default
/// handler.
CaseIt findCaseValue(const ConstantInt *C) {
- for (CaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValue() == C)
- return i;
+ CaseIt I = llvm::find_if(
+ cases(), [C](CaseHandle &Case) { return Case.getCaseValue() == C; });
+ if (I != case_end())
+ return I;
+
return case_default();
}
ConstCaseIt findCaseValue(const ConstantInt *C) const {
- for (ConstCaseIt i = case_begin(), e = case_end(); i != e; ++i)
- if (i.getCaseValue() == C)
- return i;
+ ConstCaseIt I = llvm::find_if(cases(), [C](ConstCaseHandle &Case) {
+ return Case.getCaseValue() == C;
+ });
+ if (I != case_end())
+ return I;
+
return case_default();
}
/// Finds the unique case value for a given successor. Returns null if the
/// successor is not found, not unique, or is the default case.
ConstantInt *findCaseDest(BasicBlock *BB) {
- if (BB == getDefaultDest()) return nullptr;
+ if (BB == getDefaultDest())
+ return nullptr;
ConstantInt *CI = nullptr;
- for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) {
- if (i.getCaseSuccessor() == BB) {
- if (CI) return nullptr; // Multiple cases lead to BB.
- else CI = i.getCaseValue();
- }
+ for (auto Case : cases()) {
+ if (Case.getCaseSuccessor() != BB)
+ continue;
+
+ if (CI)
+ return nullptr; // Multiple cases lead to BB.
+
+ CI = Case.getCaseValue();
}
+
return CI;
}
@@ -3316,8 +3379,9 @@ public:
/// index idx and above.
/// Note:
/// This action invalidates iterators for all cases following the one removed,
- /// including the case_end() iterator.
- void removeCase(CaseIt i);
+ /// including the case_end() iterator. It returns an iterator for the next
+ /// case.
+ CaseIt removeCase(CaseIt I);
unsigned getNumSuccessors() const { return getNumOperands()/2; }
BasicBlock *getSuccessor(unsigned idx) const {
@@ -3465,7 +3529,7 @@ class InvokeInst : public TerminatorInst,
public OperandBundleUser<InvokeInst, User::op_iterator> {
friend class OperandBundleUser<InvokeInst, User::op_iterator>;
- AttributeSet AttributeList;
+ AttributeList Attrs;
FunctionType *FTy;
InvokeInst(const InvokeInst &BI);
@@ -3669,11 +3733,11 @@ public:
/// Return the parameter attributes for this invoke.
///
- AttributeSet getAttributes() const { return AttributeList; }
+ AttributeList getAttributes() const { return Attrs; }
/// Set the parameter attributes for this invoke.
///
- void setAttributes(AttributeSet Attrs) { AttributeList = Attrs; }
+ void setAttributes(AttributeList A) { Attrs = A; }
/// adds the attribute to the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind Kind);
@@ -3706,8 +3770,11 @@ public:
return hasFnAttrImpl(Kind);
}
- /// Determine whether the call or the callee has the given attributes.
- bool paramHasAttr(unsigned i, Attribute::AttrKind Kind) const;
+ /// Determine whether the return value has the given attribute.
+ bool hasRetAttr(Attribute::AttrKind Kind) const;
+
+ /// Determine whether the argument or parameter has the given attribute.
+ bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const;
/// Get the attribute of a given kind at a position.
Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const {
@@ -3737,26 +3804,26 @@ public:
/// Extract the alignment for a call or parameter (0=unknown).
unsigned getParamAlignment(unsigned i) const {
- return AttributeList.getParamAlignment(i);
+ return Attrs.getParamAlignment(i);
}
/// Extract the number of dereferenceable bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableBytes(unsigned i) const {
- return AttributeList.getDereferenceableBytes(i);
+ return Attrs.getDereferenceableBytes(i);
}
/// Extract the number of dereferenceable_or_null bytes for a call or
/// parameter (0=unknown).
uint64_t getDereferenceableOrNullBytes(unsigned i) const {
- return AttributeList.getDereferenceableOrNullBytes(i);
+ return Attrs.getDereferenceableOrNullBytes(i);
}
/// @brief Determine if the parameter or return value is marked with NoAlias
/// attribute.
/// @param n The parameter to check. 1 is the first parameter, 0 is the return
bool doesNotAlias(unsigned n) const {
- return AttributeList.hasAttribute(n, Attribute::NoAlias);
+ return Attrs.hasAttribute(n, Attribute::NoAlias);
}
/// Return true if the call should not be treated as a call to a
@@ -3771,7 +3838,7 @@ public:
/// Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attribute::NoInline); }
void setIsNoInline() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoInline);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
}
/// Determine if the call does not access memory.
@@ -3779,7 +3846,7 @@ public:
return hasFnAttr(Attribute::ReadNone);
}
void setDoesNotAccessMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone);
}
/// Determine if the call does not access or only reads memory.
@@ -3787,7 +3854,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly);
}
void setOnlyReadsMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly);
}
/// Determine if the call does not access or only writes memory.
@@ -3795,7 +3862,7 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly);
}
void setDoesNotReadMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::WriteOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly);
}
/// @brief Determine if the call access memmory only using it's pointer
@@ -3804,34 +3871,34 @@ public:
return hasFnAttr(Attribute::ArgMemOnly);
}
void setOnlyAccessesArgMemory() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly);
+ addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly);
}
/// Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); }
void setDoesNotReturn() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoReturn);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn);
}
/// Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); }
void setDoesNotThrow() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind);
}
/// Determine if the invoke cannot be duplicated.
bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); }
void setCannotDuplicate() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate);
+ addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate);
}
/// Determine if the invoke is convergent
bool isConvergent() const { return hasFnAttr(Attribute::Convergent); }
void setConvergent() {
- addAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ addAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
void setNotConvergent() {
- removeAttribute(AttributeSet::FunctionIndex, Attribute::Convergent);
+ removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent);
}
/// Determine if the call returns a structure through first
@@ -3841,12 +3908,12 @@ public:
return false;
// Be friendly and also check the callee.
- return paramHasAttr(1, Attribute::StructRet);
+ return paramHasAttr(0, Attribute::StructRet);
}
/// Determine if any call argument is an aggregate passed by value.
bool hasByValArgument() const {
- return AttributeList.hasAttrSomewhere(Attribute::ByVal);
+ return Attrs.hasAttrSomewhere(Attribute::ByVal);
}
/// Return the function called, or null if this is an
@@ -3918,7 +3985,7 @@ private:
void setSuccessorV(unsigned idx, BasicBlock *B) override;
template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const {
- if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, Kind))
+ if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind))
return true;
// Operand bundles override attributes on the called function, but don't
@@ -3927,7 +3994,8 @@ private:
return false;
if (const Function *F = getCalledFunction())
- return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, Kind);
+ return F->getAttributes().hasAttribute(AttributeList::FunctionIndex,
+ Kind);
return false;
}
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index b14a54503e52..f69b5bfc0be2 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -152,6 +152,71 @@ namespace llvm {
}
};
+ /// This is the common base class for constrained floating point intrinsics.
+ class ConstrainedFPIntrinsic : public IntrinsicInst {
+ public:
+ enum RoundingMode {
+ rmInvalid,
+ rmDynamic,
+ rmToNearest,
+ rmDownward,
+ rmUpward,
+ rmTowardZero
+ };
+
+ enum ExceptionBehavior {
+ ebInvalid,
+ ebIgnore,
+ ebMayTrap,
+ ebStrict
+ };
+
+ RoundingMode getRoundingMode() const;
+ ExceptionBehavior getExceptionBehavior() const;
+
+ // Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const IntrinsicInst *I) {
+ switch (I->getIntrinsicID()) {
+ case Intrinsic::experimental_constrained_fadd:
+ case Intrinsic::experimental_constrained_fsub:
+ case Intrinsic::experimental_constrained_fmul:
+ case Intrinsic::experimental_constrained_fdiv:
+ case Intrinsic::experimental_constrained_frem:
+ return true;
+ default: return false;
+ }
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
+ /// This class represents atomic memcpy intrinsic
+ /// TODO: Integrate this class into MemIntrinsic hierarchy.
+ class ElementAtomicMemCpyInst : public IntrinsicInst {
+ public:
+ Value *getRawDest() const { return getArgOperand(0); }
+ Value *getRawSource() const { return getArgOperand(1); }
+
+ Value *getNumElements() const { return getArgOperand(2); }
+ void setNumElements(Value *V) { setArgOperand(2, V); }
+
+ uint64_t getSrcAlignment() const { return getParamAlignment(1); }
+ uint64_t getDstAlignment() const { return getParamAlignment(2); }
+
+ uint64_t getElementSizeInBytes() const {
+ Value *Arg = getArgOperand(3);
+ return cast<ConstantInt>(Arg)->getZExtValue();
+ }
+
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::memcpy_element_atomic;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ };
+
/// This is the common base class for memset/memcpy/memmove.
class MemIntrinsic : public IntrinsicInst {
public:
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index d07358445dab..2f6bdf8ecf19 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -28,7 +28,7 @@ class FunctionType;
class Function;
class LLVMContext;
class Module;
-class AttributeSet;
+class AttributeList;
/// This namespace contains an enum with a value for every intrinsic/builtin
/// function known by LLVM. The enum values are returned by
@@ -69,7 +69,7 @@ namespace Intrinsic {
bool isLeaf(ID id);
/// Return the attributes for an intrinsic.
- AttributeSet getAttributes(LLVMContext &C, ID id);
+ AttributeList getAttributes(LLVMContext &C, ID id);
/// Create or insert an LLVM Function declaration for an intrinsic, and return
/// it.
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 89ae94270888..309b21489224 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -331,13 +331,13 @@ def int_get_dynamic_area_offset : Intrinsic<[llvm_anyint_ty]>;
def int_thread_pointer : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>,
GCCBuiltin<"__builtin_thread_pointer">;
-// IntrArgMemOnly is more pessimistic than strictly necessary for prefetch,
-// however it does conveniently prevent the prefetch from being reordered
-// with respect to nearby accesses to the same memory.
-def int_prefetch : Intrinsic<[],
- [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty,
- llvm_i32_ty],
- [IntrArgMemOnly, NoCapture<0>]>;
+// IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly
+// necessary for prefetch, however it does conveniently prevent the prefetch
+// from being reordered overly much with respect to nearby access to the same
+// memory while not impeding optimization.
+def int_prefetch
+ : Intrinsic<[], [ llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ],
+ [ IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0> ]>;
def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
@@ -389,6 +389,9 @@ def int_memset : Intrinsic<[],
llvm_i32_ty, llvm_i1_ty],
[IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>;
+// FIXME: Add version of these floating point intrinsics which allow non-default
+// rounding modes and FP exception handling.
+
let IntrProperties = [IntrNoMem] in {
def int_fma : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -438,10 +441,44 @@ def int_sigsetjmp : Intrinsic<[llvm_i32_ty] , [llvm_ptr_ty, llvm_i32_ty]>;
def int_siglongjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>;
// Internal interface for object size checking
-def int_objectsize : Intrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty],
+def int_objectsize : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty],
[IntrNoMem]>,
GCCBuiltin<"__builtin_object_size">;
+//===--------------- Constrained Floating Point Intrinsics ----------------===//
+//
+
+let IntrProperties = [IntrInaccessibleMemOnly] in {
+ def int_experimental_constrained_fadd : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fsub : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fmul : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_fdiv : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_frem : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+}
+// FIXME: Add intrinsic for fcmp, fptrunc, fpext, fptoui and fptosi.
+
+
//===------------------------- Expect Intrinsics --------------------------===//
//
def int_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>,
@@ -565,10 +602,10 @@ def int_umul_with_overflow : Intrinsic<[llvm_anyint_ty, llvm_i1_ty],
//===------------------------- Memory Use Markers -------------------------===//
//
def int_lifetime_start : Intrinsic<[],
- [llvm_i64_ty, llvm_ptr_ty],
+ [llvm_i64_ty, llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<1>]>;
def int_lifetime_end : Intrinsic<[],
- [llvm_i64_ty, llvm_ptr_ty],
+ [llvm_i64_ty, llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<1>]>;
def int_invariant_start : Intrinsic<[llvm_descriptor_ty],
[llvm_i64_ty, llvm_anyptr_ty],
@@ -578,9 +615,16 @@ def int_invariant_end : Intrinsic<[],
llvm_anyptr_ty],
[IntrArgMemOnly, NoCapture<2>]>;
+// invariant.group.barrier can't be marked with 'readnone' (IntrNoMem),
+// because it would cause CSE of two barriers with the same argument.
+// Readonly and argmemonly says that barrier only reads its argument and
+// it can be CSE only if memory didn't change between 2 barriers call,
+// which is valid.
+// The argument also can't be marked with 'returned' attribute, because
+// it would remove barrier.
def int_invariant_group_barrier : Intrinsic<[llvm_ptr_ty],
[llvm_ptr_ty],
- [IntrNoMem]>;
+ [IntrReadMem, IntrArgMemOnly]>;
//===------------------------ Stackmap Intrinsics -------------------------===//
//
@@ -619,18 +663,18 @@ def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty],
// Coroutine Structure Intrinsics.
-def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty,
- llvm_ptr_ty, llvm_ptr_ty],
- [IntrArgMemOnly, IntrReadMem,
+def int_coro_id : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty,
+ llvm_ptr_ty, llvm_ptr_ty],
+ [IntrArgMemOnly, IntrReadMem,
ReadNone<1>, ReadOnly<2>, NoCapture<2>]>;
def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>;
def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
[WriteOnly<1>]>;
-def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly, ReadOnly<1>,
+def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty],
+ [IntrReadMem, IntrArgMemOnly, ReadOnly<1>,
NoCapture<1>]>;
-def int_coro_end : Intrinsic<[], [llvm_ptr_ty, llvm_i1_ty], []>;
+def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>;
def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>;
@@ -745,6 +789,10 @@ def int_memcpy_element_atomic : Intrinsic<[],
[IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
WriteOnly<0>, ReadOnly<1>]>;
+//===----- Intrinsics that are used to provide predicate information -----===//
+
+def int_ssa_copy : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>],
+ [IntrNoMem, Returned<0>]>;
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td
index dcec3860f2ca..5415c6b0d151 100644
--- a/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -64,6 +64,10 @@ def int_r600_recipsqrt_clamped : Intrinsic<
[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
>;
+def int_r600_cube : Intrinsic<
+ [llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]
+>;
+
} // End TargetPrefix = "r600"
let TargetPrefix = "amdgcn" in {
@@ -121,7 +125,8 @@ def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">,
def int_amdgcn_wave_barrier : GCCBuiltin<"__builtin_amdgcn_wave_barrier">,
Intrinsic<[], [], [IntrConvergent]>;
-def int_amdgcn_s_waitcnt : Intrinsic<[], [llvm_i32_ty], []>;
+def int_amdgcn_s_waitcnt : GCCBuiltin<"__builtin_amdgcn_s_waitcnt">,
+ Intrinsic<[], [llvm_i32_ty], []>;
def int_amdgcn_div_scale : Intrinsic<
// 1st parameter: Numerator
@@ -202,10 +207,19 @@ def int_amdgcn_fract : Intrinsic<
[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]
>;
+def int_amdgcn_cvt_pkrtz : Intrinsic<
+ [llvm_v2f16_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
+
def int_amdgcn_class : Intrinsic<
[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]
>;
+def int_amdgcn_fmed3 : GCCBuiltin<"__builtin_amdgcn_fmed3">,
+ Intrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]
+>;
+
def int_amdgcn_cubeid : GCCBuiltin<"__builtin_amdgcn_cubeid">,
Intrinsic<[llvm_float_ty],
[llvm_float_ty, llvm_float_ty, llvm_float_ty], [IntrNoMem]
@@ -231,17 +245,20 @@ def int_amdgcn_cubetc : GCCBuiltin<"__builtin_amdgcn_cubetc">,
def int_amdgcn_sffbh :
Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoMem]>;
-// TODO: Do we want an ordering for these?
-def int_amdgcn_atomic_inc : Intrinsic<[llvm_anyint_ty],
- [llvm_anyptr_ty, LLVMMatchType<0>],
- [IntrArgMemOnly, NoCapture<0>]
->;
-def int_amdgcn_atomic_dec : Intrinsic<[llvm_anyint_ty],
- [llvm_anyptr_ty, LLVMMatchType<0>],
+// Fields should mirror atomicrmw
+class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty],
+ [llvm_anyptr_ty,
+ LLVMMatchType<0>,
+ llvm_i32_ty, // ordering
+ llvm_i32_ty, // scope
+ llvm_i1_ty], // isVolatile
[IntrArgMemOnly, NoCapture<0>]
>;
+def int_amdgcn_atomic_inc : AMDGPUAtomicIncIntrin;
+def int_amdgcn_atomic_dec : AMDGPUAtomicIncIntrin;
+
class AMDGPUImageLoad : Intrinsic <
[llvm_anyfloat_ty], // vdata(VGPR)
[llvm_anyint_ty, // vaddr(VGPR)
@@ -451,6 +468,32 @@ def int_amdgcn_buffer_atomic_cmpswap : Intrinsic<
llvm_i1_ty], // slc(imm)
[]>;
+// Uses that do not set the done bit should set IntrWriteMem on the
+// call site.
+def int_amdgcn_exp : Intrinsic <[], [
+ llvm_i32_ty, // tgt,
+ llvm_i32_ty, // en
+ llvm_any_ty, // src0 (f32 or i32)
+ LLVMMatchType<0>, // src1
+ LLVMMatchType<0>, // src2
+ LLVMMatchType<0>, // src3
+ llvm_i1_ty, // done
+ llvm_i1_ty // vm
+ ],
+ []
+>;
+
+// exp with compr bit set.
+def int_amdgcn_exp_compr : Intrinsic <[], [
+ llvm_i32_ty, // tgt,
+ llvm_i32_ty, // en
+ llvm_anyvector_ty, // src0 (v2f16 or v2i16)
+ LLVMMatchType<0>, // src1
+ llvm_i1_ty, // done
+ llvm_i1_ty], // vm
+ []
+>;
+
def int_amdgcn_buffer_wbinvl1_sc :
GCCBuiltin<"__builtin_amdgcn_buffer_wbinvl1_sc">,
Intrinsic<[], [], []>;
@@ -530,7 +573,14 @@ def int_amdgcn_ds_swizzle :
GCCBuiltin<"__builtin_amdgcn_ds_swizzle">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
-// llvm.amdgcn.lerp
+def int_amdgcn_ubfe : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
+>;
+
+def int_amdgcn_sbfe : Intrinsic<[llvm_anyint_ty],
+ [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]
+>;
+
def int_amdgcn_lerp :
GCCBuiltin<"__builtin_amdgcn_lerp">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -619,10 +669,51 @@ def int_amdgcn_s_memrealtime :
// llvm.amdgcn.ds.permute <index> <src>
def int_amdgcn_ds_permute :
+ GCCBuiltin<"__builtin_amdgcn_ds_permute">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
// llvm.amdgcn.ds.bpermute <index> <src>
def int_amdgcn_ds_bpermute :
+ GCCBuiltin<"__builtin_amdgcn_ds_bpermute">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>;
+
+//===----------------------------------------------------------------------===//
+// Special Intrinsics for backend internal use only. No frontend
+// should emit calls to these.
+// ===----------------------------------------------------------------------===//
+def int_amdgcn_if : Intrinsic<[llvm_i1_ty, llvm_i64_ty],
+ [llvm_i1_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_else : Intrinsic<[llvm_i1_ty, llvm_i64_ty],
+ [llvm_i64_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_if_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i1_ty, llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_else_break : Intrinsic<[llvm_i64_ty],
+ [llvm_i64_ty, llvm_i64_ty], [IntrNoMem, IntrConvergent]
+>;
+
+def int_amdgcn_loop : Intrinsic<[llvm_i1_ty],
+ [llvm_i64_ty], [IntrConvergent]
+>;
+
+def int_amdgcn_end_cf : Intrinsic<[], [llvm_i64_ty], [IntrConvergent]>;
+
+// Represent unreachable in a divergent region.
+def int_amdgcn_unreachable : Intrinsic<[], [], [IntrConvergent]>;
+
+// Emit 2.5 ulp, no denormal division. Should only be inserted by
+// pass based on !fpmath metadata.
+def int_amdgcn_fdiv_fast : Intrinsic<
+ [llvm_float_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem]
+>;
}
diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td
index 24239689a62e..18ed24be56d4 100644
--- a/include/llvm/IR/IntrinsicsARM.td
+++ b/include/llvm/IR/IntrinsicsARM.td
@@ -67,7 +67,7 @@ def int_arm_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">,
// VFP
def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">,
- Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
+ Intrinsic<[llvm_i32_ty], [], []>;
def int_arm_set_fpscr : GCCBuiltin<"__builtin_arm_set_fpscr">,
Intrinsic<[], [llvm_i32_ty], []>;
def int_arm_vcvtr : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty],
diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td
index 6519f051deeb..8ac56e03be6a 100644
--- a/include/llvm/IR/IntrinsicsHexagon.td
+++ b/include/llvm/IR/IntrinsicsHexagon.td
@@ -5659,20 +5659,20 @@ class Hexagon_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
[IntrNoMem]>;
//
-// Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
-// tag : M6_vabsdiffb
-class Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+// Hexagon_vv64ivmemv512_Intrinsic<string GCCIntSuffix>
+// tag: V6_vS32b_qpred_ai
+class Hexagon_vv64ivmemv512_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty],
- [IntrNoMem]>;
+ [], [llvm_v512i1_ty,llvm_ptr_ty,llvm_v16i32_ty],
+ [IntrArgMemOnly]>;
//
-// Hexagon_LLii_Intrinsic<string GCCIntSuffix>
-// tag : S6_vsplatrbp
-class Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+// Hexagon_vv128ivmemv1024_Intrinsic<string GCCIntSuffix>
+// tag: V6_vS32b_qpred_ai_128B
+class Hexagon_vv128ivmemv1024_Intrinsic<string GCCIntSuffix>
: Hexagon_Intrinsic<GCCIntSuffix,
- [llvm_i64_ty], [llvm_i32_ty],
- [IntrNoMem]>;
+ [], [llvm_v1024i1_ty,llvm_ptr_ty,llvm_v32i32_ty],
+ [IntrArgMemOnly]>;
//
// BUILTIN_INFO(HEXAGON.S6_rol_i_r,SI_ftype_SISI,2)
@@ -9343,6 +9343,303 @@ def int_hexagon_V6_vlutvwh_oracc_128B :
Hexagon_v2048v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_oracc_128B">;
//
+// Masked vector stores
+//
+def int_hexagon_V6_vmaskedstoreq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstoreq">;
+
+def int_hexagon_V6_vmaskedstorenq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorenq">;
+
+def int_hexagon_V6_vmaskedstorentq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorentq">;
+
+def int_hexagon_V6_vmaskedstorentnq :
+Hexagon_vv64ivmemv512_Intrinsic<"HEXAGON_V6_vmaskedstorentnq">;
+
+def int_hexagon_V6_vmaskedstoreq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstoreq_128B">;
+
+def int_hexagon_V6_vmaskedstorenq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorenq_128B">;
+
+def int_hexagon_V6_vmaskedstorentq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentq_128B">;
+
+def int_hexagon_V6_vmaskedstorentnq_128B :
+Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentnq_128B">;
+
+
+///
+/// HexagonV62 intrinsics
+///
+
+//
+// Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+// tag : M6_vabsdiffb
+class Hexagon_LLiLLiLLi_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_i64_ty], [llvm_i64_ty,llvm_i64_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+// tag : S6_vsplatrbp
+class Hexagon_LLii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_i64_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlsrb
+class Hexagon_V62_v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlsrb_128B
+class Hexagon_V62_v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vasrwuhrndsat
+class Hexagon_V62_v512v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vasrwuhrndsat_128B
+class Hexagon_V62_v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vrounduwuh
+class Hexagon_V62_v512v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vrounduwuh_128B
+class Hexagon_V62_v1024v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v2048_Intrinsic<string GCCIntSuffix>
+// tag : V6_vadduwsat_dv_128B
+class Hexagon_V62_v2048v2048v2048_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vaddhw_acc
+class Hexagon_V62_v1024v1024v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vaddhw_acc_128B
+class Hexagon_V62_v2048v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v512v512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpyewuh_64
+class Hexagon_V62_v1024v512v512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpyewuh_64_128B
+class Hexagon_V62_v2048v1024v1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpauhb_128B
+class Hexagon_V62_v2048v2048i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v2048i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vmpauhb_acc_128B
+class Hexagon_V62_v2048v2048v2048i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v64i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt
+class Hexagon_V62_v512v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v512i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_128B
+class Hexagon_V62_v1024v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v1024i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_acc
+class Hexagon_V62_v512v512v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v512i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandnqrt_acc_128B
+class Hexagon_V62_v1024v1024v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v1024i1_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v64iv512_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandvqv
+class Hexagon_V62_v512v64iv512_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v512i1_ty,llvm_v16i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v128iv1024_Intrinsic<string GCCIntSuffix>
+// tag : V6_vandvqv_128B
+class Hexagon_V62_v1024v128iv1024_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v1024i1_ty,llvm_v32i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v64ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_pred_scalar2v2
+class Hexagon_V62_v64ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v512i1_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v128ii_Intrinsic<string GCCIntSuffix>
+// tag : V6_pred_scalar2v2_128B
+class Hexagon_V62_v128ii_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v1024i1_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v64iv64iv64i_Intrinsic<string GCCIntSuffix>
+// tag : V6_shuffeqw
+class Hexagon_V62_v64iv64iv64i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v512i1_ty], [llvm_v512i1_ty,llvm_v512i1_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v128iv128iv128i_Intrinsic<string GCCIntSuffix>
+// tag : V6_shuffeqw_128B
+class Hexagon_V62_v128iv128iv128i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v1024i1_ty], [llvm_v1024i1_ty,llvm_v1024i1_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_lvsplath
+class Hexagon_V62_v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_lvsplath_128B
+class Hexagon_V62_v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v512v512v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvvb_oracci
+class Hexagon_V62_v512v512v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v16i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvvb_oracci_128B
+class Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwhi
+class Hexagon_V62_v1024v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwhi_128B
+class Hexagon_V62_v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v1024v1024v512v512i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwh_oracci
+class Hexagon_V62_v1024v1024v512v512i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v32i32_ty], [llvm_v32i32_ty,llvm_v16i32_ty,llvm_v16i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+//
+// Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+// tag : V6_vlutvwh_oracci_128B
+class Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<string GCCIntSuffix>
+ : Hexagon_Intrinsic<GCCIntSuffix,
+ [llvm_v64i32_ty], [llvm_v64i32_ty,llvm_v32i32_ty,llvm_v32i32_ty,llvm_i32_ty],
+ [IntrNoMem]>;
+
+
+//
// BUILTIN_INFO(HEXAGON.M6_vabsdiffb,DI_ftype_DIDI,2)
// tag : M6_vabsdiffb
def int_hexagon_M6_vabsdiffb :
@@ -9355,12 +9652,6 @@ def int_hexagon_M6_vabsdiffub :
Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_M6_vabsdiffub">;
//
-// BUILTIN_INFO(HEXAGON.S6_vsplatrbp,DI_ftype_SI,1)
-// tag : S6_vsplatrbp
-def int_hexagon_S6_vsplatrbp :
-Hexagon_LLii_Intrinsic<"HEXAGON_S6_vsplatrbp">;
-
-//
// BUILTIN_INFO(HEXAGON.S6_vtrunehb_ppp,DI_ftype_DIDI,2)
// tag : S6_vtrunehb_ppp
def int_hexagon_S6_vtrunehb_ppp :
@@ -9371,3 +9662,550 @@ Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_S6_vtrunehb_ppp">;
// tag : S6_vtrunohb_ppp
def int_hexagon_S6_vtrunohb_ppp :
Hexagon_LLiLLiLLi_Intrinsic<"HEXAGON_S6_vtrunohb_ppp">;
+
+//
+// BUILTIN_INFO(HEXAGON.S6_vsplatrbp,DI_ftype_SI,1)
+// tag : S6_vsplatrbp
+def int_hexagon_S6_vsplatrbp :
+Hexagon_LLii_Intrinsic<"HEXAGON_S6_vsplatrbp">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlsrb,VI_ftype_VISI,2)
+// tag : V6_vlsrb
+def int_hexagon_V6_vlsrb :
+Hexagon_V62_v512v512i_Intrinsic<"HEXAGON_V6_vlsrb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlsrb_128B,VI_ftype_VISI,2)
+// tag : V6_vlsrb_128B
+def int_hexagon_V6_vlsrb_128B :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vlsrb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrwuhrndsat,VI_ftype_VIVISI,3)
+// tag : V6_vasrwuhrndsat
+def int_hexagon_V6_vasrwuhrndsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasrwuhrndsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrwuhrndsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasrwuhrndsat_128B
+def int_hexagon_V6_vasrwuhrndsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasrwuhrndsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasruwuhrndsat,VI_ftype_VIVISI,3)
+// tag : V6_vasruwuhrndsat
+def int_hexagon_V6_vasruwuhrndsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasruwuhrndsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasruwuhrndsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasruwuhrndsat_128B
+def int_hexagon_V6_vasruwuhrndsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasruwuhrndsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrhbsat,VI_ftype_VIVISI,3)
+// tag : V6_vasrhbsat
+def int_hexagon_V6_vasrhbsat :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vasrhbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vasrhbsat_128B,VI_ftype_VIVISI,3)
+// tag : V6_vasrhbsat_128B
+def int_hexagon_V6_vasrhbsat_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vasrhbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduwuh,VI_ftype_VIVI,2)
+// tag : V6_vrounduwuh
+def int_hexagon_V6_vrounduwuh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vrounduwuh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduwuh_128B,VI_ftype_VIVI,2)
+// tag : V6_vrounduwuh_128B
+def int_hexagon_V6_vrounduwuh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vrounduwuh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduhub,VI_ftype_VIVI,2)
+// tag : V6_vrounduhub
+def int_hexagon_V6_vrounduhub :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vrounduhub">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vrounduhub_128B,VI_ftype_VIVI,2)
+// tag : V6_vrounduhub_128B
+def int_hexagon_V6_vrounduhub_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vrounduhub_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat,VI_ftype_VIVI,2)
+// tag : V6_vadduwsat
+def int_hexagon_V6_vadduwsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vadduwsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vadduwsat_128B
+def int_hexagon_V6_vadduwsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vadduwsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vadduwsat_dv
+def int_hexagon_V6_vadduwsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vadduwsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduwsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vadduwsat_dv_128B
+def int_hexagon_V6_vadduwsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vadduwsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat,VI_ftype_VIVI,2)
+// tag : V6_vsubuwsat
+def int_hexagon_V6_vsubuwsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubuwsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubuwsat_128B
+def int_hexagon_V6_vsubuwsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubuwsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vsubuwsat_dv
+def int_hexagon_V6_vsubuwsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubuwsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubuwsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vsubuwsat_dv_128B
+def int_hexagon_V6_vsubuwsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vsubuwsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat,VI_ftype_VIVI,2)
+// tag : V6_vaddbsat
+def int_hexagon_V6_vaddbsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddbsat_128B
+def int_hexagon_V6_vaddbsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vaddbsat_dv
+def int_hexagon_V6_vaddbsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddbsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddbsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vaddbsat_dv_128B
+def int_hexagon_V6_vaddbsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vaddbsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat,VI_ftype_VIVI,2)
+// tag : V6_vsubbsat
+def int_hexagon_V6_vsubbsat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubbsat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubbsat_128B
+def int_hexagon_V6_vsubbsat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubbsat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_dv,VD_ftype_VDVD,2)
+// tag : V6_vsubbsat_dv
+def int_hexagon_V6_vsubbsat_dv :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubbsat_dv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubbsat_dv_128B,VD_ftype_VDVD,2)
+// tag : V6_vsubbsat_dv_128B
+def int_hexagon_V6_vsubbsat_dv_128B :
+Hexagon_V62_v2048v2048v2048_Intrinsic<"HEXAGON_V6_vsubbsat_dv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddububb_sat,VI_ftype_VIVI,2)
+// tag : V6_vaddububb_sat
+def int_hexagon_V6_vaddububb_sat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddububb_sat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddububb_sat_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddububb_sat_128B
+def int_hexagon_V6_vaddububb_sat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddububb_sat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubububb_sat,VI_ftype_VIVI,2)
+// tag : V6_vsubububb_sat
+def int_hexagon_V6_vsubububb_sat :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsubububb_sat">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsubububb_sat_128B,VI_ftype_VIVI,2)
+// tag : V6_vsubububb_sat_128B
+def int_hexagon_V6_vsubububb_sat_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsubububb_sat_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddhw_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vaddhw_acc
+def int_hexagon_V6_vaddhw_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vaddhw_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddhw_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vaddhw_acc_128B
+def int_hexagon_V6_vaddhw_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vaddhw_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduhw_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vadduhw_acc
+def int_hexagon_V6_vadduhw_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vadduhw_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vadduhw_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vadduhw_acc_128B
+def int_hexagon_V6_vadduhw_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vadduhw_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddubh_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vaddubh_acc
+def int_hexagon_V6_vaddubh_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vaddubh_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddubh_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vaddubh_acc_128B
+def int_hexagon_V6_vaddubh_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vaddubh_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyewuh_64,VD_ftype_VIVI,2)
+// tag : V6_vmpyewuh_64
+def int_hexagon_V6_vmpyewuh_64 :
+Hexagon_V62_v1024v512v512_Intrinsic<"HEXAGON_V6_vmpyewuh_64">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyewuh_64_128B,VD_ftype_VIVI,2)
+// tag : V6_vmpyewuh_64_128B
+def int_hexagon_V6_vmpyewuh_64_128B :
+Hexagon_V62_v2048v1024v1024_Intrinsic<"HEXAGON_V6_vmpyewuh_64_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyowh_64_acc,VD_ftype_VDVIVI,3)
+// tag : V6_vmpyowh_64_acc
+def int_hexagon_V6_vmpyowh_64_acc :
+Hexagon_V62_v1024v1024v512v512_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyowh_64_acc_128B,VD_ftype_VDVIVI,3)
+// tag : V6_vmpyowh_64_acc_128B
+def int_hexagon_V6_vmpyowh_64_acc_128B :
+Hexagon_V62_v2048v2048v1024v1024_Intrinsic<"HEXAGON_V6_vmpyowh_64_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb,VD_ftype_VDSI,2)
+// tag : V6_vmpauhb
+def int_hexagon_V6_vmpauhb :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vmpauhb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_128B,VD_ftype_VDSI,2)
+// tag : V6_vmpauhb_128B
+def int_hexagon_V6_vmpauhb_128B :
+Hexagon_V62_v2048v2048i_Intrinsic<"HEXAGON_V6_vmpauhb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_acc,VD_ftype_VDVDSI,3)
+// tag : V6_vmpauhb_acc
+def int_hexagon_V6_vmpauhb_acc :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vmpauhb_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpauhb_acc_128B,VD_ftype_VDVDSI,3)
+// tag : V6_vmpauhb_acc_128B
+def int_hexagon_V6_vmpauhb_acc_128B :
+Hexagon_V62_v2048v2048v2048i_Intrinsic<"HEXAGON_V6_vmpauhb_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub,VI_ftype_VISI,2)
+// tag : V6_vmpyiwub
+def int_hexagon_V6_vmpyiwub :
+Hexagon_V62_v512v512i_Intrinsic<"HEXAGON_V6_vmpyiwub">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_128B,VI_ftype_VISI,2)
+// tag : V6_vmpyiwub_128B
+def int_hexagon_V6_vmpyiwub_128B :
+Hexagon_V62_v1024v1024i_Intrinsic<"HEXAGON_V6_vmpyiwub_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_acc,VI_ftype_VIVISI,3)
+// tag : V6_vmpyiwub_acc
+def int_hexagon_V6_vmpyiwub_acc :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vmpyiwub_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmpyiwub_acc_128B,VI_ftype_VIVISI,3)
+// tag : V6_vmpyiwub_acc_128B
+def int_hexagon_V6_vmpyiwub_acc_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vmpyiwub_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt,VI_ftype_QVSI,2)
+// tag : V6_vandnqrt
+def int_hexagon_V6_vandnqrt :
+Hexagon_V62_v512v64ii_Intrinsic<"HEXAGON_V6_vandnqrt">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_128B,VI_ftype_QVSI,2)
+// tag : V6_vandnqrt_128B
+def int_hexagon_V6_vandnqrt_128B :
+Hexagon_V62_v1024v128ii_Intrinsic<"HEXAGON_V6_vandnqrt_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_acc,VI_ftype_VIQVSI,3)
+// tag : V6_vandnqrt_acc
+def int_hexagon_V6_vandnqrt_acc :
+Hexagon_V62_v512v512v64ii_Intrinsic<"HEXAGON_V6_vandnqrt_acc">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandnqrt_acc_128B,VI_ftype_VIQVSI,3)
+// tag : V6_vandnqrt_acc_128B
+def int_hexagon_V6_vandnqrt_acc_128B :
+Hexagon_V62_v1024v1024v128ii_Intrinsic<"HEXAGON_V6_vandnqrt_acc_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvqv,VI_ftype_QVVI,2)
+// tag : V6_vandvqv
+def int_hexagon_V6_vandvqv :
+Hexagon_V62_v512v64iv512_Intrinsic<"HEXAGON_V6_vandvqv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvqv_128B,VI_ftype_QVVI,2)
+// tag : V6_vandvqv_128B
+def int_hexagon_V6_vandvqv_128B :
+Hexagon_V62_v1024v128iv1024_Intrinsic<"HEXAGON_V6_vandvqv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvnqv,VI_ftype_QVVI,2)
+// tag : V6_vandvnqv
+def int_hexagon_V6_vandvnqv :
+Hexagon_V62_v512v64iv512_Intrinsic<"HEXAGON_V6_vandvnqv">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vandvnqv_128B,VI_ftype_QVVI,2)
+// tag : V6_vandvnqv_128B
+def int_hexagon_V6_vandvnqv_128B :
+Hexagon_V62_v1024v128iv1024_Intrinsic<"HEXAGON_V6_vandvnqv_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_pred_scalar2v2,QV_ftype_SI,1)
+// tag : V6_pred_scalar2v2
+def int_hexagon_V6_pred_scalar2v2 :
+Hexagon_V62_v64ii_Intrinsic<"HEXAGON_V6_pred_scalar2v2">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_pred_scalar2v2_128B,QV_ftype_SI,1)
+// tag : V6_pred_scalar2v2_128B
+def int_hexagon_V6_pred_scalar2v2_128B :
+Hexagon_V62_v128ii_Intrinsic<"HEXAGON_V6_pred_scalar2v2_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqw,QV_ftype_QVQV,2)
+// tag : V6_shuffeqw
+def int_hexagon_V6_shuffeqw :
+Hexagon_V62_v64iv64iv64i_Intrinsic<"HEXAGON_V6_shuffeqw">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqw_128B,QV_ftype_QVQV,2)
+// tag : V6_shuffeqw_128B
+def int_hexagon_V6_shuffeqw_128B :
+Hexagon_V62_v128iv128iv128i_Intrinsic<"HEXAGON_V6_shuffeqw_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqh,QV_ftype_QVQV,2)
+// tag : V6_shuffeqh
+def int_hexagon_V6_shuffeqh :
+Hexagon_V62_v64iv64iv64i_Intrinsic<"HEXAGON_V6_shuffeqh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_shuffeqh_128B,QV_ftype_QVQV,2)
+// tag : V6_shuffeqh_128B
+def int_hexagon_V6_shuffeqh_128B :
+Hexagon_V62_v128iv128iv128i_Intrinsic<"HEXAGON_V6_shuffeqh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmaxb,VI_ftype_VIVI,2)
+// tag : V6_vmaxb
+def int_hexagon_V6_vmaxb :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vmaxb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vmaxb_128B,VI_ftype_VIVI,2)
+// tag : V6_vmaxb_128B
+def int_hexagon_V6_vmaxb_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vmaxb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vminb,VI_ftype_VIVI,2)
+// tag : V6_vminb
+def int_hexagon_V6_vminb :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vminb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vminb_128B,VI_ftype_VIVI,2)
+// tag : V6_vminb_128B
+def int_hexagon_V6_vminb_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vminb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsatuwuh,VI_ftype_VIVI,2)
+// tag : V6_vsatuwuh
+def int_hexagon_V6_vsatuwuh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vsatuwuh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vsatuwuh_128B,VI_ftype_VIVI,2)
+// tag : V6_vsatuwuh_128B
+def int_hexagon_V6_vsatuwuh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vsatuwuh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplath,VI_ftype_SI,1)
+// tag : V6_lvsplath
+def int_hexagon_V6_lvsplath :
+Hexagon_V62_v512i_Intrinsic<"HEXAGON_V6_lvsplath">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplath_128B,VI_ftype_SI,1)
+// tag : V6_lvsplath_128B
+def int_hexagon_V6_lvsplath_128B :
+Hexagon_V62_v1024i_Intrinsic<"HEXAGON_V6_lvsplath_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplatb,VI_ftype_SI,1)
+// tag : V6_lvsplatb
+def int_hexagon_V6_lvsplatb :
+Hexagon_V62_v512i_Intrinsic<"HEXAGON_V6_lvsplatb">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_lvsplatb_128B,VI_ftype_SI,1)
+// tag : V6_lvsplatb_128B
+def int_hexagon_V6_lvsplatb_128B :
+Hexagon_V62_v1024i_Intrinsic<"HEXAGON_V6_lvsplatb_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbw,VI_ftype_VIVI,2)
+// tag : V6_vaddclbw
+def int_hexagon_V6_vaddclbw :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddclbw">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbw_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddclbw_128B
+def int_hexagon_V6_vaddclbw_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddclbw_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbh,VI_ftype_VIVI,2)
+// tag : V6_vaddclbh
+def int_hexagon_V6_vaddclbh :
+Hexagon_V62_v512v512v512_Intrinsic<"HEXAGON_V6_vaddclbh">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vaddclbh_128B,VI_ftype_VIVI,2)
+// tag : V6_vaddclbh_128B
+def int_hexagon_V6_vaddclbh_128B :
+Hexagon_V62_v1024v1024v1024_Intrinsic<"HEXAGON_V6_vaddclbh_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvbi,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvbi
+def int_hexagon_V6_vlutvvbi :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvbi">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvbi_128B,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvbi_128B
+def int_hexagon_V6_vlutvvbi_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvbi_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_oracci,VI_ftype_VIVIVISI,4)
+// tag : V6_vlutvvb_oracci
+def int_hexagon_V6_vlutvvb_oracci :
+Hexagon_V62_v512v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvb_oracci">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_oracci_128B,VI_ftype_VIVIVISI,4)
+// tag : V6_vlutvvb_oracci_128B
+def int_hexagon_V6_vlutvvb_oracci_128B :
+Hexagon_V62_v1024v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvb_oracci_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwhi,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwhi
+def int_hexagon_V6_vlutvwhi :
+Hexagon_V62_v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwhi">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwhi_128B,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwhi_128B
+def int_hexagon_V6_vlutvwhi_128B :
+Hexagon_V62_v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwhi_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_oracci,VD_ftype_VDVIVISI,4)
+// tag : V6_vlutvwh_oracci
+def int_hexagon_V6_vlutvwh_oracci :
+Hexagon_V62_v1024v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwh_oracci">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_oracci_128B,VD_ftype_VDVIVISI,4)
+// tag : V6_vlutvwh_oracci_128B
+def int_hexagon_V6_vlutvwh_oracci_128B :
+Hexagon_V62_v2048v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_oracci_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_nm,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvb_nm
+def int_hexagon_V6_vlutvvb_nm :
+Hexagon_V62_v512v512v512i_Intrinsic<"HEXAGON_V6_vlutvvb_nm">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvvb_nm_128B,VI_ftype_VIVISI,3)
+// tag : V6_vlutvvb_nm_128B
+def int_hexagon_V6_vlutvvb_nm_128B :
+Hexagon_V62_v1024v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvvb_nm_128B">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_nm,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwh_nm
+def int_hexagon_V6_vlutvwh_nm :
+Hexagon_V62_v1024v512v512i_Intrinsic<"HEXAGON_V6_vlutvwh_nm">;
+
+//
+// BUILTIN_INFO(HEXAGON.V6_vlutvwh_nm_128B,VD_ftype_VIVISI,3)
+// tag : V6_vlutvwh_nm_128B
+def int_hexagon_V6_vlutvwh_nm_128B :
+Hexagon_V62_v2048v1024v1024i_Intrinsic<"HEXAGON_V6_vlutvwh_nm_128B">;
+
diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td
index f035ac3c90ee..68f123df0430 100644
--- a/include/llvm/IR/IntrinsicsNVVM.td
+++ b/include/llvm/IR/IntrinsicsNVVM.td
@@ -11,6 +11,27 @@
//
//===----------------------------------------------------------------------===//
+// The following intrinsics were once defined here, but are now auto-upgraded
+// to target-generic LLVM intrinsics.
+//
+// * llvm.nvvm.brev32 --> llvm.bitreverse.i32
+// * llvm.nvvm.brev64 --> llvm.bitreverse.i64
+// * llvm.nvvm.clz.i --> llvm.ctlz.i32
+// * llvm.nvvm.clz.ll --> trunc i64 llvm.ctlz.i64(x) to i32
+// * llvm.nvvm.popc.i --> llvm.ctpop.i32
+// * llvm.nvvm.popc.ll --> trunc i64 llvm.ctpop.i64 to i32
+// * llvm.nvvm.abs.i --> select(x >= -x, x, -x)
+// * llvm.nvvm.abs.ll --> ibid.
+// * llvm.nvvm.max.i --> select(x sge y, x, y)
+// * llvm.nvvm.max.ll --> ibid.
+// * llvm.nvvm.max.ui --> select(x uge y, x, y)
+// * llvm.nvvm.max.ull --> ibid.
+// * llvm.nvvm.max.i --> select(x sle y, x, y)
+// * llvm.nvvm.max.ll --> ibid.
+// * llvm.nvvm.max.ui --> select(x ule y, x, y)
+// * llvm.nvvm.max.ull --> ibid.
+// * llvm.nvvm.h2f --> llvm.convert.to.fp16.f32
+
def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
//
@@ -18,16 +39,6 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
//
let TargetPrefix = "nvvm" in {
- def int_nvvm_clz_i : GCCBuiltin<"__nvvm_clz_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_clz_ll : GCCBuiltin<"__nvvm_clz_ll">,
- Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>;
-
- def int_nvvm_popc_i : GCCBuiltin<"__nvvm_popc_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_popc_ll : GCCBuiltin<"__nvvm_popc_ll">,
- Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem]>;
-
def int_nvvm_prmt : GCCBuiltin<"__nvvm_prmt">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, Commutative]>;
@@ -36,34 +47,6 @@ let TargetPrefix = "nvvm" in {
// Min Max
//
- def int_nvvm_min_i : GCCBuiltin<"__nvvm_min_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_min_ui : GCCBuiltin<"__nvvm_min_ui">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_min_ll : GCCBuiltin<"__nvvm_min_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_min_ull : GCCBuiltin<"__nvvm_min_ull">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_max_i : GCCBuiltin<"__nvvm_max_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_max_ui : GCCBuiltin<"__nvvm_max_ui">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
- [IntrNoMem, Commutative]>;
-
- def int_nvvm_max_ll : GCCBuiltin<"__nvvm_max_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
- def int_nvvm_max_ull : GCCBuiltin<"__nvvm_max_ull">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
- [IntrNoMem, Commutative]>;
-
def int_nvvm_fmin_f : GCCBuiltin<"__nvvm_fmin_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty],
[IntrNoMem, Commutative]>;
@@ -201,15 +184,6 @@ let TargetPrefix = "nvvm" in {
[IntrNoMem, Commutative]>;
//
-// Brev
-//
-
- def int_nvvm_brev32 : GCCBuiltin<"__nvvm_brev32">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_brev64 : GCCBuiltin<"__nvvm_brev64">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
-
-//
// Sad
//
@@ -242,16 +216,10 @@ let TargetPrefix = "nvvm" in {
// Abs
//
- def int_nvvm_abs_i : GCCBuiltin<"__nvvm_abs_i">,
- Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_nvvm_abs_ll : GCCBuiltin<"__nvvm_abs_ll">,
- Intrinsic<[llvm_i64_ty], [llvm_i64_ty], [IntrNoMem]>;
-
def int_nvvm_fabs_ftz_f : GCCBuiltin<"__nvvm_fabs_ftz_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
def int_nvvm_fabs_f : GCCBuiltin<"__nvvm_fabs_f">,
Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
-
def int_nvvm_fabs_d : GCCBuiltin<"__nvvm_fabs_d">,
Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
@@ -700,9 +668,6 @@ let TargetPrefix = "nvvm" in {
def int_nvvm_f2h_rn : GCCBuiltin<"__nvvm_f2h_rn">,
Intrinsic<[llvm_i16_ty], [llvm_float_ty], [IntrNoMem]>;
- def int_nvvm_h2f : GCCBuiltin<"__nvvm_h2f">,
- Intrinsic<[llvm_float_ty], [llvm_i16_ty], [IntrNoMem]>;
-
//
// Bitcast
//
@@ -768,6 +733,13 @@ let TargetPrefix = "nvvm" in {
// intrinsics in this file, this one is a user-facing API.
def int_nvvm_barrier0 : GCCBuiltin<"__syncthreads">,
Intrinsic<[], [], [IntrConvergent]>;
+ // Synchronize all threads in the CTA at barrier 'n'.
+ def int_nvvm_barrier_n : GCCBuiltin<"__nvvm_bar_n">,
+ Intrinsic<[], [llvm_i32_ty], [IntrConvergent]>;
+ // Synchronize 'm', a multiple of warp size, (arg 2) threads in
+ // the CTA at barrier 'n' (arg 1).
+ def int_nvvm_barrier : GCCBuiltin<"__nvvm_bar">,
+ Intrinsic<[], [llvm_i32_ty, llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrConvergent]>;
def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">,
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 12e23b681ca4..64240a929782 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -203,19 +203,19 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
// source address with a single pointer.
def int_ppc_altivec_stvx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvxl :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvebx :
Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvehx :
Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_altivec_stvewx :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
// Comparisons setting a vector.
def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">,
@@ -749,20 +749,20 @@ def int_ppc_vsx_lxvll :
IntrArgMemOnly]>;
def int_ppc_vsx_stxvl :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
def int_ppc_vsx_stxvll :
Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty, llvm_i64_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
// Vector store.
-def int_ppc_vsx_stxvw4x :
- Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvd2x :
- Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvw4x_be :
- Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
-def int_ppc_vsx_stxvd2x_be :
- Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrArgMemOnly]>;
+def int_ppc_vsx_stxvw4x : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvd2x : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvw4x_be : Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
+def int_ppc_vsx_stxvd2x_be : Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty],
+ [IntrWriteMem, IntrArgMemOnly]>;
// Vector and scalar maximum.
def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">;
def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">;
@@ -953,7 +953,7 @@ class PowerPC_QPX_LoadPerm_Intrinsic<string GCCIntSuffix>
class PowerPC_QPX_Store_Intrinsic<string GCCIntSuffix>
: PowerPC_QPX_Intrinsic<GCCIntSuffix,
[], [llvm_v4f64_ty, llvm_ptr_ty],
- [IntrArgMemOnly]>;
+ [IntrWriteMem, IntrArgMemOnly]>;
//===----------------------------------------------------------------------===//
// PowerPC QPX Intrinsic Definitions.
diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td
index 4234c466d973..3a0957dfa39b 100644
--- a/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -17,6 +17,6 @@ let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.".
// Note that current_memory is not IntrNoMem because it must be sequenced with
// respect to grow_memory calls.
def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>;
-def int_wasm_grow_memory : Intrinsic<[], [llvm_anyint_ty], []>;
+def int_wasm_grow_memory : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], []>;
}
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 85966af9c820..97c756cf4b60 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -785,12 +785,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
[IntrNoMem, Commutative]>;
}
-// Cacheability support ops
-let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">,
- Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
-}
-
// Test instruction with bitwise comparison.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_ptestz : GCCBuiltin<"__builtin_ia32_ptestz128">,
@@ -2346,8 +2340,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
llvm_i8_ty], [IntrNoMem, Commutative]>;
- def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -3033,17 +3025,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_xop_vfrcz_ps_256 : GCCBuiltin<"__builtin_ia32_vfrczps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>;
- def int_x86_xop_vpcmov :
- GCCBuiltin<"__builtin_ia32_vpcmov">,
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty],
- [IntrNoMem]>;
- def int_x86_xop_vpcmov_256 :
- GCCBuiltin<"__builtin_ia32_vpcmov_256">,
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty],
- [IntrNoMem]>;
-
def int_x86_xop_vpcomb : GCCBuiltin<"__builtin_ia32_vpcomb">,
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,
llvm_i8_ty], [IntrNoMem]>;
@@ -3881,74 +3862,22 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_cvtq2mask_512 : GCCBuiltin<"__builtin_ia32_cvtq2mask512">,
Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_128 : GCCBuiltin<"__builtin_ia32_cvtmask2b128">,
- Intrinsic<[llvm_v16i8_ty], [llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_256 : GCCBuiltin<"__builtin_ia32_cvtmask2b256">,
- Intrinsic<[llvm_v32i8_ty], [llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2b_512 : GCCBuiltin<"__builtin_ia32_cvtmask2b512">,
- Intrinsic<[llvm_v64i8_ty], [llvm_i64_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2w_128 : GCCBuiltin<"__builtin_ia32_cvtmask2w128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2w_256 : GCCBuiltin<"__builtin_ia32_cvtmask2w256">,
- Intrinsic<[llvm_v16i16_ty], [llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2w_512 : GCCBuiltin<"__builtin_ia32_cvtmask2w512">,
- Intrinsic<[llvm_v32i16_ty], [llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2d_128 : GCCBuiltin<"__builtin_ia32_cvtmask2d128">,
- Intrinsic<[llvm_v4i32_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2d_256 : GCCBuiltin<"__builtin_ia32_cvtmask2d256">,
- Intrinsic<[llvm_v8i32_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2d_512 : GCCBuiltin<"__builtin_ia32_cvtmask2d512">,
- Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>;
-
- def int_x86_avx512_cvtmask2q_128 : GCCBuiltin<"__builtin_ia32_cvtmask2q128">,
- Intrinsic<[llvm_v2i64_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2q_256 : GCCBuiltin<"__builtin_ia32_cvtmask2q256">,
- Intrinsic<[llvm_v4i64_ty], [llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_cvtmask2q_512 : GCCBuiltin<"__builtin_ia32_cvtmask2q512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_i8_ty], [IntrNoMem]>;
-
}
// Pack ops.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
- def int_x86_avx512_mask_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
- llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packsswb_256 : GCCBuiltin<"__builtin_ia32_packsswb256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
- llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
- llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packssdw_256 : GCCBuiltin<"__builtin_ia32_packssdw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128_mask">,
- Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty,
- llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packuswb_256 : GCCBuiltin<"__builtin_ia32_packuswb256_mask">,
- Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty,
- llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">,
- Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty,
- llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packusdw_256 : GCCBuiltin<"__builtin_ia32_packusdw256_mask">,
- Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512_mask">,
- Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
- llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512">,
+ Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512">,
+ Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty],
+ [IntrNoMem]>;
}
// Vector convert
@@ -4595,39 +4524,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_ps_128 : GCCBuiltin<"__builtin_ia32_maxps_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_pd_128 : GCCBuiltin<"__builtin_ia32_maxpd_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
- llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_ps_128 : GCCBuiltin<"__builtin_ia32_minps_mask">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
- llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256_mask">,
- Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">,
Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_pd_128 : GCCBuiltin<"__builtin_ia32_minpd_mask">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
- llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>;
- def int_x86_avx512_mask_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256_mask">,
- Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
- llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
@@ -5481,32 +5386,6 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
-
- def int_x86_avx512_mask_lzcnt_d_128 :
- Intrinsic<[llvm_v4i32_ty],
- [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_d_256 :
- Intrinsic<[llvm_v8i32_ty],
- [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_d_512 :
- Intrinsic<[llvm_v16i32_ty],
- [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
-
- def int_x86_avx512_mask_lzcnt_q_128 :
- Intrinsic<[llvm_v2i64_ty],
- [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_q_256 :
- Intrinsic<[llvm_v4i64_ty],
- [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_lzcnt_q_512 :
- Intrinsic<[llvm_v8i64_ty],
- [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
}
// Compares
@@ -6458,10 +6337,6 @@ let TargetPrefix = "x86" in {
GCCBuiltin<"__builtin_ia32_cmpsd_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_movntdqa :
- GCCBuiltin<"__builtin_ia32_movntdqa512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -6495,3 +6370,10 @@ let TargetPrefix = "x86" in {
: GCCBuiltin<"__builtin_ia32_mwaitx">,
Intrinsic<[], [ llvm_i32_ty, llvm_i32_ty, llvm_i32_ty ], []>;
}
+
+//===----------------------------------------------------------------------===//
+// Cache-line zero
+let TargetPrefix = "x86" in {
+ def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">,
+ Intrinsic<[], [llvm_ptr_ty], []>;
+}
diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h
index 7f43d5df3c3f..d13d5ddaeb3c 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -78,6 +78,7 @@ public:
MD_type = 19, // "type"
MD_section_prefix = 20, // "section_prefix"
MD_absolute_symbol = 21, // "absolute_symbol"
+ MD_associated = 22, // "associated"
};
/// Known operand bundle tag IDs, which always have the same value. All
diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h
index bab8728ed49f..899976a87bc7 100644
--- a/include/llvm/IR/MDBuilder.h
+++ b/include/llvm/IR/MDBuilder.h
@@ -15,7 +15,9 @@
#ifndef LLVM_IR_MDBUILDER_H
#define LLVM_IR_MDBUILDER_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
@@ -63,8 +65,11 @@ public:
/// Return metadata specifying that a branch or switch is unpredictable.
MDNode *createUnpredictable();
- /// Return metadata containing the entry count for a function.
- MDNode *createFunctionEntryCount(uint64_t Count);
+ /// Return metadata containing the entry \p Count for a function, and the
+ /// GUIDs stored in \p Imports that need to be imported for sample PGO, to
+ /// enable the same inlines as the profiled optimized binary
+ MDNode *createFunctionEntryCount(uint64_t Count,
+ const DenseSet<GlobalValue::GUID> *Imports);
/// Return metadata containing the section prefix for a function.
MDNode *createFunctionSectionPrefix(StringRef Prefix);
diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h
index 0eb91a3b0600..56ee21392ccd 100644
--- a/include/llvm/IR/Mangler.h
+++ b/include/llvm/IR/Mangler.h
@@ -21,6 +21,7 @@ namespace llvm {
class DataLayout;
template <typename T> class SmallVectorImpl;
+class Triple;
class Twine;
class raw_ostream;
@@ -46,6 +47,9 @@ public:
const Twine &GVName, const DataLayout &DL);
};
+void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV,
+ const Triple &TT, Mangler &Mangler);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 46c785a1c05d..fd79355bff1a 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -78,7 +78,7 @@ public:
protected:
Metadata(unsigned ID, StorageType Storage)
: SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) {
- static_assert(sizeof(*this) == 8, "Metdata fields poorly packed");
+ static_assert(sizeof(*this) == 8, "Metadata fields poorly packed");
}
~Metadata() = default;
@@ -269,12 +269,11 @@ public:
private:
LLVMContext &Context;
- uint64_t NextIndex;
+ uint64_t NextIndex = 0;
SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
public:
- ReplaceableMetadataImpl(LLVMContext &Context)
- : Context(Context), NextIndex(0) {}
+ ReplaceableMetadataImpl(LLVMContext &Context) : Context(Context) {}
~ReplaceableMetadataImpl() {
assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
@@ -586,8 +585,9 @@ dyn_extract_or_null(Y &&MD) {
class MDString : public Metadata {
friend class StringMapEntry<MDString>;
- StringMapEntry<MDString> *Entry;
- MDString() : Metadata(MDStringKind, Uniqued), Entry(nullptr) {}
+ StringMapEntry<MDString> *Entry = nullptr;
+
+ MDString() : Metadata(MDStringKind, Uniqued) {}
public:
MDString(const MDString &) = delete;
@@ -1062,7 +1062,6 @@ public:
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B);
static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
-
};
/// \brief Tuple of metadata.
@@ -1284,7 +1283,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
friend class Module;
std::string Name;
- Module *Parent;
+ Module *Parent = nullptr;
void *Operands; // SmallVector<TrackingMDRef, 4>
void setParent(Module *M) { Parent = M; }
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 79870b9455a6..70c57cf90add 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -311,7 +311,7 @@ public:
/// 4. Finally, the function exists but has the wrong prototype: return the
/// function with a constantexpr cast to the right prototype.
Constant *getOrInsertFunction(StringRef Name, FunctionType *T,
- AttributeSet AttributeList);
+ AttributeList AttributeList);
Constant *getOrInsertFunction(StringRef Name, FunctionType *T);
@@ -321,13 +321,22 @@ public:
/// or a ConstantExpr BitCast of that type if the named function has a
/// different type. This version of the method takes a null terminated list of
/// function arguments, which makes it easier for clients to use.
+ template<typename... ArgsTy>
Constant *getOrInsertFunction(StringRef Name,
- AttributeSet AttributeList,
- Type *RetTy, ...) LLVM_END_WITH_NULL;
+ AttributeList AttributeList,
+ Type *RetTy, ArgsTy... Args)
+ {
+ SmallVector<Type*, sizeof...(ArgsTy)> ArgTys{Args...};
+ return getOrInsertFunction(Name,
+ FunctionType::get(RetTy, ArgTys, false),
+ AttributeList);
+ }
/// Same as above, but without the attributes.
- Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...)
- LLVM_END_WITH_NULL;
+ template<typename... ArgsTy>
+ Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ArgsTy... Args) {
+ return getOrInsertFunction(Name, AttributeList{}, RetTy, Args...);
+ }
/// Look up the specified function in the module symbol table. If it does not
/// exist, return null.
@@ -345,20 +354,23 @@ public:
return getGlobalVariable(Name, false);
}
- GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const {
- return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal);
- }
+ GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const;
- GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false);
+ GlobalVariable *getGlobalVariable(StringRef Name,
+ bool AllowInternal = false) {
+ return static_cast<const Module *>(this)->getGlobalVariable(Name,
+ AllowInternal);
+ }
/// Return the global variable in the module with the specified name, of
/// arbitrary type. This method returns null if a global with the specified
/// name is not found.
- GlobalVariable *getNamedGlobal(StringRef Name) {
+ const GlobalVariable *getNamedGlobal(StringRef Name) const {
return getGlobalVariable(Name, true);
}
- const GlobalVariable *getNamedGlobal(StringRef Name) const {
- return const_cast<Module *>(this)->getNamedGlobal(Name);
+ GlobalVariable *getNamedGlobal(StringRef Name) {
+ return const_cast<GlobalVariable *>(
+ static_cast<const Module *>(this)->getNamedGlobal(Name));
}
/// Look up the specified global in the module symbol table.
@@ -615,6 +627,32 @@ public:
return global_objects().end();
}
+ typedef concat_iterator<GlobalValue, iterator, global_iterator,
+ alias_iterator, ifunc_iterator>
+ global_value_iterator;
+ typedef concat_iterator<const GlobalValue, const_iterator,
+ const_global_iterator, const_alias_iterator,
+ const_ifunc_iterator>
+ const_global_value_iterator;
+
+ iterator_range<global_value_iterator> global_values() {
+ return concat<GlobalValue>(functions(), globals(), aliases(), ifuncs());
+ }
+ iterator_range<const_global_value_iterator> global_values() const {
+ return concat<const GlobalValue>(functions(), globals(), aliases(),
+ ifuncs());
+ }
+
+ global_value_iterator global_value_begin() { return global_values().begin(); }
+ global_value_iterator global_value_end() { return global_values().end(); }
+
+ const_global_value_iterator global_value_begin() const {
+ return global_values().begin();
+ }
+ const_global_value_iterator global_value_end() const {
+ return global_values().end();
+ }
+
/// @}
/// @name Named Metadata Iteration
/// @{
@@ -726,6 +764,10 @@ public:
/// @name Utility functions for querying Debug information.
/// @{
+ /// \brief Returns the Number of Register ParametersDwarf Version by checking
+ /// module flags.
+ unsigned getNumberRegisterParameters() const;
+
/// \brief Returns the Dwarf Version by checking module flags.
unsigned getDwarfVersion() const;
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
index 83c4ae011216..09f6c1897009 100644
--- a/include/llvm/IR/ModuleSummaryIndex.h
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -162,7 +162,7 @@ private:
protected:
/// GlobalValueSummary constructor.
GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs)
- : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) {}
+ : Kind(K), Flags(Flags), OriginalName(0), RefEdgeList(std::move(Refs)) {}
public:
virtual ~GlobalValueSummary() = default;
@@ -233,12 +233,13 @@ public:
void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; }
const GlobalValueSummary &getAliasee() const {
- return const_cast<AliasSummary *>(this)->getAliasee();
+ assert(AliaseeSummary && "Unexpected missing aliasee summary");
+ return *AliaseeSummary;
}
GlobalValueSummary &getAliasee() {
- assert(AliaseeSummary && "Unexpected missing aliasee summary");
- return *AliaseeSummary;
+ return const_cast<GlobalValueSummary &>(
+ static_cast<const AliasSummary *>(this)->getAliasee());
}
};
@@ -249,6 +250,23 @@ public:
/// <CalleeValueInfo, CalleeInfo> call edge pair.
typedef std::pair<ValueInfo, CalleeInfo> EdgeTy;
+ /// An "identifier" for a virtual function. This contains the type identifier
+ /// represented as a GUID and the offset from the address point to the virtual
+ /// function pointer, where "address point" is as defined in the Itanium ABI:
+ /// https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
+ struct VFuncId {
+ GlobalValue::GUID GUID;
+ uint64_t Offset;
+ };
+
+ /// A specification for a virtual function call with all constant integer
+ /// arguments. This is used to perform virtual constant propagation on the
+ /// summary.
+ struct ConstVCall {
+ VFuncId VFunc;
+ std::vector<uint64_t> Args;
+ };
+
private:
/// Number of instructions (ignoring debug instructions, e.g.) computed
/// during the initial compile step when the summary index is first built.
@@ -257,17 +275,47 @@ private:
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
std::vector<EdgeTy> CallGraphEdgeList;
- /// List of type identifiers used by this function, represented as GUIDs.
- std::vector<GlobalValue::GUID> TypeIdList;
+ /// All type identifier related information. Because these fields are
+ /// relatively uncommon we only allocate space for them if necessary.
+ struct TypeIdInfo {
+ /// List of type identifiers used by this function in llvm.type.test
+ /// intrinsics other than by an llvm.assume intrinsic, represented as GUIDs.
+ std::vector<GlobalValue::GUID> TypeTests;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do
+ /// not have all constant integer arguments.
+ std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls;
+
+ /// List of virtual calls made by this function using (respectively)
+ /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with
+ /// all constant integer arguments.
+ std::vector<ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
+ };
+
+ std::unique_ptr<TypeIdInfo> TIdInfo;
public:
/// Summary constructors.
FunctionSummary(GVFlags Flags, unsigned NumInsts, std::vector<ValueInfo> Refs,
std::vector<EdgeTy> CGEdges,
- std::vector<GlobalValue::GUID> TypeIds)
+ std::vector<GlobalValue::GUID> TypeTests,
+ std::vector<VFuncId> TypeTestAssumeVCalls,
+ std::vector<VFuncId> TypeCheckedLoadVCalls,
+ std::vector<ConstVCall> TypeTestAssumeConstVCalls,
+ std::vector<ConstVCall> TypeCheckedLoadConstVCalls)
: GlobalValueSummary(FunctionKind, Flags, std::move(Refs)),
- InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)),
- TypeIdList(std::move(TypeIds)) {}
+ InstCount(NumInsts), CallGraphEdgeList(std::move(CGEdges)) {
+ if (!TypeTests.empty() || !TypeTestAssumeVCalls.empty() ||
+ !TypeCheckedLoadVCalls.empty() || !TypeTestAssumeConstVCalls.empty() ||
+ !TypeCheckedLoadConstVCalls.empty())
+ TIdInfo = llvm::make_unique<TypeIdInfo>(TypeIdInfo{
+ std::move(TypeTests), std::move(TypeTestAssumeVCalls),
+ std::move(TypeCheckedLoadVCalls),
+ std::move(TypeTestAssumeConstVCalls),
+ std::move(TypeCheckedLoadConstVCalls)});
+ }
/// Check if this is a function summary.
static bool classof(const GlobalValueSummary *GVS) {
@@ -280,8 +328,85 @@ public:
/// Return the list of <CalleeValueInfo, CalleeInfo> pairs.
ArrayRef<EdgeTy> calls() const { return CallGraphEdgeList; }
- /// Returns the list of type identifiers used by this function.
- ArrayRef<GlobalValue::GUID> type_tests() const { return TypeIdList; }
+ /// Returns the list of type identifiers used by this function in
+ /// llvm.type.test intrinsics other than by an llvm.assume intrinsic,
+ /// represented as GUIDs.
+ ArrayRef<GlobalValue::GUID> type_tests() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTests;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.assume(llvm.type.test) intrinsics that do not have all constant
+ /// integer arguments.
+ ArrayRef<VFuncId> type_test_assume_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTestAssumeVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.type.checked.load intrinsics that do not have all constant integer
+ /// arguments.
+ ArrayRef<VFuncId> type_checked_load_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeCheckedLoadVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.assume(llvm.type.test) intrinsics with all constant integer
+ /// arguments.
+ ArrayRef<ConstVCall> type_test_assume_const_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeTestAssumeConstVCalls;
+ return {};
+ }
+
+ /// Returns the list of virtual calls made by this function using
+ /// llvm.type.checked.load intrinsics with all constant integer arguments.
+ ArrayRef<ConstVCall> type_checked_load_const_vcalls() const {
+ if (TIdInfo)
+ return TIdInfo->TypeCheckedLoadConstVCalls;
+ return {};
+ }
+
+ /// Add a type test to the summary. This is used by WholeProgramDevirt if we
+ /// were unable to devirtualize a checked call.
+ void addTypeTest(GlobalValue::GUID Guid) {
+ if (!TIdInfo)
+ TIdInfo = llvm::make_unique<TypeIdInfo>();
+ TIdInfo->TypeTests.push_back(Guid);
+ }
+};
+
+template <> struct DenseMapInfo<FunctionSummary::VFuncId> {
+ static FunctionSummary::VFuncId getEmptyKey() { return {0, uint64_t(-1)}; }
+ static FunctionSummary::VFuncId getTombstoneKey() {
+ return {0, uint64_t(-2)};
+ }
+ static bool isEqual(FunctionSummary::VFuncId L, FunctionSummary::VFuncId R) {
+ return L.GUID == R.GUID && L.Offset == R.Offset;
+ }
+ static unsigned getHashValue(FunctionSummary::VFuncId I) { return I.GUID; }
+};
+
+template <> struct DenseMapInfo<FunctionSummary::ConstVCall> {
+ static FunctionSummary::ConstVCall getEmptyKey() {
+ return {{0, uint64_t(-1)}, {}};
+ }
+ static FunctionSummary::ConstVCall getTombstoneKey() {
+ return {{0, uint64_t(-2)}, {}};
+ }
+ static bool isEqual(FunctionSummary::ConstVCall L,
+ FunctionSummary::ConstVCall R) {
+ return DenseMapInfo<FunctionSummary::VFuncId>::isEqual(L.VFunc, R.VFunc) &&
+ L.Args == R.Args;
+ }
+ static unsigned getHashValue(FunctionSummary::ConstVCall I) {
+ return I.VFunc.GUID;
+ }
};
/// \brief Global variable summary information to aid decisions and
@@ -323,8 +448,40 @@ struct TypeTestResolution {
unsigned SizeM1BitWidth = 0;
};
+struct WholeProgramDevirtResolution {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ SingleImpl, ///< Single implementation devirtualization
+ } TheKind = Indir;
+
+ std::string SingleImplName;
+
+ struct ByArg {
+ enum Kind {
+ Indir, ///< Just do a regular virtual call
+ UniformRetVal, ///< Uniform return value optimization
+ UniqueRetVal, ///< Unique return value optimization
+ VirtualConstProp, ///< Virtual constant propagation
+ } TheKind = Indir;
+
+ /// Additional information for the resolution:
+ /// - UniformRetVal: the uniform return value.
+ /// - UniqueRetVal: the return value associated with the unique vtable (0 or
+ /// 1).
+ uint64_t Info = 0;
+ };
+
+ /// Resolutions for calls with all constant integer arguments (excluding the
+ /// first argument, "this"), where the key is the argument vector.
+ std::map<std::vector<uint64_t>, ByArg> ResByArg;
+};
+
struct TypeIdSummary {
TypeTestResolution TTRes;
+
+ /// Mapping from byte offset to whole-program devirt resolution for that
+ /// (typeid, byte offset) pair.
+ std::map<uint64_t, WholeProgramDevirtResolution> WPDRes;
};
/// 160 bits SHA1
@@ -372,6 +529,10 @@ private:
// FIXME: Add bitcode read/write support for this field.
std::map<std::string, TypeIdSummary> TypeIdMap;
+ /// Mapping from original ID to GUID. If original ID can map to multiple
+ /// GUIDs, it will be mapped to 0.
+ std::map<GlobalValue::GUID, GlobalValue::GUID> OidGuidMap;
+
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
@@ -399,9 +560,17 @@ public:
return GlobalValueMap.find(ValueGUID);
}
+ /// Return the GUID for \p OriginalId in the OidGuidMap.
+ GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const {
+ const auto I = OidGuidMap.find(OriginalID);
+ return I == OidGuidMap.end() ? 0 : I->second;
+ }
+
/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
+ addOriginalName(GlobalValue::getGUID(ValueName),
+ Summary->getOriginalName());
GlobalValueMap[GlobalValue::getGUID(ValueName)].push_back(
std::move(Summary));
}
@@ -409,9 +578,21 @@ public:
/// Add a global value summary for a value of the given GUID.
void addGlobalValueSummary(GlobalValue::GUID ValueGUID,
std::unique_ptr<GlobalValueSummary> Summary) {
+ addOriginalName(ValueGUID, Summary->getOriginalName());
GlobalValueMap[ValueGUID].push_back(std::move(Summary));
}
+ /// Add an original name for the value of the given GUID.
+ void addOriginalName(GlobalValue::GUID ValueGUID,
+ GlobalValue::GUID OrigGUID) {
+ if (OrigGUID == 0 || ValueGUID == OrigGUID)
+ return;
+ if (OidGuidMap.count(OrigGUID) && OidGuidMap[OrigGUID] != ValueGUID)
+ OidGuidMap[OrigGUID] = 0;
+ else
+ OidGuidMap[OrigGUID] = ValueGUID;
+ }
+
/// Find the summary for global \p GUID in module \p ModuleId, or nullptr if
/// not found.
GlobalValueSummary *findSummaryInModule(GlobalValue::GUID ValueGUID,
@@ -507,6 +688,25 @@ public:
return ModulePathStringTable.count(M.getModuleIdentifier());
}
+ const std::map<std::string, TypeIdSummary> &typeIds() const {
+ return TypeIdMap;
+ }
+
+ /// This accessor should only be used when exporting because it can mutate the
+ /// map.
+ TypeIdSummary &getOrInsertTypeIdSummary(StringRef TypeId) {
+ return TypeIdMap[TypeId];
+ }
+
+ /// This returns either a pointer to the type id summary (if present in the
+ /// summary map) or null (if not present). This may be used when importing.
+ const TypeIdSummary *getTypeIdSummary(StringRef TypeId) const {
+ auto I = TypeIdMap.find(TypeId);
+ if (I == TypeIdMap.end())
+ return nullptr;
+ return &I->second;
+ }
+
/// Remove entries in the GlobalValueMap that have empty summaries due to the
/// eager nature of map entry creation during VST parsing. These would
/// also be suppressed during combined index generation in mergeFrom(),
diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h
index e2880ec6fec8..80719c696935 100644
--- a/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -33,20 +33,135 @@ template <> struct MappingTraits<TypeTestResolution> {
}
};
+template <>
+struct ScalarEnumerationTraits<WholeProgramDevirtResolution::ByArg::Kind> {
+ static void enumeration(IO &io,
+ WholeProgramDevirtResolution::ByArg::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::ByArg::Indir);
+ io.enumCase(value, "UniformRetVal",
+ WholeProgramDevirtResolution::ByArg::UniformRetVal);
+ io.enumCase(value, "UniqueRetVal",
+ WholeProgramDevirtResolution::ByArg::UniqueRetVal);
+ io.enumCase(value, "VirtualConstProp",
+ WholeProgramDevirtResolution::ByArg::VirtualConstProp);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution::ByArg> {
+ static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("Info", res.Info);
+ }
+};
+
+template <>
+struct CustomMappingTraits<
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg>> {
+ static void inputOne(
+ IO &io, StringRef Key,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ std::vector<uint64_t> Args;
+ std::pair<StringRef, StringRef> P = {"", Key};
+ while (!P.second.empty()) {
+ P = P.second.split(',');
+ uint64_t Arg;
+ if (P.first.getAsInteger(0, Arg)) {
+ io.setError("key not an integer");
+ return;
+ }
+ Args.push_back(Arg);
+ }
+ io.mapRequired(Key.str().c_str(), V[Args]);
+ }
+ static void output(
+ IO &io,
+ std::map<std::vector<uint64_t>, WholeProgramDevirtResolution::ByArg> &V) {
+ for (auto &P : V) {
+ std::string Key;
+ for (uint64_t Arg : P.first) {
+ if (!Key.empty())
+ Key += ',';
+ Key += llvm::utostr(Arg);
+ }
+ io.mapRequired(Key.c_str(), P.second);
+ }
+ }
+};
+
+template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> {
+ static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) {
+ io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir);
+ io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl);
+ }
+};
+
+template <> struct MappingTraits<WholeProgramDevirtResolution> {
+ static void mapping(IO &io, WholeProgramDevirtResolution &res) {
+ io.mapOptional("Kind", res.TheKind);
+ io.mapOptional("SingleImplName", res.SingleImplName);
+ io.mapOptional("ResByArg", res.ResByArg);
+ }
+};
+
+template <>
+struct CustomMappingTraits<std::map<uint64_t, WholeProgramDevirtResolution>> {
+ static void inputOne(IO &io, StringRef Key,
+ std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ uint64_t KeyInt;
+ if (Key.getAsInteger(0, KeyInt)) {
+ io.setError("key not an integer");
+ return;
+ }
+ io.mapRequired(Key.str().c_str(), V[KeyInt]);
+ }
+ static void output(IO &io, std::map<uint64_t, WholeProgramDevirtResolution> &V) {
+ for (auto &P : V)
+ io.mapRequired(llvm::utostr(P.first).c_str(), P.second);
+ }
+};
+
template <> struct MappingTraits<TypeIdSummary> {
static void mapping(IO &io, TypeIdSummary& summary) {
io.mapOptional("TTRes", summary.TTRes);
+ io.mapOptional("WPDRes", summary.WPDRes);
}
};
struct FunctionSummaryYaml {
std::vector<uint64_t> TypeTests;
+ std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls,
+ TypeCheckedLoadVCalls;
+ std::vector<FunctionSummary::ConstVCall> TypeTestAssumeConstVCalls,
+ TypeCheckedLoadConstVCalls;
+};
+
+} // End yaml namespace
+} // End llvm namespace
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint64_t)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<FunctionSummary::VFuncId> {
+ static void mapping(IO &io, FunctionSummary::VFuncId& id) {
+ io.mapOptional("GUID", id.GUID);
+ io.mapOptional("Offset", id.Offset);
+ }
+};
+
+template <> struct MappingTraits<FunctionSummary::ConstVCall> {
+ static void mapping(IO &io, FunctionSummary::ConstVCall& id) {
+ io.mapOptional("VFunc", id.VFunc);
+ io.mapOptional("Args", id.Args);
+ }
};
} // End yaml namespace
} // End llvm namespace
-LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::VFuncId)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummary::ConstVCall)
namespace llvm {
namespace yaml {
@@ -54,6 +169,12 @@ namespace yaml {
template <> struct MappingTraits<FunctionSummaryYaml> {
static void mapping(IO &io, FunctionSummaryYaml& summary) {
io.mapOptional("TypeTests", summary.TypeTests);
+ io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls);
+ io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls);
+ io.mapOptional("TypeTestAssumeConstVCalls",
+ summary.TypeTestAssumeConstVCalls);
+ io.mapOptional("TypeCheckedLoadConstVCalls",
+ summary.TypeCheckedLoadConstVCalls);
}
};
@@ -82,7 +203,11 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
false);
Elem.push_back(llvm::make_unique<FunctionSummary>(
GVFlags, 0, ArrayRef<ValueInfo>{},
- ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests)));
+ ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests),
+ std::move(FSum.TypeTestAssumeVCalls),
+ std::move(FSum.TypeCheckedLoadVCalls),
+ std::move(FSum.TypeTestAssumeConstVCalls),
+ std::move(FSum.TypeCheckedLoadConstVCalls)));
}
}
static void output(IO &io, GlobalValueSummaryMapTy &V) {
@@ -90,7 +215,11 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> {
std::vector<FunctionSummaryYaml> FSums;
for (auto &Sum : P.second) {
if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get()))
- FSums.push_back(FunctionSummaryYaml{FSum->type_tests()});
+ FSums.push_back(FunctionSummaryYaml{
+ FSum->type_tests(), FSum->type_test_assume_vcalls(),
+ FSum->type_checked_load_vcalls(),
+ FSum->type_test_assume_const_vcalls(),
+ FSum->type_checked_load_const_vcalls()});
}
if (!FSums.empty())
io.mapRequired(llvm::utostr(P.first).c_str(), FSums);
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 444ce93921f6..997a85340c25 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -18,8 +18,6 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
@@ -174,12 +172,15 @@ private:
FastMathFlags(unsigned F) : Flags(F) { }
public:
+ /// This is how the bits are used in Value::SubclassOptionalData so they
+ /// should fit there too.
enum {
UnsafeAlgebra = (1 << 0),
NoNaNs = (1 << 1),
NoInfs = (1 << 2),
NoSignedZeros = (1 << 3),
- AllowReciprocal = (1 << 4)
+ AllowReciprocal = (1 << 4),
+ AllowContract = (1 << 5)
};
FastMathFlags() = default;
@@ -195,6 +196,7 @@ public:
bool noInfs() const { return 0 != (Flags & NoInfs); }
bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); }
bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); }
+ bool allowContract() const { return 0 != (Flags & AllowContract); }
bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); }
/// Flag setters
@@ -202,12 +204,16 @@ public:
void setNoInfs() { Flags |= NoInfs; }
void setNoSignedZeros() { Flags |= NoSignedZeros; }
void setAllowReciprocal() { Flags |= AllowReciprocal; }
+ void setAllowContract(bool B) {
+ Flags = (Flags & ~AllowContract) | B * AllowContract;
+ }
void setUnsafeAlgebra() {
Flags |= UnsafeAlgebra;
setNoNaNs();
setNoInfs();
setNoSignedZeros();
setAllowReciprocal();
+ setAllowContract(true);
}
void operator&=(const FastMathFlags &OtherFlags) {
@@ -259,6 +265,12 @@ private:
(B * FastMathFlags::AllowReciprocal);
}
+ void setHasAllowContract(bool B) {
+ SubclassOptionalData =
+ (SubclassOptionalData & ~FastMathFlags::AllowContract) |
+ (B * FastMathFlags::AllowContract);
+ }
+
/// Convenience function for setting multiple fast-math flags.
/// FMF is a mask of the bits to set.
void setFastMathFlags(FastMathFlags FMF) {
@@ -302,6 +314,12 @@ public:
return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0;
}
+ /// Test whether this operation is permitted to
+ /// be floating-point contracted.
+ bool hasAllowContract() const {
+ return (SubclassOptionalData & FastMathFlags::AllowContract) != 0;
+ }
+
/// Convenience function for getting all the fast-math flags
FastMathFlags getFastMathFlags() const {
return FastMathFlags(SubclassOptionalData);
diff --git a/include/llvm/IR/OptBisect.h b/include/llvm/IR/OptBisect.h
index 9eee65e93e52..185a5ac956f5 100644
--- a/include/llvm/IR/OptBisect.h
+++ b/include/llvm/IR/OptBisect.h
@@ -51,24 +51,6 @@ public:
template <class UnitT>
bool shouldRunPass(const Pass *P, const UnitT &U);
- /// Checks the bisect limit to determine if the optimization described by the
- /// /p Desc argument should run.
- ///
- /// This function will immediate return true if bisection is disabled. If the
- /// bisect limit is set to -1, the function will print a message with the
- /// bisect number assigned to the optimization along with the /p Desc
- /// description and return true. Otherwise, the function will print a message
- /// with the bisect number assigned to the optimization and indicating whether
- /// or not the pass will be run and return true if the bisect limit has not
- /// yet been exceded or false if it has.
- ///
- /// Passes may call this function to provide more fine grained control over
- /// individual optimizations performed by the pass. Passes which cannot be
- /// skipped entirely (such as non-optional code generation passes) may still
- /// call this function to control whether or not individual optional
- /// transformations are performed.
- bool shouldRunCase(const Twine &Desc);
-
private:
bool checkPass(const StringRef PassName, const StringRef TargetDesc);
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index b7811fdb7504..c845112baa45 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -73,6 +73,46 @@ struct alignas(8) AnalysisKey {};
/// if it is, the analysis knows that it itself is preserved.
struct alignas(8) AnalysisSetKey {};
+/// This templated class represents "all analyses that operate over \<a
+/// particular IR unit\>" (e.g. a Function or a Module) in instances of
+/// PreservedAnalysis.
+///
+/// This lets a transformation say e.g. "I preserved all function analyses".
+///
+/// Note that you must provide an explicit instantiation declaration and
+/// definition for this template in order to get the correct behavior on
+/// Windows. Otherwise, the address of SetKey will not be stable.
+template <typename IRUnitT> class AllAnalysesOn {
+public:
+ static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+ static AnalysisSetKey SetKey;
+};
+
+template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
+
+extern template class AllAnalysesOn<Module>;
+extern template class AllAnalysesOn<Function>;
+
+/// Represents analyses that only rely on functions' control flow.
+///
+/// This can be used with \c PreservedAnalyses to mark the CFG as preserved and
+/// to query whether it has been preserved.
+///
+/// The CFG of a function is defined as the set of basic blocks and the edges
+/// between them. Changing the set of basic blocks in a function is enough to
+/// mutate the CFG. Mutating the condition of a branch or argument of an
+/// invoked function does not mutate the CFG, but changing the successor labels
+/// of those instructions does.
+class CFGAnalyses {
+public:
+ static AnalysisSetKey *ID() { return &SetKey; }
+
+private:
+ static AnalysisSetKey SetKey;
+};
+
/// A set of analyses that are preserved following a run of a transformation
/// pass.
///
@@ -348,29 +388,6 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> {
}
};
-/// This templated class represents "all analyses that operate over \<a
-/// particular IR unit\>" (e.g. a Function or a Module) in instances of
-/// PreservedAnalysis.
-///
-/// This lets a transformation say e.g. "I preserved all function analyses".
-///
-/// Note that you must provide an explicit instantiation declaration and
-/// definition for this template in order to get the correct behavior on
-/// Windows. Otherwise, the address of SetKey will not be stable.
-template <typename IRUnitT>
-class AllAnalysesOn {
-public:
- static AnalysisSetKey *ID() { return &SetKey; }
-
-private:
- static AnalysisSetKey SetKey;
-};
-
-template <typename IRUnitT> AnalysisSetKey AllAnalysesOn<IRUnitT>::SetKey;
-
-extern template class AllAnalysesOn<Module>;
-extern template class AllAnalysesOn<Function>;
-
/// \brief Manages a sequence of passes over a particular unit of IR.
///
/// A pass manager contains a sequence of passes to run over a particular unit
@@ -780,7 +797,7 @@ public:
if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
- << "\n";
+ << " on " << IR.getName() << "\n";
I = ResultsList.erase(I);
AnalysisResults.erase({ID, &IR});
@@ -821,7 +838,8 @@ private:
if (Inserted) {
auto &P = this->lookUpPass(ID);
if (DebugLogging)
- dbgs() << "Running analysis: " << P.name() << "\n";
+ dbgs() << "Running analysis: " << P.name() << " on " << IR.getName()
+ << "\n";
AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
ResultList.emplace_back(ID, P.run(IR, *this, ExtraArgs...));
@@ -852,7 +870,7 @@ private:
if (DebugLogging)
dbgs() << "Invalidating analysis: " << this->lookUpPass(ID).name()
- << "\n";
+ << " on " << IR.getName() << "\n";
AnalysisResultLists[&IR].erase(RI->second);
AnalysisResults.erase(RI);
}
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
index 02f21675fa9d..387dc4c65c43 100644
--- a/include/llvm/IR/PassManagerInternal.h
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -291,7 +291,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT,
AnalysisResultConcept<IRUnitT, PreservedAnalysesT, InvalidatorT>>
run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs... ExtraArgs) override {
- return make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
+ return llvm::make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...));
}
/// \brief The model delegates to a static \c PassT::name method.
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index a30fc97e98ef..40f9c21f646b 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -157,6 +157,19 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
return m_CombineOr(m_Zero(), m_NegZero());
}
+struct match_nan {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<ConstantFP>(V)) {
+ const APFloat &APF = C->getValueAPF();
+ return APF.isNaN();
+ }
+ return false;
+ }
+};
+
+/// Match an arbitrary NaN constant. This includes quiet and signalling nans.
+inline match_nan m_NaN() { return match_nan(); }
+
struct apint_match {
const APInt *&Res;
apint_match(const APInt *&R) : Res(R) {}
@@ -814,6 +827,13 @@ inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
}
+template <typename OpTy>
+inline match_combine_or<CastClass_match<OpTy, Instruction::ZExt>,
+ CastClass_match<OpTy, Instruction::SExt>>
+m_ZExtOrSExt(const OpTy &Op) {
+ return m_CombineOr(m_ZExt(Op), m_SExt(Op));
+}
+
/// \brief Matches UIToFP.
template <typename OpTy>
inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
@@ -826,6 +846,18 @@ inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
+/// \brief Matches FPTrunc
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::FPTrunc> m_FPTrunc(const OpTy &Op) {
+ return CastClass_match<OpTy, Instruction::FPTrunc>(Op);
+}
+
+/// \brief Matches FPExt
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::FPExt> m_FPExt(const OpTy &Op) {
+ return CastClass_match<OpTy, Instruction::FPExt>(Op);
+}
+
//===----------------------------------------------------------------------===//
// Matchers for unary operators
//
@@ -1316,6 +1348,14 @@ template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
// Matchers for two-operands operators with the operators in either order
//
+/// \brief Matches a BinaryOperator with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<AnyBinaryOp_match<LHS, RHS>,
+ AnyBinaryOp_match<RHS, LHS>>
+m_c_BinOp(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_BinOp(L, R), m_BinOp(R, L));
+}
+
/// \brief Matches an ICmp with a predicate over LHS and RHS in either order.
/// Does not swap the predicate.
template<typename LHS, typename RHS>
@@ -1325,6 +1365,22 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
return m_CombineOr(m_ICmp(Pred, L, R), m_ICmp(Pred, R, L));
}
+/// \brief Matches a Add with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Add>,
+ BinaryOp_match<RHS, LHS, Instruction::Add>>
+m_c_Add(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Add(L, R), m_Add(R, L));
+}
+
+/// \brief Matches a Mul with LHS and RHS in either order.
+template<typename LHS, typename RHS>
+inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::Mul>,
+ BinaryOp_match<RHS, LHS, Instruction::Mul>>
+m_c_Mul(const LHS &L, const RHS &R) {
+ return m_CombineOr(m_Mul(L, R), m_Mul(R, L));
+}
+
/// \brief Matches an And with LHS and RHS in either order.
template<typename LHS, typename RHS>
inline match_combine_or<BinaryOp_match<LHS, RHS, Instruction::And>,
diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h
index 118310aed1d0..81f535311431 100644
--- a/include/llvm/IR/PredIteratorCache.h
+++ b/include/llvm/IR/PredIteratorCache.h
@@ -27,8 +27,8 @@ namespace llvm {
/// wants the predecessor list for the same blocks.
class PredIteratorCache {
/// BlockToPredsMap - Pointer to null-terminated list.
- DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
- DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
+ mutable DenseMap<BasicBlock *, BasicBlock **> BlockToPredsMap;
+ mutable DenseMap<BasicBlock *, unsigned> BlockToPredCountMap;
/// Memory - This is the space that holds cached preds.
BumpPtrAllocator Memory;
@@ -55,13 +55,15 @@ private:
return Entry;
}
- unsigned GetNumPreds(BasicBlock *BB) {
- GetPreds(BB);
- return BlockToPredCountMap[BB];
+ unsigned GetNumPreds(BasicBlock *BB) const {
+ auto Result = BlockToPredCountMap.find(BB);
+ if (Result != BlockToPredCountMap.end())
+ return Result->second;
+ return BlockToPredCountMap[BB] = std::distance(pred_begin(BB), pred_end(BB));
}
public:
- size_t size(BasicBlock *BB) { return GetNumPreds(BB); }
+ size_t size(BasicBlock *BB) const { return GetNumPreds(BB); }
ArrayRef<BasicBlock *> get(BasicBlock *BB) {
return makeArrayRef(GetPreds(BB), GetNumPreds(BB));
}
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
index 916faa4b327e..03151cd7c8f7 100644
--- a/include/llvm/IR/Statepoint.h
+++ b/include/llvm/IR/Statepoint.h
@@ -454,7 +454,7 @@ struct StatepointDirectives {
/// Parse out statepoint directives from the function attributes present in \p
/// AS.
-StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeSet AS);
+StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS);
/// Return \c true if the the \p Attr is an attribute that is a statepoint
/// directive.
diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h
index 5c6d58affd7a..49a5fb21297d 100644
--- a/include/llvm/IR/SymbolTableListTraits.h
+++ b/include/llvm/IR/SymbolTableListTraits.h
@@ -1,4 +1,4 @@
-//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===//
+//===- llvm/SymbolTableListTraits.h - Traits for iplist ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,23 +26,27 @@
#define LLVM_IR_SYMBOLTABLELISTTRAITS_H
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/simple_ilist.h"
+#include <cstddef>
namespace llvm {
-class ValueSymbolTable;
-/// Template metafunction to get the parent type for a symbol table list.
-///
-/// Implementations create a typedef called \c type so that we only need a
-/// single template parameter for the list and traits.
-template <typename NodeTy> struct SymbolTableListParentType {};
class Argument;
class BasicBlock;
class Function;
-class Instruction;
-class GlobalVariable;
class GlobalAlias;
class GlobalIFunc;
+class GlobalVariable;
+class Instruction;
class Module;
+class ValueSymbolTable;
+
+/// Template metafunction to get the parent type for a symbol table list.
+///
+/// Implementations create a typedef called \c type so that we only need a
+/// single template parameter for the list and traits.
+template <typename NodeTy> struct SymbolTableListParentType {};
+
#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
@@ -67,7 +71,7 @@ class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
typename SymbolTableListParentType<ValueSubClass>::type ItemParentClass;
public:
- SymbolTableListTraits() {}
+ SymbolTableListTraits() = default;
private:
/// getListOwner - Return the object that owns this list. If this is a list
@@ -109,6 +113,6 @@ template <class T>
class SymbolTableList
: public iplist_impl<simple_ilist<T>, SymbolTableListTraits<T>> {};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_SYMBOLTABLELISTTRAITS_H
diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h
index fe513a8f9795..12b196432006 100644
--- a/include/llvm/IR/TrackingMDRef.h
+++ b/include/llvm/IR/TrackingMDRef.h
@@ -15,6 +15,8 @@
#define LLVM_IR_TRACKINGMDREF_H
#include "llvm/IR/Metadata.h"
+#include <algorithm>
+#include <cassert>
namespace llvm {
@@ -22,14 +24,15 @@ namespace llvm {
///
/// This class behaves like \a TrackingVH, but for metadata.
class TrackingMDRef {
- Metadata *MD;
+ Metadata *MD = nullptr;
public:
- TrackingMDRef() : MD(nullptr) {}
+ TrackingMDRef() = default;
explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
+
TrackingMDRef &operator=(TrackingMDRef &&X) {
if (&X == this)
return *this;
@@ -39,6 +42,7 @@ public:
retrack(X);
return *this;
}
+
TrackingMDRef &operator=(const TrackingMDRef &X) {
if (&X == this)
return *this;
@@ -48,6 +52,7 @@ public:
track();
return *this;
}
+
~TrackingMDRef() { untrack(); }
Metadata *get() const { return MD; }
@@ -80,10 +85,12 @@ private:
if (MD)
MetadataTracking::track(MD);
}
+
void untrack() {
if (MD)
MetadataTracking::untrack(MD);
}
+
void retrack(TrackingMDRef &X) {
assert(MD == X.MD && "Expected values to match");
if (X.MD) {
@@ -101,15 +108,17 @@ template <class T> class TypedTrackingMDRef {
TrackingMDRef Ref;
public:
- TypedTrackingMDRef() {}
+ TypedTrackingMDRef() = default;
explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
+
TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
Ref = std::move(X.Ref);
return *this;
}
+
TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
Ref = X.Ref;
return *this;
@@ -162,4 +171,4 @@ template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
} // end namespace llvm
-#endif
+#endif // LLVM_IR_TRACKINGMDREF_H
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index 778ee06169f1..e6a0df937e9b 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -290,7 +290,11 @@ public:
/// If this is a vector type, return the element type, otherwise return
/// 'this'.
- Type *getScalarType() const LLVM_READONLY;
+ Type *getScalarType() const {
+ if (isVectorTy())
+ return getVectorElementType();
+ return const_cast<Type*>(this);
+ }
//===--------------------------------------------------------------------===//
// Type Iteration support.
@@ -423,7 +427,7 @@ private:
};
// Printing of types.
-static inline raw_ostream &operator<<(raw_ostream &OS, Type &T) {
+static inline raw_ostream &operator<<(raw_ostream &OS, const Type &T) {
T.print(OS);
return OS;
}
diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h
index 046f85caec9d..48c4f1161aa1 100644
--- a/include/llvm/IR/TypeFinder.h
+++ b/include/llvm/IR/TypeFinder.h
@@ -1,4 +1,4 @@
-//===-- llvm/IR/TypeFinder.h - Class to find used struct types --*- C++ -*-===//
+//===- llvm/IR/TypeFinder.h - Class to find used struct types ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,8 +15,7 @@
#define LLVM_IR_TYPEFINDER_H
#include "llvm/ADT/DenseSet.h"
-#include "llvm/IR/Metadata.h"
-#include "llvm/IR/Type.h"
+#include <cstddef>
#include <vector>
namespace llvm {
@@ -24,6 +23,7 @@ namespace llvm {
class MDNode;
class Module;
class StructType;
+class Type;
class Value;
/// TypeFinder - Walk over a module, identifying all of the types that are
@@ -36,10 +36,10 @@ class TypeFinder {
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> StructTypes;
- bool OnlyNamed;
+ bool OnlyNamed = false;
public:
- TypeFinder() : OnlyNamed(false) {}
+ TypeFinder() = default;
void run(const Module &M, bool onlyNamed);
void clear();
@@ -77,6 +77,6 @@ private:
void incorporateMDNode(const MDNode *V);
};
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_TYPEFINDER_H
diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h
index ff6b2e1f1e22..05b68ccbb38e 100644
--- a/include/llvm/IR/Use.h
+++ b/include/llvm/IR/Use.h
@@ -85,7 +85,7 @@ public:
///
/// For an instruction operand, for example, this will return the
/// instruction.
- User *getUser() const;
+ User *getUser() const LLVM_READONLY;
inline void set(Value *Val);
@@ -111,7 +111,7 @@ public:
static void zap(Use *Start, const Use *Stop, bool del = false);
private:
- const Use *getImpliedUser() const;
+ const Use *getImpliedUser() const LLVM_READONLY;
Value *Val;
Use *Next;
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
index efff208295b6..ebe99223facd 100644
--- a/include/llvm/IR/UseListOrder.h
+++ b/include/llvm/IR/UseListOrder.h
@@ -20,20 +20,19 @@
namespace llvm {
-class Module;
class Function;
class Value;
/// \brief Structure to hold a use-list order.
struct UseListOrder {
- const Value *V;
- const Function *F;
+ const Value *V = nullptr;
+ const Function *F = nullptr;
std::vector<unsigned> Shuffle;
UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
: V(V), F(F), Shuffle(ShuffleSize) {}
- UseListOrder() : V(nullptr), F(nullptr) {}
+ UseListOrder() = default;
UseListOrder(UseListOrder &&) = default;
UseListOrder &operator=(UseListOrder &&) = default;
};
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index c907d6b670b5..54758a9b6d6a 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -122,8 +122,16 @@ protected:
}
private:
+ const Use *getHungOffOperands() const {
+ return *(reinterpret_cast<const Use *const *>(this) - 1);
+ }
+
Use *&getHungOffOperands() { return *(reinterpret_cast<Use **>(this) - 1); }
+ const Use *getIntrusiveOperands() const {
+ return reinterpret_cast<const Use *>(this) - NumUserOperands;
+ }
+
Use *getIntrusiveOperands() {
return reinterpret_cast<Use *>(this) - NumUserOperands;
}
@@ -135,11 +143,11 @@ private:
}
public:
- Use *getOperandList() {
+ const Use *getOperandList() const {
return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands();
}
- const Use *getOperandList() const {
- return const_cast<User *>(this)->getOperandList();
+ Use *getOperandList() {
+ return const_cast<Use *>(static_cast<const User *>(this)->getOperandList());
}
Value *getOperand(unsigned i) const {
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index bdafbbf58cc4..a4b48d7f3539 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -294,7 +294,15 @@ public:
// when using them since you might not get all uses.
// The methods that don't start with materialized_ assert that modules is
// fully materialized.
- void assertModuleIsMaterialized() const;
+ void assertModuleIsMaterializedImpl() const;
+ // This indirection exists so we can keep assertModuleIsMaterializedImpl()
+ // around in release builds of Value.cpp to be linked with other code built
+ // in debug mode. But this avoids calling it in any of the release built code.
+ void assertModuleIsMaterialized() const {
+#ifndef NDEBUG
+ assertModuleIsMaterializedImpl();
+#endif
+ }
bool use_empty() const {
assertModuleIsMaterialized();
@@ -468,27 +476,30 @@ public:
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripPointerCasts();
- const Value *stripPointerCasts() const {
- return const_cast<Value*>(this)->stripPointerCasts();
+ const Value *stripPointerCasts() const;
+ Value *stripPointerCasts() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripPointerCasts());
}
/// \brief Strip off pointer casts and all-zero GEPs.
///
/// Returns the original uncasted value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripPointerCastsNoFollowAliases();
- const Value *stripPointerCastsNoFollowAliases() const {
- return const_cast<Value*>(this)->stripPointerCastsNoFollowAliases();
+ const Value *stripPointerCastsNoFollowAliases() const;
+ Value *stripPointerCastsNoFollowAliases() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripPointerCastsNoFollowAliases());
}
/// \brief Strip off pointer casts and all-constant inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripInBoundsConstantOffsets();
- const Value *stripInBoundsConstantOffsets() const {
- return const_cast<Value*>(this)->stripInBoundsConstantOffsets();
+ const Value *stripInBoundsConstantOffsets() const;
+ Value *stripInBoundsConstantOffsets() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripInBoundsConstantOffsets());
}
/// \brief Accumulate offsets from \a stripInBoundsConstantOffsets().
@@ -498,21 +509,22 @@ public:
/// correct bitwidth for an offset of this pointer type.
///
/// If this is called on a non-pointer value, it returns 'this'.
- Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
- APInt &Offset);
const Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
- APInt &Offset) const {
- return const_cast<Value *>(this)
- ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
+ APInt &Offset) const;
+ Value *stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
+ APInt &Offset) {
+ return const_cast<Value *>(static_cast<const Value *>(this)
+ ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset));
}
/// \brief Strip off pointer casts and inbounds GEPs.
///
/// Returns the original pointer value. If this is called on a non-pointer
/// value, it returns 'this'.
- Value *stripInBoundsOffsets();
- const Value *stripInBoundsOffsets() const {
- return const_cast<Value*>(this)->stripInBoundsOffsets();
+ const Value *stripInBoundsOffsets() const;
+ Value *stripInBoundsOffsets() {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->stripInBoundsOffsets());
}
/// \brief Returns the number of bytes known to be dereferenceable for the
@@ -535,11 +547,12 @@ public:
/// the PHI node corresponding to PredBB. If not, return ourself. This is
/// useful if you want to know the value something has in a predecessor
/// block.
- Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB);
-
const Value *DoPHITranslation(const BasicBlock *CurBB,
- const BasicBlock *PredBB) const{
- return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
+ const BasicBlock *PredBB) const;
+
+ Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) {
+ return const_cast<Value *>(
+ static_cast<const Value *>(this)->DoPHITranslation(CurBB, PredBB));
}
/// \brief The maximum alignment for instructions.
diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h
index a4d4893a9bc9..4838bac9e0f7 100644
--- a/include/llvm/IR/ValueHandle.h
+++ b/include/llvm/IR/ValueHandle.h
@@ -98,6 +98,15 @@ protected:
V != DenseMapInfo<Value *>::getTombstoneKey();
}
+ /// \brief Remove this ValueHandle from its current use list.
+ void RemoveFromUseList();
+
+ /// \brief Clear the underlying pointer without clearing the use list.
+ ///
+ /// This should only be used if a derived class has manually removed the
+ /// handle from the use list.
+ void clearValPtr() { V = nullptr; }
+
public:
// Callbacks made from Value.
static void ValueIsDeleted(Value *V);
@@ -120,8 +129,6 @@ private:
/// \brief Add this ValueHandle to the use list for V.
void AddToUseList();
- /// \brief Remove this ValueHandle from its current use list.
- void RemoveFromUseList();
};
/// \brief Value handle that is nullable, but tries to track the Value.
@@ -259,7 +266,6 @@ struct isPodLike<AssertingVH<T> > {
#endif
};
-
/// \brief Value handle that tracks a Value across RAUW.
///
/// TrackingVH is designed for situations where a client needs to hold a handle
@@ -370,6 +376,130 @@ public:
virtual void allUsesReplacedWith(Value *) {}
};
+/// Value handle that poisons itself if the Value is deleted.
+///
+/// This is a Value Handle that points to a value and poisons itself if the
+/// value is destroyed while the handle is still live. This is very useful for
+/// catching dangling pointer bugs where an \c AssertingVH cannot be used
+/// because the dangling handle needs to outlive the value without ever being
+/// used.
+///
+/// One particularly useful place to use this is as the Key of a map. Dangling
+/// pointer bugs often lead to really subtle bugs that only occur if another
+/// object happens to get allocated to the same address as the old one. Using
+/// a PoisoningVH ensures that an assert is triggered if looking up a new value
+/// in the map finds a handle from the old value.
+///
+/// Note that a PoisoningVH handle does *not* follow values across RAUW
+/// operations. This means that RAUW's need to explicitly update the
+/// PoisoningVH's as it moves. This is required because in non-assert mode this
+/// class turns into a trivial wrapper around a pointer.
+template <typename ValueTy>
+class PoisoningVH
+#ifndef NDEBUG
+ final : public CallbackVH
+#endif
+{
+ friend struct DenseMapInfo<PoisoningVH<ValueTy>>;
+
+ // Convert a ValueTy*, which may be const, to the raw Value*.
+ static Value *GetAsValue(Value *V) { return V; }
+ static Value *GetAsValue(const Value *V) { return const_cast<Value *>(V); }
+
+#ifndef NDEBUG
+ /// A flag tracking whether this value has been poisoned.
+ ///
+ /// On delete and RAUW, we leave the value pointer alone so that as a raw
+ /// pointer it produces the same value (and we fit into the same key of
+ /// a hash table, etc), but we poison the handle so that any top-level usage
+ /// will fail.
+ bool Poisoned = false;
+
+ Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
+ void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
+
+ /// Handle deletion by poisoning the handle.
+ void deleted() override {
+ assert(!Poisoned && "Tried to delete an already poisoned handle!");
+ Poisoned = true;
+ RemoveFromUseList();
+ }
+
+ /// Handle RAUW by poisoning the handle.
+ void allUsesReplacedWith(Value *) override {
+ assert(!Poisoned && "Tried to RAUW an already poisoned handle!");
+ Poisoned = true;
+ RemoveFromUseList();
+ }
+#else // NDEBUG
+ Value *ThePtr = nullptr;
+
+ Value *getRawValPtr() const { return ThePtr; }
+ void setRawValPtr(Value *P) { ThePtr = P; }
+#endif
+
+ ValueTy *getValPtr() const {
+ assert(!Poisoned && "Accessed a poisoned value handle!");
+ return static_cast<ValueTy *>(getRawValPtr());
+ }
+ void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
+
+public:
+ PoisoningVH() = default;
+#ifndef NDEBUG
+ PoisoningVH(ValueTy *P) : CallbackVH(GetAsValue(P)) {}
+ PoisoningVH(const PoisoningVH &RHS)
+ : CallbackVH(RHS), Poisoned(RHS.Poisoned) {}
+ ~PoisoningVH() {
+ if (Poisoned)
+ clearValPtr();
+ }
+ PoisoningVH &operator=(const PoisoningVH &RHS) {
+ if (Poisoned)
+ clearValPtr();
+ CallbackVH::operator=(RHS);
+ Poisoned = RHS.Poisoned;
+ return *this;
+ }
+#else
+ PoisoningVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
+#endif
+
+ operator ValueTy *() const { return getValPtr(); }
+
+ ValueTy *operator->() const { return getValPtr(); }
+ ValueTy &operator*() const { return *getValPtr(); }
+};
+
+// Specialize DenseMapInfo to allow PoisoningVH to participate in DenseMap.
+template <typename T> struct DenseMapInfo<PoisoningVH<T>> {
+ static inline PoisoningVH<T> getEmptyKey() {
+ PoisoningVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
+ return Res;
+ }
+ static inline PoisoningVH<T> getTombstoneKey() {
+ PoisoningVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
+ return Res;
+ }
+ static unsigned getHashValue(const PoisoningVH<T> &Val) {
+ return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
+ }
+ static bool isEqual(const PoisoningVH<T> &LHS, const PoisoningVH<T> &RHS) {
+ return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
+ RHS.getRawValPtr());
+ }
+};
+
+template <typename T> struct isPodLike<PoisoningVH<T>> {
+#ifdef NDEBUG
+ static const bool value = true;
+#else
+ static const bool value = false;
+#endif
+};
+
} // End llvm namespace
#endif
diff --git a/include/llvm/IR/ValueSymbolTable.h b/include/llvm/IR/ValueSymbolTable.h
index 61a12db403ea..9e86751dae6f 100644
--- a/include/llvm/IR/ValueSymbolTable.h
+++ b/include/llvm/IR/ValueSymbolTable.h
@@ -1,4 +1,4 @@
-//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- C++ -*-===//
+//===- llvm/ValueSymbolTable.h - Implement a Value Symtab -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,31 +15,36 @@
#define LLVM_IR_VALUESYMBOLTABLE_H
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Value.h"
-#include "llvm/Support/DataTypes.h"
+#include <cstdint>
namespace llvm {
- template <typename ValueSubClass> class SymbolTableListTraits;
- template <unsigned InternalLen> class SmallString;
- class BasicBlock;
- class Function;
- class NamedMDNode;
- class Module;
- class StringRef;
+
+class Argument;
+class BasicBlock;
+class Function;
+class GlobalAlias;
+class GlobalIFunc;
+class GlobalVariable;
+class Instruction;
+template <unsigned InternalLen> class SmallString;
+template <typename ValueSubClass> class SymbolTableListTraits;
/// This class provides a symbol table of name/value pairs. It is essentially
/// a std::map<std::string,Value*> but has a controlled interface provided by
/// LLVM as well as ensuring uniqueness of names.
///
class ValueSymbolTable {
- friend class Value;
friend class SymbolTableListTraits<Argument>;
friend class SymbolTableListTraits<BasicBlock>;
- friend class SymbolTableListTraits<Instruction>;
friend class SymbolTableListTraits<Function>;
- friend class SymbolTableListTraits<GlobalVariable>;
friend class SymbolTableListTraits<GlobalAlias>;
friend class SymbolTableListTraits<GlobalIFunc>;
+ friend class SymbolTableListTraits<GlobalVariable>;
+ friend class SymbolTableListTraits<Instruction>;
+ friend class Value;
+
/// @name Types
/// @{
public:
@@ -55,14 +60,14 @@ public:
/// @}
/// @name Constructors
/// @{
-public:
- ValueSymbolTable() : vmap(0), LastUnique(0) {}
+
+ ValueSymbolTable() : vmap(0) {}
~ValueSymbolTable();
/// @}
/// @name Accessors
/// @{
-public:
+
/// This method finds the value with the given \p Name in the
/// the symbol table.
/// @returns the value associated with the \p Name
@@ -84,7 +89,7 @@ public:
/// @}
/// @name Iteration
/// @{
-public:
+
/// @brief Get an iterator that from the beginning of the symbol table.
inline iterator begin() { return vmap.begin(); }
@@ -122,13 +127,13 @@ private:
/// @}
/// @name Internal Data
/// @{
-private:
+
ValueMap vmap; ///< The map that holds the symbol table.
- mutable uint32_t LastUnique; ///< Counter for tracking unique names
+ mutable uint32_t LastUnique = 0; ///< Counter for tracking unique names
/// @}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_VALUESYMBOLTABLE_H