[llvm-commits] CVS: llvm/utils/TableGen/DAGISelEmitter.cpp DAGISelEmitter.h
Chris Lattner
lattner at cs.uiuc.edu
Thu Sep 29 12:28:22 PDT 2005
Changes in directory llvm/utils/TableGen:
DAGISelEmitter.cpp updated: 1.49 -> 1.50
DAGISelEmitter.h updated: 1.28 -> 1.29
---
Log message:
Teach tblgen to build permutations of instructions, so that the target author
doesn't have to specify them manually. It currently handles associativity,
e.g. knowing that (X*Y)+Z also matches X+(Y*Z) and will be extended in
the future.
It is smart enough to not introduce duplicate patterns or patterns that can
never match.
---
Diffs of the changes: (+193 -6)
DAGISelEmitter.cpp | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++--
DAGISelEmitter.h | 6 +
2 files changed, 193 insertions(+), 6 deletions(-)
Index: llvm/utils/TableGen/DAGISelEmitter.cpp
diff -u llvm/utils/TableGen/DAGISelEmitter.cpp:1.49 llvm/utils/TableGen/DAGISelEmitter.cpp:1.50
--- llvm/utils/TableGen/DAGISelEmitter.cpp:1.49 Wed Sep 28 15:58:06 2005
+++ llvm/utils/TableGen/DAGISelEmitter.cpp Thu Sep 29 14:28:10 2005
@@ -232,6 +232,32 @@
print(std::cerr);
}
+/// 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 TreePatternNode::isIsomorphicTo(const TreePatternNode *N) const {
+ if (N == this) return true;
+ if (N->isLeaf() != isLeaf() || getType() != N->getType() ||
+ getPredicateFn() != N->getPredicateFn() ||
+ getTransformFn() != N->getTransformFn())
+ return false;
+
+ if (isLeaf()) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue()))
+ if (DefInit *NDI = dynamic_cast<DefInit*>(N->getLeafValue()))
+ return DI->getDef() == NDI->getDef();
+ return getLeafValue() == N->getLeafValue();
+ }
+
+ if (N->getOperator() != getOperator() ||
+ N->getNumChildren() != getNumChildren()) return false;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->isIsomorphicTo(N->getChild(i)))
+ return false;
+ return true;
+}
+
/// clone - Make a copy of this tree and all of its children.
///
TreePatternNode *TreePatternNode::clone() const {
@@ -1042,18 +1068,165 @@
PatternsToMatch.push_back(std::make_pair(Pattern->getOnlyTree(),
Result->getOnlyTree()));
}
+}
- DEBUG(std::cerr << "\n\nPARSED PATTERNS TO MATCH:\n\n";
- for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
- std::cerr << "PATTERN: "; PatternsToMatch[i].first->dump();
- std::cerr << "\nRESULT: ";PatternsToMatch[i].second->dump();
- std::cerr << "\n";
- });
+/// CombineChildVariants - Given a bunch of permutations of each child of the
+/// 'operator' node, put them together in all possible ways.
+static void CombineChildVariants(TreePatternNode *Orig,
+ std::vector<std::vector<TreePatternNode*> > &ChildVariants,
+ std::vector<TreePatternNode*> &OutVariants,
+ DAGISelEmitter &ISE) {
+ // The end result is an all-pairs construction of the resultant pattern.
+ std::vector<unsigned> Idxs;
+ Idxs.resize(ChildVariants.size());
+ bool NotDone = true;
+ while (NotDone) {
+ // Create the variant and add it to the output list.
+ std::vector<TreePatternNode*> NewChildren;
+ for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
+ NewChildren.push_back(ChildVariants[i][Idxs[i]]);
+ TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren);
+
+ // Copy over properties.
+ R->setName(Orig->getName());
+ R->setPredicateFn(Orig->getPredicateFn());
+ R->setTransformFn(Orig->getTransformFn());
+ R->setType(Orig->getType());
+
+ // If this pattern cannot every match, do not include it as a variant.
+ std::string ErrString;
+ if (!R->canPatternMatch(ErrString, ISE)) {
+ delete R;
+ } else {
+ bool AlreadyExists = false;
+
+ // Scan to see if this pattern has already been emitted. We can get
+ // duplication due to things like commuting:
+ // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
+ // which are the same pattern. Ignore the dups.
+ for (unsigned i = 0, e = OutVariants.size(); i != e; ++i)
+ if (R->isIsomorphicTo(OutVariants[i])) {
+ AlreadyExists = true;
+ break;
+ }
+
+ if (AlreadyExists)
+ delete R;
+ else
+ OutVariants.push_back(R);
+ }
+
+ // Increment indices to the next permutation.
+ NotDone = false;
+ // Look for something we can increment without causing a wrap-around.
+ for (unsigned IdxsIdx = 0; IdxsIdx != Idxs.size(); ++IdxsIdx) {
+ if (++Idxs[IdxsIdx] < ChildVariants[IdxsIdx].size()) {
+ NotDone = true; // Found something to increment.
+ break;
+ }
+ Idxs[IdxsIdx] = 0;
+ }
+ }
}
+/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
+/// the (potentially recursive) pattern by using algebraic laws.
+///
+static void GenerateVariantsOf(TreePatternNode *N,
+ std::vector<TreePatternNode*> &OutVariants,
+ DAGISelEmitter &ISE) {
+ // We cannot permute leaves.
+ if (N->isLeaf()) {
+ OutVariants.push_back(N);
+ return;
+ }
+
+ // Look up interesting info about the node.
+ const SDNodeInfo &NodeInfo = ISE.getSDNodeInfo(N->getOperator());
+
+ // If this node is associative, reassociate.
+ // TODO!
+
+ // Compute permutations of all children.
+ std::vector<std::vector<TreePatternNode*> > ChildVariants;
+ ChildVariants.resize(N->getNumChildren());
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ GenerateVariantsOf(N->getChild(i), ChildVariants[i], ISE);
+
+ // Build all permutations based on how the children were formed.
+ CombineChildVariants(N, ChildVariants, OutVariants, ISE);
+
+ // If this node is commutative, consider the commuted order.
+ if (NodeInfo.hasProperty(SDNodeInfo::SDNPCommutative)) {
+ assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!");
+ std::vector<std::vector<TreePatternNode*> > CommChildVariants;
+ CommChildVariants.push_back(ChildVariants[1]);
+ CommChildVariants.push_back(ChildVariants[0]);
+
+ // Consider all commuted orders.
+ CombineChildVariants(N, CommChildVariants, OutVariants, ISE);
+ }
+}
+
+
// GenerateVariants - Generate variants. For example, commutative patterns can
// match multiple ways. Add them to PatternsToMatch as well.
void DAGISelEmitter::GenerateVariants() {
+
+ DEBUG(std::cerr << "Generating instruction variants.\n");
+
+ // Loop over all of the patterns we've collected, checking to see if we can
+ // generate variants of the instruction, through the exploitation of
+ // identities. This permits the target to provide agressive matching without
+ // the .td file having to contain tons of variants of instructions.
+ //
+ // Note that this loop adds new patterns to the PatternsToMatch list, but we
+ // intentionally do not reconsider these. Any variants of added patterns have
+ // already been added.
+ //
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+ std::vector<TreePatternNode*> Variants;
+ GenerateVariantsOf(PatternsToMatch[i].first, Variants, *this);
+
+ assert(!Variants.empty() && "Must create at least original variant!");
+ assert(Variants[0]->isIsomorphicTo(PatternsToMatch[i].first) &&
+ "Input pattern should be first variant!");
+ Variants.erase(Variants.begin()); // Remove the original pattern.
+
+ if (Variants.empty()) // No variants for this pattern.
+ continue;
+
+ DEBUG(std::cerr << "FOUND VARIANTS OF: ";
+ PatternsToMatch[i].first->dump();
+ std::cerr << "\n");
+
+ for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
+ TreePatternNode *Variant = Variants[v];
+
+ DEBUG(std::cerr << " VAR#" << v << ": ";
+ Variant->dump();
+ std::cerr << "\n");
+
+ // Scan to see if an instruction or explicit pattern already matches this.
+ bool AlreadyExists = false;
+ for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
+ // Check to see if this variant already exists.
+ if (Variant->isIsomorphicTo(PatternsToMatch[p].first)) {
+ DEBUG(std::cerr << " *** ALREADY EXISTS, ignoring variant.\n");
+ AlreadyExists = true;
+ break;
+ }
+ }
+ // If we already have it, ignore the variant.
+ if (AlreadyExists) continue;
+
+ // Otherwise, add it to the list of patterns we have.
+ PatternsToMatch.push_back(std::make_pair(Variant,
+ PatternsToMatch[i].second));
+ }
+
+ DEBUG(std::cerr << "\n");
+ }
}
@@ -1381,6 +1554,14 @@
// multiple ways. Add them to PatternsToMatch as well.
GenerateVariants();
+
+ DEBUG(std::cerr << "\n\nALL PATTERNS TO MATCH:\n\n";
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+ std::cerr << "PATTERN: "; PatternsToMatch[i].first->dump();
+ std::cerr << "\nRESULT: ";PatternsToMatch[i].second->dump();
+ std::cerr << "\n";
+ });
+
// At this point, we have full information about the 'Patterns' we need to
// parse, both implicitly from instructions as well as from explicit pattern
// definitions. Emit the resultant instruction selector.
Index: llvm/utils/TableGen/DAGISelEmitter.h
diff -u llvm/utils/TableGen/DAGISelEmitter.h:1.28 llvm/utils/TableGen/DAGISelEmitter.h:1.29
--- llvm/utils/TableGen/DAGISelEmitter.h:1.28 Wed Sep 28 15:58:06 2005
+++ llvm/utils/TableGen/DAGISelEmitter.h Thu Sep 29 14:28:10 2005
@@ -174,6 +174,12 @@
///
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<std::string,
More information about the llvm-commits
mailing list