Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1 | //===-- PredicateSimplifier.cpp - Path Sensitive Simplifier ---------------===// |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by Nick Lewycky and is distributed under the |
| 6 | // University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 8 | //===----------------------------------------------------------------------===// |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 9 | // |
| 10 | // Path-sensitive optimizer. In a branch where x == y, replace uses of |
| 11 | // x with y. Permits further optimization, such as the elimination of |
| 12 | // the unreachable call: |
| 13 | // |
| 14 | // void test(int *p, int *q) |
| 15 | // { |
| 16 | // if (p != q) |
| 17 | // return; |
| 18 | // |
| 19 | // if (*p != *q) |
| 20 | // foo(); // unreachable |
| 21 | // } |
| 22 | // |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 23 | //===----------------------------------------------------------------------===// |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 24 | // |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 25 | // This pass focusses on four properties; equals, not equals, less-than |
| 26 | // and less-than-or-equals-to. The greater-than forms are also held just |
| 27 | // to allow walking from a lesser node to a greater one. These properties |
| 28 | // are stored in a lattice; LE can become LT or EQ, NE can become LT or GT. |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 29 | // |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 30 | // These relationships define a graph between values of the same type. Each |
| 31 | // Value is stored in a map table that retrieves the associated Node. This |
| 32 | // is how EQ relationships are stored; the map contains pointers to the |
| 33 | // same node. The node contains a most canonical Value* form and the list of |
| 34 | // known relationships. |
| 35 | // |
| 36 | // If two nodes are known to be inequal, then they will contain pointers to |
| 37 | // each other with an "NE" relationship. If node getNode(%x) is less than |
| 38 | // getNode(%y), then the %x node will contain <%y, GT> and %y will contain |
| 39 | // <%x, LT>. This allows us to tie nodes together into a graph like this: |
| 40 | // |
| 41 | // %a < %b < %c < %d |
| 42 | // |
| 43 | // with four nodes representing the properties. The InequalityGraph provides |
| 44 | // queries (such as "isEqual") and mutators (such as "addEqual"). To implement |
| 45 | // "isLess(%a, %c)", we start with getNode(%c) and walk downwards until |
| 46 | // we reach %a or the leaf node. Note that the graph is directed and acyclic, |
| 47 | // but may contain joins, meaning that this walk is not a linear time |
| 48 | // algorithm. |
| 49 | // |
| 50 | // To create these properties, we wait until a branch or switch instruction |
| 51 | // implies that a particular value is true (or false). The VRPSolver is |
| 52 | // responsible for analyzing the variable and seeing what new inferences |
| 53 | // can be made from each property. For example: |
| 54 | // |
| 55 | // %P = seteq int* %ptr, null |
| 56 | // %a = or bool %P, %Q |
| 57 | // br bool %a label %cond_true, label %cond_false |
| 58 | // |
| 59 | // For the true branch, the VRPSolver will start with %a EQ true and look at |
| 60 | // the definition of %a and find that it can infer that %P and %Q are both |
| 61 | // true. From %P being true, it can infer that %ptr NE null. For the false |
| 62 | // branch it can't infer anything from the "or" instruction. |
| 63 | // |
| 64 | // Besides branches, we can also infer properties from instruction that may |
| 65 | // have undefined behaviour in certain cases. For example, the dividend of |
| 66 | // a division may never be zero. After the division instruction, we may assume |
| 67 | // that the dividend is not equal to zero. |
| 68 | // |
| 69 | //===----------------------------------------------------------------------===// |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 70 | |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 71 | #define DEBUG_TYPE "predsimplify" |
| 72 | #include "llvm/Transforms/Scalar.h" |
| 73 | #include "llvm/Constants.h" |
Nick Lewycky | f345008 | 2006-10-22 19:53:27 +0000 | [diff] [blame] | 74 | #include "llvm/DerivedTypes.h" |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 75 | #include "llvm/Instructions.h" |
| 76 | #include "llvm/Pass.h" |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 77 | #include "llvm/ADT/SetOperations.h" |
| 78 | #include "llvm/ADT/SmallVector.h" |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 79 | #include "llvm/ADT/Statistic.h" |
| 80 | #include "llvm/ADT/STLExtras.h" |
| 81 | #include "llvm/Analysis/Dominators.h" |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 82 | #include "llvm/Analysis/ET-Forest.h" |
| 83 | #include "llvm/Assembly/Writer.h" |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 84 | #include "llvm/Support/CFG.h" |
Chris Lattner | f06bb65 | 2006-12-06 18:14:47 +0000 | [diff] [blame] | 85 | #include "llvm/Support/Compiler.h" |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 86 | #include "llvm/Support/Debug.h" |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 87 | #include "llvm/Support/InstVisitor.h" |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 88 | #include "llvm/Transforms/Utils/Local.h" |
| 89 | #include <algorithm> |
| 90 | #include <deque> |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 91 | #include <sstream> |
| 92 | #include <map> |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 93 | using namespace llvm; |
| 94 | |
| 95 | namespace { |
Chris Lattner | 700b873 | 2006-12-06 17:46:33 +0000 | [diff] [blame] | 96 | Statistic |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 97 | NumVarsReplaced("predsimplify", "Number of argument substitutions"); |
Chris Lattner | 700b873 | 2006-12-06 17:46:33 +0000 | [diff] [blame] | 98 | Statistic |
Nick Lewycky | 5f8f9af | 2006-08-30 02:46:48 +0000 | [diff] [blame] | 99 | NumInstruction("predsimplify", "Number of instructions removed"); |
Chris Lattner | 700b873 | 2006-12-06 17:46:33 +0000 | [diff] [blame] | 100 | Statistic |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 101 | NumSimple("predsimplify", "Number of simple replacements"); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 102 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 103 | /// The InequalityGraph stores the relationships between values. |
| 104 | /// Each Value in the graph is assigned to a Node. Nodes are pointer |
| 105 | /// comparable for equality. The caller is expected to maintain the logical |
| 106 | /// consistency of the system. |
| 107 | /// |
| 108 | /// The InequalityGraph class may invalidate Node*s after any mutator call. |
| 109 | /// @brief The InequalityGraph stores the relationships between values. |
| 110 | class VISIBILITY_HIDDEN InequalityGraph { |
| 111 | public: |
| 112 | class Node; |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 113 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 114 | // LT GT EQ |
| 115 | // 0 0 0 -- invalid (false) |
| 116 | // 0 0 1 -- invalid (EQ) |
| 117 | // 0 1 0 -- GT |
| 118 | // 0 1 1 -- GE |
| 119 | // 1 0 0 -- LT |
| 120 | // 1 0 1 -- LE |
| 121 | // 1 1 0 -- NE |
| 122 | // 1 1 1 -- invalid (true) |
| 123 | enum LatticeBits { |
| 124 | EQ_BIT = 1, GT_BIT = 2, LT_BIT = 4 |
| 125 | }; |
| 126 | enum LatticeVal { |
| 127 | GT = GT_BIT, GE = GT_BIT | EQ_BIT, |
| 128 | LT = LT_BIT, LE = LT_BIT | EQ_BIT, |
| 129 | NE = GT_BIT | LT_BIT |
| 130 | }; |
| 131 | |
| 132 | static bool validPredicate(LatticeVal LV) { |
| 133 | return LV > 1 && LV < 7; |
| 134 | } |
| 135 | |
| 136 | private: |
| 137 | typedef std::map<Value *, Node *> NodeMapType; |
| 138 | NodeMapType Nodes; |
| 139 | |
| 140 | const InequalityGraph *ConcreteIG; |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 141 | |
| 142 | public: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 143 | /// A single node in the InequalityGraph. This stores the canonical Value |
| 144 | /// for the node, as well as the relationships with the neighbours. |
| 145 | /// |
| 146 | /// Because the lists are intended to be used for traversal, it is invalid |
| 147 | /// for the node to list itself in LessEqual or GreaterEqual lists. The |
| 148 | /// fact that a node is equal to itself is implied, and may be checked |
| 149 | /// with pointer comparison. |
| 150 | /// @brief A single node in the InequalityGraph. |
| 151 | class VISIBILITY_HIDDEN Node { |
| 152 | friend class InequalityGraph; |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 153 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 154 | Value *Canonical; |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 155 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 156 | typedef SmallVector<std::pair<Node *, LatticeVal>, 4> RelationsType; |
| 157 | RelationsType Relations; |
| 158 | public: |
| 159 | typedef RelationsType::iterator iterator; |
| 160 | typedef RelationsType::const_iterator const_iterator; |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 161 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 162 | private: |
| 163 | /// Updates the lattice value for a given node. Create a new entry if |
| 164 | /// one doesn't exist, otherwise it merges the values. The new lattice |
| 165 | /// value must not be inconsistent with any previously existing value. |
| 166 | void update(Node *N, LatticeVal R) { |
| 167 | iterator I = find(N); |
| 168 | if (I == end()) { |
| 169 | Relations.push_back(std::make_pair(N, R)); |
| 170 | } else { |
| 171 | I->second = static_cast<LatticeVal>(I->second & R); |
| 172 | assert(validPredicate(I->second) && |
| 173 | "Invalid union of lattice values."); |
Nick Lewycky | 51ce8d6 | 2006-09-13 19:24:01 +0000 | [diff] [blame] | 174 | } |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 175 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 176 | |
| 177 | void assign(Node *N, LatticeVal R) { |
| 178 | iterator I = find(N); |
| 179 | if (I != end()) I->second = R; |
| 180 | |
| 181 | Relations.push_back(std::make_pair(N, R)); |
| 182 | } |
| 183 | |
| 184 | public: |
| 185 | iterator begin() { return Relations.begin(); } |
| 186 | iterator end() { return Relations.end(); } |
| 187 | iterator find(Node *N) { |
| 188 | iterator I = begin(); |
| 189 | for (iterator E = end(); I != E; ++I) |
| 190 | if (I->first == N) break; |
| 191 | return I; |
| 192 | } |
| 193 | |
| 194 | const_iterator begin() const { return Relations.begin(); } |
| 195 | const_iterator end() const { return Relations.end(); } |
| 196 | const_iterator find(Node *N) const { |
| 197 | const_iterator I = begin(); |
| 198 | for (const_iterator E = end(); I != E; ++I) |
| 199 | if (I->first == N) break; |
| 200 | return I; |
| 201 | } |
| 202 | |
| 203 | unsigned findIndex(Node *N) { |
| 204 | unsigned i = 0; |
| 205 | iterator I = begin(); |
| 206 | for (iterator E = end(); I != E; ++I, ++i) |
| 207 | if (I->first == N) return i; |
| 208 | return (unsigned)-1; |
| 209 | } |
| 210 | |
| 211 | void erase(iterator i) { Relations.erase(i); } |
| 212 | |
| 213 | Value *getValue() const { return Canonical; } |
| 214 | void setValue(Value *V) { Canonical = V; } |
| 215 | |
| 216 | void addNotEqual(Node *N) { update(N, NE); } |
| 217 | void addLess(Node *N) { update(N, LT); } |
| 218 | void addLessEqual(Node *N) { update(N, LE); } |
| 219 | void addGreater(Node *N) { update(N, GT); } |
| 220 | void addGreaterEqual(Node *N) { update(N, GE); } |
| 221 | }; |
| 222 | |
| 223 | InequalityGraph() : ConcreteIG(NULL) {} |
| 224 | |
| 225 | InequalityGraph(const InequalityGraph &_IG) { |
| 226 | #if 0 // disable COW |
| 227 | if (_IG.ConcreteIG) ConcreteIG = _IG.ConcreteIG; |
| 228 | else ConcreteIG = &_IG; |
| 229 | #else |
| 230 | ConcreteIG = &_IG; |
| 231 | materialize(); |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 232 | #endif |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 233 | } |
| 234 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 235 | ~InequalityGraph(); |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 236 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 237 | private: |
| 238 | void materialize(); |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 239 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 240 | public: |
| 241 | /// If the Value is in the graph, return the canonical form. Otherwise, |
| 242 | /// return the original Value. |
| 243 | Value *canonicalize(Value *V) const { |
| 244 | if (const Node *N = getNode(V)) |
| 245 | return N->getValue(); |
| 246 | else |
| 247 | return V; |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 248 | } |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 249 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 250 | /// Returns the node currently representing Value V, or null if no such |
| 251 | /// node exists. |
| 252 | Node *getNode(Value *V) { |
| 253 | materialize(); |
| 254 | |
| 255 | NodeMapType::const_iterator I = Nodes.find(V); |
| 256 | return (I != Nodes.end()) ? I->second : 0; |
| 257 | } |
| 258 | |
| 259 | const Node *getNode(Value *V) const { |
| 260 | if (ConcreteIG) return ConcreteIG->getNode(V); |
| 261 | |
| 262 | NodeMapType::const_iterator I = Nodes.find(V); |
| 263 | return (I != Nodes.end()) ? I->second : 0; |
| 264 | } |
| 265 | |
| 266 | Node *getOrInsertNode(Value *V) { |
| 267 | if (Node *N = getNode(V)) |
| 268 | return N; |
| 269 | else |
| 270 | return newNode(V); |
| 271 | } |
| 272 | |
| 273 | Node *newNode(Value *V) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 274 | //DOUT << "new node: " << *V << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 275 | materialize(); |
| 276 | Node *&N = Nodes[V]; |
| 277 | assert(N == 0 && "Node already exists for value."); |
| 278 | N = new Node(); |
| 279 | N->setValue(V); |
| 280 | return N; |
| 281 | } |
| 282 | |
| 283 | /// Returns true iff the nodes are provably inequal. |
| 284 | bool isNotEqual(const Node *N1, const Node *N2) const { |
| 285 | if (N1 == N2) return false; |
| 286 | for (Node::const_iterator I = N1->begin(), E = N1->end(); I != E; ++I) { |
| 287 | if (I->first == N2) |
| 288 | return (I->second & EQ_BIT) == 0; |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 289 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 290 | return isLess(N1, N2) || isGreater(N1, N2); |
| 291 | } |
| 292 | |
| 293 | /// Returns true iff N1 is provably less than N2. |
| 294 | bool isLess(const Node *N1, const Node *N2) const { |
| 295 | if (N1 == N2) return false; |
| 296 | for (Node::const_iterator I = N2->begin(), E = N2->end(); I != E; ++I) { |
| 297 | if (I->first == N1) |
| 298 | return I->second == LT; |
| 299 | } |
| 300 | for (Node::const_iterator I = N2->begin(), E = N2->end(); I != E; ++I) { |
| 301 | if ((I->second & (LT_BIT | GT_BIT)) == LT_BIT) |
| 302 | if (isLess(N1, I->first)) return true; |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 303 | } |
| 304 | return false; |
| 305 | } |
| 306 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 307 | /// Returns true iff N1 is provably less than or equal to N2. |
| 308 | bool isLessEqual(const Node *N1, const Node *N2) const { |
| 309 | if (N1 == N2) return true; |
| 310 | for (Node::const_iterator I = N2->begin(), E = N2->end(); I != E; ++I) { |
| 311 | if (I->first == N1) |
| 312 | return (I->second & (LT_BIT | GT_BIT)) == LT_BIT; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 313 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 314 | for (Node::const_iterator I = N2->begin(), E = N2->end(); I != E; ++I) { |
| 315 | if ((I->second & (LT_BIT | GT_BIT)) == LT_BIT) |
| 316 | if (isLessEqual(N1, I->first)) return true; |
| 317 | } |
| 318 | return false; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 319 | } |
| 320 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 321 | /// Returns true iff N1 is provably greater than N2. |
| 322 | bool isGreater(const Node *N1, const Node *N2) const { |
| 323 | return isLess(N2, N1); |
| 324 | } |
Nick Lewycky | 8e55993 | 2006-09-02 19:40:38 +0000 | [diff] [blame] | 325 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 326 | /// Returns true iff N1 is provably greater than or equal to N2. |
| 327 | bool isGreaterEqual(const Node *N1, const Node *N2) const { |
| 328 | return isLessEqual(N2, N1); |
| 329 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 330 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 331 | // The add* methods assume that your input is logically valid and may |
| 332 | // assertion-fail or infinitely loop if you attempt a contradiction. |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 333 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 334 | void addEqual(Node *N, Value *V) { |
| 335 | materialize(); |
| 336 | Nodes[V] = N; |
| 337 | } |
| 338 | |
| 339 | void addNotEqual(Node *N1, Node *N2) { |
| 340 | assert(N1 != N2 && "A node can't be inequal to itself."); |
| 341 | materialize(); |
| 342 | N1->addNotEqual(N2); |
| 343 | N2->addNotEqual(N1); |
| 344 | } |
| 345 | |
| 346 | /// N1 is less than N2. |
| 347 | void addLess(Node *N1, Node *N2) { |
| 348 | assert(N1 != N2 && !isLess(N2, N1) && "Attempt to create < cycle."); |
| 349 | materialize(); |
| 350 | N2->addLess(N1); |
| 351 | N1->addGreater(N2); |
| 352 | } |
| 353 | |
| 354 | /// N1 is less than or equal to N2. |
| 355 | void addLessEqual(Node *N1, Node *N2) { |
| 356 | assert(N1 != N2 && "Nodes are equal. Use mergeNodes instead."); |
| 357 | assert(!isGreater(N1, N2) && "Impossible: Adding x <= y when x > y."); |
| 358 | materialize(); |
| 359 | N2->addLessEqual(N1); |
| 360 | N1->addGreaterEqual(N2); |
| 361 | } |
| 362 | |
| 363 | /// Find the transitive closure starting at a node walking down the edges |
| 364 | /// of type Val. Type Inserter must be an inserter that accepts Node *. |
| 365 | template <typename Inserter> |
| 366 | void transitiveClosure(Node *N, LatticeVal Val, Inserter insert) { |
| 367 | for (Node::iterator I = N->begin(), E = N->end(); I != E; ++I) { |
| 368 | if (I->second == Val) { |
| 369 | *insert = I->first; |
| 370 | transitiveClosure(I->first, Val, insert); |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 371 | } |
| 372 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 373 | } |
| 374 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 375 | /// Kills off all the nodes in Kill by replicating their properties into |
| 376 | /// node N. The elements of Kill must be unique. After merging, N's new |
| 377 | /// canonical value is NewCanonical. Type C must be a container of Node *. |
| 378 | template <typename C> |
| 379 | void mergeNodes(Node *N, C &Kill, Value *NewCanonical); |
Nick Lewycky | 51ce8d6 | 2006-09-13 19:24:01 +0000 | [diff] [blame] | 380 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 381 | /// Removes a Value from the graph, but does not delete any nodes. As this |
| 382 | /// method does not delete Nodes, V may not be the canonical choice for |
| 383 | /// any node. |
| 384 | void remove(Value *V) { |
| 385 | materialize(); |
Nick Lewycky | 8e55993 | 2006-09-02 19:40:38 +0000 | [diff] [blame] | 386 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 387 | for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); I != E;) { |
| 388 | NodeMapType::iterator J = I++; |
| 389 | assert(J->second->getValue() != V && "Can't delete canonical choice."); |
| 390 | if (J->first == V) Nodes.erase(J); |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 391 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 392 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 393 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 394 | #ifndef NDEBUG |
| 395 | void debug(std::ostream &os) const { |
| 396 | std::set<Node *> VisitedNodes; |
| 397 | for (NodeMapType::const_iterator I = Nodes.begin(), E = Nodes.end(); |
| 398 | I != E; ++I) { |
| 399 | Node *N = I->second; |
| 400 | os << *I->first << " == " << *N->getValue() << "\n"; |
| 401 | if (VisitedNodes.insert(N).second) { |
| 402 | os << *N->getValue() << ":\n"; |
| 403 | for (Node::const_iterator NI = N->begin(), NE = N->end(); |
| 404 | NI != NE; ++NI) { |
| 405 | static const std::string names[8] = |
| 406 | { "00", "01", " <", "<=", " >", ">=", "!=", "07" }; |
| 407 | os << " " << names[NI->second] << " " |
| 408 | << *NI->first->getValue() << "\n"; |
| 409 | } |
| 410 | } |
| 411 | } |
| 412 | } |
| 413 | #endif |
| 414 | }; |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 415 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 416 | InequalityGraph::~InequalityGraph() { |
| 417 | if (ConcreteIG) return; |
| 418 | |
| 419 | std::vector<Node *> Remove; |
| 420 | for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); |
| 421 | I != E; ++I) { |
| 422 | if (I->first == I->second->getValue()) |
| 423 | Remove.push_back(I->second); |
| 424 | } |
| 425 | for (std::vector<Node *>::iterator I = Remove.begin(), E = Remove.end(); |
| 426 | I != E; ++I) { |
| 427 | delete *I; |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | template <typename C> |
| 432 | void InequalityGraph::mergeNodes(Node *N, C &Kill, Value *NewCanonical) { |
| 433 | materialize(); |
| 434 | |
| 435 | // Merge the relationships from the members of Kill into N. |
| 436 | for (typename C::iterator KI = Kill.begin(), KE = Kill.end(); |
| 437 | KI != KE; ++KI) { |
| 438 | |
Jeff Cohen | cc08c83 | 2006-12-02 02:22:01 +0000 | [diff] [blame] | 439 | for (Node::iterator I = (*KI)->begin(), E = (*KI)->end(); I != E; ++I) { |
| 440 | if (I->first == N) continue; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 441 | |
| 442 | Node::iterator NI = N->find(I->first); |
| 443 | if (NI == N->end()) { |
| 444 | N->Relations.push_back(std::make_pair(I->first, I->second)); |
| 445 | } else { |
| 446 | unsigned char LV = NI->second & I->second; |
| 447 | if (LV == EQ_BIT) { |
| 448 | |
Jeff Cohen | cc08c83 | 2006-12-02 02:22:01 +0000 | [diff] [blame] | 449 | assert(std::find(Kill.begin(), Kill.end(), I->first) != Kill.end() |
| 450 | && "Lost EQ property."); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 451 | N->erase(NI); |
| 452 | } else { |
| 453 | NI->second = static_cast<LatticeVal>(LV); |
| 454 | assert(InequalityGraph::validPredicate(NI->second) && |
| 455 | "Invalid union of lattice values."); |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 456 | } |
| 457 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 458 | |
| 459 | // All edges are reciprocal; every Node that Kill points to also |
| 460 | // contains a pointer to Kill. Replace those with pointers with N. |
| 461 | unsigned iter = I->first->findIndex(*KI); |
| 462 | assert(iter != (unsigned)-1 && "Edge not reciprocal."); |
| 463 | I->first->assign(N, (I->first->begin()+iter)->second); |
| 464 | I->first->erase(I->first->begin()+iter); |
| 465 | } |
| 466 | |
| 467 | // Removing references from N to Kill. |
Jeff Cohen | cc08c83 | 2006-12-02 02:22:01 +0000 | [diff] [blame] | 468 | Node::iterator NI = N->find(*KI); |
| 469 | if (NI != N->end()) { |
| 470 | N->erase(NI); // breaks reciprocity until Kill is deleted. |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 471 | } |
| 472 | } |
| 473 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 474 | N->setValue(NewCanonical); |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 475 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 476 | // Update value mapping to point to the merged node. |
| 477 | for (NodeMapType::iterator I = Nodes.begin(), E = Nodes.end(); |
| 478 | I != E; ++I) { |
| 479 | if (std::find(Kill.begin(), Kill.end(), I->second) != Kill.end()) |
| 480 | I->second = N; |
| 481 | } |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 482 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 483 | for (typename C::iterator KI = Kill.begin(), KE = Kill.end(); |
| 484 | KI != KE; ++KI) { |
| 485 | delete *KI; |
| 486 | } |
| 487 | } |
| 488 | |
| 489 | void InequalityGraph::materialize() { |
| 490 | if (!ConcreteIG) return; |
| 491 | const InequalityGraph *IG = ConcreteIG; |
| 492 | ConcreteIG = NULL; |
| 493 | |
| 494 | for (NodeMapType::const_iterator I = IG->Nodes.begin(), |
| 495 | E = IG->Nodes.end(); I != E; ++I) { |
| 496 | if (I->first == I->second->getValue()) { |
| 497 | Node *N = newNode(I->first); |
| 498 | N->Relations.reserve(N->Relations.size()); |
| 499 | } |
| 500 | } |
| 501 | for (NodeMapType::const_iterator I = IG->Nodes.begin(), |
| 502 | E = IG->Nodes.end(); I != E; ++I) { |
| 503 | if (I->first != I->second->getValue()) { |
| 504 | Nodes[I->first] = getNode(I->second->getValue()); |
| 505 | } else { |
| 506 | Node *Old = I->second; |
| 507 | Node *N = getNode(I->first); |
| 508 | for (Node::const_iterator NI = Old->begin(), NE = Old->end(); |
| 509 | NI != NE; ++NI) { |
| 510 | N->assign(getNode(NI->first->getValue()), NI->second); |
| 511 | } |
| 512 | } |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | /// VRPSolver keeps track of how changes to one variable affect other |
| 517 | /// variables, and forwards changes along to the InequalityGraph. It |
| 518 | /// also maintains the correct choice for "canonical" in the IG. |
| 519 | /// @brief VRPSolver calculates inferences from a new relationship. |
| 520 | class VISIBILITY_HIDDEN VRPSolver { |
| 521 | private: |
| 522 | std::deque<Instruction *> WorkList; |
| 523 | |
| 524 | InequalityGraph &IG; |
| 525 | const InequalityGraph &cIG; |
| 526 | ETForest *Forest; |
| 527 | ETNode *Top; |
| 528 | |
| 529 | typedef InequalityGraph::Node Node; |
| 530 | |
| 531 | /// Returns true if V1 is a better canonical value than V2. |
| 532 | bool compare(Value *V1, Value *V2) const { |
| 533 | if (isa<Constant>(V1)) |
| 534 | return !isa<Constant>(V2); |
| 535 | else if (isa<Constant>(V2)) |
| 536 | return false; |
| 537 | else if (isa<Argument>(V1)) |
| 538 | return !isa<Argument>(V2); |
| 539 | else if (isa<Argument>(V2)) |
| 540 | return false; |
| 541 | |
| 542 | Instruction *I1 = dyn_cast<Instruction>(V1); |
| 543 | Instruction *I2 = dyn_cast<Instruction>(V2); |
| 544 | |
| 545 | if (!I1 || !I2) return false; |
| 546 | |
| 547 | BasicBlock *BB1 = I1->getParent(), |
| 548 | *BB2 = I2->getParent(); |
| 549 | if (BB1 == BB2) { |
| 550 | for (BasicBlock::const_iterator I = BB1->begin(), E = BB1->end(); |
| 551 | I != E; ++I) { |
| 552 | if (&*I == I1) return true; |
| 553 | if (&*I == I2) return false; |
| 554 | } |
| 555 | assert(!"Instructions not found in parent BasicBlock?"); |
| 556 | } else { |
| 557 | return Forest->properlyDominates(BB1, BB2); |
| 558 | } |
| 559 | return false; |
| 560 | } |
| 561 | |
| 562 | void addToWorklist(Instruction *I) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 563 | //DOUT << "addToWorklist: " << *I << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 564 | |
| 565 | if (!isa<BinaryOperator>(I) && !isa<SelectInst>(I)) return; |
| 566 | |
| 567 | const Type *Ty = I->getType(); |
| 568 | if (Ty == Type::VoidTy || Ty->isFPOrFPVector()) return; |
| 569 | |
| 570 | if (isInstructionTriviallyDead(I)) return; |
| 571 | |
| 572 | WorkList.push_back(I); |
| 573 | } |
| 574 | |
| 575 | void addRecursive(Value *V) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 576 | //DOUT << "addRecursive: " << *V << "\n"; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 577 | |
| 578 | Instruction *I = dyn_cast<Instruction>(V); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 579 | if (I) |
| 580 | addToWorklist(I); |
| 581 | else if (!isa<Argument>(V)) |
| 582 | return; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 583 | |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 584 | //DOUT << "addRecursive uses...\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 585 | for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); |
| 586 | UI != UE; ++UI) { |
| 587 | // Use must be either be dominated by Top, or dominate Top. |
| 588 | if (Instruction *Inst = dyn_cast<Instruction>(*UI)) { |
| 589 | ETNode *INode = Forest->getNodeForBlock(Inst->getParent()); |
| 590 | if (INode->DominatedBy(Top) || Top->DominatedBy(INode)) |
| 591 | addToWorklist(Inst); |
| 592 | } |
| 593 | } |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 594 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 595 | if (I) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 596 | //DOUT << "addRecursive ops...\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 597 | for (User::op_iterator OI = I->op_begin(), OE = I->op_end(); |
| 598 | OI != OE; ++OI) { |
| 599 | if (Instruction *Inst = dyn_cast<Instruction>(*OI)) |
| 600 | addToWorklist(Inst); |
| 601 | } |
| 602 | } |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 603 | //DOUT << "exit addRecursive (" << *V << ").\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 604 | } |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 605 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 606 | public: |
| 607 | VRPSolver(InequalityGraph &IG, ETForest *Forest, BasicBlock *TopBB) |
| 608 | : IG(IG), cIG(IG), Forest(Forest), Top(Forest->getNodeForBlock(TopBB)) {} |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 609 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 610 | bool isEqual(Value *V1, Value *V2) const { |
| 611 | if (V1 == V2) return true; |
| 612 | if (const Node *N1 = cIG.getNode(V1)) |
| 613 | return N1 == cIG.getNode(V2); |
| 614 | return false; |
| 615 | } |
| 616 | |
| 617 | bool isNotEqual(Value *V1, Value *V2) const { |
| 618 | if (V1 == V2) return false; |
| 619 | if (const Node *N1 = cIG.getNode(V1)) |
| 620 | if (const Node *N2 = cIG.getNode(V2)) |
| 621 | return cIG.isNotEqual(N1, N2); |
| 622 | return false; |
| 623 | } |
| 624 | |
| 625 | bool isLess(Value *V1, Value *V2) const { |
| 626 | if (V1 == V2) return false; |
| 627 | if (const Node *N1 = cIG.getNode(V1)) |
| 628 | if (const Node *N2 = cIG.getNode(V2)) |
| 629 | return cIG.isLess(N1, N2); |
| 630 | return false; |
| 631 | } |
| 632 | |
| 633 | bool isLessEqual(Value *V1, Value *V2) const { |
| 634 | if (V1 == V2) return true; |
| 635 | if (const Node *N1 = cIG.getNode(V1)) |
| 636 | if (const Node *N2 = cIG.getNode(V2)) |
| 637 | return cIG.isLessEqual(N1, N2); |
| 638 | return false; |
| 639 | } |
| 640 | |
| 641 | bool isGreater(Value *V1, Value *V2) const { |
| 642 | if (V1 == V2) return false; |
| 643 | if (const Node *N1 = cIG.getNode(V1)) |
| 644 | if (const Node *N2 = cIG.getNode(V2)) |
| 645 | return cIG.isGreater(N1, N2); |
| 646 | return false; |
| 647 | } |
| 648 | |
| 649 | bool isGreaterEqual(Value *V1, Value *V2) const { |
| 650 | if (V1 == V2) return true; |
| 651 | if (const Node *N1 = IG.getNode(V1)) |
| 652 | if (const Node *N2 = IG.getNode(V2)) |
| 653 | return cIG.isGreaterEqual(N1, N2); |
| 654 | return false; |
| 655 | } |
| 656 | |
| 657 | // All of the add* functions return true if the InequalityGraph represents |
| 658 | // the property, and false if there is a logical contradiction. On false, |
| 659 | // you may no longer perform any queries on the InequalityGraph. |
| 660 | |
| 661 | bool addEqual(Value *V1, Value *V2) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 662 | //DOUT << "addEqual(" << *V1 << ", " << *V2 << ")\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 663 | if (isEqual(V1, V2)) return true; |
| 664 | |
| 665 | const Node *cN1 = cIG.getNode(V1), *cN2 = cIG.getNode(V2); |
| 666 | |
| 667 | if (cN1 && cN2 && cIG.isNotEqual(cN1, cN2)) |
| 668 | return false; |
| 669 | |
| 670 | if (compare(V2, V1)) { std::swap(V1, V2); std::swap(cN1, cN2); } |
| 671 | |
| 672 | if (cN1) { |
| 673 | if (ConstantBool *CB = dyn_cast<ConstantBool>(V1)) { |
| 674 | Node *N1 = IG.getNode(V1); |
| 675 | |
| 676 | // When "addEqual" is performed and the new value is a ConstantBool, |
| 677 | // iterate through the NE set and fix them up to be EQ of the |
| 678 | // opposite bool. |
| 679 | |
| 680 | for (Node::iterator I = N1->begin(), E = N1->end(); I != E; ++I) |
| 681 | if ((I->second & 1) == 0) { |
| 682 | assert(N1 != I->first && "Node related to itself?"); |
| 683 | addEqual(I->first->getValue(), |
| 684 | ConstantBool::get(!CB->getValue())); |
| 685 | } |
| 686 | } |
| 687 | } |
| 688 | |
| 689 | if (!cN2) { |
| 690 | if (Instruction *I2 = dyn_cast<Instruction>(V2)) { |
| 691 | ETNode *Node_I2 = Forest->getNodeForBlock(I2->getParent()); |
| 692 | if (Top != Node_I2 && Node_I2->DominatedBy(Top)) { |
| 693 | Value *V = V1; |
| 694 | if (cN1 && compare(V1, cN1->getValue())) V = cN1->getValue(); |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 695 | //DOUT << "Simply removing " << *I2 |
| 696 | // << ", replacing with " << *V << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 697 | I2->replaceAllUsesWith(V); |
| 698 | // leave it dead; it'll get erased later. |
| 699 | ++NumSimple; |
| 700 | addRecursive(V1); |
| 701 | return true; |
| 702 | } |
| 703 | } |
| 704 | } |
| 705 | |
| 706 | Node *N1 = IG.getNode(V1), *N2 = IG.getNode(V2); |
| 707 | |
| 708 | if ( N1 && !N2) { |
| 709 | IG.addEqual(N1, V2); |
| 710 | if (compare(V1, N1->getValue())) N1->setValue(V1); |
| 711 | } |
| 712 | if (!N1 && N2) { |
| 713 | IG.addEqual(N2, V1); |
| 714 | if (compare(V1, N2->getValue())) N2->setValue(V1); |
| 715 | } |
| 716 | if ( N1 && N2) { |
| 717 | // Suppose we're being told that %x == %y, and %x <= %z and %y >= %z. |
| 718 | // We can't just merge %x and %y because the relationship with %z would |
| 719 | // be EQ and that's invalid; they need to be the same Node. |
| 720 | // |
| 721 | // What we're doing is looking for any chain of nodes reaching %z such |
| 722 | // that %x <= %z and %y >= %z, and vice versa. The cool part is that |
| 723 | // every node in between is also equal because of the squeeze principle. |
| 724 | |
| 725 | std::vector<Node *> N1_GE, N2_LE, N1_LE, N2_GE; |
| 726 | IG.transitiveClosure(N1, InequalityGraph::GE, back_inserter(N1_GE)); |
| 727 | std::sort(N1_GE.begin(), N1_GE.end()); |
| 728 | N1_GE.erase(std::unique(N1_GE.begin(), N1_GE.end()), N1_GE.end()); |
| 729 | IG.transitiveClosure(N2, InequalityGraph::LE, back_inserter(N2_LE)); |
| 730 | std::sort(N1_LE.begin(), N1_LE.end()); |
| 731 | N1_LE.erase(std::unique(N1_LE.begin(), N1_LE.end()), N1_LE.end()); |
| 732 | IG.transitiveClosure(N1, InequalityGraph::LE, back_inserter(N1_LE)); |
| 733 | std::sort(N2_GE.begin(), N2_GE.end()); |
| 734 | N2_GE.erase(std::unique(N2_GE.begin(), N2_GE.end()), N2_GE.end()); |
| 735 | std::unique(N2_GE.begin(), N2_GE.end()); |
| 736 | IG.transitiveClosure(N2, InequalityGraph::GE, back_inserter(N2_GE)); |
| 737 | std::sort(N2_LE.begin(), N2_LE.end()); |
| 738 | N2_LE.erase(std::unique(N2_LE.begin(), N2_LE.end()), N2_LE.end()); |
| 739 | |
| 740 | std::vector<Node *> Set1, Set2; |
| 741 | std::set_intersection(N1_GE.begin(), N1_GE.end(), |
| 742 | N2_LE.begin(), N2_LE.end(), |
| 743 | back_inserter(Set1)); |
| 744 | std::set_intersection(N1_LE.begin(), N1_LE.end(), |
| 745 | N2_GE.begin(), N2_GE.end(), |
| 746 | back_inserter(Set2)); |
| 747 | |
| 748 | std::vector<Node *> Equal; |
| 749 | std::set_union(Set1.begin(), Set1.end(), Set2.begin(), Set2.end(), |
| 750 | back_inserter(Equal)); |
| 751 | |
| 752 | Value *Best = N1->getValue(); |
| 753 | if (compare(N2->getValue(), Best)) Best = N2->getValue(); |
| 754 | |
| 755 | for (std::vector<Node *>::iterator I = Equal.begin(), E = Equal.end(); |
| 756 | I != E; ++I) { |
| 757 | Value *V = (*I)->getValue(); |
| 758 | if (compare(V, Best)) Best = V; |
| 759 | } |
| 760 | |
| 761 | Equal.push_back(N2); |
| 762 | IG.mergeNodes(N1, Equal, Best); |
| 763 | } |
| 764 | if (!N1 && !N2) IG.addEqual(IG.newNode(V1), V2); |
| 765 | |
| 766 | addRecursive(V1); |
| 767 | addRecursive(V2); |
| 768 | |
| 769 | return true; |
| 770 | } |
| 771 | |
| 772 | bool addNotEqual(Value *V1, Value *V2) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 773 | //DOUT << "addNotEqual(" << *V1 << ", " << *V2 << ")\n"); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 774 | if (isNotEqual(V1, V2)) return true; |
| 775 | |
| 776 | // Never permit %x NE true/false. |
| 777 | if (ConstantBool *B1 = dyn_cast<ConstantBool>(V1)) { |
| 778 | return addEqual(ConstantBool::get(!B1->getValue()), V2); |
| 779 | } else if (ConstantBool *B2 = dyn_cast<ConstantBool>(V2)) { |
| 780 | return addEqual(V1, ConstantBool::get(!B2->getValue())); |
| 781 | } |
| 782 | |
| 783 | Node *N1 = IG.getOrInsertNode(V1), |
| 784 | *N2 = IG.getOrInsertNode(V2); |
| 785 | |
| 786 | if (N1 == N2) return false; |
| 787 | |
| 788 | IG.addNotEqual(N1, N2); |
| 789 | |
| 790 | addRecursive(V1); |
| 791 | addRecursive(V2); |
| 792 | |
| 793 | return true; |
| 794 | } |
| 795 | |
| 796 | /// Set V1 less than V2. |
| 797 | bool addLess(Value *V1, Value *V2) { |
| 798 | if (isLess(V1, V2)) return true; |
| 799 | if (isGreaterEqual(V1, V2)) return false; |
| 800 | |
| 801 | Node *N1 = IG.getOrInsertNode(V1), *N2 = IG.getOrInsertNode(V2); |
| 802 | |
| 803 | if (N1 == N2) return false; |
| 804 | |
| 805 | IG.addLess(N1, N2); |
| 806 | |
| 807 | addRecursive(V1); |
| 808 | addRecursive(V2); |
| 809 | |
| 810 | return true; |
| 811 | } |
| 812 | |
| 813 | /// Set V1 less than or equal to V2. |
| 814 | bool addLessEqual(Value *V1, Value *V2) { |
| 815 | if (isLessEqual(V1, V2)) return true; |
| 816 | if (V1 == V2) return true; |
| 817 | |
| 818 | if (isLessEqual(V2, V1)) |
| 819 | return addEqual(V1, V2); |
| 820 | |
| 821 | if (isGreater(V1, V2)) return false; |
| 822 | |
| 823 | Node *N1 = IG.getOrInsertNode(V1), |
| 824 | *N2 = IG.getOrInsertNode(V2); |
| 825 | |
| 826 | if (N1 == N2) return true; |
| 827 | |
| 828 | IG.addLessEqual(N1, N2); |
| 829 | |
| 830 | addRecursive(V1); |
| 831 | addRecursive(V2); |
| 832 | |
| 833 | return true; |
| 834 | } |
| 835 | |
| 836 | void solve() { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 837 | DOUT << "WorkList entry, size: " << WorkList.size() << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 838 | while (!WorkList.empty()) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 839 | DOUT << "WorkList size: " << WorkList.size() << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 840 | |
| 841 | Instruction *I = WorkList.front(); |
| 842 | WorkList.pop_front(); |
| 843 | |
| 844 | Value *Canonical = cIG.canonicalize(I); |
| 845 | const Type *Ty = I->getType(); |
| 846 | |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 847 | //DOUT << "solving: " << *I << "\n"; |
| 848 | //DEBUG(IG.debug(*cerr.stream())); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 849 | |
| 850 | if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) { |
| 851 | Value *Op0 = cIG.canonicalize(BO->getOperand(0)), |
| 852 | *Op1 = cIG.canonicalize(BO->getOperand(1)); |
| 853 | |
| 854 | ConstantIntegral *CI1 = dyn_cast<ConstantIntegral>(Op0), |
| 855 | *CI2 = dyn_cast<ConstantIntegral>(Op1); |
| 856 | |
| 857 | if (CI1 && CI2) |
| 858 | addEqual(BO, ConstantExpr::get(BO->getOpcode(), CI1, CI2)); |
| 859 | |
| 860 | switch (BO->getOpcode()) { |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 861 | case Instruction::SetEQ: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 862 | // "seteq int %a, %b" EQ true then %a EQ %b |
| 863 | // "seteq int %a, %b" EQ false then %a NE %b |
| 864 | if (Canonical == ConstantBool::getTrue()) |
| 865 | addEqual(Op0, Op1); |
| 866 | else if (Canonical == ConstantBool::getFalse()) |
| 867 | addNotEqual(Op0, Op1); |
| 868 | |
| 869 | // %a EQ %b then "seteq int %a, %b" EQ true |
| 870 | // %a NE %b then "seteq int %a, %b" EQ false |
| 871 | if (isEqual(Op0, Op1)) |
| 872 | addEqual(BO, ConstantBool::getTrue()); |
| 873 | else if (isNotEqual(Op0, Op1)) |
| 874 | addEqual(BO, ConstantBool::getFalse()); |
| 875 | |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 876 | break; |
| 877 | case Instruction::SetNE: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 878 | // "setne int %a, %b" EQ true then %a NE %b |
| 879 | // "setne int %a, %b" EQ false then %a EQ %b |
| 880 | if (Canonical == ConstantBool::getTrue()) |
| 881 | addNotEqual(Op0, Op1); |
| 882 | else if (Canonical == ConstantBool::getFalse()) |
| 883 | addEqual(Op0, Op1); |
| 884 | |
| 885 | // %a EQ %b then "setne int %a, %b" EQ false |
| 886 | // %a NE %b then "setne int %a, %b" EQ true |
| 887 | if (isEqual(Op0, Op1)) |
| 888 | addEqual(BO, ConstantBool::getFalse()); |
| 889 | else if (isNotEqual(Op0, Op1)) |
| 890 | addEqual(BO, ConstantBool::getTrue()); |
| 891 | |
| 892 | break; |
| 893 | case Instruction::SetLT: |
| 894 | // "setlt int %a, %b" EQ true then %a LT %b |
| 895 | // "setlt int %a, %b" EQ false then %b LE %a |
| 896 | if (Canonical == ConstantBool::getTrue()) |
| 897 | addLess(Op0, Op1); |
| 898 | else if (Canonical == ConstantBool::getFalse()) |
| 899 | addLessEqual(Op1, Op0); |
| 900 | |
| 901 | // %a LT %b then "setlt int %a, %b" EQ true |
| 902 | // %a GE %b then "setlt int %a, %b" EQ false |
| 903 | if (isLess(Op0, Op1)) |
| 904 | addEqual(BO, ConstantBool::getTrue()); |
| 905 | else if (isGreaterEqual(Op0, Op1)) |
| 906 | addEqual(BO, ConstantBool::getFalse()); |
| 907 | |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 908 | break; |
| 909 | case Instruction::SetLE: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 910 | // "setle int %a, %b" EQ true then %a LE %b |
| 911 | // "setle int %a, %b" EQ false then %b LT %a |
| 912 | if (Canonical == ConstantBool::getTrue()) |
| 913 | addLessEqual(Op0, Op1); |
| 914 | else if (Canonical == ConstantBool::getFalse()) |
| 915 | addLess(Op1, Op0); |
| 916 | |
| 917 | // %a LE %b then "setle int %a, %b" EQ true |
| 918 | // %a GT %b then "setle int %a, %b" EQ false |
| 919 | if (isLessEqual(Op0, Op1)) |
| 920 | addEqual(BO, ConstantBool::getTrue()); |
| 921 | else if (isGreater(Op0, Op1)) |
| 922 | addEqual(BO, ConstantBool::getFalse()); |
| 923 | |
| 924 | break; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 925 | case Instruction::SetGT: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 926 | // "setgt int %a, %b" EQ true then %b LT %a |
| 927 | // "setgt int %a, %b" EQ false then %a LE %b |
| 928 | if (Canonical == ConstantBool::getTrue()) |
| 929 | addLess(Op1, Op0); |
| 930 | else if (Canonical == ConstantBool::getFalse()) |
| 931 | addLessEqual(Op0, Op1); |
| 932 | |
| 933 | // %a GT %b then "setgt int %a, %b" EQ true |
| 934 | // %a LE %b then "setgt int %a, %b" EQ false |
| 935 | if (isGreater(Op0, Op1)) |
| 936 | addEqual(BO, ConstantBool::getTrue()); |
| 937 | else if (isLessEqual(Op0, Op1)) |
| 938 | addEqual(BO, ConstantBool::getFalse()); |
| 939 | |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 940 | break; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 941 | case Instruction::SetGE: |
| 942 | // "setge int %a, %b" EQ true then %b LE %a |
| 943 | // "setge int %a, %b" EQ false then %a LT %b |
| 944 | if (Canonical == ConstantBool::getTrue()) |
| 945 | addLessEqual(Op1, Op0); |
| 946 | else if (Canonical == ConstantBool::getFalse()) |
| 947 | addLess(Op0, Op1); |
| 948 | |
| 949 | // %a GE %b then "setge int %a, %b" EQ true |
| 950 | // %a LT %b then "setlt int %a, %b" EQ false |
| 951 | if (isGreaterEqual(Op0, Op1)) |
| 952 | addEqual(BO, ConstantBool::getTrue()); |
| 953 | else if (isLess(Op0, Op1)) |
| 954 | addEqual(BO, ConstantBool::getFalse()); |
| 955 | |
| 956 | break; |
| 957 | case Instruction::And: { |
| 958 | // "and int %a, %b" EQ -1 then %a EQ -1 and %b EQ -1 |
| 959 | // "and bool %a, %b" EQ true then %a EQ true and %b EQ true |
| 960 | ConstantIntegral *CI = ConstantIntegral::getAllOnesValue(Ty); |
| 961 | if (Canonical == CI) { |
| 962 | addEqual(CI, Op0); |
| 963 | addEqual(CI, Op1); |
| 964 | } |
| 965 | } break; |
| 966 | case Instruction::Or: { |
| 967 | // "or int %a, %b" EQ 0 then %a EQ 0 and %b EQ 0 |
| 968 | // "or bool %a, %b" EQ false then %a EQ false and %b EQ false |
| 969 | Constant *Zero = Constant::getNullValue(Ty); |
| 970 | if (Canonical == Zero) { |
| 971 | addEqual(Zero, Op0); |
| 972 | addEqual(Zero, Op1); |
| 973 | } |
| 974 | } break; |
| 975 | case Instruction::Xor: { |
| 976 | // "xor bool true, %a" EQ true then %a EQ false |
| 977 | // "xor bool true, %a" EQ false then %a EQ true |
| 978 | // "xor bool false, %a" EQ true then %a EQ true |
| 979 | // "xor bool false, %a" EQ false then %a EQ false |
| 980 | // "xor int %c, %a" EQ %c then %a EQ 0 |
| 981 | // "xor int %c, %a" NE %c then %a NE 0 |
| 982 | // 1. Repeat all of the above, with order of operands reversed. |
| 983 | Value *LHS = Op0, *RHS = Op1; |
| 984 | if (!isa<Constant>(LHS)) std::swap(LHS, RHS); |
| 985 | |
| 986 | if (ConstantBool *CB = dyn_cast<ConstantBool>(Canonical)) { |
| 987 | if (ConstantBool *A = dyn_cast<ConstantBool>(LHS)) |
| 988 | addEqual(RHS, ConstantBool::get(A->getValue() ^ |
| 989 | CB->getValue())); |
| 990 | } |
| 991 | if (Canonical == LHS) { |
| 992 | if (isa<ConstantIntegral>(Canonical)) |
| 993 | addEqual(RHS, Constant::getNullValue(Ty)); |
| 994 | } else if (isNotEqual(LHS, Canonical)) { |
| 995 | addNotEqual(RHS, Constant::getNullValue(Ty)); |
| 996 | } |
| 997 | } break; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 998 | default: |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 999 | break; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1000 | } |
| 1001 | |
| 1002 | // "%x = add int %y, %z" and %x EQ %y then %z EQ 0 |
| 1003 | // "%x = mul int %y, %z" and %x EQ %y then %z EQ 1 |
| 1004 | // 1. Repeat all of the above, with order of operands reversed. |
| 1005 | // "%x = fdiv float %y, %z" and %x EQ %y then %z EQ 1 |
| 1006 | Value *Known = Op0, *Unknown = Op1; |
| 1007 | if (Known != BO) std::swap(Known, Unknown); |
| 1008 | if (Known == BO) { |
| 1009 | switch (BO->getOpcode()) { |
| 1010 | default: break; |
| 1011 | case Instruction::Xor: |
| 1012 | case Instruction::Or: |
| 1013 | case Instruction::Add: |
| 1014 | case Instruction::Sub: |
| 1015 | if (!Ty->isFloatingPoint()) |
| 1016 | addEqual(Unknown, Constant::getNullValue(Ty)); |
| 1017 | break; |
| 1018 | case Instruction::UDiv: |
| 1019 | case Instruction::SDiv: |
| 1020 | case Instruction::FDiv: |
| 1021 | if (Unknown == Op0) break; // otherwise, fallthrough |
| 1022 | case Instruction::And: |
| 1023 | case Instruction::Mul: |
| 1024 | Constant *One = NULL; |
| 1025 | if (isa<ConstantInt>(Unknown)) |
| 1026 | One = ConstantInt::get(Ty, 1); |
| 1027 | else if (isa<ConstantFP>(Unknown)) |
| 1028 | One = ConstantFP::get(Ty, 1); |
| 1029 | else if (isa<ConstantBool>(Unknown)) |
| 1030 | One = ConstantBool::getTrue(); |
| 1031 | |
| 1032 | if (One) addEqual(Unknown, One); |
| 1033 | break; |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 1034 | } |
| 1035 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1036 | } else if (SelectInst *SI = dyn_cast<SelectInst>(I)) { |
| 1037 | // Given: "%a = select bool %x, int %b, int %c" |
| 1038 | // %a EQ %b then %x EQ true |
| 1039 | // %a EQ %c then %x EQ false |
| 1040 | if (isEqual(I, SI->getTrueValue()) || |
| 1041 | isNotEqual(I, SI->getFalseValue())) |
| 1042 | addEqual(SI->getCondition(), ConstantBool::getTrue()); |
| 1043 | else if (isEqual(I, SI->getFalseValue()) || |
| 1044 | isNotEqual(I, SI->getTrueValue())) |
| 1045 | addEqual(SI->getCondition(), ConstantBool::getFalse()); |
| 1046 | |
| 1047 | // %x EQ true then %a EQ %b |
| 1048 | // %x EQ false then %a NE %b |
| 1049 | if (isEqual(SI->getCondition(), ConstantBool::getTrue())) |
| 1050 | addEqual(SI, SI->getTrueValue()); |
| 1051 | else if (isEqual(SI->getCondition(), ConstantBool::getFalse())) |
| 1052 | addEqual(SI, SI->getFalseValue()); |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 1053 | } |
| 1054 | } |
Nick Lewycky | 9d17c82 | 2006-10-25 23:48:24 +0000 | [diff] [blame] | 1055 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1056 | }; |
| 1057 | |
| 1058 | /// PredicateSimplifier - This class is a simplifier that replaces |
| 1059 | /// one equivalent variable with another. It also tracks what |
| 1060 | /// can't be equal and will solve setcc instructions when possible. |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1061 | /// @brief Root of the predicate simplifier optimization. |
| 1062 | class VISIBILITY_HIDDEN PredicateSimplifier : public FunctionPass { |
| 1063 | DominatorTree *DT; |
| 1064 | ETForest *Forest; |
| 1065 | bool modified; |
| 1066 | |
| 1067 | class State { |
| 1068 | public: |
| 1069 | BasicBlock *ToVisit; |
| 1070 | InequalityGraph *IG; |
| 1071 | |
| 1072 | State(BasicBlock *BB, InequalityGraph *IG) : ToVisit(BB), IG(IG) {} |
| 1073 | }; |
| 1074 | |
| 1075 | std::vector<State> WorkList; |
| 1076 | |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1077 | public: |
| 1078 | bool runOnFunction(Function &F); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1079 | |
| 1080 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 1081 | AU.addRequiredID(BreakCriticalEdgesID); |
| 1082 | AU.addRequired<DominatorTree>(); |
| 1083 | AU.addRequired<ETForest>(); |
| 1084 | AU.setPreservesCFG(); |
| 1085 | AU.addPreservedID(BreakCriticalEdgesID); |
| 1086 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1087 | |
| 1088 | private: |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1089 | /// Forwards - Adds new properties into PropertySet and uses them to |
| 1090 | /// simplify instructions. Because new properties sometimes apply to |
| 1091 | /// a transition from one BasicBlock to another, this will use the |
| 1092 | /// PredicateSimplifier::proceedToSuccessor(s) interface to enter the |
| 1093 | /// basic block with the new PropertySet. |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1094 | /// @brief Performs abstract execution of the program. |
| 1095 | class VISIBILITY_HIDDEN Forwards : public InstVisitor<Forwards> { |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1096 | friend class InstVisitor<Forwards>; |
| 1097 | PredicateSimplifier *PS; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1098 | |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1099 | public: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1100 | InequalityGraph &IG; |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1101 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1102 | Forwards(PredicateSimplifier *PS, InequalityGraph &IG) |
| 1103 | : PS(PS), IG(IG) {} |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1104 | |
| 1105 | void visitTerminatorInst(TerminatorInst &TI); |
| 1106 | void visitBranchInst(BranchInst &BI); |
| 1107 | void visitSwitchInst(SwitchInst &SI); |
| 1108 | |
Nick Lewycky | f345008 | 2006-10-22 19:53:27 +0000 | [diff] [blame] | 1109 | void visitAllocaInst(AllocaInst &AI); |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1110 | void visitLoadInst(LoadInst &LI); |
| 1111 | void visitStoreInst(StoreInst &SI); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1112 | |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1113 | void visitBinaryOperator(BinaryOperator &BO); |
| 1114 | }; |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1115 | |
| 1116 | // Used by terminator instructions to proceed from the current basic |
| 1117 | // block to the next. Verifies that "current" dominates "next", |
| 1118 | // then calls visitBasicBlock. |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1119 | void proceedToSuccessors(const InequalityGraph &IG, BasicBlock *BBCurrent) { |
| 1120 | DominatorTree::Node *Current = DT->getNode(BBCurrent); |
| 1121 | for (DominatorTree::Node::iterator I = Current->begin(), |
| 1122 | E = Current->end(); I != E; ++I) { |
| 1123 | //visitBasicBlock((*I)->getBlock(), IG); |
| 1124 | WorkList.push_back(State((*I)->getBlock(), new InequalityGraph(IG))); |
| 1125 | } |
| 1126 | } |
| 1127 | |
| 1128 | void proceedToSuccessor(InequalityGraph *NextIG, BasicBlock *Next) { |
| 1129 | //visitBasicBlock(Next, NextIG); |
| 1130 | WorkList.push_back(State(Next, NextIG)); |
| 1131 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1132 | |
| 1133 | // Visits each instruction in the basic block. |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1134 | void visitBasicBlock(BasicBlock *BB, InequalityGraph &IG) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1135 | DOUT << "Entering Basic Block: " << BB->getName() << "\n"; |
| 1136 | for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;) { |
| 1137 | visitInstruction(I++, IG); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1138 | } |
| 1139 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1140 | |
Nick Lewycky | 9a22d7b | 2006-09-10 02:27:07 +0000 | [diff] [blame] | 1141 | // Tries to simplify each Instruction and add new properties to |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1142 | // the PropertySet. |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1143 | void visitInstruction(Instruction *I, InequalityGraph &IG) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1144 | DOUT << "Considering instruction " << *I << "\n"; |
| 1145 | DEBUG(IG.debug(*cerr.stream())); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1146 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1147 | // Sometimes instructions are made dead due to earlier analysis. |
| 1148 | if (isInstructionTriviallyDead(I)) { |
| 1149 | I->eraseFromParent(); |
| 1150 | return; |
| 1151 | } |
| 1152 | |
| 1153 | // Try to replace the whole instruction. |
| 1154 | Value *V = IG.canonicalize(I); |
| 1155 | if (V != I) { |
| 1156 | modified = true; |
| 1157 | ++NumInstruction; |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1158 | DOUT << "Removing " << *I << ", replacing with " << *V << "\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1159 | IG.remove(I); |
| 1160 | I->replaceAllUsesWith(V); |
| 1161 | I->eraseFromParent(); |
| 1162 | return; |
| 1163 | } |
| 1164 | |
| 1165 | // Try to substitute operands. |
| 1166 | for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { |
| 1167 | Value *Oper = I->getOperand(i); |
| 1168 | Value *V = IG.canonicalize(Oper); |
| 1169 | if (V != Oper) { |
| 1170 | modified = true; |
| 1171 | ++NumVarsReplaced; |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1172 | DOUT << "Resolving " << *I; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1173 | I->setOperand(i, V); |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1174 | DOUT << " into " << *I; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1175 | } |
| 1176 | } |
| 1177 | |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1178 | //DOUT << "push (%" << I->getParent()->getName() << ")\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1179 | Forwards visit(this, IG); |
| 1180 | visit.visit(*I); |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1181 | //DOUT << "pop (%" << I->getParent()->getName() << ")\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1182 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1183 | }; |
| 1184 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1185 | bool PredicateSimplifier::runOnFunction(Function &F) { |
| 1186 | DT = &getAnalysis<DominatorTree>(); |
| 1187 | Forest = &getAnalysis<ETForest>(); |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 1188 | |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1189 | DOUT << "Entering Function: " << F.getName() << "\n"; |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 1190 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1191 | modified = false; |
| 1192 | WorkList.push_back(State(DT->getRoot(), new InequalityGraph())); |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 1193 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1194 | do { |
| 1195 | State S = WorkList.back(); |
| 1196 | WorkList.pop_back(); |
| 1197 | visitBasicBlock(S.ToVisit, *S.IG); |
| 1198 | delete S.IG; |
| 1199 | } while (!WorkList.empty()); |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 1200 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1201 | //DEBUG(F.viewCFG()); |
Nick Lewycky | cfff1c3 | 2006-09-20 17:04:01 +0000 | [diff] [blame] | 1202 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1203 | return modified; |
Nick Lewycky | 8e55993 | 2006-09-02 19:40:38 +0000 | [diff] [blame] | 1204 | } |
| 1205 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1206 | void PredicateSimplifier::Forwards::visitTerminatorInst(TerminatorInst &TI) { |
| 1207 | PS->proceedToSuccessors(IG, TI.getParent()); |
| 1208 | } |
| 1209 | |
| 1210 | void PredicateSimplifier::Forwards::visitBranchInst(BranchInst &BI) { |
| 1211 | BasicBlock *BB = BI.getParent(); |
| 1212 | |
| 1213 | if (BI.isUnconditional()) { |
| 1214 | PS->proceedToSuccessors(IG, BB); |
| 1215 | return; |
| 1216 | } |
| 1217 | |
| 1218 | Value *Condition = BI.getCondition(); |
| 1219 | BasicBlock *TrueDest = BI.getSuccessor(0), |
| 1220 | *FalseDest = BI.getSuccessor(1); |
| 1221 | |
| 1222 | if (isa<ConstantBool>(Condition) || TrueDest == FalseDest) { |
| 1223 | PS->proceedToSuccessors(IG, BB); |
| 1224 | return; |
| 1225 | } |
| 1226 | |
| 1227 | DominatorTree::Node *Node = PS->DT->getNode(BB); |
| 1228 | for (DominatorTree::Node::iterator I = Node->begin(), E = Node->end(); |
| 1229 | I != E; ++I) { |
| 1230 | BasicBlock *Dest = (*I)->getBlock(); |
| 1231 | InequalityGraph *DestProperties = new InequalityGraph(IG); |
| 1232 | VRPSolver Solver(*DestProperties, PS->Forest, Dest); |
| 1233 | |
| 1234 | if (Dest == TrueDest) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1235 | DOUT << "(" << BB->getName() << ") true set:\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1236 | if (!Solver.addEqual(ConstantBool::getTrue(), Condition)) continue; |
| 1237 | Solver.solve(); |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1238 | DEBUG(DestProperties->debug(*cerr.stream())); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1239 | } else if (Dest == FalseDest) { |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1240 | DOUT << "(" << BB->getName() << ") false set:\n"; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1241 | if (!Solver.addEqual(ConstantBool::getFalse(), Condition)) continue; |
| 1242 | Solver.solve(); |
Bill Wendling | 22e978a | 2006-12-07 20:04:42 +0000 | [diff] [blame^] | 1243 | DEBUG(DestProperties->debug(*cerr.stream())); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1244 | } |
| 1245 | |
| 1246 | PS->proceedToSuccessor(DestProperties, Dest); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1247 | } |
| 1248 | } |
| 1249 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1250 | void PredicateSimplifier::Forwards::visitSwitchInst(SwitchInst &SI) { |
| 1251 | Value *Condition = SI.getCondition(); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1252 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1253 | // Set the EQProperty in each of the cases BBs, and the NEProperties |
| 1254 | // in the default BB. |
| 1255 | // InequalityGraph DefaultProperties(IG); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1256 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1257 | DominatorTree::Node *Node = PS->DT->getNode(SI.getParent()); |
| 1258 | for (DominatorTree::Node::iterator I = Node->begin(), E = Node->end(); |
| 1259 | I != E; ++I) { |
| 1260 | BasicBlock *BB = (*I)->getBlock(); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1261 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1262 | InequalityGraph *BBProperties = new InequalityGraph(IG); |
| 1263 | VRPSolver Solver(*BBProperties, PS->Forest, BB); |
| 1264 | if (BB == SI.getDefaultDest()) { |
| 1265 | for (unsigned i = 1, e = SI.getNumCases(); i < e; ++i) |
| 1266 | if (SI.getSuccessor(i) != BB) |
| 1267 | if (!Solver.addNotEqual(Condition, SI.getCaseValue(i))) continue; |
| 1268 | Solver.solve(); |
| 1269 | } else if (ConstantInt *CI = SI.findCaseDest(BB)) { |
| 1270 | if (!Solver.addEqual(Condition, CI)) continue; |
| 1271 | Solver.solve(); |
| 1272 | } |
| 1273 | PS->proceedToSuccessor(BBProperties, BB); |
Nick Lewycky | 1d00f3e | 2006-10-03 15:19:11 +0000 | [diff] [blame] | 1274 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1275 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1276 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1277 | void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) { |
| 1278 | VRPSolver VRP(IG, PS->Forest, AI.getParent()); |
| 1279 | VRP.addNotEqual(Constant::getNullValue(AI.getType()), &AI); |
| 1280 | VRP.solve(); |
| 1281 | } |
Nick Lewycky | f345008 | 2006-10-22 19:53:27 +0000 | [diff] [blame] | 1282 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1283 | void PredicateSimplifier::Forwards::visitLoadInst(LoadInst &LI) { |
| 1284 | Value *Ptr = LI.getPointerOperand(); |
| 1285 | // avoid "load uint* null" -> null NE null. |
| 1286 | if (isa<Constant>(Ptr)) return; |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1287 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1288 | VRPSolver VRP(IG, PS->Forest, LI.getParent()); |
| 1289 | VRP.addNotEqual(Constant::getNullValue(Ptr->getType()), Ptr); |
| 1290 | VRP.solve(); |
| 1291 | } |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1292 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1293 | void PredicateSimplifier::Forwards::visitStoreInst(StoreInst &SI) { |
| 1294 | Value *Ptr = SI.getPointerOperand(); |
| 1295 | if (isa<Constant>(Ptr)) return; |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1296 | |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1297 | VRPSolver VRP(IG, PS->Forest, SI.getParent()); |
| 1298 | VRP.addNotEqual(Constant::getNullValue(Ptr->getType()), Ptr); |
| 1299 | VRP.solve(); |
| 1300 | } |
| 1301 | |
| 1302 | void PredicateSimplifier::Forwards::visitBinaryOperator(BinaryOperator &BO) { |
| 1303 | Instruction::BinaryOps ops = BO.getOpcode(); |
| 1304 | |
| 1305 | switch (ops) { |
Reid Spencer | 7eb55b3 | 2006-11-02 01:53:59 +0000 | [diff] [blame] | 1306 | case Instruction::URem: |
| 1307 | case Instruction::SRem: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1308 | case Instruction::FRem: |
Reid Spencer | 7e80b0b | 2006-10-26 06:15:43 +0000 | [diff] [blame] | 1309 | case Instruction::UDiv: |
| 1310 | case Instruction::SDiv: |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1311 | case Instruction::FDiv: { |
Nick Lewycky | 77e030b | 2006-10-12 02:02:44 +0000 | [diff] [blame] | 1312 | Value *Divisor = BO.getOperand(1); |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1313 | VRPSolver VRP(IG, PS->Forest, BO.getParent()); |
| 1314 | VRP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor); |
| 1315 | VRP.solve(); |
Nick Lewycky | 5f8f9af | 2006-08-30 02:46:48 +0000 | [diff] [blame] | 1316 | break; |
| 1317 | } |
| 1318 | default: |
| 1319 | break; |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1320 | } |
Nick Lewycky | 5f8f9af | 2006-08-30 02:46:48 +0000 | [diff] [blame] | 1321 | } |
Nick Lewycky | 09b7e4d | 2006-11-22 23:49:16 +0000 | [diff] [blame] | 1322 | |
| 1323 | |
| 1324 | RegisterPass<PredicateSimplifier> X("predsimplify", |
| 1325 | "Predicate Simplifier"); |
| 1326 | } |
| 1327 | |
| 1328 | FunctionPass *llvm::createPredicateSimplifierPass() { |
| 1329 | return new PredicateSimplifier(); |
Nick Lewycky | b2e8ae1 | 2006-08-28 22:44:55 +0000 | [diff] [blame] | 1330 | } |