mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-25 00:29:20 +00:00
Most places can use PrintFatalError as the unwinding mechanism was not used for anything other than printing the error. The single exception was CodeGenDAGPatterns.cpp, where intermediate errors during type resolution were ignored to simplify incremental platform development. This use is replaced by an error flag in TreePattern and bailout earlier in various places if it is set. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166712 91177308-0d34-0410-b5e6-96231b3b80d8
817 lines
30 KiB
C++
817 lines
30 KiB
C++
//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file declares the CodeGenDAGPatterns class, which is used to read and
|
|
// represent the patterns present in a .td file for instructions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef CODEGEN_DAGPATTERNS_H
|
|
#define CODEGEN_DAGPATTERNS_H
|
|
|
|
#include "CodeGenTarget.h"
|
|
#include "CodeGenIntrinsics.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include <set>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
namespace llvm {
|
|
class Record;
|
|
class Init;
|
|
class ListInit;
|
|
class DagInit;
|
|
class SDNodeInfo;
|
|
class TreePattern;
|
|
class TreePatternNode;
|
|
class CodeGenDAGPatterns;
|
|
class ComplexPattern;
|
|
|
|
/// EEVT::DAGISelGenValueType - These are some extended forms of
|
|
/// MVT::SimpleValueType that we use as lattice values during type inference.
|
|
/// The existing MVT iAny, fAny and vAny types suffice to represent
|
|
/// arbitrary integer, floating-point, and vector types, so only an unknown
|
|
/// value is needed.
|
|
namespace EEVT {
|
|
/// TypeSet - This is either empty if it's completely unknown, or holds a set
|
|
/// of types. It is used during type inference because register classes can
|
|
/// have multiple possible types and we don't know which one they get until
|
|
/// type inference is complete.
|
|
///
|
|
/// TypeSet can have three states:
|
|
/// Vector is empty: The type is completely unknown, it can be any valid
|
|
/// target type.
|
|
/// Vector has multiple constrained types: (e.g. v4i32 + v4f32) it is one
|
|
/// of those types only.
|
|
/// Vector has one concrete type: The type is completely known.
|
|
///
|
|
class TypeSet {
|
|
SmallVector<MVT::SimpleValueType, 4> TypeVec;
|
|
public:
|
|
TypeSet() {}
|
|
TypeSet(MVT::SimpleValueType VT, TreePattern &TP);
|
|
TypeSet(const std::vector<MVT::SimpleValueType> &VTList);
|
|
|
|
bool isCompletelyUnknown() const { return TypeVec.empty(); }
|
|
|
|
bool isConcrete() const {
|
|
if (TypeVec.size() != 1) return false;
|
|
unsigned char T = TypeVec[0]; (void)T;
|
|
assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny);
|
|
return true;
|
|
}
|
|
|
|
MVT::SimpleValueType getConcrete() const {
|
|
assert(isConcrete() && "Type isn't concrete yet");
|
|
return (MVT::SimpleValueType)TypeVec[0];
|
|
}
|
|
|
|
bool isDynamicallyResolved() const {
|
|
return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny;
|
|
}
|
|
|
|
const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const {
|
|
assert(!TypeVec.empty() && "Not a type list!");
|
|
return TypeVec;
|
|
}
|
|
|
|
bool isVoid() const {
|
|
return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid;
|
|
}
|
|
|
|
/// hasIntegerTypes - Return true if this TypeSet contains any integer value
|
|
/// types.
|
|
bool hasIntegerTypes() const;
|
|
|
|
/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
|
|
/// a floating point value type.
|
|
bool hasFloatingPointTypes() const;
|
|
|
|
/// hasVectorTypes - Return true if this TypeSet contains a vector value
|
|
/// type.
|
|
bool hasVectorTypes() const;
|
|
|
|
/// getName() - Return this TypeSet as a string.
|
|
std::string getName() const;
|
|
|
|
/// MergeInTypeInfo - This merges in type information from the specified
|
|
/// argument. If 'this' changes, it returns true. If the two types are
|
|
/// contradictory (e.g. merge f32 into i32) then this flags an error.
|
|
bool MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP);
|
|
|
|
bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) {
|
|
return MergeInTypeInfo(EEVT::TypeSet(InVT, TP), TP);
|
|
}
|
|
|
|
/// Force this type list to only contain integer types.
|
|
bool EnforceInteger(TreePattern &TP);
|
|
|
|
/// Force this type list to only contain floating point types.
|
|
bool EnforceFloatingPoint(TreePattern &TP);
|
|
|
|
/// EnforceScalar - Remove all vector types from this type list.
|
|
bool EnforceScalar(TreePattern &TP);
|
|
|
|
/// EnforceVector - Remove all non-vector types from this type list.
|
|
bool EnforceVector(TreePattern &TP);
|
|
|
|
/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
|
|
/// this an other based on this information.
|
|
bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
|
|
|
|
/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
|
|
/// whose element is VT.
|
|
bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
|
|
|
|
/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to
|
|
/// be a vector type VT.
|
|
bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
|
|
|
|
bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
|
|
bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
|
|
|
|
private:
|
|
/// FillWithPossibleTypes - Set to all legal types and return true, only
|
|
/// valid on completely unknown type sets. If Pred is non-null, only MVTs
|
|
/// that pass the predicate are added.
|
|
bool FillWithPossibleTypes(TreePattern &TP,
|
|
bool (*Pred)(MVT::SimpleValueType) = 0,
|
|
const char *PredicateName = 0);
|
|
};
|
|
}
|
|
|
|
/// Set type used to track multiply used variables in patterns
|
|
typedef std::set<std::string> MultipleUseVarSet;
|
|
|
|
/// 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, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
|
|
SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
|
|
SDTCisSubVecOfVec
|
|
} ConstraintType;
|
|
|
|
union { // The discriminated union.
|
|
struct {
|
|
MVT::SimpleValueType VT;
|
|
} SDTCisVT_Info;
|
|
struct {
|
|
unsigned OtherOperandNum;
|
|
} SDTCisSameAs_Info;
|
|
struct {
|
|
unsigned OtherOperandNum;
|
|
} SDTCisVTSmallerThanOp_Info;
|
|
struct {
|
|
unsigned BigOperandNum;
|
|
} SDTCisOpSmallerThanOp_Info;
|
|
struct {
|
|
unsigned OtherOperandNum;
|
|
} SDTCisEltOfVec_Info;
|
|
struct {
|
|
unsigned OtherOperandNum;
|
|
} SDTCisSubVecOfVec_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, an error
|
|
/// is flagged.
|
|
bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
|
|
TreePattern &TP) 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<SDTypeConstraint> TypeConstraints;
|
|
public:
|
|
SDNodeInfo(Record *R); // Parse the specified record.
|
|
|
|
unsigned getNumResults() const { return NumResults; }
|
|
|
|
/// getNumOperands - This is the number of operands required or -1 if
|
|
/// variadic.
|
|
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<SDTypeConstraint> &getTypeConstraints() const {
|
|
return TypeConstraints;
|
|
}
|
|
|
|
/// getKnownType - If the type constraints on this node imply a fixed type
|
|
/// (e.g. all stores return void, etc), then return it as an
|
|
/// MVT::SimpleValueType. Otherwise, return MVT::Other.
|
|
MVT::SimpleValueType getKnownType(unsigned ResNo) const;
|
|
|
|
/// 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, an error is flagged.
|
|
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;
|
|
}
|
|
};
|
|
|
|
/// TreePredicateFn - This is an abstraction that represents the predicates on
|
|
/// a PatFrag node. This is a simple one-word wrapper around a pointer to
|
|
/// provide nice accessors.
|
|
class TreePredicateFn {
|
|
/// PatFragRec - This is the TreePattern for the PatFrag that we
|
|
/// originally came from.
|
|
TreePattern *PatFragRec;
|
|
public:
|
|
/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
|
|
TreePredicateFn(TreePattern *N);
|
|
|
|
|
|
TreePattern *getOrigPatFragRecord() const { return PatFragRec; }
|
|
|
|
/// isAlwaysTrue - Return true if this is a noop predicate.
|
|
bool isAlwaysTrue() const;
|
|
|
|
bool isImmediatePattern() const { return !getImmCode().empty(); }
|
|
|
|
/// getImmediatePredicateCode - Return the code that evaluates this pattern if
|
|
/// this is an immediate predicate. It is an error to call this on a
|
|
/// non-immediate pattern.
|
|
std::string getImmediatePredicateCode() const {
|
|
std::string Result = getImmCode();
|
|
assert(!Result.empty() && "Isn't an immediate pattern!");
|
|
return Result;
|
|
}
|
|
|
|
|
|
bool operator==(const TreePredicateFn &RHS) const {
|
|
return PatFragRec == RHS.PatFragRec;
|
|
}
|
|
|
|
bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); }
|
|
|
|
/// Return the name to use in the generated code to reference this, this is
|
|
/// "Predicate_foo" if from a pattern fragment "foo".
|
|
std::string getFnName() const;
|
|
|
|
/// getCodeToRunOnSDNode - Return the code for the function body that
|
|
/// evaluates this predicate. The argument is expected to be in "Node",
|
|
/// not N. This handles casting and conversion to a concrete node type as
|
|
/// appropriate.
|
|
std::string getCodeToRunOnSDNode() const;
|
|
|
|
private:
|
|
std::string getPredCode() const;
|
|
std::string getImmCode() const;
|
|
};
|
|
|
|
|
|
/// 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 type of each node result. Before and during type inference, each
|
|
/// result may be a set of possible types. After (successful) type inference,
|
|
/// each is a single concrete type.
|
|
SmallVector<EEVT::TypeSet, 1> Types;
|
|
|
|
/// 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;
|
|
|
|
/// PredicateFns - The predicate functions to execute on this node to check
|
|
/// for a match. If this list is empty, no predicate is involved.
|
|
std::vector<TreePredicateFn> PredicateFns;
|
|
|
|
/// 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<TreePatternNode*> Children;
|
|
public:
|
|
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,
|
|
unsigned NumResults)
|
|
: Operator(Op), Val(0), TransformFn(0), Children(Ch) {
|
|
Types.resize(NumResults);
|
|
}
|
|
TreePatternNode(Init *val, unsigned NumResults) // leaf ctor
|
|
: Operator(0), Val(val), TransformFn(0) {
|
|
Types.resize(NumResults);
|
|
}
|
|
~TreePatternNode();
|
|
|
|
const std::string &getName() const { return Name; }
|
|
void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
|
|
|
|
bool isLeaf() const { return Val != 0; }
|
|
|
|
// Type accessors.
|
|
unsigned getNumTypes() const { return Types.size(); }
|
|
MVT::SimpleValueType getType(unsigned ResNo) const {
|
|
return Types[ResNo].getConcrete();
|
|
}
|
|
const SmallVectorImpl<EEVT::TypeSet> &getExtTypes() const { return Types; }
|
|
const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; }
|
|
EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; }
|
|
void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; }
|
|
|
|
bool hasTypeSet(unsigned ResNo) const {
|
|
return Types[ResNo].isConcrete();
|
|
}
|
|
bool isTypeCompletelyUnknown(unsigned ResNo) const {
|
|
return Types[ResNo].isCompletelyUnknown();
|
|
}
|
|
bool isTypeDynamicallyResolved(unsigned ResNo) const {
|
|
return Types[ResNo].isDynamicallyResolved();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/// hasChild - Return true if N is any of our children.
|
|
bool hasChild(const TreePatternNode *N) const {
|
|
for (unsigned i = 0, e = Children.size(); i != e; ++i)
|
|
if (Children[i] == N) return true;
|
|
return false;
|
|
}
|
|
|
|
bool hasAnyPredicate() const { return !PredicateFns.empty(); }
|
|
|
|
const std::vector<TreePredicateFn> &getPredicateFns() const {
|
|
return PredicateFns;
|
|
}
|
|
void clearPredicateFns() { PredicateFns.clear(); }
|
|
void setPredicateFns(const std::vector<TreePredicateFn> &Fns) {
|
|
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
|
|
PredicateFns = Fns;
|
|
}
|
|
void addPredicateFn(const TreePredicateFn &Fn) {
|
|
assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
|
|
if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
|
|
PredicateFns.end())
|
|
PredicateFns.push_back(Fn);
|
|
}
|
|
|
|
Record *getTransformFn() const { return TransformFn; }
|
|
void setTransformFn(Record *Fn) { TransformFn = Fn; }
|
|
|
|
/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
|
|
/// CodeGenIntrinsic information for it, otherwise return a null pointer.
|
|
const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
|
|
|
|
/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
|
|
/// return the ComplexPattern information, otherwise return null.
|
|
const ComplexPattern *
|
|
getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;
|
|
|
|
/// NodeHasProperty - Return true if this node has the specified property.
|
|
bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
|
|
|
|
/// TreeHasProperty - Return true if any node in this tree has the specified
|
|
/// property.
|
|
bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
|
|
|
|
/// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
|
|
/// marked isCommutative.
|
|
bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
|
|
|
|
void print(raw_ostream &OS) const;
|
|
void dump() const;
|
|
|
|
public: // Higher level manipulation routines.
|
|
|
|
/// clone - Return a new copy of this tree.
|
|
///
|
|
TreePatternNode *clone() const;
|
|
|
|
/// RemoveAllTypes - Recursively strip all the types of this tree.
|
|
void RemoveAllTypes();
|
|
|
|
/// 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 MultipleUseVarSet &DepVars) const;
|
|
|
|
/// SubstituteFormalArguments - Replace the formal arguments in this tree
|
|
/// with actual values specified by ArgMap.
|
|
void SubstituteFormalArguments(std::map<std::string,
|
|
TreePatternNode*> &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 relevant 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, flag an error.
|
|
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 flag an
|
|
/// error. This returns true if any information was updated.
|
|
///
|
|
bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy,
|
|
TreePattern &TP) {
|
|
return Types[ResNo].MergeInTypeInfo(InTy, TP);
|
|
}
|
|
|
|
bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy,
|
|
TreePattern &TP) {
|
|
return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
|
|
}
|
|
|
|
/// ContainsUnresolvedType - Return true if this tree contains any
|
|
/// unresolved types.
|
|
bool ContainsUnresolvedType() const {
|
|
for (unsigned i = 0, e = Types.size(); i != e; ++i)
|
|
if (!Types[i].isConcrete()) 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, const CodeGenDAGPatterns &CDP);
|
|
};
|
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
|
|
TPN.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
|
|
/// 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<TreePatternNode*> Trees;
|
|
|
|
/// NamedNodes - This is all of the nodes that have names in the trees in this
|
|
/// pattern.
|
|
StringMap<SmallVector<TreePatternNode*,1> > NamedNodes;
|
|
|
|
/// 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<std::string> Args;
|
|
|
|
/// CDP - the top-level object coordinating this madness.
|
|
///
|
|
CodeGenDAGPatterns &CDP;
|
|
|
|
/// isInputPattern - True if this is an input pattern, something to match.
|
|
/// False if this is an output pattern, something to emit.
|
|
bool isInputPattern;
|
|
|
|
/// hasError - True if the currently processed nodes have unresolvable types
|
|
/// or other non-fatal errors
|
|
bool HasError;
|
|
public:
|
|
|
|
/// TreePattern constructor - Parse the specified DagInits into the
|
|
/// current record.
|
|
TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
|
|
CodeGenDAGPatterns &ise);
|
|
TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
|
|
CodeGenDAGPatterns &ise);
|
|
TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
|
|
CodeGenDAGPatterns &ise);
|
|
|
|
/// getTrees - Return the tree patterns which corresponds to this pattern.
|
|
///
|
|
const std::vector<TreePatternNode*> &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];
|
|
}
|
|
|
|
const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() {
|
|
if (NamedNodes.empty())
|
|
ComputeNamedNodes();
|
|
return NamedNodes;
|
|
}
|
|
|
|
/// 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<std::string> &getArgList() { return Args; }
|
|
|
|
CodeGenDAGPatterns &getDAGPatterns() const { return CDP; }
|
|
|
|
/// 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 inferred, false
|
|
/// otherwise. Bail out if a type contradiction is found.
|
|
bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
|
|
*NamedTypes=0);
|
|
|
|
/// error - If this is the first error in the current resolution step,
|
|
/// print it and set the error flag. Otherwise, continue silently.
|
|
void error(const std::string &Msg);
|
|
bool hasError() const {
|
|
return HasError;
|
|
}
|
|
void resetError() {
|
|
HasError = false;
|
|
}
|
|
|
|
void print(raw_ostream &OS) const;
|
|
void dump() const;
|
|
|
|
private:
|
|
TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
|
|
void ComputeNamedNodes();
|
|
void ComputeNamedNodes(TreePatternNode *N);
|
|
};
|
|
|
|
/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
|
|
/// that has a set ExecuteAlways / DefaultOps field.
|
|
struct DAGDefaultOperand {
|
|
std::vector<TreePatternNode*> DefaultOps;
|
|
};
|
|
|
|
class DAGInstruction {
|
|
TreePattern *Pattern;
|
|
std::vector<Record*> Results;
|
|
std::vector<Record*> Operands;
|
|
std::vector<Record*> ImpResults;
|
|
TreePatternNode *ResultPattern;
|
|
public:
|
|
DAGInstruction(TreePattern *TP,
|
|
const std::vector<Record*> &results,
|
|
const std::vector<Record*> &operands,
|
|
const std::vector<Record*> &impresults)
|
|
: Pattern(TP), Results(results), Operands(operands),
|
|
ImpResults(impresults), ResultPattern(0) {}
|
|
|
|
TreePattern *getPattern() const { return Pattern; }
|
|
unsigned getNumResults() const { return Results.size(); }
|
|
unsigned getNumOperands() const { return Operands.size(); }
|
|
unsigned getNumImpResults() const { return ImpResults.size(); }
|
|
const std::vector<Record*>& getImpResults() const { return ImpResults; }
|
|
|
|
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];
|
|
}
|
|
|
|
Record *getImpResult(unsigned RN) const {
|
|
assert(RN < ImpResults.size());
|
|
return ImpResults[RN];
|
|
}
|
|
|
|
TreePatternNode *getResultPattern() const { return ResultPattern; }
|
|
};
|
|
|
|
/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
|
|
/// processed to produce isel.
|
|
class PatternToMatch {
|
|
public:
|
|
PatternToMatch(Record *srcrecord, ListInit *preds,
|
|
TreePatternNode *src, TreePatternNode *dst,
|
|
const std::vector<Record*> &dstregs,
|
|
unsigned complexity, unsigned uid)
|
|
: SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),
|
|
Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
|
|
|
|
Record *SrcRecord; // Originating Record for the pattern.
|
|
ListInit *Predicates; // Top level predicate conditions to match.
|
|
TreePatternNode *SrcPattern; // Source pattern to match.
|
|
TreePatternNode *DstPattern; // Resulting pattern.
|
|
std::vector<Record*> Dstregs; // Physical register defs being matched.
|
|
unsigned AddedComplexity; // Add to matching pattern complexity.
|
|
unsigned ID; // Unique ID for the record.
|
|
|
|
Record *getSrcRecord() const { return SrcRecord; }
|
|
ListInit *getPredicates() const { return Predicates; }
|
|
TreePatternNode *getSrcPattern() const { return SrcPattern; }
|
|
TreePatternNode *getDstPattern() const { return DstPattern; }
|
|
const std::vector<Record*> &getDstRegs() const { return Dstregs; }
|
|
unsigned getAddedComplexity() const { return AddedComplexity; }
|
|
|
|
std::string getPredicateCheck() const;
|
|
|
|
/// Compute the complexity metric for the input pattern. This roughly
|
|
/// corresponds to the number of nodes that are covered.
|
|
unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
|
|
};
|
|
|
|
class CodeGenDAGPatterns {
|
|
RecordKeeper &Records;
|
|
CodeGenTarget Target;
|
|
std::vector<CodeGenIntrinsic> Intrinsics;
|
|
std::vector<CodeGenIntrinsic> TgtIntrinsics;
|
|
|
|
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
|
|
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
|
|
std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns;
|
|
std::map<Record*, TreePattern*, LessRecordByID> PatternFragments;
|
|
std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands;
|
|
std::map<Record*, DAGInstruction, LessRecordByID> Instructions;
|
|
|
|
// Specific SDNode definitions:
|
|
Record *intrinsic_void_sdnode;
|
|
Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;
|
|
|
|
/// 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<PatternToMatch> PatternsToMatch;
|
|
public:
|
|
CodeGenDAGPatterns(RecordKeeper &R);
|
|
~CodeGenDAGPatterns();
|
|
|
|
CodeGenTarget &getTargetInfo() { return Target; }
|
|
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;
|
|
}
|
|
|
|
// Node transformation lookups.
|
|
typedef std::pair<Record*, std::string> NodeXForm;
|
|
const NodeXForm &getSDNodeTransform(Record *R) const {
|
|
assert(SDNodeXForms.count(R) && "Invalid transform!");
|
|
return SDNodeXForms.find(R)->second;
|
|
}
|
|
|
|
typedef std::map<Record*, NodeXForm, LessRecordByID>::const_iterator
|
|
nx_iterator;
|
|
nx_iterator nx_begin() const { return SDNodeXForms.begin(); }
|
|
nx_iterator nx_end() const { return SDNodeXForms.end(); }
|
|
|
|
|
|
const ComplexPattern &getComplexPattern(Record *R) const {
|
|
assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
|
|
return ComplexPatterns.find(R)->second;
|
|
}
|
|
|
|
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
|
|
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
|
if (Intrinsics[i].TheDef == R) return Intrinsics[i];
|
|
for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
|
|
if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i];
|
|
llvm_unreachable("Unknown intrinsic!");
|
|
}
|
|
|
|
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
|
|
if (IID-1 < Intrinsics.size())
|
|
return Intrinsics[IID-1];
|
|
if (IID-Intrinsics.size()-1 < TgtIntrinsics.size())
|
|
return TgtIntrinsics[IID-Intrinsics.size()-1];
|
|
llvm_unreachable("Bad intrinsic ID!");
|
|
}
|
|
|
|
unsigned getIntrinsicID(Record *R) const {
|
|
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
|
if (Intrinsics[i].TheDef == R) return i;
|
|
for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
|
|
if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size();
|
|
llvm_unreachable("Unknown intrinsic!");
|
|
}
|
|
|
|
const DAGDefaultOperand &getDefaultOperand(Record *R) const {
|
|
assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!");
|
|
return DefaultOperands.find(R)->second;
|
|
}
|
|
|
|
// Pattern Fragment information.
|
|
TreePattern *getPatternFragment(Record *R) const {
|
|
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
|
|
return PatternFragments.find(R)->second;
|
|
}
|
|
TreePattern *getPatternFragmentIfRead(Record *R) const {
|
|
if (!PatternFragments.count(R)) return 0;
|
|
return PatternFragments.find(R)->second;
|
|
}
|
|
|
|
typedef std::map<Record*, TreePattern*, LessRecordByID>::const_iterator
|
|
pf_iterator;
|
|
pf_iterator pf_begin() const { return PatternFragments.begin(); }
|
|
pf_iterator pf_end() const { return PatternFragments.end(); }
|
|
|
|
// Patterns to match information.
|
|
typedef std::vector<PatternToMatch>::const_iterator ptm_iterator;
|
|
ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
|
|
ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
|
|
|
|
|
|
|
|
const DAGInstruction &getInstruction(Record *R) const {
|
|
assert(Instructions.count(R) && "Unknown instruction!");
|
|
return Instructions.find(R)->second;
|
|
}
|
|
|
|
Record *get_intrinsic_void_sdnode() const {
|
|
return intrinsic_void_sdnode;
|
|
}
|
|
Record *get_intrinsic_w_chain_sdnode() const {
|
|
return intrinsic_w_chain_sdnode;
|
|
}
|
|
Record *get_intrinsic_wo_chain_sdnode() const {
|
|
return intrinsic_wo_chain_sdnode;
|
|
}
|
|
|
|
bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); }
|
|
|
|
private:
|
|
void ParseNodeInfo();
|
|
void ParseNodeTransforms();
|
|
void ParseComplexPatterns();
|
|
void ParsePatternFragments();
|
|
void ParseDefaultOperands();
|
|
void ParseInstructions();
|
|
void ParsePatterns();
|
|
void InferInstructionFlags();
|
|
void GenerateVariants();
|
|
void VerifyInstructionFlags();
|
|
|
|
void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM);
|
|
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
|
|
std::map<std::string,
|
|
TreePatternNode*> &InstInputs,
|
|
std::map<std::string,
|
|
TreePatternNode*> &InstResults,
|
|
std::vector<Record*> &InstImpResults);
|
|
};
|
|
} // end namespace llvm
|
|
|
|
#endif
|