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 
114