diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h new file mode 100644 index 00000000000..eab8b7d29ac --- /dev/null +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -0,0 +1,334 @@ +//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG Rep. ----*- C++ -*-===// +// +// This file declares the SelectionDAG class, which is used to represent an LLVM +// function in a low-level representation suitable for instruction selection. +// This DAG is constructed as the first step of instruction selection in order +// to allow implementation of machine specific optimizations and code +// simplifications. +// +// The representation used by the SelectionDAG is a target-independent +// representation, which is loosly modeled after the GCC RTL representation, but +// is significantly simpler. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_H +#define LLVM_CODEGEN_SELECTIONDAG_H + +#include "llvm/CodeGen/ValueTypes.h" +#include "Support/DataTypes.h" +#include +#include +class Value; +class Type; +class Instruction; +class BasicBlock; +class MachineBasicBlock; +class MachineFunction; +class TargetMachine; +class SelectionDAGNode; +class SelectionDAGBlock; +class SelectionDAGBuilder; +class SelectionDAGTargetBuilder; + +/// ISD namespace - This namespace contains an enum which represents all of the +/// SelectionDAG node types and value types. +/// +namespace ISD { + enum NodeType { + // ChainNode nodes are used to sequence operations within a basic block + // which cannot be reordered (such as loads, stores, calls, etc). + // BlockChainNodes are used to connect the DAG's for different basic blocks + // into one big DAG. + ChainNode, BlockChainNode, + + // ProtoNodes are nodes that are only half way constructed. + ProtoNode, + + // Leaf nodes. + Constant, FrameIndex, + + // Simple binary arithmetic operators + Plus, Minus, Times, SDiv, UDiv, SRem, URem, + + // Bitwise operators + And, Or, Xor, + + // Control flow instructions + Br, Switch, Ret, RetVoid, + + // Other operators + Load, Store, PHI, Call, + }; +} + +class SelectionDAG { + friend class SelectionDAGBuilder; + MachineFunction &F; + const TargetMachine &TM; + MVT::ValueType PointerType; // The ValueType the target uses for pointers + + // ValueMap - The SelectionDAGNode for each LLVM value in the function. + std::map ValueMap; + + // BlockMap - The MachineBasicBlock created for each LLVM BasicBlock + std::map BlockMap; + + // Root - The root of the entire DAG + SelectionDAGNode *Root; + + // AllNodes - All of the nodes in the DAG + std::vector AllNodes; +public: + /// SelectionDAG constructor - Build a SelectionDAG for the specified + /// function. Implemented in DAGBuilder.cpp + /// + SelectionDAG(MachineFunction &F, const TargetMachine &TM, + SelectionDAGTargetBuilder &SDTB); + ~SelectionDAG(); + + /// getValueType - Return the ValueType for the specified LLVM type. This + /// method works on all scalar LLVM types. + /// + MVT::ValueType getValueType(const Type *Ty) const; + + /// getRoot - Return the root of the current SelectionDAG. + /// + SelectionDAGNode *getRoot() const { return Root; } + + /// getMachineFunction - Return the MachineFunction object that this + /// SelectionDAG corresponds to. + /// + MachineFunction &getMachineFunction() const { return F; } + + //===--------------------------------------------------------------------===// + // Addition and updating methods + // + + /// addNode - Add the specified node to the SelectionDAG so that it will be + /// deleted when the DAG is... + /// + SelectionDAGNode *addNode(SelectionDAGNode *N) { + AllNodes.push_back(N); + return N; + } + + /// addNodeForValue - Add the specified node to the SelectionDAG so that it + /// will be deleted when the DAG is... and update the value map to indicate + /// that the specified DAG node computes the value. Note that it is an error + /// to specify multiple DAG nodes that compute the same value. + /// + SelectionDAGNode *addNodeForValue(SelectionDAGNode *N, const Value *V) { + assert(ValueMap.count(V) == 0 && "Value already has a DAG node!"); + return addNode(ValueMap[V] = N); + } + + void dump() const; +private: + void addInstructionToDAG(const Instruction &I, const BasicBlock &BB); +}; + + +/// SelectionDAGReducedValue - During the reducer pass we need the ability to +/// add an arbitrary (but usually 1 or 0) number of arbitrarily sized values to +/// the selection DAG. Because of this, we represent these values as a singly +/// linked list of values attached to the DAGNode. We end up putting the +/// arbitrary state for the value in subclasses of this node. +/// +/// Note that this class does not have a virtual dtor, this is because we know +/// that the subclasses will not hold state that needs to be destroyed. +/// +class SelectionDAGReducedValue { + unsigned Code; + SelectionDAGReducedValue *Next; +public: + SelectionDAGReducedValue(unsigned C) : Code(C), Next(0) {} + + /// getValueCode - Return the code for this reducer value... + /// + unsigned getValueCode() const { return Code; } + + /// getNext - Return the next value in the list + /// + const SelectionDAGReducedValue *getNext() const { return Next; } + void setNext(SelectionDAGReducedValue *N) { Next = N; } + + SelectionDAGReducedValue *getNext() { return Next; } +}; + + + +/// SelectionDAGNode - Represents one node in the selection DAG. +/// +class SelectionDAGNode { + std::vector Uses; + ISD::NodeType NodeType; + MVT::ValueType ValueType; + MachineBasicBlock *BB; + SelectionDAGReducedValue *ValList; + + /// Costs - Each pair of elements of 'Costs' contains the cost of producing + /// the value with the target specific slot number and the production number + /// to use to produce it. A zero value for the production number indicates + /// that the cost has not yet been computed. + unsigned *Costs; +public: + SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, + MachineBasicBlock *bb = 0) + : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {} + + SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, + SelectionDAGNode *N) + : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { + assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); + Uses.reserve(1); Uses.push_back(N); + } + SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, + SelectionDAGNode *N1, SelectionDAGNode *N2) + : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { + assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); + Uses.reserve(2); Uses.push_back(N1); Uses.push_back(N2); + } + + ~SelectionDAGNode() { delete [] Costs; delete ValList; } + + void setNode(ISD::NodeType NT, MachineBasicBlock *bb) { + assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); + NodeType = NT; BB = bb; + } + void setNode(ISD::NodeType NT, MachineBasicBlock *bb, SelectionDAGNode *N) { + assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); + NodeType = NT; BB = bb; Uses.reserve(1); Uses.push_back(N); + } + void setNode(ISD::NodeType NT, MachineBasicBlock *bb, + SelectionDAGNode *N1, SelectionDAGNode *N2) { + assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); + NodeType = NT; BB = bb; + Uses.reserve(1); Uses.push_back(N1); Uses.push_back(N2); + } + + //===--------------------------------------------------------------------===// + // Accessors + // + ISD::NodeType getNodeType() const { return NodeType; } + MVT::ValueType getValueType() const { return ValueType; } + MachineBasicBlock *getBB() const { return BB; } + + SelectionDAGNode *getUse(unsigned Num) { + assert(Num < Uses.size() && "Invalid child # of SelectionDAGNode!"); + return Uses[Num]; + } + + template + Type *getValue(unsigned Code) const { + SelectionDAGReducedValue *Vals = ValList; + while (1) { + assert(Vals && "Code does not exist in this list!"); + if (Vals->getValueCode() == Code) + return (Type*)Vals; + Vals = Vals->getNext(); + } + } + + template + Type *hasValue(unsigned Code) const { + SelectionDAGReducedValue *Vals = ValList; + while (Vals) { + if (Vals->getValueCode() == Code) + return (Type*)Vals; + Vals = Vals->getNext(); + } + return false; + } + + void addValue(SelectionDAGReducedValue *New) { + assert(New->getNext() == 0); + New->setNext(ValList); + ValList = New; + } + + //===--------------------------------------------------------------------===// + // Utility methods used by the pattern matching instruction selector + // + + /// getPatternFor - Return the pattern selected to compute the specified slot, + /// or zero if there is no pattern yet. + /// + unsigned getPatternFor(unsigned Slot) const { + return Costs ? Costs[Slot*2] : 0; + } + + /// getCostFor - Return the cost to compute the value corresponding to Slot. + /// + unsigned getCostFor(unsigned Slot) const { + return Costs ? Costs[Slot*2+1] : 0; + } + + /// setPatternCostFor - Sets the pattern and the cost for the specified slot + /// to the specified values. This allocates the Costs vector if necessary, so + /// you must specify the maximum number of slots that may be used. + /// + void setPatternCostFor(unsigned Slot, unsigned Pattern, unsigned Cost, + unsigned NumSlots) { + if (Costs == 0) { + Costs = new unsigned[NumSlots*2]; + for (unsigned i = 0; i != NumSlots*2; ++i) Costs[i] = 0; + } + Costs[Slot*2] = Pattern; + Costs[Slot*2+1] = Cost; + } + + void dump() const; +private: + void printit(unsigned Offset, unsigned &LastID, + std::map &NodeIDs) const; +}; + + +/// SelectionDAGTargetBuilder - This class must be implemented by the target, to +/// indicate how to perform the extremely target-specific tasks of building DAG +/// nodes to represent the calling convention used by the target. +/// +struct SelectionDAGTargetBuilder { + /// expandArguments - This method is called once by the SelectionDAG + /// construction mechanisms to add DAG nodes for each formal argument to the + /// current function. If any of the incoming arguments lives on the stack, + /// this method should also create the stack slots for the arguments as + /// necessary. + virtual void expandArguments(SelectionDAG &SD, MachineFunction &MF) = 0; +}; + +namespace ISD { + enum { // Builtin Slot numbers + Constant_i1_Slot, + Constant_i8_Slot, + Constant_i16_Slot, + Constant_i32_Slot, + Constant_i64_Slot, + Constant_f32_Slot, + Constant_f64_Slot, + + FrameIndex_i32_Slot, + FrameIndex_i64_Slot, + NumBuiltinSlots + }; +} + +template +struct ReducedValue : public SelectionDAGReducedValue { + ReducedValue(const ValType &V) : SelectionDAGReducedValue(NodeCode), Val(V) {} + ValType Val; +}; + +typedef ReducedValue ReducedValue_FrameIndex_i32; +typedef ReducedValue ReducedValue_FrameIndex_i64; + +typedef ReducedValue ReducedValue_Constant_i1; +typedef ReducedValue ReducedValue_Constant_i8; +typedef ReducedValue ReducedValue_Constant_i16; +typedef ReducedValue ReducedValue_Constant_i32; +typedef ReducedValue ReducedValue_Constant_i64; +typedef ReducedValue ReducedValue_Constant_f32; +typedef ReducedValue ReducedValue_Constant_f64; + +#endif