#include "llvm/ADT/iterator.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/alist.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Support/Allocator.h"
class CompileUnitDesc;
template <typename T> struct DenseMapInfo;
template <typename T> struct simplify_type;
+template <typename T> class ilist_traits;
/// SDVTList - This represents a list of ValueType's that has been intern'd by
/// a SelectionDAG. Instances of this simple value class are returned by
// conversions, but that is a noop, deleted by getNode().
BIT_CONVERT,
- // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW - Perform unary floating point
- // negation, absolute value, square root, sine and cosine, powi, and pow
- // operations.
+ // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
+ // FCEIL, FTRUNC, FRINT, FNEARYINT, FFLOOR - Perform various unary floating
+ // point operations. These are inspired by libm.
FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
+ FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR,
// LOAD and STORE have token chains as their first operand, then the same
// operands as an LLVM load/store instruction, then an offset node that
//===----------------------------------------------------------------------===//
-/// SDOperand - Unlike LLVM values, Selection DAG nodes may return multiple
+/// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple
/// values as the result of a computation. Many nodes return multiple values,
/// from loads (which define a token and a return value) to ADDC (which returns
/// a result and a carry value), to calls (which may return an arbitrary number
///
/// As such, each use of a SelectionDAG computation must indicate the node that
/// computes it as well as which return value to use from that node. This pair
-/// of information is represented with the SDOperand value type.
+/// of information is represented with the SDValue value type.
///
-class SDOperand {
+class SDValue {
public:
SDNode *Val; // The node defining the value we are using.
unsigned ResNo; // Which return value of the node we are using.
- SDOperand() : Val(0), ResNo(0) {}
- SDOperand(SDNode *val, unsigned resno) : Val(val), ResNo(resno) {}
+ SDValue() : Val(0), ResNo(0) {}
+ SDValue(SDNode *val, unsigned resno) : Val(val), ResNo(resno) {}
- bool operator==(const SDOperand &O) const {
+ bool operator==(const SDValue &O) const {
return Val == O.Val && ResNo == O.ResNo;
}
- bool operator!=(const SDOperand &O) const {
+ bool operator!=(const SDValue &O) const {
return !operator==(O);
}
- bool operator<(const SDOperand &O) const {
+ bool operator<(const SDValue &O) const {
return Val < O.Val || (Val == O.Val && ResNo < O.ResNo);
}
- SDOperand getValue(unsigned R) const {
- return SDOperand(Val, R);
+ SDValue getValue(unsigned R) const {
+ return SDValue(Val, R);
}
// isOperandOf - Return true if this node is an operand of N.
// Forwarding methods - These forward to the corresponding methods in SDNode.
inline unsigned getOpcode() const;
inline unsigned getNumOperands() const;
- inline const SDOperand &getOperand(unsigned i) const;
+ inline const SDValue &getOperand(unsigned i) const;
inline uint64_t getConstantOperandVal(unsigned i) const;
inline bool isTargetOpcode() const;
inline bool isMachineOpcode() const;
/// side-effecting instructions. In practice, this looks through token
/// factors and non-volatile loads. In order to remain efficient, this only
/// looks a couple of nodes in, it does not do an exhaustive search.
- bool reachesChainWithoutSideEffects(SDOperand Dest,
+ bool reachesChainWithoutSideEffects(SDValue Dest,
unsigned Depth = 2) const;
/// use_empty - Return true if there are no nodes using value ResNo
};
-template<> struct DenseMapInfo<SDOperand> {
- static inline SDOperand getEmptyKey() {
- return SDOperand((SDNode*)-1, -1U);
+template<> struct DenseMapInfo<SDValue> {
+ static inline SDValue getEmptyKey() {
+ return SDValue((SDNode*)-1, -1U);
}
- static inline SDOperand getTombstoneKey() {
- return SDOperand((SDNode*)-1, 0);
+ static inline SDValue getTombstoneKey() {
+ return SDValue((SDNode*)-1, 0);
}
- static unsigned getHashValue(const SDOperand &Val) {
+ static unsigned getHashValue(const SDValue &Val) {
return ((unsigned)((uintptr_t)Val.Val >> 4) ^
(unsigned)((uintptr_t)Val.Val >> 9)) + Val.ResNo;
}
- static bool isEqual(const SDOperand &LHS, const SDOperand &RHS) {
+ static bool isEqual(const SDValue &LHS, const SDValue &RHS) {
return LHS == RHS;
}
static bool isPod() { return true; }
};
/// simplify_type specializations - Allow casting operators to work directly on
-/// SDOperands as if they were SDNode*'s.
-template<> struct simplify_type<SDOperand> {
+/// SDValues as if they were SDNode*'s.
+template<> struct simplify_type<SDValue> {
typedef SDNode* SimpleType;
- static SimpleType getSimplifiedValue(const SDOperand &Val) {
+ static SimpleType getSimplifiedValue(const SDValue &Val) {
return static_cast<SimpleType>(Val.Val);
}
};
-template<> struct simplify_type<const SDOperand> {
+template<> struct simplify_type<const SDValue> {
typedef SDNode* SimpleType;
- static SimpleType getSimplifiedValue(const SDOperand &Val) {
+ static SimpleType getSimplifiedValue(const SDValue &Val) {
return static_cast<SimpleType>(Val.Val);
}
};
/// SDUse - Represents a use of the SDNode referred by
-/// the SDOperand.
+/// the SDValue.
class SDUse {
- SDOperand Operand;
+ SDValue Operand;
/// User - Parent node of this operand.
SDNode *User;
/// Prev, next - Pointers to the uses list of the SDNode referred by
SDUse(SDNode *val, unsigned resno) :
Operand(val,resno), User(NULL), Prev(NULL), Next(NULL) {}
- SDUse& operator= (const SDOperand& Op) {
+ SDUse& operator= (const SDValue& Op) {
Operand = Op;
Next = NULL;
Prev = NULL;
return *this;
}
- SDUse * getNext() { return Next; }
+ SDUse *getNext() { return Next; }
SDNode *getUser() { return User; }
void setUser(SDNode *p) { User = p; }
- operator SDOperand() const { return Operand; }
+ operator SDValue() const { return Operand; }
- const SDOperand& getSDOperand() const { return Operand; }
+ const SDValue& getSDValue() const { return Operand; }
- SDNode* &getVal () { return Operand.Val; }
+ SDNode *&getVal() { return Operand.Val; }
+ SDNode *const &getVal() const { return Operand.Val; }
- bool operator==(const SDOperand &O) const {
+ bool operator==(const SDValue &O) const {
return Operand == O;
}
- bool operator!=(const SDOperand &O) const {
+ bool operator!=(const SDValue &O) const {
return !(Operand == O);
}
- bool operator<(const SDOperand &O) const {
+ bool operator<(const SDValue &O) const {
return Operand < O;
}
/// simplify_type specializations - Allow casting operators to work directly on
-/// SDOperands as if they were SDNode*'s.
+/// SDValues as if they were SDNode*'s.
template<> struct simplify_type<SDUse> {
typedef SDNode* SimpleType;
static SimpleType getSimplifiedValue(const SDUse &Val) {
- return static_cast<SimpleType>(Val.getSDOperand().Val);
+ return static_cast<SimpleType>(Val.getVal());
}
};
template<> struct simplify_type<const SDUse> {
typedef SDNode* SimpleType;
static SimpleType getSimplifiedValue(const SDUse &Val) {
- return static_cast<SimpleType>(Val.getSDOperand().Val);
+ return static_cast<SimpleType>(Val.getVal());
}
};
-/// SDOperandPtr - A helper SDOperand pointer class, that can handle
-/// arrays of SDUse and arrays of SDOperand objects. This is required
+/// SDOperandPtr - A helper SDValue pointer class, that can handle
+/// arrays of SDUse and arrays of SDValue objects. This is required
/// in many places inside the SelectionDAG.
///
class SDOperandPtr {
- const SDOperand *ptr; // The pointer to the SDOperand object
- int object_size; // The size of the object containg the SDOperand
+ const SDValue *ptr; // The pointer to the SDValue object
+ int object_size; // The size of the object containg the SDValue
public:
SDOperandPtr() : ptr(0), object_size(0) {}
SDOperandPtr(SDUse * use_ptr) {
- ptr = &use_ptr->getSDOperand();
+ ptr = &use_ptr->getSDValue();
object_size = (int)sizeof(SDUse);
}
- SDOperandPtr(const SDOperand * op_ptr) {
+ SDOperandPtr(const SDValue * op_ptr) {
ptr = op_ptr;
- object_size = (int)sizeof(SDOperand);
+ object_size = (int)sizeof(SDValue);
}
- const SDOperand operator *() { return *ptr; }
- const SDOperand *operator ->() { return ptr; }
+ const SDValue operator *() { return *ptr; }
+ const SDValue *operator ->() { return ptr; }
SDOperandPtr operator ++ () {
- ptr = (SDOperand*)((char *)ptr + object_size);
+ ptr = (SDValue*)((char *)ptr + object_size);
return *this;
}
SDOperandPtr operator ++ (int) {
SDOperandPtr tmp = *this;
- ptr = (SDOperand*)((char *)ptr + object_size);
+ ptr = (SDValue*)((char *)ptr + object_size);
return tmp;
}
- SDOperand operator[] (int idx) const {
- return *(SDOperand*)((char*) ptr + object_size * idx);
+ SDValue operator[] (int idx) const {
+ return *(SDValue*)((char*) ptr + object_size * idx);
}
};
/// SDNode - Represents one node in the SelectionDAG.
///
-class SDNode : public FoldingSetNode {
+class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
private:
/// NodeType - The operation that this node performs.
///
/// true. It returns the MachineInstr opcode value that the node's opcode
/// corresponds to.
unsigned getMachineOpcode() const {
- assert(isMachineOpcode() && "Not a target opcode!");
+ assert(isMachineOpcode() && "Not a MachineInstr opcode!");
return ~NodeType;
}
- /// use_empty - Return true if there are no uses of this value.
+ /// use_empty - Return true if there are no uses of this node.
///
bool use_empty() const { return Uses == NULL; }
- /// hasOneUse - Return true if there is exactly one use of this value.
+ /// hasOneUse - Return true if there is exactly one use of this node.
///
bool hasOneUse() const {
return !use_empty() && next(use_begin()) == use_end();
}
- /// use_size - Return the number of uses of this value. This method takes
+ /// use_size - Return the number of uses of this node. This method takes
/// time proportional to the number of uses.
///
size_t use_size() const { return std::distance(use_begin(), use_end()); }
use_iterator tmp = *this; ++*this; return tmp;
}
-
- /// getOperandNum - Retrive a number of a current operand.
- unsigned getOperandNum() const {
+ /// Retrieve a pointer to the current user node.
+ SDNode *operator*() const {
assert(Op && "Cannot dereference end iterator!");
- return (unsigned)(Op - Op->getUser()->OperandList);
+ return Op->getUser();
}
- /// Retrieve a reference to the current operand.
- SDUse &operator*() const {
- assert(Op && "Cannot dereference end iterator!");
- return *Op;
- }
+ SDNode *operator->() const { return operator*(); }
+
+ SDUse &getUse() const { return *Op; }
- /// Retrieve a pointer to the current operand.
- SDUse *operator->() const {
+ /// getOperandNo - Retrive the operand # of this use in its user.
+ ///
+ unsigned getOperandNo() const {
assert(Op && "Cannot dereference end iterator!");
- return Op;
+ return (unsigned)(Op - Op->getUser()->OperandList);
}
};
/// use_begin/use_end - Provide iteration support to walk over all uses
/// of an SDNode.
- use_iterator use_begin(SDNode *node) const {
- return use_iterator(node->Uses);
- }
-
use_iterator use_begin() const {
return use_iterator(Uses);
}
/// value. This method ignores uses of other values defined by this operation.
bool hasAnyUseOfValue(unsigned Value) const;
- /// isOnlyUseOf - Return true if this node is the only use of N.
+ /// isOnlyUserOf - Return true if this node is the only use of N.
///
- bool isOnlyUseOf(SDNode *N) const;
+ bool isOnlyUserOf(SDNode *N) const;
/// isOperandOf - Return true if this node is an operand of N.
///
/// ConstantSDNode operand.
uint64_t getConstantOperandVal(unsigned Num) const;
- const SDOperand &getOperand(unsigned Num) const {
+ const SDValue &getOperand(unsigned Num) const {
assert(Num < NumOperands && "Invalid child # of SDNode!");
- return OperandList[Num].getSDOperand();
+ return OperandList[Num].getSDValue();
}
typedef SDUse* op_iterator;
/// Profile - Gather unique data for the node.
///
- void Profile(FoldingSetNodeID &ID);
+ void Profile(FoldingSetNodeID &ID) const;
protected:
friend class SelectionDAG;
+ friend class ilist_traits<SDNode>;
/// getValueTypeList - Return a pointer to the specified value type.
///
return Ret;
}
- SDNode(unsigned Opc, SDVTList VTs, const SDOperand *Ops, unsigned NumOps)
+ SDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps)
: NodeType(Opc), OperandsNeedDelete(true), SubclassData(0),
NodeId(-1), Uses(NULL) {
NumOperands = NumOps;
for (unsigned i = 0; i != NumOps; ++i) {
OperandList[i] = Ops[i];
OperandList[i].setUser(this);
- Ops[i].getSDOperand().Val->addUse(OperandList[i]);
+ Ops[i].getVal()->addUse(OperandList[i]);
}
ValueList = VTs.VTs;
};
-// Define inline functions from the SDOperand class.
+// Define inline functions from the SDValue class.
-inline unsigned SDOperand::getOpcode() const {
+inline unsigned SDValue::getOpcode() const {
return Val->getOpcode();
}
-inline MVT SDOperand::getValueType() const {
+inline MVT SDValue::getValueType() const {
return Val->getValueType(ResNo);
}
-inline unsigned SDOperand::getNumOperands() const {
+inline unsigned SDValue::getNumOperands() const {
return Val->getNumOperands();
}
-inline const SDOperand &SDOperand::getOperand(unsigned i) const {
+inline const SDValue &SDValue::getOperand(unsigned i) const {
return Val->getOperand(i);
}
-inline uint64_t SDOperand::getConstantOperandVal(unsigned i) const {
+inline uint64_t SDValue::getConstantOperandVal(unsigned i) const {
return Val->getConstantOperandVal(i);
}
-inline bool SDOperand::isTargetOpcode() const {
+inline bool SDValue::isTargetOpcode() const {
return Val->isTargetOpcode();
}
-inline bool SDOperand::isMachineOpcode() const {
+inline bool SDValue::isMachineOpcode() const {
return Val->isMachineOpcode();
}
-inline unsigned SDOperand::getMachineOpcode() const {
+inline unsigned SDValue::getMachineOpcode() const {
return Val->getMachineOpcode();
}
-inline bool SDOperand::use_empty() const {
+inline bool SDValue::use_empty() const {
return !Val->hasAnyUseOfValue(ResNo);
}
-inline bool SDOperand::hasOneUse() const {
+inline bool SDValue::hasOneUse() const {
return Val->hasNUsesOfValue(1, ResNo);
}
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
SDUse Op;
public:
- UnarySDNode(unsigned Opc, SDVTList VTs, SDOperand X)
+ UnarySDNode(unsigned Opc, SDVTList VTs, SDValue X)
: SDNode(Opc, VTs) {
Op = X;
InitOperands(&Op, 1);
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
SDUse Ops[2];
public:
- BinarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y)
+ BinarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y)
: SDNode(Opc, VTs) {
Ops[0] = X;
Ops[1] = Y;
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
SDUse Ops[3];
public:
- TernarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y,
- SDOperand Z)
+ TernarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y,
+ SDValue Z)
: SDNode(Opc, VTs) {
Ops[0] = X;
Ops[1] = Y;
// FIXME: Remove the "noinline" attribute once <rdar://problem/5852746> is
// fixed.
#ifdef __GNUC__
- explicit __attribute__((__noinline__)) HandleSDNode(SDOperand X)
+ explicit __attribute__((__noinline__)) HandleSDNode(SDValue X)
#else
- explicit HandleSDNode(SDOperand X)
+ explicit HandleSDNode(SDValue X)
#endif
: SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)) {
Op = X;
InitOperands(&Op, 1);
}
~HandleSDNode();
- SDUse getValue() const { return Op; }
+ const SDValue &getValue() const { return Op.getSDValue(); }
};
/// Abstact virtual class for operations for memory operations
/// reference performed by operation.
MachineMemOperand getMemOperand() const;
- const SDOperand &getChain() const { return getOperand(0); }
- const SDOperand &getBasePtr() const {
+ const SDValue &getChain() const { return getOperand(0); }
+ const SDValue &getBasePtr() const {
return getOperand(getOpcode() == ISD::STORE ? 2 : 1);
}
+ /// getRawFlags - Represent the flags as a bunch of bits.
+ ///
+ unsigned getRawFlags() const { return Flags; }
+
// Methods to support isa and dyn_cast
static bool classof(const MemSDNode *) { return true; }
static bool classof(const SDNode *N) {
// Opc: opcode for atomic
// VTL: value type list
// Chain: memory chain for operaand
- // Ptr: address to update as a SDOperand
+ // Ptr: address to update as a SDValue
// Cmp: compare value
// Swp: swap value
// SrcVal: address to update as a Value (used for MemOperand)
// Align: alignment of memory
- AtomicSDNode(unsigned Opc, SDVTList VTL, SDOperand Chain, SDOperand Ptr,
- SDOperand Cmp, SDOperand Swp, const Value* SrcVal,
+ AtomicSDNode(unsigned Opc, SDVTList VTL, SDValue Chain, SDValue Ptr,
+ SDValue Cmp, SDValue Swp, const Value* SrcVal,
unsigned Align=0)
: MemSDNode(Opc, VTL, Cmp.getValueType(), SrcVal, /*SVOffset=*/0,
Align, /*isVolatile=*/true) {
Ops[3] = Cmp;
InitOperands(Ops, 4);
}
- AtomicSDNode(unsigned Opc, SDVTList VTL, SDOperand Chain, SDOperand Ptr,
- SDOperand Val, const Value* SrcVal, unsigned Align=0)
+ AtomicSDNode(unsigned Opc, SDVTList VTL, SDValue Chain, SDValue Ptr,
+ SDValue Val, const Value* SrcVal, unsigned Align=0)
: MemSDNode(Opc, VTL, Val.getValueType(), SrcVal, /*SVOffset=*/0,
Align, /*isVolatile=*/true) {
Ops[0] = Chain;
InitOperands(Ops, 3);
}
- const SDOperand &getBasePtr() const { return getOperand(1); }
- const SDOperand &getVal() const { return getOperand(2); }
+ const SDValue &getBasePtr() const { return getOperand(1); }
+ const SDValue &getVal() const { return getOperand(2); }
bool isCompareAndSwap() const { return getOpcode() == ISD::ATOMIC_CMP_SWAP; }
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- DbgStopPointSDNode(SDOperand ch, unsigned l, unsigned c,
+ DbgStopPointSDNode(SDValue ch, unsigned l, unsigned c,
const CompileUnitDesc *cu)
: SDNode(ISD::DBG_STOPPOINT, getSDVTList(MVT::Other)),
Line(l), Column(c), CU(cu) {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- LabelSDNode(unsigned NodeTy, SDOperand ch, unsigned id)
+ LabelSDNode(unsigned NodeTy, SDValue ch, unsigned id)
: SDNode(NodeTy, getSDVTList(MVT::Other)), LabelID(id) {
Chain = ch;
InitOperands(&Chain, 1);
*/
SDUse Ops[4];
public:
- LSBaseSDNode(ISD::NodeType NodeTy, SDOperand *Operands, unsigned numOperands,
+ LSBaseSDNode(ISD::NodeType NodeTy, SDValue *Operands, unsigned numOperands,
SDVTList VTs, ISD::MemIndexedMode AM, MVT VT,
const Value *SV, int SVO, unsigned Align, bool Vol)
: MemSDNode(NodeTy, VTs, VT, SV, SVO, Align, Vol) {
"Only indexed loads and stores have a non-undef offset operand");
}
- const SDOperand &getOffset() const {
+ const SDValue &getOffset() const {
return getOperand(getOpcode() == ISD::LOAD ? 2 : 3);
}
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- LoadSDNode(SDOperand *ChainPtrOff, SDVTList VTs,
+ LoadSDNode(SDValue *ChainPtrOff, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT LVT,
const Value *SV, int O=0, unsigned Align=0, bool Vol=false)
: LSBaseSDNode(ISD::LOAD, ChainPtrOff, 3,
return ISD::LoadExtType((SubclassData >> 3) & 3);
}
- const SDOperand &getBasePtr() const { return getOperand(1); }
- const SDOperand &getOffset() const { return getOperand(2); }
+ const SDValue &getBasePtr() const { return getOperand(1); }
+ const SDValue &getOffset() const { return getOperand(2); }
static bool classof(const LoadSDNode *) { return true; }
static bool classof(const SDNode *N) {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- StoreSDNode(SDOperand *ChainValuePtrOff, SDVTList VTs,
+ StoreSDNode(SDValue *ChainValuePtrOff, SDVTList VTs,
ISD::MemIndexedMode AM, bool isTrunc, MVT SVT,
const Value *SV, int O=0, unsigned Align=0, bool Vol=false)
: LSBaseSDNode(ISD::STORE, ChainValuePtrOff, 4,
/// For floats, it is the same as doing an FP_ROUND and storing the result.
bool isTruncatingStore() const { return (SubclassData >> 3) & 1; }
- const SDOperand &getValue() const { return getOperand(1); }
- const SDOperand &getBasePtr() const { return getOperand(2); }
- const SDOperand &getOffset() const { return getOperand(3); }
+ const SDValue &getValue() const { return getOperand(1); }
+ const SDValue &getBasePtr() const { return getOperand(2); }
+ const SDValue &getOffset() const { return getOperand(3); }
static bool classof(const StoreSDNode *) { return true; }
static bool classof(const SDNode *N) {
///
typedef LoadSDNode LargestSDNode;
-// alist_traits specialization for pool-allocating SDNodes.
-template <>
-class alist_traits<SDNode, LargestSDNode> {
- typedef alist_iterator<SDNode, LargestSDNode> iterator;
-
-public:
- // Pool-allocate and recycle SDNodes.
- typedef RecyclingAllocator<BumpPtrAllocator, SDNode, LargestSDNode>
- AllocatorType;
-
- // Allocate the allocator immediately inside the traits class.
- AllocatorType Allocator;
-
- void addNodeToList(SDNode*) {}
- void removeNodeFromList(SDNode*) {}
- void transferNodesFromList(alist_traits &, iterator, iterator) {}
- void deleteNode(SDNode *N) {
- N->~SDNode();
- Allocator.Deallocate(N);
- }
-};
+/// MostAlignedSDNode - The SDNode class with the greatest alignment
+/// requirement.
+///
+typedef ConstantSDNode MostAlignedSDNode;
namespace ISD {
/// isNormalLoad - Returns true if the specified node is a non-extending