//===- DAGISelEmitter.h - Generate an instruction selector ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file was developed by Chris Lattner and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This tablegen backend emits a DAG instruction selector. // //===----------------------------------------------------------------------===// #ifndef DAGISEL_EMITTER_H #define DAGISEL_EMITTER_H #include "TableGenBackend.h" #include "CodeGenTarget.h" namespace llvm { class Record; struct Init; class ListInit; class DagInit; class SDNodeInfo; class TreePattern; class TreePatternNode; class DAGISelEmitter; class ComplexPattern; /// MVT::DAGISelGenValueType - These are some extended forms of MVT::ValueType /// that we use as lattice values during type inferrence. namespace MVT { enum DAGISelGenValueType { isFP = MVT::LAST_VALUETYPE, isInt, isUnknown }; } /// SDTypeConstraint - This is a discriminated union of constraints, /// corresponding to the SDTypeConstraint tablegen class in Target.td. struct SDTypeConstraint { SDTypeConstraint(Record *R); unsigned OperandNo; // The operand # this constraint applies to. enum { SDTCisVT, SDTCisInt, SDTCisFP, SDTCisSameAs, SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp } ConstraintType; union { // The discriminated union. struct { MVT::ValueType VT; } SDTCisVT_Info; struct { unsigned OtherOperandNum; } SDTCisSameAs_Info; struct { unsigned OtherOperandNum; } SDTCisVTSmallerThanOp_Info; struct { unsigned BigOperandNum; } SDTCisOpSmallerThanOp_Info; } x; /// ApplyTypeConstraint - Given a node in a pattern, apply this type /// constraint to the nodes operands. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, throw an /// exception. bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, TreePattern &TP) const; /// getOperandNum - Return the node corresponding to operand #OpNo in tree /// N, which has NumResults results. TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, unsigned NumResults) const; }; /// SDNodeInfo - One of these records is created for each SDNode instance in /// the target .td file. This represents the various dag nodes we will be /// processing. class SDNodeInfo { Record *Def; std::string EnumName; std::string SDClassName; unsigned Properties; unsigned NumResults; int NumOperands; std::vector TypeConstraints; public: SDNodeInfo(Record *R); // Parse the specified record. unsigned getNumResults() const { return NumResults; } int getNumOperands() const { return NumOperands; } Record *getRecord() const { return Def; } const std::string &getEnumName() const { return EnumName; } const std::string &getSDClassName() const { return SDClassName; } const std::vector &getTypeConstraints() const { return TypeConstraints; } // SelectionDAG node properties. enum SDNP { SDNPCommutative, SDNPAssociative, SDNPHasChain }; /// hasProperty - Return true if this node has the specified property. /// bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } /// ApplyTypeConstraints - Given a node in a pattern, apply the type /// constraints for this node to the operands of the node. This returns /// true if it makes a change, false otherwise. If a type contradiction is /// found, throw an exception. bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const { bool MadeChange = false; for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP); return MadeChange; } }; /// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped /// patterns), and as such should be ref counted. We currently just leak all /// TreePatternNode objects! class TreePatternNode { /// The inferred type for this node, or MVT::LAST_VALUETYPE if it hasn't /// been determined yet. unsigned char Ty; /// Operator - The Record for the operator if this is an interior node (not /// a leaf). Record *Operator; /// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf. /// Init *Val; /// Name - The name given to this node with the :$foo notation. /// std::string Name; /// PredicateFn - The predicate function to execute on this node to check /// for a match. If this string is empty, no predicate is involved. std::string PredicateFn; /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. Record *TransformFn; std::vector Children; public: TreePatternNode(Record *Op, const std::vector &Ch) : Ty(MVT::isUnknown), Operator(Op), Val(0), TransformFn(0), Children(Ch) {} TreePatternNode(Init *val) // leaf ctor : Ty(MVT::isUnknown), Operator(0), Val(val), TransformFn(0) {} ~TreePatternNode(); const std::string &getName() const { return Name; } void setName(const std::string &N) { Name = N; } bool isLeaf() const { return Val != 0; } bool hasTypeSet() const { return Ty < MVT::LAST_VALUETYPE; } bool isTypeCompletelyUnknown() const { return Ty == MVT::isUnknown; } MVT::ValueType getType() const { assert(hasTypeSet() && "Doesn't have a type yet!"); return (MVT::ValueType)Ty; } unsigned char getExtType() const { return Ty; } void setType(unsigned char VT) { Ty = VT; } Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } unsigned getNumChildren() const { return Children.size(); } TreePatternNode *getChild(unsigned N) const { return Children[N]; } void setChild(unsigned i, TreePatternNode *N) { Children[i] = N; } const std::string &getPredicateFn() const { return PredicateFn; } void setPredicateFn(const std::string &Fn) { PredicateFn = Fn; } Record *getTransformFn() const { return TransformFn; } void setTransformFn(Record *Fn) { TransformFn = Fn; } void print(std::ostream &OS) const; void dump() const; public: // Higher level manipulation routines. /// clone - Return a new copy of this tree. /// TreePatternNode *clone() const; /// isIsomorphicTo - Return true if this node is recursively isomorphic to /// the specified node. For this comparison, all of the state of the node /// is considered, except for the assigned name. Nodes with differing names /// that are otherwise identical are considered isomorphic. bool isIsomorphicTo(const TreePatternNode *N) const; /// SubstituteFormalArguments - Replace the formal arguments in this tree /// with actual values specified by ArgMap. void SubstituteFormalArguments(std::map &ArgMap); /// InlinePatternFragments - If this pattern refers to any pattern /// fragments, inline them into place, giving us a pattern without any /// PatFrag references. TreePatternNode *InlinePatternFragments(TreePattern &TP); /// ApplyTypeConstraints - Apply all of the type constraints relevent to /// this node and its children in the tree. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, throw an /// exception. bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); /// UpdateNodeType - Set the node type of N to VT if VT contains /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. /// bool UpdateNodeType(unsigned char EVT, TreePattern &TP); /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { if (!hasTypeSet()) return true; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) if (getChild(i)->ContainsUnresolvedType()) return true; return false; } /// canPatternMatch - If it is impossible for this pattern to match on this /// target, fill in Reason and return false. Otherwise, return true. bool canPatternMatch(std::string &Reason, DAGISelEmitter &ISE); }; /// TreePattern - Represent a pattern, used for instructions, pattern /// fragments, etc. /// class TreePattern { /// Trees - The list of pattern trees which corresponds to this pattern. /// Note that PatFrag's only have a single tree. /// std::vector Trees; /// TheRecord - The actual TableGen record corresponding to this pattern. /// Record *TheRecord; /// Args - This is a list of all of the arguments to this pattern (for /// PatFrag patterns), which are the 'node' markers in this pattern. std::vector Args; /// ISE - the DAG isel emitter coordinating this madness. /// DAGISelEmitter &ISE; /// isInputPattern - True if this is an input pattern, something to match. /// False if this is an output pattern, something to emit. bool isInputPattern; public: /// TreePattern constructor - Parse the specified DagInits into the /// current record. TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, DAGISelEmitter &ise); TreePattern(Record *TheRec, DagInit *Pat, bool isInput, DAGISelEmitter &ise); TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, DAGISelEmitter &ise); /// getTrees - Return the tree patterns which corresponds to this pattern. /// const std::vector &getTrees() const { return Trees; } unsigned getNumTrees() const { return Trees.size(); } TreePatternNode *getTree(unsigned i) const { return Trees[i]; } TreePatternNode *getOnlyTree() const { assert(Trees.size() == 1 && "Doesn't have exactly one pattern!"); return Trees[0]; } /// getRecord - Return the actual TableGen record corresponding to this /// pattern. /// Record *getRecord() const { return TheRecord; } unsigned getNumArgs() const { return Args.size(); } const std::string &getArgName(unsigned i) const { assert(i < Args.size() && "Argument reference out of range!"); return Args[i]; } std::vector &getArgList() { return Args; } DAGISelEmitter &getDAGISelEmitter() const { return ISE; } /// InlinePatternFragments - If this pattern refers to any pattern /// fragments, inline them into place, giving us a pattern without any /// PatFrag references. void InlinePatternFragments() { for (unsigned i = 0, e = Trees.size(); i != e; ++i) Trees[i] = Trees[i]->InlinePatternFragments(*this); } /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are infered, false /// otherwise. Throw an exception if a type contradiction is found. bool InferAllTypes(); /// error - Throw an exception, prefixing it with information about this /// pattern. void error(const std::string &Msg) const; void print(std::ostream &OS) const; void dump() const; private: TreePatternNode *ParseTreePattern(DagInit *DI); }; class DAGInstruction { TreePattern *Pattern; std::vector Results; std::vector Operands; TreePatternNode *ResultPattern; public: DAGInstruction(TreePattern *TP, const std::vector &results, const std::vector &operands) : Pattern(TP), Results(results), Operands(operands), ResultPattern(0) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return Results.size(); } unsigned getNumOperands() const { return Operands.size(); } void setResultPattern(TreePatternNode *R) { ResultPattern = R; } Record *getResult(unsigned RN) const { assert(RN < Results.size()); return Results[RN]; } Record *getOperand(unsigned ON) const { assert(ON < Operands.size()); return Operands[ON]; } TreePatternNode *getResultPattern() const { return ResultPattern; } }; /// InstrSelectorEmitter - The top-level class which coordinates construction /// and emission of the instruction selector. /// class DAGISelEmitter : public TableGenBackend { public: typedef std::pair PatternToMatch; private: RecordKeeper &Records; CodeGenTarget Target; std::map SDNodes; std::map > SDNodeXForms; std::map ComplexPatterns; std::map PatternFragments; std::map Instructions; /// PatternsToMatch - All of the things we are matching on the DAG. The first /// value is the pattern to match, the second pattern is the result to /// emit. std::vector PatternsToMatch; public: DAGISelEmitter(RecordKeeper &R) : Records(R) {} // run - Output the isel, returning true on failure. void run(std::ostream &OS); const CodeGenTarget &getTargetInfo() const { return Target; } Record *getSDNodeNamed(const std::string &Name) const; const SDNodeInfo &getSDNodeInfo(Record *R) const { assert(SDNodes.count(R) && "Unknown node!"); return SDNodes.find(R)->second; } const std::pair &getSDNodeTransform(Record *R) const { assert(SDNodeXForms.count(R) && "Invalid transform!"); return SDNodeXForms.find(R)->second; } const ComplexPattern &getComplexPattern(Record *R) const { assert(ComplexPatterns.count(R) && "Unknown addressing mode!"); return ComplexPatterns.find(R)->second; } TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); return PatternFragments.find(R)->second; } const DAGInstruction &getInstruction(Record *R) const { assert(Instructions.count(R) && "Unknown instruction!"); return Instructions.find(R)->second; } private: void ParseNodeInfo(); void ParseNodeTransforms(std::ostream &OS); void ParseComplexPatterns(); void ParsePatternFragments(std::ostream &OS); void ParseInstructions(); void ParsePatterns(); void GenerateVariants(); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map &InstInputs, std::map &InstResults); void EmitMatchForPattern(TreePatternNode *N, const std::string &RootName, std::map &VarMap, unsigned PatternNo, std::ostream &OS); void EmitLeadChainForPattern(TreePatternNode *N, const std::string &RootName, std::ostream &OS, bool &HasChain); void EmitCopyToRegsForPattern(TreePatternNode *N, const std::string &RootName, std::ostream &OS, bool &HasChain, bool &InFlag); std::pair CodeGenPatternResult(TreePatternNode *N, unsigned &Ctr, std::map &VariableMap, unsigned PatternNo, std::ostream &OS, bool &HasChain, bool InFlag, bool isRoot = false); void EmitCodeForPattern(PatternToMatch &Pattern, std::ostream &OS); void EmitInstructionSelector(std::ostream &OS); }; } // End llvm namespace #endif