aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen/SelectionDAGNodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/CodeGen/SelectionDAGNodes.h')
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h185
1 files changed, 154 insertions, 31 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 10f284179084..5aab9643e09d 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -184,6 +183,7 @@ public:
inline unsigned getNumOperands() const;
inline const SDValue &getOperand(unsigned i) const;
inline uint64_t getConstantOperandVal(unsigned i) const;
+ inline const APInt &getConstantOperandAPInt(unsigned i) const;
inline bool isTargetMemoryOpcode() const;
inline bool isTargetOpcode() const;
inline bool isMachineOpcode() const;
@@ -232,7 +232,6 @@ template<> struct DenseMapInfo<SDValue> {
return LHS == RHS;
}
};
-template <> struct isPodLike<SDValue> { static const bool value = true; };
/// Allow casting operators to work directly on
/// SDValues as if they were SDNode*'s.
@@ -369,6 +368,13 @@ private:
bool ApproximateFuncs : 1;
bool AllowReassociation : 1;
+ // We assume instructions do not raise floating-point exceptions by default,
+ // and only those marked explicitly may do so. We could choose to represent
+ // this via a positive "FPExcept" flags like on the MI level, but having a
+ // negative "NoFPExcept" flag here (that defaults to true) makes the flag
+ // intersection logic more straightforward.
+ bool NoFPExcept : 1;
+
public:
/// Default constructor turns off all optimization flags.
SDNodeFlags()
@@ -376,7 +382,7 @@ public:
Exact(false), NoNaNs(false), NoInfs(false),
NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false),
AllowContract(false), ApproximateFuncs(false),
- AllowReassociation(false) {}
+ AllowReassociation(false), NoFPExcept(true) {}
/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
@@ -439,6 +445,10 @@ public:
setDefined();
AllowReassociation = b;
}
+ void setFPExcept(bool b) {
+ setDefined();
+ NoFPExcept = !b;
+ }
// These are accessors for each flag.
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
@@ -452,9 +462,10 @@ public:
bool hasAllowContract() const { return AllowContract; }
bool hasApproximateFuncs() const { return ApproximateFuncs; }
bool hasAllowReassociation() const { return AllowReassociation; }
+ bool hasFPExcept() const { return !NoFPExcept; }
bool isFast() const {
- return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs &&
+ return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && NoFPExcept &&
AllowContract && ApproximateFuncs && AllowReassociation;
}
@@ -474,6 +485,7 @@ public:
AllowContract &= Flags.AllowContract;
ApproximateFuncs &= Flags.ApproximateFuncs;
AllowReassociation &= Flags.AllowReassociation;
+ NoFPExcept &= Flags.NoFPExcept;
}
};
@@ -489,6 +501,17 @@ protected:
// SubclassData. These are designed to fit within a uint16_t so they pack
// with NodeType.
+#if defined(_AIX) && (!defined(__GNUC__) || defined(__ibmxl__))
+// Except for GCC; by default, AIX compilers store bit-fields in 4-byte words
+// and give the `pack` pragma push semantics.
+#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)")
+#define END_TWO_BYTE_PACK() _Pragma("pack(pop)")
+#else
+#define BEGIN_TWO_BYTE_PACK()
+#define END_TWO_BYTE_PACK()
+#endif
+
+BEGIN_TWO_BYTE_PACK()
class SDNodeBitfields {
friend class SDNode;
friend class MemIntrinsicSDNode;
@@ -561,6 +584,9 @@ protected:
LoadSDNodeBitfields LoadSDNodeBits;
StoreSDNodeBitfields StoreSDNodeBits;
};
+END_TWO_BYTE_PACK()
+#undef BEGIN_TWO_BYTE_PACK
+#undef END_TWO_BYTE_PACK
// RawSDNodeBits must cover the entirety of the union. This means that all of
// the union's members must have size <= RawSDNodeBits. We write the RHS as
@@ -678,6 +704,8 @@ public:
case ISD::STRICT_FFLOOR:
case ISD::STRICT_FROUND:
case ISD::STRICT_FTRUNC:
+ case ISD::STRICT_FP_ROUND:
+ case ISD::STRICT_FP_EXTEND:
return true;
}
}
@@ -898,9 +926,17 @@ public:
/// Return the number of values used by this operation.
unsigned getNumOperands() const { return NumOperands; }
+ /// Return the maximum number of operands that a SDNode can hold.
+ static constexpr size_t getMaxNumOperands() {
+ return std::numeric_limits<decltype(SDNode::NumOperands)>::max();
+ }
+
/// Helper method returns the integer value of a ConstantSDNode operand.
inline uint64_t getConstantOperandVal(unsigned Num) const;
+ /// Helper method returns the APInt of a ConstantSDNode operand.
+ inline const APInt &getConstantOperandAPInt(unsigned Num) const;
+
const SDValue &getOperand(unsigned Num) const {
assert(Num < NumOperands && "Invalid child # of SDNode!");
return OperandList[Num];
@@ -1128,6 +1164,10 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const {
return Node->getConstantOperandVal(i);
}
+inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const {
+ return Node->getConstantOperandAPInt(i);
+}
+
inline bool SDValue::isTargetOpcode() const {
return Node->isTargetOpcode();
}
@@ -1356,6 +1396,8 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_MAX ||
N->getOpcode() == ISD::ATOMIC_LOAD_UMIN ||
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_FADD ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_FSUB ||
N->getOpcode() == ISD::ATOMIC_LOAD ||
N->getOpcode() == ISD::ATOMIC_STORE ||
N->getOpcode() == ISD::MLOAD ||
@@ -1372,7 +1414,10 @@ class AtomicSDNode : public MemSDNode {
public:
AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL,
EVT MemVT, MachineMemOperand *MMO)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {}
+ : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
+ assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) ||
+ MMO->isAtomic()) && "then why are we using an AtomicSDNode?");
+ }
const SDValue &getBasePtr() const { return getOperand(1); }
const SDValue &getVal() const { return getOperand(2); }
@@ -1408,6 +1453,8 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_MAX ||
N->getOpcode() == ISD::ATOMIC_LOAD_UMIN ||
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_FADD ||
+ N->getOpcode() == ISD::ATOMIC_LOAD_FSUB ||
N->getOpcode() == ISD::ATOMIC_LOAD ||
N->getOpcode() == ISD::ATOMIC_STORE;
}
@@ -1467,14 +1514,16 @@ public:
bool isSplat() const { return isSplatMask(Mask, getValueType(0)); }
- int getSplatIndex() const {
+ int getSplatIndex() const {
assert(isSplat() && "Cannot get splat index for non-splat!");
EVT VT = getValueType(0);
- for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) {
+ for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
if (Mask[i] >= 0)
return Mask[i];
- }
- llvm_unreachable("Splat with all undef indices?");
+
+ // We can choose any index value here and be correct because all elements
+ // are undefined. Return 0 for better potential for callers to simplify.
+ return 0;
}
static bool isSplatMask(const int *Mask, EVT VT);
@@ -1536,6 +1585,10 @@ uint64_t SDNode::getConstantOperandVal(unsigned Num) const {
return cast<ConstantSDNode>(getOperand(Num))->getZExtValue();
}
+const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const {
+ return cast<ConstantSDNode>(getOperand(Num))->getAPIntValue();
+}
+
class ConstantFPSDNode : public SDNode {
friend class SelectionDAG;
@@ -1603,20 +1656,36 @@ SDValue peekThroughBitcasts(SDValue V);
/// If \p V is not a bitcasted one-use value, it is returned as-is.
SDValue peekThroughOneUseBitcasts(SDValue V);
+/// Return the non-extracted vector source operand of \p V if it exists.
+/// If \p V is not an extracted subvector, it is returned as-is.
+SDValue peekThroughExtractSubvectors(SDValue V);
+
/// Returns true if \p V is a bitwise not operation. Assumes that an all ones
/// constant is canonicalized to be operand 1.
-bool isBitwiseNot(SDValue V);
+bool isBitwiseNot(SDValue V, bool AllowUndefs = false);
/// Returns the SDNode if it is a constant splat BuildVector or constant int.
-ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false);
+ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false,
+ bool AllowTruncation = false);
+
+/// Returns the SDNode if it is a demanded constant splat BuildVector or
+/// constant int.
+ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts,
+ bool AllowUndefs = false,
+ bool AllowTruncation = false);
/// Returns the SDNode if it is a constant splat BuildVector or constant float.
ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false);
+/// Returns the SDNode if it is a demanded constant splat BuildVector or
+/// constant float.
+ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts,
+ bool AllowUndefs = false);
+
/// Return true if the value is a constant 0 integer or a splatted vector of
-/// a constant 0 integer (with no undefs).
+/// a constant 0 integer (with no undefs by default).
/// Build vector implicit truncation is not an issue for null values.
-bool isNullOrNullSplat(SDValue V);
+bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false);
/// Return true if the value is a constant 1 integer or a splatted vector of a
/// constant 1 integer (with no undefs).
@@ -1673,6 +1742,38 @@ public:
}
};
+/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate
+/// the offet and size that are started/ended in the underlying FrameIndex.
+class LifetimeSDNode : public SDNode {
+ friend class SelectionDAG;
+ int64_t Size;
+ int64_t Offset; // -1 if offset is unknown.
+
+ LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl,
+ SDVTList VTs, int64_t Size, int64_t Offset)
+ : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {}
+public:
+ int64_t getFrameIndex() const {
+ return cast<FrameIndexSDNode>(getOperand(1))->getIndex();
+ }
+
+ bool hasOffset() const { return Offset >= 0; }
+ int64_t getOffset() const {
+ assert(hasOffset() && "offset is unknown");
+ return Offset;
+ }
+ int64_t getSize() const {
+ assert(hasOffset() && "offset is unknown");
+ return Size;
+ }
+
+ // Methods to support isa and dyn_cast
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::LIFETIME_START ||
+ N->getOpcode() == ISD::LIFETIME_END;
+ }
+};
+
class JumpTableSDNode : public SDNode {
friend class SelectionDAG;
@@ -1818,12 +1919,31 @@ public:
unsigned MinSplatBits = 0,
bool isBigEndian = false) const;
+ /// Returns the demanded splatted value or a null value if this is not a
+ /// splat.
+ ///
+ /// The DemandedElts mask indicates the elements that must be in the splat.
+ /// If passed a non-null UndefElements bitvector, it will resize it to match
+ /// the vector width and set the bits where elements are undef.
+ SDValue getSplatValue(const APInt &DemandedElts,
+ BitVector *UndefElements = nullptr) const;
+
/// Returns the splatted value or a null value if this is not a splat.
///
/// If passed a non-null UndefElements bitvector, it will resize it to match
/// the vector width and set the bits where elements are undef.
SDValue getSplatValue(BitVector *UndefElements = nullptr) const;
+ /// Returns the demanded splatted constant or null if this is not a constant
+ /// splat.
+ ///
+ /// The DemandedElts mask indicates the elements that must be in the splat.
+ /// If passed a non-null UndefElements bitvector, it will resize it to match
+ /// the vector width and set the bits where elements are undef.
+ ConstantSDNode *
+ getConstantSplatNode(const APInt &DemandedElts,
+ BitVector *UndefElements = nullptr) const;
+
/// Returns the splatted constant or null if this is not a constant
/// splat.
///
@@ -1832,6 +1952,16 @@ public:
ConstantSDNode *
getConstantSplatNode(BitVector *UndefElements = nullptr) const;
+ /// Returns the demanded splatted constant FP or null if this is not a
+ /// constant FP splat.
+ ///
+ /// The DemandedElts mask indicates the elements that must be in the splat.
+ /// If passed a non-null UndefElements bitvector, it will resize it to match
+ /// the vector width and set the bits where elements are undef.
+ ConstantFPSDNode *
+ getConstantFPSplatNode(const APInt &DemandedElts,
+ BitVector *UndefElements = nullptr) const;
+
/// Returns the splatted constant FP or null if this is not a constant
/// FP splat.
///
@@ -1956,8 +2086,10 @@ class LabelSDNode : public SDNode {
MCSymbol *Label;
- LabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
- : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
+ LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L)
+ : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) {
+ assert(LabelSDNode::classof(this) && "not a label opcode");
+ }
public:
MCSymbol *getLabel() const { return Label; }
@@ -2049,6 +2181,8 @@ public:
: MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
LSBaseSDNodeBits.AddressingMode = AM;
assert(getAddressingMode() == AM && "Value truncated");
+ assert((!MMO->isAtomic() || MMO->isVolatile()) &&
+ "use an AtomicSDNode instead for non-volatile atomics");
}
const SDValue &getOffset() const {
@@ -2473,18 +2607,6 @@ namespace ISD {
cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
}
- /// Return true if the node is a math/logic binary operator. This corresponds
- /// to the IR function of the same name.
- inline bool isBinaryOp(const SDNode *N) {
- auto Op = N->getOpcode();
- return (Op == ISD::ADD || Op == ISD::SUB || Op == ISD::MUL ||
- Op == ISD::AND || Op == ISD::OR || Op == ISD::XOR ||
- Op == ISD::SHL || Op == ISD::SRL || Op == ISD::SRA ||
- Op == ISD::SDIV || Op == ISD::UDIV || Op == ISD::SREM ||
- Op == ISD::UREM || Op == ISD::FADD || Op == ISD::FSUB ||
- Op == ISD::FMUL || Op == ISD::FDIV || Op == ISD::FREM);
- }
-
/// Attempt to match a unary predicate against a scalar/splat constant or
/// every element of a constant BUILD_VECTOR.
/// If AllowUndef is true, then UNDEF elements will pass nullptr to Match.
@@ -2495,10 +2617,11 @@ namespace ISD {
/// Attempt to match a binary predicate against a pair of scalar/splat
/// constants or every element of a pair of constant BUILD_VECTORs.
/// If AllowUndef is true, then UNDEF elements will pass nullptr to Match.
+ /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match.
bool matchBinaryPredicate(
SDValue LHS, SDValue RHS,
std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match,
- bool AllowUndefs = false);
+ bool AllowUndefs = false, bool AllowTypeMismatch = false);
} // end namespace ISD
} // end namespace llvm