blob: f4da8d46dc8aee58ae33db06ddb15ebd74b3703c [file] [log] [blame]
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001//===- 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
13namespace clang {
14namespace threadSafety {
15namespace til {
16
17
18StringRef 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
28StringRef 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.
54SExpr *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().
89void 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