Chris Lattner | 36e646c | 2010-02-24 07:06:50 +0000 | [diff] [blame] | 1 | //===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements the DAG Matcher optimizer. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "DAGISelMatcher.h" |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/DenseMap.h" |
| 16 | #include <vector> |
Chris Lattner | 36e646c | 2010-02-24 07:06:50 +0000 | [diff] [blame] | 17 | using namespace llvm; |
| 18 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 19 | static void ContractNodes(OwningPtr<Matcher> &MatcherPtr) { |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 20 | // If we reached the end of the chain, we're done. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 21 | Matcher *N = MatcherPtr.get(); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 22 | if (N == 0) return; |
| 23 | |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 24 | // If we have a scope node, walk down all of the children. |
| 25 | if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { |
| 26 | for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { |
| 27 | OwningPtr<Matcher> Child(Scope->takeChild(i)); |
| 28 | ContractNodes(Child); |
| 29 | Scope->resetChild(i, Child.take()); |
| 30 | } |
| 31 | return; |
| 32 | } |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 33 | |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 34 | // If we found a movechild node with a node that comes in a 'foochild' form, |
| 35 | // transform it. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 36 | if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) { |
| 37 | Matcher *New = 0; |
| 38 | if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext())) |
| 39 | New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor()); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 40 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 41 | if (CheckTypeMatcher *CT= dyn_cast<CheckTypeMatcher>(MC->getNext())) |
| 42 | New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType()); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 43 | |
| 44 | if (New) { |
| 45 | // Insert the new node. |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 46 | New->setNext(MatcherPtr.take()); |
| 47 | MatcherPtr.reset(New); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 48 | // Remove the old one. |
| 49 | MC->setNext(MC->getNext()->takeNext()); |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 50 | return ContractNodes(MatcherPtr); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 51 | } |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 52 | } |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 53 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 54 | if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) |
| 55 | if (MoveParentMatcher *MP = |
| 56 | dyn_cast<MoveParentMatcher>(MC->getNext())) { |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 57 | MatcherPtr.reset(MP->takeNext()); |
| 58 | return ContractNodes(MatcherPtr); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | ContractNodes(N->getNextPtr()); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 62 | } |
| 63 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 64 | static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 65 | // If we reached the end of the chain, we're done. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 66 | Matcher *N = MatcherPtr.get(); |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 67 | if (N == 0) return; |
| 68 | |
| 69 | // If this is not a push node, just scan for one. |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 70 | ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N); |
| 71 | if (Scope == 0) |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 72 | return FactorNodes(N->getNextPtr()); |
| 73 | |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 74 | // Okay, pull together the children of the scope node into a vector so we can |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 75 | // inspect it more easily. While we're at it, bucket them up by the hash |
| 76 | // code of their first predicate. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 77 | SmallVector<Matcher*, 32> OptionsToMatch; |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 78 | |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 79 | for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 80 | // Factor the subexpression. |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 81 | OwningPtr<Matcher> Child(Scope->takeChild(i)); |
| 82 | FactorNodes(Child); |
| 83 | |
Chris Lattner | 92a2246 | 2010-02-26 08:08:41 +0000 | [diff] [blame] | 84 | if (Matcher *N = Child.take()) |
Chris Lattner | 4236366 | 2010-02-25 19:00:39 +0000 | [diff] [blame] | 85 | OptionsToMatch.push_back(N); |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 86 | } |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 87 | |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 88 | SmallVector<Matcher*, 32> NewOptionsToMatch; |
| 89 | |
Chris Lattner | 92a2246 | 2010-02-26 08:08:41 +0000 | [diff] [blame] | 90 | // Loop over options to match, merging neighboring patterns with identical |
| 91 | // starting nodes into a shared matcher. |
| 92 | for (unsigned i = 0, e = OptionsToMatch.size(); i != e;) { |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 93 | // Find the set of matchers that start with this node. |
Chris Lattner | 92a2246 | 2010-02-26 08:08:41 +0000 | [diff] [blame] | 94 | Matcher *Optn = OptionsToMatch[i++]; |
| 95 | |
| 96 | // See if the next option starts with the same matcher, if not, no sharing. |
| 97 | if (i == e || !OptionsToMatch[i]->isEqual(Optn)) { |
| 98 | // TODO: Skip over mutually exclusive patterns. |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 99 | NewOptionsToMatch.push_back(Optn); |
| 100 | continue; |
| 101 | } |
| 102 | |
Chris Lattner | 92a2246 | 2010-02-26 08:08:41 +0000 | [diff] [blame] | 103 | // If the two neighbors *do* start with the same matcher, we can factor the |
| 104 | // matcher out of at least these two patterns. See what the maximal set we |
| 105 | // can merge together is. |
| 106 | SmallVector<Matcher*, 8> EqualMatchers; |
| 107 | EqualMatchers.push_back(Optn); |
| 108 | EqualMatchers.push_back(OptionsToMatch[i++]); |
| 109 | |
| 110 | while (i != e && OptionsToMatch[i]->isEqual(Optn)) |
| 111 | EqualMatchers.push_back(OptionsToMatch[i++]); |
| 112 | |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 113 | // Factor these checks by pulling the first node off each entry and |
Chris Lattner | b0e6810 | 2010-02-26 07:36:37 +0000 | [diff] [blame] | 114 | // discarding it. Take the first one off the first entry to reuse. |
| 115 | Matcher *Shared = Optn; |
| 116 | Optn = Optn->takeNext(); |
| 117 | EqualMatchers[0] = Optn; |
| 118 | |
Chris Lattner | 92a2246 | 2010-02-26 08:08:41 +0000 | [diff] [blame] | 119 | // Remove and delete the first node from the other matchers we're factoring. |
| 120 | for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) { |
| 121 | Matcher *Tmp = EqualMatchers[i]->takeNext(); |
| 122 | delete EqualMatchers[i]; |
| 123 | EqualMatchers[i] = Tmp; |
| 124 | } |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 125 | |
Chris Lattner | b0e6810 | 2010-02-26 07:36:37 +0000 | [diff] [blame] | 126 | Shared->setNext(new ScopeMatcher(&EqualMatchers[0], EqualMatchers.size())); |
| 127 | |
| 128 | // Recursively factor the newly created node. |
| 129 | FactorNodes(Shared->getNextPtr()); |
| 130 | |
| 131 | NewOptionsToMatch.push_back(Shared); |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | // Reassemble a new Scope node. |
Chris Lattner | b0e6810 | 2010-02-26 07:36:37 +0000 | [diff] [blame] | 135 | assert(!NewOptionsToMatch.empty() && "where'd all our children go?"); |
| 136 | if (NewOptionsToMatch.size() == 1) |
| 137 | MatcherPtr.reset(NewOptionsToMatch[0]); |
| 138 | else { |
| 139 | Scope->setNumChildren(NewOptionsToMatch.size()); |
| 140 | for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) |
| 141 | Scope->resetChild(i, NewOptionsToMatch[i]); |
| 142 | } |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 143 | } |
| 144 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 145 | Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher) { |
| 146 | OwningPtr<Matcher> MatcherPtr(TheMatcher); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 147 | ContractNodes(MatcherPtr); |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 148 | FactorNodes(MatcherPtr); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 149 | return MatcherPtr.take(); |
Chris Lattner | 36e646c | 2010-02-24 07:06:50 +0000 | [diff] [blame] | 150 | } |