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
This commit is contained in:
Dan Gohman 2009-09-25 20:36:54 +00:00
parent 602b0c8c17
commit c76909abfe
30 changed files with 744 additions and 544 deletions

View File

@ -27,6 +27,7 @@
namespace llvm { namespace llvm {
class Value;
class Function; class Function;
class MachineRegisterInfo; class MachineRegisterInfo;
class MachineFrameInfo; class MachineFrameInfo;
@ -320,6 +321,24 @@ public:
/// ///
void DeleteMachineBasicBlock(MachineBasicBlock *MBB); 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. // Debug location.
// //

View File

@ -20,10 +20,8 @@
#include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetInstrDesc.h"
#include "llvm/Support/DebugLoc.h" #include "llvm/Support/DebugLoc.h"
#include <list>
#include <vector> #include <vector>
namespace llvm { namespace llvm {
@ -32,17 +30,23 @@ class TargetInstrDesc;
class TargetInstrInfo; class TargetInstrInfo;
class TargetRegisterInfo; class TargetRegisterInfo;
class MachineFunction; class MachineFunction;
class MachineMemOperand;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// MachineInstr - Representation of each machine instruction. /// MachineInstr - Representation of each machine instruction.
/// ///
class MachineInstr : public ilist_node<MachineInstr> { class MachineInstr : public ilist_node<MachineInstr> {
public:
typedef MachineMemOperand **mmo_iterator;
private:
const TargetInstrDesc *TID; // Instruction descriptor. const TargetInstrDesc *TID; // Instruction descriptor.
unsigned short NumImplicitOps; // Number of implicit operands (which unsigned short NumImplicitOps; // Number of implicit operands (which
// are determined at construction time). // are determined at construction time).
std::vector<MachineOperand> Operands; // the operands 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. MachineBasicBlock *Parent; // Pointer to the owning basic block.
DebugLoc debugLoc; // Source line information. DebugLoc debugLoc; // Source line information.
@ -132,21 +136,14 @@ public:
unsigned getNumExplicitOperands() const; unsigned getNumExplicitOperands() const;
/// Access to memory operands of the instruction /// Access to memory operands of the instruction
std::list<MachineMemOperand>::iterator memoperands_begin() mmo_iterator memoperands_begin() const { return MemRefs; }
{ return MemOperands.begin(); } mmo_iterator memoperands_end() const { return MemRefsEnd; }
std::list<MachineMemOperand>::iterator memoperands_end() bool memoperands_empty() const { return MemRefsEnd == MemRefs; }
{ 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(); }
/// hasOneMemOperand - Return true if this instruction has exactly one /// hasOneMemOperand - Return true if this instruction has exactly one
/// MachineMemOperand. /// MachineMemOperand.
bool hasOneMemOperand() const { bool hasOneMemOperand() const {
return !memoperands_empty() && return MemRefsEnd - MemRefs == 1;
next(memoperands_begin()) == memoperands_end();
} }
/// isIdenticalTo - Return true if this instruction is identical to (same /// isIdenticalTo - Return true if this instruction is identical to (same
@ -319,13 +316,17 @@ public:
/// ///
void RemoveOperand(unsigned i); void RemoveOperand(unsigned i);
/// addMemOperand - Add a MachineMemOperand to the machine instruction, /// addMemOperand - Add a MachineMemOperand to the machine instruction.
/// referencing arbitrary storage. /// This function should be used only occasionally. The setMemRefs function
void addMemOperand(MachineFunction &MF, /// is the primary method for setting up a MachineInstr's MemRefs list.
const MachineMemOperand &MO); void addMemOperand(MachineFunction &MF, MachineMemOperand *MO);
/// clearMemOperands - Erase all of this MachineInstr's MachineMemOperands. /// setMemRefs - Assign this MachineInstr's memory reference descriptor
void clearMemOperands(MachineFunction &MF); /// list. This does not transfer ownership.
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) {
MemRefs = NewMemRefs;
MemRefsEnd = NewMemRefsEnd;
}
private: private:
/// getRegInfo - If this instruction is embedded into a MachineFunction, /// getRegInfo - If this instruction is embedded into a MachineFunction,

View File

@ -121,7 +121,7 @@ public:
return *this; return *this;
} }
const MachineInstrBuilder &addMemOperand(const MachineMemOperand &MMO) const { const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const {
MI->addMemOperand(*MI->getParent()->getParent(), MMO); MI->addMemOperand(*MI->getParent()->getParent(), MMO);
return *this; return *this;
} }

View File

@ -88,6 +88,16 @@ public:
bool isStore() const { return Flags & MOStore; } bool isStore() const { return Flags & MOStore; }
bool isVolatile() const { return Flags & MOVolatile; } 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. /// Profile - Gather unique data for the object.
/// ///
void Profile(FoldingSetNodeID &ID) const; void Profile(FoldingSetNodeID &ID) const;

View File

@ -516,8 +516,6 @@ namespace llvm {
/// ///
void EmitNoop(); void EmitNoop();
void AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO);
void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap); void EmitPhysRegCopy(SUnit *SU, DenseMap<SUnit*, unsigned> &VRBaseMap);
private: private:

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include <cassert> #include <cassert>
#include <vector> #include <vector>
@ -514,15 +515,23 @@ public:
SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal, SDValue Ptr, SDValue Cmp, SDValue Swp, const Value* PtrVal,
unsigned Alignment=0); 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 /// getAtomic - Gets a node for an atomic op, produces result and chain and
/// takes 2 operands. /// takes 2 operands.
SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain, SDValue getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value* PtrVal, SDValue Ptr, SDValue Val, const Value* PtrVal,
unsigned Alignment = 0); 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 /// 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, SDValue getMemIntrinsicNode(unsigned Opcode, DebugLoc dl,
const EVT *VTs, unsigned NumVTs, const EVT *VTs, unsigned NumVTs,
const SDValue *Ops, unsigned NumOps, const SDValue *Ops, unsigned NumOps,
@ -536,6 +545,10 @@ public:
unsigned Align = 0, bool Vol = false, unsigned Align = 0, bool Vol = false,
bool ReadMem = true, bool WriteMem = true); 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. /// getMergeValues - Create a MERGE_VALUES node from the given operands.
SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl); SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, DebugLoc dl);
@ -555,25 +568,28 @@ public:
EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset,
const Value *SV, int SVOffset, EVT MemVT, const Value *SV, int SVOffset, EVT MemVT,
bool isVolatile=false, unsigned Alignment=0); 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. /// getStore - Helper function to build ISD::STORE nodes.
/// ///
SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, SDValue getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr,
const Value *SV, int SVOffset, bool isVolatile=false, const Value *SV, int SVOffset, bool isVolatile=false,
unsigned Alignment=0); 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, SDValue getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr,
const Value *SV, int SVOffset, EVT TVT, const Value *SV, int SVOffset, EVT TVT,
bool isVolatile=false, unsigned Alignment=0); 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 getIndexedStore(SDValue OrigStoe, DebugLoc dl, SDValue Base,
SDValue Offset, ISD::MemIndexedMode AM); SDValue Offset, ISD::MemIndexedMode AM);
/// getSrcValue - Construct a node to track a Value* through the backend. /// getSrcValue - Construct a node to track a Value* through the backend.
SDValue getSrcValue(const Value *v); 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 /// getShiftAmountOperand - Return the specified value casted to
/// the target's desired shift amount type. /// the target's desired shift amount type.
SDValue getShiftAmountOperand(SDValue Op); SDValue getShiftAmountOperand(SDValue Op);
@ -684,6 +700,8 @@ public:
SDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *getMachineNode(unsigned Opcode, DebugLoc dl,
const std::vector<EVT> &ResultTys, const SDValue *Ops, const std::vector<EVT> &ResultTys, const SDValue *Ops,
unsigned NumOps); unsigned NumOps);
SDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs,
const SDValue *Ops, unsigned NumOps);
/// getTargetExtractSubreg - A convenience function for creating /// getTargetExtractSubreg - A convenience function for creating
/// TargetInstrInfo::EXTRACT_SUBREG nodes. /// TargetInstrInfo::EXTRACT_SUBREG nodes.

View File

@ -27,13 +27,10 @@
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/ValueTypes.h" #include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/DebugLoc.h" #include "llvm/Support/DebugLoc.h"
#include <cassert> #include <cassert>
#include <climits>
namespace llvm { namespace llvm {
@ -536,11 +533,6 @@ namespace ISD {
// make reference to a value in the LLVM IR. // make reference to a value in the LLVM IR.
SRCVALUE, 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 - This corresponds to the pcmarker intrinsic.
PCMARKER, PCMARKER,
@ -617,10 +609,17 @@ namespace ISD {
ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMIN,
ATOMIC_LOAD_UMAX, 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 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 /// Node predicates
/// isBuildVectorAllOnes - Return true if the specified node is a /// isBuildVectorAllOnes - Return true if the specified node is a
@ -867,6 +866,7 @@ public:
inline unsigned getNumOperands() const; inline unsigned getNumOperands() const;
inline const SDValue &getOperand(unsigned i) const; inline const SDValue &getOperand(unsigned i) const;
inline uint64_t getConstantOperandVal(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const;
inline bool isTargetMemoryOpcode() const;
inline bool isTargetOpcode() const; inline bool isTargetOpcode() const;
inline bool isMachineOpcode() const; inline bool isMachineOpcode() const;
inline unsigned getMachineOpcode() const; inline unsigned getMachineOpcode() const;
@ -1031,17 +1031,17 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
private: private:
/// NodeType - The operation that this node performs. /// NodeType - The operation that this node performs.
/// ///
short NodeType; int16_t NodeType;
/// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true,
/// then they will be delete[]'d when the node is destroyed. /// then they will be delete[]'d when the node is destroyed.
unsigned short OperandsNeedDelete : 1; uint16_t OperandsNeedDelete : 1;
protected: protected:
/// SubclassData - This member is defined by this class, but is not used for /// 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. /// anything. Subclasses can use it to hold whatever state they find useful.
/// This field is initialized to zero by the ctor. /// This field is initialized to zero by the ctor.
unsigned short SubclassData : 15; uint16_t SubclassData : 15;
private: private:
/// NodeId - Unique id per SDNode in the DAG. /// NodeId - Unique id per SDNode in the DAG.
@ -1085,6 +1085,13 @@ public:
/// \<target\>ISD namespace). /// \<target\>ISD namespace).
bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } 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 /// isMachineOpcode - Test if this node has a post-isel opcode, directly
/// corresponding to a MachineInstr opcode. /// corresponding to a MachineInstr opcode.
bool isMachineOpcode() const { return NodeType < 0; } bool isMachineOpcode() const { return NodeType < 0; }
@ -1417,6 +1424,9 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const {
inline bool SDValue::isTargetOpcode() const { inline bool SDValue::isTargetOpcode() const {
return Node->isTargetOpcode(); return Node->isTargetOpcode();
} }
inline bool SDValue::isTargetMemoryOpcode() const {
return Node->isTargetMemoryOpcode();
}
inline bool SDValue::isMachineOpcode() const { inline bool SDValue::isMachineOpcode() const {
return Node->isMachineOpcode(); return Node->isMachineOpcode();
} }
@ -1515,47 +1525,55 @@ private:
// MemoryVT - VT of in-memory value. // MemoryVT - VT of in-memory value.
EVT MemoryVT; EVT MemoryVT;
//! SrcValue - Memory location for alias analysis. protected:
const Value *SrcValue; /// MMO - Memory reference information.
MachineMemOperand *MMO;
//! SVOffset - Memory location offset. Note that base is defined in MemSDNode
int SVOffset;
public: public:
MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT,
const Value *srcValue, int SVOff, unsigned alignment, MachineMemOperand *MMO);
bool isvolatile);
MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops,
unsigned NumOps, EVT MemoryVT, const Value *srcValue, int SVOff, unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO);
unsigned alignment, bool isvolatile);
bool readMem() const { return MMO->isLoad(); }
bool writeMem() const { return MMO->isStore(); }
/// Returns alignment and volatility of the memory access /// Returns alignment and volatility of the memory access
unsigned getOriginalAlignment() const { unsigned getOriginalAlignment() const {
return (1u << (SubclassData >> 6)) >> 1; return MMO->getBaseAlignment();
} }
unsigned getAlignment() const { 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 /// getRawSubclassData - Return the SubclassData value, which contains an
/// encoding of the alignment and volatile information, as well as bits /// encoding of the volatile flag, as well as bits used by subclasses. This
/// used by subclasses. This function should only be used to compute a /// function should only be used to compute a FoldingSetNodeID value.
/// FoldingSetNodeID value.
unsigned getRawSubclassData() const { unsigned getRawSubclassData() const {
return SubclassData; return SubclassData;
} }
bool isVolatile() const { return (SubclassData >> 5) & 1; }
/// Returns the SrcValue and offset that describes the location of the access /// Returns the SrcValue and offset that describes the location of the access
const Value *getSrcValue() const { return SrcValue; } const Value *getSrcValue() const { return MMO->getValue(); }
int getSrcValueOffset() const { return SVOffset; } int64_t getSrcValueOffset() const { return MMO->getOffset(); }
/// getMemoryVT - Return the type of the in-memory value. /// getMemoryVT - Return the type of the in-memory value.
EVT getMemoryVT() const { return MemoryVT; } EVT getMemoryVT() const { return MemoryVT; }
/// getMemOperand - Return a MachineMemOperand object describing the memory /// getMemOperand - Return a MachineMemOperand object describing the memory
/// reference performed by operation. /// 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 &getChain() const { return getOperand(0); }
const SDValue &getBasePtr() const { const SDValue &getBasePtr() const {
@ -1583,7 +1601,7 @@ public:
N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX ||
N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_W_CHAIN ||
N->getOpcode() == ISD::INTRINSIC_VOID || N->getOpcode() == ISD::INTRINSIC_VOID ||
N->isTargetOpcode(); N->isTargetMemoryOpcode();
} }
}; };
@ -1603,17 +1621,18 @@ public:
// Align: alignment of memory // Align: alignment of memory
AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT,
SDValue Chain, SDValue Ptr, SDValue Chain, SDValue Ptr,
SDValue Cmp, SDValue Swp, const Value* SrcVal, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO)
unsigned Align=0) : MemSDNode(Opc, dl, VTL, MemVT, MMO) {
: MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, assert(readMem() && "Atomic MachineMemOperand is not a load!");
Align, /*isVolatile=*/true) { assert(writeMem() && "Atomic MachineMemOperand is not a store!");
InitOperands(Ops, Chain, Ptr, Cmp, Swp); InitOperands(Ops, Chain, Ptr, Cmp, Swp);
} }
AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT,
SDValue Chain, SDValue Ptr, SDValue Chain, SDValue Ptr,
SDValue Val, const Value* SrcVal, unsigned Align=0) SDValue Val, MachineMemOperand *MMO)
: MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, : MemSDNode(Opc, dl, VTL, MemVT, MMO) {
Align, /*isVolatile=*/true) { assert(readMem() && "Atomic MachineMemOperand is not a load!");
assert(writeMem() && "Atomic MachineMemOperand is not a store!");
InitOperands(Ops, Chain, Ptr, Val); InitOperands(Ops, Chain, Ptr, Val);
} }
@ -1643,24 +1662,18 @@ public:
} }
}; };
/// MemIntrinsicSDNode - This SDNode is used for target intrinsic that touches /// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch
/// memory and need an associated memory operand. /// 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 { class MemIntrinsicSDNode : public MemSDNode {
bool ReadMem; // Intrinsic reads memory
bool WriteMem; // Intrinsic writes memory
public: public:
MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs,
const SDValue *Ops, unsigned NumOps, const SDValue *Ops, unsigned NumOps,
EVT MemoryVT, const Value *srcValue, int SVO, EVT MemoryVT, MachineMemOperand *MMO)
unsigned Align, bool Vol, bool ReadMem, bool WriteMem) : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) {
: MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, srcValue, SVO, Align, Vol),
ReadMem(ReadMem), WriteMem(WriteMem) {
} }
bool readMem() const { return ReadMem; }
bool writeMem() const { return WriteMem; }
// Methods to support isa and dyn_cast // Methods to support isa and dyn_cast
static bool classof(const MemIntrinsicSDNode *) { return true; } static bool classof(const MemIntrinsicSDNode *) { return true; }
static bool classof(const SDNode *N) { static bool classof(const SDNode *N) {
@ -1668,7 +1681,7 @@ public:
// early a node with a target opcode can be of this class // early a node with a target opcode can be of this class
return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || return N->getOpcode() == ISD::INTRINSIC_W_CHAIN ||
N->getOpcode() == ISD::INTRINSIC_VOID || 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 /// used when the SelectionDAG needs to make a simple reference to something
/// in the LLVM IR representation. /// 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 { class SrcValueSDNode : public SDNode {
const Value *V; const Value *V;
friend class SelectionDAG; 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 { class RegisterSDNode : public SDNode {
unsigned Reg; unsigned Reg;
friend class SelectionDAG; friend class SelectionDAG;
@ -2269,9 +2256,8 @@ class LSBaseSDNode : public MemSDNode {
public: public:
LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands,
unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM,
EVT VT, const Value *SV, int SVO, unsigned Align, bool Vol) EVT MemVT, MachineMemOperand *MMO)
: MemSDNode(NodeTy, dl, VTs, VT, SV, SVO, Align, Vol) { : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) {
assert(Align != 0 && "Loads and stores should have non-zero aligment");
SubclassData |= AM << 2; SubclassData |= AM << 2;
assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); assert(getAddressingMode() == AM && "MemIndexedMode encoding error!");
InitOperands(Ops, Operands, numOperands); InitOperands(Ops, Operands, numOperands);
@ -2307,12 +2293,14 @@ public:
class LoadSDNode : public LSBaseSDNode { class LoadSDNode : public LSBaseSDNode {
friend class SelectionDAG; friend class SelectionDAG;
LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT LVT, ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT,
const Value *SV, int O=0, unsigned Align=0, bool Vol=false) MachineMemOperand *MMO)
: LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3,
VTs, AM, LVT, SV, O, Align, Vol) { VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)ETy; SubclassData |= (unsigned short)ETy;
assert(getExtensionType() == ETy && "LoadExtType encoding error!"); assert(getExtensionType() == ETy && "LoadExtType encoding error!");
assert(readMem() && "Load MachineMemOperand is not a load!");
assert(!writeMem() && "Load MachineMemOperand is a store!");
} }
public: public:
@ -2336,12 +2324,14 @@ public:
class StoreSDNode : public LSBaseSDNode { class StoreSDNode : public LSBaseSDNode {
friend class SelectionDAG; friend class SelectionDAG;
StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs,
ISD::MemIndexedMode AM, bool isTrunc, EVT SVT, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
const Value *SV, int O=0, unsigned Align=0, bool Vol=false) MachineMemOperand *MMO)
: LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4,
VTs, AM, SVT, SV, O, Align, Vol) { VTs, AM, MemVT, MMO) {
SubclassData |= (unsigned short)isTrunc; SubclassData |= (unsigned short)isTrunc;
assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!");
assert(!readMem() && "Store MachineMemOperand is a load!");
assert(writeMem() && "Store MachineMemOperand is not a store!");
} }
public: 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, class SDNodeIterator : public std::iterator<std::forward_iterator_tag,
SDNode, ptrdiff_t> { SDNode, ptrdiff_t> {

View File

@ -25,6 +25,7 @@
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
@ -1443,12 +1444,12 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
// If the instruction accesses memory and the memory could be non-constant, // If the instruction accesses memory and the memory could be non-constant,
// assume the instruction is not rematerializable. // assume the instruction is not rematerializable.
for (std::list<MachineMemOperand>::const_iterator for (MachineInstr::mmo_iterator I = MI->memoperands_begin(),
I = MI->memoperands_begin(), E = MI->memoperands_end(); I != E; ++I){ E = MI->memoperands_end(); I != E; ++I){
const MachineMemOperand &MMO = *I; const MachineMemOperand *MMO = *I;
if (MMO.isVolatile() || MMO.isStore()) if (MMO->isVolatile() || MMO->isStore())
return false; return false;
const Value *V = MMO.getValue(); const Value *V = MMO->getValue();
if (!V) if (!V)
return false; return false;
if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) { if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) {

View File

@ -190,11 +190,6 @@ MachineFunction::CloneMachineInstr(const MachineInstr *Orig) {
/// ///
void void
MachineFunction::DeleteMachineInstr(MachineInstr *MI) { MachineFunction::DeleteMachineInstr(MachineInstr *MI) {
// Clear the instructions memoperands. This must be done manually because
// the instruction's parent pointer is now null, so it can't properly
// deallocate them on its own.
MI->clearMemOperands(*this);
MI->~MachineInstr(); MI->~MachineInstr();
InstructionRecycler.Deallocate(Allocator, MI); InstructionRecycler.Deallocate(Allocator, MI);
} }
@ -217,6 +212,29 @@ MachineFunction::DeleteMachineBasicBlock(MachineBasicBlock *MBB) {
BasicBlockRecycler.Deallocate(Allocator, MBB); BasicBlockRecycler.Deallocate(Allocator, MBB);
} }
MachineMemOperand *
MachineFunction::getMachineMemOperand(const Value *v, unsigned f,
int64_t o, uint64_t s,
unsigned base_alignment) {
return new (Allocator.Allocate<MachineMemOperand>())
MachineMemOperand(v, f, o, s, base_alignment);
}
MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
int64_t Offset, uint64_t Size) {
return new (Allocator.Allocate<MachineMemOperand>())
MachineMemOperand(MMO->getValue(), MMO->getFlags(),
int64_t(uint64_t(MMO->getOffset()) +
uint64_t(Offset)),
Size, MMO->getBaseAlignment());
}
MachineInstr::mmo_iterator
MachineFunction::allocateMemRefsArray(unsigned long Num) {
return Allocator.Allocate<MachineMemOperand *>(Num);
}
void MachineFunction::dump() const { void MachineFunction::dump() const {
print(errs()); print(errs());
} }

View File

@ -17,6 +17,7 @@
#include "llvm/Value.h" #include "llvm/Value.h"
#include "llvm/Assembly/Writer.h" #include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
@ -298,40 +299,56 @@ void MachineMemOperand::Profile(FoldingSetNodeID &ID) const {
ID.AddInteger(Flags); ID.AddInteger(Flags);
} }
raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MRO) { void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) {
assert((MRO.isLoad() || MRO.isStore()) && // The Value and Offset may differ due to CSE. But the flags and size
// should be the same.
assert(MMO->getFlags() == getFlags() && "Flags mismatch!");
assert(MMO->getSize() == getSize() && "Size mismatch!");
if (MMO->getBaseAlignment() >= getBaseAlignment()) {
// Update the alignment value.
Flags = (Flags & 7) | ((Log2_32(MMO->getBaseAlignment()) + 1) << 3);
// Also update the base and offset, because the new alignment may
// not be applicable with the old ones.
V = MMO->getValue();
Offset = MMO->getOffset();
}
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) {
assert((MMO.isLoad() || MMO.isStore()) &&
"SV has to be a load, store or both."); "SV has to be a load, store or both.");
if (MRO.isVolatile()) if (MMO.isVolatile())
OS << "Volatile "; OS << "Volatile ";
if (MRO.isLoad()) if (MMO.isLoad())
OS << "LD"; OS << "LD";
if (MRO.isStore()) if (MMO.isStore())
OS << "ST"; OS << "ST";
OS << MRO.getSize(); OS << MMO.getSize();
// Print the address information. // Print the address information.
OS << "["; OS << "[";
if (!MRO.getValue()) if (!MMO.getValue())
OS << "<unknown>"; OS << "<unknown>";
else else
WriteAsOperand(OS, MRO.getValue(), /*PrintType=*/false); WriteAsOperand(OS, MMO.getValue(), /*PrintType=*/false);
// If the alignment of the memory reference itself differs from the alignment // If the alignment of the memory reference itself differs from the alignment
// of the base pointer, print the base alignment explicitly, next to the base // of the base pointer, print the base alignment explicitly, next to the base
// pointer. // pointer.
if (MRO.getBaseAlignment() != MRO.getAlignment()) if (MMO.getBaseAlignment() != MMO.getAlignment())
OS << "(align=" << MRO.getBaseAlignment() << ")"; OS << "(align=" << MMO.getBaseAlignment() << ")";
if (MRO.getOffset() != 0) if (MMO.getOffset() != 0)
OS << "+" << MRO.getOffset(); OS << "+" << MMO.getOffset();
OS << "]"; OS << "]";
// Print the alignment of the reference. // Print the alignment of the reference.
if (MRO.getBaseAlignment() != MRO.getAlignment() || if (MMO.getBaseAlignment() != MMO.getAlignment() ||
MRO.getBaseAlignment() != MRO.getSize()) MMO.getBaseAlignment() != MMO.getSize())
OS << "(align=" << MRO.getAlignment() << ")"; OS << "(align=" << MMO.getAlignment() << ")";
return OS; return OS;
} }
@ -343,7 +360,8 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MRO) {
/// MachineInstr ctor - This constructor creates a dummy MachineInstr with /// MachineInstr ctor - This constructor creates a dummy MachineInstr with
/// TID NULL and no operands. /// TID NULL and no operands.
MachineInstr::MachineInstr() MachineInstr::MachineInstr()
: TID(0), NumImplicitOps(0), Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { : TID(0), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0),
Parent(0), debugLoc(DebugLoc::getUnknownLoc()) {
// Make sure that we get added to a machine basicblock // Make sure that we get added to a machine basicblock
LeakDetector::addGarbageObject(this); LeakDetector::addGarbageObject(this);
} }
@ -362,7 +380,7 @@ void MachineInstr::addImplicitDefUseOperands() {
/// TargetInstrDesc or the numOperands if it is not zero. (for /// TargetInstrDesc or the numOperands if it is not zero. (for
/// instructions with variable number of operands). /// instructions with variable number of operands).
MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp)
: TID(&tid), NumImplicitOps(0), Parent(0), : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), Parent(0),
debugLoc(DebugLoc::getUnknownLoc()) { debugLoc(DebugLoc::getUnknownLoc()) {
if (!NoImp && TID->getImplicitDefs()) if (!NoImp && TID->getImplicitDefs())
for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
@ -380,7 +398,8 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp)
/// MachineInstr ctor - As above, but with a DebugLoc. /// MachineInstr ctor - As above, but with a DebugLoc.
MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl,
bool NoImp) bool NoImp)
: TID(&tid), NumImplicitOps(0), Parent(0), debugLoc(dl) { : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0),
Parent(0), debugLoc(dl) {
if (!NoImp && TID->getImplicitDefs()) if (!NoImp && TID->getImplicitDefs())
for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
NumImplicitOps++; NumImplicitOps++;
@ -399,7 +418,7 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl,
/// basic block. /// basic block.
/// ///
MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid)
: TID(&tid), NumImplicitOps(0), Parent(0), : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), Parent(0),
debugLoc(DebugLoc::getUnknownLoc()) { debugLoc(DebugLoc::getUnknownLoc()) {
assert(MBB && "Cannot use inserting ctor with null basic block!"); assert(MBB && "Cannot use inserting ctor with null basic block!");
if (TID->ImplicitDefs) if (TID->ImplicitDefs)
@ -419,7 +438,8 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid)
/// ///
MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl,
const TargetInstrDesc &tid) const TargetInstrDesc &tid)
: TID(&tid), NumImplicitOps(0), Parent(0), debugLoc(dl) { : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0),
Parent(0), debugLoc(dl) {
assert(MBB && "Cannot use inserting ctor with null basic block!"); assert(MBB && "Cannot use inserting ctor with null basic block!");
if (TID->ImplicitDefs) if (TID->ImplicitDefs)
for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
@ -437,8 +457,9 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl,
/// MachineInstr ctor - Copies MachineInstr arg exactly /// MachineInstr ctor - Copies MachineInstr arg exactly
/// ///
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
: TID(&MI.getDesc()), NumImplicitOps(0), Parent(0), : TID(&MI.getDesc()), NumImplicitOps(0),
debugLoc(MI.getDebugLoc()) { MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd),
Parent(0), debugLoc(MI.getDebugLoc()) {
Operands.reserve(MI.getNumOperands()); Operands.reserve(MI.getNumOperands());
// Add operands // Add operands
@ -446,11 +467,6 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
addOperand(MI.getOperand(i)); addOperand(MI.getOperand(i));
NumImplicitOps = MI.NumImplicitOps; NumImplicitOps = MI.NumImplicitOps;
// Add memory operands.
for (std::list<MachineMemOperand>::const_iterator i = MI.memoperands_begin(),
j = MI.memoperands_end(); i != j; ++i)
addMemOperand(MF, *i);
// Set parent to null. // Set parent to null.
Parent = 0; Parent = 0;
@ -459,8 +475,6 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
MachineInstr::~MachineInstr() { MachineInstr::~MachineInstr() {
LeakDetector::removeGarbageObject(this); LeakDetector::removeGarbageObject(this);
assert(MemOperands.empty() &&
"MachineInstr being deleted with live memoperands!");
#ifndef NDEBUG #ifndef NDEBUG
for (unsigned i = 0, e = Operands.size(); i != e; ++i) { for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
assert(Operands[i].ParentMI == this && "ParentMI mismatch!"); assert(Operands[i].ParentMI == this && "ParentMI mismatch!");
@ -621,18 +635,24 @@ void MachineInstr::RemoveOperand(unsigned OpNo) {
} }
} }
/// addMemOperand - Add a MachineMemOperand to the machine instruction, /// addMemOperand - Add a MachineMemOperand to the machine instruction.
/// referencing arbitrary storage. /// This function should be used only occasionally. The setMemRefs function
/// is the primary method for setting up a MachineInstr's MemRefs list.
void MachineInstr::addMemOperand(MachineFunction &MF, void MachineInstr::addMemOperand(MachineFunction &MF,
const MachineMemOperand &MO) { MachineMemOperand *MO) {
MemOperands.push_back(MO); mmo_iterator OldMemRefs = MemRefs;
} mmo_iterator OldMemRefsEnd = MemRefsEnd;
/// clearMemOperands - Erase all of this MachineInstr's MachineMemOperands. size_t NewNum = (MemRefsEnd - MemRefs) + 1;
void MachineInstr::clearMemOperands(MachineFunction &MF) { mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NewNum);
MemOperands.clear(); mmo_iterator NewMemRefsEnd = NewMemRefs + NewNum;
}
std::copy(OldMemRefs, OldMemRefsEnd, NewMemRefs);
NewMemRefs[NewNum - 1] = MO;
MemRefs = NewMemRefs;
MemRefsEnd = NewMemRefsEnd;
}
/// removeFromParent - This method unlinks 'this' from the containing basic /// removeFromParent - This method unlinks 'this' from the containing basic
/// block, and returns it, but does not delete it. /// block, and returns it, but does not delete it.
@ -972,9 +992,8 @@ bool MachineInstr::hasVolatileMemoryRef() const {
return true; return true;
// Check the memory reference information for volatile references. // Check the memory reference information for volatile references.
for (std::list<MachineMemOperand>::const_iterator I = memoperands_begin(), for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I)
E = memoperands_end(); I != E; ++I) if ((*I)->isVolatile())
if (I->isVolatile())
return true; return true;
return false; return false;
@ -1004,9 +1023,9 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
if (!memoperands_empty()) { if (!memoperands_empty()) {
OS << ", Mem:"; OS << ", Mem:";
for (std::list<MachineMemOperand>::const_iterator i = memoperands_begin(), for (mmo_iterator i = memoperands_begin(), e = memoperands_end();
e = memoperands_end(); i != e; ++i) { i != e; ++i) {
OS << *i; OS << **i;
if (next(i) != e) if (next(i) != e)
OS << " "; OS << " ";
} }

View File

@ -28,10 +28,6 @@
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
using namespace llvm; using namespace llvm;
void ScheduleDAG::AddMemOperand(MachineInstr *MI, const MachineMemOperand &MO) {
MI->addMemOperand(MF, MO);
}
void ScheduleDAG::EmitNoop() { void ScheduleDAG::EmitNoop() {
TII->insertNoop(*BB, InsertPos); TII->insertNoop(*BB, InsertPos);
} }

View File

@ -17,6 +17,7 @@
#include "llvm/Operator.h" #include "llvm/Operator.h"
#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
@ -96,11 +97,11 @@ static const Value *getUnderlyingObject(const Value *V) {
/// object, return the Value for that object. Otherwise return null. /// object, return the Value for that object. Otherwise return null.
static const Value *getUnderlyingObjectForInstr(const MachineInstr *MI) { static const Value *getUnderlyingObjectForInstr(const MachineInstr *MI) {
if (!MI->hasOneMemOperand() || if (!MI->hasOneMemOperand() ||
!MI->memoperands_begin()->getValue() || !(*MI->memoperands_begin())->getValue() ||
MI->memoperands_begin()->isVolatile()) (*MI->memoperands_begin())->isVolatile())
return 0; return 0;
const Value *V = MI->memoperands_begin()->getValue(); const Value *V = (*MI->memoperands_begin())->getValue();
if (!V) if (!V)
return 0; return 0;
@ -335,10 +336,10 @@ void ScheduleDAGInstrs::BuildSchedGraph() {
if (!ChainTID.isCall() && if (!ChainTID.isCall() &&
!ChainTID.hasUnmodeledSideEffects() && !ChainTID.hasUnmodeledSideEffects() &&
ChainMI->hasOneMemOperand() && ChainMI->hasOneMemOperand() &&
!ChainMI->memoperands_begin()->isVolatile() && !(*ChainMI->memoperands_begin())->isVolatile() &&
ChainMI->memoperands_begin()->getValue()) (*ChainMI->memoperands_begin())->getValue())
// We know that the Chain accesses one specific memory location. // We know that the Chain accesses one specific memory location.
ChainMMO = &*ChainMI->memoperands_begin(); ChainMMO = *ChainMI->memoperands_begin();
else else
// Unknown memory accesses. Assume the worst. // Unknown memory accesses. Assume the worst.
ChainMMO = 0; ChainMMO = 0;

View File

@ -263,19 +263,10 @@ unsigned ScheduleDAGSDNodes::CountResults(SDNode *Node) {
} }
/// CountOperands - The inputs to target nodes have any actual inputs first, /// CountOperands - The inputs to target nodes have any actual inputs first,
/// followed by special operands that describe memory references, then an /// followed by an optional chain operand, then an optional flag operand.
/// optional chain operand, then an optional flag operand. Compute the number /// Compute the number of actual operands that will go into the resulting
/// of actual operands that will go into the resulting MachineInstr. /// MachineInstr.
unsigned ScheduleDAGSDNodes::CountOperands(SDNode *Node) { unsigned ScheduleDAGSDNodes::CountOperands(SDNode *Node) {
unsigned N = ComputeMemOperandsEnd(Node);
while (N && isa<MemOperandSDNode>(Node->getOperand(N - 1).getNode()))
--N; // Ignore MEMOPERAND nodes
return N;
}
/// ComputeMemOperandsEnd - Find the index one past the last MemOperandSDNode
/// operand
unsigned ScheduleDAGSDNodes::ComputeMemOperandsEnd(SDNode *Node) {
unsigned N = Node->getNumOperands(); unsigned N = Node->getNumOperands();
while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag) while (N && Node->getOperand(N - 1).getValueType() == MVT::Flag)
--N; --N;
@ -284,7 +275,6 @@ unsigned ScheduleDAGSDNodes::ComputeMemOperandsEnd(SDNode *Node) {
return N; return N;
} }
void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const { void ScheduleDAGSDNodes::dumpNode(const SUnit *SU) const {
if (!SU->getNode()) { if (!SU->getNode()) {
errs() << "PHYS REG COPY\n"; errs() << "PHYS REG COPY\n";

View File

@ -58,7 +58,6 @@ namespace llvm {
if (isa<ConstantPoolSDNode>(Node)) return true; if (isa<ConstantPoolSDNode>(Node)) return true;
if (isa<JumpTableSDNode>(Node)) return true; if (isa<JumpTableSDNode>(Node)) return true;
if (isa<ExternalSymbolSDNode>(Node)) return true; if (isa<ExternalSymbolSDNode>(Node)) return true;
if (isa<MemOperandSDNode>(Node)) return true;
if (Node->getOpcode() == ISD::EntryToken) return true; if (Node->getOpcode() == ISD::EntryToken) return true;
return false; return false;
} }
@ -99,15 +98,11 @@ namespace llvm {
static unsigned CountResults(SDNode *Node); static unsigned CountResults(SDNode *Node);
/// CountOperands - The inputs to target nodes have any actual inputs first, /// CountOperands - The inputs to target nodes have any actual inputs first,
/// followed by special operands that describe memory references, then an /// followed by an optional chain operand, then flag operands. Compute
/// optional chain operand, then flag operands. Compute the number of /// the number of actual operands that will go into the resulting
/// actual operands that will go into the resulting MachineInstr. /// MachineInstr.
static unsigned CountOperands(SDNode *Node); static unsigned CountOperands(SDNode *Node);
/// ComputeMemOperandsEnd - Find the index one past the last
/// MemOperandSDNode operand
static unsigned ComputeMemOperandsEnd(SDNode *Node);
/// EmitNode - Generate machine code for an node and needed dependencies. /// EmitNode - Generate machine code for an node and needed dependencies.
/// VRBaseMap contains, for each already emitted node, the first virtual /// VRBaseMap contains, for each already emitted node, the first virtual
/// register number for the results of the node. /// register number for the results of the node.

View File

@ -497,7 +497,6 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
const TargetInstrDesc &II = TII->get(Opc); const TargetInstrDesc &II = TII->get(Opc);
unsigned NumResults = CountResults(Node); unsigned NumResults = CountResults(Node);
unsigned NodeOperands = CountOperands(Node); unsigned NodeOperands = CountOperands(Node);
unsigned MemOperandsEnd = ComputeMemOperandsEnd(Node);
bool HasPhysRegOuts = (NumResults > II.getNumDefs()) && bool HasPhysRegOuts = (NumResults > II.getNumDefs()) &&
II.getImplicitDefs() != 0; II.getImplicitDefs() != 0;
#ifndef NDEBUG #ifndef NDEBUG
@ -525,9 +524,9 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
AddOperand(MI, Node->getOperand(i), i-NumSkip+II.getNumDefs(), &II, AddOperand(MI, Node->getOperand(i), i-NumSkip+II.getNumDefs(), &II,
VRBaseMap); VRBaseMap);
// Emit all of the memory operands of this instruction // Transfer all of the memory reference descriptions of this instruction.
for (unsigned i = NodeOperands; i != MemOperandsEnd; ++i) MI->setMemRefs(cast<MachineSDNode>(Node)->memoperands_begin(),
AddMemOperand(MI,cast<MemOperandSDNode>(Node->getOperand(i+NumSkip))->MO); cast<MachineSDNode>(Node)->memoperands_end());
if (II.usesCustomDAGSchedInsertionHook()) { if (II.usesCustomDAGSchedInsertionHook()) {
// Insert this instruction into the basic block using a target // Insert this instruction into the basic block using a target

View File

@ -402,11 +402,6 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
case ISD::SRCVALUE: case ISD::SRCVALUE:
ID.AddPointer(cast<SrcValueSDNode>(N)->getValue()); ID.AddPointer(cast<SrcValueSDNode>(N)->getValue());
break; break;
case ISD::MEMOPERAND: {
const MachineMemOperand &MO = cast<MemOperandSDNode>(N)->MO;
MO.Profile(ID);
break;
}
case ISD::FrameIndex: case ISD::FrameIndex:
case ISD::TargetFrameIndex: case ISD::TargetFrameIndex:
ID.AddInteger(cast<FrameIndexSDNode>(N)->getIndex()); ID.AddInteger(cast<FrameIndexSDNode>(N)->getIndex());
@ -481,20 +476,18 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) {
} }
/// encodeMemSDNodeFlags - Generic routine for computing a value for use in /// encodeMemSDNodeFlags - Generic routine for computing a value for use in
/// the CSE map that carries alignment, volatility, indexing mode, and /// the CSE map that carries volatility, indexing mode, and
/// extension/truncation information. /// extension/truncation information.
/// ///
static inline unsigned static inline unsigned
encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, bool isVolatile) {
bool isVolatile, unsigned Alignment) {
assert((ConvType & 3) == ConvType && assert((ConvType & 3) == ConvType &&
"ConvType may not require more than 2 bits!"); "ConvType may not require more than 2 bits!");
assert((AM & 7) == AM && assert((AM & 7) == AM &&
"AM may not require more than 3 bits!"); "AM may not require more than 3 bits!");
return ConvType | return ConvType |
(AM << 2) | (AM << 2) |
(isVolatile << 5) | (isVolatile << 5);
((Log2_32(Alignment) + 1) << 6);
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -1330,28 +1323,6 @@ SDValue SelectionDAG::getSrcValue(const Value *V) {
return SDValue(N, 0); return SDValue(N, 0);
} }
SDValue SelectionDAG::getMemOperand(const MachineMemOperand &MO) {
#ifndef NDEBUG
const Value *v = MO.getValue();
assert((!v || isa<PointerType>(v->getType())) &&
"SrcValue is not a pointer?");
#endif
FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::MEMOPERAND, getVTList(MVT::Other), 0, 0);
MO.Profile(ID);
void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
return SDValue(E, 0);
SDNode *N = NodeAllocator.Allocate<MemOperandSDNode>();
new (N) MemOperandSDNode(MO);
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
return SDValue(N, 0);
}
/// getShiftAmountOperand - Return the specified value casted to /// getShiftAmountOperand - Return the specified value casted to
/// the target's desired shift amount type. /// the target's desired shift amount type.
SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) {
@ -3523,25 +3494,49 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
SDValue Ptr, SDValue Cmp, SDValue Ptr, SDValue Cmp,
SDValue Swp, const Value* PtrVal, SDValue Swp, const Value* PtrVal,
unsigned Alignment) { unsigned Alignment) {
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(MemVT);
// Check if the memory reference references a frame index
if (!PtrVal)
if (const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(Ptr.getNode()))
PtrVal = PseudoSourceValue::getFixedStack(FI->getIndex());
MachineFunction &MF = getMachineFunction();
unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore;
// For now, atomics are considered to be volatile always.
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrVal, Flags, 0,
MemVT.getStoreSize(), Alignment);
return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Cmp, Swp, MMO);
}
SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
SDValue Chain,
SDValue Ptr, SDValue Cmp,
SDValue Swp, MachineMemOperand *MMO) {
assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op"); assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op");
assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types"); assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types");
EVT VT = Cmp.getValueType(); EVT VT = Cmp.getValueType();
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(MemVT);
SDVTList VTs = getVTList(VT, MVT::Other); SDVTList VTs = getVTList(VT, MVT::Other);
FoldingSetNodeID ID; FoldingSetNodeID ID;
ID.AddInteger(MemVT.getRawBits()); ID.AddInteger(MemVT.getRawBits());
SDValue Ops[] = {Chain, Ptr, Cmp, Swp}; SDValue Ops[] = {Chain, Ptr, Cmp, Swp};
AddNodeIDNode(ID, Opcode, VTs, Ops, 4); AddNodeIDNode(ID, Opcode, VTs, Ops, 4);
void* IP = 0; void* IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<AtomicSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
SDNode* N = NodeAllocator.Allocate<AtomicSDNode>(); SDNode* N = NodeAllocator.Allocate<AtomicSDNode>();
new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO);
Chain, Ptr, Cmp, Swp, PtrVal, Alignment);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3552,6 +3547,32 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
SDValue Ptr, SDValue Val, SDValue Ptr, SDValue Val,
const Value* PtrVal, const Value* PtrVal,
unsigned Alignment) { unsigned Alignment) {
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(MemVT);
// Check if the memory reference references a frame index
if (!PtrVal)
if (const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(Ptr.getNode()))
PtrVal = PseudoSourceValue::getFixedStack(FI->getIndex());
MachineFunction &MF = getMachineFunction();
unsigned Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore;
// For now, atomics are considered to be volatile always.
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(PtrVal, Flags, 0,
MemVT.getStoreSize(), Alignment);
return getAtomic(Opcode, dl, MemVT, Chain, Ptr, Val, MMO);
}
SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
SDValue Chain,
SDValue Ptr, SDValue Val,
MachineMemOperand *MMO) {
assert((Opcode == ISD::ATOMIC_LOAD_ADD || assert((Opcode == ISD::ATOMIC_LOAD_ADD ||
Opcode == ISD::ATOMIC_LOAD_SUB || Opcode == ISD::ATOMIC_LOAD_SUB ||
Opcode == ISD::ATOMIC_LOAD_AND || Opcode == ISD::ATOMIC_LOAD_AND ||
@ -3567,20 +3588,18 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
EVT VT = Val.getValueType(); EVT VT = Val.getValueType();
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(MemVT);
SDVTList VTs = getVTList(VT, MVT::Other); SDVTList VTs = getVTList(VT, MVT::Other);
FoldingSetNodeID ID; FoldingSetNodeID ID;
ID.AddInteger(MemVT.getRawBits()); ID.AddInteger(MemVT.getRawBits());
SDValue Ops[] = {Chain, Ptr, Val}; SDValue Ops[] = {Chain, Ptr, Val};
AddNodeIDNode(ID, Opcode, VTs, Ops, 3); AddNodeIDNode(ID, Opcode, VTs, Ops, 3);
void* IP = 0; void* IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<AtomicSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
SDNode* N = NodeAllocator.Allocate<AtomicSDNode>(); SDNode* N = NodeAllocator.Allocate<AtomicSDNode>();
new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO);
Chain, Ptr, Val, PtrVal, Alignment);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3619,23 +3638,51 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList,
EVT MemVT, const Value *srcValue, int SVOff, EVT MemVT, const Value *srcValue, int SVOff,
unsigned Align, bool Vol, unsigned Align, bool Vol,
bool ReadMem, bool WriteMem) { bool ReadMem, bool WriteMem) {
if (Align == 0) // Ensure that codegen never sees alignment 0
Align = getEVTAlignment(MemVT);
MachineFunction &MF = getMachineFunction();
unsigned Flags = 0;
if (WriteMem)
Flags |= MachineMemOperand::MOStore;
if (ReadMem)
Flags |= MachineMemOperand::MOLoad;
if (Vol)
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(srcValue, Flags, SVOff,
MemVT.getStoreSize(), Align);
return getMemIntrinsicNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO);
}
SDValue
SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList,
const SDValue *Ops, unsigned NumOps,
EVT MemVT, MachineMemOperand *MMO) {
assert((Opcode == ISD::INTRINSIC_VOID ||
Opcode == ISD::INTRINSIC_W_CHAIN ||
(Opcode <= INT_MAX &&
(int)Opcode >= ISD::FIRST_TARGET_MEMORY_OPCODE)) &&
"Opcode is not a memory-accessing opcode!");
// Memoize the node unless it returns a flag. // Memoize the node unless it returns a flag.
MemIntrinsicSDNode *N; MemIntrinsicSDNode *N;
if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) { if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) {
FoldingSetNodeID ID; FoldingSetNodeID ID;
AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps);
void *IP = 0; void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<MemIntrinsicSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
N = NodeAllocator.Allocate<MemIntrinsicSDNode>(); N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO);
srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
} else { } else {
N = NodeAllocator.Allocate<MemIntrinsicSDNode>(); N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO);
srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
} }
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3650,6 +3697,27 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
if (Alignment == 0) // Ensure that codegen never sees alignment 0 if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(VT); Alignment = getEVTAlignment(VT);
// Check if the memory reference references a frame index
if (!SV)
if (const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(Ptr.getNode()))
SV = PseudoSourceValue::getFixedStack(FI->getIndex());
MachineFunction &MF = getMachineFunction();
unsigned Flags = MachineMemOperand::MOLoad;
if (isVolatile)
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(SV, Flags, SVOffset,
MemVT.getStoreSize(), Alignment);
return getLoad(AM, dl, ExtType, VT, Chain, Ptr, Offset, MemVT, MMO);
}
SDValue
SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
ISD::LoadExtType ExtType, EVT VT, SDValue Chain,
SDValue Ptr, SDValue Offset, EVT MemVT,
MachineMemOperand *MMO) {
if (VT == MemVT) { if (VT == MemVT) {
ExtType = ISD::NON_EXTLOAD; ExtType = ISD::NON_EXTLOAD;
} else if (ExtType == ISD::NON_EXTLOAD) { } else if (ExtType == ISD::NON_EXTLOAD) {
@ -3678,13 +3746,14 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
FoldingSetNodeID ID; FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3);
ID.AddInteger(MemVT.getRawBits()); ID.AddInteger(MemVT.getRawBits());
ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, isVolatile, Alignment)); ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, MMO->isVolatile()));
void *IP = 0; void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<LoadSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
SDNode *N = NodeAllocator.Allocate<LoadSDNode>(); SDNode *N = NodeAllocator.Allocate<LoadSDNode>();
new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, SV, SVOffset, new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO);
Alignment, isVolatile);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3724,25 +3793,43 @@ SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base,
SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val,
SDValue Ptr, const Value *SV, int SVOffset, SDValue Ptr, const Value *SV, int SVOffset,
bool isVolatile, unsigned Alignment) { bool isVolatile, unsigned Alignment) {
EVT VT = Val.getValueType();
if (Alignment == 0) // Ensure that codegen never sees alignment 0 if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(VT); Alignment = getEVTAlignment(Val.getValueType());
// Check if the memory reference references a frame index
if (!SV)
if (const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(Ptr.getNode()))
SV = PseudoSourceValue::getFixedStack(FI->getIndex());
MachineFunction &MF = getMachineFunction();
unsigned Flags = MachineMemOperand::MOStore;
if (isVolatile)
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(SV, Flags, SVOffset,
Val.getValueType().getStoreSize(), Alignment);
return getStore(Chain, dl, Val, Ptr, MMO);
}
SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val,
SDValue Ptr, MachineMemOperand *MMO) {
EVT VT = Val.getValueType();
SDVTList VTs = getVTList(MVT::Other); SDVTList VTs = getVTList(MVT::Other);
SDValue Undef = getUNDEF(Ptr.getValueType()); SDValue Undef = getUNDEF(Ptr.getValueType());
SDValue Ops[] = { Chain, Val, Ptr, Undef }; SDValue Ops[] = { Chain, Val, Ptr, Undef };
FoldingSetNodeID ID; FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4);
ID.AddInteger(VT.getRawBits()); ID.AddInteger(VT.getRawBits());
ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, MMO->isVolatile()));
isVolatile, Alignment));
void *IP = 0; void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<StoreSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO);
VT, SV, SVOffset, Alignment, isVolatile);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3752,17 +3839,37 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val,
SDValue Ptr, const Value *SV, SDValue Ptr, const Value *SV,
int SVOffset, EVT SVT, int SVOffset, EVT SVT,
bool isVolatile, unsigned Alignment) { bool isVolatile, unsigned Alignment) {
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(SVT);
// Check if the memory reference references a frame index
if (!SV)
if (const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(Ptr.getNode()))
SV = PseudoSourceValue::getFixedStack(FI->getIndex());
MachineFunction &MF = getMachineFunction();
unsigned Flags = MachineMemOperand::MOStore;
if (isVolatile)
Flags |= MachineMemOperand::MOVolatile;
MachineMemOperand *MMO =
MF.getMachineMemOperand(SV, Flags, SVOffset, SVT.getStoreSize(), Alignment);
return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO);
}
SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val,
SDValue Ptr, EVT SVT,
MachineMemOperand *MMO) {
EVT VT = Val.getValueType(); EVT VT = Val.getValueType();
if (VT == SVT) if (VT == SVT)
return getStore(Chain, dl, Val, Ptr, SV, SVOffset, isVolatile, Alignment); return getStore(Chain, dl, Val, Ptr, MMO);
assert(VT.bitsGT(SVT) && "Not a truncation?"); assert(VT.bitsGT(SVT) && "Not a truncation?");
assert(VT.isInteger() == SVT.isInteger() && assert(VT.isInteger() == SVT.isInteger() &&
"Can't do FP-INT conversion!"); "Can't do FP-INT conversion!");
if (Alignment == 0) // Ensure that codegen never sees alignment 0
Alignment = getEVTAlignment(VT);
SDVTList VTs = getVTList(MVT::Other); SDVTList VTs = getVTList(MVT::Other);
SDValue Undef = getUNDEF(Ptr.getValueType()); SDValue Undef = getUNDEF(Ptr.getValueType());
@ -3770,14 +3877,14 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val,
FoldingSetNodeID ID; FoldingSetNodeID ID;
AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4);
ID.AddInteger(SVT.getRawBits()); ID.AddInteger(SVT.getRawBits());
ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, MMO->isVolatile()));
isVolatile, Alignment));
void *IP = 0; void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) {
cast<StoreSDNode>(E)->refineAlignment(MMO);
return SDValue(E, 0); return SDValue(E, 0);
}
SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO);
SVT, SV, SVOffset, Alignment, isVolatile);
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -3801,8 +3908,7 @@ SelectionDAG::getIndexedStore(SDValue OrigStore, DebugLoc dl, SDValue Base,
SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
new (N) StoreSDNode(Ops, dl, VTs, AM, new (N) StoreSDNode(Ops, dl, VTs, AM,
ST->isTruncatingStore(), ST->getMemoryVT(), ST->isTruncatingStore(), ST->getMemoryVT(),
ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemOperand());
ST->getAlignment(), ST->isVolatile());
CSEMap.InsertNode(N, IP); CSEMap.InsertNode(N, IP);
AllNodes.push_back(N); AllNodes.push_back(N);
return SDValue(N, 0); return SDValue(N, 0);
@ -4454,29 +4560,35 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
DeadNodeSet.insert(Used); DeadNodeSet.insert(Used);
} }
if (MachineSDNode *MN = dyn_cast<MachineSDNode>(N)) {
// Initialize the memory references information.
MN->setMemRefs(0, 0);
// If NumOps is larger than the # of operands we can have in a
// MachineSDNode, reallocate the operand list.
if (NumOps > MN->NumOperands || !MN->OperandsNeedDelete) {
if (MN->OperandsNeedDelete)
delete[] MN->OperandList;
if (NumOps > array_lengthof(MN->LocalOperands))
// We're creating a final node that will live unmorphed for the
// remainder of the current SelectionDAG iteration, so we can allocate
// the operands directly out of a pool with no recycling metadata.
MN->InitOperands(OperandAllocator.Allocate<SDUse>(NumOps),
Ops, NumOps);
else
MN->InitOperands(MN->LocalOperands, Ops, NumOps);
MN->OperandsNeedDelete = false;
} else
MN->InitOperands(MN->OperandList, Ops, NumOps);
} else {
// If NumOps is larger than the # of operands we currently have, reallocate // If NumOps is larger than the # of operands we currently have, reallocate
// the operand list. // the operand list.
if (NumOps > N->NumOperands) { if (NumOps > N->NumOperands) {
if (N->OperandsNeedDelete) if (N->OperandsNeedDelete)
delete[] N->OperandList; delete[] N->OperandList;
N->InitOperands(new SDUse[NumOps], Ops, NumOps);
if (N->isMachineOpcode()) {
// We're creating a final node that will live unmorphed for the
// remainder of the current SelectionDAG iteration, so we can allocate
// the operands directly out of a pool with no recycling metadata.
N->OperandList = OperandAllocator.Allocate<SDUse>(NumOps);
N->OperandsNeedDelete = false;
} else {
N->OperandList = new SDUse[NumOps];
N->OperandsNeedDelete = true; N->OperandsNeedDelete = true;
} } else
} MN->InitOperands(MN->OperandList, Ops, NumOps);
// Assign the new operands.
N->NumOperands = NumOps;
for (unsigned i = 0, e = NumOps; i != e; ++i) {
N->OperandList[i].setUser(N);
N->OperandList[i].setInitial(Ops[i]);
} }
// Delete any nodes that are still dead after adding the uses for the // Delete any nodes that are still dead after adding the uses for the
@ -4501,41 +4613,49 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
/// node of the specified opcode and operands, it returns that node instead of /// node of the specified opcode and operands, it returns that node instead of
/// the current one. /// the current one.
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT) { SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT) {
return getNode(~Opcode, dl, VT).getNode(); SDVTList VTs = getVTList(VT);
return getMachineNode(Opcode, dl, VTs, 0, 0);
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT,
SDValue Op1) { SDValue Op1) {
return getNode(~Opcode, dl, VT, Op1).getNode(); SDVTList VTs = getVTList(VT);
SDValue Ops[] = { Op1 };
return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT,
SDValue Op1, SDValue Op2) { SDValue Op1, SDValue Op2) {
return getNode(~Opcode, dl, VT, Op1, Op2).getNode(); SDVTList VTs = getVTList(VT);
SDValue Ops[] = { Op1, Op2 };
return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT,
SDValue Op1, SDValue Op2, SDValue Op1, SDValue Op2,
SDValue Op3) { SDValue Op3) {
return getNode(~Opcode, dl, VT, Op1, Op2, Op3).getNode(); SDVTList VTs = getVTList(VT);
SDValue Ops[] = { Op1, Op2, Op3 };
return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT,
const SDValue *Ops, unsigned NumOps) { const SDValue *Ops, unsigned NumOps) {
return getNode(~Opcode, dl, VT, Ops, NumOps).getNode(); SDVTList VTs = getVTList(VT);
return getMachineNode(Opcode, dl, VTs, Ops, NumOps);
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
EVT VT1, EVT VT2) { EVT VT1, EVT VT2) {
SDVTList VTs = getVTList(VT1, VT2); SDVTList VTs = getVTList(VT1, VT2);
SDValue Op; return getMachineNode(Opcode, dl, VTs, 0, 0);
return getNode(~Opcode, dl, VTs, &Op, 0).getNode();
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
EVT VT2, SDValue Op1) { EVT VT2, SDValue Op1) {
SDVTList VTs = getVTList(VT1, VT2); SDVTList VTs = getVTList(VT1, VT2);
return getNode(~Opcode, dl, VTs, &Op1, 1).getNode(); SDValue Ops[] = { Op1 };
return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
@ -4543,7 +4663,7 @@ SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
SDValue Op2) { SDValue Op2) {
SDVTList VTs = getVTList(VT1, VT2); SDVTList VTs = getVTList(VT1, VT2);
SDValue Ops[] = { Op1, Op2 }; SDValue Ops[] = { Op1, Op2 };
return getNode(~Opcode, dl, VTs, Ops, 2).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
@ -4551,14 +4671,14 @@ SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
SDValue Op2, SDValue Op3) { SDValue Op2, SDValue Op3) {
SDVTList VTs = getVTList(VT1, VT2); SDVTList VTs = getVTList(VT1, VT2);
SDValue Ops[] = { Op1, Op2, Op3 }; SDValue Ops[] = { Op1, Op2, Op3 };
return getNode(~Opcode, dl, VTs, Ops, 3).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
EVT VT1, EVT VT2, EVT VT1, EVT VT2,
const SDValue *Ops, unsigned NumOps) { const SDValue *Ops, unsigned NumOps) {
SDVTList VTs = getVTList(VT1, VT2); SDVTList VTs = getVTList(VT1, VT2);
return getNode(~Opcode, dl, VTs, Ops, NumOps).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, NumOps);
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
@ -4566,7 +4686,7 @@ SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
SDValue Op1, SDValue Op2) { SDValue Op1, SDValue Op2) {
SDVTList VTs = getVTList(VT1, VT2, VT3); SDVTList VTs = getVTList(VT1, VT2, VT3);
SDValue Ops[] = { Op1, Op2 }; SDValue Ops[] = { Op1, Op2 };
return getNode(~Opcode, dl, VTs, Ops, 2).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
@ -4575,27 +4695,67 @@ SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
SDValue Op3) { SDValue Op3) {
SDVTList VTs = getVTList(VT1, VT2, VT3); SDVTList VTs = getVTList(VT1, VT2, VT3);
SDValue Ops[] = { Op1, Op2, Op3 }; SDValue Ops[] = { Op1, Op2, Op3 };
return getNode(~Opcode, dl, VTs, Ops, 3).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, array_lengthof(Ops));
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
EVT VT1, EVT VT2, EVT VT3, EVT VT1, EVT VT2, EVT VT3,
const SDValue *Ops, unsigned NumOps) { const SDValue *Ops, unsigned NumOps) {
SDVTList VTs = getVTList(VT1, VT2, VT3); SDVTList VTs = getVTList(VT1, VT2, VT3);
return getNode(~Opcode, dl, VTs, Ops, NumOps).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, NumOps);
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1,
EVT VT2, EVT VT3, EVT VT4, EVT VT2, EVT VT3, EVT VT4,
const SDValue *Ops, unsigned NumOps) { const SDValue *Ops, unsigned NumOps) {
SDVTList VTs = getVTList(VT1, VT2, VT3, VT4); SDVTList VTs = getVTList(VT1, VT2, VT3, VT4);
return getNode(~Opcode, dl, VTs, Ops, NumOps).getNode(); return getMachineNode(Opcode, dl, VTs, Ops, NumOps);
} }
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl, SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc dl,
const std::vector<EVT> &ResultTys, const std::vector<EVT> &ResultTys,
const SDValue *Ops, unsigned NumOps) { const SDValue *Ops, unsigned NumOps) {
return getNode(~Opcode, dl, ResultTys, Ops, NumOps).getNode(); SDVTList VTs = getVTList(&ResultTys[0], ResultTys.size());
return getMachineNode(Opcode, dl, VTs, Ops, NumOps);
}
SDNode *SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc DL, SDVTList VTs,
const SDValue *Ops, unsigned NumOps) {
bool DoCSE = VTs.VTs[VTs.NumVTs-1] != MVT::Flag;
MachineSDNode *N;
void *IP;
if (DoCSE) {
FoldingSetNodeID ID;
AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps);
IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
return E;
}
// Allocate a new MachineSDNode.
N = NodeAllocator.Allocate<MachineSDNode>();
new (N) MachineSDNode(~Opcode, DL, VTs);
// Initialize the operands list.
if (NumOps > array_lengthof(N->LocalOperands))
// We're creating a final node that will live unmorphed for the
// remainder of the current SelectionDAG iteration, so we can allocate
// the operands directly out of a pool with no recycling metadata.
N->InitOperands(OperandAllocator.Allocate<SDUse>(NumOps),
Ops, NumOps);
else
N->InitOperands(N->LocalOperands, Ops, NumOps);
N->OperandsNeedDelete = false;
if (DoCSE)
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
#ifndef NDEBUG
VerifyNode(N);
#endif
return N;
} }
/// getTargetExtractSubreg - A convenience function for creating /// getTargetExtractSubreg - A convenience function for creating
@ -4968,57 +5128,21 @@ GlobalAddressSDNode::GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA,
} }
MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT memvt, MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT memvt,
const Value *srcValue, int SVO, unsigned alignment, MachineMemOperand *mmo)
bool vol) : SDNode(Opc, dl, VTs), MemoryVT(memvt), MMO(mmo) {
: SDNode(Opc, dl, VTs), MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile());
SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!");
assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!");
assert(getOriginalAlignment() == alignment && "Alignment encoding error!");
assert(isVolatile() == vol && "Volatile encoding error!");
} }
MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs,
const SDValue *Ops, unsigned NumOps, EVT memvt, const SDValue *Ops, unsigned NumOps, EVT memvt,
const Value *srcValue, int SVO, unsigned alignment, MachineMemOperand *mmo)
bool vol)
: SDNode(Opc, dl, VTs, Ops, NumOps), : SDNode(Opc, dl, VTs, Ops, NumOps),
MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { MemoryVT(memvt), MMO(mmo) {
SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile());
assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!");
assert(getOriginalAlignment() == alignment && "Alignment encoding error!"); assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!");
assert(isVolatile() == vol && "Volatile encoding error!");
}
/// getMemOperand - Return a MachineMemOperand object describing the memory
/// reference performed by this memory reference.
MachineMemOperand MemSDNode::getMemOperand() const {
int Flags = 0;
if (isa<LoadSDNode>(this))
Flags = MachineMemOperand::MOLoad;
else if (isa<StoreSDNode>(this))
Flags = MachineMemOperand::MOStore;
else if (isa<AtomicSDNode>(this)) {
Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore;
}
else {
const MemIntrinsicSDNode* MemIntrinNode = dyn_cast<MemIntrinsicSDNode>(this);
assert(MemIntrinNode && "Unknown MemSDNode opcode!");
if (MemIntrinNode->readMem()) Flags |= MachineMemOperand::MOLoad;
if (MemIntrinNode->writeMem()) Flags |= MachineMemOperand::MOStore;
}
int Size = (getMemoryVT().getSizeInBits() + 7) >> 3;
if (isVolatile()) Flags |= MachineMemOperand::MOVolatile;
// Check if the memory reference references a frame index
const FrameIndexSDNode *FI =
dyn_cast<const FrameIndexSDNode>(getBasePtr().getNode());
if (!getSrcValue() && FI)
return MachineMemOperand(PseudoSourceValue::getFixedStack(FI->getIndex()),
Flags, 0, Size, getOriginalAlignment());
else
return MachineMemOperand(getSrcValue(), Flags, getSrcValueOffset(),
Size, getOriginalAlignment());
} }
/// Profile - Gather unique data for the node. /// Profile - Gather unique data for the node.
@ -5221,7 +5345,6 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::PCMARKER: return "PCMarker"; case ISD::PCMARKER: return "PCMarker";
case ISD::READCYCLECOUNTER: return "ReadCycleCounter"; case ISD::READCYCLECOUNTER: return "ReadCycleCounter";
case ISD::SRCVALUE: return "SrcValue"; case ISD::SRCVALUE: return "SrcValue";
case ISD::MEMOPERAND: return "MemOperand";
case ISD::EntryToken: return "EntryToken"; case ISD::EntryToken: return "EntryToken";
case ISD::TokenFactor: return "TokenFactor"; case ISD::TokenFactor: return "TokenFactor";
case ISD::AssertSext: return "AssertSext"; case ISD::AssertSext: return "AssertSext";
@ -5500,8 +5623,20 @@ void SDNode::print_types(raw_ostream &OS, const SelectionDAG *G) const {
} }
void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
if (!isTargetOpcode() && getOpcode() == ISD::VECTOR_SHUFFLE) { if (const MachineSDNode *MN = dyn_cast<MachineSDNode>(this)) {
const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(this); if (!MN->memoperands_empty()) {
OS << "<";
OS << "Mem:";
for (MachineSDNode::mmo_iterator i = MN->memoperands_begin(),
e = MN->memoperands_end(); i != e; ++i) {
OS << **i;
if (next(i) != e)
OS << " ";
}
OS << ">";
}
} else if (const ShuffleVectorSDNode *SVN =
dyn_cast<ShuffleVectorSDNode>(this)) {
OS << "<"; OS << "<";
for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) {
int Idx = SVN->getMaskElt(i); int Idx = SVN->getMaskElt(i);
@ -5512,9 +5647,7 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
OS << Idx; OS << Idx;
} }
OS << ">"; OS << ">";
} } else if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(this)) {
if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(this)) {
OS << '<' << CSDN->getAPIntValue() << '>'; OS << '<' << CSDN->getAPIntValue() << '>';
} else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(this)) { } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(this)) {
if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle)
@ -5579,68 +5712,40 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
OS << "<" << M->getValue() << ">"; OS << "<" << M->getValue() << ">";
else else
OS << "<null>"; OS << "<null>";
} else if (const MemOperandSDNode *M = dyn_cast<MemOperandSDNode>(this)) {
OS << ": " << M->MO;
} else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) { } else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) {
OS << ":" << N->getVT().getEVTString(); OS << ":" << N->getVT().getEVTString();
} }
else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) { else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) {
const Value *SrcValue = LD->getSrcValue(); OS << " <" << *LD->getMemOperand();
int SrcOffset = LD->getSrcValueOffset();
OS << " <";
if (SrcValue)
OS << SrcValue;
else
OS << "null";
OS << ":" << SrcOffset << ">";
bool doExt = true; bool doExt = true;
switch (LD->getExtensionType()) { switch (LD->getExtensionType()) {
default: doExt = false; break; default: doExt = false; break;
case ISD::EXTLOAD: OS << " <anyext "; break; case ISD::EXTLOAD: OS << ", anyext"; break;
case ISD::SEXTLOAD: OS << " <sext "; break; case ISD::SEXTLOAD: OS << ", sext"; break;
case ISD::ZEXTLOAD: OS << " <zext "; break; case ISD::ZEXTLOAD: OS << ", zext"; break;
} }
if (doExt) if (doExt)
OS << LD->getMemoryVT().getEVTString() << ">"; OS << " from " << LD->getMemoryVT().getEVTString();
const char *AM = getIndexedModeName(LD->getAddressingMode()); const char *AM = getIndexedModeName(LD->getAddressingMode());
if (*AM) if (*AM)
OS << " " << AM; OS << ", " << AM;
if (LD->isVolatile())
OS << " <volatile>"; OS << ">";
OS << " alignment=" << LD->getAlignment();
} else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(this)) { } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(this)) {
const Value *SrcValue = ST->getSrcValue(); OS << " <" << *ST->getMemOperand();
int SrcOffset = ST->getSrcValueOffset();
OS << " <";
if (SrcValue)
OS << SrcValue;
else
OS << "null";
OS << ":" << SrcOffset << ">";
if (ST->isTruncatingStore()) if (ST->isTruncatingStore())
OS << " <trunc " << ST->getMemoryVT().getEVTString() << ">"; OS << ", trunc to " << ST->getMemoryVT().getEVTString();
const char *AM = getIndexedModeName(ST->getAddressingMode()); const char *AM = getIndexedModeName(ST->getAddressingMode());
if (*AM) if (*AM)
OS << " " << AM; OS << ", " << AM;
if (ST->isVolatile())
OS << " <volatile>"; OS << ">";
OS << " alignment=" << ST->getAlignment(); } else if (const MemSDNode* M = dyn_cast<MemSDNode>(this)) {
} else if (const AtomicSDNode* AT = dyn_cast<AtomicSDNode>(this)) { OS << " <" << *M->getMemOperand() << ">";
const Value *SrcValue = AT->getSrcValue();
int SrcOffset = AT->getSrcValueOffset();
OS << " <";
if (SrcValue)
OS << SrcValue;
else
OS << "null";
OS << ":" << SrcOffset << ">";
if (AT->isVolatile())
OS << " <volatile>";
OS << " alignment=" << AT->getAlignment();
} }
} }

View File

@ -18,6 +18,7 @@
#include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
@ -451,6 +452,7 @@ bool StackSlotColoring::AllMemRefsCanBeUnfolded(int SS) {
/// to old frame index with new one. /// to old frame index with new one.
void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI, void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI,
int NewFI, MachineFunction &MF) { int NewFI, MachineFunction &MF) {
// Update the operands.
for (unsigned i = 0, ee = MI->getNumOperands(); i != ee; ++i) { for (unsigned i = 0, ee = MI->getNumOperands(); i != ee; ++i) {
MachineOperand &MO = MI->getOperand(i); MachineOperand &MO = MI->getOperand(i);
if (!MO.isFI()) if (!MO.isFI())
@ -461,22 +463,15 @@ void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI,
MO.setIndex(NewFI); MO.setIndex(NewFI);
} }
// Update the MachineMemOperand for the new memory location. // Update the memory references. This changes the MachineMemOperands
// FIXME: We need a better method of managing these too. // directly. They may be in use by multiple instructions, however all
SmallVector<MachineMemOperand, 2> MMOs(MI->memoperands_begin(), // instructions using OldFI are being rewritten to use NewFI.
MI->memoperands_end());
MI->clearMemOperands(MF);
const Value *OldSV = PseudoSourceValue::getFixedStack(OldFI); const Value *OldSV = PseudoSourceValue::getFixedStack(OldFI);
for (unsigned i = 0, ee = MMOs.size(); i != ee; ++i) { const Value *NewSV = PseudoSourceValue::getFixedStack(NewFI);
if (MMOs[i].getValue() != OldSV) for (MachineInstr::mmo_iterator I = MI->memoperands_begin(),
MI->addMemOperand(MF, MMOs[i]); E = MI->memoperands_end(); I != E; ++I)
else { if ((*I)->getValue() == OldSV)
MachineMemOperand MMO(PseudoSourceValue::getFixedStack(NewFI), (*I)->setValue(NewSV);
MMOs[i].getFlags(), MMOs[i].getOffset(),
MMOs[i].getSize(), MMOs[i].getBaseAlignment());
MI->addMemOperand(MF, MMO);
}
}
} }
/// PropagateBackward - Traverse backward and look for the definition of /// PropagateBackward - Traverse backward and look for the definition of

View File

@ -17,6 +17,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -203,9 +204,9 @@ TargetInstrInfo::foldMemoryOperand(MachineFunction &MF,
"Folded a use to a non-load!"); "Folded a use to a non-load!");
const MachineFrameInfo &MFI = *MF.getFrameInfo(); const MachineFrameInfo &MFI = *MF.getFrameInfo();
assert(MFI.getObjectOffset(FrameIndex) != -1); assert(MFI.getObjectOffset(FrameIndex) != -1);
MachineMemOperand MMO(PseudoSourceValue::getFixedStack(FrameIndex), MachineMemOperand *MMO =
Flags, MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FrameIndex),
/*Offset=*/0, Flags, /*Offset=*/0,
MFI.getObjectSize(FrameIndex), MFI.getObjectSize(FrameIndex),
MFI.getObjectAlignment(FrameIndex)); MFI.getObjectAlignment(FrameIndex));
NewMI->addMemOperand(MF, MMO); NewMI->addMemOperand(MF, MMO);
@ -232,9 +233,8 @@ TargetInstrInfo::foldMemoryOperand(MachineFunction &MF,
if (!NewMI) return 0; if (!NewMI) return 0;
// Copy the memoperands from the load to the folded instruction. // Copy the memoperands from the load to the folded instruction.
for (std::list<MachineMemOperand>::iterator I = LoadMI->memoperands_begin(), NewMI->setMemRefs(LoadMI->memoperands_begin(),
E = LoadMI->memoperands_end(); I != E; ++I) LoadMI->memoperands_end());
NewMI->addMemOperand(MF, *I);
return NewMI; return NewMI;
} }

View File

@ -1174,11 +1174,11 @@ ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
// Must sure the base address satisfies i64 ld / st alignment requirement. // Must sure the base address satisfies i64 ld / st alignment requirement.
if (!Op0->hasOneMemOperand() || if (!Op0->hasOneMemOperand() ||
!Op0->memoperands_begin()->getValue() || !(*Op0->memoperands_begin())->getValue() ||
Op0->memoperands_begin()->isVolatile()) (*Op0->memoperands_begin())->isVolatile())
return false; return false;
unsigned Align = Op0->memoperands_begin()->getAlignment(); unsigned Align = (*Op0->memoperands_begin())->getAlignment();
unsigned ReqAlign = STI->hasV6Ops() unsigned ReqAlign = STI->hasV6Ops()
? TD->getPrefTypeAlignment( ? TD->getPrefTypeAlignment(
Type::getInt64Ty(Op0->getParent()->getParent()->getFunction()->getContext())) Type::getInt64Ty(Op0->getParent()->getParent()->getFunction()->getContext()))

View File

@ -3377,7 +3377,8 @@ SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
// 64-bit registers. In particular, sign extend the input value into the // 64-bit registers. In particular, sign extend the input value into the
// 64-bit register with extsw, store the WHOLE 64-bit value into the stack // 64-bit register with extsw, store the WHOLE 64-bit value into the stack
// then lfd it and fcfid it. // then lfd it and fcfid it.
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *FrameInfo = MF.getFrameInfo();
int FrameIdx = FrameInfo->CreateStackObject(8, 8); int FrameIdx = FrameInfo->CreateStackObject(8, 8);
EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT);
@ -3386,11 +3387,13 @@ SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
Op.getOperand(0)); Op.getOperand(0));
// STD the extended value into the stack slot. // STD the extended value into the stack slot.
MachineMemOperand MO(PseudoSourceValue::getFixedStack(FrameIdx), MachineMemOperand *MMO =
MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FrameIdx),
MachineMemOperand::MOStore, 0, 8, 8); MachineMemOperand::MOStore, 0, 8, 8);
SDValue Store = DAG.getNode(PPCISD::STD_32, dl, MVT::Other, SDValue Ops[] = { DAG.getEntryNode(), Ext64, FIdx };
DAG.getEntryNode(), Ext64, FIdx, SDValue Store =
DAG.getMemOperand(MO)); DAG.getMemIntrinsicNode(PPCISD::STD_32, dl, DAG.getVTList(MVT::Other),
Ops, 4, MVT::i64, MMO);
// Load the value as a double. // Load the value as a double.
SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0); SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0);
@ -4931,9 +4934,15 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
if (BSwapOp.getValueType() == MVT::i16) if (BSwapOp.getValueType() == MVT::i16)
BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp); BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp);
return DAG.getNode(PPCISD::STBRX, dl, MVT::Other, N->getOperand(0), SDValue Ops[] = {
BSwapOp, N->getOperand(2), N->getOperand(3), N->getOperand(0), BSwapOp, N->getOperand(2),
DAG.getValueType(N->getOperand(1).getValueType())); DAG.getValueType(N->getOperand(1).getValueType())
};
return
DAG.getMemIntrinsicNode(PPCISD::STBRX, dl, DAG.getVTList(MVT::Other),
Ops, array_lengthof(Ops),
cast<StoreSDNode>(N)->getMemoryVT(),
cast<StoreSDNode>(N)->getMemOperand());
} }
break; break;
case ISD::BSWAP: case ISD::BSWAP:
@ -4944,17 +4953,15 @@ SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N,
SDValue Load = N->getOperand(0); SDValue Load = N->getOperand(0);
LoadSDNode *LD = cast<LoadSDNode>(Load); LoadSDNode *LD = cast<LoadSDNode>(Load);
// Create the byte-swapping load. // Create the byte-swapping load.
std::vector<EVT> VTs;
VTs.push_back(MVT::i32);
VTs.push_back(MVT::Other);
SDValue MO = DAG.getMemOperand(LD->getMemOperand());
SDValue Ops[] = { SDValue Ops[] = {
LD->getChain(), // Chain LD->getChain(), // Chain
LD->getBasePtr(), // Ptr LD->getBasePtr(), // Ptr
MO, // MemOperand
DAG.getValueType(N->getValueType(0)) // VT DAG.getValueType(N->getValueType(0)) // VT
}; };
SDValue BSLoad = DAG.getNode(PPCISD::LBRX, dl, VTs, Ops, 4); SDValue BSLoad =
DAG.getMemIntrinsicNode(PPCISD::LBRX, dl,
DAG.getVTList(MVT::i32, MVT::Other), Ops, 3,
LD->getMemoryVT(), LD->getMemOperand());
// If this is an i16 load, insert the truncate. // If this is an i16 load, insert the truncate.
SDValue ResVal = BSLoad; SDValue ResVal = BSLoad;

View File

@ -41,8 +41,7 @@ namespace llvm {
FCTIDZ, FCTIWZ, FCTIDZ, FCTIWZ,
/// STFIWX - The STFIWX instruction. The first operand is an input token /// STFIWX - The STFIWX instruction. The first operand is an input token
/// chain, then an f64 value to store, then an address to store it to, /// chain, then an f64 value to store, then an address to store it to.
/// then a SRCVALUE for the address.
STFIWX, STFIWX,
// VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking // VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking
@ -80,9 +79,6 @@ namespace llvm {
/// registers. /// registers.
EXTSW_32, EXTSW_32,
/// STD_32 - This is the STD instruction for use with "32-bit" registers.
STD_32,
/// CALL - A direct function call. /// CALL - A direct function call.
CALL_Darwin, CALL_SVR4, CALL_Darwin, CALL_SVR4,
@ -124,18 +120,6 @@ namespace llvm {
/// an optional input flag argument. /// an optional input flag argument.
COND_BRANCH, COND_BRANCH,
/// CHAIN = STBRX CHAIN, GPRC, Ptr, SRCVALUE, Type - This is a
/// byte-swapping store instruction. It byte-swaps the low "Type" bits of
/// the GPRC input, then stores it through Ptr. Type can be either i16 or
/// i32.
STBRX,
/// GPRC, CHAIN = LBRX CHAIN, Ptr, SRCVALUE, Type - This is a
/// byte-swapping load instruction. It loads "Type" bits, byte swaps it,
/// then puts it in the bottom bits of the GPRC. TYPE can be either i16
/// or i32.
LBRX,
// The following 5 instructions are used only as part of the // The following 5 instructions are used only as part of the
// long double-to-int conversion sequence. // long double-to-int conversion sequence.
@ -170,7 +154,22 @@ namespace llvm {
/// operand #1 callee (register or absolute) /// operand #1 callee (register or absolute)
/// operand #2 stack adjustment /// operand #2 stack adjustment
/// operand #3 optional in flag /// operand #3 optional in flag
TC_RETURN TC_RETURN,
/// STD_32 - This is the STD instruction for use with "32-bit" registers.
STD_32 = ISD::FIRST_TARGET_MEMORY_OPCODE,
/// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
/// byte-swapping store instruction. It byte-swaps the low "Type" bits of
/// the GPRC input, then stores it through Ptr. Type can be either i16 or
/// i32.
STBRX,
/// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a
/// byte-swapping load instruction. It loads "Type" bits, byte swaps it,
/// then puts it in the bottom bits of the GPRC. TYPE can be either i16
/// or i32.
LBRX
}; };
} }

View File

@ -35,11 +35,11 @@ def SDT_PPCcondbr : SDTypeProfile<0, 3, [
SDTCisVT<0, i32>, SDTCisVT<2, OtherVT> SDTCisVT<0, i32>, SDTCisVT<2, OtherVT>
]>; ]>;
def SDT_PPClbrx : SDTypeProfile<1, 3, [ def SDT_PPClbrx : SDTypeProfile<1, 2, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT> SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>
]>; ]>;
def SDT_PPCstbrx : SDTypeProfile<0, 4, [ def SDT_PPCstbrx : SDTypeProfile<0, 3, [
SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT> SDTCisVT<0, i32>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>
]>; ]>;
def SDT_PPClarx : SDTypeProfile<1, 1, [ def SDT_PPClarx : SDTypeProfile<1, 1, [
@ -741,10 +741,10 @@ def LWZX : XForm_1<31, 23, (outs GPRC:$rD), (ins memrr:$src),
def LHBRX : XForm_1<31, 790, (outs GPRC:$rD), (ins memrr:$src), def LHBRX : XForm_1<31, 790, (outs GPRC:$rD), (ins memrr:$src),
"lhbrx $rD, $src", LdStGeneral, "lhbrx $rD, $src", LdStGeneral,
[(set GPRC:$rD, (PPClbrx xoaddr:$src, srcvalue:$sv, i16))]>; [(set GPRC:$rD, (PPClbrx xoaddr:$src, i16))]>;
def LWBRX : XForm_1<31, 534, (outs GPRC:$rD), (ins memrr:$src), def LWBRX : XForm_1<31, 534, (outs GPRC:$rD), (ins memrr:$src),
"lwbrx $rD, $src", LdStGeneral, "lwbrx $rD, $src", LdStGeneral,
[(set GPRC:$rD, (PPClbrx xoaddr:$src, srcvalue:$sv, i32))]>; [(set GPRC:$rD, (PPClbrx xoaddr:$src, i32))]>;
def LFSX : XForm_25<31, 535, (outs F4RC:$frD), (ins memrr:$src), def LFSX : XForm_25<31, 535, (outs F4RC:$frD), (ins memrr:$src),
"lfsx $frD, $src", LdStLFDU, "lfsx $frD, $src", LdStLFDU,
@ -837,11 +837,11 @@ def STWUX : XForm_8<31, 183, (outs), (ins GPRC:$rS, GPRC:$rA, GPRC:$rB),
} }
def STHBRX: XForm_8<31, 918, (outs), (ins GPRC:$rS, memrr:$dst), def STHBRX: XForm_8<31, 918, (outs), (ins GPRC:$rS, memrr:$dst),
"sthbrx $rS, $dst", LdStGeneral, "sthbrx $rS, $dst", LdStGeneral,
[(PPCstbrx GPRC:$rS, xoaddr:$dst, srcvalue:$dummy, i16)]>, [(PPCstbrx GPRC:$rS, xoaddr:$dst, i16)]>,
PPC970_DGroup_Cracked; PPC970_DGroup_Cracked;
def STWBRX: XForm_8<31, 662, (outs), (ins GPRC:$rS, memrr:$dst), def STWBRX: XForm_8<31, 662, (outs), (ins GPRC:$rS, memrr:$dst),
"stwbrx $rS, $dst", LdStGeneral, "stwbrx $rS, $dst", LdStGeneral,
[(PPCstbrx GPRC:$rS, xoaddr:$dst, srcvalue:$dummy, i32)]>, [(PPCstbrx GPRC:$rS, xoaddr:$dst, i32)]>,
PPC970_DGroup_Cracked; PPC970_DGroup_Cracked;
def STFIWX: XForm_28<31, 983, (outs), (ins F8RC:$frS, memrr:$dst), def STFIWX: XForm_28<31, 983, (outs), (ins F8RC:$frS, memrr:$dst),

View File

@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
namespace llvm { namespace llvm {
@ -113,9 +114,9 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
Flags |= MachineMemOperand::MOLoad; Flags |= MachineMemOperand::MOLoad;
if (TID.mayStore()) if (TID.mayStore())
Flags |= MachineMemOperand::MOStore; Flags |= MachineMemOperand::MOStore;
MachineMemOperand MMO(PseudoSourceValue::getFixedStack(FI), MachineMemOperand *MMO =
Flags, MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
Offset, Flags, Offset,
MFI.getObjectSize(FI), MFI.getObjectSize(FI),
MFI.getObjectAlignment(FI)); MFI.getObjectAlignment(FI));
return addOffset(MIB.addFrameIndex(FI), Offset) return addOffset(MIB.addFrameIndex(FI), Offset)

View File

@ -1465,11 +1465,14 @@ SDNode *X86DAGToDAGISel::SelectAtomic64(SDNode *Node, unsigned Opc) {
SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4; SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
if (!SelectAddr(In1, In1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) if (!SelectAddr(In1, In1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4))
return NULL; return NULL;
SDValue LSI = Node->getOperand(4); // MemOperand MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
const SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, In2L, In2H, LSI, Chain}; MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
return CurDAG->getMachineNode(Opc, Node->getDebugLoc(), const SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, In2L, In2H, Chain};
SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(),
MVT::i32, MVT::i32, MVT::Other, Ops, MVT::i32, MVT::i32, MVT::Other, Ops,
array_lengthof(Ops)); array_lengthof(Ops));
cast<MachineSDNode>(ResNode)->setMemRefs(MemOp, MemOp + 1);
return ResNode;
} }
SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) {
@ -1605,15 +1608,18 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) {
DebugLoc dl = Node->getDebugLoc(); DebugLoc dl = Node->getDebugLoc();
SDValue Undef = SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF, SDValue Undef = SDValue(CurDAG->getMachineNode(TargetInstrInfo::IMPLICIT_DEF,
dl, NVT), 0); dl, NVT), 0);
SDValue MemOp = CurDAG->getMemOperand(cast<MemSDNode>(Node)->getMemOperand()); MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
MemOp[0] = cast<MemSDNode>(Node)->getMemOperand();
if (isInc || isDec) { if (isInc || isDec) {
SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, MemOp, Chain }; SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain };
SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7), 0); SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 6), 0);
cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1);
SDValue RetVals[] = { Undef, Ret }; SDValue RetVals[] = { Undef, Ret };
return CurDAG->getMergeValues(RetVals, 2, dl).getNode(); return CurDAG->getMergeValues(RetVals, 2, dl).getNode();
} else { } else {
SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Val, MemOp, Chain }; SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Val, Chain };
SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 8), 0); SDValue Ret = SDValue(CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops, 7), 0);
cast<MachineSDNode>(Ret)->setMemRefs(MemOp, MemOp + 1);
SDValue RetVals[] = { Undef, Ret }; SDValue RetVals[] = { Undef, Ret };
return CurDAG->getMergeValues(RetVals, 2, dl).getNode(); return CurDAG->getMergeValues(RetVals, 2, dl).getNode();
} }

View File

@ -6983,12 +6983,11 @@ ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl<SDValue>&Results,
Node->getOperand(2), DAG.getIntPtrConstant(0)); Node->getOperand(2), DAG.getIntPtrConstant(0));
SDValue In2H = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, SDValue In2H = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
Node->getOperand(2), DAG.getIntPtrConstant(1)); Node->getOperand(2), DAG.getIntPtrConstant(1));
// This is a generalized SDNode, not an AtomicSDNode, so it doesn't SDValue Ops[] = { Chain, In1, In2L, In2H };
// have a MemOperand. Pass the info through as a normal operand.
SDValue LSI = DAG.getMemOperand(cast<MemSDNode>(Node)->getMemOperand());
SDValue Ops[] = { Chain, In1, In2L, In2H, LSI };
SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other); SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
SDValue Result = DAG.getNode(NewOp, dl, Tys, Ops, 5); SDValue Result =
DAG.getMemIntrinsicNode(NewOp, dl, Tys, Ops, 4, MVT::i64,
cast<MemSDNode>(Node)->getMemOperand());
SDValue OpsF[] = { Result.getValue(0), Result.getValue(1)}; SDValue OpsF[] = { Result.getValue(0), Result.getValue(1)};
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2)); Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, OpsF, 2));
Results.push_back(Result.getValue(2)); Results.push_back(Result.getValue(2));
@ -7396,7 +7395,8 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr,
(*MIB).addOperand(*argOpers[i]); (*MIB).addOperand(*argOpers[i]);
MIB.addReg(t2); MIB.addReg(t2);
assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand"); assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand");
(*MIB).addMemOperand(*F, *bInstr->memoperands_begin()); (*MIB).setMemRefs(bInstr->memoperands_begin(),
bInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), destOper.getReg()); MIB = BuildMI(newMBB, dl, TII->get(copyOpc), destOper.getReg());
MIB.addReg(EAXreg); MIB.addReg(EAXreg);
@ -7548,7 +7548,8 @@ X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr,
(*MIB).addOperand(*argOpers[i]); (*MIB).addOperand(*argOpers[i]);
assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand"); assert(bInstr->hasOneMemOperand() && "Unexpected number of memoperand");
(*MIB).addMemOperand(*F, *bInstr->memoperands_begin()); (*MIB).setMemRefs(bInstr->memoperands_begin(),
bInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t3); MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t3);
MIB.addReg(X86::EAX); MIB.addReg(X86::EAX);
@ -7652,7 +7653,8 @@ X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr,
(*MIB).addOperand(*argOpers[i]); (*MIB).addOperand(*argOpers[i]);
MIB.addReg(t3); MIB.addReg(t3);
assert(mInstr->hasOneMemOperand() && "Unexpected number of memoperand"); assert(mInstr->hasOneMemOperand() && "Unexpected number of memoperand");
(*MIB).addMemOperand(*F, *mInstr->memoperands_begin()); (*MIB).setMemRefs(mInstr->memoperands_begin(),
mInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), destOper.getReg()); MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), destOper.getReg());
MIB.addReg(X86::EAX); MIB.addReg(X86::EAX);
@ -7747,6 +7749,11 @@ X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter(
// In the XMM save block, save all the XMM argument registers. // In the XMM save block, save all the XMM argument registers.
for (int i = 3, e = MI->getNumOperands(); i != e; ++i) { for (int i = 3, e = MI->getNumOperands(); i != e; ++i) {
int64_t Offset = (i - 3) * 16 + VarArgsFPOffset; int64_t Offset = (i - 3) * 16 + VarArgsFPOffset;
MachineMemOperand *MMO =
F->getMachineMemOperand(
PseudoSourceValue::getFixedStack(RegSaveFrameIndex),
MachineMemOperand::MOStore, Offset,
/*Size=*/16, /*Align=*/16);
BuildMI(XMMSaveMBB, DL, TII->get(X86::MOVAPSmr)) BuildMI(XMMSaveMBB, DL, TII->get(X86::MOVAPSmr))
.addFrameIndex(RegSaveFrameIndex) .addFrameIndex(RegSaveFrameIndex)
.addImm(/*Scale=*/1) .addImm(/*Scale=*/1)
@ -7754,10 +7761,7 @@ X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter(
.addImm(/*Disp=*/Offset) .addImm(/*Disp=*/Offset)
.addReg(/*Segment=*/0) .addReg(/*Segment=*/0)
.addReg(MI->getOperand(i).getReg()) .addReg(MI->getOperand(i).getReg())
.addMemOperand(MachineMemOperand( .addMemOperand(MMO);
PseudoSourceValue::getFixedStack(RegSaveFrameIndex),
MachineMemOperand::MOStore, Offset,
/*Size=*/16, /*Align=*/16));
} }
F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.

View File

@ -204,17 +204,6 @@ namespace llvm {
LCMPXCHG_DAG, LCMPXCHG_DAG,
LCMPXCHG8_DAG, LCMPXCHG8_DAG,
// ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG,
// ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG -
// Atomic 64-bit binary operations.
ATOMADD64_DAG,
ATOMSUB64_DAG,
ATOMOR64_DAG,
ATOMXOR64_DAG,
ATOMAND64_DAG,
ATOMNAND64_DAG,
ATOMSWAP64_DAG,
// FNSTCW16m - Store FP control world into i16 memory. // FNSTCW16m - Store FP control world into i16 memory.
FNSTCW16m, FNSTCW16m,
@ -248,7 +237,18 @@ namespace llvm {
// VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack, // VASTART_SAVE_XMM_REGS - Save xmm argument registers to the stack,
// according to %al. An operator is needed so that this can be expanded // according to %al. An operator is needed so that this can be expanded
// with control flow. // with control flow.
VASTART_SAVE_XMM_REGS VASTART_SAVE_XMM_REGS,
// ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG,
// ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG -
// Atomic 64-bit binary operations.
ATOMADD64_DAG = ISD::FIRST_TARGET_MEMORY_OPCODE,
ATOMSUB64_DAG,
ATOMOR64_DAG,
ATOMXOR64_DAG,
ATOMAND64_DAG,
ATOMNAND64_DAG,
ATOMSWAP64_DAG
}; };
} }

View File

@ -26,6 +26,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/PseudoSourceValue.h"
namespace llvm { namespace llvm {
@ -142,9 +143,9 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0) {
Flags |= MachineMemOperand::MOLoad; Flags |= MachineMemOperand::MOLoad;
if (TID.mayStore()) if (TID.mayStore())
Flags |= MachineMemOperand::MOStore; Flags |= MachineMemOperand::MOStore;
MachineMemOperand MMO(PseudoSourceValue::getFixedStack(FI), MachineMemOperand *MMO =
Flags, MF.getMachineMemOperand(PseudoSourceValue::getFixedStack(FI),
Offset, Flags, Offset,
MFI.getObjectSize(FI), MFI.getObjectSize(FI),
MFI.getObjectAlignment(FI)); MFI.getObjectAlignment(FI));
return addOffset(MIB.addFrameIndex(FI), Offset) return addOffset(MIB.addFrameIndex(FI), Offset)

View File

@ -2296,7 +2296,7 @@ MachineInstr* X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF,
// Determine the alignment of the load. // Determine the alignment of the load.
unsigned Alignment = 0; unsigned Alignment = 0;
if (LoadMI->hasOneMemOperand()) if (LoadMI->hasOneMemOperand())
Alignment = LoadMI->memoperands_begin()->getAlignment(); Alignment = (*LoadMI->memoperands_begin())->getAlignment();
else else
switch (LoadMI->getOpcode()) { switch (LoadMI->getOpcode()) {
case X86::V_SET0: case X86::V_SET0:
@ -2567,7 +2567,7 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
std::vector<SDValue> AfterOps; std::vector<SDValue> AfterOps;
DebugLoc dl = N->getDebugLoc(); DebugLoc dl = N->getDebugLoc();
unsigned NumOps = N->getNumOperands(); unsigned NumOps = N->getNumOperands();
for (unsigned i = 0; i != NumOps-2; ++i) { for (unsigned i = 0; i != NumOps-1; ++i) {
SDValue Op = N->getOperand(i); SDValue Op = N->getOperand(i);
if (i >= Index-NumDefs && i < Index-NumDefs + X86AddrNumOperands) if (i >= Index-NumDefs && i < Index-NumDefs + X86AddrNumOperands)
AddrOps.push_back(Op); AddrOps.push_back(Op);
@ -2576,8 +2576,6 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
else if (i > Index-NumDefs) else if (i > Index-NumDefs)
AfterOps.push_back(Op); AfterOps.push_back(Op);
} }
SDValue MemOp = N->getOperand(NumOps-2);
AddrOps.push_back(MemOp);
SDValue Chain = N->getOperand(NumOps-1); SDValue Chain = N->getOperand(NumOps-1);
AddrOps.push_back(Chain); AddrOps.push_back(Chain);
@ -2614,10 +2612,8 @@ X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
// Emit the store instruction. // Emit the store instruction.
if (FoldedStore) { if (FoldedStore) {
AddrOps.pop_back();
AddrOps.pop_back(); AddrOps.pop_back();
AddrOps.push_back(SDValue(NewNode, 0)); AddrOps.push_back(SDValue(NewNode, 0));
AddrOps.push_back(MemOp);
AddrOps.push_back(Chain); AddrOps.push_back(Chain);
bool isAligned = (RI.getStackAlignment() >= 16) || bool isAligned = (RI.getStackAlignment() >= 16) ||
RI.needsStackRealignment(MF); RI.needsStackRealignment(MF);

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -mtriple=arm-apple-darwin9 -stats |& grep asm-printer | grep 162 ; RUN: llc < %s -mtriple=arm-apple-darwin9 -stats |& grep asm-printer | grep 159
%"struct.Adv5::Ekin<3>" = type <{ i8 }> %"struct.Adv5::Ekin<3>" = type <{ i8 }>
%"struct.Adv5::X::Energyflux<3>" = type { double } %"struct.Adv5::X::Energyflux<3>" = type { double }

View File

@ -1135,24 +1135,18 @@ public:
emitCode("}"); emitCode("}");
} }
// Generate MemOperandSDNodes nodes for each memory accesses covered by // Populate MemRefs with entries for each memory accesses covered by
// this pattern. // this pattern.
if (II.mayLoad | II.mayStore) { if (isRoot && !LSI.empty()) {
std::vector<std::string>::const_iterator mi, mie; std::string MemRefs = "MemRefs" + utostr(OpsNo);
for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) { emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
std::string LSIName = "LSI_" + *mi; "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
emitCode("SDValue " + LSIName + " = " for (unsigned i = 0, e = LSI.size(); i != e; ++i)
"CurDAG->getMemOperand(cast<MemSDNode>(" + emitCode(MemRefs + "[" + utostr(i) + "] = "
*mi + ")->getMemOperand());"); "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
if (GenDebug) { After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"yellow\");"); MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"black\");"); ");");
}
if (IsVariadic)
emitCode("Ops" + utostr(OpsNo) + ".push_back(" + LSIName + ");");
else
AllOps.push_back(LSIName);
}
} }
if (NodeHasChain) { if (NodeHasChain) {
@ -1965,7 +1959,6 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
<< " assert(!N.isMachineOpcode() && \"Node already selected!\");\n" << " assert(!N.isMachineOpcode() && \"Node already selected!\");\n"
<< " break;\n" << " break;\n"
<< " case ISD::EntryToken: // These nodes remain the same.\n" << " case ISD::EntryToken: // These nodes remain the same.\n"
<< " case ISD::MEMOPERAND:\n"
<< " case ISD::BasicBlock:\n" << " case ISD::BasicBlock:\n"
<< " case ISD::Register:\n" << " case ISD::Register:\n"
<< " case ISD::HANDLENODE:\n" << " case ISD::HANDLENODE:\n"