1 #include "orderencoder.h"
5 #include "ordergraph.h"
9 #include "mutableset.h"
12 void DFS(OrderGraph *graph, VectorOrderNode *finishNodes) {
13 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
14 while (hasNextOrderNode(iterator)) {
15 OrderNode *node = nextOrderNode(iterator);
16 if (node->status == NOTVISITED) {
17 node->status = VISITED;
18 DFSNodeVisit(node, finishNodes, false, false, 0);
19 node->status = FINISHED;
20 pushVectorOrderNode(finishNodes, node);
23 deleteIterOrderNode(iterator);
26 void DFSReverse(OrderGraph *graph, VectorOrderNode *finishNodes) {
27 uint size = getSizeVectorOrderNode(finishNodes);
29 for (int i = size - 1; i >= 0; i--) {
30 OrderNode *node = getVectorOrderNode(finishNodes, i);
31 if (node->status == NOTVISITED) {
32 node->status = VISITED;
33 DFSNodeVisit(node, NULL, true, false, sccNum);
34 node->sccNum = sccNum;
35 node->status = FINISHED;
41 void DFSNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool isReverse, bool mustvisit, uint sccNum) {
42 HSIteratorOrderEdge *iterator = isReverse ? iteratorOrderEdge(node->inEdges) : iteratorOrderEdge(node->outEdges);
43 while (hasNextOrderEdge(iterator)) {
44 OrderEdge *edge = nextOrderEdge(iterator);
49 if (!edge->polPos && !edge->pseudoPos)//Ignore edges that do not have positive polarity
52 OrderNode *child = isReverse ? edge->source : edge->sink;
54 if (child->status == NOTVISITED) {
55 child->status = VISITED;
56 DFSNodeVisit(child, finishNodes, isReverse, mustvisit, sccNum);
57 child->status = FINISHED;
58 if (finishNodes != NULL)
59 pushVectorOrderNode(finishNodes, child);
61 child->sccNum = sccNum;
64 deleteIterOrderEdge(iterator);
67 void resetNodeInfoStatusSCC(OrderGraph *graph) {
68 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
69 while (hasNextOrderNode(iterator)) {
70 nextOrderNode(iterator)->status = NOTVISITED;
72 deleteIterOrderNode(iterator);
75 void computeStronglyConnectedComponentGraph(OrderGraph *graph) {
76 VectorOrderNode finishNodes;
77 initDefVectorOrderNode(&finishNodes);
78 DFS(graph, &finishNodes);
79 resetNodeInfoStatusSCC(graph);
80 DFSReverse(graph, &finishNodes);
81 resetNodeInfoStatusSCC(graph);
82 deleteVectorArrayOrderNode(&finishNodes);
85 void removeMustBeTrueNodes(OrderGraph *graph) {
86 //TODO: Nodes that all the incoming/outgoing edges are MUST_BE_TRUE
89 /** This function computes a source set for every nodes, the set of
90 nodes that can reach that node via pospolarity edges. It then
91 looks for negative polarity edges from nodes in the the source set
92 to determine whether we need to generate pseudoPos edges. */
94 void completePartialOrderGraph(OrderGraph *graph) {
95 VectorOrderNode finishNodes;
96 initDefVectorOrderNode(&finishNodes);
97 DFS(graph, &finishNodes);
98 resetNodeInfoStatusSCC(graph);
99 HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25);
101 VectorOrderNode sccNodes;
102 initDefVectorOrderNode(&sccNodes);
104 uint size = getSizeVectorOrderNode(&finishNodes);
106 for (int i = size - 1; i >= 0; i--) {
107 OrderNode *node = getVectorOrderNode(&finishNodes, i);
108 HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25);
109 putNodeToNodeSet(table, node, sources);
111 if (node->status == NOTVISITED) {
112 //Need to do reverse traversal here...
113 node->status = VISITED;
114 DFSNodeVisit(node, &sccNodes, true, false, sccNum);
115 node->status = FINISHED;
116 node->sccNum = sccNum;
118 pushVectorOrderNode(&sccNodes, node);
120 //Compute in set for entire SCC
121 uint rSize = getSizeVectorOrderNode(&sccNodes);
122 for (int j = 0; j < rSize; j++) {
123 OrderNode *rnode = getVectorOrderNode(&sccNodes, j);
124 //Compute source sets
125 HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges);
126 while (hasNextOrderEdge(iterator)) {
127 OrderEdge *edge = nextOrderEdge(iterator);
128 OrderNode *parent = edge->source;
130 addHashSetOrderNode(sources, parent);
131 HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent);
132 addAllHashSetOrderNode(sources, parent_srcs);
135 deleteIterOrderEdge(iterator);
137 for (int j=0; j < rSize; j++) {
138 //Copy in set of entire SCC
139 OrderNode *rnode = getVectorOrderNode(&sccNodes, j);
140 HashSetOrderNode * set = (j==0) ? sources : copyHashSetOrderNode(sources);
141 putNodeToNodeSet(table, rnode, set);
143 //Use source sets to compute pseudoPos edges
144 HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges);
145 while (hasNextOrderEdge(iterator)) {
146 OrderEdge *edge = nextOrderEdge(iterator);
147 OrderNode *parent = edge->source;
148 ASSERT(parent != rnode);
149 if (edge->polNeg && parent->sccNum != rnode->sccNum &&
150 containsHashSetOrderNode(sources, parent)) {
151 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, rnode, parent);
152 newedge->pseudoPos = true;
155 deleteIterOrderEdge(iterator);
158 clearVectorOrderNode(&sccNodes);
162 resetAndDeleteHashTableNodeToNodeSet(table);
163 resetNodeInfoStatusSCC(graph);
164 deleteVectorArrayOrderNode(&sccNodes);
165 deleteVectorArrayOrderNode(&finishNodes);
168 void DFSMust(OrderGraph *graph, VectorOrderNode *finishNodes) {
169 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
170 while (hasNextOrderNode(iterator)) {
171 OrderNode *node = nextOrderNode(iterator);
172 if (node->status == NOTVISITED) {
173 node->status = VISITED;
174 DFSNodeVisit(node, finishNodes, false, true, 0);
175 node->status = FINISHED;
176 pushVectorOrderNode(finishNodes, node);
179 deleteIterOrderNode(iterator);
182 void DFSClearContradictions(CSolver *solver, OrderGraph *graph, VectorOrderNode *finishNodes, bool computeTransitiveClosure) {
183 uint size = getSizeVectorOrderNode(finishNodes);
184 HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25);
186 for (int i = size - 1; i >= 0; i--) {
187 OrderNode *node = getVectorOrderNode(finishNodes, i);
188 HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25);
189 putNodeToNodeSet(table, node, sources);
192 //Compute source sets
193 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
194 while (hasNextOrderEdge(iterator)) {
195 OrderEdge *edge = nextOrderEdge(iterator);
196 OrderNode *parent = edge->source;
198 addHashSetOrderNode(sources, parent);
199 HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent);
200 addAllHashSetOrderNode(sources, parent_srcs);
203 deleteIterOrderEdge(iterator);
205 if (computeTransitiveClosure) {
206 //Compute full transitive closure for nodes
207 HSIteratorOrderNode *srciterator = iteratorOrderNode(sources);
208 while (hasNextOrderNode(srciterator)) {
209 OrderNode *srcnode = nextOrderNode(srciterator);
210 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, srcnode, node);
211 newedge->mustPos = true;
212 newedge->polPos = true;
213 if (newedge->mustNeg)
214 solver->unsat = true;
215 addHashSetOrderEdge(srcnode->outEdges,newedge);
216 addHashSetOrderEdge(node->inEdges,newedge);
218 deleteIterOrderNode(srciterator);
221 //Use source sets to compute mustPos edges
222 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
223 while (hasNextOrderEdge(iterator)) {
224 OrderEdge *edge = nextOrderEdge(iterator);
225 OrderNode *parent = edge->source;
226 if (!edge->mustPos && containsHashSetOrderNode(sources, parent)) {
227 edge->mustPos = true;
230 solver->unsat = true;
233 deleteIterOrderEdge(iterator);
236 //Use source sets to compute mustNeg for edges that would introduce cycle if true
237 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
238 while (hasNextOrderEdge(iterator)) {
239 OrderEdge *edge = nextOrderEdge(iterator);
240 OrderNode *child = edge->sink;
241 if (!edge->mustNeg && containsHashSetOrderNode(sources, child)) {
242 edge->mustNeg = true;
245 solver->unsat = true;
248 deleteIterOrderEdge(iterator);
252 resetAndDeleteHashTableNodeToNodeSet(table);
255 /* This function finds edges that would form a cycle with must edges
256 and forces them to be mustNeg. It also decides whether an edge
257 must be true because of transitivity from other must be true
260 void reachMustAnalysis(CSolver * solver, OrderGraph *graph, bool computeTransitiveClosure) {
261 VectorOrderNode finishNodes;
262 initDefVectorOrderNode(&finishNodes);
263 //Topologically sort the mustPos edge graph
264 DFSMust(graph, &finishNodes);
265 resetNodeInfoStatusSCC(graph);
267 //Find any backwards edges that complete cycles and force them to be mustNeg
268 DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure);
269 deleteVectorArrayOrderNode(&finishNodes);
272 /* This function finds edges that must be positive and forces the
273 inverse edge to be negative (and clears its positive polarity if it
276 void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) {
277 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
278 while (hasNextOrderEdge(iterator)) {
279 OrderEdge *edge = nextOrderEdge(iterator);
281 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
282 if (invEdge != NULL) {
283 if (!invEdge->mustPos) {
284 invEdge->polPos = false;
286 solver->unsat = true;
288 invEdge->mustNeg = true;
289 invEdge->polNeg = true;
293 deleteIterOrderEdge(iterator);
296 /** This finds edges that must be positive and forces the inverse edge
297 to be negative. It also clears the negative flag of this edge.
298 It also finds edges that must be negative and clears the positive
301 void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) {
302 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
303 while (hasNextOrderEdge(iterator)) {
304 OrderEdge *edge = nextOrderEdge(iterator);
306 if (!edge->mustNeg) {
307 edge->polNeg = false;
309 solver->unsat = true;
311 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
312 if (invEdge != NULL) {
313 if (!invEdge->mustPos)
314 invEdge->polPos = false;
316 solver->unsat = true;
317 invEdge->mustNeg = true;
318 invEdge->polNeg = true;
321 if (edge->mustNeg && !edge->mustPos) {
322 edge->polPos = false;
325 deleteIterOrderEdge(iterator);
328 void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) {
329 VectorOrder ordervec;
330 initDefVectorOrder(&ordervec);
331 uint size = getSizeVectorBooleanOrder(&order->constraints);
332 for (uint i = 0; i < size; i++) {
333 BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i);
334 OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first);
335 OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second);
336 if (from->sccNum != to->sccNum) {
337 OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to);
339 replaceBooleanWithTrue(This, (Boolean *)orderconstraint);
340 } else if (edge->polNeg) {
341 replaceBooleanWithFalse(This, (Boolean *)orderconstraint);
343 //This case should only be possible if constraint isn't in AST
347 //Build new order and change constraint's order
348 Order *neworder = NULL;
349 if (getSizeVectorOrder(&ordervec) > from->sccNum)
350 neworder = getVectorOrder(&ordervec, from->sccNum);
351 if (neworder == NULL) {
352 Set *set = (Set *) allocMutableSet(order->set->type);
353 neworder = allocOrder(order->type, set);
354 pushVectorOrder(This->allOrders, neworder);
355 setExpandVectorOrder(&ordervec, from->sccNum, neworder);
357 if (from->status != ADDEDTOSET) {
358 from->status = ADDEDTOSET;
359 addElementMSet((MutableSet *)neworder->set, from->id);
361 if (to->status != ADDEDTOSET) {
362 to->status = ADDEDTOSET;
363 addElementMSet((MutableSet *)neworder->set, to->id);
365 orderconstraint->order = neworder;
366 addOrderConstraint(neworder, orderconstraint);
369 deleteVectorArrayOrder(&ordervec);
372 void orderAnalysis(CSolver *This) {
373 uint size = getSizeVectorOrder(This->allOrders);
374 for (uint i = 0; i < size; i++) {
375 Order *order = getVectorOrder(This->allOrders, i);
376 bool doDecompose=GETVARTUNABLE(This->tuner, order->type, DECOMPOSEORDER, &onoff);
380 OrderGraph *graph = buildOrderGraph(order);
381 if (order->type == PARTIAL) {
382 //Required to do SCC analysis for partial order graphs. It
383 //makes sure we don't incorrectly optimize graphs with negative
385 completePartialOrderGraph(graph);
389 bool mustReachGlobal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHGLOBAL, &onoff);
392 reachMustAnalysis(This, graph, false);
394 bool mustReachLocal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHLOCAL, &onoff);
396 if (mustReachLocal) {
397 //This pair of analysis is also optional
398 if (order->type == PARTIAL) {
399 localMustAnalysisPartial(This, graph);
401 localMustAnalysisTotal(This, graph);
405 bool mustReachPrune=GETVARTUNABLE(This->tuner, order->type, MUSTREACHPRUNE, &onoff);
408 removeMustBeTrueNodes(graph);
410 //This is needed for splitorder
411 computeStronglyConnectedComponentGraph(graph);
413 decomposeOrder(This, order, graph);
415 deleteOrderGraph(graph);