ROSE 0.11.145.147
ConstrGraph.h
1#include <featureTests.h>
2#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
3
4#ifndef CONSTR_GRAPH_H
5#define CONSTR_GRAPH_H
6
7#include "genericDataflowCommon.h"
8
9#include <sstream>
10#include <iostream>
11#include <string>
12#include <functional>
13#include <queue>
14#include <map>
15#include <set>
16
17#include "VirtualCFGIterator.h"
18#include "cfgUtils.h"
19#include "CallGraphTraverse.h"
20#include "analysisCommon.h"
21#include "analysis.h"
22#include "dataflow.h"
23#include "latticeFull.h"
24#include "affineInequality.h"
25#include "divAnalysis.h"
26// GB : 2011-03-05 (Removing Sign Lattice Dependence)#include "sgnAnalysis.h"
27#include "liveDeadVarAnalysis.h"
28
29extern int CGDebugLevel;
30extern int CGmeetDebugLevel;
31extern int CGprofileLevel;
32extern int CGdebugTransClosure;
33
34// top - relations between each pair of variables are unknown or too complex to be representable as affine inequalities (minimal information)
35// intermediate - some concrete information is known about some variable pairs
36// bottom - impossible situation (maximal information) (bottom flag = true)
37
38// By default the constraint graph is = top. Since this implies a top inequality between every pair, we don't
39// actually maintain such affineInequality objects. Instead, if there is no affineInequality between a pair of
40// variables, this itself implies that this affineInequality=top.
41class ConstrGraph : public virtual InfiniteLattice, public dottable//, public virtual LogicalCond
42{
43public:
44 // Possible levels of this constraint graph, defined by their information content in ascending order.
45 enum levels {
46 // Uninitialized constraint graph. Uninitialized constraint graphs behave
47 // just like regular constraint graphs but they are not equal to any other graph
48 // until they are initialized. Any operation that modifies or reads the state
49 // of a constraint graph (not including comparisons or other operations that don't
50 // access individual variable mappings) causes it to become initialized (if it
51 // wasn't already). An uninitialized constraint graph is !=bottom.
52 // printing a graph's contents does not make it initialized.
53 uninitialized = 0,
54 // Constraint graph that has no constraints
55 bottom,
56 // This graph's constraints are defined as a conjunction or disjunction of inequalities.
57 // More details are provided in constrType field
58 constrKnown,
59 // The set of constraints in this graph are too complex to be described as a conjunction of inequalities or
60 // a negation of such a conjunction
61 top};
62protected:
63 levels level;
64
65public:
66 typedef enum {
67 unknown,
68 // This graph's constraints are represented as a conjunction of inequalities.
69 conj,
70 // Constraints are representes as the negation of a conjunction of inequalities.
71 // This is the same as a disjunction of the negations of the same inequalities.
72 negConj,
73 // This graph's constrants are mutually-inconsistent
74 inconsistent
75 } constrTypes;
76protected:
77 constrTypes constrType;
78
79 // The function and DataflowNode that this constraint graph corresponds to
80 // as well as the node's state
81 const Function& func;
82 //const DataflowNode& n;
83 const NodeState& state;
84
85 // Represents constrants (x<=y+c). vars2Value[x] maps to a set of constraint::<y, a, b, c>
86 //std::map<varID, std::map<varID, constraint> > vars2Value;
87 std::map<varID, std::map<varID, affineInequality> > vars2Value;
88
89 // The LiveDeadVarsAnalysis that identifies the live/dead state of all application variables.
90 // Needed to create a FiniteVarsExprsProductLattice.
92
93 // To allow the user to modify the graph in several spots before calling isSelfConsistent()
94 // we allow them to perform their modifications inside a transaction and call isSelfConsistent only
95 // at the end of the transaction
96 bool inTransaction;
97
98 // The divisibility lattices associated with the current CFG node
99 // divL is a map from annotations to product lattices. Each product lattice will only be used to
100 // reason about variables that have the same annotation. When a variable has multiple annotations
101 // only one matching product lattice will be used.
102 // The annotation ""->NULL matches all variables
103 std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*> divL;
104
105 // The sign lattices associated with the current CFG node
106 // sgnL is a map from annotations to product lattices. Each product lattice will only be used to
107 // reason about variables that have the same annotation. When a variable has multiple annotations
108 // only one matching product lattice will be used.
109 // The annotation ""->NULL matches all variables
110 // GB : 2011-03-05 (Removing Sign Lattice Dependence) std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*> sgnL;
111
112 // Set of live variables that this constraint graph applies to
113 std::set<varID> vars;
114
115 // set of variables for which we have divisibility information
116 // noDivVars std::set<varID> divVars;
117
118 // Flag indicating whether some of the constraints have changed since the last time
119 // this graph was checked for bottom-ness
120 bool constrChanged;
121 // Set of variables the for which we've added constraints since the last transitive closure
122 /* GB 2011-06-02 : newConstrVars->modifiedVars : set<varID> newConstrVars; */
123 // Set of variables the constraints on which have been modified since the last transitive closure
124 std::set<varID> modifiedVars;
125
126
127 /**** Constructors & Destructors ****/
128 public:
129 // DataflowNode Descriptor object that summarizes the key info about a DataflowNode
130 // in case this ConstrGraph must represent the state of multiple nodes
131 class NodeDesc {
132 public:
133 const DataflowNode& n;
134 const NodeState& state;
135 std::string annotName;
136 void* annotVal;
137 std::set<varID> varsToInclude; // Set of variables that must be included in the ConstrGraph that describes this node, even if they are not live
138 NodeDesc(const DataflowNode& n, const NodeState& state, std::string annotName, void* annotVal, const std::set<varID>& varsToInclude) :
139 n(n), state(state), annotName(annotName), annotVal(annotVal), varsToInclude(varsToInclude) {}
140 NodeDesc(const DataflowNode& n, const NodeState& state, std::string annotName, void* annotVal) :
141 n(n), state(state), annotName(annotName), annotVal(annotVal) {}
142 NodeDesc(const DataflowNode& n, const NodeState& state) :
143 n(n), state(state), annotName(""), annotVal(NULL) {}
144 bool operator==(const NodeDesc& that) const { return n==that.n && &state==&(that.state) && annotName==that.annotName && annotVal==that.annotVal && varsToInclude==that.varsToInclude; }
145 bool operator<(const NodeDesc& that) const {
146 return (n<that.n) ||
147 (n==that.n && &state< &(that.state)) ||
148 (n==that.n && &state==&(that.state) && annotName<that.annotName) ||
149 (n==that.n && &state==&(that.state) && annotName==that.annotName && annotVal<that.annotVal) ||
150 (n==that.n && &state==&(that.state) && annotName==that.annotName && annotVal==that.annotVal && varsToInclude<that.varsToInclude);
151 }
152 };
153
154protected:
155 ConstrGraph(const Function& func, const DataflowNode& n, const NodeState& state, bool initialized=false, std::string indent="");
156
157public:
158 ConstrGraph(const Function& func, const DataflowNode& n, const NodeState& state,
159 LiveDeadVarsAnalysis* ldva, FiniteVarsExprsProductLattice* divL, // GB : 2011-03-05 (Removing Sign Lattice Dependence) FiniteVarsExprsProductLattice* sgnL,
160 bool initialized=true, std::string indent="");
161 ConstrGraph(const Function& func, const DataflowNode& n, const NodeState& state,
163 const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& divL,
164 // GB : 2011-03-05 (Removing Sign Lattice Dependence)const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& sgnL,
165 bool initialized=true, std::string indent="");
166 ConstrGraph(const Function& func, const std::set<NodeDesc>& nodes, const NodeState& state,
168 const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& divL,
169 // GB : 2011-03-05 (Removing Sign Lattice Dependence)const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& sgnL,
170 bool initialized=true, std::string indent="");
171
172 //ConstrGraph(const varIDSet& scalars, const varIDSet& arrays, bool initialized=true);
173
174 //ConstrGraph(varIDSet& arrays, varIDSet& scalars, FiniteVarsExprsProductLattice* divL, bool initialized=true);
175
176 ConstrGraph(ConstrGraph &that, bool initialized=true, std::string indent="");
177
178 ConstrGraph(const ConstrGraph* that, bool initialized=true, std::string indent="");
179
180 // Creates a constraint graph that contains the given set of inequalities,
182 ConstrGraph(const std::set<varAffineInequality>& ineqs, const Function& func, const DataflowNode& n, const NodeState& state,
184 // GB : 2011-03-05 (Removing Sign Lattice Dependence)FiniteVarsExprsProductLattice* sgnL,
185 std::string indent="");
186 ConstrGraph(const std::set<varAffineInequality>& ineqs, const Function& func, const DataflowNode& n, const NodeState& state,
188 const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& divL,
189 // GB : 2011-03-05 (Removing Sign Lattice Dependence)const std::map<std::pair<std::string, void*>, FiniteVarsExprsProductLattice*>& sgnL,
190 std::string indent="");
191
192 protected:
193 // Initialization code that is common to multiple constructors.
194 // func - The function that the object corresponds to
195 // nodes - set of NodeDesc objects, each of which contains
196 // n - a Dataflow node this ConstrGraph corresponds to
197 // state - the NodeState of node n
198 // annotName/annotVal - the annotation that will be associated with all variables live at node n
199 // initialized - If false, starts this ConstrGraph as uninitialized. If false, starts it at bottom.
200 void initCG(const Function& func, const std::set<NodeDesc>& nodes, bool initialized, std::string indent="");
201
202 public:
203 ~ConstrGraph ();
204
205 // Initializes this Lattice to its default state, if it is not already initialized
206 void initialize(std::string indent="");
207 void initialize()
208 { initialize(""); }
209
210 // For a given variable returns the corresponding divisibility variable
211 // noDivVars static varID getDivVar(const varID& scalar);
212
213 // Returns true if the given variable is a divisibility variable and false otherwise
214 // noDivVars static bool isDivVar(const varID& scalar);
215
216 // Returns a divisibility product lattice that matches the given variable
217 FiniteVarsExprsProductLattice* getDivLattice(const varID& var, std::string indent="");
218
219 std::string DivLattices2Str(std::string indent="");
220
221 // Returns a sign product lattice that matches the given variable
222 // GB : 2011-03-05 (Removing Sign Lattice Dependence)
223 // FiniteVarsExprsProductLattice* getSgnLattice(const varID& var, std::string indent="");
224
225 // Adds the given variable to the variables list, returning true if this causes
226 // the constraint graph to change and false otherwise.
227 bool addVar(const varID& scalar, std::string indent="");
228
229 // Removes the given variable and its divisibility variables (if one exists) from the variables list
230 // and removes any constraints that involve them.
231 // Returning true if this causes the constraint graph to change and false otherwise.
232 bool removeVar(const varID& scalar, std::string indent="");
233
234 // Returns a reference to the constraint graph's set of variables
235 const varIDSet& getVars() const;
236
237 // Returns a modifiable reference to the constraint graph's set of variables
238 varIDSet& getVarsMod();
239
240 /***** Copying *****/
241
242 // Overwrites the state of this Lattice with that of that Lattice
243 void copy(Lattice* that);
244
245 // Returns a copy of this lattice
246 Lattice* copy() const;
247
248 // Copies the state of that to this constraint graph
249 // Returns true if this causes this constraint graph's state to change
250 bool copyFrom(ConstrGraph &that, std::string indent="");
251
252 // Copies the state of That into This constraint graph, but mapping constraints of varFrom to varTo, even
253 // if varFrom is not mapped by This and is only mapped by That. varTo must be mapped by This.
254 // Returns true if this causes this constraint graph's state to change.
255 bool copyFromReplace(ConstrGraph &that, varID varTo, varID varFrom, std::string indent="");
256
257 // Copies the given var and its associated constrants from that to this.
258 // Returns true if this causes this constraint graph's state to change; false otherwise.
259 bool copyVar(const ConstrGraph& that, const varID& var);
260
261protected:
262 // Determines whether constraints in cg are different from
263 // the constraints in this
264 bool diffConstraints(ConstrGraph &that, std::string indent="");
265
266public:
267 // Copies the constraints of cg into this constraint graph.
268 // Returns true if this causes this constraint graph's state to change.
269 bool copyConstraints(ConstrGraph &that, std::string indent="");
270
271 // Copies the constraints of cg associated with varFrom into this constraint graph,
272 // but mapping them instead to varTo.
273 // Returns true if this causes this constraint graph's state to change.
274 bool copyConstraintsReplace(ConstrGraph &that, varID varTo, varID varFrom, std::string indent="");
275
276 /**** Erasing ****/
277 // erases all constraints from this constraint graph
278 // noBottomCheck - flag indicating whether this function should do nothing if this isBottom() returns
279 // true (=false) or to not bother checking with isBottom (=true)
280 void eraseConstraints(bool noBottomCheck=false, std::string indent="");
281
282public:
283 // Erases all constraints that relate to variable eraseVar and its corresponding divisibility variable
284 // from this constraint graph
285 // Returns true if this causes the constraint graph to change and false otherwise
286 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
287 // or to not bother checking self-consistency and just return the last-known value (=true)
288 bool eraseVarConstr(const varID& eraseVar, bool noConsistencyCheck=false, std::string indent="");
289
290 // Erases all constraints that relate to variable eraseVar but not its divisibility variable from
291 // this constraint graph
292 // Returns true if this causes the constraint graph to change and false otherwise
293 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
294 // or to not bother checking self-consistency and just return the last-known value (=true)
295 bool eraseVarConstrNoDiv(const varID& eraseVar, bool noConsistencyCheck=false, std::string indent="");
296
297 // Erases all constraints between eraseVar and scalars in this constraint graph but leave the constraints
298 // that relate to its divisibility variable alone
299 // Returns true if this causes the constraint graph to change and false otherwise
300 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
301 // or to not bother checking self-consistency and just return the last-known value (=true)
302 bool eraseVarConstrNoDivVars(const varID& eraseVar, bool noConsistencyCheck=false, std::string indent="");
303
304 // Removes any constraints between the given pair of variables
305 // Returns true if this causes the constraint graph to change and false otherwise
306 //bool disconnectVars(const varID& x, const varID& y);
307
308 // Replaces all instances of origVar with newVar. Both are assumed to be scalars.
309 // Returns true if this causes the constraint graph to change and false otherwise
310 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
311 // or to not bother checking self-consistency and just return the last-known value (=true)
312 bool replaceVar(const varID& origVar, const varID& newVar, bool noConsistencyCheck=false, std::string indent="");
313
314 protected:
315 // Used by copyAnnotVars() and mergeAnnotVars() to identify variables that are interesting
316 // from their perspective.
317 bool annotInterestingVar(const varID& var, const std::set<std::pair<std::string, void*> >& noCopyAnnots, const std::set<varID>& noCopyVars,
318 const std::string& annotName, void* annotVal, std::string indent="");
319
320 public:
321 // Copies the constrains on all the variables that have the given annotation (srcAnnotName -> srcAnnotVal).
322 // For each such variable we create a copy variable that is identical except that the
323 // (srcAnnotName -> srcAnnotVal) annotation is replaced with the (tgtAnnotName -> tgtAnnotVal) annotation.
324 // If two variables match the (srcAnnotName -> srcAnnotVal) annotation and the constraint graph has a relation
325 // between them, their copies will have the same relation between each other but will have no relation to the
326 // original variables. If two variables have a relation and only one is copied, then the copy maintains the
327 // original relation to the non-copied variable.
328 // A variable matches the given (srcAnnotName -> srcAnnotVal) annotation if this is one of the variable's annotations
329 // or if srcAnnotName=="" and the variable has no annotations.
330 // Avoids copying variables with annotations in the noCopyAnnots set and variables in the noCopyVars set.
331 // Returns true if this causes the constraint graph to change and false otherwise.
332 bool copyAnnotVars(std::string srcAnnotName, void* srcAnnotVal,
333 std::string tgtAnnotName, void* tgtAnnotVal,
334 const std::set<std::pair<std::string, void*> >& noCopyAnnots,
335 const std::set<varID>& noCopyVars, std::string indent="");
336
337 // Merges the state of the variables in the constraint graph with the [finalAnnotName -> finalAnnotVal] annotation
338 // with the state of the variables with the [remAnnotName -> remAnnotVal]. Each constraint that involves a variable
339 // with the former annotation and the same variable with the latter annotation is replaced with the union of the
340 // two constraints and will only involve the variable with the [finalAnnotName -> finalAnnotVal] (latter) annotation.
341 // All variables with the [remAnnotName -> remAnnotVal] annotation are removed from the constraint graph.
342 // A variable matches the given (srcAnnotName -> srcAnnotVal) annotation if this is one of the variable's annotations
343 // or if srcAnnotName=="" and the variable has no annotations.
344 // Avoids merging variables with annotations in the noCopyAnnots set and variables in the noCopyVars set.
345 // Returns true if this causes the constraint graph to change and false otherwise.
346 // It is assumed that variables that match [finalAnnotName -> finalAnnotVal] differ from variables that match
347 // [remAnnotName -> remAnnotVal] in only that annotation.
348 bool mergeAnnotVars(const std::string& finalAnnotName, void* finalAnnotVal,
349 const std::string& remAnnotName, void* remAnnotVal,
350 const std::set<std::pair<std::string, void*> >& noCopyAnnots,
351 const std::set<varID>& noCopyVars, std::string indent="");
352
353
354 protected:
355 // Union the current inequality for y in the given subMap of vars2Value with the given affine inequality
356 // Returns true if this causes a change in the subMap, false otherwise.
357 bool unionXYsubMap(std::map<varID, affineInequality>& subMap, const varID& y, const affineInequality& ineq, std::string indent="");
358
359 // Merges the given sub-map of var2Vals, just like mergeAnnotVars. Specifically, for every variable in the subMap
360 // that has a [remAnnotName -> remAnnotVal] annotation,
361 // If there exists a corresponding variable that has the [finalAnnotName -> finalAnnotVal] annotation,
362 // their respective inequalities are unioned. This union is left with the latter variable and the former
363 // variable's entry in subMap is removed
364 // If one does not exist, we simply replace the variable's record with an identical one that now belongs
365 // to its counterpart with the [finalAnnotName -> finalAnnotVal] annotation.
366 // Other entries are left alone.
367 // Returns true if this causes the subMap to change, false otherwise.
368 bool mergeAnnotVarsSubMap(std::map<varID, affineInequality>& subMap,
369 std::string finalAnnotName, void* finalAnnotVal,
370 std::string remAnnotName, void* remAnnotVal,
371 const std::set<std::pair<std::string, void*> >& noCopyAnnots,
372 const std::set<varID>& noCopyVars, std::string indent="");
373
374 // Support routine for mergeAnnotVars(). Filters out any rem variables in the given set, replacing
375 // them with their corresponding final versions if those final versions are not already in the set
376 // Returns true if this causes the set to change, false otherwise.
377 bool mergeAnnotVarsSet(std::set<varID> varsSet,
378 std::string finalAnnotName, void* finalAnnotVal,
379 std::string remAnnotName, void* remAnnotVal,
380 const std::set<std::pair<std::string, void*> >& noCopyAnnots,
381 const std::set<varID>& noCopyVars, std::string indent="");
382
383 public:
384
385 // Returns true if the given variable has an annotation in the given set and false otherwise.
386 // The variable matches an annotation if its name and value directly match or if the variable
387 // has no annotations and the annotation's name is "".
388 static bool varHasAnnot(const varID& var, const std::set<std::pair<std::string, void*> >& annots, std::string indent="");
389
390 // Returns true if the given variable has an annotation in the given set and false otherwise.
391 // The variable matches an annotation if its name and value directly match or if the variable
392 // has no annotations and the annotName=="".
393 static bool varHasAnnot(const varID& var, std::string annotName, void* annotVal, std::string indent="");
394
395 // Called by analyses to create a copy of this lattice. However, if this lattice maintains any
396 // information on a per-variable basis, these per-variable mappings must be converted from
397 // the current set of variables to another set. This may be needed during function calls,
398 // when dataflow information from the caller/callee needs to be transferred to the callee/calleer.
399 // We do not force child classes to define their own versions of this function since not all
400 // Lattices have per-variable information.
401 // varNameMap - maps all variable names that have changed, in each mapping pair, pair->first is the
402 // old variable and pair->second is the new variable
403 // func - the function that the copy Lattice will now be associated with
404 void remapVars(const std::map<varID, varID>&, const Function &) {
405 }
406
407 // Called by analyses to copy over from the that Lattice dataflow information into this Lattice.
408 // that contains data for a set of variables and incorporateVars must overwrite the state of just
409 // those variables, while leaving its state for other variables alone.
410 // We do not force child classes to define their own versions of this function since not all
411 // Lattices have per-variable information.
412 void incorporateVars(Lattice*) {
413 }
414
415 // Returns a Lattice that describes the information known within this lattice
416 // about the given expression. By default this could be the entire lattice or any portion of it.
417 // For example, a lattice that maintains lattices for different known variables and expression will
418 // return a lattice for the given expression. Similarly, a lattice that keeps track of constraints
419 // on values of variables and expressions will return the portion of the lattice that relates to
420 // the given expression.
421 // It it legal for this function to return NULL if no information is available.
422 // The function's caller is responsible for deallocating the returned object
423 Lattice* project(SgExpression*) {
424 return copy();
425 }
426
427 // The inverse of project(). The call is provided with an expression and a Lattice that describes
428 // the dataflow state that relates to expression. This Lattice must be of the same type as the lattice
429 // returned by project(). unProject() must incorporate this dataflow state into the overall state it holds.
430 // Call must make an internal copy of the passed-in lattice and the caller is responsible for deallocating it.
431 // Returns true if this causes this to change and false otherwise.
432 bool unProject(SgExpression* /*expr*/, Lattice* exprState) {
433 return meetUpdate(exprState, " ");
434 }
435
436 // Returns a constraint graph that only includes the constrains in this constraint graph that involve the
437 // variables in focusVars and their respective divisibility variables, if any.
438 // It is assumed that focusVars only contains scalars and not array ranges.
439 ConstrGraph* getProjection(const varIDSet& focusVars, std::string indent="");
440
441 // Creates a new constraint graph that is the disjoint union of the two given constraint graphs.
442 // The variables in cg1 and cg2 that are not in the noAnnot set, are annotated with cg1Annot and cg2Annot, respectively,
443 // under the name annotName.
444 // cg1 and cg2 are assumed to have identical constraints between variables in the noAnnotset.
445 static ConstrGraph* joinCG(ConstrGraph* cg1, void* cg1Annot, ConstrGraph* cg2, void* cg2Annot,
446 std::string annotName, const varIDSet& noAnnot, std::string indent="");
447
448 protected:
449 // Copies the per-variable contents of srcCG to tgtCG, while ensuring that in tgtCG all variables that are not
450 // in noAnnot are annotated with the annotName->annot label. For variables in noAnnot, the function ensures
451 // that tgtCG does not have inconsistent mappings between such variables.
452 static void joinCG_copyState(ConstrGraph* tgtCG, ConstrGraph* srcCG, void* annot,
453 std::string annotName, const varIDSet& noAnnot, std::string indent="");
454
455 public:
456 // Replaces all references to variables with the given annotName->annot annotation to
457 // references to variables without the annotation
458 // Returns true if this causes the constraint graph to change and false otherwise
459 bool removeVarAnnot(std::string annotName, void* annot, std::string indent="");
460
461 // Replaces all references to variables with the given annotName->annot annotation to
462 // references to variables without the annotation
463 // Returns true if this causes the constraint graph to change and false otherwise
464 bool replaceVarAnnot(std::string oldAnnotName, void* oldAnnot,
465 std::string newAnnotName, void* newAnnot, std::string indent="");
466
467 // For all variables that have a string (tgtAnnotName -> tgtAnnotVal) annotation
468 // (or if tgtAnnotName=="" and the variable has no annotation), add the annotation
469 // (newAnnotName -> newAnnotVal).
470 // Returns true if this causes the constraint graph to change and false otherwise
471 bool addVarAnnot(std::string tgtAnnotName, void* tgtAnnotVal, std::string newAnnotName, void* newAnnotVal, std::string indent="");
472
473 // adds a new range into this constraint graph
474 //void addRange(varID rangeVar);
475
476public:
477 /**** Transfer Function-Related Updates ****/
478 // Negates the constraint graph.
479 // Returns true if this causes the constraint graph to change and false otherwise
480 bool negate(std::string indent="");
481
482 // Updates the constraint graph with the information that x*a = y*b+c
483 // Returns true if this causes the constraint graph to change and false otherwise
484 bool assign(const varAffineInequality& cond, std::string indent="");
485 bool assign(varID x, varID y, const affineInequality& ineq, std::string indent="");
486 bool assign(varID x, varID y, int a, int b, int c, std::string indent="");
487
488 // Updates the constraint graph to record that there are no constraints in the given variable.
489 // Returns true if this causes the constraint graph to change and false otherwise
490 bool assignBot(varID var, std::string indent="");
491
492 // Updates the constraint graph to record that the constraints between the given variable and
493 // other variables are Top.
494 // Returns true if this causes the constraint graph to change and false otherwise
495 bool assignTop(varID var, std::string indent="");
496
497/* // Undoes the i = j + c assignment for backwards analysis
498 void undoAssignment( quad i, quad j, quad c );*/
499
500/* // kills all links from variable x to every other variable
501 void killVariable( quad x );
502*/
503
504 // Add the condition (x*a <= y*b + c) to this constraint graph. The addition is done via a conjunction operator,
505 // meaning that the resulting graph will be left with either (x*a <= y*b + c) or the original condition, whichever is stronger.
506 // returns true if this causes the constraint graph to change and false otherwise
507 bool assertCond(const varAffineInequality& cond, std::string indent="");
508
509 // add the condition (x*a <= y*b + c) to this constraint graph
510 // returns true if this causes the constraint graph to change and false otherwise
511 bool assertCond(const varID& x, const varID& y, const affineInequality& ineq, std::string indent="");
512
513 // add the condition (x*a <= y*b + c) to this constraint graph
514 // returns true if this causes the constraint graph to change and false otherwise
515 bool assertCond(const varID& x, const varID& y, int a, int b, int c, std::string indent="");
516
517 // add the condition (x*a = y*b + c) to this constraint graph
518 // returns true if this causes the constraint graph to change and false otherwise
519 bool assertEq(const varAffineInequality& cond, std::string indent="");
520 bool assertEq(varID x, varID y, const affineInequality& ineq, std::string indent="");
521 bool assertEq(const varID& x, const varID& y, int a=1, int b=1, int c=0, std::string indent="");
522
523 /**** Dataflow Functions ****/
524
525 // returns the sign of the given variable
526 affineInequality::signs getVarSign(const varID& var, std::string indent="");
527
528 // returns true of the given variable is =0 and false otherwise
529 bool isEqZero(const varID& var, std::string indent="");
530
531 // Returns true if v1*a = v2*b + c and false otherwise
532 bool eqVars(const varID& v1, const varID& v2, int a=1, int b=1, int c=0, std::string indent="");
533 bool eqVars(const varID& v1, const varID& v2, std::string indent="")
534 { return eqVars(v1, v2, 1, 1, 0, indent); }
535
536 // If v1*a = v2*b + c, sets a, b and c appropriately and returns true.
537 // Otherwise, returns false.
538 bool isEqVars(const varID& v1, const varID& v2, int& a, int& b, int& c, std::string indent="");
539
540 // Returns a list of variables that are equal to var in this constraint graph as a list of pairs
541 // <x, ineq>, where var*ineq.getA() = x*ineq.getB() + ineq.getC()
542 std::map<varID, affineInequality> getEqVars(varID var, std::string indent="");
543
544 // Returns true if v1*a <= v2*b + c and false otherwise
545 bool lteVars(const varID& v1, const varID& v2, int a=1, int b=1, int c=0, std::string indent="");
546
547 // Returns true if v1*a < v2*b + c and false otherwise
548 bool ltVars(const varID& v1, const varID& v2, int a=1, int b=1, int c=0, std::string indent="");
549
550 // Class used to iterate over all the constraints x*a <= y*b + c for a given variable x
552 {
553 varID x;
554 const ConstrGraph* parent;
555 std::map<varID, std::map<varID, affineInequality> >::const_iterator curX;
556 std::map<varID, affineInequality>::const_iterator curY;
557
558 public:
559 leIterator(const ConstrGraph* parent,
560 const std::map<varID, std::map<varID, affineInequality> >::iterator& curX);
561
562 leIterator(const ConstrGraph* parent,
563 const varID& x);
564
565 bool isDone() const;
566
567 varAffineInequality operator*() const ;
568
569 void operator ++ ();
570 void operator ++ (int);
571
572 bool operator==(const leIterator& otherIt) const;
573 bool operator!=(const leIterator& otherIt) const;
574 };
575 // Beginning and end points of the iteration over all constraints x*a <= y*b + c for a
576 // given variable x.
577 leIterator leBegin(const varID& y);
578 leIterator leEnd();
579
580 // Class used to iterate over all the constraints x*a <= y*b + c for a given variable y
582 {
583 bool isEnd; // true if this is the end iterator
584 std::map<varID, std::map<varID, affineInequality> >::const_iterator curX;
585 std::map<varID, affineInequality>::const_iterator curY;
586 const ConstrGraph* parent;
587 const varID y;
588
589 public:
590 geIterator();
591
592 geIterator(const ConstrGraph* parent, const varID& y);
593
594 geIterator(const ConstrGraph* parent, const varID& y,
595 const std::map<varID, std::map<varID, affineInequality> >::iterator& curX,
596 const std::map<varID, affineInequality>::iterator& curY);
597
598 // Advances curX and curY by one step. Returns false if curX/curY is already at the
599 // end of parent.vars2Value and true otherwise (i.e. successful step).
600 bool step();
601
602 // Move curX/curY to the next x/y pair with a matching y (may leave curX/curY already satisfy this).
603 // Returns true if there are no more such pairs.
604 bool advance();
605
606 bool isDone() const;
607
608 const varID& getX() const;
609
610 varAffineInequality operator*() const ;
611
612 void operator ++ ();
613 void operator ++ (int);
614
615 bool operator==(const geIterator& otherIt) const;
616 bool operator!=(const geIterator& otherIt) const;
617 };
618 // Beginning and End points of the iteration over all constraints x*a <= y*b + c for a
619 // given variable y.
620 geIterator geBegin(const varID& y);
621 geIterator geEnd();
622
623 // widens this from that and saves the result in this
624 // returns true if this causes this to change and false otherwise
625 bool widenUpdate(InfiniteLattice* that, std::string indent="");
626 bool widenUpdate(InfiniteLattice* that) { return widenUpdate(that, ""); }
627
628 // Widens this from that and saves the result in this, while ensuring that if a given constraint
629 // doesn't exist in that, its counterpart in this is not modified
630 // returns true if this causes this to change and false otherwise
631 bool widenUpdateLimitToThat(InfiniteLattice* that, std::string indent="");
632
633 // Common code for widenUpdate() and widenUpdateLimitToThat()
634 bool widenUpdate_ex(InfiniteLattice* that_arg, bool limitToThat, std::string indent="");
635
636 // computes the meet of this and that and saves the result in this
637 // returns true if this causes this to change and false otherwise
638 // The meet is the intersection of constraints: the set of constraints
639 // that is common to both constraint graphs. Thus, the result is the loosest
640 // set of constraints that satisfies both sets and therefore also the information union.
641 bool meetUpdate(Lattice* that, std::string indent="");
642 bool meetUpdate(Lattice* that) { return meetUpdate(that, ""); }
643
644 // Meet this and that and saves the result in this, while ensuring that if a given constraint
645 // doesn't exist in that, its counterpart in this is not modified
646 // returns true if this causes this to change and false otherwise
647 bool meetUpdateLimitToThat(InfiniteLattice* that, std::string indent="");
648
649 // Common code for meetUpdate() and meetUpdateLimitToThat()
650 bool meetUpdate_ex(Lattice* that_arg, bool limitToThat, std::string indent="");
651
652 // <from LogicalCond>
653 bool orUpd(LogicalCond& that, std::string indent="");
654 bool orUpd(LogicalCond& that)
655 { return orUpd(that, ""); }
656
657 // <from LogicalCond>
658 bool andUpd(LogicalCond& that, std::string indent="");
659 bool andUpd(LogicalCond& that)
660 { return andUpd(that, ""); }
661
662 bool andUpd(ConstrGraph* that, std::string indent="");
663 bool andUpd(ConstrGraph* that)
664 { return andUpd(that, ""); }
665
666 // Unified function for Or(meet), And and Widening
667 // If meet == true, this function computes the meet and if =false, computes the widening.
668 // If OR == true, the function computes the OR of each pair of inequalities and otherwise, computes the AND.
669 // if limitToThat == true, if a given constraint does not exist in that, this has no effect on the meet/widening
670 bool OrAndWidenUpdate(ConstrGraph* that, bool meet, bool OR, bool limitToThat, std::string indent="");
671
672
673 // Portion of OrAndWidenUpdate that deals with x variables for which there exist x->y mapping
674 // in This but not in That. Increments itThisX and updates modified and modifiedVars in case this
675 // function modifies the constraint graph.
676 void OrAndWidenUpdate_XinThisNotThat(
677 bool OR, bool limitToThat,
678 std::map<varID, std::map<varID, affineInequality> >::iterator& itThisX, bool& modified,
679 std::string indent="");
680
681 // Portion of OrAndWidenUpdate that deals with x variables for which there exist x->y mapping
682 // in That but not in This. Increments itThisX and updates modified and modifiedVars in case this
683 // function modifies the constraint graph.
684 // additionsToThis - Records the new additions to vars2Value that need to be made after we are done iterating
685 // over it. It guaranteed that the keys mapped by the first level of additionsToThis are not mapped
686 // at the first level by vals2Value.
687 void OrAndWidenUpdate_XinThatNotThis(
688 bool OR, bool limitToThat,
689 ConstrGraph* that,
690 std::map<varID, std::map<varID, affineInequality> >::iterator& itThatX,
691 std::map<varID, std::map<varID, affineInequality> >& additionsToThis,
692 bool& modified, std::string indent="");
693
694 // Portion of OrAndWidenUpdate that deals with x->y pairs for which there exist x->y mapping
695 // in This but not in That. Increments itThisX and updates modified and modifiedVars in case this
696 // function modifies the constraint graph.
697 void OrAndWidenUpdate_YinThisNotThat(
698 bool OR, bool limitToThat,
699 std::map<varID, std::map<varID, affineInequality> >::iterator& itThisX,
700 std::map<varID, affineInequality>::iterator& itThisY,
701 bool& modified, std::string indent="");
702
703 // Portion of OrAndWidenUpdate that deals with x->y pairs for which there exist x->y mapping
704 // in That but not in This. Increments itThisX and updates modified and modifiedVars in case this
705 // function modifies the constraint graph.
706 // additionsToThis - Records the new additions to vars2Value[itThisX->first] that need to be made after
707 // we are done iterating over it. It guaranteed that the keys mapped by additionsToThis are not mapped
708 // at the first level by vals2Value[itThisX->first].
709 void OrAndWidenUpdate_YinThatNotThis(
710 bool OR, bool limitToThat,
711 std::map<varID, std::map<varID, affineInequality> >::iterator& itThatX,
712 std::map<varID, affineInequality>::iterator& itThatY,
713 std::map<varID, affineInequality>& additionsToThis,
714 bool& modified, std::string indent="");
715
716 // Computes the transitive closure of the given constraint graph, and updates the graph to be that transitive closure.
717 // Returns true if this causes the graph to change and false otherwise.
718 bool transitiveClosure(std::string indent="");
719 protected:
720 bool transitiveClosureDiv(std::string indent="");
721 void transitiveClosureY(const varID& x, const varID& y, bool& modified, int& numSteps, int& numInfers, bool& iterModified, std::string indent="");
722 void transitiveClosureZ(const varID& x, const varID& y, const varID& z, bool& modified, int& numSteps, int& numInfers, bool& iterModified, std::string indent="");
723
724 public:
725 // Computes the transitive closure of the given constraint graph,
726 // focusing on the constraints of scalars that have divisibility variables
727 // we only bother propagating constraints to each such variable through its divisibility variable
728 // Returns true if this causes the graph to change and false otherwise.
729 // noDivVars bool divVarsClosure(std::string indent="");
730
731 // The portion of divVarsClosure that is called for every y variable. Thus, given x and x' (x's divisibility variable)
732 // divVarsClosure_perY() is called for every scalar or array y to infer the x->y connection thru x->x'->y and
733 // infer the y->x connection thru x->x'->x
734 // Returns true if this causes the graph to change and false otherwise.
735 // noDivVars bool divVarsClosure_perY(const varID& x, const varID& divX, const varID& y,
736 // noDivVars affineInequality* constrXDivX, affineInequality* constrDivXX/*,
737 // noDivVars affineInequality::signs xSign, affineInequality::signs ySign*/,
738 // noDivVars std::string indent="");
739
740 // Computes the transitive closure of this constraint graph while modifying
741 // only the constraints that involve the given variable
742 // Returns true if this causes the graph to change and false otherwise.
743 bool localTransClosure(const varID& tgtVar, std::string indent="");
744
745protected:
746 // Searches this constraint graph for negative cycles, which indicates that the constraints represented
747 // by the graph are not self-consistent (the code region where the graph holds is unreachable). Modifies
748 // the level of this graph as needed.
749 // Returns true if this call caused a modification in the graph and false otherwise.
750 bool checkSelfConsistency(std::string indent="");
751
752public:
753
754 // Creates a divisibility variable for the given variable and adds it to the constraint graph
755 // If var = r (mod d), then the relationship between x and x' (the divisibility variable)
756 // will be x = x'*d + r
757 // returns true if this causes the constraint graph to be modified (it may not if this
758 // information is already in the graph) and false otherwise
759 // noDivVars bool addDivVar(varID var/*, int div, int rem*/, bool killDivVar=false, std::string indent="");
760
761 // Disconnect this variable from all other variables except its divisibility variable. This is done
762 // in order to compute the original variable's relationships while taking its divisibility information
763 // into account.
764 // Returns true if this causes the constraint graph to be modified and false otherwise
765 // noDivVars bool disconnectDivOrigVar(varID var/*, int div, int rem*/, std::string indent="");
766
767 // Finds the variable within this constraint graph that corresponds to the given divisibility variable.
768 // If such a variable exists, returns the pair <variable, true>.
769 // Otherwise, returns <???, false>.
770 // noDivVars std::pair<varID, bool> divVar2Var(const varID& divVar, std::string indent="");
771
772 // Adds a new divisibility lattice, with the associated anotation
773 // Returns true if this causes the constraint graph to be modified and false otherwise
774 bool addDivL(FiniteVarsExprsProductLattice* divLattice, std::string annotName, void* annot, std::string indent="");
775
776 // Adds a new sign lattice, with the associated anotation
777 // Returns true if this causes the constraint graph to be modified and false otherwise
778 // GB : 2011-03-05 (Removing Sign Lattice Dependence)
779 // bool addSgnL(FiniteVarsExprsProductLattice* sgnLattice, std::string annotName, void* annot, std::string indent="");
780
781 /**** State Accessor Functions *****/
782 // Returns true if this constraint graph includes constraints for the given variable
783 // and false otherwise
784 bool containsVar(const varID& var, std::string indent="");
785
786 // returns the x->y constraint in this constraint graph
787 affineInequality* getVal(varID x, varID y, std::string indent="");
788
789 // set the x->y connection in this constraint graph to c
790 // return true if this results this ConstrGraph being changed, false otherwise
791 // xSign, ySign: the default signs for x and y. If they're set to unknown, setVal computes them on its own using getVarSign.
792 // otherwise, it uses the given signs
793 // GB : 2011-03-05 (Removing Sign Lattice Dependence)
794 /*bool setVal(varID x, varID y, int a, int b, int c,
795 affineInequality::signs xSign=affineInequality::unknownSgn, affineInequality::signs ySign=affineInequality::unknownSgn,
796 std::string indent="");*/
797 bool setVal(varID x, varID y, int a, int b, int c,
798 std::string indent="");
799 /*{ return setVal(x, y, a, b, c,
800 // GB : 2011-03-05 (Removing Sign Lattice Dependence)affineInequality::unknownSgn, affineInequality::unknownSgn,
801 indent); }*/
802
803 bool setVal(varID x, varID y, const affineInequality& ineq, std::string indent="");
804
805 // Sets the state of this constraint graph to Uninitialized, without modifying its contents. Thus,
806 // the graph will register as uninitalized but when it is next used, its state will already be set up.
807 // Returns true if this causes the constraint graph to be modified and false otherwise.
808 bool setToUninitialized_KeepState(std::string indent="");
809
810 // Sets the state of this constraint graph to Bottom
811 // Returns true if this causes the constraint graph to be modified and false otherwise.
812 bool setToBottom(std::string indent="");
813
814 // Sets the state of this constraint graph to constrKnown, with the given constraintType
815 // eraseCurConstr - if true, erases the current set of constraints and if false, leaves them alone
816 // Returns true if this causes the constraint graph to be modified and false otherwise.
817 bool setToConstrKnown(constrTypes ct, bool eraseCurConstr=true, std::string indent="");
818
819 // Sets the state of this constraint graph to Inconsistent
820 // noConsistencyCheck - flag indicating whether this function should do nothing if this noConsistencyCheck() returns
821 // true (=false) or to not bother checking with isBottom (=true)
822 // Returns true if this causes the constraint graph to be modified and false otherwise.
823 bool setToInconsistent(std::string indent="");
824
825 // Sets the state of this constraint graph to top
826 // If onlyIfNotInit=true, this is only done if the graph is currently uninitialized
827 // Returns true if this causes the constraint graph to be modified and false otherwise.
828 bool setToTop(bool onlyIfNotInit=false, std::string indent="");
829
830
831 // Returns the level and constraint type of this constraint graph
832 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
833 // or to not bother checking self-consistency and just return the last-known value (=true)
834 std::pair<levels, constrTypes> getLevel(bool noConsistencyCheck=false, std::string indent="");
835
836 // Returns true if this graph is self-consistent and false otherwise
837 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
838 // or to not bother checking self-consistency and just return the last-known value (=true)
839 bool isSelfConsistent(bool noConsistencyCheck=false, std::string indent="");
840
841 // Returns true if this graph has valid constraints and is self-consistent
842 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
843 // or to not bother checking self-consistency and just return the last-known value (=true)
844 bool hasConsistentConstraints(bool noConsistencyCheck=false, std::string indent="");
845
846 // Returns true if this constraint graph is maximal in that it can never reach a higher lattice state: it is
847 // either top or inconsistent). Returns false if it not maximal.
848 // noConsistencyCheck - flag indicating whether this function should explicitly check the self-consisteny of this graph (=false)
849 // or to not bother checking self-consistency and just return the last-known value (=true)
850 bool isMaximalState(bool noConsistencyCheck=false, std::string indent="");
851
852 /**** String Output *****/
853
854 // Returns the string representation of the constraints held by this constraint graph,
855 // with a line for each pair of variables for which the constraint is < bottom. It also prints
856 // the names of all the arrays that have empty ranges in this constraint graph
857 // There is no \n on the last line of output, even if it is a multi-line string
858 std::string str(std::string indent="");
859 void varSetStatusToStream(const std::set<varID>& vars, std::ostringstream& outs, bool &needEndl, std::string indent="");
860
861//protected:
862 // Returns the string representation of the constraints held by this constraint graph,
863 // with a line for each pair of variables for which the constraint is < bottom. It also prints
864 // the names of all the arrays that have empty ranges in this constraint graph
865 // There is no \n on the last line of output, even if it is a multi-line string
866 // If useIsBottom=true, isBottom() is used to determine whether the graph is =bottom.
867 // Otherwise, the bottom variable is checked.
868 // If useIsBottom=true, isBottom() is used to determine whether the graph is =bottom.
869 // Otherwise, the bottom variable is checked.
870 std::string str(std::string indent, bool useIsBottom);
871
872 // Returns a string that containts the representation of this constraint graph as a graph in the DOT language
873 // that has the given name
874 std::string toDOT(std::string graphName);
875
876 // Returns a string that containts the representation of this constraint graph as a graph in the DOT language
877 // that has the given name, focusing the graph on just the variables inside focusVars.
878 std::string toDOT(std::string graphName, std::set<varID>& focusVars);
879
880public:
881 /**** Comparison Functions ****/
882 bool operator != (ConstrGraph &that);
883 bool operator == (ConstrGraph &that);
884 bool operator == (Lattice* that);
885 bool operator <<= (ConstrGraph &that);
886
887
888 // Returns true if x*b+c MUST be outside the range of y and false otherwise.
889 // If two variables are unrelated, it is assumed that there is no information
890 // about their relationship and mustOutsideRange() thus proceeds conservatively (returns true).
891 bool mustOutsideRange(varID x, int b, int c, varID y, std::string indent="");
892
893 // returns true if this logical condition must be true and false otherwise
894 // <from LogicalCond>
895 bool mayTrue(std::string indent="");
896 bool mayTrue() { return mayTrue(""); }
897
898/* // returns true if x+c MUST be inside the range of y and false otherwise
899 // If two variables are unrelated, it is assumed that there is no information
900 // about their relationship and mustInsideRange() thus proceeds conservatively.
901 bool mustInsideRange(varID x, int b, int c, varID y);*/
902
903 /* Transactions */
904 void beginTransaction(std::string indent="");
905 void endTransaction(std::string indent="");
906};
907
908
909
910#endif
911#endif
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes,...