//===-- 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 #include class Value; class Type; class Instruction; class CallInst; 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, BasicBlock, // Simple binary arithmetic operators Plus, Minus, Times, SDiv, UDiv, SRem, URem, // Bitwise operators And, Or, Xor, // Comparisons SetEQ, SetNE, SetLT, SetLE, SetGT, SetGE, // Control flow instructions Br, BrCond, Switch, Ret, RetVoid, // Other operators Load, Store, PHI, Call, // Unknown operators, of a specified arity Unspec1, Unspec2 }; } 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(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, SelectionDAGNode *N1, SelectionDAGNode *N2, SelectionDAGNode *N3) : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); Uses.reserve(3); Uses.push_back(N1); Uses.push_back(N2); Uses.push_back(N3); } ~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) = 0; /// expandCall - This method is called once per function call by the /// SelectionDAG construction algorithm. It must add DAG nodes to the /// SelectionDAG specified to perform that call. virtual void expandCall(SelectionDAG &SD, CallInst &CI) = 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, BasicBlock_i32_Slot, BasicBlock_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_BasicBlock_i32; typedef ReducedValue ReducedValue_BasicBlock_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