summaryrefslogtreecommitdiff
path: root/include/llvm/IR
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-18 16:17:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-18 16:17:27 +0000
commit67c32a98315f785a9ec9d531c1f571a0196c7463 (patch)
tree4abb9cbeecc7901726dd0b4a37369596c852e9ef /include/llvm/IR
parent9f61947910e6ab40de38e6b4034751ef1513200f (diff)
Diffstat (limited to 'include/llvm/IR')
-rw-r--r--include/llvm/IR/Argument.h8
-rw-r--r--include/llvm/IR/AssemblyAnnotationWriter.h4
-rw-r--r--include/llvm/IR/BasicBlock.h16
-rw-r--r--include/llvm/IR/CFG.h6
-rw-r--r--include/llvm/IR/CallingConv.h11
-rw-r--r--include/llvm/IR/Constant.h8
-rw-r--r--include/llvm/IR/ConstantRange.h99
-rw-r--r--include/llvm/IR/Constants.h158
-rw-r--r--include/llvm/IR/DIBuilder.h224
-rw-r--r--include/llvm/IR/DataLayout.h311
-rw-r--r--include/llvm/IR/DebugInfo.h776
-rw-r--r--include/llvm/IR/DebugLoc.h98
-rw-r--r--include/llvm/IR/DerivedTypes.h17
-rw-r--r--include/llvm/IR/DiagnosticInfo.h17
-rw-r--r--include/llvm/IR/DiagnosticPrinter.h4
-rw-r--r--include/llvm/IR/Dominators.h49
-rw-r--r--include/llvm/IR/Function.h33
-rw-r--r--include/llvm/IR/GVMaterializer.h10
-rw-r--r--include/llvm/IR/GlobalObject.h16
-rw-r--r--include/llvm/IR/GlobalValue.h12
-rw-r--r--include/llvm/IR/IRBuilder.h139
-rw-r--r--include/llvm/IR/IRPrintingPasses.h8
-rw-r--r--include/llvm/IR/InlineAsm.h12
-rw-r--r--include/llvm/IR/InstrTypes.h88
-rw-r--r--include/llvm/IR/Instruction.h42
-rw-r--r--include/llvm/IR/Instructions.h24
-rw-r--r--include/llvm/IR/IntrinsicInst.h46
-rw-r--r--include/llvm/IR/Intrinsics.h44
-rw-r--r--include/llvm/IR/Intrinsics.td59
-rw-r--r--include/llvm/IR/IntrinsicsARM.td12
-rw-r--r--include/llvm/IR/IntrinsicsNVVM.td18
-rw-r--r--include/llvm/IR/IntrinsicsPowerPC.td70
-rw-r--r--include/llvm/IR/IntrinsicsR600.td17
-rw-r--r--include/llvm/IR/IntrinsicsX86.td780
-rw-r--r--include/llvm/IR/LLVMContext.h34
-rw-r--r--include/llvm/IR/LeakDetector.h92
-rw-r--r--include/llvm/IR/LegacyPassManager.h12
-rw-r--r--include/llvm/IR/LegacyPassManagers.h10
-rw-r--r--include/llvm/IR/MDBuilder.h48
-rw-r--r--include/llvm/IR/Mangler.h6
-rw-r--r--include/llvm/IR/Metadata.def59
-rw-r--r--include/llvm/IR/Metadata.h954
-rw-r--r--include/llvm/IR/MetadataTracking.h99
-rw-r--r--include/llvm/IR/Module.h96
-rw-r--r--include/llvm/IR/Operator.h72
-rw-r--r--include/llvm/IR/PassManager.h821
-rw-r--r--include/llvm/IR/PassManagerInternal.h349
-rw-r--r--include/llvm/IR/PatternMatch.h766
-rw-r--r--include/llvm/IR/PredIteratorCache.h6
-rw-r--r--include/llvm/IR/Statepoint.h215
-rw-r--r--include/llvm/IR/TrackingMDRef.h170
-rw-r--r--include/llvm/IR/Type.h9
-rw-r--r--include/llvm/IR/TypeFinder.h1
-rw-r--r--include/llvm/IR/UseListOrder.h62
-rw-r--r--include/llvm/IR/User.h45
-rw-r--r--include/llvm/IR/Value.h334
-rw-r--r--include/llvm/IR/ValueHandle.h165
-rw-r--r--include/llvm/IR/ValueMap.h45
-rw-r--r--include/llvm/IR/Verifier.h4
59 files changed, 5362 insertions, 2348 deletions
diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h
index 7c398a5e5530..dd76a90aa5ea 100644
--- a/include/llvm/IR/Argument.h
+++ b/include/llvm/IR/Argument.h
@@ -105,6 +105,14 @@ public:
/// its containing function.
bool hasInAllocaAttr() const;
+ /// \brief Return true if this argument has the zext attribute on it in its
+ /// containing function.
+ bool hasZExtAttr() const;
+
+ /// \brief Return true if this argument has the sext attribute on it in its
+ /// containing function.
+ bool hasSExtAttr() const;
+
/// \brief Add a Attribute to an argument.
void addAttr(AttributeSet AS);
diff --git a/include/llvm/IR/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h
index a8d52f68176c..19e32a2dcdcc 100644
--- a/include/llvm/IR/AssemblyAnnotationWriter.h
+++ b/include/llvm/IR/AssemblyAnnotationWriter.h
@@ -14,8 +14,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_ASMANNOTATIONWRITER_H
-#define LLVM_IR_ASMANNOTATIONWRITER_H
+#ifndef LLVM_IR_ASSEMBLYANNOTATIONWRITER_H
+#define LLVM_IR_ASSEMBLYANNOTATIONWRITER_H
namespace llvm {
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index a19489aa49b1..7c7dd2ca5643 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -23,6 +23,7 @@
namespace llvm {
+class CallInst;
class LandingPadInst;
class TerminatorInst;
class LLVMContext;
@@ -125,6 +126,14 @@ public:
TerminatorInst *getTerminator();
const TerminatorInst *getTerminator() const;
+ /// \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();
+ }
+
/// \brief Returns a pointer to the first instruction in this block that is
/// not a PHINode instruction.
///
@@ -173,6 +182,13 @@ public:
/// right after \p MovePos in the function \p MovePos lives in.
void moveAfter(BasicBlock *MovePos);
+ /// \brief Insert unlinked basic block into a function.
+ ///
+ /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is
+ /// provided, inserts before that basic block, otherwise inserts at the end.
+ ///
+ /// \pre \a getParent() is \c nullptr.
+ void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr);
/// \brief Return the predecessor of this block if it has a single predecessor
/// block. Otherwise return a null pointer.
diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h
index c8be8bd1f2a7..5400d2384868 100644
--- a/include/llvm/IR/CFG.h
+++ b/include/llvm/IR/CFG.h
@@ -93,6 +93,9 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);}
inline const_pred_iterator pred_end(const BasicBlock *BB) {
return const_pred_iterator(BB, true);
}
+inline bool pred_empty(const BasicBlock *BB) {
+ return pred_begin(BB) == pred_end(BB);
+}
@@ -257,6 +260,9 @@ inline succ_iterator succ_end(BasicBlock *BB) {
inline succ_const_iterator succ_end(const BasicBlock *BB) {
return succ_const_iterator(BB->getTerminator(), true);
}
+inline bool succ_empty(const BasicBlock *BB) {
+ return succ_begin(BB) == succ_end(BB);
+}
template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > {
static const bool value = isPodLike<T>::value;
diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h
index 1eaf4f7f469f..9872e6ec794d 100644
--- a/include/llvm/IR/CallingConv.h
+++ b/include/llvm/IR/CallingConv.h
@@ -20,10 +20,13 @@ namespace llvm {
/// the well-known calling conventions.
///
namespace CallingConv {
+ /// LLVM IR allows to use arbitrary numbers as calling convention identifiers.
+ typedef unsigned ID;
+
/// A set of enums which specify the assigned numeric values for known llvm
/// calling conventions.
/// @brief LLVM Calling Convention Representation
- enum ID {
+ enum {
/// C - The default llvm calling convention, compatible with C. This
/// convention is the only calling convention that supports varargs calls.
/// As with typical C calling conventions, the callee/caller have to
@@ -137,7 +140,11 @@ namespace CallingConv {
/// convention differs from the more common \c X86_64_SysV convention
/// in a number of ways, most notably in that XMM registers used to pass
/// arguments are shadowed by GPRs, and vice versa.
- X86_64_Win64 = 79
+ X86_64_Win64 = 79,
+
+ /// \brief MSVC calling convention that passes vectors and vector aggregates
+ /// in SSE registers.
+ X86_VectorCall = 80
};
} // End CallingConv namespace
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 82ad9fc2f407..d26991eaab75 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -48,11 +48,16 @@ protected:
: User(ty, vty, Ops, NumOps) {}
void destroyConstantImpl();
+ void replaceUsesOfWithOnConstantImpl(Constant *Replacement);
+
public:
/// isNullValue - Return true if this is the value that would be returned by
/// getNullValue.
bool isNullValue() const;
+ /// \brief Returns true if the value is one.
+ bool isOneValue() const;
+
/// isAllOnesValue - Return true if this is the value that would be returned by
/// getAllOnesValue.
bool isAllOnesValue() const;
@@ -64,6 +69,9 @@ public:
/// Return true if the value is negative zero or null value.
bool isZeroValue() const;
+ /// \brief Return true if the value is not the smallest signed value.
+ bool isNotMinSignedValue() const;
+
/// \brief Return true if the value is the smallest signed value.
bool isMinSignedValue() const;
diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h
index 342422cbe25f..5e8cd34c4d69 100644
--- a/include/llvm/IR/ConstantRange.h
+++ b/include/llvm/IR/ConstantRange.h
@@ -29,15 +29,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_CONSTANTRANGE_H
-#define LLVM_SUPPORT_CONSTANTRANGE_H
+#ifndef LLVM_IR_CONSTANTRANGE_H
+#define LLVM_IR_CONSTANTRANGE_H
#include "llvm/ADT/APInt.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
-/// ConstantRange - This class represents an range of values.
+/// This class represents a range of values.
///
class ConstantRange {
APInt Lower, Upper;
@@ -59,7 +59,7 @@ public:
/// assert out if the two APInt's are not the same bit width.
ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper);
- /// makeICmpRegion - Produce the smallest range that contains all values that
+ /// Produce the smallest range that contains all values that
/// might satisfy the comparison specified by Pred when compared to any value
/// contained within Other.
///
@@ -69,47 +69,46 @@ public:
static ConstantRange makeICmpRegion(unsigned Pred,
const ConstantRange &Other);
- /// getLower - Return the lower value for this range...
+ /// Return the lower value for this range.
///
const APInt &getLower() const { return Lower; }
- /// getUpper - Return the upper value for this range...
+ /// Return the upper value for this range.
///
const APInt &getUpper() const { return Upper; }
- /// getBitWidth - get the bit width of this ConstantRange
+ /// Get the bit width of this ConstantRange.
///
uint32_t getBitWidth() const { return Lower.getBitWidth(); }
- /// isFullSet - Return true if this set contains all of the elements possible
- /// for this data-type
+ /// Return true if this set contains all of the elements possible
+ /// for this data-type.
///
bool isFullSet() const;
- /// isEmptySet - Return true if this set contains no members.
+ /// Return true if this set contains no members.
///
bool isEmptySet() const;
- /// isWrappedSet - Return true if this set wraps around the top of the range,
- /// for example: [100, 8)
+ /// Return true if this set wraps around the top of the range.
+ /// For example: [100, 8).
///
bool isWrappedSet() const;
- /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of
- /// its bitwidth, for example: i8 [120, 140).
+ /// Return true if this set wraps around the INT_MIN of
+ /// its bitwidth. For example: i8 [120, 140).
///
bool isSignWrappedSet() const;
- /// contains - Return true if the specified value is in the set.
+ /// Return true if the specified value is in the set.
///
bool contains(const APInt &Val) const;
- /// contains - Return true if the other range is a subset of this one.
+ /// Return true if the other range is a subset of this one.
///
bool contains(const ConstantRange &CR) const;
- /// getSingleElement - If this set contains a single element, return it,
- /// otherwise return null.
+ /// If this set contains a single element, return it, otherwise return null.
///
const APInt *getSingleElement() const {
if (Upper == Lower + 1)
@@ -117,35 +116,31 @@ public:
return nullptr;
}
- /// isSingleElement - Return true if this set contains exactly one member.
+ /// Return true if this set contains exactly one member.
///
bool isSingleElement() const { return getSingleElement() != nullptr; }
- /// getSetSize - Return the number of elements in this set.
+ /// Return the number of elements in this set.
///
APInt getSetSize() const;
- /// getUnsignedMax - Return the largest unsigned value contained in the
- /// ConstantRange.
+ /// Return the largest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMax() const;
- /// getUnsignedMin - Return the smallest unsigned value contained in the
- /// ConstantRange.
+ /// Return the smallest unsigned value contained in the ConstantRange.
///
APInt getUnsignedMin() const;
- /// getSignedMax - Return the largest signed value contained in the
- /// ConstantRange.
+ /// Return the largest signed value contained in the ConstantRange.
///
APInt getSignedMax() const;
- /// getSignedMin - Return the smallest signed value contained in the
- /// ConstantRange.
+ /// Return the smallest signed value contained in the ConstantRange.
///
APInt getSignedMin() const;
- /// operator== - Return true if this range is equal to another range.
+ /// Return true if this range is equal to another range.
///
bool operator==(const ConstantRange &CR) const {
return Lower == CR.Lower && Upper == CR.Upper;
@@ -154,15 +149,14 @@ public:
return !operator==(CR);
}
- /// subtract - Subtract the specified constant from the endpoints of this
- /// constant range.
+ /// Subtract the specified constant from the endpoints of this constant range.
ConstantRange subtract(const APInt &CI) const;
/// \brief Subtract the specified range from this range (aka relative
/// complement of the sets).
ConstantRange difference(const ConstantRange &CR) const;
- /// intersectWith - Return the range that results from the intersection of
+ /// Return the range that results from the intersection of
/// this range with another range. The resultant range is guaranteed to
/// include all elements contained in both input ranges, and to have the
/// smallest possible set size that does so. Because there may be two
@@ -171,7 +165,7 @@ public:
///
ConstantRange intersectWith(const ConstantRange &CR) const;
- /// unionWith - Return the range that results from the union of this range
+ /// Return the range that results from the union of this range
/// with another range. The resultant range is guaranteed to include the
/// elements of both sets, but may contain more. For example, [3, 9) union
/// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included
@@ -179,85 +173,84 @@ public:
///
ConstantRange unionWith(const ConstantRange &CR) const;
- /// zeroExtend - Return a new range in the specified integer type, which must
+ /// Return a new range in the specified integer type, which must
/// be strictly larger than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// zero extended to BitWidth.
ConstantRange zeroExtend(uint32_t BitWidth) const;
- /// signExtend - Return a new range in the specified integer type, which must
+ /// Return a new range in the specified integer type, which must
/// be strictly larger than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// sign extended to BitWidth.
ConstantRange signExtend(uint32_t BitWidth) const;
- /// truncate - Return a new range in the specified integer type, which must be
+ /// Return a new range in the specified integer type, which must be
/// strictly smaller than the current type. The returned range will
/// correspond to the possible range of values if the source range had been
/// truncated to the specified type.
ConstantRange truncate(uint32_t BitWidth) const;
- /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The
+ /// Make this range have the bit width given by \p BitWidth. The
/// value is zero extended, truncated, or left alone to make it that width.
ConstantRange zextOrTrunc(uint32_t BitWidth) const;
- /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The
+ /// Make this range have the bit width given by \p BitWidth. The
/// value is sign extended, truncated, or left alone to make it that width.
ConstantRange sextOrTrunc(uint32_t BitWidth) const;
- /// add - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an addition of a value in this range and a value in \p Other.
ConstantRange add(const ConstantRange &Other) const;
- /// sub - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a subtraction of a value in this range and a value in \p Other.
ConstantRange sub(const ConstantRange &Other) const;
- /// multiply - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a multiplication of a value in this range and a value in \p Other.
/// TODO: This isn't fully implemented yet.
ConstantRange multiply(const ConstantRange &Other) const;
- /// smax - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a signed maximum of a value in this range and a value in \p Other.
ConstantRange smax(const ConstantRange &Other) const;
- /// umax - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an unsigned maximum of a value in this range and a value in \p Other.
ConstantRange umax(const ConstantRange &Other) const;
- /// udiv - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from an unsigned division of a value in this range and a value in
/// \p Other.
ConstantRange udiv(const ConstantRange &Other) const;
- /// binaryAnd - return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a binary-and of a value in this range by a value in \p Other.
ConstantRange binaryAnd(const ConstantRange &Other) const;
- /// binaryOr - return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a binary-or of a value in this range by a value in \p Other.
ConstantRange binaryOr(const ConstantRange &Other) const;
- /// shl - Return a new range representing the possible values resulting
+ /// Return a new range representing the possible values resulting
/// from a left shift of a value in this range by a value in \p Other.
/// TODO: This isn't fully implemented yet.
ConstantRange shl(const ConstantRange &Other) const;
- /// lshr - Return a new range representing the possible values resulting
- /// from a logical right shift of a value in this range and a value in
- /// \p Other.
+ /// Return a new range representing the possible values resulting from a
+ /// logical right shift of a value in this range and a value in \p Other.
ConstantRange lshr(const ConstantRange &Other) const;
- /// inverse - Return a new range that is the logical not of the current set.
+ /// Return a new range that is the logical not of the current set.
///
ConstantRange inverse() const;
- /// print - Print out the bounds to a stream...
+ /// Print out the bounds to a stream.
///
void print(raw_ostream &OS) const;
- /// dump - Allow printing from a debugger easily...
+ /// Allow printing from a debugger easily.
///
void dump() const;
};
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index 0e72f040d3e0..1b0e1b7e7b77 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -37,12 +37,8 @@ class PointerType;
class VectorType;
class SequentialType;
-template<class ConstantClass, class TypeClass, class ValType>
-struct ConstantCreator;
-template<class ConstantClass, class TypeClass>
-struct ConstantArrayCreator;
-template<class ConstantClass, class TypeClass>
-struct ConvertConstantType;
+struct ConstantExprKeyType;
+template <class ConstantClass> struct ConstantAggrKeyType;
//===----------------------------------------------------------------------===//
/// This is the shared class of boolean and integer constants. This class
@@ -268,6 +264,9 @@ public:
/// isNegative - Return true if the sign bit is set.
bool isNegative() const { return Val.isNegative(); }
+ /// isInfinity - Return true if the value is infinity
+ bool isInfinity() const { return Val.isInfinity(); }
+
/// isNaN - Return true if the value is a NaN.
bool isNaN() const { return Val.isNaN(); }
@@ -338,7 +337,7 @@ public:
/// ConstantArray - Constant Array Declarations
///
class ConstantArray : public Constant {
- friend struct ConstantArrayCreator<ConstantArray, ArrayType>;
+ friend struct ConstantAggrKeyType<ConstantArray>;
ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION;
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
@@ -346,6 +345,10 @@ public:
// ConstantArray accessors
static Constant *get(ArrayType *T, ArrayRef<Constant*> V);
+private:
+ static Constant *getImpl(ArrayType *T, ArrayRef<Constant *> V);
+
+public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
@@ -376,14 +379,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
// ConstantStruct - Constant Struct Declarations
//
class ConstantStruct : public Constant {
- friend struct ConstantArrayCreator<ConstantStruct, StructType>;
+ friend struct ConstantAggrKeyType<ConstantStruct>;
ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION;
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
public:
// ConstantStruct accessors
static Constant *get(StructType *T, ArrayRef<Constant*> V);
- static Constant *get(StructType *T, ...) END_WITH_NULL;
+ static Constant *get(StructType *T, ...) LLVM_END_WITH_NULL;
/// getAnon - Return an anonymous struct that has the specified
/// elements. If the struct is possibly empty, then you must specify a
@@ -435,7 +438,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
/// ConstantVector - Constant Vector Declarations
///
class ConstantVector : public Constant {
- friend struct ConstantArrayCreator<ConstantVector, VectorType>;
+ friend struct ConstantAggrKeyType<ConstantVector>;
ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION;
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);
@@ -443,6 +446,10 @@ public:
// ConstantVector accessors
static Constant *get(ArrayRef<Constant*> V);
+private:
+ static Constant *getImpl(ArrayRef<Constant *> V);
+
+public:
/// getSplat - Return a ConstantVector with the specified constant in each
/// element.
static Constant *getSplat(unsigned NumElts, Constant *Elt);
@@ -794,9 +801,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value)
/// constant expressions. The Opcode field for the ConstantExpr class is
/// maintained in the Value::SubclassData field.
class ConstantExpr : public Constant {
- friend struct ConstantCreator<ConstantExpr,Type,
- std::pair<unsigned, std::vector<Constant*> > >;
- friend struct ConvertConstantType<ConstantExpr, Type>;
+ friend struct ConstantExprKeyType;
protected:
ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps)
@@ -856,19 +861,25 @@ public:
bool HasNUW = false, bool HasNSW = false);
static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false);
static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false);
- static Constant *getTrunc (Constant *C, Type *Ty);
- static Constant *getSExt (Constant *C, Type *Ty);
- static Constant *getZExt (Constant *C, Type *Ty);
- static Constant *getFPTrunc (Constant *C, Type *Ty);
- static Constant *getFPExtend(Constant *C, Type *Ty);
- static Constant *getUIToFP (Constant *C, Type *Ty);
- static Constant *getSIToFP (Constant *C, Type *Ty);
- static Constant *getFPToUI (Constant *C, Type *Ty);
- static Constant *getFPToSI (Constant *C, Type *Ty);
- static Constant *getPtrToInt(Constant *C, Type *Ty);
- static Constant *getIntToPtr(Constant *C, Type *Ty);
- static Constant *getBitCast (Constant *C, Type *Ty);
- static Constant *getAddrSpaceCast(Constant *C, Type *Ty);
+ static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getSExt(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getZExt(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPTrunc(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getFPExtend(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced = false);
+ static Constant *getPtrToInt(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getIntToPtr(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getBitCast(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
+ static Constant *getAddrSpaceCast(Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); }
static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); }
@@ -923,13 +934,14 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
- // @brief Convenience function for getting one of the casting operations
- // using a CastOps opcode.
- static Constant *getCast(
- unsigned ops, ///< The opcode for the conversion
- Constant *C, ///< The constant to be converted
- Type *Ty ///< The type to which the constant is converted
- );
+ /// \brief Convenience function for getting a Cast operation.
+ ///
+ /// \param ops The opcode for the conversion
+ /// \param C The constant to be converted
+ /// \param Ty The type to which the constant is converted
+ /// \param OnlyIfReduced see \a getWithOperands() docs.
+ static Constant *getCast(unsigned ops, Constant *C, Type *Ty,
+ bool OnlyIfReduced = false);
// @brief Create a ZExt or BitCast cast constant expression
static Constant *getZExtOrBitCast(
@@ -995,44 +1007,53 @@ public:
/// Select constant expr
///
- static Constant *getSelect(Constant *C, Constant *V1, Constant *V2);
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
+ static Constant *getSelect(Constant *C, Constant *V1, Constant *V2,
+ Type *OnlyIfReducedTy = nullptr);
/// get - Return a binary or shift operator constant expression,
/// folding if possible.
///
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
static Constant *get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags = 0);
+ unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr);
- /// @brief Return an ICmp or FCmp comparison operator constant expression.
- static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2);
+ /// \brief Return an ICmp or FCmp comparison operator constant expression.
+ ///
+ /// \param OnlyIfReduced see \a getWithOperands() docs.
+ static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2,
+ bool OnlyIfReduced = false);
/// get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier.
///
- static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS);
- static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS);
+ static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS,
+ bool OnlyIfReduced = false);
+ static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS,
+ bool OnlyIfReduced = false);
/// Getelementptr form. Value* is only accepted for convenience;
/// all elements must be Constant's.
///
- static Constant *getGetElementPtr(Constant *C,
- ArrayRef<Constant *> IdxList,
- bool InBounds = false) {
- return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(),
- IdxList.size()),
- InBounds);
- }
- static Constant *getGetElementPtr(Constant *C,
- Constant *Idx,
- bool InBounds = false) {
+ /// \param OnlyIfReducedTy see \a getWithOperands() docs.
+ static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr) {
+ return getGetElementPtr(
+ C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()),
+ InBounds, OnlyIfReducedTy);
+ }
+ static Constant *getGetElementPtr(Constant *C, Constant *Idx,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr) {
// This form of the function only exists to avoid ambiguous overload
// warnings about whether to convert Idx to ArrayRef<Constant *> or
// ArrayRef<Value *>.
- return getGetElementPtr(C, cast<Value>(Idx), InBounds);
+ return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy);
}
- static Constant *getGetElementPtr(Constant *C,
- ArrayRef<Value *> IdxList,
- bool InBounds = false);
+ static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList,
+ bool InBounds = false,
+ Type *OnlyIfReducedTy = nullptr);
/// Create an "inbounds" getelementptr. See the documentation for the
/// "inbounds" flag in LangRef.html for details.
@@ -1052,12 +1073,17 @@ public:
return getGetElementPtr(C, IdxList, true);
}
- static Constant *getExtractElement(Constant *Vec, Constant *Idx);
- static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx);
- static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask);
- static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs);
+ static Constant *getExtractElement(Constant *Vec, Constant *Idx,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask,
+ Type *OnlyIfReducedTy = nullptr);
+ static Constant *getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy = nullptr);
static Constant *getInsertValue(Constant *Agg, Constant *Val,
- ArrayRef<unsigned> Idxs);
+ ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy = nullptr);
/// getOpcode - Return the opcode at the root of this constant expression
unsigned getOpcode() const { return getSubclassDataFromValue(); }
@@ -1084,11 +1110,17 @@ public:
return getWithOperands(Ops, getType());
}
- /// getWithOperands - This returns the current constant expression with the
- /// operands replaced with the specified values and with the specified result
- /// type. The specified array must have the same number of operands as our
- /// current one.
- Constant *getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const;
+ /// \brief Get the current expression with the operands replaced.
+ ///
+ /// Return the current constant expression with the operands replaced with \c
+ /// Ops and the type with \c Ty. The new operands must have the same number
+ /// as the current ones.
+ ///
+ /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something
+ /// gets constant-folded, the type changes, or the expression is otherwise
+ /// canonicalized. This parameter should almost always be \c false.
+ Constant *getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
+ bool OnlyIfReduced = false) const;
/// getAsInstruction - Returns an Instruction which implements the same operation
/// as this ConstantExpr. The instruction is not linked to any basic block.
diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h
index 267350409604..ae1ac650a9ec 100644
--- a/include/llvm/IR/DIBuilder.h
+++ b/include/llvm/IR/DIBuilder.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/DataTypes.h"
@@ -27,6 +28,7 @@ namespace llvm {
class Function;
class Module;
class Value;
+ class Constant;
class LLVMContext;
class MDNode;
class StringRef;
@@ -38,7 +40,6 @@ namespace llvm {
class DIFile;
class DIEnumerator;
class DIType;
- class DIArray;
class DIGlobalVariable;
class DIImportedEntity;
class DINameSpace;
@@ -53,7 +54,6 @@ namespace llvm {
class DIObjCProperty;
class DIBuilder {
- private:
Module &M;
LLVMContext &VMContext;
@@ -66,27 +66,34 @@ namespace llvm {
Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value
- SmallVector<Value *, 4> AllEnumTypes;
- /// Use TrackingVH to collect RetainTypes, since they can be updated
- /// later on.
- SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes;
- SmallVector<Value *, 4> AllSubprograms;
- SmallVector<Value *, 4> AllGVs;
- SmallVector<TrackingVH<MDNode>, 4> AllImportedModules;
+ SmallVector<Metadata *, 4> AllEnumTypes;
+ /// Track the RetainTypes, since they can be updated later on.
+ SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
+ SmallVector<Metadata *, 4> AllSubprograms;
+ SmallVector<Metadata *, 4> AllGVs;
+ SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
- // Private use for multiple types of template parameters.
- DITemplateValueParameter
- createTemplateValueParameter(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIType Ty, Value *Val,
- MDNode *File = nullptr, unsigned LineNo = 0,
- unsigned ColumnNo = 0);
+ /// \brief Track nodes that may be unresolved.
+ SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
+ bool AllowUnresolvedNodes;
+
+ /// Each subprogram's preserved local variables.
+ DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables;
DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION;
void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION;
- public:
- explicit DIBuilder(Module &M);
- enum ComplexAddrKind { OpPlus=1, OpDeref };
+ /// \brief Create a temporary.
+ ///
+ /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes.
+ void trackIfUnresolved(MDNode *N);
+
+ public:
+ /// \brief Construct a builder for a module.
+ ///
+ /// If \c AllowUnresolved, collect unresolved nodes attached to the module
+ /// in order to resolve cycles during \a finalize().
+ explicit DIBuilder(Module &M, bool AllowUnresolved = true);
enum DebugEmissionKind { FullDebug=1, LineTablesOnly };
/// finalize - Construct any deferred debug info descriptors.
@@ -165,8 +172,12 @@ namespace llvm {
/// \brief Create debugging information entry for a pointer to member.
/// @param PointeeTy Type pointed to by this pointer.
+ /// @param SizeInBits Size.
+ /// @param AlignInBits Alignment. (optional)
/// @param Class Type for which this pointer points to members of.
- DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class);
+ DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits = 0);
/// createReferenceType - Create debugging information entry for a c++
/// style reference or rvalue reference type.
@@ -218,36 +229,10 @@ namespace llvm {
/// @param Ty Type of the static member.
/// @param Flags Flags to encode member attribute, e.g. private.
/// @param Val Const initializer of the member.
- DIDerivedType
- createStaticMemberType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNo, DIType Ty,
- unsigned Flags, llvm::Value *Val);
-
- /// createObjCIVar - Create debugging information entry for Objective-C
- /// instance variable.
- /// @param Name Member name.
- /// @param File File where this member is defined.
- /// @param LineNo Line number.
- /// @param SizeInBits Member size.
- /// @param AlignInBits Member alignment.
- /// @param OffsetInBits Member offset.
- /// @param Flags Flags to encode member attribute, e.g. private
- /// @param Ty Parent type.
- /// @param PropertyName Name of the Objective C property associated with
- /// this ivar.
- /// @param PropertyGetterName Name of the Objective C property getter
- /// selector.
- /// @param PropertySetterName Name of the Objective C property setter
- /// selector.
- /// @param PropertyAttributes Objective C property attributes.
- DIDerivedType createObjCIVar(StringRef Name, DIFile File,
- unsigned LineNo, uint64_t SizeInBits,
- uint64_t AlignInBits, uint64_t OffsetInBits,
- unsigned Flags, DIType Ty,
- StringRef PropertyName = StringRef(),
- StringRef PropertyGetterName = StringRef(),
- StringRef PropertySetterName = StringRef(),
- unsigned PropertyAttributes = 0);
+ DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name,
+ DIFile File, unsigned LineNo,
+ DIType Ty, unsigned Flags,
+ llvm::Constant *Val);
/// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable.
@@ -366,8 +351,8 @@ namespace llvm {
/// @param LineNo Line number.
/// @param ColumnNo Column Number.
DITemplateValueParameter
- createTemplateValueParameter(DIDescriptor Scope, StringRef Name,
- DIType Ty, Value *Val, MDNode *File = nullptr,
+ createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
+ Constant *Val, MDNode *File = nullptr,
unsigned LineNo = 0, unsigned ColumnNo = 0);
/// \brief Create debugging information for a template template parameter.
@@ -435,8 +420,9 @@ namespace llvm {
/// includes return type at 0th index.
/// @param Flags E.g.: LValueReference.
/// These flags are used to emit dwarf attributes.
- DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes,
- unsigned Flags = 0);
+ DISubroutineType createSubroutineType(DIFile File,
+ DITypeArray ParameterTypes,
+ unsigned Flags = 0);
/// createArtificialType - Create a new DIType with "artificial" flag set.
DIType createArtificialType(DIType Ty);
@@ -463,44 +449,22 @@ namespace llvm {
/// through debug info anchors.
void retainType(DIType T);
- /// createUnspecifiedParameter - Create unspecified type descriptor
+ /// createUnspecifiedParameter - Create unspecified parameter type
/// for a subroutine type.
- DIDescriptor createUnspecifiedParameter();
+ DIBasicType createUnspecifiedParameter();
/// getOrCreateArray - Get a DIArray, create one if required.
- DIArray getOrCreateArray(ArrayRef<Value *> Elements);
+ DIArray getOrCreateArray(ArrayRef<Metadata *> Elements);
+
+ /// getOrCreateTypeArray - Get a DITypeArray, create one if required.
+ DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements);
/// getOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count);
- /// createGlobalVariable - Create a new descriptor for the specified global.
- /// @param Name Name of the variable.
- /// @param File File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type.
- /// @param isLocalToUnit Boolean flag indicate whether this variable is
- /// externally visible or not.
- /// @param Val llvm::Value of the variable.
- DIGlobalVariable
- createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
- DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val);
- /// \brief Create a new descriptor for the specified global.
- /// @param Name Name of the variable.
- /// @param LinkageName Mangled variable name.
- /// @param File File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type.
- /// @param isLocalToUnit Boolean flag indicate whether this variable is
- /// externally visible or not.
- /// @param Val llvm::Value of the variable.
- DIGlobalVariable
- createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File,
- unsigned LineNo, DITypeRef Ty, bool isLocalToUnit,
- llvm::Value *Val);
-
- /// createStaticVariable - Create a new descriptor for the specified
+ /// createGlobalVariable - Create a new descriptor for the specified
/// variable.
/// @param Context Variable scope.
/// @param Name Name of the variable.
@@ -512,12 +476,19 @@ namespace llvm {
/// externally visible or not.
/// @param Val llvm::Value of the variable.
/// @param Decl Reference to the corresponding declaration.
- DIGlobalVariable
- createStaticVariable(DIDescriptor Context, StringRef Name,
- StringRef LinkageName, DIFile File, unsigned LineNo,
- DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val,
- MDNode *Decl = nullptr);
-
+ DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile File,
+ unsigned LineNo, DITypeRef Ty,
+ bool isLocalToUnit,
+ llvm::Constant *Val,
+ MDNode *Decl = nullptr);
+
+ /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable
+ /// except that the resulting DbgNode is temporary and meant to be RAUWed.
+ DIGlobalVariable createTempGlobalVariableFwdDecl(
+ DIDescriptor Context, StringRef Name, StringRef LinkageName,
+ DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit,
+ llvm::Constant *Val, MDNode *Decl = nullptr);
/// createLocalVariable - Create a new descriptor for the specified
/// local variable.
@@ -540,23 +511,18 @@ namespace llvm {
unsigned Flags = 0,
unsigned ArgNo = 0);
-
- /// createComplexVariable - Create a new descriptor for the specified
+ /// createExpression - Create a new descriptor for the specified
/// variable which has a complex address expression for its address.
- /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
- /// DW_TAG_arg_variable.
- /// @param Scope Variable scope.
- /// @param Name Variable name.
- /// @param F File where this variable is defined.
- /// @param LineNo Line number.
- /// @param Ty Variable Type
/// @param Addr An array of complex address operations.
- /// @param ArgNo If this variable is an argument then this argument's
- /// number. 1 indicates 1st argument.
- DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIFile F, unsigned LineNo,
- DITypeRef Ty, ArrayRef<Value *> Addr,
- unsigned ArgNo = 0);
+ DIExpression createExpression(ArrayRef<int64_t> Addr = None);
+
+ /// createPieceExpression - Create a descriptor to describe one part
+ /// of aggregate variable that is fragmented across multiple Values.
+ ///
+ /// @param OffsetInBytes Offset of the piece in bytes.
+ /// @param SizeInBytes Size of the piece in bytes.
+ DIExpression createPieceExpression(unsigned OffsetInBytes,
+ unsigned SizeInBytes);
/// createFunction - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields.
@@ -586,6 +552,21 @@ namespace llvm {
MDNode *TParam = nullptr,
MDNode *Decl = nullptr);
+ /// createTempFunctionFwdDecl - Identical to createFunction,
+ /// except that the resulting DbgNode is meant to be RAUWed.
+ DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name,
+ StringRef LinkageName,
+ DIFile File, unsigned LineNo,
+ DICompositeType Ty, bool isLocalToUnit,
+ bool isDefinition,
+ unsigned ScopeLine,
+ unsigned Flags = 0,
+ bool isOptimized = false,
+ Function *Fn = nullptr,
+ MDNode *TParam = nullptr,
+ MDNode *Decl = nullptr);
+
+
/// FIXME: this is added for dragonegg. Once we update dragonegg
/// to call resolve function, this will be removed.
DISubprogram createFunction(DIScopeRef Scope, StringRef Name,
@@ -646,8 +627,9 @@ namespace llvm {
/// lexical block as it crosses a file.
/// @param Scope Lexical block.
/// @param File Source file.
- DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope,
- DIFile File);
+ /// @param Discriminator DWARF path discriminator value.
+ DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File,
+ unsigned Discriminator = 0);
/// createLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context.
@@ -655,10 +637,8 @@ namespace llvm {
/// @param File Source file.
/// @param Line Line number.
/// @param Col Column number.
- /// @param Discriminator DWARF path discriminator value.
DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File,
- unsigned Line, unsigned Col,
- unsigned Discriminator);
+ unsigned Line, unsigned Col);
/// \brief Create a descriptor for an imported module.
/// @param Context The scope this module is imported into
@@ -679,7 +659,7 @@ namespace llvm {
/// @param Decl The declaration (or definition) of a function, type, or
/// variable
/// @param Line Line number
- DIImportedEntity createImportedDeclaration(DIScope Context, DIScope Decl,
+ DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl,
unsigned Line,
StringRef Name = StringRef());
DIImportedEntity createImportedDeclaration(DIScope Context,
@@ -690,36 +670,52 @@ namespace llvm {
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- BasicBlock *InsertAtEnd);
+ DIExpression Expr, BasicBlock *InsertAtEnd);
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
/// @param Storage llvm::Value of the variable
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertBefore Location for the new intrinsic.
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
- Instruction *InsertBefore);
-
+ DIExpression Expr, Instruction *InsertBefore);
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertAtEnd Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo,
+ DIVariable VarInfo, DIExpression Expr,
BasicBlock *InsertAtEnd);
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
/// @param Val llvm::Value of the variable
/// @param Offset Offset
/// @param VarInfo Variable's debug info descriptor.
+ /// @param Expr A complex location expression.
/// @param InsertBefore Location for the new intrinsic.
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
- DIVariable VarInfo,
+ DIVariable VarInfo, DIExpression Expr,
Instruction *InsertBefore);
+ /// \brief Replace the vtable holder in the given composite type.
+ ///
+ /// If this creates a self reference, it may orphan some unresolved cycles
+ /// in the operands of \c T, so \a DIBuilder needs to track that.
+ void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder);
+
+ /// \brief Replace arrays on a composite type.
+ ///
+ /// If \c T is resolved, but the arrays aren't -- which can happen if \c T
+ /// has a self-reference -- \a DIBuilder needs to track the array to
+ /// resolve cycles.
+ void replaceArrays(DICompositeType &T, DIArray Elements,
+ DIArray TParems = DIArray());
};
} // end namespace llvm
diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h
index 877029f92f0b..a9e75955ce74 100644
--- a/include/llvm/IR/DataLayout.h
+++ b/include/llvm/IR/DataLayout.h
@@ -27,7 +27,8 @@
#include "llvm/Pass.h"
#include "llvm/Support/DataTypes.h"
-// this needs to be outside of the namespace, to avoid conflict with llvm-c decl
+// This needs to be outside of the namespace, to avoid conflict with llvm-c
+// decl.
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
namespace llvm {
@@ -45,79 +46,71 @@ class ArrayRef;
/// Enum used to categorize the alignment types stored by LayoutAlignElem
enum AlignTypeEnum {
- INVALID_ALIGN = 0, ///< An invalid alignment
- INTEGER_ALIGN = 'i', ///< Integer type alignment
- VECTOR_ALIGN = 'v', ///< Vector type alignment
- FLOAT_ALIGN = 'f', ///< Floating point type alignment
- AGGREGATE_ALIGN = 'a' ///< Aggregate alignment
+ INVALID_ALIGN = 0,
+ INTEGER_ALIGN = 'i',
+ VECTOR_ALIGN = 'v',
+ FLOAT_ALIGN = 'f',
+ AGGREGATE_ALIGN = 'a'
};
-/// Layout alignment element.
+/// \brief Layout alignment element.
///
/// Stores the alignment data associated with a given alignment type (integer,
/// vector, float) and type bit width.
///
-/// @note The unusual order of elements in the structure attempts to reduce
+/// \note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct LayoutAlignElem {
- unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum)
- unsigned TypeBitWidth : 24; ///< Type bit width
- unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw
- unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw
+ /// \brief Alignment type from \c AlignTypeEnum
+ unsigned AlignType : 8;
+ unsigned TypeBitWidth : 24;
+ unsigned ABIAlign : 16;
+ unsigned PrefAlign : 16;
- /// Initializer
static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
- /// Equality predicate
bool operator==(const LayoutAlignElem &rhs) const;
};
-/// Layout pointer alignment element.
+/// \brief Layout pointer alignment element.
///
/// Stores the alignment data associated with a given pointer and address space.
///
-/// @note The unusual order of elements in the structure attempts to reduce
+/// \note The unusual order of elements in the structure attempts to reduce
/// padding and make the structure slightly more cache friendly.
struct PointerAlignElem {
- unsigned ABIAlign; ///< ABI alignment for this type/bitw
- unsigned PrefAlign; ///< Pref. alignment for this type/bitw
- uint32_t TypeByteWidth; ///< Type byte width
- uint32_t AddressSpace; ///< Address space for the pointer type
+ unsigned ABIAlign;
+ unsigned PrefAlign;
+ uint32_t TypeByteWidth;
+ uint32_t AddressSpace;
/// Initializer
static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign,
- unsigned PrefAlign, uint32_t TypeByteWidth);
- /// Equality predicate
+ unsigned PrefAlign, uint32_t TypeByteWidth);
bool operator==(const PointerAlignElem &rhs) const;
};
-/// This class holds a parsed version of the target data layout string in a
-/// module and provides methods for querying it. The target data layout string
-/// is specified *by the target* - a frontend generating LLVM IR is required to
-/// generate the right target data for the target being codegen'd to.
+/// \brief A parsed version of the target data layout string in and methods for
+/// querying it.
+///
+/// The target data layout string is specified *by the target* - a frontend
+/// generating LLVM IR is required to generate the right target data for the
+/// target being codegen'd to.
class DataLayout {
private:
- bool LittleEndian; ///< Defaults to false
- unsigned StackNaturalAlign; ///< Stack natural alignment
-
- enum ManglingModeT {
- MM_None,
- MM_ELF,
- MM_MachO,
- MM_WINCOFF,
- MM_Mips
- };
+ /// Defaults to false.
+ bool BigEndian;
+
+ unsigned StackNaturalAlign;
+
+ enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips };
ManglingModeT ManglingMode;
- SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
+ SmallVector<unsigned char, 8> LegalIntWidths;
- /// Alignments - Where the primitive type alignment data is stored.
- ///
- /// @sa reset().
- /// @note Could support multiple size pointer alignments, e.g., 32-bit
- /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now,
- /// we don't.
+ /// \brief Primitive type alignment data.
SmallVector<LayoutAlignElem, 16> Alignments;
+
typedef SmallVector<PointerAlignElem, 8> PointersTy;
PointersTy Pointers;
@@ -128,31 +121,28 @@ private:
PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace);
- /// InvalidAlignmentElem - This member is a signal that a requested alignment
- /// type and bit width were not found in the SmallVector.
+ /// This member is a signal that a requested alignment type and bit width were
+ /// not found in the SmallVector.
static const LayoutAlignElem InvalidAlignmentElem;
- /// InvalidPointerElem - This member is a signal that a requested pointer
- /// type and bit width were not found in the DenseSet.
+ /// 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;
- //! Set/initialize target alignments
void setAlignment(AlignTypeEnum align_type, unsigned abi_align,
unsigned pref_align, uint32_t bit_width);
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
bool ABIAlign, Type *Ty) const;
-
- //! Set/initialize pointer alignments
void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
unsigned PrefAlign, uint32_t TypeByteWidth);
- //! Internal helper method that returns requested alignment for type.
+ /// Internal helper method that returns requested alignment for type.
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
- /// Valid alignment predicate.
+ /// \brief Valid alignment predicate.
///
/// Predicate that tests a LayoutAlignElem reference returned by get() against
/// InvalidAlignmentElem.
@@ -160,10 +150,10 @@ private:
return &align != &InvalidAlignmentElem;
}
- /// Valid pointer predicate.
+ /// \brief Valid pointer predicate.
///
- /// Predicate that tests a PointerAlignElem reference returned by get() against
- /// InvalidPointerElem.
+ /// Predicate that tests a PointerAlignElem reference returned by get()
+ /// against \c InvalidPointerElem.
bool validPointer(const PointerAlignElem &align) const {
return &align != &InvalidPointerElem;
}
@@ -184,11 +174,13 @@ public:
/// Initialize target data from properties stored in the module.
explicit DataLayout(const Module *M);
+ void init(const Module *M);
+
DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; }
DataLayout &operator=(const DataLayout &DL) {
clear();
- LittleEndian = DL.isLittleEndian();
+ BigEndian = DL.isBigEndian();
StackNaturalAlign = DL.StackNaturalAlign;
ManglingMode = DL.ManglingMode;
LegalIntWidths = DL.LegalIntWidths;
@@ -200,27 +192,28 @@ public:
bool operator==(const DataLayout &Other) const;
bool operator!=(const DataLayout &Other) const { return !(*this == Other); }
- ~DataLayout(); // Not virtual, do not subclass this class
+ ~DataLayout(); // Not virtual, do not subclass this class
/// Parse a data layout string (with fallback to default values).
void reset(StringRef LayoutDescription);
/// Layout endianness...
- bool isLittleEndian() const { return LittleEndian; }
- bool isBigEndian() const { return !LittleEndian; }
+ bool isLittleEndian() const { return !BigEndian; }
+ bool isBigEndian() const { return BigEndian; }
- /// getStringRepresentation - Return the string representation of the
- /// DataLayout. This representation is in the same format accepted by the
- /// string constructor above.
+ /// \brief Returns the string representation of the DataLayout.
+ ///
+ /// This representation is in the same format accepted by the string
+ /// constructor above.
std::string getStringRepresentation() const;
- /// isLegalInteger - This function returns true if the specified type is
- /// known to be a native integer type supported by the CPU. For example,
- /// i64 is not native on most 32-bit CPUs and i37 is not native on any known
- /// one. This returns false if the integer width is not legal.
+ /// \brief Returns true if the specified type is known to be a native integer
+ /// type supported by the CPU.
///
- /// The width is specified in bits.
+ /// For example, i64 is not native on most 32-bit CPUs and i37 is not native
+ /// on any known one. This returns false if the integer width is not legal.
///
+ /// The width is specified in bits.
bool isLegalInteger(unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (LegalIntWidth == Width)
@@ -228,22 +221,20 @@ public:
return false;
}
- bool isIllegalInteger(unsigned Width) const {
- return !isLegalInteger(Width);
- }
+ bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); }
/// Returns true if the given alignment exceeds the natural stack alignment.
bool exceedsNaturalStackAlignment(unsigned Align) const {
return (StackNaturalAlign != 0) && (Align > StackNaturalAlign);
}
+ unsigned getStackAlignment() const { return StackNaturalAlign; }
+
bool hasMicrosoftFastStdCallMangling() const {
return ManglingMode == MM_WINCOFF;
}
- bool hasLinkerPrivateGlobalPrefix() const {
- return ManglingMode == MM_MachO;
- }
+ bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; }
const char *getLinkerPrivateGlobalPrefix() const {
if (ManglingMode == MM_MachO)
@@ -281,10 +272,11 @@ public:
static const char *getManglingComponent(const Triple &T);
- /// fitsInLegalInteger - This function returns true if the specified type fits
- /// in a native integer type supported by the CPU. For example, if the CPU
- /// only supports i32 as a native integer type, then i27 fits in a legal
- /// integer type but i45 does not.
+ /// \brief Returns true if the specified type fits in a native integer type
+ /// supported by the CPU.
+ ///
+ /// For example, if the CPU only supports i32 as a native integer type, then
+ /// i27 fits in a legal integer type but i45 does not.
bool fitsInLegalInteger(unsigned Width) const {
for (unsigned LegalIntWidth : LegalIntWidths)
if (Width <= LegalIntWidth)
@@ -342,118 +334,116 @@ public:
/// [*] The alloc size depends on the alignment, and thus on the target.
/// These values are for x86-32 linux.
- /// getTypeSizeInBits - Return the number of bits necessary to hold the
- /// specified type. For example, returns 36 for i36 and 80 for x86_fp80.
- /// The type passed must have a size (Type::isSized() must return true).
+ /// \brief Returns the number of bits necessary to hold the specified type.
+ ///
+ /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must
+ /// have a size (Type::isSized() must return true).
uint64_t getTypeSizeInBits(Type *Ty) const;
- /// getTypeStoreSize - Return the maximum number of bytes that may be
- /// overwritten by storing the specified type. For example, returns 5
- /// for i36 and 10 for x86_fp80.
+ /// \brief Returns the maximum number of bytes that may be overwritten by
+ /// storing the specified type.
+ ///
+ /// For example, returns 5 for i36 and 10 for x86_fp80.
uint64_t getTypeStoreSize(Type *Ty) const {
- return (getTypeSizeInBits(Ty)+7)/8;
+ return (getTypeSizeInBits(Ty) + 7) / 8;
}
- /// getTypeStoreSizeInBits - Return the maximum number of bits that may be
- /// overwritten by storing the specified type; always a multiple of 8. For
- /// example, returns 40 for i36 and 80 for x86_fp80.
+ /// \brief Returns the maximum number of bits that may be overwritten by
+ /// storing the specified type; always a multiple of 8.
+ ///
+ /// For example, returns 40 for i36 and 80 for x86_fp80.
uint64_t getTypeStoreSizeInBits(Type *Ty) const {
- return 8*getTypeStoreSize(Ty);
+ return 8 * getTypeStoreSize(Ty);
}
- /// getTypeAllocSize - Return the offset in bytes between successive objects
- /// of the specified type, including alignment padding. This is the amount
- /// that alloca reserves for this type. For example, returns 12 or 16 for
- /// x86_fp80, depending on alignment.
+ /// \brief Returns the offset in bytes between successive objects of the
+ /// specified type, including alignment padding.
+ ///
+ /// This is the amount that alloca reserves for this type. For example,
+ /// returns 12 or 16 for x86_fp80, depending on alignment.
uint64_t getTypeAllocSize(Type *Ty) const {
// Round up to the next alignment boundary.
- return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
+ return RoundUpToAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty));
}
- /// getTypeAllocSizeInBits - Return the offset in bits between successive
- /// objects of the specified type, including alignment padding; always a
- /// multiple of 8. This is the amount that alloca reserves for this type.
- /// For example, returns 96 or 128 for x86_fp80, depending on alignment.
+ /// \brief Returns the offset in bits between successive objects of the
+ /// specified type, including alignment padding; always a multiple of 8.
+ ///
+ /// This is the amount that alloca reserves for this type. For example,
+ /// returns 96 or 128 for x86_fp80, depending on alignment.
uint64_t getTypeAllocSizeInBits(Type *Ty) const {
- return 8*getTypeAllocSize(Ty);
+ return 8 * getTypeAllocSize(Ty);
}
- /// getABITypeAlignment - Return the minimum ABI-required alignment for the
- /// specified type.
+ /// \brief Returns the minimum ABI-required alignment for the specified type.
unsigned getABITypeAlignment(Type *Ty) const;
- /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for
- /// an integer type of the specified bitwidth.
+ /// \brief Returns the minimum ABI-required alignment for an integer type of
+ /// the specified bitwidth.
unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const;
- /// getPrefTypeAlignment - Return the preferred stack/global alignment for
- /// the specified type. This is always at least as good as the ABI alignment.
+ /// \brief Returns the preferred stack/global alignment for the specified
+ /// type.
+ ///
+ /// This is always at least as good as the ABI alignment.
unsigned getPrefTypeAlignment(Type *Ty) const;
- /// getPreferredTypeAlignmentShift - Return the preferred alignment for the
- /// specified type, returned as log2 of the value (a shift amount).
+ /// \brief Returns the preferred alignment for the specified type, returned as
+ /// log2 of the value (a shift amount).
unsigned getPreferredTypeAlignmentShift(Type *Ty) const;
- /// getIntPtrType - Return an integer type with size at least as big as that
- /// of a pointer in the given address space.
+ /// \brief Returns an integer type with size at least as big as that of a
+ /// pointer in the given address space.
IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const;
- /// getIntPtrType - Return an integer (vector of integer) type with size at
- /// least as big as that of a pointer of the given pointer (vector of pointer)
- /// type.
+ /// \brief Returns an integer (vector of integer) type with size at least as
+ /// big as that of a pointer of the given pointer (vector of pointer) type.
Type *getIntPtrType(Type *) const;
- /// getSmallestLegalIntType - Return the smallest integer type with size at
- /// least as big as Width bits.
+ /// \brief Returns the smallest integer type with size at least as big as
+ /// Width bits.
Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const;
- /// getLargestLegalIntType - Return the largest legal integer type, or null if
- /// none are set.
+ /// \brief Returns the largest legal integer type, or null if none are set.
Type *getLargestLegalIntType(LLVMContext &C) const {
unsigned LargestSize = getLargestLegalIntTypeSize();
return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize);
}
- /// getLargestLegalIntTypeSize - Return the size of largest legal integer
- /// type size, or 0 if none are set.
+ /// \brief Returns the size of largest legal integer type size, or 0 if none
+ /// are set.
unsigned getLargestLegalIntTypeSize() const;
- /// getIndexedOffset - return the offset from the beginning of the type for
- /// the specified indices. This is used to implement getelementptr.
+ /// \brief Returns the offset from the beginning of the type for the specified
+ /// indices.
+ ///
+ /// This is used to implement getelementptr.
uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const;
- /// getStructLayout - Return a StructLayout object, indicating the alignment
- /// of the struct, its size, and the offsets of its fields. Note that this
- /// information is lazily cached.
+ /// \brief Returns a StructLayout object, indicating the alignment of the
+ /// struct, its size, and the offsets of its fields.
+ ///
+ /// Note that this information is lazily cached.
const StructLayout *getStructLayout(StructType *Ty) const;
- /// getPreferredAlignment - Return the preferred alignment of the specified
- /// global. This includes an explicitly requested alignment (if the global
- /// has one).
+ /// \brief Returns the preferred alignment of the specified global.
+ ///
+ /// This includes an explicitly requested alignment (if the global has one).
unsigned getPreferredAlignment(const GlobalVariable *GV) const;
- /// getPreferredAlignmentLog - Return the preferred alignment of the
- /// specified global, returned in log form. This includes an explicitly
- /// requested alignment (if the global has one).
+ /// \brief Returns the preferred alignment of the specified global, returned
+ /// in log form.
+ ///
+ /// This includes an explicitly requested alignment (if the global has one).
unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const;
-
- /// RoundUpAlignment - Round the specified value up to the next alignment
- /// boundary specified by Alignment. For example, 7 rounded up to an
- /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4
- /// is 8 because it is already aligned.
- template <typename UIntTy>
- static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) {
- assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!");
- return (Val + (Alignment-1)) & ~UIntTy(Alignment-1);
- }
};
inline DataLayout *unwrap(LLVMTargetDataRef P) {
- return reinterpret_cast<DataLayout*>(P);
+ return reinterpret_cast<DataLayout *>(P);
}
inline LLVMTargetDataRef wrap(const DataLayout *P) {
- return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P));
+ return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout *>(P));
}
class DataLayoutPass : public ImmutablePass {
@@ -466,40 +456,28 @@ public:
const DataLayout &getDataLayout() const { return DL; }
- // For use with the C API. C++ code should always use the constructor that
- // takes a module.
- explicit DataLayoutPass(const DataLayout &DL);
-
- explicit DataLayoutPass(const Module *M);
-
static char ID; // Pass identification, replacement for typeid
+
+ bool doFinalization(Module &M) override;
+ bool doInitialization(Module &M) override;
};
-/// StructLayout - used to lazily calculate structure layout information for a
-/// target machine, based on the DataLayout structure.
-///
+/// Used to lazily calculate structure layout information for a target machine,
+/// based on the DataLayout structure.
class StructLayout {
uint64_t StructSize;
unsigned StructAlignment;
unsigned NumElements;
- uint64_t MemberOffsets[1]; // variable sized array!
+ uint64_t MemberOffsets[1]; // variable sized array!
public:
+ uint64_t getSizeInBytes() const { return StructSize; }
- uint64_t getSizeInBytes() const {
- return StructSize;
- }
+ uint64_t getSizeInBits() const { return 8 * StructSize; }
- uint64_t getSizeInBits() const {
- return 8*StructSize;
- }
+ unsigned getAlignment() const { return StructAlignment; }
- unsigned getAlignment() const {
- return StructAlignment;
- }
-
- /// getElementContainingOffset - Given a valid byte offset into the structure,
- /// return the structure index that contains it.
- ///
+ /// \brief Given a valid byte offset into the structure, returns the structure
+ /// index that contains it.
unsigned getElementContainingOffset(uint64_t Offset) const;
uint64_t getElementOffset(unsigned Idx) const {
@@ -508,15 +486,14 @@ public:
}
uint64_t getElementOffsetInBits(unsigned Idx) const {
- return getElementOffset(Idx)*8;
+ return getElementOffset(Idx) * 8;
}
private:
- friend class DataLayout; // Only DataLayout can create this class
+ friend class DataLayout; // Only DataLayout can create this class
StructLayout(StructType *ST, const DataLayout &DL);
};
-
// The implementation of this method is provided inline as it is particularly
// well suited to constant folding when called on a specific Type subclass.
inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
@@ -546,7 +523,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
case Type::PPC_FP128TyID:
case Type::FP128TyID:
return 128;
- // In memory objects this is always aligned to a higher boundary, but
+ // In memory objects this is always aligned to a higher boundary, but
// only 80 bits contain information.
case Type::X86_FP80TyID:
return 80;
diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h
index 088eb9f01049..5c85d6d52824 100644
--- a/include/llvm/IR/DebugInfo.h
+++ b/include/llvm/IR/DebugInfo.h
@@ -18,13 +18,15 @@
#define LLVM_IR_DEBUGINFO_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <iterator>
namespace llvm {
class BasicBlock;
@@ -37,6 +39,7 @@ class Value;
class DbgDeclareInst;
class DbgValueInst;
class Instruction;
+class Metadata;
class MDNode;
class MDString;
class NamedMDNode;
@@ -52,21 +55,78 @@ class DIType;
class DIScope;
class DIObjCProperty;
-/// Maps from type identifier to the actual MDNode.
+/// \brief Maps from type identifier to the actual MDNode.
typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap;
-/// DIDescriptor - A thin wraper around MDNode to access encoded debug info.
-/// This should not be stored in a container, because the underlying MDNode
-/// may change in certain situations.
+class DIHeaderFieldIterator
+ : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t,
+ const StringRef *, StringRef> {
+ StringRef Header;
+ StringRef Current;
+
+public:
+ DIHeaderFieldIterator() {}
+ DIHeaderFieldIterator(StringRef Header)
+ : Header(Header), Current(Header.slice(0, Header.find('\0'))) {}
+ StringRef operator*() const { return Current; }
+ const StringRef * operator->() const { return &Current; }
+ DIHeaderFieldIterator &operator++() {
+ increment();
+ return *this;
+ }
+ DIHeaderFieldIterator operator++(int) {
+ DIHeaderFieldIterator X(*this);
+ increment();
+ return X;
+ }
+ bool operator==(const DIHeaderFieldIterator &X) const {
+ return Current.data() == X.Current.data();
+ }
+ bool operator!=(const DIHeaderFieldIterator &X) const {
+ return !(*this == X);
+ }
+
+ StringRef getHeader() const { return Header; }
+ StringRef getCurrent() const { return Current; }
+ StringRef getPrefix() const {
+ if (Current.begin() == Header.begin())
+ return StringRef();
+ return Header.slice(0, Current.begin() - Header.begin() - 1);
+ }
+ StringRef getSuffix() const {
+ if (Current.end() == Header.end())
+ return StringRef();
+ return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos);
+ }
+
+private:
+ void increment() {
+ assert(Current.data() != nullptr && "Cannot increment past the end");
+ StringRef Suffix = getSuffix();
+ Current = Suffix.slice(0, Suffix.find('\0'));
+ }
+};
+
+/// \brief A thin wraper around MDNode to access encoded debug info.
+///
+/// This should not be stored in a container, because the underlying MDNode may
+/// change in certain situations.
class DIDescriptor {
// Befriends DIRef so DIRef can befriend the protected member
// function: getFieldAs<DIRef>.
template <typename T> friend class DIRef;
public:
+ /// \brief Accessibility flags.
+ ///
+ /// The three accessibility flags are mutually exclusive and rolled together
+ /// in the first two bits.
enum {
- FlagPrivate = 1 << 0,
- FlagProtected = 1 << 1,
+ FlagAccessibility = 1 << 0 | 1 << 1,
+ FlagPrivate = 1,
+ FlagProtected = 2,
+ FlagPublic = 3,
+
FlagFwdDecl = 1 << 2,
FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4,
@@ -108,8 +168,9 @@ public:
bool Verify() const;
- operator MDNode *() const { return const_cast<MDNode *>(DbgNode); }
- MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); }
+ MDNode *get() const { return const_cast<MDNode *>(DbgNode); }
+ operator MDNode *() const { return get(); }
+ MDNode *operator->() const { return get(); }
// An explicit operator bool so that we can do testing of DI values
// easily.
@@ -121,12 +182,36 @@ public:
bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; }
bool operator!=(DIDescriptor Other) const { return !operator==(Other); }
- uint16_t getTag() const {
- return getUnsignedField(0) & ~LLVMDebugVersionMask;
+ StringRef getHeader() const {
+ return getStringField(0);
+ }
+
+ size_t getNumHeaderFields() const {
+ return std::distance(DIHeaderFieldIterator(getHeader()),
+ DIHeaderFieldIterator());
}
+ StringRef getHeaderField(unsigned Index) const {
+ // Since callers expect an empty string for out-of-range accesses, we can't
+ // use std::advance() here.
+ for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index)
+ if (!Index)
+ return *I;
+ return StringRef();
+ }
+
+ template <class T> T getHeaderFieldAs(unsigned Index) const {
+ T Int;
+ if (getHeaderField(Index).getAsInteger(0, Int))
+ return 0;
+ return Int;
+ }
+
+ uint16_t getTag() const { return getHeaderFieldAs<uint16_t>(0); }
+
bool isDerivedType() const;
bool isCompositeType() const;
+ bool isSubroutineType() const;
bool isBasicType() const;
bool isVariable() const;
bool isSubprogram() const;
@@ -140,20 +225,21 @@ public:
bool isSubrange() const;
bool isEnumerator() const;
bool isType() const;
- bool isUnspecifiedParameter() const;
bool isTemplateTypeParameter() const;
bool isTemplateValueParameter() const;
bool isObjCProperty() const;
bool isImportedEntity() const;
+ bool isExpression() const;
- /// print - print descriptor.
void print(raw_ostream &OS) const;
-
- /// dump - print descriptor to dbgs() with a newline.
void dump() const;
+
+ /// \brief Replace all uses of debug info referenced by this descriptor.
+ void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
+ void replaceAllUsesWith(MDNode *D);
};
-/// DISubrange - This is used to represent ranges, for array bounds.
+/// \brief This is used to represent ranges, for array bounds.
class DISubrange : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -161,23 +247,27 @@ class DISubrange : public DIDescriptor {
public:
explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {}
- int64_t getLo() const { return getInt64Field(1); }
- int64_t getCount() const { return getInt64Field(2); }
+ int64_t getLo() const { return getHeaderFieldAs<int64_t>(1); }
+ int64_t getCount() const { return getHeaderFieldAs<int64_t>(2); }
bool Verify() const;
};
-/// DIArray - This descriptor holds an array of descriptors.
-class DIArray : public DIDescriptor {
+/// \brief This descriptor holds an array of nodes with type T.
+template <typename T> class DITypedArray : public DIDescriptor {
public:
- explicit DIArray(const MDNode *N = nullptr) : DIDescriptor(N) {}
-
- unsigned getNumElements() const;
- DIDescriptor getElement(unsigned Idx) const {
- return getDescriptorField(Idx);
+ explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {}
+ unsigned getNumElements() const {
+ return DbgNode ? DbgNode->getNumOperands() : 0;
+ }
+ T getElement(unsigned Idx) const {
+ return getFieldAs<T>(Idx);
}
};
-/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
+typedef DITypedArray<DIDescriptor> DIArray;
+
+/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
+///
/// FIXME: it seems strange that this doesn't have either a reference to the
/// type/precision or a file/line pair for location info.
class DIEnumerator : public DIDescriptor {
@@ -187,16 +277,17 @@ class DIEnumerator : public DIDescriptor {
public:
explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {}
- StringRef getName() const { return getStringField(1); }
- int64_t getEnumValue() const { return getInt64Field(2); }
+ StringRef getName() const { return getHeaderField(1); }
+ int64_t getEnumValue() const { return getHeaderFieldAs<int64_t>(2); }
bool Verify() const;
};
template <typename T> class DIRef;
typedef DIRef<DIScope> DIScopeRef;
typedef DIRef<DIType> DITypeRef;
+typedef DITypedArray<DITypeRef> DITypeArray;
-/// DIScope - A base class for various scopes.
+/// \brief A base class for various scopes.
///
/// Although, implementation-wise, DIScope is the parent class of most
/// other DIxxx classes, including DIType and its descendants, most of
@@ -212,21 +303,28 @@ protected:
public:
explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {}
- /// Gets the parent scope for this scope node or returns a
- /// default constructed scope.
+ /// \brief Get the parent scope.
+ ///
+ /// Gets the parent scope for this scope node or returns a default
+ /// constructed scope.
DIScopeRef getContext() const;
+ /// \brief Get the scope name.
+ ///
/// If the scope node has a name, return that, else return an empty string.
StringRef getName() const;
StringRef getFilename() const;
StringRef getDirectory() const;
- /// Generate a reference to this DIScope. Uses the type identifier instead
- /// of the actual MDNode if possible, to help type uniquing.
+ /// \brief Generate a reference to this DIScope.
+ ///
+ /// Uses the type identifier instead of the actual MDNode if possible, to
+ /// help type uniquing.
DIScopeRef getRef() const;
};
-/// Represents reference to a DIDescriptor, abstracts over direct and
-/// identifier-based metadata references.
+/// \brief Represents reference to a DIDescriptor.
+///
+/// Abstracts over direct and identifier-based metadata references.
template <typename T> class DIRef {
template <typename DescTy>
friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const;
@@ -234,15 +332,16 @@ template <typename T> class DIRef {
friend DIScopeRef DIScope::getRef() const;
friend class DIType;
- /// Val can be either a MDNode or a MDString, in the latter,
- /// MDString specifies the type identifier.
- const Value *Val;
- explicit DIRef(const Value *V);
+ /// \brief Val can be either a MDNode or a MDString.
+ ///
+ /// In the latter, MDString specifies the type identifier.
+ const Metadata *Val;
+ explicit DIRef(const Metadata *V);
public:
T resolve(const DITypeIdentifierMap &Map) const;
StringRef getName() const;
- operator Value *() const { return const_cast<Value *>(Val); }
+ operator Metadata *() const { return const_cast<Metadata *>(Val); }
};
template <typename T>
@@ -273,17 +372,18 @@ template <typename T> StringRef DIRef<T>::getName() const {
return MS->getString();
}
-/// Specialize getFieldAs to handle fields that are references to DIScopes.
+/// \brief Handle fields that are references to DIScopes.
template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const;
-/// Specialize DIRef constructor for DIScopeRef.
-template <> DIRef<DIScope>::DIRef(const Value *V);
+/// \brief Specialize DIRef constructor for DIScopeRef.
+template <> DIRef<DIScope>::DIRef(const Metadata *V);
-/// Specialize getFieldAs to handle fields that are references to DITypes.
+/// \brief Handle fields that are references to DITypes.
template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const;
-/// Specialize DIRef constructor for DITypeRef.
-template <> DIRef<DIType>::DIRef(const Value *V);
+/// \brief Specialize DIRef constructor for DITypeRef.
+template <> DIRef<DIType>::DIRef(const Metadata *V);
-/// DIType - This is a wrapper for a type.
+/// \briefThis is a wrapper for a type.
+///
/// FIXME: Types should be factored much better so that CV qualifiers and
/// others do not require a huge and empty descriptor full of zeros.
class DIType : public DIScope {
@@ -299,22 +399,35 @@ public:
return DITypeRef(&*getRef());
}
- /// Verify - Verify that a type descriptor is well formed.
bool Verify() const;
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- StringRef getName() const { return getStringField(3); }
- unsigned getLineNumber() const { return getUnsignedField(4); }
- uint64_t getSizeInBits() const { return getUInt64Field(5); }
- uint64_t getAlignInBits() const { return getUInt64Field(6); }
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const {
+ return getHeaderFieldAs<unsigned>(2);
+ }
+ uint64_t getSizeInBits() const {
+ return getHeaderFieldAs<unsigned>(3);
+ }
+ uint64_t getAlignInBits() const {
+ return getHeaderFieldAs<unsigned>(4);
+ }
// FIXME: Offset is only used for DW_TAG_member nodes. Making every type
// carry this is just plain insane.
- uint64_t getOffsetInBits() const { return getUInt64Field(7); }
- unsigned getFlags() const { return getUnsignedField(8); }
- bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; }
- bool isProtected() const { return (getFlags() & FlagProtected) != 0; }
+ uint64_t getOffsetInBits() const {
+ return getHeaderFieldAs<unsigned>(5);
+ }
+ unsigned getFlags() const { return getHeaderFieldAs<unsigned>(6); }
+ bool isPrivate() const {
+ return (getFlags() & FlagAccessibility) == FlagPrivate;
+ }
+ bool isProtected() const {
+ return (getFlags() & FlagAccessibility) == FlagProtected;
+ }
+ bool isPublic() const {
+ return (getFlags() & FlagAccessibility) == FlagPublic;
+ }
bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; }
- // isAppleBlock - Return true if this is the Apple Blocks extension.
bool isAppleBlockExtension() const {
return (getFlags() & FlagAppleBlock) != 0;
}
@@ -336,27 +449,22 @@ public:
return (getFlags() & FlagRValueReference) != 0;
}
bool isValid() const { return DbgNode && isType(); }
-
- /// replaceAllUsesWith - Replace all uses of debug info referenced by
- /// this descriptor.
- void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D);
- void replaceAllUsesWith(MDNode *D);
};
-/// DIBasicType - A basic type, like 'int' or 'float'.
+/// \brief A basic type, like 'int' or 'float'.
class DIBasicType : public DIType {
public:
explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {}
- unsigned getEncoding() const { return getUnsignedField(9); }
+ unsigned getEncoding() const { return getHeaderFieldAs<unsigned>(7); }
- /// Verify - Verify that a basic type descriptor is well formed.
bool Verify() const;
};
-/// DIDerivedType - A simple derived type, like a const qualified type,
-/// a typedef, a pointer or reference, et cetera. Or, a data member of
-/// a class/struct/union.
+/// \brief A simple derived type
+///
+/// Like a const qualified type, a typedef, a pointer or reference, et cetera.
+/// Or, a data member of a class/struct/union.
class DIDerivedType : public DIType {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -364,62 +472,96 @@ class DIDerivedType : public DIType {
public:
explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {}
- DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); }
+ DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(3); }
- /// getObjCProperty - Return property node, if this ivar is
- /// associated with one.
+ /// \brief Return property node, if this ivar is associated with one.
MDNode *getObjCProperty() const;
DITypeRef getClassType() const {
assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
- return getFieldAs<DITypeRef>(10);
+ return getFieldAs<DITypeRef>(4);
}
Constant *getConstant() const {
assert((getTag() == dwarf::DW_TAG_member) && isStaticMember());
- return getConstantField(10);
+ return getConstantField(4);
}
- /// Verify - Verify that a derived type descriptor is well formed.
bool Verify() const;
};
-/// DICompositeType - This descriptor holds a type that can refer to multiple
-/// other types, like a function or struct.
+/// \brief Types that refer to multiple other types.
+///
+/// This descriptor holds a type that can refer to multiple other types, like a
+/// function or struct.
+///
/// DICompositeType is derived from DIDerivedType because some
/// composite types (such as enums) can be derived from basic types
// FIXME: Make this derive from DIType directly & just store the
// base type in a single DIType field.
class DICompositeType : public DIDerivedType {
+ friend class DIBuilder;
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
+ /// \brief Set the array of member DITypes.
+ void setArraysHelper(MDNode *Elements, MDNode *TParams);
+
public:
explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {}
- DIArray getTypeArray() const { return getFieldAs<DIArray>(10); }
- void setTypeArray(DIArray Elements, DIArray TParams = DIArray());
- unsigned getRunTimeLang() const { return getUnsignedField(11); }
- DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); }
+ DIArray getElements() const {
+ assert(!isSubroutineType() && "no elements for DISubroutineType");
+ return getFieldAs<DIArray>(4);
+ }
+
+private:
+ template <typename T>
+ void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) {
+ assert((!TParams || DbgNode->getNumOperands() == 8) &&
+ "If you're setting the template parameters this should include a slot "
+ "for that!");
+ setArraysHelper(Elements, TParams);
+ }
+
+public:
+ unsigned getRunTimeLang() const {
+ return getHeaderFieldAs<unsigned>(7);
+ }
+ DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(5); }
+
+private:
+ /// \brief Set the containing type.
void setContainingType(DICompositeType ContainingType);
- DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); }
+
+public:
+ DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
MDString *getIdentifier() const;
- /// Verify - Verify that a composite type descriptor is well formed.
bool Verify() const;
};
-/// DIFile - This is a wrapper for a file.
+class DISubroutineType : public DICompositeType {
+public:
+ explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {}
+ DITypedArray<DITypeRef> getTypeArray() const {
+ return getFieldAs<DITypedArray<DITypeRef>>(4);
+ }
+};
+
+/// \brief This is a wrapper for a file.
class DIFile : public DIScope {
friend class DIDescriptor;
public:
explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {}
+
+ /// \brief Retrieve the MDNode for the directory/file pair.
MDNode *getFileNode() const;
bool Verify() const;
};
-/// DICompileUnit - A wrapper for a compile unit.
+/// \brief A wrapper for a compile unit.
class DICompileUnit : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -428,13 +570,13 @@ public:
explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {}
dwarf::SourceLanguage getLanguage() const {
- return static_cast<dwarf::SourceLanguage>(getUnsignedField(2));
+ return static_cast<dwarf::SourceLanguage>(getHeaderFieldAs<unsigned>(1));
}
- StringRef getProducer() const { return getStringField(3); }
+ StringRef getProducer() const { return getHeaderField(2); }
- bool isOptimized() const { return getUnsignedField(4) != 0; }
- StringRef getFlags() const { return getStringField(5); }
- unsigned getRunTimeVersion() const { return getUnsignedField(6); }
+ bool isOptimized() const { return getHeaderFieldAs<bool>(3) != 0; }
+ StringRef getFlags() const { return getHeaderField(4); }
+ unsigned getRunTimeVersion() const { return getHeaderFieldAs<unsigned>(5); }
DIArray getEnumTypes() const;
DIArray getRetainedTypes() const;
@@ -442,14 +584,16 @@ public:
DIArray getGlobalVariables() const;
DIArray getImportedEntities() const;
- StringRef getSplitDebugFilename() const { return getStringField(12); }
- unsigned getEmissionKind() const { return getUnsignedField(13); }
+ void replaceSubprograms(DIArray Subprograms);
+ void replaceGlobalVariables(DIArray GlobalVariables);
+
+ StringRef getSplitDebugFilename() const { return getHeaderField(6); }
+ unsigned getEmissionKind() const { return getHeaderFieldAs<unsigned>(7); }
- /// Verify - Verify that a compile unit is well formed.
bool Verify() const;
};
-/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
+/// \brief This is a wrapper for a subprogram (e.g. a function).
class DISubprogram : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -457,93 +601,95 @@ class DISubprogram : public DIScope {
public:
explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {}
- DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
- StringRef getName() const { return getStringField(3); }
- StringRef getDisplayName() const { return getStringField(4); }
- StringRef getLinkageName() const { return getStringField(5); }
- unsigned getLineNumber() const { return getUnsignedField(6); }
- DICompositeType getType() const { return getFieldAs<DICompositeType>(7); }
-
- /// isLocalToUnit - Return true if this subprogram is local to the current
- /// compile unit, like 'static' in C.
- unsigned isLocalToUnit() const { return getUnsignedField(8); }
- unsigned isDefinition() const { return getUnsignedField(9); }
+ StringRef getName() const { return getHeaderField(1); }
+ StringRef getDisplayName() const { return getHeaderField(2); }
+ StringRef getLinkageName() const { return getHeaderField(3); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); }
- unsigned getVirtuality() const { return getUnsignedField(10); }
- unsigned getVirtualIndex() const { return getUnsignedField(11); }
+ /// \brief Check if this is local (like 'static' in C).
+ unsigned isLocalToUnit() const { return getHeaderFieldAs<unsigned>(5); }
+ unsigned isDefinition() const { return getHeaderFieldAs<unsigned>(6); }
- DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); }
+ unsigned getVirtuality() const { return getHeaderFieldAs<unsigned>(7); }
+ unsigned getVirtualIndex() const { return getHeaderFieldAs<unsigned>(8); }
- unsigned getFlags() const { return getUnsignedField(13); }
+ unsigned getFlags() const { return getHeaderFieldAs<unsigned>(9); }
- unsigned isArtificial() const {
- return (getUnsignedField(13) & FlagArtificial) != 0;
- }
- /// isPrivate - Return true if this subprogram has "private"
- /// access specifier.
- bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; }
- /// isProtected - Return true if this subprogram has "protected"
- /// access specifier.
- bool isProtected() const {
- return (getUnsignedField(13) & FlagProtected) != 0;
- }
- /// isExplicit - Return true if this subprogram is marked as explicit.
- bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; }
- /// isPrototyped - Return true if this subprogram is prototyped.
- bool isPrototyped() const {
- return (getUnsignedField(13) & FlagPrototyped) != 0;
- }
+ unsigned isOptimized() const { return getHeaderFieldAs<bool>(10); }
- /// Return true if this subprogram is a C++11 reference-qualified
- /// non-static member function (void foo() &).
- unsigned isLValueReference() const {
- return (getUnsignedField(13) & FlagLValueReference) != 0;
- }
+ /// \brief Get the beginning of the scope of the function (not the name).
+ unsigned getScopeLineNumber() const { return getHeaderFieldAs<unsigned>(11); }
- /// Return true if this subprogram is a C++11
- /// rvalue-reference-qualified non-static member function
- /// (void foo() &&).
- unsigned isRValueReference() const {
- return (getUnsignedField(13) & FlagRValueReference) != 0;
- }
+ DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); }
+ DISubroutineType getType() const { return getFieldAs<DISubroutineType>(3); }
- unsigned isOptimized() const;
+ DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(4); }
- /// Verify - Verify that a subprogram descriptor is well formed.
bool Verify() const;
- /// describes - Return true if this subprogram provides debugging
- /// information for the function F.
+ /// \brief Check if this provides debugging information for the function F.
bool describes(const Function *F);
- Function *getFunction() const { return getFunctionField(15); }
- void replaceFunction(Function *F) { replaceFunctionField(15, F); }
- DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); }
+ Function *getFunction() const { return getFunctionField(5); }
+ void replaceFunction(Function *F) { replaceFunctionField(5, F); }
+ DIArray getTemplateParams() const { return getFieldAs<DIArray>(6); }
DISubprogram getFunctionDeclaration() const {
- return getFieldAs<DISubprogram>(17);
+ return getFieldAs<DISubprogram>(7);
}
MDNode *getVariablesNodes() const;
DIArray getVariables() const;
- /// getScopeLineNumber - Get the beginning of the scope of the
- /// function, not necessarily where the name of the program
- /// starts.
- unsigned getScopeLineNumber() const { return getUnsignedField(19); }
+ unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; }
+ /// \brief Check for the "private" access specifier.
+ bool isPrivate() const {
+ return (getFlags() & FlagAccessibility) == FlagPrivate;
+ }
+ /// \brief Check for the "protected" access specifier.
+ bool isProtected() const {
+ return (getFlags() & FlagAccessibility) == FlagProtected;
+ }
+ /// \brief Check for the "public" access specifier.
+ bool isPublic() const {
+ return (getFlags() & FlagAccessibility) == FlagPublic;
+ }
+ /// \brief Check for "explicit".
+ bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; }
+ /// \brief Check if this is prototyped.
+ bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; }
+
+ /// \brief Check if this is reference-qualified.
+ ///
+ /// Return true if this subprogram is a C++11 reference-qualified non-static
+ /// member function (void foo() &).
+ unsigned isLValueReference() const {
+ return (getFlags() & FlagLValueReference) != 0;
+ }
+
+ /// \brief Check if this is rvalue-reference-qualified.
+ ///
+ /// Return true if this subprogram is a C++11 rvalue-reference-qualified
+ /// non-static member function (void foo() &&).
+ unsigned isRValueReference() const {
+ return (getFlags() & FlagRValueReference) != 0;
+ }
+
};
-/// DILexicalBlock - This is a wrapper for a lexical block.
+/// \brief This is a wrapper for a lexical block.
class DILexicalBlock : public DIScope {
public:
explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
- unsigned getColumnNumber() const { return getUnsignedField(4); }
- unsigned getDiscriminator() const { return getUnsignedField(5); }
+ unsigned getLineNumber() const {
+ return getHeaderFieldAs<unsigned>(1);
+ }
+ unsigned getColumnNumber() const {
+ return getHeaderFieldAs<unsigned>(2);
+ }
bool Verify() const;
};
-/// DILexicalBlockFile - This is a wrapper for a lexical block with
-/// a filename change.
+/// \brief This is a wrapper for a lexical block with a filename change.
class DILexicalBlockFile : public DIScope {
public:
explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {}
@@ -555,68 +701,63 @@ public:
unsigned getLineNumber() const { return getScope().getLineNumber(); }
unsigned getColumnNumber() const { return getScope().getColumnNumber(); }
DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); }
+ unsigned getDiscriminator() const { return getHeaderFieldAs<unsigned>(1); }
bool Verify() const;
};
-/// DINameSpace - A wrapper for a C++ style name space.
+/// \brief A wrapper for a C++ style name space.
class DINameSpace : public DIScope {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
public:
explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
DIScope getContext() const { return getFieldAs<DIScope>(2); }
- StringRef getName() const { return getStringField(3); }
- unsigned getLineNumber() const { return getUnsignedField(4); }
- bool Verify() const;
-};
-
-/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters.
-class DIUnspecifiedParameter : public DIDescriptor {
-public:
- explicit DIUnspecifiedParameter(const MDNode *N = nullptr)
- : DIDescriptor(N) {}
bool Verify() const;
};
-/// DITemplateTypeParameter - This is a wrapper for template type parameter.
+/// \brief This is a wrapper for template type parameter.
class DITemplateTypeParameter : public DIDescriptor {
public:
explicit DITemplateTypeParameter(const MDNode *N = nullptr)
: DIDescriptor(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
+
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
- StringRef getName() const { return getStringField(2); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
+ StringRef getFilename() const { return getFieldAs<DIFile>(3).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(4).getDirectory();
+ return getFieldAs<DIFile>(3).getDirectory();
}
- unsigned getLineNumber() const { return getUnsignedField(5); }
- unsigned getColumnNumber() const { return getUnsignedField(6); }
bool Verify() const;
};
-/// DITemplateValueParameter - This is a wrapper for template value parameter.
+/// \brief This is a wrapper for template value parameter.
class DITemplateValueParameter : public DIDescriptor {
public:
explicit DITemplateValueParameter(const MDNode *N = nullptr)
: DIDescriptor(N) {}
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
+ unsigned getColumnNumber() const { return getHeaderFieldAs<unsigned>(3); }
+
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
- StringRef getName() const { return getStringField(2); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- Value *getValue() const;
- StringRef getFilename() const { return getFieldAs<DIFile>(5).getFilename(); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
+ Metadata *getValue() const;
+ StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(5).getDirectory();
+ return getFieldAs<DIFile>(4).getDirectory();
}
- unsigned getLineNumber() const { return getUnsignedField(6); }
- unsigned getColumnNumber() const { return getUnsignedField(7); }
bool Verify() const;
};
-/// DIGlobalVariable - This is a wrapper for a global variable.
+/// \brief This is a wrapper for a global variable.
class DIGlobalVariable : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -624,32 +765,30 @@ class DIGlobalVariable : public DIDescriptor {
public:
explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIScope getContext() const { return getFieldAs<DIScope>(2); }
- StringRef getName() const { return getStringField(3); }
- StringRef getDisplayName() const { return getStringField(4); }
- StringRef getLinkageName() const { return getStringField(5); }
- StringRef getFilename() const { return getFieldAs<DIFile>(6).getFilename(); }
+ StringRef getName() const { return getHeaderField(1); }
+ StringRef getDisplayName() const { return getHeaderField(2); }
+ StringRef getLinkageName() const { return getHeaderField(3); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(4); }
+ unsigned isLocalToUnit() const { return getHeaderFieldAs<bool>(5); }
+ unsigned isDefinition() const { return getHeaderFieldAs<bool>(6); }
+
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
+ StringRef getFilename() const { return getFieldAs<DIFile>(2).getFilename(); }
StringRef getDirectory() const {
- return getFieldAs<DIFile>(6).getDirectory();
+ return getFieldAs<DIFile>(2).getDirectory();
}
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- unsigned getLineNumber() const { return getUnsignedField(7); }
- DITypeRef getType() const { return getFieldAs<DITypeRef>(8); }
- unsigned isLocalToUnit() const { return getUnsignedField(9); }
- unsigned isDefinition() const { return getUnsignedField(10); }
-
- GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
- Constant *getConstant() const { return getConstantField(11); }
+ GlobalVariable *getGlobal() const { return getGlobalVariableField(4); }
+ Constant *getConstant() const { return getConstantField(4); }
DIDerivedType getStaticDataMemberDeclaration() const {
- return getFieldAs<DIDerivedType>(12);
+ return getFieldAs<DIDerivedType>(5);
}
- /// Verify - Verify that a global variable descriptor is well formed.
bool Verify() const;
};
-/// DIVariable - This is a wrapper for a variable (e.g. parameter, local,
-/// global etc).
+/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc).
class DIVariable : public DIDescriptor {
friend class DIDescriptor;
void printInternal(raw_ostream &OS) const;
@@ -657,73 +796,107 @@ class DIVariable : public DIDescriptor {
public:
explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {}
- DIScope getContext() const { return getFieldAs<DIScope>(1); }
- StringRef getName() const { return getStringField(2); }
- DIFile getFile() const { return getFieldAs<DIFile>(3); }
- unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; }
- unsigned getArgNumber() const {
- unsigned L = getUnsignedField(4);
- return L >> 24;
+ StringRef getName() const { return getHeaderField(1); }
+ unsigned getLineNumber() const {
+ // FIXME: Line number and arg number shouldn't be merged together like this.
+ return (getHeaderFieldAs<unsigned>(2) << 8) >> 8;
}
- DITypeRef getType() const { return getFieldAs<DITypeRef>(5); }
+ unsigned getArgNumber() const { return getHeaderFieldAs<unsigned>(2) >> 24; }
+
+ DIScope getContext() const { return getFieldAs<DIScope>(1); }
+ DIFile getFile() const { return getFieldAs<DIFile>(2); }
+ DITypeRef getType() const { return getFieldAs<DITypeRef>(3); }
- /// isArtificial - Return true if this variable is marked as "artificial".
+ /// \brief Return true if this variable is marked as "artificial".
bool isArtificial() const {
- return (getUnsignedField(6) & FlagArtificial) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagArtificial) != 0;
}
bool isObjectPointer() const {
- return (getUnsignedField(6) & FlagObjectPointer) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagObjectPointer) != 0;
}
/// \brief Return true if this variable is represented as a pointer.
bool isIndirect() const {
- return (getUnsignedField(6) & FlagIndirectVariable) != 0;
+ return (getHeaderFieldAs<unsigned>(3) & FlagIndirectVariable) != 0;
}
- /// getInlinedAt - If this variable is inlined then return inline location.
+ /// \brief If this variable is inlined then return inline location.
MDNode *getInlinedAt() const;
- /// Verify - Verify that a variable descriptor is well formed.
bool Verify() const;
- /// HasComplexAddr - Return true if the variable has a complex address.
- bool hasComplexAddress() const { return getNumAddrElements() > 0; }
-
- /// \brief Return the size of this variable's complex address or
- /// zero if there is none.
- unsigned getNumAddrElements() const {
- if (DbgNode->getNumOperands() < 9)
- return 0;
- return getDescriptorField(8)->getNumOperands();
- }
-
- /// \brief return the Idx'th complex address element.
- uint64_t getAddrElement(unsigned Idx) const;
-
- /// isBlockByrefVariable - Return true if the variable was declared as
- /// a "__block" variable (Apple Blocks).
+ /// \brief Check if this is a "__block" variable (Apple Blocks).
bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const {
return (getType().resolve(Map)).isBlockByrefStruct();
}
- /// isInlinedFnArgument - Return true if this variable provides debugging
- /// information for an inlined function arguments.
+ /// \brief Check if this is an inlined function argument.
bool isInlinedFnArgument(const Function *CurFn);
+ /// \brief Return the size reported by the variable's type.
+ unsigned getSizeInBits(const DITypeIdentifierMap &Map);
+
void printExtendedName(raw_ostream &OS) const;
};
-/// DILocation - This object holds location information. This object
-/// is not associated with any DWARF tag.
+/// \brief A complex location expression.
+class DIExpression : public DIDescriptor {
+ friend class DIDescriptor;
+ void printInternal(raw_ostream &OS) const;
+
+public:
+ explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {}
+
+ bool Verify() const;
+
+ /// \brief Return the number of elements in the complex expression.
+ unsigned getNumElements() const {
+ if (!DbgNode)
+ return 0;
+ unsigned N = getNumHeaderFields();
+ assert(N > 0 && "missing tag");
+ return N - 1;
+ }
+
+ /// \brief return the Idx'th complex address element.
+ uint64_t getElement(unsigned Idx) const;
+
+ /// \brief Return whether this is a piece of an aggregate variable.
+ bool isVariablePiece() const;
+ /// \brief Return the offset of this piece in bytes.
+ uint64_t getPieceOffset() const;
+ /// \brief Return the size of this piece in bytes.
+ uint64_t getPieceSize() const;
+};
+
+/// \brief This object holds location information.
+///
+/// This object is not associated with any DWARF tag.
class DILocation : public DIDescriptor {
public:
explicit DILocation(const MDNode *N) : DIDescriptor(N) {}
- unsigned getLineNumber() const { return getUnsignedField(0); }
- unsigned getColumnNumber() const { return getUnsignedField(1); }
- DIScope getScope() const { return getFieldAs<DIScope>(2); }
- DILocation getOrigLocation() const { return getFieldAs<DILocation>(3); }
+ unsigned getLineNumber() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return L->getLine();
+ return 0;
+ }
+ unsigned getColumnNumber() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return L->getColumn();
+ return 0;
+ }
+ DIScope getScope() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return DIScope(dyn_cast_or_null<MDNode>(L->getScope()));
+ return DIScope(nullptr);
+ }
+ DILocation getOrigLocation() const {
+ if (auto *L = dyn_cast_or_null<MDLocation>(DbgNode))
+ return DILocation(dyn_cast_or_null<MDNode>(L->getInlinedAt()));
+ return DILocation(nullptr);
+ }
StringRef getFilename() const { return getScope().getFilename(); }
StringRef getDirectory() const { return getScope().getDirectory(); }
bool Verify() const;
@@ -731,23 +904,30 @@ public:
return (getLineNumber() == Other.getLineNumber() &&
getFilename() == Other.getFilename());
}
- /// getDiscriminator - DWARF discriminators are used to distinguish
- /// identical file locations for instructions that are on different
- /// basic blocks. If two instructions are inside the same lexical block
- /// and are in different basic blocks, we create a new lexical block
- /// with identical location as the original but with a different
- /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp
- /// for details).
+ /// \brief Get the DWAF discriminator.
+ ///
+ /// DWARF discriminators are used to distinguish identical file locations for
+ /// instructions that are on different basic blocks. If two instructions are
+ /// inside the same lexical block and are in different basic blocks, we
+ /// create a new lexical block with identical location as the original but
+ /// with a different discriminator value
+ /// (lib/Transforms/Util/AddDiscriminators.cpp for details).
unsigned getDiscriminator() const {
// Since discriminators are associated with lexical blocks, make
// sure this location is a lexical block before retrieving its
// value.
- return getScope().isLexicalBlock()
- ? getFieldAs<DILexicalBlock>(2).getDiscriminator()
+ return getScope().isLexicalBlockFile()
+ ? DILexicalBlockFile(
+ cast<MDNode>(cast<MDLocation>(DbgNode)->getScope()))
+ .getDiscriminator()
: 0;
}
+
+ /// \brief Generate a new discriminator value for this location.
unsigned computeNewDiscriminator(LLVMContext &Ctx);
- DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlock NewScope);
+
+ /// \brief Return a copy of this location with a different scope.
+ DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope);
};
class DIObjCProperty : public DIDescriptor {
@@ -757,36 +937,38 @@ class DIObjCProperty : public DIDescriptor {
public:
explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {}
- StringRef getObjCPropertyName() const { return getStringField(1); }
- DIFile getFile() const { return getFieldAs<DIFile>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
+ StringRef getObjCPropertyName() const { return getHeaderField(1); }
+ DIFile getFile() const { return getFieldAs<DIFile>(1); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(2); }
- StringRef getObjCPropertyGetterName() const { return getStringField(4); }
- StringRef getObjCPropertySetterName() const { return getStringField(5); }
+ StringRef getObjCPropertyGetterName() const { return getHeaderField(3); }
+ StringRef getObjCPropertySetterName() const { return getHeaderField(4); }
+ unsigned getAttributes() const { return getHeaderFieldAs<unsigned>(5); }
bool isReadOnlyObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
}
bool isReadWriteObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
}
bool isAssignObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0;
}
bool isRetainObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0;
}
bool isCopyObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0;
}
bool isNonAtomicObjCProperty() const {
- return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
+ return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
}
- /// Objective-C doesn't have an ODR, so there is no benefit in storing
+ /// \brief Get the type.
+ ///
+ /// \note Objective-C doesn't have an ODR, so there is no benefit in storing
/// the type as a DITypeRef here.
- DIType getType() const { return getFieldAs<DIType>(7); }
+ DIType getType() const { return getFieldAs<DIType>(2); }
- /// Verify - Verify that a derived type descriptor is well formed.
bool Verify() const;
};
@@ -799,47 +981,47 @@ public:
explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {}
DIScope getContext() const { return getFieldAs<DIScope>(1); }
DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); }
- unsigned getLineNumber() const { return getUnsignedField(3); }
- StringRef getName() const { return getStringField(4); }
+ unsigned getLineNumber() const { return getHeaderFieldAs<unsigned>(1); }
+ StringRef getName() const { return getHeaderField(2); }
bool Verify() const;
};
-/// getDISubprogram - Find subprogram that is enclosing this scope.
+/// \brief Find subprogram that is enclosing this scope.
DISubprogram getDISubprogram(const MDNode *Scope);
-/// getDICompositeType - Find underlying composite type.
-DICompositeType getDICompositeType(DIType T);
-
-/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
-/// to hold function specific information.
-NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP);
+/// \brief Find debug info for a given function.
+/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty
+/// DISubprogram.
+DISubprogram getDISubprogram(const Function *F);
-/// getFnSpecificMDNode - Return a NameMDNode, if available, that is
-/// suitable to hold function specific information.
-NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP);
+/// \brief Find underlying composite type.
+DICompositeType getDICompositeType(DIType T);
-/// createInlinedVariable - Create a new inlined variable based on current
-/// variable.
+/// \brief Create a new inlined variable based on current variable.
+///
/// @param DV Current Variable.
/// @param InlinedScope Location at current variable is inlined.
DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
LLVMContext &VMContext);
-/// cleanseInlinedVariable - Remove inlined scope from the variable.
+/// \brief Remove inlined scope from the variable.
DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
-/// Construct DITypeIdentifierMap by going through retained types of each CU.
+/// \brief Generate map by visiting all retained types.
DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
-/// Strip debug info in the module if it exists.
+/// \brief Strip debug info in the module if it exists.
+///
/// To do this, we remove all calls to the debugger intrinsics and any named
/// metadata for debugging. We also remove debug locations for instructions.
/// Return true if module is modified.
bool StripDebugInfo(Module &M);
-/// Return Debug Info Metadata Version by checking module flags.
+/// \brief Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);
+/// \brief Utility to find all debug info in a module.
+///
/// DebugInfoFinder tries to list all debug info MDNodes used in a module. To
/// list debug info MDNodes used by an instruction, DebugInfoFinder uses
/// processDeclare, processValue and processLocation to handle DbgDeclareInst,
@@ -850,44 +1032,29 @@ class DebugInfoFinder {
public:
DebugInfoFinder() : TypeMapInitialized(false) {}
- /// processModule - Process entire module and collect debug info
- /// anchors.
+ /// \brief Process entire module and collect debug info anchors.
void processModule(const Module &M);
- /// processDeclare - Process DbgDeclareInst.
+ /// \brief Process DbgDeclareInst.
void processDeclare(const Module &M, const DbgDeclareInst *DDI);
- /// Process DbgValueInst.
+ /// \brief Process DbgValueInst.
void processValue(const Module &M, const DbgValueInst *DVI);
- /// processLocation - Process DILocation.
+ /// \brief Process DILocation.
void processLocation(const Module &M, DILocation Loc);
- /// Clear all lists.
+ /// \brief Clear all lists.
void reset();
private:
- /// Initialize TypeIdentifierMap.
void InitializeTypeMap(const Module &M);
- /// processType - Process DIType.
void processType(DIType DT);
-
- /// processSubprogram - Process DISubprogram.
void processSubprogram(DISubprogram SP);
-
void processScope(DIScope Scope);
-
- /// addCompileUnit - Add compile unit into CUs.
bool addCompileUnit(DICompileUnit CU);
-
- /// addGlobalVariable - Add global variable into GVs.
bool addGlobalVariable(DIGlobalVariable DIG);
-
- // addSubprogram - Add subprogram into SPs.
bool addSubprogram(DISubprogram SP);
-
- /// addType - Add type into Tys.
bool addType(DIType DT);
-
bool addScope(DIScope Scope);
public:
@@ -924,14 +1091,15 @@ public:
unsigned scope_count() const { return Scopes.size(); }
private:
- SmallVector<DICompileUnit, 8> CUs; // Compile Units
- SmallVector<DISubprogram, 8> SPs; // Subprograms
- SmallVector<DIGlobalVariable, 8> GVs; // Global Variables;
- SmallVector<DIType, 8> TYs; // Types
- SmallVector<DIScope, 8> Scopes; // Scopes
+ SmallVector<DICompileUnit, 8> CUs;
+ SmallVector<DISubprogram, 8> SPs;
+ SmallVector<DIGlobalVariable, 8> GVs;
+ SmallVector<DIType, 8> TYs;
+ SmallVector<DIScope, 8> Scopes;
SmallPtrSet<MDNode *, 64> NodesSeen;
DITypeIdentifierMap TypeIdentifierMap;
- /// Specify if TypeIdentifierMap is initialized.
+
+ /// \brief Specify if TypeIdentifierMap is initialized.
bool TypeMapInitialized;
};
diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h
index 3d969a8b7532..86e64417099d 100644
--- a/include/llvm/IR/DebugLoc.h
+++ b/include/llvm/IR/DebugLoc.h
@@ -15,51 +15,41 @@
#ifndef LLVM_IR_DEBUGLOC_H
#define LLVM_IR_DEBUGLOC_H
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
- template <typename T> struct DenseMapInfo;
- class MDNode;
+
class LLVMContext;
class raw_ostream;
+ class MDNode;
/// DebugLoc - Debug location id. This is carried by Instruction, SDNode,
/// and MachineInstr to compactly encode file/line/scope information for an
/// operation.
class DebugLoc {
- friend struct DenseMapInfo<DebugLoc>;
-
- /// getEmptyKey() - A private constructor that returns an unknown that is
- /// not equal to the tombstone key or DebugLoc().
- static DebugLoc getEmptyKey() {
- DebugLoc DL;
- DL.LineCol = 1;
- return DL;
- }
+ TrackingMDNodeRef Loc;
- /// getTombstoneKey() - A private constructor that returns an unknown that
- /// is not equal to the empty key or DebugLoc().
- static DebugLoc getTombstoneKey() {
- DebugLoc DL;
- DL.LineCol = 2;
- return DL;
+ public:
+ DebugLoc() {}
+ DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {}
+ DebugLoc(const DebugLoc &X) : Loc(X.Loc) {}
+ DebugLoc &operator=(DebugLoc &&X) {
+ Loc = std::move(X.Loc);
+ return *this;
+ }
+ DebugLoc &operator=(const DebugLoc &X) {
+ Loc = X.Loc;
+ return *this;
}
- /// LineCol - This 32-bit value encodes the line and column number for the
- /// location, encoded as 24-bits for line and 8 bits for col. A value of 0
- /// for either means unknown.
- uint32_t LineCol;
-
- /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information,
- /// decoded by LLVMContext. 0 is unknown.
- int ScopeIdx;
- public:
- DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown.
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); }
/// get - Get a new DebugLoc that corresponds to the specified line/col
/// scope/inline location.
- static DebugLoc get(unsigned Line, unsigned Col,
- MDNode *Scope, MDNode *InlinedAt = nullptr);
+ static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope,
+ MDNode *InlinedAt = nullptr);
/// getFromDILocation - Translate the DILocation quad into a DebugLoc.
static DebugLoc getFromDILocation(MDNode *N);
@@ -68,56 +58,54 @@ namespace llvm {
static DebugLoc getFromDILexicalBlock(MDNode *N);
/// isUnknown - Return true if this is an unknown location.
- bool isUnknown() const { return ScopeIdx == 0; }
+ bool isUnknown() const { return !Loc; }
- unsigned getLine() const {
- return (LineCol << 8) >> 8; // Mask out column.
- }
-
- unsigned getCol() const {
- return LineCol >> 24;
- }
+ unsigned getLine() const;
+ unsigned getCol() const;
/// getScope - This returns the scope pointer for this DebugLoc, or null if
/// invalid.
- MDNode *getScope(const LLVMContext &Ctx) const;
+ MDNode *getScope() const;
+ MDNode *getScope(const LLVMContext &) const { return getScope(); }
/// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or
/// null if invalid or not present.
- MDNode *getInlinedAt(const LLVMContext &Ctx) const;
+ MDNode *getInlinedAt() const;
+ MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); }
/// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values.
+ void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const;
void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
- const LLVMContext &Ctx) const;
+ const LLVMContext &) const {
+ return getScopeAndInlinedAt(Scope, IA);
+ }
/// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid.
- MDNode *getScopeNode(const LLVMContext &Ctx) const;
+ MDNode *getScopeNode() const;
+ MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); }
// getFnDebugLoc - Walk up the scope chain of given debug loc and find line
// number info for the function.
- DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const;
+ DebugLoc getFnDebugLoc() const;
+ DebugLoc getFnDebugLoc(const LLVMContext &) const {
+ return getFnDebugLoc();
+ }
/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation compatible MDNode.
- MDNode *getAsMDNode(const LLVMContext &Ctx) const;
+ MDNode *getAsMDNode() const;
+ MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); }
- bool operator==(const DebugLoc &DL) const {
- return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx;
- }
+ bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
bool operator!=(const DebugLoc &DL) const { return !(*this == DL); }
- void dump(const LLVMContext &Ctx) const;
+ void dump() const;
+ void dump(const LLVMContext &) const { dump(); }
/// \brief prints source location /path/to/file.exe:line:col @[inlined at]
- void print(const LLVMContext &Ctx, raw_ostream &OS) const;
+ void print(raw_ostream &OS) const;
+ void print(const LLVMContext &, raw_ostream &OS) const { print(OS); }
};
- template <>
- struct DenseMapInfo<DebugLoc> {
- static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); }
- static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); }
- static unsigned getHashValue(const DebugLoc &Key);
- static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; }
- };
} // end namespace llvm
#endif /* LLVM_SUPPORT_DEBUGLOC_H */
diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h
index ff150872a4e1..182015c98aa2 100644
--- a/include/llvm/IR/DerivedTypes.h
+++ b/include/llvm/IR/DerivedTypes.h
@@ -123,6 +123,9 @@ public:
typedef Type::subtype_iterator param_iterator;
param_iterator param_begin() const { return ContainedTys + 1; }
param_iterator param_end() const { return &ContainedTys[NumContainedTys]; }
+ ArrayRef<Type *> params() const {
+ return makeArrayRef(param_begin(), param_end());
+ }
/// Parameter type accessors.
Type *getParamType(unsigned i) const { return ContainedTys[i+1]; }
@@ -204,9 +207,6 @@ class StructType : public CompositeType {
///
void *SymbolTableEntry;
public:
- ~StructType() {
- delete [] ContainedTys; // Delete the body.
- }
/// StructType::create - This creates an identified struct.
static StructType *create(LLVMContext &Context, StringRef Name);
@@ -221,7 +221,7 @@ public:
StringRef Name,
bool isPacked = false);
static StructType *create(LLVMContext &Context, ArrayRef<Type*> Elements);
- static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL;
+ static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL;
/// StructType::get - This static method is the primary way to create a
/// literal StructType.
@@ -236,7 +236,7 @@ public:
/// structure types by specifying the elements as arguments. Note that this
/// method always returns a non-packed struct, and requires at least one
/// element type.
- static StructType *get(Type *elt1, ...) END_WITH_NULL;
+ static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL;
bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; }
@@ -249,7 +249,7 @@ public:
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
/// isSized - Return true if this is a sized type.
- bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const;
+ bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const;
/// hasName - Return true if this is a named struct that has a non-empty name.
bool hasName() const { return SymbolTableEntry != nullptr; }
@@ -266,7 +266,7 @@ public:
/// setBody - Specify a body for an opaque identified type.
void setBody(ArrayRef<Type*> Elements, bool isPacked = false);
- void setBody(Type *elt1, ...) END_WITH_NULL;
+ void setBody(Type *elt1, ...) LLVM_END_WITH_NULL;
/// isValidElementType - Return true if the specified type is valid as a
/// element type.
@@ -277,6 +277,9 @@ public:
typedef Type::subtype_iterator element_iterator;
element_iterator element_begin() const { return ContainedTys; }
element_iterator element_end() const { return &ContainedTys[NumContainedTys];}
+ ArrayRef<Type *> const elements() const {
+ return makeArrayRef(element_begin(), element_end());
+ }
/// isLayoutIdentical - Return true if this is layout identical to the
/// specified struct.
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index 9c9f236180ce..c6a8854e0774 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -12,12 +12,13 @@
// Diagnostics reporting is still done as part of the LLVMContext.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H
-#define LLVM_SUPPORT_DIAGNOSTICINFO_H
+#ifndef LLVM_IR_DIAGNOSTICINFO_H
+#define LLVM_IR_DIAGNOSTICINFO_H
#include "llvm-c/Core.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
namespace llvm {
@@ -44,8 +45,10 @@ enum DiagnosticSeverity {
/// \brief Defines the different supported kind of a diagnostic.
/// This enum should be extended with a new ID for each added concrete subclass.
enum DiagnosticKind {
+ DK_Bitcode,
DK_InlineAsm,
DK_StackSize,
+ DK_Linker,
DK_DebugMetadataVersion,
DK_SampleProfile,
DK_OptimizationRemark,
@@ -95,6 +98,8 @@ public:
virtual void print(DiagnosticPrinter &DP) const = 0;
};
+typedef std::function<void(const DiagnosticInfo &)> DiagnosticHandlerFunction;
+
/// Diagnostic information for inline asm reporting.
/// This is basically a message and an optional location.
class DiagnosticInfoInlineAsm : public DiagnosticInfo {
@@ -324,7 +329,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Diagnostic information for missed-optimization remarks.
@@ -350,7 +355,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Diagnostic information for optimization analysis remarks.
@@ -377,7 +382,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
@@ -432,7 +437,7 @@ public:
}
/// \see DiagnosticInfoOptimizationBase::isEnabled.
- virtual bool isEnabled() const override;
+ bool isEnabled() const override;
};
/// Emit a warning when loop vectorization is specified but fails. \p Fn is the
diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h
index 411c781e01c5..db5779a8a8a5 100644
--- a/include/llvm/IR/DiagnosticPrinter.h
+++ b/include/llvm/IR/DiagnosticPrinter.h
@@ -13,8 +13,8 @@
// on their needs.
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H
-#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H
+#ifndef LLVM_IR_DIAGNOSTICPRINTER_H
+#define LLVM_IR_DIAGNOSTICPRINTER_H
#include <string>
diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h
index e2d1ccc8a3ca..c1f208e3d72f 100644
--- a/include/llvm/IR/Dominators.h
+++ b/include/llvm/IR/Dominators.h
@@ -31,6 +31,11 @@
namespace llvm {
+// FIXME: Replace this brittle forward declaration with the include of the new
+// PassManager.h when doing so doesn't break the PassManagerBuilder.
+template <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>);
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
@@ -69,6 +74,13 @@ public:
DominatorTree() : DominatorTreeBase<BasicBlock>(false) {}
+ DominatorTree(DominatorTree &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
+ DominatorTree &operator=(DominatorTree &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(RHS)));
+ return *this;
+ }
+
/// \brief Returns *false* if the other dominator tree matches this dominator
/// tree.
inline bool compare(const DominatorTree &Other) const {
@@ -155,6 +167,43 @@ template <> struct GraphTraits<DominatorTree*>
};
/// \brief Analysis pass which computes a \c DominatorTree.
+class DominatorTreeAnalysis {
+public:
+ /// \brief Provide the result typedef for this analysis pass.
+ typedef DominatorTree Result;
+
+ /// \brief Opaque, unique identifier for this analysis pass.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Run the analysis pass over a function and produce a dominator tree.
+ DominatorTree run(Function &F);
+
+ /// \brief Provide access to a name for this pass for debugging purposes.
+ static StringRef name() { return "DominatorTreeAnalysis"; }
+
+private:
+ static char PassID;
+};
+
+/// \brief Printer pass for the \c DominatorTree.
+class DominatorTreePrinterPass {
+ raw_ostream &OS;
+
+public:
+ explicit DominatorTreePrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "DominatorTreePrinterPass"; }
+};
+
+/// \brief Verifier pass for the \c DominatorTree.
+struct DominatorTreeVerifierPass {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "DominatorTreeVerifierPass"; }
+};
+
+/// \brief Legacy analysis pass which computes a \c DominatorTree.
class DominatorTreeWrapperPass : public FunctionPass {
DominatorTree DT;
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index ad4b1395f0cb..51403281e964 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -87,11 +87,14 @@ private:
ValueSymbolTable *SymTab; ///< Symbol table of args/instructions
AttributeSet AttributeSets; ///< Parameter attributes
- // HasLazyArguments is stored in Value::SubclassData.
- /*bool HasLazyArguments;*/
-
- // The Calling Convention is stored in Value::SubclassData.
- /*CallingConv::ID CallingConvention;*/
+ /*
+ * Value::SubclassData
+ *
+ * bit 0 : HasLazyArguments
+ * bit 1 : HasPrefixData
+ * bit 2 : HasPrologueData
+ * bit 3-6: CallingConvention
+ */
friend class SymbolTableListTraits<Function, Module>;
@@ -102,7 +105,7 @@ private:
/// needs it. The hasLazyArguments predicate returns true if the arg list
/// hasn't been set up yet.
bool hasLazyArguments() const {
- return getSubclassDataFromValue() & 1;
+ return getSubclassDataFromValue() & (1<<0);
}
void CheckLazyArguments() const {
if (hasLazyArguments())
@@ -143,6 +146,9 @@ public:
/// arguments.
bool isVarArg() const;
+ bool isMaterializable() const;
+ void setIsMaterializable(bool V);
+
/// getIntrinsicID - This method returns the ID number of the specified
/// function, or Intrinsic::not_intrinsic if the function is not an
/// intrinsic, or if the pointer is null. This value is always defined to be
@@ -159,11 +165,11 @@ public:
/// calling convention of this function. The enum values for the known
/// calling conventions are defined in CallingConv.h.
CallingConv::ID getCallingConv() const {
- return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 2);
+ return static_cast<CallingConv::ID>(getSubclassDataFromValue() >> 3);
}
void setCallingConv(CallingConv::ID CC) {
- setValueSubclassData((getSubclassDataFromValue() & 3) |
- (static_cast<unsigned>(CC) << 2));
+ setValueSubclassData((getSubclassDataFromValue() & 7) |
+ (static_cast<unsigned>(CC) << 3));
}
/// @brief Return the attribute list for this Function.
@@ -445,12 +451,19 @@ public:
bool arg_empty() const;
bool hasPrefixData() const {
- return getSubclassDataFromValue() & 2;
+ return getSubclassDataFromValue() & (1<<1);
}
Constant *getPrefixData() const;
void setPrefixData(Constant *PrefixData);
+ bool hasPrologueData() const {
+ return getSubclassDataFromValue() & (1<<2);
+ }
+
+ Constant *getPrologueData() const;
+ void setPrologueData(Constant *PrologueData);
+
/// viewCFG - This function is meant for use from the debugger. You can just
/// say 'call F->viewCFG()' and a ghostview window should pop up from the
/// program, displaying the CFG of the current function with the code for each
diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h
index a1216a174282..6f57dc2a98a6 100644
--- a/include/llvm/IR/GVMaterializer.h
+++ b/include/llvm/IR/GVMaterializer.h
@@ -19,11 +19,13 @@
#define LLVM_IR_GVMATERIALIZER_H
#include <system_error>
+#include <vector>
namespace llvm {
class Function;
class GlobalValue;
class Module;
+class StructType;
class GVMaterializer {
protected:
@@ -32,17 +34,13 @@ protected:
public:
virtual ~GVMaterializer();
- /// True if GV can be materialized from whatever backing store this
- /// GVMaterializer uses and has not been materialized yet.
- virtual bool isMaterializable(const GlobalValue *GV) const = 0;
-
/// True if GV has been materialized and can be dematerialized back to
/// whatever backing store this GVMaterializer uses.
virtual bool isDematerializable(const GlobalValue *GV) const = 0;
/// Make sure the given GlobalValue is fully read.
///
- virtual std::error_code Materialize(GlobalValue *GV) = 0;
+ virtual std::error_code materialize(GlobalValue *GV) = 0;
/// If the given GlobalValue is read in, and if the GVMaterializer supports
/// it, release the memory for the GV, and set it up to be materialized
@@ -55,7 +53,7 @@ public:
///
virtual std::error_code MaterializeModule(Module *M) = 0;
- virtual void releaseBuffer() = 0;
+ virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;
};
} // End llvm namespace
diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h
index 2e042f489749..546fea2dfa9b 100644
--- a/include/llvm/IR/GlobalObject.h
+++ b/include/llvm/IR/GlobalObject.h
@@ -1,4 +1,4 @@
-//===-- llvm/GlobalObject.h - Class to represent a global object *- C++ -*-===//
+//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -35,12 +35,24 @@ protected:
std::string Section; // Section to emit this into, empty means default
Comdat *ObjComdat;
+ static const unsigned AlignmentBits = 5;
+ static const unsigned GlobalObjectSubClassDataBits =
+ GlobalValueSubClassDataBits - AlignmentBits;
+
+private:
+ static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
+
public:
unsigned getAlignment() const {
- return (1u << getGlobalValueSubClassData()) >> 1;
+ unsigned Data = getGlobalValueSubClassData();
+ unsigned AlignmentData = Data & AlignmentMask;
+ return (1u << AlignmentData) >> 1;
}
void setAlignment(unsigned Align);
+ unsigned getGlobalObjectSubClassData() const;
+ void setGlobalObjectSubClassData(unsigned Val);
+
bool hasSection() const { return !StringRef(getSection()).empty(); }
const char *getSection() const { return Section.c_str(); }
void setSection(StringRef S);
diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h
index 68e410ba4b8b..d0f7e9a11790 100644
--- a/include/llvm/IR/GlobalValue.h
+++ b/include/llvm/IR/GlobalValue.h
@@ -20,6 +20,7 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
+#include <system_error>
namespace llvm {
@@ -84,6 +85,7 @@ private:
// (19 + 3 + 2 + 1 + 2 + 5) == 32.
unsigned SubClassData : 19;
protected:
+ static const unsigned GlobalValueSubClassDataBits = 19;
unsigned getGlobalValueSubClassData() const {
return SubClassData;
}
@@ -246,6 +248,7 @@ public:
bool hasLinkOnceLinkage() const {
return isLinkOnceLinkage(Linkage);
}
+ bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); }
bool hasWeakLinkage() const {
return isWeakLinkage(Linkage);
}
@@ -309,7 +312,7 @@ public:
/// Make sure this GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
- bool Materialize(std::string *ErrInfo = nullptr);
+ std::error_code materialize();
/// If this GlobalValue is read in, and if the GVMaterializer supports it,
/// release the memory for the function, and set it up to be materialized
@@ -325,6 +328,13 @@ public:
/// the current translation unit.
bool isDeclaration() const;
+ bool isDeclarationForLinker() const {
+ if (hasAvailableExternallyLinkage())
+ return true;
+
+ return isDeclaration();
+ }
+
/// This method unlinks 'this' from the containing module, but does not delete
/// it.
virtual void removeFromParent() = 0;
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index aed2463d42d8..e5f62fb9625e 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -28,7 +28,7 @@
#include "llvm/Support/CBindingWrapping.h"
namespace llvm {
- class MDNode;
+class MDNode;
/// \brief This provides the default implementation of the IRBuilder
/// 'InsertHelper' method that is called whenever an instruction is created by
@@ -364,43 +364,60 @@ public:
/// \brief Create and insert a memset to the specified pointer and the
/// specified value.
///
- /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr) {
- return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memcpy between the specified pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
bool isVolatile = false, MDNode *TBAATag = nullptr,
- MDNode *TBAAStructTag = nullptr) {
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag,
- TBAAStructTag);
+ TBAAStructTag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
bool isVolatile = false, MDNode *TBAATag = nullptr,
- MDNode *TBAAStructTag = nullptr);
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memmove between the specified
/// pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr) {
- return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = nullptr);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create a lifetime.start intrinsic.
///
@@ -412,7 +429,46 @@ public:
/// If the pointer isn't i8* it will be converted.
CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
+ /// \brief Create a call to Masked Load intrinsic
+ CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask,
+ Value *PassThru = 0, const Twine &Name = "");
+
+ /// \brief Create a call to Masked Store intrinsic
+ CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
+ Value *Mask);
+
+ /// \brief Create an assume intrinsic call that allows the optimizer to
+ /// assume that the provided condition will be true.
+ CallInst *CreateAssumption(Value *Cond);
+
+ /// \brief Create a call to the experimental.gc.statepoint intrinsic to
+ /// start a new statepoint sequence.
+ CallInst *CreateGCStatepoint(Value *ActualCallee,
+ ArrayRef<Value*> CallArgs,
+ ArrayRef<Value*> DeoptArgs,
+ ArrayRef<Value*> GCArgs,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.result intrinsic to extract
+ /// the result from a call wrapped in a statepoint.
+ CallInst *CreateGCResult(Instruction *Statepoint,
+ Type *ResultType,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.relocate intrinsics to
+ /// project the relocated value of one pointer from the statepoint.
+ CallInst *CreateGCRelocate(Instruction *Statepoint,
+ int BaseOffset,
+ int DerivedOffset,
+ Type *ResultType,
+ const Twine &Name = "");
+
private:
+ /// \brief Create a call to a masked intrinsic with given Id.
+ /// Masked intrinsic has only one overloaded type - data type.
+ CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops,
+ Type *DataTy, const Twine &Name = "");
+
Value *getCastedInt8PtrValue(Value *Ptr);
};
@@ -429,7 +485,7 @@ private:
/// The first template argument handles whether or not to preserve names in the
/// final instruction output. This defaults to on. The second template argument
/// specifies a class to use for creating constants. This defaults to creating
-/// minimally folded constants. The fourth template argument allows clients to
+/// minimally folded constants. The third template argument allows clients to
/// specify custom insertion hooks that are called on every newly created
/// insertion.
template<bool preserveNames = true, typename T = ConstantFolder,
@@ -570,8 +626,7 @@ public:
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
BasicBlock *UnwindDest, const Twine &Name = "") {
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest,
- ArrayRef<Value *>()),
+ return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None),
Name);
}
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
@@ -1226,6 +1281,18 @@ public:
return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
}
+
+ Value *CreateBitOrPointerCast(Value *V, Type *DestTy,
+ const Twine &Name = "") {
+ if (V->getType() == DestTy)
+ return V;
+ if (V->getType()->isPointerTy() && DestTy->isIntegerTy())
+ return CreatePtrToInt(V, DestTy, Name);
+ if (V->getType()->isIntegerTy() && DestTy->isPointerTy())
+ return CreateIntToPtr(V, DestTy, Name);
+
+ return CreateBitCast(V, DestTy, Name);
+ }
private:
// \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
// compile time error, instead of converting the string to bool for the
@@ -1508,6 +1575,44 @@ 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());
+ 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))
+ IsOffsetZero = CI->isZero();
+
+ if (!IsOffsetZero) {
+ if (OffsetValue->getType() != IntPtrTy)
+ OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true,
+ "offsetcast");
+ PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr");
+ }
+ }
+
+ Value *Zero = ConstantInt::get(IntPtrTy, 0);
+ Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr");
+ Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond");
+
+ return CreateAssumption(InvCond);
+ }
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h
index 2f78c83165eb..7f2027b6e297 100644
--- a/include/llvm/IR/IRPrintingPasses.h
+++ b/include/llvm/IR/IRPrintingPasses.h
@@ -16,8 +16,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_IR_PRINTING_PASSES_H
-#define LLVM_IR_IR_PRINTING_PASSES_H
+#ifndef LLVM_IR_IRPRINTINGPASSES_H
+#define LLVM_IR_IRPRINTINGPASSES_H
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -58,7 +58,7 @@ public:
PrintModulePass();
PrintModulePass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Module *M);
+ PreservedAnalyses run(Module &M);
static StringRef name() { return "PrintModulePass"; }
};
@@ -75,7 +75,7 @@ public:
PrintFunctionPass();
PrintFunctionPass(raw_ostream &OS, const std::string &Banner = "");
- PreservedAnalyses run(Function *F);
+ PreservedAnalyses run(Function &F);
static StringRef name() { return "PrintFunctionPass"; }
};
diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h
index ac190892bab0..b2d79d0f0bfc 100644
--- a/include/llvm/IR/InlineAsm.h
+++ b/include/llvm/IR/InlineAsm.h
@@ -25,12 +25,9 @@ namespace llvm {
class PointerType;
class FunctionType;
class Module;
+
struct InlineAsmKeyType;
-template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
- bool HasLargeKey>
-class ConstantUniqueMap;
-template<class ConstantClass, class TypeClass, class ValType>
-struct ConstantCreator;
+template <class ConstantClass> class ConstantUniqueMap;
class InlineAsm : public Value {
public:
@@ -40,9 +37,8 @@ public:
};
private:
- friend struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType>;
- friend class ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&,
- PointerType, InlineAsm, false>;
+ friend struct InlineAsmKeyType;
+ friend class ConstantUniqueMap<InlineAsm>;
InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION;
void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION;
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index 981aad852b29..030f5d690a0c 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -29,8 +29,8 @@ class LLVMContext;
// TerminatorInst Class
//===----------------------------------------------------------------------===//
-/// TerminatorInst - Subclasses of this class are all able to terminate a basic
-/// block. Thus, these are all the flow control type of operations.
+/// Subclasses of this class are all able to terminate a basic
+/// block. Thus, these are all the flow control type of operations.
///
class TerminatorInst : public Instruction {
protected:
@@ -51,23 +51,19 @@ protected:
virtual BasicBlock *getSuccessorV(unsigned idx) const = 0;
virtual unsigned getNumSuccessorsV() const = 0;
virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0;
- TerminatorInst *clone_impl() const override = 0;
public:
- /// getNumSuccessors - Return the number of successors that this terminator
- /// has.
+ /// Return the number of successors that this terminator has.
unsigned getNumSuccessors() const {
return getNumSuccessorsV();
}
- /// getSuccessor - Return the specified successor.
- ///
+ /// Return the specified successor.
BasicBlock *getSuccessor(unsigned idx) const {
return getSuccessorV(idx);
}
- /// setSuccessor - Update the specified successor to point at the provided
- /// block.
+ /// Update the specified successor to point at the provided block.
void setSuccessor(unsigned idx, BasicBlock *B) {
setSuccessorV(idx, B);
}
@@ -153,7 +149,7 @@ public:
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- /// Create() - Construct a binary instruction, given the opcode and the two
+ /// Construct a binary instruction, given the opcode and the two
/// operands. Optionally (if InstBefore is specified) insert the instruction
/// into a BasicBlock right before the specified instruction. The specified
/// Instruction is allowed to be a dereferenced end iterator.
@@ -162,14 +158,14 @@ public:
const Twine &Name = Twine(),
Instruction *InsertBefore = nullptr);
- /// Create() - Construct a binary instruction, given the opcode and the two
+ /// Construct a binary instruction, given the opcode and the two
/// operands. Also automatically insert this instruction to the end of the
/// BasicBlock specified.
///
static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2,
const Twine &Name, BasicBlock *InsertAtEnd);
- /// Create* - These methods just forward to Create, and are useful when you
+ /// These methods just forward to Create, and are useful when you
/// statically know what type of instruction you're going to create. These
/// helpers just save some typing.
#define HANDLE_BINARY_INST(N, OPC, CLASS) \
@@ -281,8 +277,7 @@ public:
/// Helper functions to construct and inspect unary operations (NEG and NOT)
/// via binary operators SUB and XOR:
///
- /// CreateNeg, CreateNot - Create the NEG and NOT
- /// instructions out of SUB and XOR instructions.
+ /// Create the NEG and NOT instructions out of SUB and XOR instructions.
///
static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "",
Instruction *InsertBefore = nullptr);
@@ -305,16 +300,14 @@ public:
static BinaryOperator *CreateNot(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd);
- /// isNeg, isFNeg, isNot - Check if the given Value is a
- /// NEG, FNeg, or NOT instruction.
+ /// Check if the given Value is a NEG, FNeg, or NOT instruction.
///
static bool isNeg(const Value *V);
static bool isFNeg(const Value *V, bool IgnoreZeroSign=false);
static bool isNot(const Value *V);
- /// getNegArgument, getNotArgument - Helper functions to extract the
- /// unary argument of a NEG, FNEG or NOT operation implemented via
- /// Sub, FSub, or Xor.
+ /// Helper functions to extract the unary argument of a NEG, FNEG or NOT
+ /// operation implemented via Sub, FSub, or Xor.
///
static const Value *getNegArgument(const Value *BinOp);
static Value *getNegArgument( Value *BinOp);
@@ -327,37 +320,42 @@ public:
return static_cast<BinaryOps>(Instruction::getOpcode());
}
- /// swapOperands - Exchange the two operands to this instruction.
+ /// Exchange the two operands to this instruction.
/// This instruction is safe to use on any binary instruction and
/// does not modify the semantics of the instruction. If the instruction
/// cannot be reversed (ie, it's a Div), then return true.
///
bool swapOperands();
- /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setHasNoUnsignedWrap(bool b = true);
- /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the nsw flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setHasNoSignedWrap(bool b = true);
- /// setIsExact - Set or clear the exact flag on this instruction,
- /// which must be an operator which supports this flag. See LangRef.html
- /// for the meaning of this flag.
+ /// Set or clear the exact flag on this instruction, which must be an operator
+ /// which supports this flag. See LangRef.html for the meaning of this flag.
void setIsExact(bool b = true);
- /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set.
+ /// Determine whether the no unsigned wrap flag is set.
bool hasNoUnsignedWrap() const;
- /// hasNoSignedWrap - Determine whether the no signed wrap flag is set.
+ /// Determine whether the no signed wrap flag is set.
bool hasNoSignedWrap() const;
- /// isExact - Determine whether the exact flag is set.
+ /// Determine whether the exact flag is set.
bool isExact() const;
+ /// Convenience method to copy supported wrapping, exact, and fast-math flags
+ /// from V to this instruction.
+ void copyIRFlags(const Value *V);
+
+ /// Logical 'and' of any supported wrapping, exact, and fast-math flags of
+ /// V and this instruction.
+ void andIRFlags(const Value *V);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Instruction *I) {
return I->isBinaryOp();
@@ -378,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value)
// CastInst Class
//===----------------------------------------------------------------------===//
-/// CastInst - This is the base class for all instructions that perform data
+/// This is the base class for all instructions that perform data
/// casts. It is simply provided so that instruction category testing
/// can be performed with code like:
///
@@ -491,6 +489,19 @@ public:
Instruction *InsertBefore = 0 ///< Place to insert the instruction
);
+ /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction.
+ ///
+ /// If the value is a pointer type and the destination an integer type,
+ /// creates a PtrToInt cast. If the value is an integer type and the
+ /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates
+ /// a bitcast.
+ static CastInst *CreateBitOrPointerCast(
+ Value *S, ///< The pointer value to be casted (operand 0)
+ Type *Ty, ///< The type to which cast should be made
+ const Twine &Name = "", ///< Name for the instruction
+ Instruction *InsertBefore = 0 ///< Place to insert the instruction
+ );
+
/// @brief Create a ZExt, BitCast, or Trunc for int -> int casts.
static CastInst *CreateIntegerCast(
Value *S, ///< The pointer value to be casted (operand 0)
@@ -553,6 +564,17 @@ public:
Type *DestTy ///< The Type to which the value should be cast.
);
+ /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these
+ /// types is valid and a no-op.
+ ///
+ /// This ensures that any pointer<->integer cast has enough bits in the
+ /// integer and any other cast is a bitcast.
+ static bool isBitOrNoopPointerCastable(
+ Type *SrcTy, ///< The Type from which the value should be cast.
+ Type *DestTy, ///< The Type to which the value should be cast.
+ const DataLayout *Layout = 0 ///< Optional DataLayout.
+ );
+
/// Returns the opcode necessary to cast Val into Ty using usual casting
/// rules.
/// @brief Infer the opcode for cast operand and type
diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h
index bac6a95b1b71..ba7791c99b6a 100644
--- a/include/llvm/IR/Instruction.h
+++ b/include/llvm/IR/Instruction.h
@@ -25,6 +25,7 @@ namespace llvm {
class FastMathFlags;
class LLVMContext;
class MDNode;
+struct AAMDNodes;
template<typename ValueSubClass, typename ItemParentClass>
class SymbolTableListTraits;
@@ -155,19 +156,25 @@ public:
/// getAllMetadata - Get all metadata attached to this Instruction. The first
/// element of each pair returned is the KindID, the second element is the
/// metadata value. This list is returned sorted by the KindID.
- void getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode*> > &MDs)const{
+ void
+ getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadata())
getAllMetadataImpl(MDs);
}
/// getAllMetadataOtherThanDebugLoc - This does the same thing as
/// getAllMetadata, except that it filters out the debug location.
- void getAllMetadataOtherThanDebugLoc(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &MDs) const {
+ void getAllMetadataOtherThanDebugLoc(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
if (hasMetadataOtherThanDebugLoc())
getAllMetadataOtherThanDebugLocImpl(MDs);
}
+ /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from
+ /// this instruction. When Merge is true, the existing AA metadata is
+ /// merged with that from this instruction providing the most-general result.
+ void getAAMetadata(AAMDNodes &N, bool Merge = false) const;
+
/// setMetadata - Set the metadata of the specified kind to the specified
/// node. This updates/replaces metadata if already present, or removes it if
/// Node is null.
@@ -179,7 +186,7 @@ public:
/// convenience method for passes to do so.
void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
void dropUnknownMetadata() {
- return dropUnknownMetadata(ArrayRef<unsigned>());
+ return dropUnknownMetadata(None);
}
void dropUnknownMetadata(unsigned ID1) {
return dropUnknownMetadata(makeArrayRef(ID1));
@@ -189,6 +196,10 @@ public:
return dropUnknownMetadata(IDs);
}
+ /// setAAMetadata - Sets the metadata on this instruction from the
+ /// AAMDNodes structure.
+ void setAAMetadata(const AAMDNodes &N);
+
/// setDebugLoc - Set the debug location information for this instruction.
void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; }
@@ -220,11 +231,16 @@ public:
/// this flag.
void setHasAllowReciprocal(bool B);
- /// Convenience function for setting all the fast-math flags on this
+ /// Convenience function for setting multiple fast-math flags on this
/// instruction, which must be an operator which supports these flags. See
- /// LangRef.html for the meaning of these flats.
+ /// LangRef.html for the meaning of these flags.
void setFastMathFlags(FastMathFlags FMF);
+ /// Convenience function for transferring all fast-math flag values to this
+ /// instruction, which must be an operator which supports these flags. See
+ /// LangRef.html for the meaning of these flags.
+ void copyFastMathFlags(FastMathFlags FMF);
+
/// Determine whether the unsafe-algebra flag is set.
bool hasUnsafeAlgebra() const;
@@ -242,7 +258,7 @@ public:
/// 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 flats.
+ /// these flags.
FastMathFlags getFastMathFlags() const;
/// Copy I's fast-math flags
@@ -258,9 +274,10 @@ private:
// These are all implemented in Metadata.cpp.
MDNode *getMetadataImpl(unsigned KindID) const;
MDNode *getMetadataImpl(StringRef Kind) const;
- void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const;
- void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &) const;
+ void
+ getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
+ void getAllMetadataOtherThanDebugLocImpl(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &) const;
void clearMetadataHashEntries();
public:
//===--------------------------------------------------------------------===//
@@ -323,6 +340,11 @@ public:
return mayReadFromMemory() || mayWriteToMemory();
}
+ /// isAtomic - Return true if this instruction has an
+ /// AtomicOrdering of unordered or higher.
+ ///
+ bool isAtomic() const;
+
/// mayThrow - Return true if this instruction may throw an exception.
///
bool mayThrow() const;
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 308467f7aa17..045e51eb1baa 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -17,8 +17,8 @@
#define LLVM_IR_INSTRUCTIONS_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DerivedTypes.h"
@@ -50,6 +50,22 @@ enum SynchronizationScope {
CrossThread = 1
};
+/// Returns true if the ordering is at least as strong as acquire
+/// (i.e. acquire, acq_rel or seq_cst)
+inline bool isAtLeastAcquire(AtomicOrdering Ord) {
+ return (Ord == Acquire ||
+ Ord == AcquireRelease ||
+ Ord == SequentiallyConsistent);
+}
+
+/// Returns true if the ordering is at least as strong as release
+/// (i.e. release, acq_rel or seq_cst)
+inline bool isAtLeastRelease(AtomicOrdering Ord) {
+return (Ord == Release ||
+ Ord == AcquireRelease ||
+ Ord == SequentiallyConsistent);
+}
+
//===----------------------------------------------------------------------===//
// AllocaInst Class
//===----------------------------------------------------------------------===//
@@ -119,7 +135,7 @@ public:
return getSubclassDataFromInstruction() & 32;
}
- /// \brief Specify whether this alloca is used to represent a the arguments to
+ /// \brief Specify whether this alloca is used to represent the arguments to
/// a call.
void setUsedWithInAlloca(bool V) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~32) |
@@ -225,7 +241,6 @@ public:
(xthread << 6));
}
- bool isAtomic() const { return getOrdering() != NotAtomic; }
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
setOrdering(Ordering);
@@ -345,7 +360,6 @@ public:
(xthread << 6));
}
- bool isAtomic() const { return getOrdering() != NotAtomic; }
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
setOrdering(Ordering);
@@ -637,7 +651,7 @@ public:
Sub,
/// *p = old & v
And,
- /// *p = ~old & v
+ /// *p = ~(old & v)
Nand,
/// *p = old | v
Or,
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index e053f7867c53..c227ea080167 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -28,6 +28,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
namespace llvm {
/// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
@@ -81,7 +82,14 @@ namespace llvm {
class DbgDeclareInst : public DbgInfoIntrinsic {
public:
Value *getAddress() const;
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(1))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
@@ -102,7 +110,14 @@ namespace llvm {
return cast<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
}
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(3))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
@@ -320,6 +335,33 @@ namespace llvm {
Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); }
};
+ /// This represents the llvm.instrprof_increment intrinsic.
+ class InstrProfIncrementInst : public IntrinsicInst {
+ public:
+ static inline bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::instrprof_increment;
+ }
+ static inline bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+
+ GlobalVariable *getName() const {
+ return cast<GlobalVariable>(
+ const_cast<Value *>(getArgOperand(0))->stripPointerCasts());
+ }
+
+ ConstantInt *getHash() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1)));
+ }
+
+ ConstantInt *getNumCounters() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2)));
+ }
+
+ ConstantInt *getIndex() const {
+ return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3)));
+ }
+ };
}
#endif
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index b0d746bd4127..56d1e4af26aa 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -28,10 +28,9 @@ class LLVMContext;
class Module;
class AttributeSet;
-/// Intrinsic Namespace - This namespace contains an enum with a value for
-/// every intrinsic/builtin function known by LLVM. These enum values are
-/// returned by Function::getIntrinsicID().
-///
+/// This namespace contains an enum with a value for every intrinsic/builtin
+/// function known by LLVM. The enum values are returned by
+/// Function::getIntrinsicID().
namespace Intrinsic {
enum ID {
not_intrinsic = 0, // Must be zero
@@ -43,25 +42,21 @@ namespace Intrinsic {
, num_intrinsics
};
- /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as
- /// "llvm.ppc.altivec.lvx".
+ /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx".
std::string getName(ID id, ArrayRef<Type*> Tys = None);
- /// Intrinsic::getType(ID) - Return the function type for an intrinsic.
- ///
+ /// Return the function type for an intrinsic.
FunctionType *getType(LLVMContext &Context, ID id,
ArrayRef<Type*> Tys = None);
- /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be
- /// overloaded.
+ /// Returns true if the intrinsic can be overloaded.
bool isOverloaded(ID id);
- /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic.
- ///
+ /// Return the attributes for an intrinsic.
AttributeSet getAttributes(LLVMContext &C, ID id);
- /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function
- /// declaration for an intrinsic, and return it.
+ /// Create or insert an LLVM Function declaration for an intrinsic, and return
+ /// it.
///
/// The Tys parameter is for intrinsics with overloaded types (e.g., those
/// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded
@@ -75,14 +70,14 @@ namespace Intrinsic {
/// Map a MS builtin name to an intrinsic ID.
ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName);
- /// IITDescriptor - This is a type descriptor which explains the type
- /// requirements of an intrinsic. This is returned by
- /// getIntrinsicInfoTableEntries.
+ /// This is a type descriptor which explains the type requirements of an
+ /// intrinsic. This is returned by getIntrinsicInfoTableEntries.
struct IITDescriptor {
enum IITDescriptorKind {
Void, VarArg, MMX, Metadata, Half, Float, Double,
Integer, Vector, Pointer, Struct,
- Argument, ExtendArgument, TruncArgument, HalfVecArgument
+ Argument, ExtendArgument, TruncArgument, HalfVecArgument,
+ SameVecWidthArgument, PtrToArgument
} Kind;
union {
@@ -102,13 +97,15 @@ namespace Intrinsic {
};
unsigned getArgumentNumber() const {
assert(Kind == Argument || Kind == ExtendArgument ||
- Kind == TruncArgument || Kind == HalfVecArgument);
+ Kind == TruncArgument || Kind == HalfVecArgument ||
+ Kind == SameVecWidthArgument || Kind == PtrToArgument);
return Argument_Info >> 2;
}
ArgKind getArgumentKind() const {
assert(Kind == Argument || Kind == ExtendArgument ||
- Kind == TruncArgument || Kind == HalfVecArgument);
- return (ArgKind)(Argument_Info&3);
+ Kind == TruncArgument || Kind == HalfVecArgument ||
+ Kind == SameVecWidthArgument || Kind == PtrToArgument);
+ return (ArgKind)(Argument_Info & 3);
}
static IITDescriptor get(IITDescriptorKind K, unsigned Field) {
@@ -117,9 +114,8 @@ namespace Intrinsic {
}
};
- /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the
- /// specified intrinsic into an array of IITDescriptors.
- ///
+ /// Return the IIT table descriptor for the specified intrinsic into an array
+ /// of IITDescriptors.
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
} // End Intrinsic namespace
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 0b8f64fc7984..a1188bccdc25 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -112,6 +112,11 @@ class LLVMMatchType<int num>
// the intrinsic is overloaded, so the matched type should be declared as iAny.
class LLVMExtendedType<int num> : LLVMMatchType<num>;
class LLVMTruncatedType<int num> : LLVMMatchType<num>;
+class LLVMVectorSameWidth<int num, LLVMType elty>
+ : LLVMMatchType<num> {
+ ValueType ElTy = elty.VT;
+}
+class LLVMPointerTo<int num> : LLVMMatchType<num>;
// Match the type of another intrinsic parameter that is expected to be a
// vector type, but change the element count to be half as many
@@ -254,6 +259,10 @@ def int_gcwrite : Intrinsic<[],
//
def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>;
+def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
+def int_framerecover : Intrinsic<[llvm_ptr_ty],
+ [llvm_ptr_ty, llvm_ptr_ty],
+ [IntrNoMem]>;
def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
[IntrNoMem], "llvm.read_register">;
def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],
@@ -277,12 +286,22 @@ def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>;
def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>;
+// The assume intrinsic is marked as arbitrarily writing so that proper
+// control dependencies will be maintained.
+def int_assume : Intrinsic<[], [llvm_i1_ty], []>;
+
// Stack Protector Intrinsic - The stackprotector intrinsic writes the stack
// guard to the correct place on the stack frame.
def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>;
def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty],
[IntrReadWriteArgMem]>;
+// A counter increment for instrumentation based profiling.
+def int_instrprof_increment : Intrinsic<[],
+ [llvm_ptr_ty, llvm_i64_ty,
+ llvm_i32_ty, llvm_i32_ty],
+ []>;
+
//===------------------- Standard C Library Intrinsics --------------------===//
//
@@ -324,6 +343,8 @@ let Properties = [IntrNoMem] in {
def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
+ def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
+ def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_copysign : Intrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>]>;
def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>;
@@ -369,9 +390,12 @@ let Properties = [IntrNoMem] in {
// places.
let Properties = [IntrNoMem] in {
def int_dbg_declare : Intrinsic<[],
- [llvm_metadata_ty, llvm_metadata_ty]>;
+ [llvm_metadata_ty,
+ llvm_metadata_ty,
+ llvm_metadata_ty]>;
def int_dbg_value : Intrinsic<[],
[llvm_metadata_ty, llvm_i64_ty,
+ llvm_metadata_ty,
llvm_metadata_ty]>;
}
@@ -476,11 +500,29 @@ def int_experimental_stackmap : Intrinsic<[],
def int_experimental_patchpoint_void : Intrinsic<[],
[llvm_i64_ty, llvm_i32_ty,
llvm_ptr_ty, llvm_i32_ty,
- llvm_vararg_ty]>;
+ llvm_vararg_ty],
+ [Throws]>;
def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
[llvm_i64_ty, llvm_i32_ty,
llvm_ptr_ty, llvm_i32_ty,
- llvm_vararg_ty]>;
+ llvm_vararg_ty],
+ [Throws]>;
+
+
+//===------------------------ Garbage Collection Intrinsics ---------------===//
+// These are documented in docs/Statepoint.rst
+
+def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
+ [llvm_anyptr_ty, llvm_i32_ty,
+ llvm_i32_ty, llvm_vararg_ty]>;
+
+def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>;
+def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty],
+ [llvm_i32_ty]>;
+def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>;
+
+def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
+ [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>;
//===-------------------------- Other Intrinsics --------------------------===//
//
@@ -528,6 +570,17 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty],
def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty],
[], "llvm.clear_cache">;
+//===-------------------------- Masked Intrinsics -------------------------===//
+//
+def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>,
+ llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>],
+ [IntrReadWriteArgMem]>;
+
+def int_masked_load : Intrinsic<[llvm_anyvector_ty],
+ [LLVMPointerTo<0>, llvm_i32_ty,
+ LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>],
+ [IntrReadArgMem]>;
//===----------------------------------------------------------------------===//
// Target-specific intrinsics
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td
index a02d7072d720..ce758e257312 100644
--- a/include/llvm/IR/IntrinsicsARM.td
+++ b/include/llvm/IR/IntrinsicsARM.td
@@ -20,8 +20,13 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.".
def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">,
Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
+// A space-consuming intrinsic primarily for testing ARMConstantIslands. The
+// first argument is the number of bytes this "instruction" takes up, the second
+// and return value are essentially chains, used to force ordering during ISel.
+def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>;
+
//===----------------------------------------------------------------------===//
-// Saturating Arithmentic
+// Saturating Arithmetic
def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
@@ -132,6 +137,7 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
// HINT
def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>;
+def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>;
//===----------------------------------------------------------------------===//
// RBIT
@@ -340,10 +346,6 @@ def int_arm_neon_vqneg : Neon_1Arg_Intrinsic;
// Vector Count Leading Sign/Zero Bits.
def int_arm_neon_vcls : Neon_1Arg_Intrinsic;
-def int_arm_neon_vclz : Neon_1Arg_Intrinsic;
-
-// Vector Count One Bits.
-def int_arm_neon_vcnt : Neon_1Arg_Intrinsic;
// Vector Reciprocal Estimate.
def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic;
diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td
index cd512841a1af..9deed414b50a 100644
--- a/include/llvm/IR/IntrinsicsNVVM.td
+++ b/include/llvm/IR/IntrinsicsNVVM.td
@@ -797,24 +797,30 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
// Generated within nvvm. Use for ldu on sm_20 or later
def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.i">;
def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.f">;
def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldu.global.p">;
// Generated within nvvm. Use for ldg on sm_35 or later
def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.i">;
def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.f">;
def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty],
- [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>],
+ [LLVMAnyPointerType<LLVMMatchType<0>>, llvm_i32_ty],
+ [IntrReadMem, NoCapture<0>],
"llvm.nvvm.ldg.global.p">;
// Use for generic pointers
diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td
index 49ddfb8b613b..5cdabdeadaea 100644
--- a/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/include/llvm/IR/IntrinsicsPowerPC.td
@@ -28,8 +28,10 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>;
def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>;
- // sync instruction
+ // sync instruction (i.e. sync 0, a.k.a hwsync)
def int_ppc_sync : Intrinsic<[], [], []>;
+ // lwsync is sync 1
+ def int_ppc_lwsync : Intrinsic<[], [], []>;
// Intrinsics used to generate ctr-based loops. These should only be
// generated by the PowerPC backend!
@@ -45,6 +47,13 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
list<IntrinsicProperty> properties>
: GCCBuiltin<!strconcat("__builtin_altivec_", GCCIntSuffix)>,
Intrinsic<ret_types, param_types, properties>;
+
+ /// PowerPC_VSX_Intrinsic - Base class for all VSX intrinsics.
+ class PowerPC_VSX_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types,
+ list<LLVMType> param_types,
+ list<IntrinsicProperty> properties>
+ : GCCBuiltin<!strconcat("__builtin_vsx_", GCCIntSuffix)>,
+ Intrinsic<ret_types, param_types, properties>;
}
//===----------------------------------------------------------------------===//
@@ -87,6 +96,32 @@ class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix>
//===----------------------------------------------------------------------===//
+// PowerPC VSX Intrinsic Class Definitions.
+//
+
+/// PowerPC_VSX_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2f64
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Vec_DDD_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_VSX_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32
+/// vectors and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Vec_FFF_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty],
+ [IntrNoMem]>;
+
+/// PowerPC_VSX_Sca_DDD_Intrinsic - A PowerPC intrinsic that takes two f64
+/// scalars and returns one. These intrinsics have no side effects.
+class PowerPC_VSX_Sca_DDD_Intrinsic<string GCCIntSuffix>
+ : PowerPC_VSX_Intrinsic<GCCIntSuffix,
+ [llvm_double_ty], [llvm_double_ty, llvm_double_ty],
+ [IntrNoMem]>;
+
+
+//===----------------------------------------------------------------------===//
// PowerPC Altivec Intrinsic Definitions.
let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
@@ -474,3 +509,36 @@ def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">;
def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">;
def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">;
def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">;
+
+
+//===----------------------------------------------------------------------===//
+// PowerPC VSX Intrinsic Definitions.
+
+let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
+
+// Vector load.
+def int_ppc_vsx_lxvw4x :
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+def int_ppc_vsx_lxvd2x :
+ Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>;
+
+// Vector store.
+def int_ppc_vsx_stxvw4x :
+ Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+def int_ppc_vsx_stxvd2x :
+ Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>;
+
+// 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">;
+def int_ppc_vsx_xsmaxdp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmaxdp">;
+
+// Vector and scalar minimum.
+def int_ppc_vsx_xvmindp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmindp">;
+def int_ppc_vsx_xvminsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvminsp">;
+def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">;
+
+// Vector divide.
+def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">;
+def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">;
+}
diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td
index ba69eaae089f..505566738221 100644
--- a/include/llvm/IR/IntrinsicsR600.td
+++ b/include/llvm/IR/IntrinsicsR600.td
@@ -33,10 +33,14 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz <
"__builtin_r600_read_tgid">;
defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz <
"__builtin_r600_read_tidig">;
-
} // End TargetPrefix = "r600"
let TargetPrefix = "AMDGPU" in {
+
+class AMDGPUReadPreloadRegisterIntrinsic<string name>
+ : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>,
+ GCCBuiltin<name>;
+
def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">,
// 1st parameter: Numerator
// 2nd parameter: Denominator
@@ -48,7 +52,7 @@ def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">,
def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">,
Intrinsic<[llvm_anyfloat_ty],
- [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
+ [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
[IntrNoMem]>;
def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">,
@@ -69,4 +73,13 @@ def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">,
def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">,
Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">,
+ Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>;
+
+def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">,
+ Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>;
+
+def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic <
+ "__builtin_amdgpu_read_workdim">;
+
} // End TargetPrefix = "AMDGPU"
diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td
index 5de950813cd4..81c729065505 100644
--- a/include/llvm/IR/IntrinsicsX86.td
+++ b/include/llvm/IR/IntrinsicsX86.td
@@ -886,7 +886,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector insert
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
}
@@ -896,13 +896,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty],
[IntrNoMem]>;
def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem]>;
def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">,
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty],
@@ -915,17 +915,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
// Vector dot product
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">,
- Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
[IntrNoMem, Commutative]>;
def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">,
- Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
[IntrNoMem, Commutative]>;
}
// Vector sum of absolute differences
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">,
- Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty],
+ Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty],
[IntrNoMem, Commutative]>;
}
@@ -1171,10 +1171,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
- llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">,
Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty,
llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>;
@@ -1187,7 +1187,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">,
Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty,
- llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>;
+ llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Vector compare
@@ -1389,6 +1389,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
GCCBuiltin<"__builtin_ia32_storeupd512_mask">,
Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_store_ss :
+ GCCBuiltin<"__builtin_ia32_storess_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty],
+ [IntrReadWriteArgMem]>;
}
//===----------------------------------------------------------------------===//
@@ -1580,6 +1584,44 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_i32_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrai_d : GCCBuiltin<"__builtin_ia32_psradi512">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Pack ops.
@@ -1706,13 +1748,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v32i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">,
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
- llvm_i32_ty], [IntrNoMem]>;
+ llvm_i8_ty], [IntrNoMem]>;
}
// Vector load with broadcast
@@ -1787,6 +1829,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">,
Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty,
llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_vextractf32x4_512 :
+ GCCBuiltin<"__builtin_ia32_extractf32x4_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty,
+ llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextracti32x4_512 :
+ GCCBuiltin<"__builtin_ia32_extracti32x4_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v16i32_ty, llvm_i8_ty,
+ llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextractf64x4_512 :
+ GCCBuiltin<"__builtin_ia32_extractf64x4_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v8f64_ty, llvm_i8_ty,
+ llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_vextracti64x4_512 :
+ GCCBuiltin<"__builtin_ia32_extracti64x4_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v8i64_ty, llvm_i8_ty,
+ llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>;
}
// Conditional load ops
@@ -1871,6 +1930,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">,
Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty],
[IntrNoMem]>;
+
+ def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty,
+ llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty,
+ llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
}
// Gather ops
@@ -1951,11 +2035,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
llvm_v32i8_ty], [IntrNoMem]>;
def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">,
Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty,
- llvm_i32_ty], [IntrNoMem, Commutative]>;
+ llvm_i8_ty], [IntrNoMem, Commutative]>;
def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">,
Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
- def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">,
- Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
@@ -1986,13 +2068,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">,
+ def int_x86_fma_mask_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">,
+ def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2018,13 +2122,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">,
+ def int_x86_fma_mask_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">,
+ def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2050,13 +2176,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">,
+ def int_x86_fma_mask_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">,
+ def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">,
Intrinsic<[llvm_v4f32_ty],
@@ -2082,13 +2230,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">,
+ def int_x86_fma_mask_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
[IntrNoMem]>;
- def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">,
+ def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">,
Intrinsic<[llvm_v4f32_ty],
@@ -2108,13 +2278,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">,
+ def int_x86_fma_mask_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">,
+ def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">,
Intrinsic<[llvm_v4f32_ty],
@@ -2134,13 +2326,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v4f64_ty],
[llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">,
+ def int_x86_fma_mask_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask">,
Intrinsic<[llvm_v16f32_ty],
- [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty],
+ [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
- def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">,
+ def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">,
Intrinsic<[llvm_v8f64_ty],
- [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty],
+ [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty],
[IntrNoMem]>;
}
@@ -2749,6 +2963,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
}
//===----------------------------------------------------------------------===//
+// ADX
+
+let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
+ def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarry_u32: GCCBuiltin<"__builtin_ia32_addcarry_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_addcarry_u64: GCCBuiltin<"__builtin_ia32_addcarry_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_subborrow_u32: GCCBuiltin<"__builtin_ia32_subborrow_u32">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+ def int_x86_subborrow_u64: GCCBuiltin<"__builtin_ia32_subborrow_u64">,
+ Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty,
+ llvm_ptr_ty], [IntrReadWriteArgMem]>;
+}
+
+//===----------------------------------------------------------------------===//
// RTM intrinsics. Transactional Memory support.
let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
@@ -2955,10 +3193,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty],
[IntrNoMem]>;
- def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">,
- Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>;
- def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">,
- Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty,
@@ -2993,6 +3233,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">,
Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
+
def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_mask">,
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty],
@@ -3167,10 +3414,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v16f32_ty],
[llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">,
+ Intrinsic<[llvm_v8f32_ty],
+ [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">,
+ Intrinsic<[llvm_v4f32_ty],
+ [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">,
Intrinsic<[llvm_v8f64_ty],
[llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">,
+ Intrinsic<[llvm_v4f64_ty],
+ [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">,
+ Intrinsic<[llvm_v2f64_ty],
+ [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">,
Intrinsic<[llvm_v16i32_ty],
@@ -3180,8 +3443,428 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
Intrinsic<[llvm_v8i64_ty],
[llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">,
+ Intrinsic<[llvm_v8i32_ty],
+ [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">,
+ Intrinsic<[llvm_v4i64_ty],
+ [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">,
+ Intrinsic<[llvm_v4i32_ty],
+ [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">,
+ Intrinsic<[llvm_v2i64_ty],
+ [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">,
+ Intrinsic<[llvm_v32i16_ty],
+ [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">,
+ Intrinsic<[llvm_v16i16_ty],
+ [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">,
+ Intrinsic<[llvm_v8i16_ty],
+ [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">,
+ Intrinsic<[llvm_v64i8_ty],
+ [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">,
+ Intrinsic<[llvm_v32i8_ty],
+ [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">,
+ Intrinsic<[llvm_v16i8_ty],
+ [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+
+}
+
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_valign_q_512 : GCCBuiltin<"__builtin_ia32_alignq512_mask">,
+ Intrinsic<[llvm_v8i64_ty],
+ [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_valign_d_512 : GCCBuiltin<"__builtin_ia32_alignd512_mask">,
+ Intrinsic<[llvm_v16i32_ty],
+ [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
}
+// Compares
+let TargetPrefix = "x86" in {
+ // 512-bit
+ def int_x86_avx512_mask_pcmpeq_b_512 : GCCBuiltin<"__builtin_ia32_pcmpeqb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_512 : GCCBuiltin<"__builtin_ia32_pcmpeqw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_512: GCCBuiltin<"__builtin_ia32_pcmpgtb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_512: GCCBuiltin<"__builtin_ia32_pcmpgtw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_512: GCCBuiltin<"__builtin_ia32_pcmpgtd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_512: GCCBuiltin<"__builtin_ia32_pcmpgtq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
+ llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem ]>;
+ def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">,
+ Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty,
+ llvm_i64_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ // 256-bit
+ def int_x86_avx512_mask_pcmpeq_b_256 : GCCBuiltin<"__builtin_ia32_pcmpeqb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_256 : GCCBuiltin<"__builtin_ia32_pcmpeqw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_256 : GCCBuiltin<"__builtin_ia32_pcmpeqd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_256 : GCCBuiltin<"__builtin_ia32_pcmpeqq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_256: GCCBuiltin<"__builtin_ia32_pcmpgtb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_256: GCCBuiltin<"__builtin_ia32_pcmpgtw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_256: GCCBuiltin<"__builtin_ia32_pcmpgtd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_256: GCCBuiltin<"__builtin_ia32_pcmpgtq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">,
+ Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty,
+ llvm_i32_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ // 128-bit
+ def int_x86_avx512_mask_pcmpeq_b_128 : GCCBuiltin<"__builtin_ia32_pcmpeqb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_w_128 : GCCBuiltin<"__builtin_ia32_pcmpeqw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_d_128 : GCCBuiltin<"__builtin_ia32_pcmpeqd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpeq_q_128 : GCCBuiltin<"__builtin_ia32_pcmpeqq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_pcmpgt_b_128: GCCBuiltin<"__builtin_ia32_pcmpgtb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_w_128: GCCBuiltin<"__builtin_ia32_pcmpgtw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_d_128: GCCBuiltin<"__builtin_ia32_pcmpgtd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+ def int_x86_avx512_mask_pcmpgt_q_128: GCCBuiltin<"__builtin_ia32_pcmpgtq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty],
+ [IntrNoMem]>;
+
+ def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">,
+ Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">,
+ Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+}
+
+// Compress, Expand
+let TargetPrefix = "x86" in {
+ def int_x86_avx512_mask_compress_ps_512 :
+ GCCBuiltin<"__builtin_ia32_compresssf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_512 :
+ GCCBuiltin<"__builtin_ia32_compressdf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_ps_256 :
+ GCCBuiltin<"__builtin_ia32_compresssf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_256 :
+ GCCBuiltin<"__builtin_ia32_compressdf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_ps_128 :
+ GCCBuiltin<"__builtin_ia32_compresssf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_pd_128 :
+ GCCBuiltin<"__builtin_ia32_compressdf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_compress_store_ps_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_ps_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_ps_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_pd_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+
+ def int_x86_avx512_mask_compress_d_512 :
+ GCCBuiltin<"__builtin_ia32_compresssi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_512 :
+ GCCBuiltin<"__builtin_ia32_compressdi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_d_256 :
+ GCCBuiltin<"__builtin_ia32_compresssi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_256 :
+ GCCBuiltin<"__builtin_ia32_compressdi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_d_128 :
+ GCCBuiltin<"__builtin_ia32_compresssi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_compress_q_128 :
+ GCCBuiltin<"__builtin_ia32_compressdi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_compress_store_d_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_512 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_d_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_256 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_d_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+ def int_x86_avx512_mask_compress_store_q_128 :
+ GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">,
+ Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrReadWriteArgMem]>;
+
+// expand
+ def int_x86_avx512_mask_expand_ps_512 :
+ GCCBuiltin<"__builtin_ia32_expandsf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_512 :
+ GCCBuiltin<"__builtin_ia32_expanddf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_ps_256 :
+ GCCBuiltin<"__builtin_ia32_expandsf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_256 :
+ GCCBuiltin<"__builtin_ia32_expanddf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_ps_128 :
+ GCCBuiltin<"__builtin_ia32_expandsf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_pd_128 :
+ GCCBuiltin<"__builtin_ia32_expanddf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_expand_load_ps_512 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">,
+ Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty,
+ llvm_i16_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_512 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">,
+ Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_ps_256 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">,
+ Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_256 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">,
+ Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_ps_128 :
+ GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">,
+ Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_pd_128 :
+ GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">,
+ Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+
+ def int_x86_avx512_mask_expand_d_512 :
+ GCCBuiltin<"__builtin_ia32_expandsi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_512 :
+ GCCBuiltin<"__builtin_ia32_expanddi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_d_256 :
+ GCCBuiltin<"__builtin_ia32_expandsi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_256 :
+ GCCBuiltin<"__builtin_ia32_expanddi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_d_128 :
+ GCCBuiltin<"__builtin_ia32_expandsi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+ def int_x86_avx512_mask_expand_q_128 :
+ GCCBuiltin<"__builtin_ia32_expanddi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrNoMem]>;
+
+ def int_x86_avx512_mask_expand_load_d_512 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">,
+ Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty,
+ llvm_i16_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_512 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_d_256 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">,
+ Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_256 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">,
+ Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_d_128 :
+ GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">,
+ Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+ def int_x86_avx512_mask_expand_load_q_128 :
+ GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">,
+ Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty,
+ llvm_i8_ty], [IntrReadArgMem]>;
+
+}
// Misc.
let TargetPrefix = "x86" in {
def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">,
@@ -3190,13 +3873,6 @@ let TargetPrefix = "x86" in {
def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">,
Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty,
llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>;
-
- def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">,
- Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty],
- [IntrNoMem]>;
- def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">,
- Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty],
- [IntrNoMem]>;
def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">,
Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty,
llvm_v16i32_ty, llvm_i16_ty],
@@ -3205,6 +3881,8 @@ let TargetPrefix = "x86" in {
Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty,
llvm_v8i64_ty, llvm_i8_ty],
[IntrNoMem]>;
+ def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">,
+ Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>;
}
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h
index 4d940d599b9a..2f18782a0730 100644
--- a/include/llvm/IR/LLVMContext.h
+++ b/include/llvm/IR/LLVMContext.h
@@ -18,6 +18,7 @@
#include "llvm-c/Core.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Options.h"
namespace llvm {
@@ -52,7 +53,12 @@ public:
MD_fpmath = 3, // "fpmath"
MD_range = 4, // "range"
MD_tbaa_struct = 5, // "tbaa.struct"
- MD_invariant_load = 6 // "invariant.load"
+ MD_invariant_load = 6, // "invariant.load"
+ MD_alias_scope = 7, // "alias.scope"
+ MD_noalias = 8, // "noalias",
+ MD_nontemporal = 9, // "nontemporal"
+ MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access"
+ MD_nonnull = 11 // "nonnull"
};
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
@@ -97,12 +103,14 @@ public:
/// setDiagnosticHandler - This method sets a handler that is invoked
/// when the backend needs to report anything to the user. The first
/// argument is a function pointer and the second is a context pointer that
- /// gets passed into the DiagHandler.
+ /// gets passed into the DiagHandler. The third argument should be set to
+ /// true if the handler only expects enabled diagnostics.
///
/// LLVMContext doesn't take ownership or interpret either of these
/// pointers.
void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
- void *DiagContext = nullptr);
+ void *DiagContext = nullptr,
+ bool RespectFilters = false);
/// getDiagnosticHandler - Return the diagnostic handler set by
/// setDiagnosticHandler.
@@ -112,14 +120,16 @@ public:
/// setDiagnosticContext.
void *getDiagnosticContext() const;
- /// diagnose - Report a message to the currently installed diagnostic handler.
+ /// \brief Report a message to the currently installed diagnostic handler.
+ ///
/// This function returns, in particular in the case of error reporting
- /// (DI.Severity == RS_Error), so the caller should leave the compilation
+ /// (DI.Severity == \a DS_Error), so the caller should leave the compilation
/// process in a self-consistent state, even though the generated code
/// need not be correct.
- /// The diagnostic message will be implicitly prefixed with a severity
- /// keyword according to \p DI.getSeverity(), i.e., "error: "
- /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.
+ ///
+ /// The diagnostic message will be implicitly prefixed with a severity keyword
+ /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error,
+ /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note.
void diagnose(const DiagnosticInfo &DI);
/// \brief Registers a yield callback with the given context.
@@ -157,6 +167,14 @@ public:
void emitError(const Instruction *I, const Twine &ErrorStr);
void emitError(const Twine &ErrorStr);
+ /// \brief Query for a debug option's value.
+ ///
+ /// This function returns typed data populated from command line parsing.
+ template <typename ValT, typename Base, ValT(Base::*Mem)>
+ ValT getOption() const {
+ return OptionRegistry::instance().template get<ValT, Base, Mem>();
+ }
+
private:
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h
deleted file mode 100644
index cb18df875867..000000000000
--- a/include/llvm/IR/LeakDetector.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a class that can be used to provide very simple memory leak
-// checks for an API. Basically LLVM uses this to make sure that Instructions,
-// for example, are deleted when they are supposed to be, and not leaked away.
-//
-// When compiling with NDEBUG (Release build), this class does nothing, thus
-// adding no checking overhead to release builds. Note that this class is
-// implemented in a very simple way, requiring completely manual manipulation
-// and checking for garbage, but this is intentional: users should not be using
-// this API, only other APIs should.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_IR_LEAKDETECTOR_H
-#define LLVM_IR_LEAKDETECTOR_H
-
-#include <string>
-
-namespace llvm {
-
-class LLVMContext;
-class Value;
-
-struct LeakDetector {
- /// addGarbageObject - Add a pointer to the internal set of "garbage" object
- /// pointers. This should be called when objects are created, or if they are
- /// taken out of an owning collection.
- ///
- static void addGarbageObject(void *Object) {
-#ifndef NDEBUG
- addGarbageObjectImpl(Object);
-#endif
- }
-
- /// removeGarbageObject - Remove a pointer from our internal representation of
- /// our "garbage" objects. This should be called when an object is added to
- /// an "owning" collection.
- ///
- static void removeGarbageObject(void *Object) {
-#ifndef NDEBUG
- removeGarbageObjectImpl(Object);
-#endif
- }
-
- /// checkForGarbage - Traverse the internal representation of garbage
- /// pointers. If there are any pointers that have been add'ed, but not
- /// remove'd, big obnoxious warnings about memory leaks are issued.
- ///
- /// The specified message will be printed indicating when the check was
- /// performed.
- ///
- static void checkForGarbage(LLVMContext &C, const std::string &Message) {
-#ifndef NDEBUG
- checkForGarbageImpl(C, Message);
-#endif
- }
-
- /// Overload the normal methods to work better with Value*'s because they are
- /// by far the most common in LLVM. This does not affect the actual
- /// functioning of this class, it just makes the warning messages nicer.
- ///
- static void addGarbageObject(const Value *Object) {
-#ifndef NDEBUG
- addGarbageObjectImpl(Object);
-#endif
- }
- static void removeGarbageObject(const Value *Object) {
-#ifndef NDEBUG
- removeGarbageObjectImpl(Object);
-#endif
- }
-
-private:
- // If we are debugging, the actual implementations will be called...
- static void addGarbageObjectImpl(const Value *Object);
- static void removeGarbageObjectImpl(const Value *Object);
- static void addGarbageObjectImpl(void *Object);
- static void removeGarbageObjectImpl(void *Object);
- static void checkForGarbageImpl(LLVMContext &C, const std::string &Message);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h
index c967a6bca8b2..6c04e9dc3d3f 100644
--- a/include/llvm/IR/LegacyPassManager.h
+++ b/include/llvm/IR/LegacyPassManager.h
@@ -37,9 +37,10 @@ class PassManagerBase {
public:
virtual ~PassManagerBase();
- /// add - Add a pass to the queue of passes to run. This passes ownership of
+ /// Add a pass to the queue of passes to run. This passes ownership of
/// the Pass to the PassManager. When the PassManager is destroyed, the pass
/// will be destroyed as well, so there is no need to delete the pass. This
+ /// may even destroy the pass right away if it is found to be redundant. This
/// implies that all passes MUST be allocated with 'new'.
virtual void add(Pass *P) = 0;
};
@@ -51,10 +52,6 @@ public:
PassManager();
~PassManager();
- /// add - Add a pass to the queue of passes to run. This passes ownership of
- /// the Pass to the PassManager. When the PassManager is destroyed, the pass
- /// will be destroyed as well, so there is no need to delete the pass. This
- /// implies that all passes MUST be allocated with 'new'.
void add(Pass *P) override;
/// run - Execute all of the passes scheduled for execution. Keep track of
@@ -75,11 +72,6 @@ public:
explicit FunctionPassManager(Module *M);
~FunctionPassManager();
- /// add - Add a pass to the queue of passes to run. This passes
- /// ownership of the Pass to the PassManager. When the
- /// PassManager_X is destroyed, the pass will be destroyed as well, so
- /// there is no need to delete the pass.
- /// This implies that all passes MUST be allocated with 'new'.
void add(Pass *P) override;
/// run - Execute all of the passes scheduled for execution. Keep
diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h
index f6065a4e21a6..ab500a1dd2a3 100644
--- a/include/llvm/IR/LegacyPassManagers.h
+++ b/include/llvm/IR/LegacyPassManagers.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PASSMANAGERS_H
-#define LLVM_PASSMANAGERS_H
+#ifndef LLVM_IR_LEGACYPASSMANAGERS_H
+#define LLVM_IR_LEGACYPASSMANAGERS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -61,7 +61,7 @@
//
// [o] class FunctionPassManager;
//
-// This is a external interface used by JIT to manage FunctionPasses. This
+// This is a external interface used to manage FunctionPasses. This
// interface relies on FunctionPassManagerImpl to do all the tasks.
//
// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager,
@@ -248,7 +248,7 @@ private:
DenseMap<Pass *, SmallPtrSet<Pass *, 8> > InversedLastUser;
/// Immutable passes are managed by top level manager.
- SmallVector<ImmutablePass *, 8> ImmutablePasses;
+ SmallVector<ImmutablePass *, 16> ImmutablePasses;
DenseMap<Pass *, AnalysisUsage *> AnUsageMap;
};
@@ -393,7 +393,7 @@ private:
// Collection of higher level analysis used by the pass managed by
// this manager.
- SmallVector<Pass *, 8> HigherLevelAnalysis;
+ SmallVector<Pass *, 16> HigherLevelAnalysis;
unsigned Depth;
};
diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h
index 37d263bf52a8..91a6685f6125 100644
--- a/include/llvm/IR/MDBuilder.h
+++ b/include/llvm/IR/MDBuilder.h
@@ -15,6 +15,7 @@
#ifndef LLVM_IR_MDBUILDER_H
#define LLVM_IR_MDBUILDER_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
@@ -23,9 +24,10 @@ namespace llvm {
class APInt;
template <typename T> class ArrayRef;
class LLVMContext;
+class Constant;
+class ConstantAsMetadata;
class MDNode;
class MDString;
-class StringRef;
class MDBuilder {
LLVMContext &Context;
@@ -36,6 +38,9 @@ public:
/// \brief Return the given string as metadata.
MDString *createString(StringRef Str);
+ /// \brief Return the given constant as metadata.
+ ConstantAsMetadata *createConstant(Constant *C);
+
//===------------------------------------------------------------------===//
// FPMath metadata.
//===------------------------------------------------------------------===//
@@ -63,19 +68,54 @@ public:
MDNode *createRange(const APInt &Lo, const APInt &Hi);
//===------------------------------------------------------------------===//
- // TBAA metadata.
+ // AA metadata.
//===------------------------------------------------------------------===//
- /// \brief Return metadata appropriate for a TBAA root node. Each returned
+protected:
+ /// \brief Return metadata appropriate for a AA root node (scope or TBAA).
+ /// Each returned node is distinct from all other metadata and will never
+ /// be identified (uniqued) with anything else.
+ MDNode *createAnonymousAARoot(StringRef Name = StringRef(),
+ MDNode *Extra = nullptr);
+
+public:
+ /// \brief Return metadata appropriate for a TBAA root node. Each returned
/// node is distinct from all other metadata and will never be identified
/// (uniqued) with anything else.
- MDNode *createAnonymousTBAARoot();
+ MDNode *createAnonymousTBAARoot() {
+ return createAnonymousAARoot();
+ }
+
+ /// \brief Return metadata appropriate for an alias scope domain node.
+ /// Each returned node is distinct from all other metadata and will never
+ /// be identified (uniqued) with anything else.
+ MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) {
+ return createAnonymousAARoot(Name);
+ }
+
+ /// \brief Return metadata appropriate for an alias scope root node.
+ /// Each returned node is distinct from all other metadata and will never
+ /// be identified (uniqued) with anything else.
+ MDNode *createAnonymousAliasScope(MDNode *Domain,
+ StringRef Name = StringRef()) {
+ return createAnonymousAARoot(Name, Domain);
+ }
/// \brief Return metadata appropriate for a TBAA root node with the given
/// name. This may be identified (uniqued) with other roots with the same
/// name.
MDNode *createTBAARoot(StringRef Name);
+ /// \brief Return metadata appropriate for an alias scope domain node with
+ /// the given name. This may be identified (uniqued) with other roots with
+ /// the same name.
+ MDNode *createAliasScopeDomain(StringRef Name);
+
+ /// \brief Return metadata appropriate for an alias scope node with
+ /// the given name. This may be identified (uniqued) with other scopes with
+ /// the same name and domain.
+ MDNode *createAliasScope(StringRef Name, MDNode *Domain);
+
/// \brief Return metadata for a non-root TBAA node with the given name,
/// parent in the TBAA tree, and value for 'pointsToConstantMemory'.
MDNode *createTBAANode(StringRef Name, MDNode *Parent,
diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h
index c1ba5858a612..1e6b5b1dca00 100644
--- a/include/llvm/IR/Mangler.h
+++ b/include/llvm/IR/Mangler.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_MANGLER_H
-#define LLVM_TARGET_MANGLER_H
+#ifndef LLVM_IR_MANGLER_H
+#define LLVM_IR_MANGLER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/raw_ostream.h"
@@ -66,4 +66,4 @@ public:
} // End llvm namespace
-#endif // LLVM_TARGET_MANGLER_H
+#endif
diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def
new file mode 100644
index 000000000000..2098bb57eb56
--- /dev/null
+++ b/include/llvm/IR/Metadata.def
@@ -0,0 +1,59 @@
+//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through all types of metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \
+ defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \
+ defined HANDLE_UNIQUABLE_BRANCH)
+#error "Missing macro definition of HANDLE_METADATA*"
+#endif
+
+// Handler for all types of metadata.
+#ifndef HANDLE_METADATA
+#define HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_LEAF
+#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for non-leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_BRANCH
+#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_LEAF
+#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS)
+#endif
+
+// Handler for non-leaf nodes under UniquableMDNode.
+#ifndef HANDLE_UNIQUABLE_BRANCH
+#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS)
+#endif
+
+HANDLE_METADATA_LEAF(MDString)
+HANDLE_METADATA_BRANCH(ValueAsMetadata)
+HANDLE_METADATA_LEAF(ConstantAsMetadata)
+HANDLE_METADATA_LEAF(LocalAsMetadata)
+HANDLE_METADATA_BRANCH(MDNode)
+HANDLE_METADATA_LEAF(MDNodeFwdDecl)
+HANDLE_UNIQUABLE_BRANCH(UniquableMDNode)
+HANDLE_UNIQUABLE_LEAF(MDTuple)
+HANDLE_UNIQUABLE_LEAF(MDLocation)
+
+#undef HANDLE_METADATA
+#undef HANDLE_METADATA_LEAF
+#undef HANDLE_METADATA_BRANCH
+#undef HANDLE_UNIQUABLE_LEAF
+#undef HANDLE_UNIQUABLE_BRANCH
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 7a0ca887201b..3bf6d38d311d 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -17,10 +17,14 @@
#define LLVM_IR_METADATA_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/MetadataTracking.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <type_traits>
namespace llvm {
class LLVMContext;
@@ -30,169 +34,887 @@ template<typename ValueSubClass, typename ItemParentClass>
enum LLVMConstants : uint32_t {
- DEBUG_METADATA_VERSION = 1 // Current debug info version number.
+ DEBUG_METADATA_VERSION = 2 // Current debug info version number.
};
+/// \brief Root of the metadata hierarchy.
+///
+/// This is a root class for typeless data in the IR.
+class Metadata {
+ friend class ReplaceableMetadataImpl;
+
+ /// \brief RTTI.
+ const unsigned char SubclassID;
+
+protected:
+ /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
+ bool IsDistinctInContext : 1;
+ // TODO: expose remaining bits to subclasses.
+
+ unsigned short SubclassData16;
+ unsigned SubclassData32;
+
+public:
+ enum MetadataKind {
+ MDTupleKind,
+ MDLocationKind,
+ MDNodeFwdDeclKind,
+ ConstantAsMetadataKind,
+ LocalAsMetadataKind,
+ MDStringKind
+ };
+
+protected:
+ Metadata(unsigned ID)
+ : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
+ SubclassData32(0) {}
+ ~Metadata() {}
+
+ /// \brief Store this in a big non-uniqued untyped bucket.
+ bool isStoredDistinctInContext() const { return IsDistinctInContext; }
+
+ /// \brief Default handling of a changed operand, which asserts.
+ ///
+ /// If subclasses pass themselves in as owners to a tracking node reference,
+ /// they must provide an implementation of this method.
+ void handleChangedOperand(void *, Metadata *) {
+ llvm_unreachable("Unimplemented in Metadata subclass");
+ }
+
+public:
+ unsigned getMetadataID() const { return SubclassID; }
+
+ /// \brief User-friendly dump.
+ void dump() const;
+ void print(raw_ostream &OS) const;
+ void printAsOperand(raw_ostream &OS, bool PrintType = true,
+ const Module *M = nullptr) const;
+};
+
+#define HANDLE_METADATA(CLASS) class CLASS;
+#include "llvm/IR/Metadata.def"
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
+ MD.print(OS);
+ return OS;
+}
+
+/// \brief Metadata wrapper in the Value hierarchy.
+///
+/// A member of the \a Value hierarchy to represent a reference to metadata.
+/// This allows, e.g., instrinsics to have metadata as operands.
+///
+/// Notably, this is the only thing in either hierarchy that is allowed to
+/// reference \a LocalAsMetadata.
+class MetadataAsValue : public Value {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Metadata *MD;
+
+ MetadataAsValue(Type *Ty, Metadata *MD);
+ ~MetadataAsValue();
+
+ /// \brief Drop use of metadata (during teardown).
+ void dropUse() { MD = nullptr; }
+
+public:
+ static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
+ static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
+ Metadata *getMetadata() const { return MD; }
+
+ static bool classof(const Value *V) {
+ return V->getValueID() == MetadataAsValueVal;
+ }
+
+private:
+ void handleChangedMetadata(Metadata *MD);
+ void track();
+ void untrack();
+};
+
+/// \brief Shared implementation of use-lists for replaceable metadata.
+///
+/// Most metadata cannot be RAUW'ed. This is a shared implementation of
+/// use-lists and associated API for the two that support it (\a ValueAsMetadata
+/// and \a TempMDNode).
+class ReplaceableMetadataImpl {
+ friend class MetadataTracking;
+
+public:
+ typedef MetadataTracking::OwnerTy OwnerTy;
+
+private:
+ uint64_t NextIndex;
+ SmallDenseMap<void *, std::pair<OwnerTy, uint64_t>, 4> UseMap;
+
+public:
+ ReplaceableMetadataImpl() : NextIndex(0) {}
+ ~ReplaceableMetadataImpl() {
+ assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
+ }
+
+ /// \brief Replace all uses of this with MD.
+ ///
+ /// Replace all uses of this with \c MD, which is allowed to be null.
+ void replaceAllUsesWith(Metadata *MD);
+
+ /// \brief Resolve all uses of this.
+ ///
+ /// Resolve all uses of this, turning off RAUW permanently. If \c
+ /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last
+ /// operand is resolved.
+ void resolveAllUses(bool ResolveUsers = true);
+
+private:
+ void addRef(void *Ref, OwnerTy Owner);
+ void dropRef(void *Ref);
+ void moveRef(void *Ref, void *New, const Metadata &MD);
+
+ static ReplaceableMetadataImpl *get(Metadata &MD);
+};
+
+/// \brief Value wrapper in the Metadata hierarchy.
+///
+/// This is a custom value handle that allows other metadata to refer to
+/// classes in the Value hierarchy.
+///
+/// Because of full uniquing support, each value is only wrapped by a single \a
+/// ValueAsMetadata object, so the lookup maps are far more efficient than
+/// those using ValueHandleBase.
+class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Value *V;
+
+ /// \brief Drop users without RAUW (during teardown).
+ void dropUsers() {
+ ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false);
+ }
+
+protected:
+ ValueAsMetadata(unsigned ID, Value *V)
+ : Metadata(ID), V(V) {
+ assert(V && "Expected valid value");
+ }
+ ~ValueAsMetadata() {}
+
+public:
+ static ValueAsMetadata *get(Value *V);
+ static ConstantAsMetadata *getConstant(Value *C) {
+ return cast<ConstantAsMetadata>(get(C));
+ }
+ static LocalAsMetadata *getLocal(Value *Local) {
+ return cast<LocalAsMetadata>(get(Local));
+ }
+
+ static ValueAsMetadata *getIfExists(Value *V);
+ static ConstantAsMetadata *getConstantIfExists(Value *C) {
+ return cast_or_null<ConstantAsMetadata>(getIfExists(C));
+ }
+ static LocalAsMetadata *getLocalIfExists(Value *Local) {
+ return cast_or_null<LocalAsMetadata>(getIfExists(Local));
+ }
+
+ Value *getValue() const { return V; }
+ Type *getType() const { return V->getType(); }
+ LLVMContext &getContext() const { return V->getContext(); }
+
+ static void handleDeletion(Value *V);
+ static void handleRAUW(Value *From, Value *To);
+
+protected:
+ /// \brief Handle collisions after \a Value::replaceAllUsesWith().
+ ///
+ /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped
+ /// \a Value gets RAUW'ed and the target already exists, this is used to
+ /// merge the two metadata nodes.
+ void replaceAllUsesWith(Metadata *MD) {
+ ReplaceableMetadataImpl::replaceAllUsesWith(MD);
+ }
+
+public:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind ||
+ MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class ConstantAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ ConstantAsMetadata(Constant *C)
+ : ValueAsMetadata(ConstantAsMetadataKind, C) {}
+
+public:
+ static ConstantAsMetadata *get(Constant *C) {
+ return ValueAsMetadata::getConstant(C);
+ }
+ static ConstantAsMetadata *getIfExists(Constant *C) {
+ return ValueAsMetadata::getConstantIfExists(C);
+ }
+
+ Constant *getValue() const {
+ return cast<Constant>(ValueAsMetadata::getValue());
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class LocalAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ LocalAsMetadata(Value *Local)
+ : ValueAsMetadata(LocalAsMetadataKind, Local) {
+ assert(!isa<Constant>(Local) && "Expected local value");
+ }
+
+public:
+ static LocalAsMetadata *get(Value *Local) {
+ return ValueAsMetadata::getLocal(Local);
+ }
+ static LocalAsMetadata *getIfExists(Value *Local) {
+ return ValueAsMetadata::getLocalIfExists(Local);
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind;
+ }
+};
+
+/// \brief Transitional API for extracting constants from Metadata.
+///
+/// This namespace contains transitional functions for metadata that points to
+/// \a Constants.
+///
+/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode
+/// operands could refer to any \a Value. There's was a lot of code like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = dyn_cast<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining
+/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three
+/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and
+/// cast in the \a Value hierarchy. Besides creating boiler-plate, this
+/// requires subtle control flow changes.
+///
+/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt,
+/// so that metadata can refer to numbers without traversing a bridge to the \a
+/// Value hierarchy. In this final state, the code above would look like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *MI = dyn_cast<MDInt>(N->getOperand(2));
+/// \endcode
+///
+/// The API in this namespace supports the transition. \a MDInt doesn't exist
+/// yet, and even once it does, changing each metadata schema to use it is its
+/// own mini-project. In the meantime this API prevents us from introducing
+/// complex and bug-prone control flow that will disappear in the end. In
+/// particular, the above code looks like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// The full set of provided functions includes:
+///
+/// mdconst::hasa <=> isa
+/// mdconst::extract <=> cast
+/// mdconst::extract_or_null <=> cast_or_null
+/// mdconst::dyn_extract <=> dyn_cast
+/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null
+///
+/// The target of the cast must be a subclass of \a Constant.
+namespace mdconst {
+
+namespace detail {
+template <class T> T &make();
+template <class T, class Result> struct HasDereference {
+ typedef char Yes[1];
+ typedef char No[2];
+ template <size_t N> struct SFINAE {};
+
+ template <class U, class V>
+ static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0);
+ template <class U, class V> static No &hasDereference(...);
+
+ static const bool value =
+ sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes);
+};
+template <class V, class M> struct IsValidPointer {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ HasDereference<M, const Metadata &>::value;
+};
+template <class V, class M> struct IsValidReference {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ std::is_convertible<M, const Metadata &>::value;
+};
+} // end namespace detail
+
+/// \brief Check whether Metadata has a Value.
+///
+/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of
+/// type \c X.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type
+hasa(Y &&MD) {
+ assert(MD && "Null pointer sent into hasa");
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return isa<X>(V->getValue());
+ return false;
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type
+ hasa(Y &MD) {
+ return hasa(&MD);
+}
+
+/// \brief Extract a Value from Metadata.
+///
+/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract(Y &&MD) {
+ return cast<X>(cast<ConstantAsMetadata>(MD)->getValue());
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type
+ extract(Y &MD) {
+ return extract(&MD);
+}
+
+/// \brief Extract a Value from Metadata, allowing null.
+///
+/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract_or_null(Y &&MD) {
+ if (auto *V = cast_or_null<ConstantAsMetadata>(MD))
+ return cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract(Y &&MD) {
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any, allowing null.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract_or_null(Y &&MD) {
+ if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+} // end namespace mdconst
+
//===----------------------------------------------------------------------===//
-/// MDString - a single uniqued string.
+/// \brief A single uniqued string.
+///
/// These are used to efficiently contain a byte sequence for metadata.
/// MDString is always unnamed.
-class MDString : public Value {
- virtual void anchor();
+class MDString : public Metadata {
+ friend class StringMapEntry<MDString>;
+
MDString(const MDString &) LLVM_DELETED_FUNCTION;
+ MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION;
+ MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION;
+
+ StringMapEntry<MDString> *Entry;
+ MDString() : Metadata(MDStringKind), Entry(nullptr) {}
+ MDString(MDString &&) : Metadata(MDStringKind) {}
- explicit MDString(LLVMContext &C);
public:
static MDString *get(LLVMContext &Context, StringRef Str);
static MDString *get(LLVMContext &Context, const char *Str) {
return get(Context, Str ? StringRef(Str) : StringRef());
}
- StringRef getString() const { return getName(); }
+ StringRef getString() const;
- unsigned getLength() const { return (unsigned)getName().size(); }
+ unsigned getLength() const { return (unsigned)getString().size(); }
typedef StringRef::iterator iterator;
- /// begin() - Pointer to the first byte of the string.
- iterator begin() const { return getName().begin(); }
+ /// \brief Pointer to the first byte of the string.
+ iterator begin() const { return getString().begin(); }
- /// end() - Pointer to one byte past the end of the string.
- iterator end() const { return getName().end(); }
+ /// \brief Pointer to one byte past the end of the string.
+ iterator end() const { return getString().end(); }
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *V) {
- return V->getValueID() == MDStringVal;
+ const unsigned char *bytes_begin() const { return getString().bytes_begin(); }
+ const unsigned char *bytes_end() const { return getString().bytes_end(); }
+
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDStringKind;
}
};
+/// \brief A collection of metadata nodes that might be associated with a
+/// memory access used by the alias-analysis infrastructure.
+struct AAMDNodes {
+ explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr,
+ MDNode *N = nullptr)
+ : TBAA(T), Scope(S), NoAlias(N) {}
+
+ bool operator==(const AAMDNodes &A) const {
+ return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias;
+ }
+
+ bool operator!=(const AAMDNodes &A) const { return !(*this == A); }
+
+ LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; }
+
+ /// \brief The tag for type-based alias analysis.
+ MDNode *TBAA;
-class MDNodeOperand;
+ /// \brief The tag for alias scope specification (used with noalias).
+ MDNode *Scope;
+
+ /// \brief The tag specifying the noalias scope.
+ MDNode *NoAlias;
+};
+
+// Specialize DenseMapInfo for AAMDNodes.
+template<>
+struct DenseMapInfo<AAMDNodes> {
+ static inline AAMDNodes getEmptyKey() {
+ return AAMDNodes(DenseMapInfo<MDNode *>::getEmptyKey(), 0, 0);
+ }
+ static inline AAMDNodes getTombstoneKey() {
+ return AAMDNodes(DenseMapInfo<MDNode *>::getTombstoneKey(), 0, 0);
+ }
+ static unsigned getHashValue(const AAMDNodes &Val) {
+ return DenseMapInfo<MDNode *>::getHashValue(Val.TBAA) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.Scope) ^
+ DenseMapInfo<MDNode *>::getHashValue(Val.NoAlias);
+ }
+ static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) {
+ return LHS == RHS;
+ }
+};
+
+/// \brief Tracking metadata reference owned by Metadata.
+///
+/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance
+/// of \a Metadata, which has the option of registering itself for callbacks to
+/// re-unique itself.
+///
+/// In particular, this is used by \a MDNode.
+class MDOperand {
+ MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION;
+
+ Metadata *MD;
+
+public:
+ MDOperand() : MD(nullptr) {}
+ ~MDOperand() { untrack(); }
+
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD, Metadata *Owner) {
+ untrack();
+ this->MD = MD;
+ track(Owner);
+ }
+
+private:
+ void track(Metadata *Owner) {
+ if (MD) {
+ if (Owner)
+ MetadataTracking::track(this, *MD, *Owner);
+ else
+ MetadataTracking::track(MD);
+ }
+ }
+ void untrack() {
+ assert(static_cast<void *>(this) == &MD && "Expected same address");
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+};
+
+template <> struct simplify_type<MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
+};
//===----------------------------------------------------------------------===//
-/// MDNode - a tuple of other values.
-class MDNode : public Value, public FoldingSetNode {
+/// \brief Tuple of metadata.
+class MDNode : public Metadata {
MDNode(const MDNode &) LLVM_DELETED_FUNCTION;
void operator=(const MDNode &) LLVM_DELETED_FUNCTION;
- friend class MDNodeOperand;
- friend class LLVMContextImpl;
- friend struct FoldingSetTrait<MDNode>;
-
- /// Hash - If the MDNode is uniqued cache the hash to speed up lookup.
- unsigned Hash;
+ void *operator new(size_t) LLVM_DELETED_FUNCTION;
- /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the
- /// end of this MDNode.
+ LLVMContext &Context;
unsigned NumOperands;
- // Subclass data enums.
- enum {
- /// FunctionLocalBit - This bit is set if this MDNode is function local.
- /// This is true when it (potentially transitively) contains a reference to
- /// something in a function, like an argument, basicblock, or instruction.
- FunctionLocalBit = 1 << 0,
+protected:
+ unsigned MDNodeSubclassData;
- /// NotUniquedBit - This is set on MDNodes that are not uniqued because they
- /// have a null operand.
- NotUniquedBit = 1 << 1,
+ void *operator new(size_t Size, unsigned NumOps);
+ void operator delete(void *Mem);
- /// DestroyFlag - This bit is set by destroy() so the destructor can assert
- /// that the node isn't being destroyed with a plain 'delete'.
- DestroyFlag = 1 << 2
- };
+ /// \brief Required by std, but never called.
+ void operator delete(void *, unsigned) {
+ llvm_unreachable("Constructor throws?");
+ }
- // FunctionLocal enums.
- enum FunctionLocalness {
- FL_Unknown = -1,
- FL_No = 0,
- FL_Yes = 1
- };
+ /// \brief Required by std, but never called.
+ void operator delete(void *, unsigned, bool) {
+ llvm_unreachable("Constructor throws?");
+ }
- /// replaceOperand - Replace each instance of F from the operand list of this
- /// node with T.
- void replaceOperand(MDNodeOperand *Op, Value *NewVal);
- ~MDNode();
+ MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs);
+ ~MDNode() {}
- MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal);
+ void dropAllReferences();
+
+ MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
+ MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
- static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals,
- FunctionLocalness FL, bool Insert = true);
public:
- // Constructors and destructors.
- static MDNode *get(LLVMContext &Context, ArrayRef<Value*> Vals);
- // getWhenValsUnresolved - Construct MDNode determining function-localness
- // from isFunctionLocal argument, not by analyzing Vals.
- static MDNode *getWhenValsUnresolved(LLVMContext &Context,
- ArrayRef<Value*> Vals,
- bool isFunctionLocal);
-
- static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals);
-
- /// getTemporary - Return a temporary MDNode, for use in constructing
- /// cyclic MDNode structures. A temporary MDNode is not uniqued,
- /// may be RAUW'd, and must be manually deleted with deleteTemporary.
- static MDNode *getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals);
-
- /// deleteTemporary - Deallocate a node created by getTemporary. The
- /// node must not have any users.
+ static inline MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+ static inline MDNode *getIfExists(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+ static inline MDNode *getDistinct(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+
+ /// \brief Return a temporary MDNode
+ ///
+ /// For use in constructing cyclic MDNode structures. A temporary MDNode is
+ /// not uniqued, may be RAUW'd, and must be manually deleted with
+ /// deleteTemporary.
+ static MDNodeFwdDecl *getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
+
+ /// \brief Deallocate a node created by getTemporary.
+ ///
+ /// The node must not have any users.
static void deleteTemporary(MDNode *N);
- /// replaceOperandWith - Replace a specific operand.
- void replaceOperandWith(unsigned i, Value *NewVal);
+ LLVMContext &getContext() const { return Context; }
- /// getOperand - Return specified operand.
- Value *getOperand(unsigned i) const LLVM_READONLY;
+ /// \brief Replace a specific operand.
+ void replaceOperandWith(unsigned I, Metadata *New);
- /// getNumOperands - Return number of MDNode operands.
- unsigned getNumOperands() const { return NumOperands; }
+ /// \brief Check if node is fully resolved.
+ bool isResolved() const;
- /// isFunctionLocal - Return whether MDNode is local to a function.
- bool isFunctionLocal() const {
- return (getSubclassDataFromValue() & FunctionLocalBit) != 0;
+ /// \brief Check if node is distinct.
+ ///
+ /// Distinct nodes are not uniqued, and will not be returned by \a
+ /// MDNode::get().
+ bool isDistinct() const {
+ return isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this);
}
- // getFunction - If this metadata is function-local and recursively has a
- // function-local operand, return the first such operand's parent function.
- // Otherwise, return null. getFunction() should not be used for performance-
- // critical code because it recursively visits all the MDNode's operands.
- const Function *getFunction() const;
+protected:
+ /// \brief Set an operand.
+ ///
+ /// Sets the operand directly, without worrying about uniquing.
+ void setOperand(unsigned I, Metadata *New);
- /// Profile - calculate a unique identifier for this MDNode to collapse
- /// duplicates
- void Profile(FoldingSetNodeID &ID) const;
+public:
+ typedef const MDOperand *op_iterator;
+ typedef iterator_range<op_iterator> op_range;
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *V) {
- return V->getValueID() == MDNodeVal;
+ op_iterator op_begin() const {
+ return const_cast<MDNode *>(this)->mutable_begin();
+ }
+ op_iterator op_end() const {
+ return const_cast<MDNode *>(this)->mutable_end();
+ }
+ op_range operands() const { return op_range(op_begin(), op_end()); }
+
+ const MDOperand &getOperand(unsigned I) const {
+ assert(I < NumOperands && "Out of range");
+ return op_begin()[I];
+ }
+
+ /// \brief Return number of MDNode operands.
+ unsigned getNumOperands() const { return NumOperands; }
+
+ /// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind ||
+ MD->getMetadataID() == MDNodeFwdDeclKind;
}
- /// Check whether MDNode is a vtable access.
+ /// \brief Check whether MDNode is a vtable access.
bool isTBAAVtableAccess() const;
- /// Methods for metadata merging.
+ /// \brief Methods for metadata merging.
+ static MDNode *concatenate(MDNode *A, MDNode *B);
+ static MDNode *intersect(MDNode *A, MDNode *B);
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
+ static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B);
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
+};
+
+/// \brief Uniquable metadata node.
+///
+/// A uniquable metadata node. This contains the basic functionality
+/// for implementing sub-types of \a MDNode that can be uniqued like
+/// constants.
+///
+/// There is limited support for RAUW at construction time. At
+/// construction time, if any operands are an instance of \a
+/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which
+/// indicates an \a MDNodeFwdDecl in its path), the node itself will be
+/// unresolved. As soon as all operands become resolved, it will drop
+/// RAUW support permanently.
+///
+/// If an unresolved node is part of a cycle, \a resolveCycles() needs
+/// to be called on some member of the cycle when each \a MDNodeFwdDecl
+/// has been removed.
+class UniquableMDNode : public MDNode {
+ friend class ReplaceableMetadataImpl;
+ friend class MDNode;
+ friend class LLVMContextImpl;
+
+ /// \brief Support RAUW as long as one of its arguments is replaceable.
+ ///
+ /// FIXME: Save memory by storing this in a pointer union with the
+ /// LLVMContext, and adding an LLVMContext reference to RMI.
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
+
+protected:
+ /// \brief Create a new node.
+ ///
+ /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW
+ /// will be dropped once all operands have been resolved (or if \a
+ /// resolveCycles() is called).
+ UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef<Metadata *> Vals,
+ bool AllowRAUW);
+ ~UniquableMDNode() {}
+
+ void storeDistinctInContext();
+
+public:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind ||
+ MD->getMetadataID() == MDLocationKind;
+ }
+
+ /// \brief Check whether any operands are forward declarations.
+ ///
+ /// Returns \c true as long as any operands (or their operands, etc.) are \a
+ /// MDNodeFwdDecl.
+ ///
+ /// As forward declarations are resolved, their containers should get
+ /// resolved automatically. However, if this (or one of its operands) is
+ /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
+ bool isResolved() const { return !ReplaceableUses; }
+
+ /// \brief Resolve cycles.
+ ///
+ /// Once all forward declarations have been resolved, force cycles to be
+ /// resolved.
+ ///
+ /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl.
+ void resolveCycles();
+
+private:
+ void handleChangedOperand(void *Ref, Metadata *New);
+
+ void resolve();
+ void resolveAfterOperandChange(Metadata *Old, Metadata *New);
+ void decrementUnresolvedOperandCount();
+
+ void deleteAsSubclass();
+ UniquableMDNode *uniquify();
+ void eraseFromStore();
+};
+
+/// \brief Tuple of metadata.
+///
+/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by
+/// default based on their operands.
+class MDTuple : public UniquableMDNode {
+ friend class LLVMContextImpl;
+ friend class UniquableMDNode;
+
+ MDTuple(LLVMContext &C, ArrayRef<Metadata *> Vals, bool AllowRAUW)
+ : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {}
+ ~MDTuple() { dropAllReferences(); }
+
+ void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
+ void recalculateHash();
+
+ static MDTuple *getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ bool ShouldCreate);
+
+public:
+ /// \brief Get the hash, if any.
+ unsigned getHash() const { return MDNodeSubclassData; }
+
+ static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getImpl(Context, MDs, /* ShouldCreate */ true);
+ }
+ static MDTuple *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getImpl(Context, MDs, /* ShouldCreate */ false);
+ }
+
+ /// \brief Return a distinct node.
+ ///
+ /// Return a distinct node -- i.e., a node that is not uniqued.
+ static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs);
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDTupleKind;
+ }
+
+private:
+ MDTuple *uniquifyImpl();
+ void eraseFromStoreImpl();
+};
+
+MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::get(Context, MDs);
+}
+MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getIfExists(Context, MDs);
+}
+MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return MDTuple::getDistinct(Context, MDs);
+}
+
+/// \brief Debug location.
+///
+/// A debug location in source code, used for debug info and otherwise.
+class MDLocation : public UniquableMDNode {
+ friend class LLVMContextImpl;
+ friend class UniquableMDNode;
+
+ MDLocation(LLVMContext &C, unsigned Line, unsigned Column,
+ ArrayRef<Metadata *> MDs, bool AllowRAUW);
+ ~MDLocation() { dropAllReferences(); }
+
+ static MDLocation *constructHelper(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool AllowRAUW);
+
+ static MDLocation *getImpl(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt, bool ShouldCreate);
+
+ // Disallow replacing operands.
+ void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION;
+
+public:
+ static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column,
+ Metadata *Scope, Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ true);
+ }
+ static MDLocation *getIfExists(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr) {
+ return getImpl(Context, Line, Column, Scope, InlinedAt,
+ /* ShouldCreate */ false);
+ }
+ static MDLocation *getDistinct(LLVMContext &Context, unsigned Line,
+ unsigned Column, Metadata *Scope,
+ Metadata *InlinedAt = nullptr);
+
+ unsigned getLine() const { return MDNodeSubclassData; }
+ unsigned getColumn() const { return SubclassData16; }
+ Metadata *getScope() const { return getOperand(0); }
+ Metadata *getInlinedAt() const {
+ if (getNumOperands() == 2)
+ return getOperand(1);
+ return nullptr;
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDLocationKind;
+ }
+
private:
- // destroy - Delete this node. Only when there are no uses.
- void destroy();
+ MDLocation *uniquifyImpl();
+ void eraseFromStoreImpl();
+};
+
+/// \brief Forward declaration of metadata.
+///
+/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a
+/// MDTuple, this class has full support for RAUW, is not owned, is not
+/// uniqued, and is suitable for forward references.
+class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl {
+ friend class Metadata;
+ friend class ReplaceableMetadataImpl;
+
+ MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals)
+ : MDNode(C, MDNodeFwdDeclKind, Vals) {}
+
+public:
+ ~MDNodeFwdDecl() { dropAllReferences(); }
+
+ // MSVC doesn't see the alternative: "using MDNode::operator delete".
+ void operator delete(void *Mem) { MDNode::operator delete(Mem); }
- bool isNotUniqued() const {
- return (getSubclassDataFromValue() & NotUniquedBit) != 0;
+ static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return new (MDs.size()) MDNodeFwdDecl(Context, MDs);
}
- void setIsNotUniqued();
- // Shadow Value::setValueSubclassData with a private forwarding method so that
- // any future subclasses cannot accidentally use it.
- void setValueSubclassData(unsigned short D) {
- Value::setValueSubclassData(D);
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDNodeFwdDeclKind;
}
+
+ using ReplaceableMetadataImpl::replaceAllUsesWith;
};
//===----------------------------------------------------------------------===//
-/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't
-/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain
-/// lists of MDNodes.
+/// \brief A tuple of MDNodes.
+///
+/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong
+/// to modules, have names, and contain lists of MDNodes.
+///
+/// TODO: Inherit from Metadata.
class NamedMDNode : public ilist_node<NamedMDNode> {
friend class SymbolTableListTraits<NamedMDNode, Module>;
friend struct ilist_traits<NamedMDNode>;
@@ -202,7 +924,7 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
std::string Name;
Module *Parent;
- void *Operands; // SmallVector<TrackingVH<MDNode>, 4>
+ void *Operands; // SmallVector<TrackingMDRef, 4>
void setParent(Module *M) { Parent = M; }
@@ -245,46 +967,34 @@ class NamedMDNode : public ilist_node<NamedMDNode> {
};
public:
- /// eraseFromParent - Drop all references and remove the node from parent
- /// module.
+ /// \brief Drop all references and remove the node from parent module.
void eraseFromParent();
- /// dropAllReferences - Remove all uses and clear node vector.
+ /// \brief Remove all uses and clear node vector.
void dropAllReferences();
- /// ~NamedMDNode - Destroy NamedMDNode.
~NamedMDNode();
- /// getParent - Get the module that holds this named metadata collection.
+ /// \brief Get the module that holds this named metadata collection.
inline Module *getParent() { return Parent; }
inline const Module *getParent() const { return Parent; }
- /// getOperand - Return specified operand.
MDNode *getOperand(unsigned i) const;
-
- /// getNumOperands - Return the number of NamedMDNode operands.
unsigned getNumOperands() const;
-
- /// addOperand - Add metadata operand.
void addOperand(MDNode *M);
-
- /// getName - Return a constant reference to this named metadata's name.
+ void setOperand(unsigned I, MDNode *New);
StringRef getName() const;
-
- /// print - Implement operator<< on NamedMDNode.
void print(raw_ostream &ROS) const;
-
- /// dump() - Allow printing of NamedMDNodes from the debugger.
void dump() const;
// ---------------------------------------------------------------------------
// Operand Iterator interface...
//
- typedef op_iterator_impl<MDNode*, MDNode> op_iterator;
+ typedef op_iterator_impl<MDNode *, MDNode> op_iterator;
op_iterator op_begin() { return op_iterator(this, 0); }
op_iterator op_end() { return op_iterator(this, getNumOperands()); }
- typedef op_iterator_impl<const MDNode*, MDNode> const_op_iterator;
+ typedef op_iterator_impl<const MDNode *, MDNode> const_op_iterator;
const_op_iterator op_begin() const { return const_op_iterator(this, 0); }
const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); }
diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h
new file mode 100644
index 000000000000..541d9b3b1245
--- /dev/null
+++ b/include/llvm/IR/MetadataTracking.h
@@ -0,0 +1,99 @@
+//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Low-level functions to enable tracking of metadata that could RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_METADATATRACKING_H
+#define LLVM_IR_METADATATRACKING_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Casting.h"
+#include <type_traits>
+
+namespace llvm {
+
+class Metadata;
+class MetadataAsValue;
+
+/// \brief API for tracking metadata references through RAUW and deletion.
+///
+/// Shared API for updating \a Metadata pointers in subclasses that support
+/// RAUW.
+///
+/// This API is not meant to be used directly. See \a TrackingMDRef for a
+/// user-friendly tracking reference.
+class MetadataTracking {
+public:
+ /// \brief Track the reference to metadata.
+ ///
+ /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD
+ /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets
+ /// deleted, \c MD will be set to \c nullptr.
+ ///
+ /// If tracking isn't supported, \c *MD will not change.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool track(Metadata *&MD) {
+ return track(&MD, *MD, static_cast<Metadata *>(nullptr));
+ }
+
+ /// \brief Track the reference to metadata for \a Metadata.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, Metadata &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Track the reference to metadata for \a MetadataAsValue.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Stop tracking a reference to metadata.
+ ///
+ /// Stops \c *MD from tracking \c MD.
+ static void untrack(Metadata *&MD) { untrack(&MD, *MD); }
+ static void untrack(void *Ref, Metadata &MD);
+
+ /// \brief Move tracking from one reference to another.
+ ///
+ /// Semantically equivalent to \c untrack(MD) followed by \c track(New),
+ /// except that ownership callbacks are maintained.
+ ///
+ /// Note: it is an error if \c *MD does not equal \c New.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool retrack(Metadata *&MD, Metadata *&New) {
+ return retrack(&MD, *MD, &New);
+ }
+ static bool retrack(void *Ref, Metadata &MD, void *New);
+
+ /// \brief Check whether metadata is replaceable.
+ static bool isReplaceable(const Metadata &MD);
+
+ typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy;
+
+private:
+ /// \brief Track a reference to metadata for an owner.
+ ///
+ /// Generalized version of tracking.
+ static bool track(void *Ref, Metadata &MD, OwnerTy Owner);
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 26f62db9db53..b24023b05e4f 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -23,6 +23,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/CodeGen.h"
#include "llvm/Support/DataTypes.h"
#include <system_error>
@@ -32,8 +33,6 @@ class GVMaterializer;
class LLVMContext;
class RandomNumberGenerator;
class StructType;
-template<typename T> struct DenseMapInfo;
-template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap;
template<> struct ilist_traits<Function>
: public SymbolTableListTraits<Function, Module> {
@@ -137,6 +136,11 @@ public:
/// The Function constant iterator
typedef FunctionListType::const_iterator const_iterator;
+ /// The Function reverse iterator.
+ typedef FunctionListType::reverse_iterator reverse_iterator;
+ /// The Function constant reverse iterator.
+ typedef FunctionListType::const_reverse_iterator const_reverse_iterator;
+
/// The Global Alias iterators.
typedef AliasListType::iterator alias_iterator;
/// The Global Alias constant iterator
@@ -144,7 +148,7 @@ public:
/// The named metadata iterators.
typedef NamedMDListType::iterator named_metadata_iterator;
- /// The named metadata constant interators.
+ /// The named metadata constant iterators.
typedef NamedMDListType::const_iterator const_named_metadata_iterator;
/// This enumeration defines the supported behaviors of module flags.
@@ -177,15 +181,23 @@ public:
/// Appends the two values, which are required to be metadata
/// nodes. However, duplicate entries in the second list are dropped
/// during the append operation.
- AppendUnique = 6
+ AppendUnique = 6,
+
+ // Markers:
+ ModFlagBehaviorFirstVal = Error,
+ ModFlagBehaviorLastVal = AppendUnique
};
+ /// Checks if Metadata represents a valid ModFlagBehavior, and stores the
+ /// converted result in MFB.
+ static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB);
+
struct ModuleFlagEntry {
ModFlagBehavior Behavior;
MDString *Key;
- Value *Val;
- ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V)
- : Behavior(B), Key(K), Val(V) {}
+ Metadata *Val;
+ ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V)
+ : Behavior(B), Key(K), Val(V) {}
};
/// @}
@@ -205,9 +217,8 @@ private:
Materializer; ///< Used to materialize GlobalValues
std::string ModuleID; ///< Human readable identifier for the module
std::string TargetTriple; ///< Platform target triple Module compiled on
+ ///< Format: (arch)(sub)-(vendor)-(sys0-(abi)
void *NamedMDSymTab; ///< NamedMDNode names.
- // Allow lazy initialization in const method.
- mutable RandomNumberGenerator *RNG; ///< The random number generator for this module.
// We need to keep the string because the C API expects us to own the string
// representation.
@@ -237,6 +248,12 @@ public:
/// @returns the module identifier as a string
const std::string &getModuleIdentifier() const { return ModuleID; }
+ /// \brief Get a short "name" for the module.
+ ///
+ /// This is useful for debugging or logging. It is essentially a convenience
+ /// wrapper around getModuleIdentifier().
+ StringRef getName() const { return ModuleID; }
+
/// Get the data layout string for the module's target platform. This is
/// equivalent to getDataLayout()->getStringRepresentation().
const std::string &getDataLayoutStr() const { return DataLayoutStr; }
@@ -256,10 +273,16 @@ public:
/// @returns a string containing the module-scope inline assembly blocks.
const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; }
- /// Get the RandomNumberGenerator for this module. The RNG can be
- /// seeded via -rng-seed=<uint64> and is salted with the ModuleID.
- /// The returned RNG should not be shared across threads.
- RandomNumberGenerator &getRNG() const;
+ /// Get a RandomNumberGenerator salted for use with this module. The
+ /// RNG can be seeded via -rng-seed=<uint64> and is salted with the
+ /// ModuleID and the provided pass salt. The returned RNG should not
+ /// be shared across threads or passes.
+ ///
+ /// A unique RNG per pass ensures a reproducible random stream even
+ /// when other randomness consuming passes are added or removed. In
+ /// addition, the random stream will be reproducible across LLVM
+ /// versions when the pass does not change.
+ RandomNumberGenerator *createRNG(const Pass* P) const;
/// @}
/// @name Module Level Mutators
@@ -313,6 +336,8 @@ public:
/// name.
StructType *getTypeByName(StringRef Name) const;
+ std::vector<StructType *> getIdentifiedStructTypes() const;
+
/// @}
/// @name Function Accessors
/// @{
@@ -339,11 +364,11 @@ public:
/// function arguments, which makes it easier for clients to use.
Constant *getOrInsertFunction(StringRef Name,
AttributeSet AttributeList,
- Type *RetTy, ...) END_WITH_NULL;
+ Type *RetTy, ...) LLVM_END_WITH_NULL;
/// Same as above, but without the attributes.
Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...)
- END_WITH_NULL;
+ LLVM_END_WITH_NULL;
/// Look up the specified function in the module symbol table. If it does not
/// exist, return null.
@@ -357,8 +382,11 @@ public:
/// does not exist, return null. If AllowInternal is set to true, this
/// function will return types that have InternalLinkage. By default, these
/// types are not returned.
- const GlobalVariable *getGlobalVariable(StringRef Name,
- bool AllowInternal = false) const {
+ GlobalVariable *getGlobalVariable(StringRef Name) const {
+ return getGlobalVariable(Name, false);
+ }
+
+ GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const {
return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal);
}
@@ -424,7 +452,7 @@ public:
/// Return the corresponding value if Key appears in module flags, otherwise
/// return null.
- Value *getModuleFlag(StringRef Key) const;
+ Metadata *getModuleFlag(StringRef Key) const;
/// Returns the NamedMDNode in the module that represents module-level flags.
/// This method returns null if there are no module-level flags.
@@ -437,7 +465,8 @@ public:
/// Add a module-level flag to the module-level flags metadata. It will create
/// the module-level flags named metadata if it doesn't already exist.
- void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val);
void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val);
void addModuleFlag(MDNode *Node);
@@ -456,9 +485,6 @@ public:
/// Retrieves the GVMaterializer, if any, for this Module.
GVMaterializer *getMaterializer() const { return Materializer.get(); }
- /// True if the definition of GV has yet to be materializedfrom the
- /// GVMaterializer.
- bool isMaterializable(const GlobalValue *GV) const;
/// Returns true if this GV was loaded from this Module's GVMaterializer and
/// the GVMaterializer knows how to dematerialize the GV.
bool isDematerializable(const GlobalValue *GV) const;
@@ -466,10 +492,10 @@ public:
/// Make sure the GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
- bool Materialize(GlobalValue *GV, std::string *ErrInfo = nullptr);
+ std::error_code materialize(GlobalValue *GV);
/// If the GlobalValue is read in, and if the GVMaterializer supports it,
/// release the memory for the function, and set it up to be materialized
- /// lazily. If !isDematerializable(), this method is a noop.
+ /// lazily. If !isDematerializable(), this method is a no-op.
void Dematerialize(GlobalValue *GV);
/// Make sure all GlobalValues in this Module are fully read.
@@ -478,7 +504,7 @@ public:
/// Make sure all GlobalValues in this Module are fully read and clear the
/// Materializer. If the module is corrupt, this DOES NOT clear the old
/// Materializer.
- std::error_code materializeAllPermanently(bool ReleaseBuffer = false);
+ std::error_code materializeAllPermanently();
/// @}
/// @name Direct access to the globals list, functions list, and symbol table
@@ -546,9 +572,20 @@ public:
const_iterator begin() const { return FunctionList.begin(); }
iterator end () { return FunctionList.end(); }
const_iterator end () const { return FunctionList.end(); }
+ reverse_iterator rbegin() { return FunctionList.rbegin(); }
+ const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); }
+ reverse_iterator rend() { return FunctionList.rend(); }
+ const_reverse_iterator rend() const { return FunctionList.rend(); }
size_t size() const { return FunctionList.size(); }
bool empty() const { return FunctionList.empty(); }
+ iterator_range<iterator> functions() {
+ return iterator_range<iterator>(begin(), end());
+ }
+ iterator_range<const_iterator> functions() const {
+ return iterator_range<const_iterator>(begin(), end());
+ }
+
/// @}
/// @name Alias Iteration
/// @{
@@ -620,6 +657,15 @@ public:
unsigned getDwarfVersion() const;
/// @}
+/// @name Utility functions for querying and setting PIC level
+/// @{
+
+ /// \brief Returns the PIC level (small or large model)
+ PICLevel::Level getPICLevel() const;
+
+ /// \brief Set the PIC level (small or large model)
+ void setPICLevel(PICLevel::Level PL);
+/// @}
};
/// An raw_ostream inserter for modules.
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 888cabffe378..0933f2170236 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -28,9 +28,8 @@ class GetElementPtrInst;
class BinaryOperator;
class ConstantExpr;
-/// Operator - This is a utility class that provides an abstraction for the
-/// common functionality between Instructions and ConstantExprs.
-///
+/// This is a utility class that provides an abstraction for the common
+/// functionality between Instructions and ConstantExprs.
class Operator : public User {
private:
// The Operator class is intended to be used as a utility, and is never itself
@@ -46,17 +45,15 @@ protected:
~Operator();
public:
- /// getOpcode - Return the opcode for this Instruction or ConstantExpr.
- ///
+ /// Return the opcode for this Instruction or ConstantExpr.
unsigned getOpcode() const {
if (const Instruction *I = dyn_cast<Instruction>(this))
return I->getOpcode();
return cast<ConstantExpr>(this)->getOpcode();
}
- /// getOpcode - If V is an Instruction or ConstantExpr, return its
- /// opcode. Otherwise return UserOp1.
- ///
+ /// If V is an Instruction or ConstantExpr, return its opcode.
+ /// Otherwise return UserOp1.
static unsigned getOpcode(const Value *V) {
if (const Instruction *I = dyn_cast<Instruction>(V))
return I->getOpcode();
@@ -72,10 +69,9 @@ public:
}
};
-/// OverflowingBinaryOperator - Utility class for integer arithmetic operators
-/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv,
-/// despite that operator having the potential for overflow.
-///
+/// Utility class for integer arithmetic operators which may exhibit overflow -
+/// Add, Sub, and Mul. It does not include SDiv, despite that operator having
+/// the potential for overflow.
class OverflowingBinaryOperator : public Operator {
public:
enum {
@@ -96,13 +92,13 @@ private:
}
public:
- /// hasNoUnsignedWrap - Test whether this operation is known to never
+ /// Test whether this operation is known to never
/// undergo unsigned overflow, aka the nuw property.
bool hasNoUnsignedWrap() const {
return SubclassOptionalData & NoUnsignedWrap;
}
- /// hasNoSignedWrap - Test whether this operation is known to never
+ /// Test whether this operation is known to never
/// undergo signed overflow, aka the nsw property.
bool hasNoSignedWrap() const {
return (SubclassOptionalData & NoSignedWrap) != 0;
@@ -126,8 +122,8 @@ public:
}
};
-/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as
-/// "exact", indicating that no bits are destroyed.
+/// A udiv or sdiv instruction, which can be marked as "exact",
+/// indicating that no bits are destroyed.
class PossiblyExactOperator : public Operator {
public:
enum {
@@ -142,8 +138,7 @@ private:
}
public:
- /// isExact - Test whether this division is known to be exact, with
- /// zero remainder.
+ /// Test whether this division is known to be exact, with zero remainder.
bool isExact() const {
return SubclassOptionalData & IsExact;
}
@@ -217,7 +212,7 @@ public:
};
-/// FPMathOperator - Utility class for floating point operations which can have
+/// Utility class for floating point operations which can have
/// information about relaxed accuracy requirements attached to them.
class FPMathOperator : public Operator {
private:
@@ -257,11 +252,18 @@ private:
(B * FastMathFlags::AllowReciprocal);
}
- /// Convenience function for setting all the fast-math flags
+ /// Convenience function for setting multiple fast-math flags.
+ /// FMF is a mask of the bits to set.
void setFastMathFlags(FastMathFlags FMF) {
SubclassOptionalData |= FMF.Flags;
}
+ /// Convenience function for copying all fast-math flags.
+ /// All values in FMF are transferred to this operator.
+ void copyFastMathFlags(FastMathFlags FMF) {
+ SubclassOptionalData = FMF.Flags;
+ }
+
public:
/// Test whether this operation is permitted to be
/// algebraically transformed, aka the 'A' fast-math property.
@@ -312,8 +314,7 @@ public:
};
-/// ConcreteOperator - A helper template for defining operators for individual
-/// opcodes.
+/// A helper template for defining operators for individual opcodes.
template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass {
public:
@@ -357,6 +358,8 @@ class LShrOperator
};
+class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {};
+
class GEPOperator
: public ConcreteOperator<Operator, Instruction::GetElementPtr> {
@@ -372,8 +375,7 @@ class GEPOperator
}
public:
- /// isInBounds - Test whether this is an inbounds GEP, as defined
- /// by LangRef.html.
+ /// Test whether this is an inbounds GEP, as defined by LangRef.html.
bool isInBounds() const {
return SubclassOptionalData & IsInBounds;
}
@@ -393,16 +395,14 @@ public:
return 0U; // get index for modifying correct operand
}
- /// getPointerOperandType - Method to return the pointer operand as a
- /// PointerType.
+ /// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const {
return getPointerOperand()->getType();
}
- /// getPointerAddressSpace - Method to return the address space of the
- /// pointer operand.
+ /// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
- return cast<PointerType>(getPointerOperandType())->getAddressSpace();
+ return getPointerOperandType()->getPointerAddressSpace();
}
unsigned getNumIndices() const { // Note: always non-negative
@@ -413,8 +413,8 @@ public:
return getNumOperands() > 1;
}
- /// hasAllZeroIndices - Return true if all of the indices of this GEP are
- /// zeros. If so, the result pointer and the first operand have the same
+ /// Return true if all of the indices of this GEP are zeros.
+ /// If so, the result pointer and the first operand have the same
/// value, just potentially different types.
bool hasAllZeroIndices() const {
for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
@@ -426,8 +426,8 @@ public:
return true;
}
- /// hasAllConstantIndices - Return true if all of the indices of this GEP are
- /// constant integers. If so, the result pointer and the first operand have
+ /// Return true if all of the indices of this GEP are constant integers.
+ /// If so, the result pointer and the first operand have
/// a constant offset between them.
bool hasAllConstantIndices() const {
for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) {
@@ -493,14 +493,12 @@ public:
return 0U; // get index for modifying correct operand
}
- /// getPointerOperandType - Method to return the pointer operand as a
- /// PointerType.
+ /// Method to return the pointer operand as a PointerType.
Type *getPointerOperandType() const {
return getPointerOperand()->getType();
}
- /// getPointerAddressSpace - Method to return the address space of the
- /// pointer operand.
+ /// Method to return the address space of the pointer operand.
unsigned getPointerAddressSpace() const {
return cast<PointerType>(getPointerOperandType())->getAddressSpace();
}
diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h
index cc2a80b9ff7d..262576849264 100644
--- a/include/llvm/IR/PassManager.h
+++ b/include/llvm/IR/PassManager.h
@@ -35,14 +35,17 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_PASS_MANAGER_H
-#define LLVM_IR_PASS_MANAGER_H
+#ifndef LLVM_IR_PASSMANAGER_H
+#define LLVM_IR_PASSMANAGER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManagerInternal.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/type_traits.h"
#include <list>
#include <memory>
@@ -91,9 +94,12 @@ public:
}
/// \brief Mark a particular pass as preserved, adding it to the set.
- template <typename PassT> void preserve() {
+ template <typename PassT> void preserve() { preserve(PassT::ID()); }
+
+ /// \brief Mark an abstract PassID as preserved, adding it to the set.
+ void preserve(void *PassID) {
if (!areAllPreserved())
- PreservedPassIDs.insert(PassT::ID());
+ PreservedPassIDs.insert(PassID);
}
/// \brief Intersect this set with another in place.
@@ -107,11 +113,9 @@ public:
PreservedPassIDs = Arg.PreservedPassIDs;
return;
}
- for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
- E = PreservedPassIDs.end();
- I != E; ++I)
- if (!Arg.PreservedPassIDs.count(*I))
- PreservedPassIDs.erase(*I);
+ for (void *P : PreservedPassIDs)
+ if (!Arg.PreservedPassIDs.count(P))
+ PreservedPassIDs.erase(P);
}
/// \brief Intersect this set with a temporary other set in place.
@@ -125,11 +129,9 @@ public:
PreservedPassIDs = std::move(Arg.PreservedPassIDs);
return;
}
- for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
- E = PreservedPassIDs.end();
- I != E; ++I)
- if (!Arg.PreservedPassIDs.count(*I))
- PreservedPassIDs.erase(*I);
+ for (void *P : PreservedPassIDs)
+ if (!Arg.PreservedPassIDs.count(P))
+ PreservedPassIDs.erase(P);
}
/// \brief Query whether a pass is marked as preserved by this set.
@@ -144,408 +146,115 @@ public:
PreservedPassIDs.count(PassID);
}
+ /// \brief Test whether all passes are preserved.
+ ///
+ /// This is used primarily to optimize for the case of no changes which will
+ /// common in many scenarios.
+ bool areAllPreserved() const {
+ return PreservedPassIDs.count((void *)AllPassesID);
+ }
+
private:
// Note that this must not be -1 or -2 as those are already used by the
// SmallPtrSet.
static const uintptr_t AllPassesID = (intptr_t)(-3);
- bool areAllPreserved() const {
- return PreservedPassIDs.count((void *)AllPassesID);
- }
-
SmallPtrSet<void *, 2> PreservedPassIDs;
};
-/// \brief Implementation details of the pass manager interfaces.
-namespace detail {
-
-/// \brief Template for the abstract base class used to dispatch
-/// polymorphically over pass objects.
-template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept {
- // Boiler plate necessary for the container of derived classes.
- virtual ~PassConcept() {}
-
- /// \brief The polymorphic API which runs the pass over a given IR entity.
- ///
- /// Note that actual pass object can omit the analysis manager argument if
- /// desired. Also that the analysis manager may be null if there is no
- /// analysis manager in the pass pipeline.
- virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0;
-
- /// \brief Polymorphic method to access the name of a pass.
- virtual StringRef name() = 0;
-};
-
-/// \brief SFINAE metafunction for computing whether \c PassT has a run method
-/// accepting an \c AnalysisManagerT.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- typename ResultT>
-class PassRunAcceptsAnalysisManager {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::run> *);
- template <typename T> static BigType f(...);
+// Forward declare the analysis manager template.
+template <typename IRUnitT> class AnalysisManager;
-public:
- enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
-};
-
-/// \brief A template wrapper used to implement the polymorphic API.
+/// \brief Manages a sequence of passes over units of IR.
///
-/// Can be instantiated for any object which provides a \c run method accepting
-/// an \c IRUnitT. It requires the pass to be a copyable object. When the
-/// \c run method also accepts an \c AnalysisManagerT*, we pass it along.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value>
-struct PassModel;
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
- PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(PassModel &LHS, PassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- PassModel &operator=(PassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
- return Pass.run(IR, AM);
- }
- StringRef name() override { return PassT::name(); }
- PassT Pass;
-};
-
-/// \brief Specialization of \c PassModel for passes that accept an analyis
-/// manager.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct PassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : PassConcept<IRUnitT, AnalysisManagerT> {
- explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
- PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(PassModel &LHS, PassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- PassModel &operator=(PassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override {
- return Pass.run(IR);
- }
- StringRef name() override { return PassT::name(); }
- PassT Pass;
-};
-
-/// \brief Abstract concept of an analysis result.
+/// A pass manager contains a sequence of passes to run over units of IR. It is
+/// itself a valid pass over that unit of IR, and when over some given IR will
+/// run each pass in sequence. This is the primary and most basic building
+/// block of a pass pipeline.
///
-/// This concept is parameterized over the IR unit that this result pertains
-/// to.
-template <typename IRUnitT> struct AnalysisResultConcept {
- virtual ~AnalysisResultConcept() {}
-
- /// \brief Method to try and mark a result as invalid.
- ///
- /// When the outer analysis manager detects a change in some underlying
- /// unit of the IR, it will call this method on all of the results cached.
- ///
- /// This method also receives a set of preserved analyses which can be used
- /// to avoid invalidation because the pass which changed the underlying IR
- /// took care to update or preserve the analysis result in some way.
- ///
- /// \returns true if the result is indeed invalid (the default).
- virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0;
-};
-
-/// \brief SFINAE metafunction for computing whether \c ResultT provides an
-/// \c invalidate member function.
-template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
- typedef char SmallType;
- struct BigType {
- char a, b;
- };
-
- template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)>
- struct Checker;
-
- template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
- template <typename T> static BigType f(...);
-
+/// If it is run with an \c AnalysisManager<IRUnitT> argument, it will propagate
+/// that analysis manager to each pass it runs, as well as calling the analysis
+/// manager's invalidation routine with the PreservedAnalyses of each pass it
+/// runs.
+template <typename IRUnitT> class PassManager {
public:
- enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
-};
-
-/// \brief Wrapper to model the analysis result concept.
-///
-/// By default, this will implement the invalidate method with a trivial
-/// implementation so that the actual analysis result doesn't need to provide
-/// an invalidation handler. It is only selected when the invalidation handler
-/// is not part of the ResultT's interface.
-template <typename IRUnitT, typename PassT, typename ResultT,
- bool HasInvalidateHandler =
- ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
-struct AnalysisResultModel;
-
-/// \brief Specialization of \c AnalysisResultModel which provides the default
-/// invalidate functionality.
-template <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, false>
- : AnalysisResultConcept<IRUnitT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- /// \brief The model bases invalidation solely on being in the preserved set.
- //
- // FIXME: We should actually use two different concepts for analysis results
- // rather than two different models, and avoid the indirect function call for
- // ones that use the trivial behavior.
- bool invalidate(IRUnitT, const PreservedAnalyses &PA) override {
- return !PA.preserved(PassT::ID());
- }
-
- ResultT Result;
-};
-
-/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
-/// handling to \c ResultT.
-template <typename IRUnitT, typename PassT, typename ResultT>
-struct AnalysisResultModel<IRUnitT, PassT, ResultT, true>
- : AnalysisResultConcept<IRUnitT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
-
- /// \brief The model delegates to the \c ResultT method.
- bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override {
- return Result.invalidate(IR, PA);
- }
-
- ResultT Result;
-};
-
-/// \brief Abstract concept of an analysis pass.
-///
-/// This concept is parameterized over the IR unit that it can run over and
-/// produce an analysis result.
-template <typename IRUnitT, typename AnalysisManagerT>
-struct AnalysisPassConcept {
- virtual ~AnalysisPassConcept() {}
-
- /// \brief Method to run this analysis over a unit of IR.
- /// \returns A unique_ptr to the analysis result object to be queried by
- /// users.
- virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *AM) = 0;
-};
-
-/// \brief Wrapper to model the analysis pass concept.
-///
-/// Can wrap any type which implements a suitable \c run method. The method
-/// must accept the IRUnitT as an argument and produce an object which can be
-/// wrapped in a \c AnalysisResultModel.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT,
- bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
- IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value>
-struct AnalysisPassModel;
-
-/// \brief Specialization of \c AnalysisPassModel which passes an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ /// \brief Construct a pass manager.
+ ///
+ /// It can be passed a flag to get debug logging as the passes are run.
+ PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
- AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- AnalysisPassModel &operator=(AnalysisPassModel RHS) {
- swap(*this, RHS);
+ PassManager(PassManager &&Arg)
+ : Passes(std::move(Arg.Passes)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
+ PassManager &operator=(PassManager &&RHS) {
+ Passes = std::move(RHS.Passes);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
- // FIXME: Replace PassT::Result with type traits when we use C++11.
- typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
-
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *AM) override {
- return make_unique<ResultModelT>(Pass.run(IR, AM));
- }
+ /// \brief Run all of the passes in this manager over the IR.
+ PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM = nullptr) {
+ PreservedAnalyses PA = PreservedAnalyses::all();
- PassT Pass;
-};
+ if (DebugLogging)
+ dbgs() << "Starting pass manager run.\n";
-/// \brief Specialization of \c AnalysisPassModel which does not pass an
-/// \c AnalysisManager to PassT's run method.
-template <typename IRUnitT, typename AnalysisManagerT, typename PassT>
-struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false>
- : AnalysisPassConcept<IRUnitT, AnalysisManagerT> {
- explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
- AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
- friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
- using std::swap;
- swap(LHS.Pass, RHS.Pass);
- }
- AnalysisPassModel &operator=(AnalysisPassModel RHS) {
- swap(*this, RHS);
- return *this;
- }
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
+ if (DebugLogging)
+ dbgs() << "Running pass: " << Passes[Idx]->name() << "\n";
- // FIXME: Replace PassT::Result with type traits when we use C++11.
- typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
- ResultModelT;
+ PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM);
- /// \brief The model delegates to the \c PassT::run method.
- ///
- /// The return is wrapped in an \c AnalysisResultModel.
- std::unique_ptr<AnalysisResultConcept<IRUnitT>>
- run(IRUnitT IR, AnalysisManagerT *) override {
- return make_unique<ResultModelT>(Pass.run(IR));
- }
+ // If we have an active analysis manager at this level we want to ensure
+ // we update it as each pass runs and potentially invalidates analyses.
+ // We also update the preserved set of analyses based on what analyses we
+ // have already handled the invalidation for here and don't need to
+ // invalidate when finished.
+ if (AM)
+ PassPA = AM->invalidate(IR, std::move(PassPA));
- PassT Pass;
-};
+ // Finally, we intersect the final preserved analyses to compute the
+ // aggregate preserved set for this pass manager.
+ PA.intersect(std::move(PassPA));
-} // End namespace detail
+ // FIXME: Historically, the pass managers all called the LLVM context's
+ // yield function here. We don't have a generic way to acquire the
+ // context and it isn't yet clear what the right pattern is for yielding
+ // in the new pass manager so it is currently omitted.
+ //IR.getContext().yield();
+ }
-class ModuleAnalysisManager;
+ if (DebugLogging)
+ dbgs() << "Finished pass manager run.\n";
-class ModulePassManager {
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- ModulePassManager() {}
- ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {}
- ModulePassManager &operator=(ModulePassManager &&RHS) {
- Passes = std::move(RHS.Passes);
- return *this;
+ return PA;
}
- /// \brief Run all of the module passes in this module pass manager over
- /// a module.
- ///
- /// This method should only be called for a single module as there is the
- /// expectation that the lifetime of a pass is bounded to that of a module.
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr);
-
- template <typename ModulePassT> void addPass(ModulePassT Pass) {
- Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass)));
+ template <typename PassT> void addPass(PassT Pass) {
+ typedef detail::PassModel<IRUnitT, PassT> PassModelT;
+ Passes.emplace_back(new PassModelT(std::move(Pass)));
}
- static StringRef name() { return "ModulePassManager"; }
+ static StringRef name() { return "PassManager"; }
private:
- // Pull in the concept type and model template specialized for modules.
- typedef detail::PassConcept<Module *, ModuleAnalysisManager>
- ModulePassConcept;
- template <typename PassT>
- struct ModulePassModel
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT> {
- ModulePassModel(PassT Pass)
- : detail::PassModel<Module *, ModuleAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
+ typedef detail::PassConcept<IRUnitT> PassConceptT;
- ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION;
- ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION;
+ PassManager(const PassManager &) LLVM_DELETED_FUNCTION;
+ PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION;
- std::vector<std::unique_ptr<ModulePassConcept>> Passes;
-};
-
-class FunctionAnalysisManager;
+ std::vector<std::unique_ptr<PassConceptT>> Passes;
-class FunctionPassManager {
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- FunctionPassManager() {}
- FunctionPassManager(FunctionPassManager &&Arg)
- : Passes(std::move(Arg.Passes)) {}
- FunctionPassManager &operator=(FunctionPassManager &&RHS) {
- Passes = std::move(RHS.Passes);
- return *this;
- }
-
- template <typename FunctionPassT> void addPass(FunctionPassT Pass) {
- Passes.emplace_back(new FunctionPassModel<FunctionPassT>(std::move(Pass)));
- }
-
- PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr);
-
- static StringRef name() { return "FunctionPassManager"; }
-
-private:
- // Pull in the concept type and model template specialized for functions.
- typedef detail::PassConcept<Function *, FunctionAnalysisManager>
- FunctionPassConcept;
- template <typename PassT>
- struct FunctionPassModel
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT> {
- FunctionPassModel(PassT Pass)
- : detail::PassModel<Function *, FunctionAnalysisManager, PassT>(
- std::move(Pass)) {}
- };
+ /// \brief Flag indicating whether we should do debug logging.
+ bool DebugLogging;
+};
- FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
- FunctionPassManager &
- operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION;
+/// \brief Convenience typedef for a pass manager over modules.
+typedef PassManager<Module> ModulePassManager;
- std::vector<std::unique_ptr<FunctionPassConcept>> Passes;
-};
+/// \brief Convenience typedef for a pass manager over functions.
+typedef PassManager<Function> FunctionPassManager;
namespace detail {
@@ -560,6 +269,12 @@ namespace detail {
/// - invalidateImpl
///
/// The details of the call pattern are within.
+///
+/// Note that there is also a generic analysis manager template which implements
+/// the above required functions along with common datastructures used for
+/// managing analyses. This base class is factored so that if you need to
+/// customize the handling of a specific IR unit, you can do so without
+/// replicating *all* of the boilerplate.
template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
DerivedT *derived_this() { return static_cast<DerivedT *>(this); }
const DerivedT *derived_this() const {
@@ -572,7 +287,7 @@ template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase {
protected:
typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT;
- typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT;
+ typedef detail::AnalysisPassConcept<IRUnitT> PassConceptT;
// FIXME: Provide template aliases for the models when we're using C++11 in
// a mode supporting them.
@@ -592,7 +307,7 @@ public:
///
/// If there is not a valid cached result in the manager already, this will
/// re-run the analysis to produce a valid result.
- template <typename PassT> typename PassT::Result &getResult(IRUnitT IR) {
+ template <typename PassT> typename PassT::Result &getResult(IRUnitT &IR) {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried");
@@ -609,7 +324,7 @@ public:
///
/// \returns null if there is no cached result.
template <typename PassT>
- typename PassT::Result *getCachedResult(IRUnitT IR) const {
+ typename PassT::Result *getCachedResult(IRUnitT &IR) const {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried");
@@ -631,25 +346,28 @@ public:
template <typename PassT> void registerPass(PassT Pass) {
assert(!AnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!");
- typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT;
+ typedef detail::AnalysisPassModel<IRUnitT, PassT> PassModelT;
AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass)));
}
/// \brief Invalidate a specific analysis pass for an IR module.
///
/// Note that the analysis result can disregard invalidation.
- template <typename PassT> void invalidate(Module *M) {
+ template <typename PassT> void invalidate(IRUnitT &IR) {
assert(AnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being invalidated");
- derived_this()->invalidateImpl(PassT::ID(), M);
+ derived_this()->invalidateImpl(PassT::ID(), IR);
}
/// \brief Invalidate analyses cached for an IR unit.
///
/// Walk through all of the analyses pertaining to this unit of IR and
/// invalidate them unless they are preserved by the PreservedAnalyses set.
- void invalidate(IRUnitT IR, const PreservedAnalyses &PA) {
- derived_this()->invalidateImpl(IR, PA);
+ /// We accept the PreservedAnalyses set by value and update it with each
+ /// analyis pass which has been successfully invalidated and thus can be
+ /// preserved going forward. The updated set is returned.
+ PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) {
+ return derived_this()->invalidateImpl(IR, std::move(PA));
}
protected:
@@ -679,108 +397,153 @@ private:
} // End namespace detail
-/// \brief A module analysis pass manager with lazy running and caching of
+/// \brief A generic analysis pass manager with lazy running and caching of
/// results.
-class ModuleAnalysisManager
- : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> {
- friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>;
- typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT;
- typedef BaseT::ResultConceptT ResultConceptT;
- typedef BaseT::PassConceptT PassConceptT;
-
-public:
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- ModuleAnalysisManager() {}
- ModuleAnalysisManager(ModuleAnalysisManager &&Arg)
- : BaseT(std::move(static_cast<BaseT &>(Arg))),
- ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {}
- ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) {
- BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
- ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults);
- return *this;
- }
-
-private:
- ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION;
- ModuleAnalysisManager &
- operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION;
-
- /// \brief Get a module pass result, running the pass if necessary.
- ResultConceptT &getResultImpl(void *PassID, Module *M);
-
- /// \brief Get a cached module pass result or return null.
- ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const;
-
- /// \brief Invalidate a module pass result.
- void invalidateImpl(void *PassID, Module *M);
-
- /// \brief Invalidate results across a module.
- void invalidateImpl(Module *M, const PreservedAnalyses &PA);
-
- /// \brief Map type from module analysis pass ID to pass result concept
- /// pointer.
- typedef DenseMap<void *,
- std::unique_ptr<detail::AnalysisResultConcept<Module *>>>
- ModuleAnalysisResultMapT;
-
- /// \brief Cache of computed module analysis results for this module.
- ModuleAnalysisResultMapT ModuleAnalysisResults;
-};
-
-/// \brief A function analysis manager to coordinate and cache analyses run over
-/// a module.
-class FunctionAnalysisManager
- : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> {
- friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>;
- typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>
- BaseT;
- typedef BaseT::ResultConceptT ResultConceptT;
- typedef BaseT::PassConceptT PassConceptT;
+///
+/// This analysis manager can be used for any IR unit where the address of the
+/// IR unit sufficies as its identity. It manages the cache for a unit of IR via
+/// the address of each unit of IR cached.
+template <typename IRUnitT>
+class AnalysisManager
+ : public detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> {
+ friend class detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT>;
+ typedef detail::AnalysisManagerBase<AnalysisManager<IRUnitT>, IRUnitT> BaseT;
+ typedef typename BaseT::ResultConceptT ResultConceptT;
+ typedef typename BaseT::PassConceptT PassConceptT;
public:
// Most public APIs are inherited from the CRTP base class.
+ /// \brief Construct an empty analysis manager.
+ ///
+ /// A flag can be passed to indicate that the manager should perform debug
+ /// logging.
+ AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {}
+
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
- FunctionAnalysisManager() {}
- FunctionAnalysisManager(FunctionAnalysisManager &&Arg)
+ AnalysisManager(AnalysisManager &&Arg)
: BaseT(std::move(static_cast<BaseT &>(Arg))),
- FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {}
- FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) {
+ AnalysisResults(std::move(Arg.AnalysisResults)),
+ DebugLogging(std::move(Arg.DebugLogging)) {}
+ AnalysisManager &operator=(AnalysisManager &&RHS) {
BaseT::operator=(std::move(static_cast<BaseT &>(RHS)));
- FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults);
+ AnalysisResults = std::move(RHS.AnalysisResults);
+ DebugLogging = std::move(RHS.DebugLogging);
return *this;
}
/// \brief Returns true if the analysis manager has an empty results cache.
- bool empty() const;
+ bool empty() const {
+ assert(AnalysisResults.empty() == AnalysisResultLists.empty() &&
+ "The storage and index of analysis results disagree on how many "
+ "there are!");
+ return AnalysisResults.empty();
+ }
- /// \brief Clear the function analysis result cache.
+ /// \brief Clear the analysis result cache.
///
- /// This routine allows cleaning up when the set of functions itself has
+ /// This routine allows cleaning up when the set of IR units itself has
/// potentially changed, and thus we can't even look up a a result and
- /// invalidate it directly. Notably, this does *not* call invalidate
- /// functions as there is nothing to be done for them.
- void clear();
+ /// invalidate it directly. Notably, this does *not* call invalidate functions
+ /// as there is nothing to be done for them.
+ void clear() {
+ AnalysisResults.clear();
+ AnalysisResultLists.clear();
+ }
private:
- FunctionAnalysisManager(const FunctionAnalysisManager &)
- LLVM_DELETED_FUNCTION;
- FunctionAnalysisManager &
- operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION;
+ AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION;
+ AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION;
+
+ /// \brief Get an analysis result, running the pass if necessary.
+ ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) {
+ typename AnalysisResultMapT::iterator RI;
+ bool Inserted;
+ std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair(
+ std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator()));
+
+ // If we don't have a cached result for this function, look up the pass and
+ // run it to produce a result, which we then add to the cache.
+ if (Inserted) {
+ auto &P = this->lookupPass(PassID);
+ if (DebugLogging)
+ dbgs() << "Running analysis: " << P.name() << "\n";
+ AnalysisResultListT &ResultList = AnalysisResultLists[&IR];
+ ResultList.emplace_back(PassID, P.run(IR, this));
+ RI->second = std::prev(ResultList.end());
+ }
- /// \brief Get a function pass result, running the pass if necessary.
- ResultConceptT &getResultImpl(void *PassID, Function *F);
+ return *RI->second->second;
+ }
- /// \brief Get a cached function pass result or return null.
- ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const;
+ /// \brief Get a cached analysis result or return null.
+ ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const {
+ typename AnalysisResultMapT::const_iterator RI =
+ AnalysisResults.find(std::make_pair(PassID, &IR));
+ return RI == AnalysisResults.end() ? nullptr : &*RI->second->second;
+ }
/// \brief Invalidate a function pass result.
- void invalidateImpl(void *PassID, Function *F);
+ void invalidateImpl(void *PassID, IRUnitT &IR) {
+ typename AnalysisResultMapT::iterator RI =
+ AnalysisResults.find(std::make_pair(PassID, &IR));
+ if (RI == AnalysisResults.end())
+ return;
+
+ if (DebugLogging)
+ dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
+ << "\n";
+ AnalysisResultLists[&IR].erase(RI->second);
+ AnalysisResults.erase(RI);
+ }
/// \brief Invalidate the results for a function..
- void invalidateImpl(Function *F, const PreservedAnalyses &PA);
+ PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) {
+ // Short circuit for a common case of all analyses being preserved.
+ if (PA.areAllPreserved())
+ return std::move(PA);
+
+ if (DebugLogging)
+ dbgs() << "Invalidating all non-preserved analyses for: "
+ << IR.getName() << "\n";
+
+ // Clear all the invalidated results associated specifically with this
+ // function.
+ SmallVector<void *, 8> InvalidatedPassIDs;
+ AnalysisResultListT &ResultsList = AnalysisResultLists[&IR];
+ for (typename AnalysisResultListT::iterator I = ResultsList.begin(),
+ E = ResultsList.end();
+ I != E;) {
+ void *PassID = I->first;
+
+ // Pass the invalidation down to the pass itself to see if it thinks it is
+ // necessary. The analysis pass can return false if no action on the part
+ // of the analysis manager is required for this invalidation event.
+ if (I->second->invalidate(IR, PA)) {
+ if (DebugLogging)
+ dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name()
+ << "\n";
+
+ InvalidatedPassIDs.push_back(I->first);
+ I = ResultsList.erase(I);
+ } else {
+ ++I;
+ }
+
+ // After handling each pass, we mark it as preserved. Once we've
+ // invalidated any stale results, the rest of the system is allowed to
+ // start preserving this analysis again.
+ PA.preserve(PassID);
+ }
+ while (!InvalidatedPassIDs.empty())
+ AnalysisResults.erase(
+ std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR));
+ if (ResultsList.empty())
+ AnalysisResultLists.erase(&IR);
+
+ return std::move(PA);
+ }
/// \brief List of function analysis pass IDs and associated concept pointers.
///
@@ -788,30 +551,37 @@ private:
/// erases. Provides both the pass ID and concept pointer such that it is
/// half of a bijection and provides storage for the actual result concept.
typedef std::list<std::pair<
- void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>>
- FunctionAnalysisResultListT;
+ void *, std::unique_ptr<detail::AnalysisResultConcept<IRUnitT>>>>
+ AnalysisResultListT;
/// \brief Map type from function pointer to our custom list type.
- typedef DenseMap<Function *, FunctionAnalysisResultListT>
- FunctionAnalysisResultListMapT;
+ typedef DenseMap<IRUnitT *, AnalysisResultListT> AnalysisResultListMapT;
/// \brief Map from function to a list of function analysis results.
///
/// Provides linear time removal of all analysis results for a function and
/// the ultimate storage for a particular cached analysis result.
- FunctionAnalysisResultListMapT FunctionAnalysisResultLists;
+ AnalysisResultListMapT AnalysisResultLists;
/// \brief Map type from a pair of analysis ID and function pointer to an
/// iterator into a particular result list.
- typedef DenseMap<std::pair<void *, Function *>,
- FunctionAnalysisResultListT::iterator>
- FunctionAnalysisResultMapT;
+ typedef DenseMap<std::pair<void *, IRUnitT *>,
+ typename AnalysisResultListT::iterator> AnalysisResultMapT;
/// \brief Map from an analysis ID and function to a particular cached
/// analysis result.
- FunctionAnalysisResultMapT FunctionAnalysisResults;
+ AnalysisResultMapT AnalysisResults;
+
+ /// \brief A flag indicating whether debug logging is enabled.
+ bool DebugLogging;
};
+/// \brief Convenience typedef for the Module analysis manager.
+typedef AnalysisManager<Module> ModuleAnalysisManager;
+
+/// \brief Convenience typedef for the Function analysis manager.
+typedef AnalysisManager<Function> FunctionAnalysisManager;
+
/// \brief A module analysis which acts as a proxy for a function analysis
/// manager.
///
@@ -826,6 +596,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; }
+
explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM)
: FAM(&FAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -850,7 +622,7 @@ public:
/// In debug builds, it will also assert that the analysis manager is empty
/// as no queries should arrive at the function analysis manager prior to
/// this analysis being requested.
- Result run(Module *M);
+ Result run(Module &M);
private:
static char PassID;
@@ -888,7 +660,7 @@ public:
/// Regardless of whether this analysis is marked as preserved, all of the
/// analyses in the \c FunctionAnalysisManager are potentially invalidated
/// based on the set of preserved analyses.
- bool invalidate(Module *M, const PreservedAnalyses &PA);
+ bool invalidate(Module &M, const PreservedAnalyses &PA);
private:
FunctionAnalysisManager *FAM;
@@ -924,7 +696,7 @@ public:
const ModuleAnalysisManager &getManager() const { return *MAM; }
/// \brief Handle invalidation by ignoring it, this pass is immutable.
- bool invalidate(Function *) { return false; }
+ bool invalidate(Function &) { return false; }
private:
const ModuleAnalysisManager *MAM;
@@ -932,6 +704,8 @@ public:
static void *ID() { return (void *)&PassID; }
+ static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; }
+
ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM)
: MAM(&MAM) {}
// We have to explicitly define all the special member functions because MSVC
@@ -950,7 +724,7 @@ public:
/// \brief Run the analysis pass and create our proxy result object.
/// Nothing to see here, it just forwards the \c MAM reference into the
/// result.
- Result run(Function *) { return Result(*MAM); }
+ Result run(Function &) { return Result(*MAM); }
private:
static char PassID;
@@ -966,6 +740,20 @@ private:
/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function
/// pass over the module to enable a \c FunctionAnalysisManager to be used
/// within this run safely.
+///
+/// Function passes run within this adaptor can rely on having exclusive access
+/// to the function they are run over. They should not read or modify any other
+/// functions! Other threads or systems may be manipulating other functions in
+/// the module, and so their state should never be relied on.
+/// FIXME: Make the above true for all of LLVM's actual passes, some still
+/// violate this principle.
+///
+/// Function passes can also read the module containing the function, but they
+/// should not modify that module outside of the use lists of various globals.
+/// For example, a function pass is not permitted to add functions to the
+/// module.
+/// FIXME: Make the above true for all of LLVM's actual passes, some still
+/// violate this principle.
template <typename FunctionPassT> class ModuleToFunctionPassAdaptor {
public:
explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass)
@@ -976,7 +764,8 @@ public:
: Pass(Arg.Pass) {}
ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg)
: Pass(std::move(Arg.Pass)) {}
- friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) {
+ friend void swap(ModuleToFunctionPassAdaptor &LHS,
+ ModuleToFunctionPassAdaptor &RHS) {
using std::swap;
swap(LHS.Pass, RHS.Pass);
}
@@ -986,21 +775,23 @@ public:
}
/// \brief Runs the function pass across every function in the module.
- PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
FunctionAnalysisManager *FAM = nullptr;
if (AM)
// Setup the function analysis manager from its proxy.
FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
PreservedAnalyses PA = PreservedAnalyses::all();
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
- PreservedAnalyses PassPA = Pass.run(I, FAM);
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ PreservedAnalyses PassPA = Pass.run(*I, FAM);
// We know that the function pass couldn't have invalidated any other
// function's analyses (that's the contract of a function pass), so
- // directly handle the function analysis manager's invalidation here.
+ // directly handle the function analysis manager's invalidation here and
+ // update our preserved set to reflect that these have already been
+ // handled.
if (FAM)
- FAM->invalidate(I, PassPA);
+ PassPA = FAM->invalidate(*I, std::move(PassPA));
// Then intersect the preserved set so that invalidation of module
// analyses will eventually occur when the module pass completes.
@@ -1029,6 +820,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) {
return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)));
}
+/// \brief A template utility pass to force an analysis result to be available.
+///
+/// This is a no-op pass which simply forces a specific analysis pass's result
+/// to be available when it is run.
+template <typename AnalysisT> struct RequireAnalysisPass {
+ /// \brief Run this pass over some unit of IR.
+ ///
+ /// This pass can be run over any unit of IR and use any analysis manager
+ /// provided they satisfy the basic API requirements. When this pass is
+ /// created, these methods can be instantiated to satisfy whatever the
+ /// context requires.
+ template <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
+ if (AM)
+ (void)AM->template getResult<AnalysisT>(Arg);
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "RequireAnalysisPass"; }
+};
+
+/// \brief A template utility pass to force an analysis result to be
+/// invalidated.
+///
+/// This is a no-op pass which simply forces a specific analysis result to be
+/// invalidated when it is run.
+template <typename AnalysisT> struct InvalidateAnalysisPass {
+ /// \brief Run this pass over some unit of IR.
+ ///
+ /// This pass can be run over any unit of IR and use any analysis manager
+ /// provided they satisfy the basic API requirements. When this pass is
+ /// created, these methods can be instantiated to satisfy whatever the
+ /// context requires.
+ template <typename IRUnitT>
+ PreservedAnalyses run(IRUnitT &Arg, AnalysisManager<IRUnitT> *AM) {
+ if (AM)
+ // We have to directly invalidate the analysis result as we can't
+ // enumerate all other analyses and use the preserved set to control it.
+ (void)AM->template invalidate<AnalysisT>(Arg);
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "InvalidateAnalysisPass"; }
+};
+
+/// \brief A utility pass that does nothing but preserves no analyses.
+///
+/// As a consequence fo not preserving any analyses, this pass will force all
+/// analysis passes to be re-run to produce fresh results if any are needed.
+struct InvalidateAllAnalysesPass {
+ /// \brief Run this pass over some unit of IR.
+ template <typename IRUnitT> PreservedAnalyses run(IRUnitT &Arg) {
+ return PreservedAnalyses::none();
+ }
+
+ static StringRef name() { return "InvalidateAllAnalysesPass"; }
+};
+
}
#endif
diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h
new file mode 100644
index 000000000000..297f5f4e07f4
--- /dev/null
+++ b/include/llvm/IR/PassManagerInternal.h
@@ -0,0 +1,349 @@
+//===- PassManager internal APIs and implementation details -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This header provides internal APIs and implementation details used by the
+/// pass management interfaces exposed in PassManager.h. To understand more
+/// context of why these particular interfaces are needed, see that header
+/// file. None of these APIs should be used elsewhere.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_PASSMANAGERINTERNAL_H
+#define LLVM_IR_PASSMANAGERINTERNAL_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+template <typename IRUnitT> class AnalysisManager;
+class PreservedAnalyses;
+
+/// \brief Implementation details of the pass manager interfaces.
+namespace detail {
+
+/// \brief Template for the abstract base class used to dispatch
+/// polymorphically over pass objects.
+template <typename IRUnitT> struct PassConcept {
+ // Boiler plate necessary for the container of derived classes.
+ virtual ~PassConcept() {}
+
+ /// \brief The polymorphic API which runs the pass over a given IR entity.
+ ///
+ /// Note that actual pass object can omit the analysis manager argument if
+ /// desired. Also that the analysis manager may be null if there is no
+ /// analysis manager in the pass pipeline.
+ virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+
+ /// \brief Polymorphic method to access the name of a pass.
+ virtual StringRef name() = 0;
+};
+
+/// \brief SFINAE metafunction for computing whether \c PassT has a run method
+/// accepting an \c AnalysisManager<IRUnitT>.
+template <typename IRUnitT, typename PassT, typename ResultT>
+class PassRunAcceptsAnalysisManager {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, ResultT (T::*)(IRUnitT &, AnalysisManager<IRUnitT> *)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::run> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) };
+};
+
+/// \brief A template wrapper used to implement the polymorphic API.
+///
+/// Can be instantiated for any object which provides a \c run method accepting
+/// an \c IRUnitT. It requires the pass to be a copyable object. When the
+/// \c run method also accepts an \c AnalysisManager<IRUnitT>*, we pass it
+/// along.
+template <typename IRUnitT, typename PassT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, PreservedAnalysesT>::Value>
+struct PassModel;
+
+/// \brief Specialization of \c PassModel for passes that accept an analyis
+/// manager.
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, true>
+ : PassConcept<IRUnitT> {
+ explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
+ PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(PassModel &LHS, PassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ PassModel &operator=(PassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return Pass.run(IR, AM);
+ }
+ StringRef name() override { return PassT::name(); }
+ PassT Pass;
+};
+
+/// \brief Specialization of \c PassModel for passes that accept an analyis
+/// manager.
+template <typename IRUnitT, typename PassT, typename PreservedAnalysesT>
+struct PassModel<IRUnitT, PassT, PreservedAnalysesT, false>
+ : PassConcept<IRUnitT> {
+ explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
+ PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(PassModel &LHS, PassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ PassModel &operator=(PassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ PreservedAnalysesT run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return Pass.run(IR);
+ }
+ StringRef name() override { return PassT::name(); }
+ PassT Pass;
+};
+
+/// \brief Abstract concept of an analysis result.
+///
+/// This concept is parameterized over the IR unit that this result pertains
+/// to.
+template <typename IRUnitT> struct AnalysisResultConcept {
+ virtual ~AnalysisResultConcept() {}
+
+ /// \brief Method to try and mark a result as invalid.
+ ///
+ /// When the outer analysis manager detects a change in some underlying
+ /// unit of the IR, it will call this method on all of the results cached.
+ ///
+ /// This method also receives a set of preserved analyses which can be used
+ /// to avoid invalidation because the pass which changed the underlying IR
+ /// took care to update or preserve the analysis result in some way.
+ ///
+ /// \returns true if the result is indeed invalid (the default).
+ virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0;
+};
+
+/// \brief SFINAE metafunction for computing whether \c ResultT provides an
+/// \c invalidate member function.
+template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod {
+ typedef char SmallType;
+ struct BigType {
+ char a, b;
+ };
+
+ template <typename T, bool (T::*)(IRUnitT &, const PreservedAnalyses &)>
+ struct Checker;
+
+ template <typename T> static SmallType f(Checker<T, &T::invalidate> *);
+ template <typename T> static BigType f(...);
+
+public:
+ enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) };
+};
+
+/// \brief Wrapper to model the analysis result concept.
+///
+/// By default, this will implement the invalidate method with a trivial
+/// implementation so that the actual analysis result doesn't need to provide
+/// an invalidation handler. It is only selected when the invalidation handler
+/// is not part of the ResultT's interface.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT = PreservedAnalyses,
+ bool HasInvalidateHandler =
+ ResultHasInvalidateMethod<IRUnitT, ResultT>::Value>
+struct AnalysisResultModel;
+
+/// \brief Specialization of \c AnalysisResultModel which provides the default
+/// invalidate functionality.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, false>
+ : AnalysisResultConcept<IRUnitT> {
+ explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
+ AnalysisResultModel(AnalysisResultModel &&Arg)
+ : Result(std::move(Arg.Result)) {}
+ friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
+ using std::swap;
+ swap(LHS.Result, RHS.Result);
+ }
+ AnalysisResultModel &operator=(AnalysisResultModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ /// \brief The model bases invalidation solely on being in the preserved set.
+ //
+ // FIXME: We should actually use two different concepts for analysis results
+ // rather than two different models, and avoid the indirect function call for
+ // ones that use the trivial behavior.
+ bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override {
+ return !PA.preserved(PassT::ID());
+ }
+
+ ResultT Result;
+};
+
+/// \brief Specialization of \c AnalysisResultModel which delegates invalidate
+/// handling to \c ResultT.
+template <typename IRUnitT, typename PassT, typename ResultT,
+ typename PreservedAnalysesT>
+struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, true>
+ : AnalysisResultConcept<IRUnitT> {
+ explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
+ AnalysisResultModel(AnalysisResultModel &&Arg)
+ : Result(std::move(Arg.Result)) {}
+ friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
+ using std::swap;
+ swap(LHS.Result, RHS.Result);
+ }
+ AnalysisResultModel &operator=(AnalysisResultModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ /// \brief The model delegates to the \c ResultT method.
+ bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override {
+ return Result.invalidate(IR, PA);
+ }
+
+ ResultT Result;
+};
+
+/// \brief Abstract concept of an analysis pass.
+///
+/// This concept is parameterized over the IR unit that it can run over and
+/// produce an analysis result.
+template <typename IRUnitT> struct AnalysisPassConcept {
+ virtual ~AnalysisPassConcept() {}
+
+ /// \brief Method to run this analysis over a unit of IR.
+ /// \returns A unique_ptr to the analysis result object to be queried by
+ /// users.
+ virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) = 0;
+
+ /// \brief Polymorphic method to access the name of a pass.
+ virtual StringRef name() = 0;
+};
+
+/// \brief Wrapper to model the analysis pass concept.
+///
+/// Can wrap any type which implements a suitable \c run method. The method
+/// must accept the IRUnitT as an argument and produce an object which can be
+/// wrapped in a \c AnalysisResultModel.
+template <typename IRUnitT, typename PassT,
+ bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager<
+ IRUnitT, PassT, typename PassT::Result>::Value>
+struct AnalysisPassModel;
+
+/// \brief Specialization of \c AnalysisPassModel which passes an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, true> : AnalysisPassConcept<IRUnitT> {
+ explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
+ AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ AnalysisPassModel &operator=(AnalysisPassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ // FIXME: Replace PassT::Result with type traits when we use C++11.
+ typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *AM) override {
+ return make_unique<ResultModelT>(Pass.run(IR, AM));
+ }
+
+ /// \brief The model delegates to a static \c PassT::name method.
+ ///
+ /// The returned string ref must point to constant immutable data!
+ StringRef name() override { return PassT::name(); }
+
+ PassT Pass;
+};
+
+/// \brief Specialization of \c AnalysisPassModel which does not pass an
+/// \c AnalysisManager to PassT's run method.
+template <typename IRUnitT, typename PassT>
+struct AnalysisPassModel<IRUnitT, PassT, false> : AnalysisPassConcept<IRUnitT> {
+ explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {}
+ // We have to explicitly define all the special member functions because MSVC
+ // refuses to generate them.
+ AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {}
+ AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
+ friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) {
+ using std::swap;
+ swap(LHS.Pass, RHS.Pass);
+ }
+ AnalysisPassModel &operator=(AnalysisPassModel RHS) {
+ swap(*this, RHS);
+ return *this;
+ }
+
+ // FIXME: Replace PassT::Result with type traits when we use C++11.
+ typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
+ ResultModelT;
+
+ /// \brief The model delegates to the \c PassT::run method.
+ ///
+ /// The return is wrapped in an \c AnalysisResultModel.
+ std::unique_ptr<AnalysisResultConcept<IRUnitT>>
+ run(IRUnitT &IR, AnalysisManager<IRUnitT> *) override {
+ return make_unique<ResultModelT>(Pass.run(IR));
+ }
+
+ /// \brief The model delegates to a static \c PassT::name method.
+ ///
+ /// The returned string ref must point to constant immutable data!
+ StringRef name() override { return PassT::name(); }
+
+ PassT Pass;
+};
+
+} // End namespace detail
+}
+
+#endif
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index 2efb29489473..f94e10576893 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -32,61 +32,64 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Operator.h"
namespace llvm {
namespace PatternMatch {
-template<typename Val, typename Pattern>
-bool match(Val *V, const Pattern &P) {
- return const_cast<Pattern&>(P).match(V);
+template <typename Val, typename Pattern> bool match(Val *V, const Pattern &P) {
+ return const_cast<Pattern &>(P).match(V);
}
-
-template<typename SubPattern_t>
-struct OneUse_match {
+template <typename SubPattern_t> struct OneUse_match {
SubPattern_t SubPattern;
OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
return V->hasOneUse() && SubPattern.match(V);
}
};
-template<typename T>
-inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; }
-
+template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) {
+ return SubPattern;
+}
-template<typename Class>
-struct class_match {
- template<typename ITy>
- bool match(ITy *V) { return isa<Class>(V); }
+template <typename Class> struct class_match {
+ template <typename ITy> bool match(ITy *V) { return isa<Class>(V); }
};
-/// m_Value() - Match an arbitrary value and ignore it.
+/// \brief Match an arbitrary value and ignore it.
inline class_match<Value> m_Value() { return class_match<Value>(); }
-/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it.
+
+/// \brief Match an arbitrary binary operation and ignore it.
+inline class_match<BinaryOperator> m_BinOp() {
+ return class_match<BinaryOperator>();
+}
+
+/// \brief Matches any compare instruction and ignore it.
+inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); }
+
+/// \brief Match an arbitrary ConstantInt and ignore it.
inline class_match<ConstantInt> m_ConstantInt() {
return class_match<ConstantInt>();
}
-/// m_Undef() - Match an arbitrary undef constant.
+
+/// \brief Match an arbitrary undef constant.
inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); }
+/// \brief Match an arbitrary Constant and ignore it.
inline class_match<Constant> m_Constant() { return class_match<Constant>(); }
/// Matching combinators
-template<typename LTy, typename RTy>
-struct match_combine_or {
+template <typename LTy, typename RTy> struct match_combine_or {
LTy L;
RTy R;
- match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { }
+ match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {}
- template<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> bool match(ITy *V) {
if (L.match(V))
return true;
if (R.match(V))
@@ -95,15 +98,13 @@ struct match_combine_or {
}
};
-template<typename LTy, typename RTy>
-struct match_combine_and {
+template <typename LTy, typename RTy> struct match_combine_and {
LTy L;
RTy R;
- match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { }
+ match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {}
- template<typename ITy>
- bool match(ITy *V) {
+ template <typename ITy> bool match(ITy *V) {
if (L.match(V))
if (R.match(V))
return true;
@@ -112,46 +113,44 @@ struct match_combine_and {
};
/// Combine two pattern matchers matching L || R
-template<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) {
return match_combine_or<LTy, RTy>(L, R);
}
/// Combine two pattern matchers matching L && R
-template<typename LTy, typename RTy>
+template <typename LTy, typename RTy>
inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) {
return match_combine_and<LTy, RTy>(L, R);
}
struct match_zero {
- template<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(V))
return C->isNullValue();
return false;
}
};
-/// m_Zero() - Match an arbitrary zero/null constant. This includes
+/// \brief Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers.
inline match_zero m_Zero() { return match_zero(); }
struct match_neg_zero {
- template<typename ITy>
- bool match(ITy *V) {
- if (const Constant *C = dyn_cast<Constant>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *C = dyn_cast<Constant>(V))
return C->isNegativeZeroValue();
return false;
}
};
-/// m_NegZero() - Match an arbitrary zero/null constant. This includes
+/// \brief Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers. For
/// floating point constants, this will match negative zero but not positive
/// zero
inline match_neg_zero m_NegZero() { return match_neg_zero(); }
-/// m_AnyZero() - Match an arbitrary zero/null constant. This includes
+/// \brief - Match an arbitrary zero/null constant. This includes
/// zero_initializer for vectors and ConstantPointerNull for pointers. For
/// floating point constants, this will match negative zero and positive zero
inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
@@ -161,16 +160,14 @@ inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() {
struct apint_match {
const APInt *&Res;
apint_match(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CI = dyn_cast<ConstantInt>(V)) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue())) {
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) {
Res = &CI->getValue();
return true;
}
@@ -178,16 +175,13 @@ struct apint_match {
}
};
-/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the
+/// \brief Match a ConstantInt or splatted ConstantVector, binding the
/// specified pointer to the contained APInt.
inline apint_match m_APInt(const APInt *&Res) { return Res; }
-
-template<int64_t Val>
-struct constantint_match {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+template <int64_t Val> struct constantint_match {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V)) {
const APInt &CIV = CI->getValue();
if (Val >= 0)
return CIV == static_cast<uint64_t>(Val);
@@ -200,45 +194,39 @@ struct constantint_match {
}
};
-/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value.
-template<int64_t Val>
-inline constantint_match<Val> m_ConstantInt() {
+/// \brief Match a ConstantInt with a specific value.
+template <int64_t Val> inline constantint_match<Val> m_ConstantInt() {
return constantint_match<Val>();
}
-/// cst_pred_ty - This helper class is used to match scalar and vector constants
-/// that satisfy a specified predicate.
-template<typename Predicate>
-struct cst_pred_ty : public Predicate {
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+/// \brief This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate.
+template <typename Predicate> struct cst_pred_ty : public Predicate {
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
return this->isValue(CI->getValue());
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (const ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (const auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
return this->isValue(CI->getValue());
return false;
}
};
-/// api_pred_ty - This helper class is used to match scalar and vector constants
-/// that satisfy a specified predicate, and bind them to an APInt.
-template<typename Predicate>
-struct api_pred_ty : public Predicate {
+/// \brief This helper class is used to match scalar and vector constants that
+/// satisfy a specified predicate, and bind them to an APInt.
+template <typename Predicate> struct api_pred_ty : public Predicate {
const APInt *&Res;
api_pred_ty(const APInt *&R) : Res(R) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CI = dyn_cast<ConstantInt>(V))
if (this->isValue(CI->getValue())) {
Res = &CI->getValue();
return true;
}
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue()))
if (this->isValue(CI->getValue())) {
Res = &CI->getValue();
return true;
@@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate {
}
};
-
struct is_one {
bool isValue(const APInt &C) { return C == 1; }
};
-/// m_One() - Match an integer 1 or a vector with all elements equal to 1.
+/// \brief Match an integer 1 or a vector with all elements equal to 1.
inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); }
inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; }
@@ -261,34 +248,43 @@ struct is_all_ones {
bool isValue(const APInt &C) { return C.isAllOnesValue(); }
};
-/// m_AllOnes() - Match an integer or vector with all bits set to true.
-inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();}
+/// \brief Match an integer or vector with all bits set to true.
+inline cst_pred_ty<is_all_ones> m_AllOnes() {
+ return cst_pred_ty<is_all_ones>();
+}
inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; }
struct is_sign_bit {
bool isValue(const APInt &C) { return C.isSignBit(); }
};
-/// m_SignBit() - Match an integer or vector with only the sign bit(s) set.
-inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();}
+/// \brief Match an integer or vector with only the sign bit(s) set.
+inline cst_pred_ty<is_sign_bit> m_SignBit() {
+ return cst_pred_ty<is_sign_bit>();
+}
inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; }
struct is_power2 {
bool isValue(const APInt &C) { return C.isPowerOf2(); }
};
-/// m_Power2() - Match an integer or vector power of 2.
+/// \brief Match an integer or vector power of 2.
inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); }
inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; }
-template<typename Class>
-struct bind_ty {
+struct is_maxsignedvalue {
+ bool isValue(const APInt &C) { return C.isMaxSignedValue(); }
+};
+
+inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { return cst_pred_ty<is_maxsignedvalue>(); }
+inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { return V; }
+
+template <typename Class> struct bind_ty {
Class *&VR;
bind_ty(Class *&V) : VR(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (Class *CV = dyn_cast<Class>(V)) {
+ template <typename ITy> bool match(ITy *V) {
+ if (auto *CV = dyn_cast<Class>(V)) {
VR = CV;
return true;
}
@@ -296,64 +292,62 @@ struct bind_ty {
}
};
-/// m_Value - Match a value, capturing it if we match.
+/// \brief Match a value, capturing it if we match.
inline bind_ty<Value> m_Value(Value *&V) { return V; }
-/// m_ConstantInt - Match a ConstantInt, capturing the value if we match.
+/// \brief Match a binary operator, capturing it if we match.
+inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; }
+
+/// \brief Match a ConstantInt, capturing the value if we match.
inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; }
-/// m_Constant - Match a Constant, capturing the value if we match.
+/// \brief Match a Constant, capturing the value if we match.
inline bind_ty<Constant> m_Constant(Constant *&C) { return C; }
-/// m_ConstantFP - Match a ConstantFP, capturing the value if we match.
+/// \brief Match a ConstantFP, capturing the value if we match.
inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; }
-/// specificval_ty - Match a specified Value*.
+/// \brief Match a specified Value*.
struct specificval_ty {
const Value *Val;
specificval_ty(const Value *V) : Val(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- return V == Val;
- }
+ template <typename ITy> bool match(ITy *V) { return V == Val; }
};
-/// m_Specific - Match if we have a specific specified value.
+/// \brief Match if we have a specific specified value.
inline specificval_ty m_Specific(const Value *V) { return V; }
-/// Match a specified floating point value or vector of all elements of that
-/// value.
+/// \brief Match a specified floating point value or vector of all elements of
+/// that value.
struct specific_fpval {
double Val;
specific_fpval(double V) : Val(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CFP = dyn_cast<ConstantFP>(V))
return CFP->isExactlyValue(Val);
if (V->getType()->isVectorTy())
- if (const Constant *C = dyn_cast<Constant>(V))
- if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
+ if (const auto *C = dyn_cast<Constant>(V))
+ if (auto *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue()))
return CFP->isExactlyValue(Val);
return false;
}
};
-/// Match a specific floating point value or vector with all elements equal to
-/// the value.
+/// \brief Match a specific floating point value or vector with all elements
+/// equal to the value.
inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); }
-/// Match a float 1.0 or vector with all elements equal to 1.0.
+/// \brief Match a float 1.0 or vector with all elements equal to 1.0.
inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); }
struct bind_const_intval_ty {
uint64_t &VR;
bind_const_intval_ty(uint64_t &V) : VR(V) {}
- template<typename ITy>
- bool match(ITy *V) {
- if (ConstantInt *CV = dyn_cast<ConstantInt>(V))
+ template <typename ITy> bool match(ITy *V) {
+ if (const auto *CV = dyn_cast<ConstantInt>(V))
if (CV->getBitWidth() <= 64) {
VR = CV->getZExtValue();
return true;
@@ -362,152 +356,196 @@ struct bind_const_intval_ty {
}
};
-/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not
-/// match ConstantInts wider than 64-bits.
+/// \brief Match a specified integer value or vector of all elements of that
+// value.
+struct specific_intval {
+ uint64_t Val;
+ specific_intval(uint64_t V) : Val(V) {}
+
+ template <typename ITy> bool match(ITy *V) {
+ const auto *CI = dyn_cast<ConstantInt>(V);
+ if (!CI && V->getType()->isVectorTy())
+ if (const auto *C = dyn_cast<Constant>(V))
+ CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue());
+
+ if (CI && CI->getBitWidth() <= 64)
+ return CI->getZExtValue() == Val;
+
+ return false;
+ }
+};
+
+/// \brief Match a specific integer value or vector with all elements equal to
+/// the value.
+inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); }
+
+/// \brief Match a ConstantInt and bind to its value. This does not match
+/// ConstantInts wider than 64-bits.
inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; }
//===----------------------------------------------------------------------===//
+// Matcher for any binary operator.
+//
+template <typename LHS_t, typename RHS_t> struct AnyBinaryOp_match {
+ LHS_t L;
+ RHS_t R;
+
+ AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<BinaryOperator>(V))
+ return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
+ return false;
+ }
+};
+
+template <typename LHS, typename RHS>
+inline AnyBinaryOp_match<LHS, RHS> m_BinOp(const LHS &L, const RHS &R) {
+ return AnyBinaryOp_match<LHS, RHS>(L, R);
+}
+
+//===----------------------------------------------------------------------===//
// Matchers for specific binary operators.
//
-template<typename LHS_t, typename RHS_t, unsigned Opcode>
+template <typename LHS_t, typename RHS_t, unsigned Opcode>
struct BinaryOp_match {
LHS_t L;
RHS_t R;
BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opcode) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) &&
R.match(CE->getOperand(1));
return false;
}
};
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Add>
-m_Add(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FAdd>
-m_FAdd(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Sub>
-m_Sub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FSub>
-m_FSub(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Mul>
-m_Mul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FMul>
-m_FMul(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::UDiv>
-m_UDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SDiv>
-m_SDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FDiv>
-m_FDiv(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::URem>
-m_URem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::SRem>
-m_SRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::FRem>
-m_FRem(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::And>
-m_And(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::And>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Or>
-m_Or(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Xor>
-m_Xor(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::Shl>
-m_Shl(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::LShr>
-m_LShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R);
}
-template<typename LHS, typename RHS>
-inline BinaryOp_match<LHS, RHS, Instruction::AShr>
-m_AShr(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L,
+ const RHS &R) {
return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R);
}
-template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0>
+template <typename LHS_t, typename RHS_t, unsigned Opcode,
+ unsigned WrapFlags = 0>
struct OverflowingBinaryOp_match {
LHS_t L;
RHS_t R;
- OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
+ OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS)
+ : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(V)) {
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *Op = dyn_cast<OverflowingBinaryOperator>(V)) {
if (Op->getOpcode() != Opcode)
return false;
if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap &&
@@ -591,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) {
//===----------------------------------------------------------------------===//
// Class that matches two different binary ops.
//
-template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
+template <typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2>
struct BinOp2_match {
LHS_t L;
RHS_t R;
BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (V->getValueID() == Value::InstructionVal + Opc1 ||
V->getValueID() == Value::InstructionVal + Opc2) {
- BinaryOperator *I = cast<BinaryOperator>(V);
+ auto *I = cast<BinaryOperator>(V);
return L.match(I->getOperand(0)) && R.match(I->getOperand(1));
}
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+ if (auto *CE = dyn_cast<ConstantExpr>(V))
return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) &&
L.match(CE->getOperand(0)) && R.match(CE->getOperand(1));
return false;
}
};
-/// m_Shr - Matches LShr or AShr.
-template<typename LHS, typename RHS>
+/// \brief Matches LShr or AShr.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>
m_Shr(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R);
}
-/// m_LogicalShift - Matches LShr or Shl.
-template<typename LHS, typename RHS>
+/// \brief Matches LShr or Shl.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>
m_LogicalShift(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R);
}
-/// m_IDiv - Matches UDiv and SDiv.
-template<typename LHS, typename RHS>
+/// \brief Matches UDiv and SDiv.
+template <typename LHS, typename RHS>
inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>
m_IDiv(const LHS &L, const RHS &R) {
return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R);
@@ -636,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) {
//===----------------------------------------------------------------------===//
// Class that matches exact binary ops.
//
-template<typename SubPattern_t>
-struct Exact_match {
+template <typename SubPattern_t> struct Exact_match {
SubPattern_t SubPattern;
Exact_match(const SubPattern_t &SP) : SubPattern(SP) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (PossiblyExactOperator *PEO = dyn_cast<PossiblyExactOperator>(V))
return PEO->isExact() && SubPattern.match(V);
return false;
}
};
-template<typename T>
-inline Exact_match<T> m_Exact(const T &SubPattern) { return SubPattern; }
+template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
+ return SubPattern;
+}
//===----------------------------------------------------------------------===//
// Matchers for CmpInst classes
//
-template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
+template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy>
struct CmpClass_match {
PredicateTy &Predicate;
LHS_t L;
RHS_t R;
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
- : Predicate(Pred), L(LHS), R(RHS) {}
+ : Predicate(Pred), L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
if (Class *I = dyn_cast<Class>(V))
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
Predicate = I->getPredicate();
@@ -677,123 +712,114 @@ struct CmpClass_match {
}
};
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
+inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
+m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+}
+
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
}
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS,
- FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+ return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
}
//===----------------------------------------------------------------------===//
// Matchers for SelectInst classes
//
-template<typename Cond_t, typename LHS_t, typename RHS_t>
+template <typename Cond_t, typename LHS_t, typename RHS_t>
struct SelectClass_match {
Cond_t C;
LHS_t L;
RHS_t R;
- SelectClass_match(const Cond_t &Cond, const LHS_t &LHS,
- const RHS_t &RHS)
- : C(Cond), L(LHS), R(RHS) {}
+ SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS)
+ : C(Cond), L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (SelectInst *I = dyn_cast<SelectInst>(V))
- return C.match(I->getOperand(0)) &&
- L.match(I->getOperand(1)) &&
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *I = dyn_cast<SelectInst>(V))
+ return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) &&
R.match(I->getOperand(2));
return false;
}
};
-template<typename Cond, typename LHS, typename RHS>
-inline SelectClass_match<Cond, LHS, RHS>
-m_Select(const Cond &C, const LHS &L, const RHS &R) {
+template <typename Cond, typename LHS, typename RHS>
+inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L,
+ const RHS &R) {
return SelectClass_match<Cond, LHS, RHS>(C, L, R);
}
-/// m_SelectCst - This matches a select of two constants, e.g.:
-/// m_SelectCst<-1, 0>(m_Value(V))
-template<int64_t L, int64_t R, typename Cond>
-inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> >
+/// \brief This matches a select of two constants, e.g.:
+/// m_SelectCst<-1, 0>(m_Value(V))
+template <int64_t L, int64_t R, typename Cond>
+inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R>>
m_SelectCst(const Cond &C) {
return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>());
}
-
//===----------------------------------------------------------------------===//
// Matchers for CastInst classes
//
-template<typename Op_t, unsigned Opcode>
-struct CastClass_match {
+template <typename Op_t, unsigned Opcode> struct CastClass_match {
Op_t Op;
CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
return O->getOpcode() == Opcode && Op.match(O->getOperand(0));
return false;
}
};
-/// m_BitCast
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::BitCast>
-m_BitCast(const OpTy &Op) {
+/// \brief Matches BitCast.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::BitCast>(Op);
}
-/// m_PtrToInt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::PtrToInt>
-m_PtrToInt(const OpTy &Op) {
+/// \brief Matches PtrToInt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::PtrToInt>(Op);
}
-/// m_Trunc
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::Trunc>
-m_Trunc(const OpTy &Op) {
+/// \brief Matches Trunc.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::Trunc>(Op);
}
-/// m_SExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SExt>
-m_SExt(const OpTy &Op) {
+/// \brief Matches SExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SExt>(Op);
}
-/// m_ZExt
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::ZExt>
-m_ZExt(const OpTy &Op) {
+/// \brief Matches ZExt.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::ZExt>(Op);
}
-/// m_UIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::UIToFP>
-m_UIToFP(const OpTy &Op) {
+/// \brief Matches UIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::UIToFP>(Op);
}
-/// m_SIToFP
-template<typename OpTy>
-inline CastClass_match<OpTy, Instruction::SIToFP>
-m_SIToFP(const OpTy &Op) {
+/// \brief Matches SIToFP.
+template <typename OpTy>
+inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) {
return CastClass_match<OpTy, Instruction::SIToFP>(Op);
}
@@ -801,46 +827,41 @@ m_SIToFP(const OpTy &Op) {
// Matchers for unary operators
//
-template<typename LHS_t>
-struct not_match {
+template <typename LHS_t> struct not_match {
LHS_t L;
not_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::Xor)
return matchIfNot(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfNot(Value *LHS, Value *RHS) {
return (isa<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) ||
// FIXME: Remove CV.
isa<ConstantVector>(RHS)) &&
- cast<Constant>(RHS)->isAllOnesValue() &&
- L.match(LHS);
+ cast<Constant>(RHS)->isAllOnesValue() && L.match(LHS);
}
};
-template<typename LHS>
-inline not_match<LHS> m_Not(const LHS &L) { return L; }
+template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; }
-
-template<typename LHS_t>
-struct neg_match {
+template <typename LHS_t> struct neg_match {
LHS_t L;
neg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::Sub)
return matchIfNeg(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfNeg(Value *LHS, Value *RHS) {
return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) ||
@@ -849,36 +870,33 @@ private:
}
};
-/// m_Neg - Match an integer negate.
-template<typename LHS>
-inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-
+/// \brief Match an integer negate.
+template <typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
-template<typename LHS_t>
-struct fneg_match {
+template <typename LHS_t> struct fneg_match {
LHS_t L;
fneg_match(const LHS_t &LHS) : L(LHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (Operator *O = dyn_cast<Operator>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *O = dyn_cast<Operator>(V))
if (O->getOpcode() == Instruction::FSub)
return matchIfFNeg(O->getOperand(0), O->getOperand(1));
return false;
}
+
private:
bool matchIfFNeg(Value *LHS, Value *RHS) {
- if (ConstantFP *C = dyn_cast<ConstantFP>(LHS))
+ if (const auto *C = dyn_cast<ConstantFP>(LHS))
return C->isNegativeZeroValue() && L.match(RHS);
return false;
}
};
-/// m_FNeg - Match a floating point negate.
-template<typename LHS>
-inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
-
+/// \brief Match a floating point negate.
+template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) {
+ return L;
+}
//===----------------------------------------------------------------------===//
// Matchers for control flow.
@@ -886,13 +904,10 @@ inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
struct br_match {
BasicBlock *&Succ;
- br_match(BasicBlock *&Succ)
- : Succ(Succ) {
- }
+ br_match(BasicBlock *&Succ) : Succ(Succ) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(V))
if (BI->isUnconditional()) {
Succ = BI->getSuccessor(0);
return true;
@@ -903,17 +918,14 @@ struct br_match {
inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); }
-template<typename Cond_t>
-struct brc_match {
+template <typename Cond_t> struct brc_match {
Cond_t Cond;
BasicBlock *&T, *&F;
brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f)
- : Cond(C), T(t), F(f) {
- }
+ : Cond(C), T(t), F(f) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- if (BranchInst *BI = dyn_cast<BranchInst>(V))
+ template <typename OpTy> bool match(OpTy *V) {
+ if (auto *BI = dyn_cast<BranchInst>(V))
if (BI->isConditional() && Cond.match(BI->getCondition())) {
T = BI->getSuccessor(0);
F = BI->getSuccessor(1);
@@ -923,31 +935,28 @@ struct brc_match {
}
};
-template<typename Cond_t>
+template <typename Cond_t>
inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) {
return brc_match<Cond_t>(C, T, F);
}
-
//===----------------------------------------------------------------------===//
// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y).
//
-template<typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
+template <typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t>
struct MaxMin_match {
LHS_t L;
RHS_t R;
- MaxMin_match(const LHS_t &LHS, const RHS_t &RHS)
- : L(LHS), R(RHS) {}
+ MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
// Look for "(x pred y) ? x : y" or "(x pred y) ? y : x".
- SelectInst *SI = dyn_cast<SelectInst>(V);
+ auto *SI = dyn_cast<SelectInst>(V);
if (!SI)
return false;
- CmpInst_t *Cmp = dyn_cast<CmpInst_t>(SI->getCondition());
+ auto *Cmp = dyn_cast<CmpInst_t>(SI->getCondition());
if (!Cmp)
return false;
// At this point we have a select conditioned on a comparison. Check that
@@ -959,8 +968,8 @@ struct MaxMin_match {
if ((TrueVal != LHS || FalseVal != RHS) &&
(TrueVal != RHS || FalseVal != LHS))
return false;
- typename CmpInst_t::Predicate Pred = LHS == TrueVal ?
- Cmp->getPredicate() : Cmp->getSwappedPredicate();
+ typename CmpInst_t::Predicate Pred =
+ LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate();
// Does "(x pred y) ? x : y" represent the desired max/min operation?
if (!Pred_t::match(Pred))
return false;
@@ -969,83 +978,83 @@ struct MaxMin_match {
}
};
-/// smax_pred_ty - Helper class for identifying signed max predicates.
+/// \brief Helper class for identifying signed max predicates.
struct smax_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE;
}
};
-/// smin_pred_ty - Helper class for identifying signed min predicates.
+/// \brief Helper class for identifying signed min predicates.
struct smin_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE;
}
};
-/// umax_pred_ty - Helper class for identifying unsigned max predicates.
+/// \brief Helper class for identifying unsigned max predicates.
struct umax_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE;
}
};
-/// umin_pred_ty - Helper class for identifying unsigned min predicates.
+/// \brief Helper class for identifying unsigned min predicates.
struct umin_pred_ty {
static bool match(ICmpInst::Predicate Pred) {
return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE;
}
};
-/// ofmax_pred_ty - Helper class for identifying ordered max predicates.
+/// \brief Helper class for identifying ordered max predicates.
struct ofmax_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE;
}
};
-/// ofmin_pred_ty - Helper class for identifying ordered min predicates.
+/// \brief Helper class for identifying ordered min predicates.
struct ofmin_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE;
}
};
-/// ufmax_pred_ty - Helper class for identifying unordered max predicates.
+/// \brief Helper class for identifying unordered max predicates.
struct ufmax_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE;
}
};
-/// ufmin_pred_ty - Helper class for identifying unordered min predicates.
+/// \brief Helper class for identifying unordered min predicates.
struct ufmin_pred_ty {
static bool match(FCmpInst::Predicate Pred) {
return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE;
}
};
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>
-m_SMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> m_SMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>
-m_SMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> m_SMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>
-m_UMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> m_UMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>(L, R);
}
-template<typename LHS, typename RHS>
-inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>
-m_UMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R);
}
@@ -1058,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_OrdFMax(L, R) = R iff L or R are NaN
-template<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>
-m_OrdFMax(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R);
}
@@ -1073,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_OrdFMin(L, R) = R iff L or R are NaN
-template<typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>
-m_OrdFMin(const LHS &L, const RHS &R) {
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
+ const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R);
}
@@ -1088,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_UnordFMin(L, R) = L iff L or R are NaN
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>
m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
@@ -1103,40 +1112,39 @@ m_UnordFMax(const LHS &L, const RHS &R) {
///
/// max(L, R) iff L and R are not NaN
/// m_UnordFMin(L, R) = L iff L or R are NaN
-template<typename LHS, typename RHS>
+template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
m_UnordFMin(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
}
-template<typename Opnd_t>
-struct Argument_match {
+template <typename Opnd_t> struct Argument_match {
unsigned OpI;
Opnd_t Val;
- Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { }
+ Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {}
- template<typename OpTy>
- bool match(OpTy *V) {
+ template <typename OpTy> bool match(OpTy *V) {
CallSite CS(V);
return CS.isCall() && Val.match(CS.getArgument(OpI));
}
};
-/// Match an argument
-template<unsigned OpI, typename Opnd_t>
+/// \brief Match an argument.
+template <unsigned OpI, typename Opnd_t>
inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) {
return Argument_match<Opnd_t>(OpI, Op);
}
-/// Intrinsic matchers.
+/// \brief Intrinsic matchers.
struct IntrinsicID_match {
unsigned ID;
- IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { }
+ IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {}
- template<typename OpTy>
- bool match(OpTy *V) {
- IntrinsicInst *II = dyn_cast<IntrinsicInst>(V);
- return II && II->getIntrinsicID() == ID;
+ template <typename OpTy> bool match(OpTy *V) {
+ if (const auto *CI = dyn_cast<CallInst>(V))
+ if (const auto *F = CI->getCalledFunction())
+ return F->getIntrinsicID() == ID;
+ return false;
}
};
@@ -1147,64 +1155,74 @@ struct IntrinsicID_match {
template <typename T0 = void, typename T1 = void, typename T2 = void,
typename T3 = void, typename T4 = void, typename T5 = void,
typename T6 = void, typename T7 = void, typename T8 = void,
- typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty;
-template <typename T0>
-struct m_Intrinsic_Ty<T0> {
- typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty;
+ typename T9 = void, typename T10 = void>
+struct m_Intrinsic_Ty;
+template <typename T0> struct m_Intrinsic_Ty<T0> {
+ typedef match_combine_and<IntrinsicID_match, Argument_match<T0>> Ty;
};
-template <typename T0, typename T1>
-struct m_Intrinsic_Ty<T0, T1> {
- typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty,
- Argument_match<T1> > Ty;
+template <typename T0, typename T1> struct m_Intrinsic_Ty<T0, T1> {
+ typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, Argument_match<T1>>
+ Ty;
};
template <typename T0, typename T1, typename T2>
struct m_Intrinsic_Ty<T0, T1, T2> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty,
- Argument_match<T2> > Ty;
+ Argument_match<T2>> Ty;
};
template <typename T0, typename T1, typename T2, typename T3>
struct m_Intrinsic_Ty<T0, T1, T2, T3> {
typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty,
- Argument_match<T3> > Ty;
+ Argument_match<T3>> Ty;
};
-/// Match intrinsic calls like this:
-/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
-template <Intrinsic::ID IntrID>
-inline IntrinsicID_match
-m_Intrinsic() { return IntrinsicID_match(IntrID); }
+/// \brief Match intrinsic calls like this:
+/// m_Intrinsic<Intrinsic::fabs>(m_Value(X))
+template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() {
+ return IntrinsicID_match(IntrID);
+}
-template<Intrinsic::ID IntrID, typename T0>
-inline typename m_Intrinsic_Ty<T0>::Ty
-m_Intrinsic(const T0 &Op0) {
+template <Intrinsic::ID IntrID, typename T0>
+inline typename m_Intrinsic_Ty<T0>::Ty m_Intrinsic(const T0 &Op0) {
return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1>
-inline typename m_Intrinsic_Ty<T0, T1>::Ty
-m_Intrinsic(const T0 &Op0, const T1 &Op1) {
+template <Intrinsic::ID IntrID, typename T0, typename T1>
+inline typename m_Intrinsic_Ty<T0, T1>::Ty m_Intrinsic(const T0 &Op0,
+ const T1 &Op1) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2>
inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2));
}
-template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3>
+template <Intrinsic::ID IntrID, typename T0, typename T1, typename T2,
+ typename T3>
inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty
m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) {
return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3));
}
-// Helper intrinsic matching specializations
-template<typename Opnd0>
-inline typename m_Intrinsic_Ty<Opnd0>::Ty
-m_BSwap(const Opnd0 &Op0) {
+// Helper intrinsic matching specializations.
+template <typename Opnd0>
+inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) {
return m_Intrinsic<Intrinsic::bswap>(Op0);
}
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
+ return m_Intrinsic<Intrinsic::minnum>(Op0, Op1);
+}
+
+template <typename Opnd0, typename Opnd1>
+inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0,
+ const Opnd1 &Op1) {
+ return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1);
+}
+
} // end namespace PatternMatch
} // end namespace llvm
diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h
index 02bc583a255a..5e1be37805ff 100644
--- a/include/llvm/IR/PredIteratorCache.h
+++ b/include/llvm/IR/PredIteratorCache.h
@@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_IR_PREDITERATORCACHE_H
+#define LLVM_IR_PREDITERATORCACHE_H
+
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/CFG.h"
#include "llvm/Support/Allocator.h"
-#ifndef LLVM_IR_PREDITERATORCACHE_H
-#define LLVM_IR_PREDITERATORCACHE_H
-
namespace llvm {
/// PredIteratorCache - This class is an extremely trivial cache for
diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h
new file mode 100644
index 000000000000..e3c4243e9d81
--- /dev/null
+++ b/include/llvm/IR/Statepoint.h
@@ -0,0 +1,215 @@
+//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions and a wrapper class analogous to
+// CallSite for accessing the fields of gc.statepoint, gc.relocate, and
+// gc.result intrinsics
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_IR_STATEPOINT_H
+#define __LLVM_IR_STATEPOINT_H
+
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+bool isStatepoint(const ImmutableCallSite &CS);
+bool isStatepoint(const Instruction *inst);
+bool isStatepoint(const Instruction &inst);
+
+bool isGCRelocate(const Instruction *inst);
+bool isGCRelocate(const ImmutableCallSite &CS);
+
+bool isGCResult(const Instruction *inst);
+bool isGCResult(const ImmutableCallSite &CS);
+
+/// Analogous to CallSiteBase, this provides most of the actual
+/// functionality for Statepoint and ImmutableStatepoint. It is
+/// templatized to allow easily specializing of const and non-const
+/// concrete subtypes. This is structured analogous to CallSite
+/// rather than the IntrinsicInst.h helpers since we want to support
+/// invokable statepoints in the near future.
+/// TODO: This does not currently allow the if(Statepoint S = ...)
+/// idiom used with CallSites. Consider refactoring to support.
+template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+class StatepointBase {
+ CallSiteTy StatepointCS;
+ void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
+ void *operator new(size_t s) LLVM_DELETED_FUNCTION;
+
+ protected:
+ explicit StatepointBase(InstructionTy *I) : StatepointCS(I) {
+ assert(isStatepoint(I));
+ }
+ explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) {
+ assert(isStatepoint(CS));
+ }
+
+ public:
+ typedef typename CallSiteTy::arg_iterator arg_iterator;
+
+ /// Return the underlying CallSite.
+ CallSiteTy getCallSite() {
+ return StatepointCS;
+ }
+
+ /// Return the value actually being called or invoked.
+ ValueTy *actualCallee() {
+ return StatepointCS.getArgument(0);
+ }
+ /// Number of arguments to be passed to the actual callee.
+ int numCallArgs() {
+ return cast<ConstantInt>(StatepointCS.getArgument(1))->getZExtValue();
+ }
+ /// Number of additional arguments excluding those intended
+ /// for garbage collection.
+ int numTotalVMSArgs() {
+ return cast<ConstantInt>(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue();
+ }
+
+ typename CallSiteTy::arg_iterator call_args_begin() {
+ // 3 = callTarget, #callArgs, flag
+ int Offset = 3;
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+ typename CallSiteTy::arg_iterator call_args_end() {
+ int Offset = 3 + numCallArgs();
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+
+ /// range adapter for call arguments
+ iterator_range<arg_iterator> call_args() {
+ return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
+ }
+
+ typename CallSiteTy::arg_iterator vm_state_begin() {
+ return call_args_end();
+ }
+ typename CallSiteTy::arg_iterator vm_state_end() {
+ int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs();
+ assert(Offset <= (int)StatepointCS.arg_size());
+ return StatepointCS.arg_begin() + Offset;
+ }
+
+ /// range adapter for vm state arguments
+ iterator_range<arg_iterator> vm_state_args() {
+ return iterator_range<arg_iterator>(vm_state_begin(), vm_state_end());
+ }
+
+ typename CallSiteTy::arg_iterator first_vm_state_stack_begin() {
+ // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci,
+ // 1st_#stack, 1st_#local, 1st_#monitor
+ return vm_state_begin() + 6;
+ }
+
+ typename CallSiteTy::arg_iterator gc_args_begin() {
+ return vm_state_end();
+ }
+ typename CallSiteTy::arg_iterator gc_args_end() {
+ return StatepointCS.arg_end();
+ }
+
+ /// range adapter for gc arguments
+ iterator_range<arg_iterator> gc_args() {
+ return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
+ }
+
+
+#ifndef NDEBUG
+ /// Asserts if this statepoint is malformed. Common cases for failure
+ /// include incorrect length prefixes for variable length sections or
+ /// illegal values for parameters.
+ void verify() {
+ assert(numCallArgs() >= 0 &&
+ "number of arguments to actually callee can't be negative");
+
+ // The internal asserts in the iterator accessors do the rest.
+ (void)call_args_begin();
+ (void)call_args_end();
+ (void)vm_state_begin();
+ (void)vm_state_end();
+ (void)gc_args_begin();
+ (void)gc_args_end();
+ }
+#endif
+};
+
+/// A specialization of it's base class for read only access
+/// to a gc.statepoint.
+class ImmutableStatepoint
+ : public StatepointBase<const Instruction, const Value,
+ ImmutableCallSite> {
+ typedef StatepointBase<const Instruction, const Value, ImmutableCallSite>
+ Base;
+
+public:
+ explicit ImmutableStatepoint(const Instruction *I) : Base(I) {}
+ explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {}
+};
+
+/// A specialization of it's base class for read-write access
+/// to a gc.statepoint.
+class Statepoint : public StatepointBase<Instruction, Value, CallSite> {
+ typedef StatepointBase<Instruction, Value, CallSite> Base;
+
+public:
+ explicit Statepoint(Instruction *I) : Base(I) {}
+ explicit Statepoint(CallSite CS) : Base(CS) {}
+};
+
+/// Wraps a call to a gc.relocate and provides access to it's operands.
+/// TODO: This should likely be refactored to resememble the wrappers in
+/// InstrinsicInst.h.
+class GCRelocateOperands {
+ ImmutableCallSite RelocateCS;
+
+ public:
+ GCRelocateOperands(const User* U) : RelocateCS(U) {
+ assert(isGCRelocate(U));
+ }
+ GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) {
+ assert(isGCRelocate(inst));
+ }
+ GCRelocateOperands(CallSite CS) : RelocateCS(CS) {
+ assert(isGCRelocate(CS));
+ }
+
+ /// The statepoint with which this gc.relocate is associated.
+ const Instruction *statepoint() {
+ return cast<Instruction>(RelocateCS.getArgument(0));
+ }
+ /// The index into the associate statepoint's argument list
+ /// which contains the base pointer of the pointer whose
+ /// relocation this gc.relocate describes.
+ int basePtrIndex() {
+ return cast<ConstantInt>(RelocateCS.getArgument(1))->getZExtValue();
+ }
+ /// The index into the associate statepoint's argument list which
+ /// contains the pointer whose relocation this gc.relocate describes.
+ int derivedPtrIndex() {
+ return cast<ConstantInt>(RelocateCS.getArgument(2))->getZExtValue();
+ }
+ Value *basePtr() {
+ ImmutableCallSite CS(statepoint());
+ return *(CS.arg_begin() + basePtrIndex());
+ }
+ Value *derivedPtr() {
+ ImmutableCallSite CS(statepoint());
+ return *(CS.arg_begin() + derivedPtrIndex());
+ }
+};
+}
+#endif
diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h
new file mode 100644
index 000000000000..e24112154e16
--- /dev/null
+++ b/include/llvm/IR/TrackingMDRef.h
@@ -0,0 +1,170 @@
+//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// References to metadata that track RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_TRACKINGMDREF_H
+#define LLVM_IR_TRACKINGMDREF_H
+
+#include "llvm/IR/MetadataTracking.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+
+class Metadata;
+class MDNode;
+class ValueAsMetadata;
+
+/// \brief Tracking metadata reference.
+///
+/// This class behaves like \a TrackingVH, but for metadata.
+class TrackingMDRef {
+ Metadata *MD;
+
+public:
+ TrackingMDRef() : MD(nullptr) {}
+ 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;
+
+ untrack();
+ MD = X.MD;
+ retrack(X);
+ return *this;
+ }
+ TrackingMDRef &operator=(const TrackingMDRef &X) {
+ if (&X == this)
+ return *this;
+
+ untrack();
+ MD = X.MD;
+ track();
+ return *this;
+ }
+ ~TrackingMDRef() { untrack(); }
+
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD) {
+ untrack();
+ this->MD = MD;
+ track();
+ }
+
+ /// \brief Check whether this has a trivial destructor.
+ ///
+ /// If \c MD isn't replaceable, the destructor will be a no-op.
+ bool hasTrivialDestructor() const {
+ return !MD || !MetadataTracking::isReplaceable(*MD);
+ }
+
+ bool operator==(const TrackingMDRef &X) const { return MD == X.MD; }
+ bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; }
+
+private:
+ void track() {
+ 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) {
+ MetadataTracking::retrack(X.MD, MD);
+ X.MD = nullptr;
+ }
+ }
+};
+
+/// \brief Typed tracking ref.
+///
+/// Track refererences of a particular type. It's useful to use this for \a
+/// MDNode and \a ValueAsMetadata.
+template <class T> class TypedTrackingMDRef {
+ TrackingMDRef Ref;
+
+public:
+ TypedTrackingMDRef() {}
+ 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;
+ }
+
+ T *get() const { return (T *)Ref.get(); }
+ operator T *() const { return get(); }
+ T *operator->() const { return get(); }
+ T &operator*() const { return *get(); }
+
+ bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; }
+ bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; }
+
+ void reset() { Ref.reset(); }
+ void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
+
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
+};
+
+typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
+typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
+
+// Expose the underlying metadata to casting.
+template <> struct simplify_type<TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h
index 7955587e3c76..c2073c7750b2 100644
--- a/include/llvm/IR/Type.h
+++ b/include/llvm/IR/Type.h
@@ -265,7 +265,7 @@ public:
/// get the actual size for a particular target, it is reasonable to use the
/// DataLayout subsystem to do this.
///
- bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const {
+ bool isSized(SmallPtrSetImpl<const Type*> *Visited = nullptr) const {
// If it's a primitive, it is always sized.
if (getTypeID() == IntegerTyID || isFloatingPointTy() ||
getTypeID() == PointerTyID ||
@@ -313,6 +313,9 @@ public:
typedef Type * const *subtype_iterator;
subtype_iterator subtype_begin() const { return ContainedTys; }
subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];}
+ ArrayRef<Type*> subtypes() const {
+ return makeArrayRef(subtype_begin(), subtype_end());
+ }
typedef std::reverse_iterator<subtype_iterator> subtype_reverse_iterator;
subtype_reverse_iterator subtype_rbegin() const {
@@ -323,7 +326,7 @@ public:
}
/// getContainedType - This method is used to implement the type iterator
- /// (defined a the end of the file). For derived types, this returns the
+ /// (defined at the end of the file). For derived types, this returns the
/// types 'contained' in the derived type.
///
Type *getContainedType(unsigned i) const {
@@ -419,7 +422,7 @@ private:
/// isSizedDerivedType - Derived types like structures and arrays are sized
/// iff all of the members of the type are sized as well. Since asking for
/// their size is relatively uncommon, move this operation out of line.
- bool isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited = nullptr) const;
+ bool isSizedDerivedType(SmallPtrSetImpl<const Type*> *Visited = nullptr) const;
};
// Printing of types.
diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h
index cea66a4ab069..73a63ad0349e 100644
--- a/include/llvm/IR/TypeFinder.h
+++ b/include/llvm/IR/TypeFinder.h
@@ -31,6 +31,7 @@ class TypeFinder {
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
+ DenseSet<const MDNode *> VisitedMetadata;
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> StructTypes;
diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h
new file mode 100644
index 000000000000..5df459b1bd30
--- /dev/null
+++ b/include/llvm/IR/UseListOrder.h
@@ -0,0 +1,62 @@
+//===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file has structures and command-line options for preserving use-list
+// order.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_USELISTORDER_H
+#define LLVM_IR_USELISTORDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include <vector>
+
+namespace llvm {
+
+class Module;
+class Function;
+class Value;
+
+/// \brief Structure to hold a use-list order.
+struct UseListOrder {
+ const Value *V;
+ const Function *F;
+ std::vector<unsigned> Shuffle;
+
+ UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
+ : V(V), F(F), Shuffle(ShuffleSize) {}
+
+ UseListOrder() : V(0), F(0) {}
+ UseListOrder(UseListOrder &&X)
+ : V(X.V), F(X.F), Shuffle(std::move(X.Shuffle)) {}
+ UseListOrder &operator=(UseListOrder &&X) {
+ V = X.V;
+ F = X.F;
+ Shuffle = std::move(X.Shuffle);
+ return *this;
+ }
+
+private:
+ UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION;
+ UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION;
+};
+
+typedef std::vector<UseListOrder> UseListOrderStack;
+
+/// \brief Whether to preserve use-list ordering.
+bool shouldPreserveBitcodeUseListOrder();
+bool shouldPreserveAssemblyUseListOrder();
+void setPreserveBitcodeUseListOrder(bool ShouldPreserve);
+void setPreserveAssemblyUseListOrder(bool ShouldPreserve);
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h
index 848adae9ceca..f578227d6cae 100644
--- a/include/llvm/IR/User.h
+++ b/include/llvm/IR/User.h
@@ -26,9 +26,9 @@
namespace llvm {
-/// OperandTraits - Compile-time customization of
-/// operand-related allocators and accessors
-/// for use of the User class
+/// \brief Compile-time customization of User operands.
+///
+/// Customizes operand-related allocators and accessors.
template <class>
struct OperandTraits;
@@ -39,11 +39,8 @@ class User : public Value {
friend struct HungoffOperandTraits;
virtual void anchor();
protected:
- /// NumOperands - The number of values used by this User.
+ /// \brief This is a pointer to the array of Uses for this User.
///
- unsigned NumOperands;
-
- /// OperandList - This is a pointer to the array of Uses for this User.
/// For nodes of fixed arity (e.g. a binary operator) this array will live
/// prefixed to some derived class instance. For nodes of resizable variable
/// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically
@@ -52,7 +49,9 @@ protected:
void *operator new(size_t s, unsigned Us);
User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
- : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {}
+ : Value(ty, vty), OperandList(OpList) {
+ NumOperands = NumOps;
+ }
Use *allocHungoffUses(unsigned) const;
void dropHungoffUses() {
Use::zap(OperandList, OperandList + NumOperands, true);
@@ -64,13 +63,13 @@ public:
~User() {
Use::zap(OperandList, OperandList + NumOperands);
}
- /// operator delete - free memory allocated for User and Use objects
+ /// \brief Free memory allocated for User and Use objects.
void operator delete(void *Usr);
- /// placement delete - required by std, but never called.
+ /// \brief Placement delete - required by std, but never called.
void operator delete(void*, unsigned) {
llvm_unreachable("Constructor throws?");
}
- /// placement delete - required by std, but never called.
+ /// \brief Placement delete - required by std, but never called.
void operator delete(void*, unsigned, bool) {
llvm_unreachable("Constructor throws?");
}
@@ -128,8 +127,7 @@ public:
return const_op_range(op_begin(), op_end());
}
- /// Convenience iterator for directly iterating over the Values in the
- /// OperandList
+ /// \brief Iterator for directly iterating over the operand Values.
struct value_op_iterator
: iterator_adaptor_base<value_op_iterator, op_iterator,
std::random_access_iterator_tag, Value *,
@@ -150,22 +148,23 @@ public:
return iterator_range<value_op_iterator>(value_op_begin(), value_op_end());
}
- // dropAllReferences() - This function is in charge of "letting go" of all
- // objects that this User refers to. This allows one to
- // 'delete' a whole class at a time, even though there may be circular
- // references... First all references are dropped, and all use counts go to
- // zero. Then everything is deleted for real. Note that no operations are
- // valid on an object that has "dropped all references", except operator
- // delete.
- //
+ /// \brief Drop all references to operands.
+ ///
+ /// This function is in charge of "letting go" of all objects that this User
+ /// refers to. This allows one to 'delete' a whole class at a time, even
+ /// though there may be circular references... First all references are
+ /// dropped, and all use counts go to zero. Then everything is deleted for
+ /// real. Note that no operations are valid on an object that has "dropped
+ /// all references", except operator delete.
void dropAllReferences() {
for (Use &U : operands())
U.set(nullptr);
}
- /// replaceUsesOfWith - Replaces all references to the "From" definition with
- /// references to the "To" definition.
+ /// \brief Replace uses of one Value with another.
///
+ /// Replaces all references to the "From" definition with references to the
+ /// "To" definition.
void replaceUsesOfWith(Value *From, Value *To);
// Methods for support type inquiry through isa, cast, and dyn_cast:
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index b5bbc96eac2a..705fc0f52d58 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -37,7 +37,6 @@ class GlobalVariable;
class InlineAsm;
class Instruction;
class LLVMContext;
-class MDNode;
class Module;
class StringRef;
class Twine;
@@ -53,6 +52,8 @@ typedef StringMapEntry<Value*> ValueName;
// Value Class
//===----------------------------------------------------------------------===//
+/// \brief LLVM Value Representation
+///
/// This is a very important LLVM class. It is the base class of all values
/// computed by a program that may be used as operands to other values. Value is
/// the super class of other important classes such as Instruction and Function.
@@ -64,31 +65,45 @@ typedef StringMapEntry<Value*> ValueName;
/// using this Value. A Value can also have an arbitrary number of ValueHandle
/// objects that watch it and listen to RAUW and Destroy events. See
/// llvm/IR/ValueHandle.h for details.
-///
-/// @brief LLVM Value Representation
class Value {
Type *VTy;
Use *UseList;
- friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name.
+ friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD.
friend class ValueHandleBase;
- ValueName *Name;
+ PointerIntPair<ValueName *, 1> NameAndIsUsedByMD;
const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
protected:
- /// SubclassOptionalData - This member is similar to SubclassData, however it
- /// is for holding information which may be used to aid optimization, but
- /// which may be cleared to zero without affecting conservative
- /// interpretation.
+ /// \brief Hold subclass data that can be dropped.
+ ///
+ /// This member is similar to SubclassData, however it is for holding
+ /// information which may be used to aid optimization, but which may be
+ /// cleared to zero without affecting conservative interpretation.
unsigned char SubclassOptionalData : 7;
private:
- /// SubclassData - This member is defined by this class, but is not used for
- /// anything. Subclasses can use it to hold whatever state they find useful.
- /// This field is initialized to zero by the ctor.
+ /// \brief Hold arbitrary subclass data.
+ ///
+ /// This member is defined by this class, but is not used for anything.
+ /// Subclasses can use it to hold whatever state they find useful. This
+ /// field is initialized to zero by the ctor.
unsigned short SubclassData;
+protected:
+ /// \brief The number of operands in the subclass.
+ ///
+ /// This member is defined by this class, but not used for anything.
+ /// Subclasses can use it to store their number of operands, if they have
+ /// any.
+ ///
+ /// This is stored here to save space in User on 64-bit hosts. Since most
+ /// instances of Value have operands, 32-bit hosts aren't significantly
+ /// affected.
+ unsigned NumOperands;
+
+private:
template <typename UseT> // UseT == 'Use' or 'const Use'
class use_iterator_impl
: public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> {
@@ -175,6 +190,7 @@ private:
Use &getUse() const { return *UI; }
/// \brief Return the operand # of this use in its User.
+ ///
/// FIXME: Replace all callers with a direct call to Use::getOperandNo.
unsigned getOperandNo() const { return UI->getOperandNo(); }
};
@@ -187,15 +203,14 @@ protected:
public:
virtual ~Value();
- /// dump - Support for debugging, callable in GDB: V->dump()
- //
+ /// \brief Support for debugging, callable in GDB: V->dump()
void dump() const;
- /// print - Implement operator<< on Value.
- ///
+ /// \brief Implement operator<< on Value.
void print(raw_ostream &O) const;
/// \brief Print the name of this Value out to the specified raw_ostream.
+ ///
/// This is useful when you just want to print 'int %reg126', not the
/// instruction that generated it. If you specify a Module for context, then
/// even constanst get pretty-printed; for example, the type of a null
@@ -203,40 +218,56 @@ public:
void printAsOperand(raw_ostream &O, bool PrintType = true,
const Module *M = nullptr) const;
- /// All values are typed, get the type of this value.
- ///
+ /// \brief All values are typed, get the type of this value.
Type *getType() const { return VTy; }
- /// All values hold a context through their type.
+ /// \brief All values hold a context through their type.
LLVMContext &getContext() const;
- // All values can potentially be named.
- bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; }
- ValueName *getValueName() const { return Name; }
- void setValueName(ValueName *VN) { Name = VN; }
+ // \brief All values can potentially be named.
+ bool hasName() const { return getValueName() != nullptr; }
+ ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); }
+ void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); }
- /// getName() - Return a constant reference to the value's name. This is cheap
- /// and guaranteed to return the same reference as long as the value is not
- /// modified.
+private:
+ void destroyValueName();
+
+public:
+ /// \brief Return a constant reference to the value's name.
+ ///
+ /// This is cheap and guaranteed to return the same reference as long as the
+ /// value is not modified.
StringRef getName() const;
- /// setName() - Change the name of the value, choosing a new unique name if
- /// the provided name is taken.
+ /// \brief Change the name of the value.
+ ///
+ /// Choose a new unique name if the provided name is taken.
///
/// \param Name The new name; or "" if the value's name should be removed.
void setName(const Twine &Name);
- /// takeName - transfer the name from V to this value, setting V's name to
- /// empty. It is an error to call V->takeName(V).
+ /// \brief Transfer the name from V to this value.
+ ///
+ /// After taking V's name, sets V's name to empty.
+ ///
+ /// \note It is an error to call V->takeName(V).
void takeName(Value *V);
- /// replaceAllUsesWith - Go through the uses list for this definition and make
- /// each use point to "V" instead of "this". After this completes, 'this's
- /// use list is guaranteed to be empty.
+ /// \brief Change all uses of this to point to a new Value.
///
+ /// Go through the uses list for this definition and make each use point to
+ /// "V" instead of "this". After this completes, 'this's use list is
+ /// guaranteed to be empty.
void replaceAllUsesWith(Value *V);
+ /// replaceUsesOutsideBlock - Go through the uses list for this definition and
+ /// make each use point to "V" instead of "this" when the use is outside the
+ /// block. 'This's use list is expected to have at least one element.
+ /// Unlike replaceAllUsesWith this function does not support basic block
+ /// values or constant users.
+ void replaceUsesOutsideBlock(Value *V, BasicBlock *BB);
+
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
@@ -255,6 +286,8 @@ public:
return iterator_range<const_use_iterator>(use_begin(), use_end());
}
+ bool user_empty() const { return UseList == nullptr; }
+
typedef user_iterator_impl<User> user_iterator;
typedef user_iterator_impl<const User> const_user_iterator;
user_iterator user_begin() { return user_iterator(UseList); }
@@ -270,36 +303,38 @@ public:
return iterator_range<const_user_iterator>(user_begin(), user_end());
}
- /// hasOneUse - Return true if there is exactly one user of this value. This
- /// is specialized because it is a common request and does not require
- /// traversing the whole use list.
+ /// \brief Return true if there is exactly one user of this value.
///
+ /// This is specialized because it is a common request and does not require
+ /// traversing the whole use list.
bool hasOneUse() const {
const_use_iterator I = use_begin(), E = use_end();
if (I == E) return false;
return ++I == E;
}
- /// hasNUses - Return true if this Value has exactly N users.
- ///
+ /// \brief Return true if this Value has exactly N users.
bool hasNUses(unsigned N) const;
- /// hasNUsesOrMore - Return true if this value has N users or more. This is
- /// logically equivalent to getNumUses() >= N.
+ /// \brief Return true if this value has N users or more.
///
+ /// This is logically equivalent to getNumUses() >= N.
bool hasNUsesOrMore(unsigned N) const;
+ /// \brief Check if this value is used in the specified basic block.
bool isUsedInBasicBlock(const BasicBlock *BB) const;
- /// getNumUses - This method computes the number of uses of this Value. This
- /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore
- /// to check for specific values.
+ /// \brief This method computes the number of uses of this Value.
+ ///
+ /// This is a linear time operation. Use hasOneUse, hasNUses, or
+ /// hasNUsesOrMore to check for specific values.
unsigned getNumUses() const;
- /// addUse - This method should only be used by the Use class.
- ///
+ /// \brief This method should only be used by the Use class.
void addUse(Use &U) { U.addToList(&UseList); }
+ /// \brief Concrete subclass of this.
+ ///
/// An enumeration for keeping track of the concrete subclass of Value that
/// is actually instantiated. Values of this enumeration are kept in the
/// Value classes SubclassID field. They are used for concrete type
@@ -322,8 +357,7 @@ public:
ConstantStructVal, // This is an instance of ConstantStruct
ConstantVectorVal, // This is an instance of ConstantVector
ConstantPointerNullVal, // This is an instance of ConstantPointerNull
- MDNodeVal, // This is an instance of MDNode
- MDStringVal, // This is an instance of MDString
+ MetadataAsValueVal, // This is an instance of MetadataAsValue
InlineAsmVal, // This is an instance of InlineAsm
InstructionVal, // This is an instance of Instruction
// Enum values starting at InstructionVal are used for Instructions;
@@ -334,11 +368,12 @@ public:
ConstantLastVal = ConstantPointerNullVal
};
- /// getValueID - Return an ID for the concrete type of this object. This is
- /// used to implement the classof checks. This should not be used for any
- /// other purpose, as the values may change as LLVM evolves. Also, note that
- /// for instructions, the Instruction's opcode is added to InstructionVal. So
- /// this means three things:
+ /// \brief Return an ID for the concrete type of this object.
+ ///
+ /// This is used to implement the classof checks. This should not be used
+ /// for any other purpose, as the values may change as LLVM evolves. Also,
+ /// note that for instructions, the Instruction's opcode is added to
+ /// InstructionVal. So this means three things:
/// # there is no value with code InstructionVal (no opcode==0).
/// # there are more possible values for the value type than in ValueTy enum.
/// # the InstructionVal enumerator must be the highest valued enumerator in
@@ -347,64 +382,62 @@ public:
return SubclassID;
}
- /// getRawSubclassOptionalData - Return the raw optional flags value
- /// contained in this value. This should only be used when testing two
- /// Values for equivalence.
+ /// \brief Return the raw optional flags value contained in this value.
+ ///
+ /// This should only be used when testing two Values for equivalence.
unsigned getRawSubclassOptionalData() const {
return SubclassOptionalData;
}
- /// clearSubclassOptionalData - Clear the optional flags contained in
- /// this value.
+ /// \brief Clear the optional flags contained in this value.
void clearSubclassOptionalData() {
SubclassOptionalData = 0;
}
- /// hasSameSubclassOptionalData - Test whether the optional flags contained
- /// in this value are equal to the optional flags in the given value.
+ /// \brief Check the optional flags for equality.
bool hasSameSubclassOptionalData(const Value *V) const {
return SubclassOptionalData == V->SubclassOptionalData;
}
- /// intersectOptionalDataWith - Clear any optional flags in this value
- /// that are not also set in the given value.
+ /// \brief Clear any optional flags not set in the given Value.
void intersectOptionalDataWith(const Value *V) {
SubclassOptionalData &= V->SubclassOptionalData;
}
- /// hasValueHandle - Return true if there is a value handle associated with
- /// this value.
+ /// \brief Return true if there is a value handle associated with this value.
bool hasValueHandle() const { return HasValueHandle; }
- /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases
- /// from the specified value, returning the original uncasted value.
+ /// \brief Return true if there is metadata referencing this value.
+ bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); }
+
+ /// \brief Strip off pointer casts, all-zero GEPs, and aliases.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// 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();
}
- /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the
- /// specified value, returning the original uncasted value.
+ /// \brief Strip off pointer casts and all-zero GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// 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();
}
- /// \brief Strips off unneeded pointer casts and all-constant GEPs from the
- /// specified value, returning the original pointer value.
+ /// \brief Strip off pointer casts and all-constant inbounds GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// 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();
}
- /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates
- /// the constant offset stripped.
+ /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets().
///
/// Stores the resulting constant offset stripped into the APInt provided.
/// The provided APInt will be extended or truncated as needed to be the
@@ -419,23 +452,27 @@ public:
->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
}
- /// \brief Strips off unneeded pointer casts and any in-bounds offsets from
- /// the specified value, returning the original pointer value.
+ /// \brief Strip off pointer casts and inbounds GEPs.
///
- /// If this is called on a non-pointer value, it returns 'this'.
+ /// 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();
}
- /// isDereferenceablePointer - Test if this value is always a pointer to
- /// allocated and suitably aligned memory for a simple load or store.
+ /// \brief Check if this is always a dereferenceable pointer.
+ ///
+ /// Test if this value is always a pointer to allocated and suitably aligned
+ /// memory for a simple load or store.
bool isDereferenceablePointer(const DataLayout *DL = nullptr) const;
- /// DoPHITranslation - If this value is a PHI node with CurBB as its parent,
- /// return the value in 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.
+ /// \brief Translate PHI node to its predecessor from the given basic block.
+ ///
+ /// If this value is a PHI node with CurBB as its parent, return the value in
+ /// 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,
@@ -443,11 +480,14 @@ public:
return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB);
}
- /// MaximumAlignment - This is the greatest alignment value supported by
- /// load, store, and alloca instructions, and global values.
+ /// \brief The maximum alignment for instructions.
+ ///
+ /// This is the greatest alignment value supported by load, store, and alloca
+ /// instructions, and global values.
static const unsigned MaximumAlignment = 1u << 29;
- /// mutateType - Mutate the type of this Value to be of the specified type.
+ /// \brief Mutate the type of this Value to be of the specified type.
+ ///
/// Note that this is an extremely dangerous operation which can create
/// completely invalid IR very easily. It is strongly recommended that you
/// recreate IR objects with the right types instead of mutating them in
@@ -456,6 +496,37 @@ public:
VTy = Ty;
}
+ /// \brief Sort the use-list.
+ ///
+ /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is
+ /// expected to compare two \a Use references.
+ template <class Compare> void sortUseList(Compare Cmp);
+
+ /// \brief Reverse the use-list.
+ void reverseUseList();
+
+private:
+ /// \brief Merge two lists together.
+ ///
+ /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes
+ /// "equal" items from L before items from R.
+ ///
+ /// \return the first element in the list.
+ ///
+ /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update).
+ template <class Compare>
+ static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) {
+ Use *Merged;
+ mergeUseListsImpl(L, R, &Merged, Cmp);
+ return Merged;
+ }
+
+ /// \brief Tail-recursive helper for \a mergeUseLists().
+ ///
+ /// \param[out] Next the first element in the list.
+ template <class Compare>
+ static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp);
+
protected:
unsigned short getSubclassDataFromValue() const { return SubclassData; }
void setValueSubclassData(unsigned short D) { SubclassData = D; }
@@ -472,6 +543,91 @@ void Use::set(Value *V) {
if (V) V->addUse(*this);
}
+template <class Compare> void Value::sortUseList(Compare Cmp) {
+ if (!UseList || !UseList->Next)
+ // No need to sort 0 or 1 uses.
+ return;
+
+ // Note: this function completely ignores Prev pointers until the end when
+ // they're fixed en masse.
+
+ // Create a binomial vector of sorted lists, visiting uses one at a time and
+ // merging lists as necessary.
+ const unsigned MaxSlots = 32;
+ Use *Slots[MaxSlots];
+
+ // Collect the first use, turning it into a single-item list.
+ Use *Next = UseList->Next;
+ UseList->Next = nullptr;
+ unsigned NumSlots = 1;
+ Slots[0] = UseList;
+
+ // Collect all but the last use.
+ while (Next->Next) {
+ Use *Current = Next;
+ Next = Current->Next;
+
+ // Turn Current into a single-item list.
+ Current->Next = nullptr;
+
+ // Save Current in the first available slot, merging on collisions.
+ unsigned I;
+ for (I = 0; I < NumSlots; ++I) {
+ if (!Slots[I])
+ break;
+
+ // Merge two lists, doubling the size of Current and emptying slot I.
+ //
+ // Since the uses in Slots[I] originally preceded those in Current, send
+ // Slots[I] in as the left parameter to maintain a stable sort.
+ Current = mergeUseLists(Slots[I], Current, Cmp);
+ Slots[I] = nullptr;
+ }
+ // Check if this is a new slot.
+ if (I == NumSlots) {
+ ++NumSlots;
+ assert(NumSlots <= MaxSlots && "Use list bigger than 2^32");
+ }
+
+ // Found an open slot.
+ Slots[I] = Current;
+ }
+
+ // Merge all the lists together.
+ assert(Next && "Expected one more Use");
+ assert(!Next->Next && "Expected only one Use");
+ UseList = Next;
+ for (unsigned I = 0; I < NumSlots; ++I)
+ if (Slots[I])
+ // Since the uses in Slots[I] originally preceded those in UseList, send
+ // Slots[I] in as the left parameter to maintain a stable sort.
+ UseList = mergeUseLists(Slots[I], UseList, Cmp);
+
+ // Fix the Prev pointers.
+ for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) {
+ I->setPrev(Prev);
+ Prev = &I->Next;
+ }
+}
+
+template <class Compare>
+void Value::mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp) {
+ if (!L) {
+ *Next = R;
+ return;
+ }
+ if (!R) {
+ *Next = L;
+ return;
+ }
+ if (Cmp(*R, *L)) {
+ *Next = R;
+ mergeUseListsImpl(L, R->Next, &R->Next, Cmp);
+ return;
+ }
+ *Next = L;
+ mergeUseListsImpl(L->Next, R, &L->Next, Cmp);
+}
// isa - Provide some specializations of isa so that we don't have to include
// the subtype header files to test to see if the value is a subclass...
@@ -537,12 +693,6 @@ template <> struct isa_impl<GlobalObject, Value> {
}
};
-template <> struct isa_impl<MDNode, Value> {
- static inline bool doit(const Value &Val) {
- return Val.getValueID() == Value::MDNodeVal;
- }
-};
-
// Value* is only 4-byte aligned.
template<>
class PointerLikeTypeTraits<Value*> {
diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h
index aa29b2ed6906..8fc7fdb03950 100644
--- a/include/llvm/IR/ValueHandle.h
+++ b/include/llvm/IR/ValueHandle.h
@@ -33,15 +33,16 @@ public:
enum { NumLowBitsAvailable = 2 };
};
-/// ValueHandleBase - This is the common base class of value handles.
+/// \brief This is the common base class of value handles.
+///
/// ValueHandle's are smart pointers to Value's that have special behavior when
/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles
/// below for details.
-///
class ValueHandleBase {
friend class Value;
protected:
- /// HandleBaseKind - This indicates what sub class the handle actually is.
+ /// \brief This indicates what sub class the handle actually is.
+ ///
/// This is to avoid having a vtable for the light-weight handle pointers. The
/// fully general Callback version does have a vtable.
enum HandleBaseKind {
@@ -55,55 +56,48 @@ private:
PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair;
ValueHandleBase *Next;
- // A subclass may want to store some information along with the value
- // pointer. Allow them to do this by making the value pointer a pointer-int
- // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this
- // access.
- PointerIntPair<Value*, 2> VP;
+ Value* V;
ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION;
public:
explicit ValueHandleBase(HandleBaseKind Kind)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {}
+ : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {}
ValueHandleBase(HandleBaseKind Kind, Value *V)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) {
- if (isValid(VP.getPointer()))
+ : PrevPair(nullptr, Kind), Next(nullptr), V(V) {
+ if (isValid(V))
AddToUseList();
}
ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS)
- : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) {
- if (isValid(VP.getPointer()))
+ : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) {
+ if (isValid(V))
AddToExistingUseList(RHS.getPrevPtr());
}
~ValueHandleBase() {
- if (isValid(VP.getPointer()))
+ if (isValid(V))
RemoveFromUseList();
}
Value *operator=(Value *RHS) {
- if (VP.getPointer() == RHS) return RHS;
- if (isValid(VP.getPointer())) RemoveFromUseList();
- VP.setPointer(RHS);
- if (isValid(VP.getPointer())) AddToUseList();
+ if (V == RHS) return RHS;
+ if (isValid(V)) RemoveFromUseList();
+ V = RHS;
+ if (isValid(V)) AddToUseList();
return RHS;
}
Value *operator=(const ValueHandleBase &RHS) {
- if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer();
- if (isValid(VP.getPointer())) RemoveFromUseList();
- VP.setPointer(RHS.VP.getPointer());
- if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr());
- return VP.getPointer();
+ if (V == RHS.V) return RHS.V;
+ if (isValid(V)) RemoveFromUseList();
+ V = RHS.V;
+ if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr());
+ return V;
}
- Value *operator->() const { return getValPtr(); }
- Value &operator*() const { return *getValPtr(); }
+ Value *operator->() const { return V; }
+ Value &operator*() const { return *V; }
protected:
- Value *getValPtr() const { return VP.getPointer(); }
-
- void setValPtrInt(unsigned K) { VP.setInt(K); }
- unsigned getValPtrInt() const { return VP.getInt(); }
+ Value *getValPtr() const { return V; }
static bool isValid(Value *V) {
return V &&
@@ -122,26 +116,28 @@ private:
HandleBaseKind getKind() const { return PrevPair.getInt(); }
void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); }
- /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where
+ /// \brief Add this ValueHandle to the use list for V.
+ ///
/// List is the address of either the head of the list or a Next node within
/// the existing use list.
void AddToExistingUseList(ValueHandleBase **List);
- /// AddToExistingUseListAfter - Add this ValueHandle to the use list after
- /// Node.
+ /// \brief Add this ValueHandle to the use list after Node.
void AddToExistingUseListAfter(ValueHandleBase *Node);
- /// AddToUseList - Add this ValueHandle to the use list for VP.
+ /// \brief Add this ValueHandle to the use list for V.
void AddToUseList();
- /// RemoveFromUseList - Remove this ValueHandle from its current use list.
+ /// \brief Remove this ValueHandle from its current use list.
void RemoveFromUseList();
};
-/// WeakVH - This is a value handle that tries hard to point to a Value, even
-/// across RAUW operations, but will null itself out if the value is destroyed.
-/// this is useful for advisory sorts of information, but should not be used as
-/// the key of a map (since the map would have to rearrange itself when the
-/// pointer changes).
+/// \brief Value handle that is nullable, but tries to track the Value.
+///
+/// This is a value handle that tries hard to point to a Value, even across
+/// RAUW operations, but will null itself out if the value is destroyed. this
+/// is useful for advisory sorts of information, but should not be used as the
+/// key of a map (since the map would have to rearrange itself when the pointer
+/// changes).
class WeakVH : public ValueHandleBase {
public:
WeakVH() : ValueHandleBase(Weak) {}
@@ -170,14 +166,16 @@ template<> struct simplify_type<WeakVH> {
}
};
-/// AssertingVH - This is a Value Handle that points to a value and asserts out
-/// if the value is destroyed while the handle is still live. This is very
-/// useful for catching dangling pointer bugs and other things which can be
-/// non-obvious. 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 an AssertingVH ensures that an assert is triggered as soon as
-/// the bad delete occurs.
+/// \brief Value handle that asserts if the Value is deleted.
+///
+/// This is a Value Handle that points to a value and asserts out if the value
+/// is destroyed while the handle is still live. This is very useful for
+/// catching dangling pointer bugs and other things which can be non-obvious.
+/// 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
+/// an AssertingVH ensures that an assert is triggered as soon as the bad
+/// delete occurs.
///
/// Note that an AssertingVH handle does *not* follow values across RAUW
/// operations. This means that RAUW's need to explicitly update the
@@ -189,25 +187,23 @@ class AssertingVH
: public ValueHandleBase
#endif
{
+ friend struct DenseMapInfo<AssertingVH<ValueTy> >;
#ifndef NDEBUG
- ValueTy *getValPtr() const {
- return static_cast<ValueTy*>(ValueHandleBase::getValPtr());
- }
- void setValPtr(ValueTy *P) {
- ValueHandleBase::operator=(GetAsValue(P));
- }
+ Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); }
+ void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); }
#else
- ValueTy *ThePtr;
- ValueTy *getValPtr() const { return ThePtr; }
- void setValPtr(ValueTy *P) { ThePtr = P; }
+ Value *ThePtr;
+ Value *getRawValPtr() const { return ThePtr; }
+ void setRawValPtr(Value *P) { ThePtr = P; }
#endif
-
- // Convert a ValueTy*, which may be const, to the type the base
- // class expects.
+ // 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); }
+ ValueTy *getValPtr() const { return static_cast<ValueTy *>(getRawValPtr()); }
+ void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); }
+
public:
#ifndef NDEBUG
AssertingVH() : ValueHandleBase(Assert) {}
@@ -215,7 +211,7 @@ public:
AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {}
#else
AssertingVH() : ThePtr(nullptr) {}
- AssertingVH(ValueTy *P) : ThePtr(P) {}
+ AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {}
#endif
operator ValueTy*() const {
@@ -238,21 +234,25 @@ public:
// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap.
template<typename T>
struct DenseMapInfo<AssertingVH<T> > {
- typedef DenseMapInfo<T*> PointerInfo;
static inline AssertingVH<T> getEmptyKey() {
- return AssertingVH<T>(PointerInfo::getEmptyKey());
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getEmptyKey());
+ return Res;
}
- static inline T* getTombstoneKey() {
- return AssertingVH<T>(PointerInfo::getTombstoneKey());
+ static inline AssertingVH<T> getTombstoneKey() {
+ AssertingVH<T> Res;
+ Res.setRawValPtr(DenseMapInfo<Value *>::getTombstoneKey());
+ return Res;
}
static unsigned getHashValue(const AssertingVH<T> &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<Value *>::getHashValue(Val.getRawValPtr());
}
static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
- return LHS == RHS;
+ return DenseMapInfo<Value *>::isEqual(LHS.getRawValPtr(),
+ RHS.getRawValPtr());
}
};
-
+
template <typename T>
struct isPodLike<AssertingVH<T> > {
#ifdef NDEBUG
@@ -263,8 +263,7 @@ struct isPodLike<AssertingVH<T> > {
};
-/// TrackingVH - This is a value handle that tracks a Value (or Value subclass),
-/// even across RAUW operations.
+/// \brief Value handle that tracks a Value across RAUW.
///
/// TrackingVH is designed for situations where a client needs to hold a handle
/// to a Value (or subclass) across some operations which may move that value,
@@ -332,12 +331,14 @@ public:
ValueTy &operator*() const { return *getValPtr(); }
};
-/// CallbackVH - This is a value handle that allows subclasses to define
-/// callbacks that run when the underlying Value has RAUW called on it or is
-/// destroyed. This class can be used as the key of a map, as long as the user
-/// takes it out of the map before calling setValPtr() (since the map has to
-/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this
-/// class has a vtable and a virtual destructor.
+/// \brief Value handle with callbacks on RAUW and destruction.
+///
+/// This is a value handle that allows subclasses to define callbacks that run
+/// when the underlying Value has RAUW called on it or is destroyed. This
+/// class can be used as the key of a map, as long as the user takes it out of
+/// the map before calling setValPtr() (since the map has to rearrange itself
+/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable
+/// and a virtual destructor.
class CallbackVH : public ValueHandleBase {
virtual void anchor();
protected:
@@ -358,16 +359,20 @@ public:
return getValPtr();
}
- /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may
- /// call any non-virtual Value method on getValPtr(), but no subclass methods.
- /// If WeakVH were implemented as a CallbackVH, it would use this method to
- /// call setValPtr(NULL). AssertingVH would use this method to cause an
- /// assertion failure.
+ /// \brief Callback for Value destruction.
+ ///
+ /// Called when this->getValPtr() is destroyed, inside ~Value(), so you
+ /// may call any non-virtual Value method on getValPtr(), but no subclass
+ /// methods. If WeakVH were implemented as a CallbackVH, it would use this
+ /// method to call setValPtr(NULL). AssertingVH would use this method to
+ /// cause an assertion failure.
///
/// All implementations must remove the reference from this object to the
/// Value that's being destroyed.
virtual void deleted() { setValPtr(nullptr); }
+ /// \brief Callback for Value RAUW.
+ ///
/// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called,
/// _before_ any of the uses have actually been replaced. If WeakVH were
/// implemented as a CallbackVH, it would use this method to call
diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h
index 43a79c7db2b9..f2ea405f1428 100644
--- a/include/llvm/IR/ValueMap.h
+++ b/include/llvm/IR/ValueMap.h
@@ -27,10 +27,13 @@
#define LLVM_IR_VALUEMAP_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
+#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/type_traits.h"
#include <iterator>
+#include <memory>
namespace llvm {
@@ -78,8 +81,10 @@ class ValueMap {
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
+ typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
typedef typename Config::ExtraData ExtraData;
MapT Map;
+ std::unique_ptr<MDMapT> MDMap;
ExtraData Data;
ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION;
ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION;
@@ -90,12 +95,19 @@ public:
typedef unsigned size_type;
explicit ValueMap(unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data() {}
+ : Map(NumInitBuckets), Data() {}
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data(Data) {}
+ : Map(NumInitBuckets), Data(Data) {}
~ValueMap() {}
+ bool hasMD() const { return MDMap; }
+ MDMapT &MD() {
+ if (!MDMap)
+ MDMap.reset(new MDMapT);
+ return *MDMap;
+ }
+
typedef ValueMapIterator<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
inline iterator begin() { return iterator(Map.begin()); }
@@ -109,9 +121,12 @@ public:
/// Grow the map so that it has at least Size buckets. Does not shrink
void resize(size_t Size) { Map.resize(Size); }
- void clear() { Map.clear(); }
+ void clear() {
+ Map.clear();
+ MDMap.reset();
+ }
- /// Return 1 if the specified key is in the map, 0 otherwise.
+ /// Return 1 if the specified key is in the map, 0 otherwise.
size_type count(const KeyT &Val) const {
return Map.find_as(Val) == Map.end() ? 0 : 1;
}
@@ -209,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH {
: CallbackVH(const_cast<Value*>(static_cast<const Value*>(Key))),
Map(Map) {}
+ // Private constructor used to create empty/tombstone DenseMap keys.
+ ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {}
+
public:
KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); }
@@ -216,12 +234,11 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->acquire();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this.
Copy.Map->Map.erase(Copy); // Definitely destroys *this.
- if (M)
- M->release();
}
void allUsesReplacedWith(Value *new_key) override {
assert(isa<KeySansPointerT>(new_key) &&
@@ -229,8 +246,9 @@ public:
// Make a copy that won't get changed even when *this is destroyed.
ValueMapCallbackVH Copy(*this);
typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data);
+ unique_lock<typename Config::mutex_type> Guard;
if (M)
- M->acquire();
+ Guard = unique_lock<typename Config::mutex_type>(*M);
KeyT typed_new_key = cast<KeySansPointerT>(new_key);
// Can destroy *this:
@@ -245,27 +263,24 @@ public:
Copy.Map->insert(std::make_pair(typed_new_key, Target));
}
}
- if (M)
- M->release();
}
};
template<typename KeyT, typename ValueT, typename Config>
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > {
typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH;
- typedef DenseMapInfo<KeyT> PointerInfo;
static inline VH getEmptyKey() {
- return VH(PointerInfo::getEmptyKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getEmptyKey());
}
static inline VH getTombstoneKey() {
- return VH(PointerInfo::getTombstoneKey(), nullptr);
+ return VH(DenseMapInfo<Value *>::getTombstoneKey());
}
static unsigned getHashValue(const VH &Val) {
- return PointerInfo::getHashValue(Val.Unwrap());
+ return DenseMapInfo<KeyT>::getHashValue(Val.Unwrap());
}
static unsigned getHashValue(const KeyT &Val) {
- return PointerInfo::getHashValue(Val);
+ return DenseMapInfo<KeyT>::getHashValue(Val);
}
static bool isEqual(const VH &LHS, const VH &RHS) {
return LHS == RHS;
diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h
index 0272e206f37a..43bd123e7f44 100644
--- a/include/llvm/IR/Verifier.h
+++ b/include/llvm/IR/Verifier.h
@@ -77,8 +77,8 @@ class VerifierPass {
public:
explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {}
- PreservedAnalyses run(Module *M);
- PreservedAnalyses run(Function *F);
+ PreservedAnalyses run(Module &M);
+ PreservedAnalyses run(Function &F);
static StringRef name() { return "VerifierPass"; }
};