diff options
author | Dan Gohman <gohman@apple.com> | 2009-09-25 20:36:54 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2009-09-25 20:36:54 +0000 |
commit | c76909abfec876c6b751d693ebd3df07df686aa0 (patch) | |
tree | bc66c4b4bc5955aa33a7c6fb19c0163ef070b08a /include/llvm/CodeGen | |
parent | 602b0c8c17f458d2c80f2deb3c8e554d516ee316 (diff) | |
download | external_llvm-c76909abfec876c6b751d693ebd3df07df686aa0.zip external_llvm-c76909abfec876c6b751d693ebd3df07df686aa0.tar.gz external_llvm-c76909abfec876c6b751d693ebd3df07df686aa0.tar.bz2 |
Improve MachineMemOperand handling.
- Allocate MachineMemOperands and MachineMemOperand lists in MachineFunctions.
This eliminates MachineInstr's std::list member and allows the data to be
created by isel and live for the remainder of codegen, avoiding a lot of
copying and unnecessary translation. This also shrinks MemSDNode.
- Delete MemOperandSDNode. Introduce MachineSDNode which has dedicated
fields for MachineMemOperands.
- Change MemSDNode to have a MachineMemOperand member instead of its own
fields with the same information. This introduces some redundancy, but
it's more consistent with what MachineInstr will eventually want.
- Ignore alignment when searching for redundant loads for CSE, but remember
the greatest alignment.
Target-specific code which previously used MemOperandSDNodes with generic
SDNodes now use MemIntrinsicSDNodes, with opcodes in a designated range
so that the SelectionDAG framework knows that MachineMemOperand information
is available.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82794 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/CodeGen')
-rw-r--r-- | include/llvm/CodeGen/MachineFunction.h | 19 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineInstr.h | 41 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineInstrBuilder.h | 2 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineMemOperand.h | 10 | ||||
-rw-r--r-- | include/llvm/CodeGen/ScheduleDAG.h | 2 | ||||
-rw-r--r-- | include/llvm/CodeGen/SelectionDAG.h | 32 | ||||
-rw-r--r-- | include/llvm/CodeGen/SelectionDAGNodes.h | 198 |
7 files changed, 189 insertions, 115 deletions
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 9fe5dfd..6019ea3 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -27,6 +27,7 @@ namespace llvm { +class Value; class Function; class MachineRegisterInfo; class MachineFrameInfo; @@ -320,6 +321,24 @@ public: /// void DeleteMachineBasicBlock(MachineBasicBlock *MBB); + /// getMachineMemOperand - Allocate a new MachineMemOperand. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const Value *v, unsigned f, + int64_t o, uint64_t s, + unsigned base_alignment); + + /// getMachineMemOperand - Allocate a new MachineMemOperand by copying + /// an existing one, adjusting by an offset and using the given EVT. + /// MachineMemOperands are owned by the MachineFunction and need not be + /// explicitly deallocated. + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size); + + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand + /// pointers. This array is owned by the MachineFunction. + MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); + //===--------------------------------------------------------------------===// // Debug location. // diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 79cb66f..66af73e 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -20,10 +20,8 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/Target/TargetInstrDesc.h" #include "llvm/Support/DebugLoc.h" -#include <list> #include <vector> namespace llvm { @@ -32,17 +30,23 @@ class TargetInstrDesc; class TargetInstrInfo; class TargetRegisterInfo; class MachineFunction; +class MachineMemOperand; //===----------------------------------------------------------------------===// /// MachineInstr - Representation of each machine instruction. /// class MachineInstr : public ilist_node<MachineInstr> { +public: + typedef MachineMemOperand **mmo_iterator; + +private: const TargetInstrDesc *TID; // Instruction descriptor. unsigned short NumImplicitOps; // Number of implicit operands (which // are determined at construction time). std::vector<MachineOperand> Operands; // the operands - std::list<MachineMemOperand> MemOperands; // information on memory references + mmo_iterator MemRefs; // information on memory references + mmo_iterator MemRefsEnd; MachineBasicBlock *Parent; // Pointer to the owning basic block. DebugLoc debugLoc; // Source line information. @@ -132,21 +136,14 @@ public: unsigned getNumExplicitOperands() const; /// Access to memory operands of the instruction - std::list<MachineMemOperand>::iterator memoperands_begin() - { return MemOperands.begin(); } - std::list<MachineMemOperand>::iterator memoperands_end() - { return MemOperands.end(); } - std::list<MachineMemOperand>::const_iterator memoperands_begin() const - { return MemOperands.begin(); } - std::list<MachineMemOperand>::const_iterator memoperands_end() const - { return MemOperands.end(); } - bool memoperands_empty() const { return MemOperands.empty(); } + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } /// hasOneMemOperand - Return true if this instruction has exactly one /// MachineMemOperand. bool hasOneMemOperand() const { - return !memoperands_empty() && - next(memoperands_begin()) == memoperands_end(); + return MemRefsEnd - MemRefs == 1; } /// isIdenticalTo - Return true if this instruction is identical to (same @@ -319,13 +316,17 @@ public: /// void RemoveOperand(unsigned i); - /// addMemOperand - Add a MachineMemOperand to the machine instruction, - /// referencing arbitrary storage. - void addMemOperand(MachineFunction &MF, - const MachineMemOperand &MO); + /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// This function should be used only occasionally. The setMemRefs function + /// is the primary method for setting up a MachineInstr's MemRefs list. + void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - /// clearMemOperands - Erase all of this MachineInstr's MachineMemOperands. - void clearMemOperands(MachineFunction &MF); + /// setMemRefs - Assign this MachineInstr's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } private: /// getRegInfo - If this instruction is embedded into a MachineFunction, diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 55b8671..7f681d7 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -121,7 +121,7 @@ public: return *this; } - const MachineInstrBuilder &addMemOperand(const MachineMemOperand &MMO) const { + const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { MI->addMemOperand(*MI->getParent()->getParent(), MMO); return *this; } diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index d52d7a6..dd70b81 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -88,6 +88,16 @@ public: bool isStore() const { return Flags & MOStore; } bool isVolatile() const { return Flags & MOVolatile; } + /// refineAlignment - Update this MachineMemOperand to reflect the alignment + /// of MMO, if it has a greater alignment. This must only be used when the + /// new alignment applies to all users of this MachineMemOperand. + void refineAlignment(const MachineMemOperand *MMO); + + /// setValue - Change the SourceValue for this MachineMemOperand. This + /// should only be used when an object is being relocated and all references + /// to it are being updated. + void setValue(const Value *NewSV) { V = NewSV; } + /// Profile - Gather unique data for the object. /// void Profile(FoldingSetNodeID &ID) const; diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index d35525d..c5e12a6 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -516,8 +516,6 @@ namespace llvm { /// void EmitNoop(); - void AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO); - void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); private: diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index a3e8a92..e1b9998 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/RecyclingAllocator.h" #include "llvm/Target/TargetMachine.h" #include <cassert> #include <vector> @@ -514,15 +515,23 @@ public: SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal, unsigned Alignment=0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO); /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 2 operands. SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* PtrVal, unsigned Alignment = 0); + SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, + SDValue Ptr, SDValue Val, + MachineMemOperand *MMO); /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a - /// result and takes a list of operands. + /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, + /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not + /// less than FIRST_TARGET_MEMORY_OPCODE. SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, const EVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps, @@ -536,6 +545,10 @@ public: unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); + SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + EVT MemVT, MachineMemOperand *MMO); + /// getMergeValues - Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); @@ -555,25 +568,28 @@ public: EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, const Value *SV, int SVOffset, EVT MemVT, bool isVolatile=false, unsigned Alignment=0); + SDValue getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, + EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, + EVT MemVT, MachineMemOperand *MMO); /// getStore - Helper function to build ISD::STORE nodes. /// SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, bool isVolatile=false, unsigned Alignment=0); + SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, EVT TVT, bool isVolatile=false, unsigned Alignment=0); + SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, + EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); - /// getMemOperand - Construct a node to track a memory reference - /// through the backend. - SDValue getMemOperand(const MachineMemOperand &MO); - /// getShiftAmountOperand - Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(SDValue Op); @@ -682,8 +698,10 @@ public: SDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); SDNode *getMachineNode(unsigned Opcode, DebugLoc dl, - const std::vector<EVT> &ResultTys, const SDValue *Ops, - unsigned NumOps); + const std::vector<EVT> &ResultTys, const SDValue *Ops, + unsigned NumOps); + SDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, unsigned NumOps); /// getTargetExtractSubreg - A convenience function for creating /// TargetInstrInfo::EXTRACT_SUBREG nodes. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 9a16903..604f065 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -27,13 +27,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/Support/Allocator.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/RecyclingAllocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include <cassert> -#include <climits> namespace llvm { @@ -536,11 +533,6 @@ namespace ISD { // make reference to a value in the LLVM IR. SRCVALUE, - // MEMOPERAND - This is a node that contains a MachineMemOperand which - // records information about a memory reference. This is used to make - // AliasAnalysis queries from the backend. - MEMOPERAND, - // PCMARKER - This corresponds to the pcmarker intrinsic. PCMARKER, @@ -617,10 +609,17 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, - // BUILTIN_OP_END - This must be the last enum value in this list. + /// BUILTIN_OP_END - This must be the last enum value in this list. + /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END }; + /// FIRST_TARGET_MEMORY_OPCODE - Target-specific pre-isel operations + /// which do not reference a specific memory location should be less than + /// this value. Those that do must not be less than this value, and can + /// be used with SelectionDAG::getMemIntrinsicNode. + static const int FIRST_TARGET_MEMORY_OPCODE = 1 << 14; + /// Node predicates /// isBuildVectorAllOnes - Return true if the specified node is a @@ -867,6 +866,7 @@ public: inline unsigned getNumOperands() const; inline const SDValue &getOperand(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetMemoryOpcode() const; inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; @@ -1031,17 +1031,17 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> { private: /// NodeType - The operation that this node performs. /// - short NodeType; + int16_t NodeType; /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, /// then they will be delete[]'d when the node is destroyed. - unsigned short OperandsNeedDelete : 1; + uint16_t OperandsNeedDelete : 1; protected: /// 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. - unsigned short SubclassData : 15; + uint16_t SubclassData : 15; private: /// NodeId - Unique id per SDNode in the DAG. @@ -1085,6 +1085,13 @@ public: /// \<target\>ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + /// isTargetMemoryOpcode - Test if this node has a target-specific + /// memory-referencing opcode (in the \<target\>ISD namespace and + /// greater than FIRST_TARGET_MEMORY_OPCODE). + bool isTargetMemoryOpcode() const { + return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; + } + /// isMachineOpcode - Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } @@ -1417,6 +1424,9 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { inline bool SDValue::isTargetOpcode() const { return Node->isTargetOpcode(); } +inline bool SDValue::isTargetMemoryOpcode() const { + return Node->isTargetMemoryOpcode(); +} inline bool SDValue::isMachineOpcode() const { return Node->isMachineOpcode(); } @@ -1515,47 +1525,55 @@ private: // MemoryVT - VT of in-memory value. EVT MemoryVT; - //! SrcValue - Memory location for alias analysis. - const Value *SrcValue; +protected: + /// MMO - Memory reference information. + MachineMemOperand *MMO; - //! SVOffset - Memory location offset. Note that base is defined in MemSDNode - int SVOffset; public: MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, - const Value *srcValue, int SVOff, unsigned alignment, - bool isvolatile); + MachineMemOperand *MMO); MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, - unsigned NumOps, EVT MemoryVT, const Value *srcValue, int SVOff, - unsigned alignment, bool isvolatile); + unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + + bool readMem() const { return MMO->isLoad(); } + bool writeMem() const { return MMO->isStore(); } /// Returns alignment and volatility of the memory access unsigned getOriginalAlignment() const { - return (1u << (SubclassData >> 6)) >> 1; + return MMO->getBaseAlignment(); } unsigned getAlignment() const { - return MinAlign(getOriginalAlignment(), SVOffset); + return MMO->getAlignment(); } - bool isVolatile() const { return (SubclassData >> 5) & 1; } /// getRawSubclassData - Return the SubclassData value, which contains an - /// encoding of the alignment and volatile information, as well as bits - /// used by subclasses. This function should only be used to compute a - /// FoldingSetNodeID value. + /// encoding of the volatile flag, as well as bits used by subclasses. This + /// function should only be used to compute a FoldingSetNodeID value. unsigned getRawSubclassData() const { return SubclassData; } + bool isVolatile() const { return (SubclassData >> 5) & 1; } + /// Returns the SrcValue and offset that describes the location of the access - const Value *getSrcValue() const { return SrcValue; } - int getSrcValueOffset() const { return SVOffset; } + const Value *getSrcValue() const { return MMO->getValue(); } + int64_t getSrcValueOffset() const { return MMO->getOffset(); } /// getMemoryVT - Return the type of the in-memory value. EVT getMemoryVT() const { return MemoryVT; } /// getMemOperand - Return a MachineMemOperand object describing the memory /// reference performed by operation. - MachineMemOperand getMemOperand() const; + MachineMemOperand *getMemOperand() const { return MMO; } + + /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// to reflect the alignment of NewMMO, if it has a greater alignment. + /// This must only be used when the new alignment applies to all users of + /// this MachineMemOperand. + void refineAlignment(const MachineMemOperand *NewMMO) { + MMO->refineAlignment(NewMMO); + } const SDValue &getChain() const { return getOperand(0); } const SDValue &getBasePtr() const { @@ -1583,7 +1601,7 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1603,17 +1621,18 @@ public: // Align: alignment of memory AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, const Value* SrcVal, - unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Val, const Value* SrcVal, unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Val, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Val); } @@ -1643,24 +1662,18 @@ public: } }; -/// MemIntrinsicSDNode - This SDNode is used for target intrinsic that touches -/// memory and need an associated memory operand. -/// +/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// memory and need an associated MachineMemOperand. Its opcode may be +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, or a target-specific opcode with a +/// value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { - bool ReadMem; // Intrinsic reads memory - bool WriteMem; // Intrinsic writes memory public: MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps, - EVT MemoryVT, const Value *srcValue, int SVO, - unsigned Align, bool Vol, bool ReadMem, bool WriteMem) - : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, srcValue, SVO, Align, Vol), - ReadMem(ReadMem), WriteMem(WriteMem) { + EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { } - bool readMem() const { return ReadMem; } - bool writeMem() const { return WriteMem; } - // Methods to support isa and dyn_cast static bool classof(const MemIntrinsicSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1668,7 +1681,7 @@ public: // early a node with a target opcode can be of this class return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1956,10 +1969,6 @@ public: /// used when the SelectionDAG needs to make a simple reference to something /// in the LLVM IR representation. /// -/// Note that this is not used for carrying alias information; that is done -/// with MemOperandSDNode, which includes a Value which is required to be a -/// pointer, and several other fields specific to memory references. -/// class SrcValueSDNode : public SDNode { const Value *V; friend class SelectionDAG; @@ -1979,28 +1988,6 @@ public: }; -/// MemOperandSDNode - An SDNode that holds a MachineMemOperand. This is -/// used to represent a reference to memory after ISD::LOAD -/// and ISD::STORE have been lowered. -/// -class MemOperandSDNode : public SDNode { - friend class SelectionDAG; - /// Create a MachineMemOperand node - explicit MemOperandSDNode(const MachineMemOperand &mo) - : SDNode(ISD::MEMOPERAND, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), MO(mo) {} - -public: - /// MO - The contained MachineMemOperand. - const MachineMemOperand MO; - - static bool classof(const MemOperandSDNode *) { return true; } - static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MEMOPERAND; - } -}; - - class RegisterSDNode : public SDNode { unsigned Reg; friend class SelectionDAG; @@ -2269,9 +2256,8 @@ class LSBaseSDNode : public MemSDNode { public: LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, - EVT VT, const Value *SV, int SVO, unsigned Align, bool Vol) - : MemSDNode(NodeTy, dl, VTs, VT, SV, SVO, Align, Vol) { - assert(Align != 0 && "Loads and stores should have non-zero aligment"); + EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); InitOperands(Ops, Operands, numOperands); @@ -2307,12 +2293,14 @@ public: class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT LVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, - VTs, AM, LVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)ETy; assert(getExtensionType() == ETy && "LoadExtType encoding error!"); + assert(readMem() && "Load MachineMemOperand is not a load!"); + assert(!writeMem() && "Load MachineMemOperand is a store!"); } public: @@ -2336,12 +2324,14 @@ public: class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, EVT SVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, - VTs, AM, SVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); + assert(!readMem() && "Store MachineMemOperand is a load!"); + assert(writeMem() && "Store MachineMemOperand is not a store!"); } public: @@ -2360,6 +2350,44 @@ public: } }; +/// MachineSDNode - An SDNode that represents everything that will be needed +/// to construct a MachineInstr. These nodes are created during the +/// instruction selection proper phase. +/// +class MachineSDNode : public SDNode { +public: + typedef MachineMemOperand **mmo_iterator; + +private: + friend class SelectionDAG; + MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + + /// LocalOperands - Operands for this instruction, if they fit here. If + /// they don't, this field is unused. + SDUse LocalOperands[4]; + + /// MemRefs - Memory reference descriptions for this instruction. + mmo_iterator MemRefs; + mmo_iterator MemRefsEnd; + +public: + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + + static bool classof(const MachineSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->isMachineOpcode(); + } +}; class SDNodeIterator : public std::iterator<std::forward_iterator_tag, SDNode, ptrdiff_t> { |