Stephen Hines | 6bcf27b | 2014-05-29 04:14:42 -0700 | [diff] [blame^] | 1 | //===- ThreadSafetyTIL.cpp -------------------------------------*- C++ --*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT in the llvm repository for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" |
| 11 | #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" |
| 12 | |
| 13 | namespace clang { |
| 14 | namespace threadSafety { |
| 15 | namespace til { |
| 16 | |
| 17 | |
| 18 | StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op) { |
| 19 | switch (Op) { |
| 20 | case UOP_Minus: return "-"; |
| 21 | case UOP_BitNot: return "~"; |
| 22 | case UOP_LogicNot: return "!"; |
| 23 | } |
| 24 | return ""; |
| 25 | } |
| 26 | |
| 27 | |
| 28 | StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op) { |
| 29 | switch (Op) { |
| 30 | case BOP_Mul: return "*"; |
| 31 | case BOP_Div: return "/"; |
| 32 | case BOP_Rem: return "%"; |
| 33 | case BOP_Add: return "+"; |
| 34 | case BOP_Sub: return "-"; |
| 35 | case BOP_Shl: return "<<"; |
| 36 | case BOP_Shr: return ">>"; |
| 37 | case BOP_BitAnd: return "&"; |
| 38 | case BOP_BitXor: return "^"; |
| 39 | case BOP_BitOr: return "|"; |
| 40 | case BOP_Eq: return "=="; |
| 41 | case BOP_Neq: return "!="; |
| 42 | case BOP_Lt: return "<"; |
| 43 | case BOP_Leq: return "<="; |
| 44 | case BOP_LogicAnd: return "&&"; |
| 45 | case BOP_LogicOr: return "||"; |
| 46 | } |
| 47 | return ""; |
| 48 | } |
| 49 | |
| 50 | |
| 51 | |
| 52 | // If E is a variable, then trace back through any aliases or redundant |
| 53 | // Phi nodes to find the canonical definition. |
| 54 | SExpr *getCanonicalVal(SExpr *E) { |
| 55 | while (auto *V = dyn_cast<Variable>(E)) { |
| 56 | SExpr *D; |
| 57 | do { |
| 58 | if (V->kind() != Variable::VK_Let) |
| 59 | return V; |
| 60 | D = V->definition(); |
| 61 | auto *V2 = dyn_cast<Variable>(D); |
| 62 | if (V2) |
| 63 | V = V2; |
| 64 | else |
| 65 | break; |
| 66 | } while (true); |
| 67 | |
| 68 | if (ThreadSafetyTIL::isTrivial(D)) |
| 69 | return D; |
| 70 | |
| 71 | if (Phi *Ph = dyn_cast<Phi>(D)) { |
| 72 | if (Ph->status() == Phi::PH_Incomplete) |
| 73 | simplifyIncompleteArg(V, Ph); |
| 74 | |
| 75 | if (Ph->status() == Phi::PH_SingleVal) { |
| 76 | E = Ph->values()[0]; |
| 77 | continue; |
| 78 | } |
| 79 | } |
| 80 | return V; |
| 81 | } |
| 82 | return E; |
| 83 | } |
| 84 | |
| 85 | |
| 86 | // Trace the arguments of an incomplete Phi node to see if they have the same |
| 87 | // canonical definition. If so, mark the Phi node as redundant. |
| 88 | // getCanonicalVal() will recursively call simplifyIncompletePhi(). |
| 89 | void simplifyIncompleteArg(Variable *V, til::Phi *Ph) { |
| 90 | assert(Ph && Ph->status() == Phi::PH_Incomplete); |
| 91 | |
| 92 | // eliminate infinite recursion -- assume that this node is not redundant. |
| 93 | Ph->setStatus(Phi::PH_MultiVal); |
| 94 | |
| 95 | SExpr *E0 = getCanonicalVal(Ph->values()[0]); |
| 96 | for (unsigned i=1, n=Ph->values().size(); i<n; ++i) { |
| 97 | SExpr *Ei = getCanonicalVal(Ph->values()[i]); |
| 98 | if (Ei == V) |
| 99 | continue; // Recursive reference to itself. Don't count. |
| 100 | if (Ei != E0) { |
| 101 | return; // Status is already set to MultiVal. |
| 102 | } |
| 103 | } |
| 104 | Ph->setStatus(Phi::PH_SingleVal); |
| 105 | // Eliminate Redundant Phi node. |
| 106 | V->setDefinition(Ph->values()[0]); |
| 107 | } |
| 108 | |
| 109 | |
| 110 | } // end namespace til |
| 111 | } // end namespace threadSafety |
| 112 | } // end namespace clang |
| 113 | |