#define LLVM_CODEGEN_SELECTIONDAG_H
#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include <cassert>
-#include <list>
#include <vector>
#include <map>
#include <string>
class MachineConstantPoolValue;
class FunctionLoweringInfo;
-/// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use
-/// pool allocation with recycling.
-///
-typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode),
- AlignOf<MostAlignedSDNode>::Alignment>
- NodeAllocatorType;
-
-template<> class ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
+template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
+private:
mutable SDNode Sentinel;
public:
ilist_traits() : Sentinel(ISD::DELETED_NODE, SDVTList()) {}
///
class SelectionDAG {
TargetLowering &TLI;
- MachineFunction &MF;
+ MachineFunction *MF;
FunctionLoweringInfo &FLI;
MachineModuleInfo *MMI;
- /// Root - The root of the entire DAG. EntryNode - The starting token.
- SDValue Root, EntryNode;
+ /// EntryNode - The starting token.
+ SDNode EntryNode;
+
+ /// Root - The root of the entire DAG.
+ SDValue Root;
/// AllNodes - A linked list of nodes in the current DAG.
ilist<SDNode> AllNodes;
- /// NodeAllocator - Pool allocation for nodes. The allocator isn't
- /// allocated inside this class because we want to reuse a single
- /// recycler across multiple SelectionDAG runs.
- NodeAllocatorType &NodeAllocator;
+ /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use
+ /// pool allocation with recycling.
+ typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode),
+ AlignOf<MostAlignedSDNode>::Alignment>
+ NodeAllocatorType;
+
+ /// NodeAllocator - Pool allocation for nodes.
+ NodeAllocatorType NodeAllocator;
/// CSEMap - This structure is used to memoize nodes, automatically performing
/// CSE with existing nodes with a duplicate is requested.
FoldingSet<SDNode> CSEMap;
+ /// OperandAllocator - Pool allocation for machine-opcode SDNode operands.
+ BumpPtrAllocator OperandAllocator;
+
/// Allocator - Pool allocation for misc. objects that are created once per
/// SelectionDAG.
BumpPtrAllocator Allocator;
/// VerifyNode - Sanity check the given node. Aborts if it is invalid.
void VerifyNode(SDNode *N);
+ /// setGraphColorHelper - Implementation of setSubgraphColor.
+ /// Return whether we had to truncate the search.
+ ///
+ bool setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
+ int level, bool &printed);
+
public:
- SelectionDAG(TargetLowering &tli, MachineFunction &mf,
- FunctionLoweringInfo &fli, MachineModuleInfo *mmi,
- NodeAllocatorType &nodeallocator)
- : TLI(tli), MF(mf), FLI(fli), MMI(mmi), NodeAllocator(nodeallocator) {
- EntryNode = Root = getNode(ISD::EntryToken, MVT::Other);
- }
+ SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli);
~SelectionDAG();
- MachineFunction &getMachineFunction() const { return MF; }
+ /// init - Prepare this SelectionDAG to process code in the given
+ /// MachineFunction.
+ ///
+ void init(MachineFunction &mf, MachineModuleInfo *mmi);
+
+ /// clear - Clear state and free memory necessary to make this
+ /// SelectionDAG ready to process a new block.
+ ///
+ void clear();
+
+ MachineFunction &getMachineFunction() const { return *MF; }
const TargetMachine &getTarget() const;
TargetLowering &getTargetLoweringInfo() const { return TLI; }
FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; }
///
void setGraphColor(const SDNode *N, const char *Color);
+ /// setGraphColor - Convenience for setting subgraph color attribute.
+ ///
+ void setSubgraphColor(SDNode *N, const char *Color);
+
typedef ilist<SDNode>::const_iterator allnodes_const_iterator;
allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); }
allnodes_const_iterator allnodes_end() const { return AllNodes.end(); }
/// getEntryNode - Return the token chain corresponding to the entry of the
/// function.
- const SDValue &getEntryNode() const { return EntryNode; }
+ SDValue getEntryNode() const {
+ return SDValue(const_cast<SDNode *>(&EntryNode), 0);
+ }
/// setRoot - Set the current root tag of the SelectionDAG.
///
const SDValue &setRoot(SDValue N) {
- assert((!N.Val || N.getValueType() == MVT::Other) &&
+ assert((!N.getNode() || N.getValueType() == MVT::Other) &&
"DAG root value is not a chain!");
return Root = N;
}
/// certain types of nodes together, or eliminating superfluous nodes. When
/// the AfterLegalize argument is set to 'true', Combine takes care not to
/// generate any nodes that will be illegal on the target.
- void Combine(bool AfterLegalize, AliasAnalysis &AA);
+ void Combine(bool AfterLegalize, AliasAnalysis &AA, bool Fast);
/// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that
/// only uses types natively supported by the target.
//
SDValue getConstant(uint64_t Val, MVT VT, bool isTarget = false);
SDValue getConstant(const APInt &Val, MVT VT, bool isTarget = false);
+ SDValue getConstant(const ConstantInt &Val, MVT VT, bool isTarget = false);
SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false);
SDValue getTargetConstant(uint64_t Val, MVT VT) {
return getConstant(Val, VT, true);
SDValue getTargetConstant(const APInt &Val, MVT VT) {
return getConstant(Val, VT, true);
}
+ SDValue getTargetConstant(const ConstantInt &Val, MVT VT) {
+ return getConstant(Val, VT, true);
+ }
SDValue getConstantFP(double Val, MVT VT, bool isTarget = false);
SDValue getConstantFP(const APFloat& Val, MVT VT, bool isTarget = false);
+ SDValue getConstantFP(const ConstantFP &CF, MVT VT, bool isTarget = false);
SDValue getTargetConstantFP(double Val, MVT VT) {
return getConstantFP(Val, VT, true);
}
SDValue getTargetConstantFP(const APFloat& Val, MVT VT) {
return getConstantFP(Val, VT, true);
}
+ SDValue getTargetConstantFP(const ConstantFP &Val, MVT VT) {
+ return getConstantFP(Val, VT, true);
+ }
SDValue getGlobalAddress(const GlobalValue *GV, MVT VT,
- int offset = 0, bool isTargetGA = false);
+ int64_t offset = 0, bool isTargetGA = false);
SDValue getTargetGlobalAddress(const GlobalValue *GV, MVT VT,
- int offset = 0) {
+ int64_t offset = 0) {
return getGlobalAddress(GV, VT, offset, true);
}
SDValue getFrameIndex(int FI, MVT VT, bool isTarget = false);
SDValue Flag) {
const MVT *VTs = getNodeValueTypes(MVT::Other, MVT::Flag);
SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Flag };
- return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.Val ? 4 : 3);
+ return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.getNode() ? 4 : 3);
}
// Similar to last getCopyToReg() except parameter Reg is a SDValue
SDValue Flag) {
const MVT *VTs = getNodeValueTypes(MVT::Other, MVT::Flag);
SDValue Ops[] = { Chain, Reg, N, Flag };
- return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.Val ? 4 : 3);
+ return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.getNode() ? 4 : 3);
}
SDValue getCopyFromReg(SDValue Chain, unsigned Reg, MVT VT) {
SDValue Flag) {
const MVT *VTs = getNodeValueTypes(VT, MVT::Other, MVT::Flag);
SDValue Ops[] = { Chain, getRegister(Reg, VT), Flag };
- return getNode(ISD::CopyFromReg, VTs, 3, Ops, Flag.Val ? 3 : 2);
+ return getNode(ISD::CopyFromReg, VTs, 3, Ops, Flag.getNode() ? 3 : 2);
}
SDValue getCondCode(ISD::CondCode Cond);
+ /// Returns the ConvertRndSat Note: Avoid using this node because it may
+ /// disappear in the future and most targets don't support it.
+ SDValue getConvertRndSat(MVT VT, SDValue Val, SDValue DTy, SDValue STy,
+ SDValue Rnd, SDValue Sat, ISD::CvtCode Code);
+
/// getZeroExtendInReg - Return the expression required to zero extend the Op
/// value assuming it was the smaller SrcTy value.
SDValue getZeroExtendInReg(SDValue Op, MVT SrcTy);
Ops.push_back(Op2);
Ops.push_back(InFlag);
return getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0],
- (unsigned)Ops.size() - (InFlag.Val == 0 ? 1 : 0));
+ (unsigned)Ops.size() - (InFlag.getNode() == 0 ? 1 : 0));
}
/// getNode - Gets or creates the specified node.
SDValue getNode(unsigned Opcode, SDVTList VTs, SDValue N);
SDValue getNode(unsigned Opcode, SDVTList VTs, SDValue N1, SDValue N2);
SDValue getNode(unsigned Opcode, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3);
+ SDValue N1, SDValue N2, SDValue N3);
SDValue getNode(unsigned Opcode, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3, SDValue N4);
+ SDValue N1, SDValue N2, SDValue N3, SDValue N4);
SDValue getNode(unsigned Opcode, SDVTList VTs,
- SDValue N1, SDValue N2, SDValue N3, SDValue N4,
- SDValue N5);
+ SDValue N1, SDValue N2, SDValue N3, SDValue N4,
+ SDValue N5);
SDValue getNode(unsigned Opcode, SDVTList VTs,
- const SDValue *Ops, unsigned NumOps);
+ const SDValue *Ops, unsigned NumOps);
SDValue getMemcpy(SDValue Chain, SDValue Dst, SDValue Src,
- SDValue Size, unsigned Align,
- bool AlwaysInline,
- const Value *DstSV, uint64_t DstSVOff,
- const Value *SrcSV, uint64_t SrcSVOff);
+ SDValue Size, unsigned Align, bool AlwaysInline,
+ const Value *DstSV, uint64_t DstSVOff,
+ const Value *SrcSV, uint64_t SrcSVOff);
SDValue getMemmove(SDValue Chain, SDValue Dst, SDValue Src,
- SDValue Size, unsigned Align,
- const Value *DstSV, uint64_t DstOSVff,
- const Value *SrcSV, uint64_t SrcSVOff);
+ SDValue Size, unsigned Align,
+ const Value *DstSV, uint64_t DstOSVff,
+ const Value *SrcSV, uint64_t SrcSVOff);
SDValue getMemset(SDValue Chain, SDValue Dst, SDValue Src,
- SDValue Size, unsigned Align,
- const Value *DstSV, uint64_t DstSVOff);
+ SDValue Size, unsigned Align,
+ const Value *DstSV, uint64_t DstSVOff);
/// getSetCC - Helper function to make it easier to build SetCC's if you just
/// have an ISD::CondCode instead of an SDValue.
///
SDValue getSetCC(MVT VT, SDValue LHS, SDValue RHS,
- ISD::CondCode Cond) {
+ ISD::CondCode Cond) {
return getNode(ISD::SETCC, VT, LHS, RHS, getCondCode(Cond));
}
/// if you just have an ISD::CondCode instead of an SDValue.
///
SDValue getVSetCC(MVT VT, SDValue LHS, SDValue RHS,
- ISD::CondCode Cond) {
+ ISD::CondCode Cond) {
return getNode(ISD::VSETCC, VT, LHS, RHS, getCondCode(Cond));
}
/// just have an ISD::CondCode instead of an SDValue.
///
SDValue getSelectCC(SDValue LHS, SDValue RHS,
- SDValue True, SDValue False, ISD::CondCode Cond) {
+ SDValue True, SDValue False, ISD::CondCode Cond) {
return getNode(ISD::SELECT_CC, True.getValueType(), LHS, RHS, True, False,
getCondCode(Cond));
}
/// getVAArg - VAArg produces a result and token chain, and takes a pointer
/// and a source value as input.
SDValue getVAArg(MVT VT, SDValue Chain, SDValue Ptr,
- SDValue SV);
+ SDValue SV);
- /// getAtomic - Gets a node for an atomic op, produces result and chain, takes
- /// 3 operands
+ /// getAtomic - Gets a node for an atomic op, produces result and chain and
+ /// takes 3 operands
SDValue getAtomic(unsigned Opcode, SDValue Chain, SDValue Ptr,
- SDValue Cmp, SDValue Swp, const Value* PtrVal,
- unsigned Alignment=0);
+ SDValue Cmp, SDValue Swp, const Value* PtrVal,
+ unsigned Alignment=0);
- /// getAtomic - Gets a node for an atomic op, produces result and chain, takes
- /// 2 operands
+ /// getAtomic - Gets a node for an atomic op, produces result and chain and
+ /// takes 2 operands.
SDValue getAtomic(unsigned Opcode, SDValue Chain, SDValue Ptr,
- SDValue Val, const Value* PtrVal,
- unsigned Alignment = 0);
+ SDValue Val, const Value* PtrVal,
+ unsigned Alignment = 0);
+
+ /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a
+ /// result and takes a list of operands.
+ SDValue getMemIntrinsicNode(unsigned Opcode,
+ const MVT *VTs, unsigned NumVTs,
+ const SDValue *Ops, unsigned NumOps,
+ MVT MemVT, const Value *srcValue, int SVOff,
+ unsigned Align = 0, bool Vol = false,
+ bool ReadMem = true, bool WriteMem = true);
+
+ SDValue getMemIntrinsicNode(unsigned Opcode, SDVTList VTList,
+ const SDValue *Ops, unsigned NumOps,
+ MVT MemVT, const Value *srcValue, int SVOff,
+ unsigned Align = 0, bool Vol = false,
+ bool ReadMem = true, bool WriteMem = true);
/// getMergeValues - Create a MERGE_VALUES node from the given operands.
/// Allowed to return something different (and simpler) if Simplify is true.
SDValue getMergeValues(const SDValue *Ops, unsigned NumOps,
- bool Simplify = true);
+ bool Simplify = true);
/// getMergeValues - Create a MERGE_VALUES node from the given types and ops.
/// Allowed to return something different (and simpler) if Simplify is true.
return getNode(ISD::MERGE_VALUES, VTs, Ops, NumOps);
}
+ /// getCall - Create a CALL node from the given information.
+ ///
+ SDValue getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall,
+ bool isInreg, SDVTList VTs, const SDValue *Operands,
+ unsigned NumOperands);
+
/// getLoad - Loads are not normal binary operators: their result type is not
/// determined by their operands, and they produce a value AND a token chain.
///
unsigned Num,
DAGUpdateListener *UpdateListener = 0);
- /// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
- /// based on their topological order. It returns the maximum id and a vector
- /// of the SDNodes* in assigned order by reference.
- unsigned AssignTopologicalOrder(std::vector<SDNode*> &TopOrder);
+ /// AssignTopologicalOrder - Topological-sort the AllNodes list and a
+ /// assign a unique node id for each node in the DAG based on their
+ /// topological order. Returns the number of nodes.
+ unsigned AssignTopologicalOrder();
+
+ /// RepositionNode - Move node N in the AllNodes list to be immediately
+ /// before the given iterator Position. This may be used to update the
+ /// topological ordering when the list of nodes is modified.
+ void RepositionNode(allnodes_iterator Position, SDNode *N) {
+ AllNodes.insert(Position, AllNodes.remove(N));
+ }
/// isCommutativeBinOp - Returns true if the opcode is a commutative binary
/// operation.
/// at least that alignment.
SDValue CreateStackTemporary(MVT VT, unsigned minAlign = 1);
+ /// FoldConstantArithmetic -
+ SDValue FoldConstantArithmetic(unsigned Opcode,
+ MVT VT,
+ ConstantSDNode *Cst1,
+ ConstantSDNode *Cst2);
+
/// FoldSetCC - Constant fold a setcc to true or false.
SDValue FoldSetCC(MVT VT, SDValue N1,
- SDValue N2, ISD::CondCode Cond);
+ SDValue N2, ISD::CondCode Cond);
/// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We
/// use this predicate to simplify operations downstream.
SDValue getShuffleScalarElt(const SDNode *N, unsigned Idx);
private:
- void RemoveNodeFromCSEMaps(SDNode *N);
+ bool RemoveNodeFromCSEMaps(SDNode *N);
SDNode *AddNonLeafNodeToCSEMaps(SDNode *N);
SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos);
SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2,
void DeleteNodeNotInCSEMaps(SDNode *N);
unsigned getMVTAlignment(MVT MemoryVT) const;
+
+ void allnodes_clear();
// List of non-single value types.
std::vector<SDVTList> VTList;