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 | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 24 | // If we have a scope node, walk down both edges. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 25 | if (ScopeMatcher *Push = dyn_cast<ScopeMatcher>(N)) |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 26 | ContractNodes(Push->getCheckPtr()); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 27 | |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 28 | // If we found a movechild node with a node that comes in a 'foochild' form, |
| 29 | // transform it. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 30 | if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) { |
| 31 | Matcher *New = 0; |
| 32 | if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext())) |
| 33 | New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor()); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 34 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 35 | if (CheckTypeMatcher *CT= dyn_cast<CheckTypeMatcher>(MC->getNext())) |
| 36 | New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType()); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 37 | |
| 38 | if (New) { |
| 39 | // Insert the new node. |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 40 | New->setNext(MatcherPtr.take()); |
| 41 | MatcherPtr.reset(New); |
Chris Lattner | 3c664b3 | 2010-02-24 20:15:25 +0000 | [diff] [blame] | 42 | // Remove the old one. |
| 43 | MC->setNext(MC->getNext()->takeNext()); |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 44 | return ContractNodes(MatcherPtr); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 45 | } |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 46 | } |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 47 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 48 | if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) |
| 49 | if (MoveParentMatcher *MP = |
| 50 | dyn_cast<MoveParentMatcher>(MC->getNext())) { |
Chris Lattner | ac10e4f | 2010-02-25 01:56:48 +0000 | [diff] [blame] | 51 | MatcherPtr.reset(MP->takeNext()); |
| 52 | return ContractNodes(MatcherPtr); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | ContractNodes(N->getNextPtr()); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 56 | } |
| 57 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 58 | static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 59 | // If we reached the end of the chain, we're done. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 60 | Matcher *N = MatcherPtr.get(); |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 61 | if (N == 0) return; |
| 62 | |
| 63 | // If this is not a push node, just scan for one. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 64 | if (!isa<ScopeMatcher>(N)) |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 65 | return FactorNodes(N->getNextPtr()); |
| 66 | |
| 67 | // Okay, pull together the series of linear push nodes into a vector so we can |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame^] | 68 | // inspect it more easily. While we're at it, bucket them up by the hash |
| 69 | // code of their first predicate. |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 70 | SmallVector<Matcher*, 32> OptionsToMatch; |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame^] | 71 | typedef DenseMap<unsigned, std::vector<Matcher*> > HashTableTy; |
| 72 | HashTableTy MatchersByHash; |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 73 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 74 | Matcher *CurNode = N; |
| 75 | for (; ScopeMatcher *PMN = dyn_cast<ScopeMatcher>(CurNode); |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame^] | 76 | CurNode = PMN->getNext()) { |
| 77 | // Factor the subexpression. |
| 78 | FactorNodes(PMN->getCheckPtr()); |
| 79 | if (Matcher *Check = PMN->getCheck()) { |
| 80 | OptionsToMatch.push_back(Check); |
| 81 | MatchersByHash[Check->getHash()].push_back(Check); |
| 82 | } |
| 83 | } |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 84 | |
Chris Lattner | cd632fb | 2010-02-25 07:45:24 +0000 | [diff] [blame^] | 85 | if (CurNode) { |
| 86 | OptionsToMatch.push_back(CurNode); |
| 87 | MatchersByHash[CurNode->getHash()].push_back(CurNode); |
| 88 | } |
| 89 | |
| 90 | |
| 91 | SmallVector<Matcher*, 32> NewOptionsToMatch; |
| 92 | |
| 93 | // Now that we have bucketed up things by hash code, iterate over sets of |
| 94 | // matchers that all start with the same node. We would like to iterate over |
| 95 | // the hash table, but it isn't in deterministic order, emulate this by going |
| 96 | // about this slightly backwards. After each set of nodes is processed, we |
| 97 | // remove them from MatchersByHash. |
| 98 | for (unsigned i = 0, e = OptionsToMatch.size(); |
| 99 | i != e && !MatchersByHash.empty(); ++i) { |
| 100 | // Find the set of matchers that start with this node. |
| 101 | Matcher *Optn = OptionsToMatch[i]; |
| 102 | |
| 103 | // Find all nodes that hash to the same value. If there is no entry in the |
| 104 | // hash table, then we must have previously processed a node equal to this |
| 105 | // one. |
| 106 | HashTableTy::iterator DMI = MatchersByHash.find(Optn->getHash()); |
| 107 | if (DMI == MatchersByHash.end()) continue; |
| 108 | |
| 109 | std::vector<Matcher*> &HashMembers = DMI->second; |
| 110 | assert(!HashMembers.empty() && "Should be removed if empty"); |
| 111 | |
| 112 | // Check to see if this node is in HashMembers, if not it was equal to a |
| 113 | // previous node and removed. |
| 114 | std::vector<Matcher*>::iterator MemberSlot = |
| 115 | std::find(HashMembers.begin(), HashMembers.end(), Optn); |
| 116 | if (MemberSlot == HashMembers.end()) continue; |
| 117 | |
| 118 | // If the node *does* exist in HashMembers, then we've confirmed that it |
| 119 | // hasn't been processed as equal to a previous node. Process it now, start |
| 120 | // by removing it from the list of hash-equal nodes. |
| 121 | HashMembers.erase(MemberSlot); |
| 122 | |
| 123 | // Scan all of the hash members looking for ones that are equal, removing |
| 124 | // them from HashMembers, adding them to EqualMatchers. |
| 125 | SmallVector<Matcher*, 8> EqualMatchers; |
| 126 | |
| 127 | // Scan the vector backwards so we're generally removing from the end to |
| 128 | // avoid pointless data copying. |
| 129 | for (unsigned i = HashMembers.size(); i != 0; --i) { |
| 130 | if (!HashMembers[i-1]->isEqual(Optn)) continue; |
| 131 | |
| 132 | EqualMatchers.push_back(HashMembers[i-1]); |
| 133 | HashMembers.erase(HashMembers.begin()+i-1); |
| 134 | } |
| 135 | EqualMatchers.push_back(Optn); |
| 136 | |
| 137 | // Reverse the vector so that we preserve the match ordering. |
| 138 | std::reverse(EqualMatchers.begin(), EqualMatchers.end()); |
| 139 | |
| 140 | // If HashMembers is empty at this point, then we've gotten all nodes with |
| 141 | // the same hash, nuke the entry in the hash table. |
| 142 | if (HashMembers.empty()) |
| 143 | MatchersByHash.erase(Optn->getHash()); |
| 144 | |
| 145 | // Okay, we have the list of all matchers that start with the same node as |
| 146 | // Optn. If there is more than one in the set, we want to factor them. |
| 147 | if (EqualMatchers.size() == 1) { |
| 148 | NewOptionsToMatch.push_back(Optn); |
| 149 | continue; |
| 150 | } |
| 151 | |
| 152 | // Factor these checks by pulling the first node off each entry and |
| 153 | // discarding it, replacing it with... |
| 154 | // something amazing?? |
| 155 | |
| 156 | // FIXME: Need to change the Scope model. |
| 157 | } |
| 158 | |
| 159 | // Reassemble a new Scope node. |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 160 | |
| 161 | } |
| 162 | |
Chris Lattner | 9a51517 | 2010-02-25 02:04:40 +0000 | [diff] [blame] | 163 | Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher) { |
| 164 | OwningPtr<Matcher> MatcherPtr(TheMatcher); |
Chris Lattner | 9feb1e3 | 2010-02-24 19:52:48 +0000 | [diff] [blame] | 165 | ContractNodes(MatcherPtr); |
Chris Lattner | 0acf2ba | 2010-02-25 01:57:41 +0000 | [diff] [blame] | 166 | FactorNodes(MatcherPtr); |
Chris Lattner | 3ee1bc4 | 2010-02-24 07:31:45 +0000 | [diff] [blame] | 167 | return MatcherPtr.take(); |
Chris Lattner | 36e646c | 2010-02-24 07:06:50 +0000 | [diff] [blame] | 168 | } |