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, 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, sccNum);
34 node->sccNum = sccNum;
35 node->status = FINISHED;
41 void DFSNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool isReverse, uint sccNum) {
42 HSIteratorOrderEdge *iterator = isReverse ? iteratorOrderEdge(node->inEdges) : iteratorOrderEdge(node->outEdges);
43 while (hasNextOrderEdge(iterator)) {
44 OrderEdge *edge = nextOrderEdge(iterator);
45 if (!edge->polPos && !edge->pseudoPos)//Ignore edges that do not have positive polarity
48 OrderNode *child = isReverse ? edge->source : edge->sink;
50 if (child->status == NOTVISITED) {
51 child->status = VISITED;
52 DFSNodeVisit(child, finishNodes, isReverse, sccNum);
53 child->status = FINISHED;
54 if (finishNodes != NULL)
55 pushVectorOrderNode(finishNodes, child);
57 child->sccNum = sccNum;
60 deleteIterOrderEdge(iterator);
63 void resetNodeInfoStatusSCC(OrderGraph *graph) {
64 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
65 while (hasNextOrderNode(iterator)) {
66 nextOrderNode(iterator)->status = NOTVISITED;
68 deleteIterOrderNode(iterator);
71 void computeStronglyConnectedComponentGraph(OrderGraph *graph) {
72 VectorOrderNode finishNodes;
73 initDefVectorOrderNode(&finishNodes);
74 DFS(graph, &finishNodes);
75 resetNodeInfoStatusSCC(graph);
76 DFSReverse(graph, &finishNodes);
77 resetNodeInfoStatusSCC(graph);
78 deleteVectorArrayOrderNode(&finishNodes);
81 void removeMustBeTrueNodes(OrderGraph *graph) {
82 //TODO: Nodes that all the incoming/outgoing edges are MUST_BE_TRUE
85 /** This function computes a source set for every nodes, the set of
86 nodes that can reach that node via pospolarity edges. It then
87 looks for negative polarity edges from nodes in the the source set
88 to determine whether we need to generate pseudoPos edges. */
90 void completePartialOrderGraph(OrderGraph *graph) {
91 VectorOrderNode finishNodes;
92 initDefVectorOrderNode(&finishNodes);
93 DFS(graph, &finishNodes);
94 resetNodeInfoStatusSCC(graph);
95 HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25);
97 VectorOrderNode sccNodes;
98 initDefVectorOrderNode(&sccNodes);
100 uint size = getSizeVectorOrderNode(&finishNodes);
102 for (int i = size - 1; i >= 0; i--) {
103 OrderNode *node = getVectorOrderNode(&finishNodes, i);
104 HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25);
105 putNodeToNodeSet(table, node, sources);
107 if (node->status == NOTVISITED) {
108 //Need to do reverse traversal here...
109 node->status = VISITED;
110 DFSNodeVisit(node, &sccNodes, true, sccNum);
111 node->status = FINISHED;
112 node->sccNum = sccNum;
114 pushVectorOrderNode(&sccNodes, node);
116 //Compute in set for entire SCC
117 uint rSize = getSizeVectorOrderNode(&sccNodes);
118 for (int j = 0; j < rSize; j++) {
119 OrderNode *rnode = getVectorOrderNode(&sccNodes, j);
120 //Compute source sets
121 HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges);
122 while (hasNextOrderEdge(iterator)) {
123 OrderEdge *edge = nextOrderEdge(iterator);
124 OrderNode *parent = edge->source;
126 addHashSetOrderNode(sources, parent);
127 HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent);
128 addAllHashSetOrderNode(sources, parent_srcs);
131 deleteIterOrderEdge(iterator);
133 for (int j=0; j < rSize; j++) {
134 //Copy in set of entire SCC
135 OrderNode *rnode = getVectorOrderNode(&sccNodes, j);
136 HashSetOrderNode * set = (j==0) ? sources : copyHashSetOrderNode(sources);
137 putNodeToNodeSet(table, rnode, set);
139 //Use source sets to compute pseudoPos edges
140 HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges);
141 while (hasNextOrderEdge(iterator)) {
142 OrderEdge *edge = nextOrderEdge(iterator);
143 OrderNode *parent = edge->source;
144 ASSERT(parent != rnode);
145 if (edge->polNeg && parent->sccNum != rnode->sccNum &&
146 containsHashSetOrderNode(sources, parent)) {
147 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, rnode, parent);
148 newedge->pseudoPos = true;
151 deleteIterOrderEdge(iterator);
154 clearVectorOrderNode(&sccNodes);
158 resetAndDeleteHashTableNodeToNodeSet(table);
159 resetNodeInfoStatusSCC(graph);
160 deleteVectorArrayOrderNode(&sccNodes);
161 deleteVectorArrayOrderNode(&finishNodes);
164 void DFSMust(OrderGraph *graph, VectorOrderNode *finishNodes) {
165 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
166 while (hasNextOrderNode(iterator)) {
167 OrderNode *node = nextOrderNode(iterator);
168 if (node->status == NOTVISITED) {
169 node->status = VISITED;
170 DFSMustNodeVisit(node, finishNodes);
171 node->status = FINISHED;
172 pushVectorOrderNode(finishNodes, node);
175 deleteIterOrderNode(iterator);
178 void DFSMustNodeVisit(OrderNode *node, VectorOrderNode *finishNodes) {
179 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
180 while (hasNextOrderEdge(iterator)) {
181 OrderEdge *edge = nextOrderEdge(iterator);
182 OrderNode *child = edge->sink;
184 if (!edge->mustPos) //Ignore edges that are not must Positive edges
187 if (child->status == NOTVISITED) {
188 child->status = VISITED;
189 DFSMustNodeVisit(child, finishNodes);
190 child->status = FINISHED;
191 pushVectorOrderNode(finishNodes, child);
194 deleteIterOrderEdge(iterator);
198 void DFSClearContradictions(CSolver *solver, OrderGraph *graph, VectorOrderNode *finishNodes, bool computeTransitiveClosure) {
199 uint size = getSizeVectorOrderNode(finishNodes);
200 HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25);
202 for (int i = size - 1; i >= 0; i--) {
203 OrderNode *node = getVectorOrderNode(finishNodes, i);
204 HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25);
205 putNodeToNodeSet(table, node, sources);
208 //Compute source sets
209 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
210 while (hasNextOrderEdge(iterator)) {
211 OrderEdge *edge = nextOrderEdge(iterator);
212 OrderNode *parent = edge->source;
214 addHashSetOrderNode(sources, parent);
215 HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent);
216 addAllHashSetOrderNode(sources, parent_srcs);
219 deleteIterOrderEdge(iterator);
221 if (computeTransitiveClosure) {
222 //Compute full transitive closure for nodes
223 HSIteratorOrderNode *srciterator = iteratorOrderNode(sources);
224 while (hasNextOrderNode(srciterator)) {
225 OrderNode *srcnode = nextOrderNode(srciterator);
226 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, srcnode, node);
227 newedge->mustPos = true;
228 newedge->polPos = true;
229 if (newedge->mustNeg)
230 solver->unsat = true;
231 addHashSetOrderEdge(srcnode->outEdges,newedge);
232 addHashSetOrderEdge(node->inEdges,newedge);
234 deleteIterOrderNode(srciterator);
237 //Use source sets to compute mustPos edges
238 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
239 while (hasNextOrderEdge(iterator)) {
240 OrderEdge *edge = nextOrderEdge(iterator);
241 OrderNode *parent = edge->source;
242 if (!edge->mustPos && containsHashSetOrderNode(sources, parent)) {
243 edge->mustPos = true;
246 solver->unsat = true;
249 deleteIterOrderEdge(iterator);
252 //Use source sets to compute mustNeg for edges that would introduce cycle if true
253 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
254 while (hasNextOrderEdge(iterator)) {
255 OrderEdge *edge = nextOrderEdge(iterator);
256 OrderNode *child = edge->sink;
257 if (!edge->mustNeg && containsHashSetOrderNode(sources, child)) {
258 edge->mustNeg = true;
261 solver->unsat = true;
264 deleteIterOrderEdge(iterator);
268 resetAndDeleteHashTableNodeToNodeSet(table);
271 /* This function finds edges that would form a cycle with must edges
272 and forces them to be mustNeg. It also decides whether an edge
273 must be true because of transitivity from other must be true
276 void reachMustAnalysis(CSolver * solver, OrderGraph *graph, bool computeTransitiveClosure) {
277 VectorOrderNode finishNodes;
278 initDefVectorOrderNode(&finishNodes);
279 //Topologically sort the mustPos edge graph
280 DFSMust(graph, &finishNodes);
281 resetNodeInfoStatusSCC(graph);
283 //Find any backwards edges that complete cycles and force them to be mustNeg
284 DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure);
285 deleteVectorArrayOrderNode(&finishNodes);
288 /* This function finds edges that must be positive and forces the
289 inverse edge to be negative (and clears its positive polarity if it
292 void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) {
293 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
294 while (hasNextOrderEdge(iterator)) {
295 OrderEdge *edge = nextOrderEdge(iterator);
297 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
298 if (invEdge != NULL) {
299 if (!invEdge->mustPos) {
300 invEdge->polPos = false;
302 solver->unsat = true;
304 invEdge->mustNeg = true;
305 invEdge->polNeg = true;
309 deleteIterOrderEdge(iterator);
312 /** This finds edges that must be positive and forces the inverse edge
313 to be negative. It also clears the negative flag of this edge.
314 It also finds edges that must be negative and clears the positive
317 void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) {
318 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
319 while (hasNextOrderEdge(iterator)) {
320 OrderEdge *edge = nextOrderEdge(iterator);
322 if (!edge->mustNeg) {
323 edge->polNeg = false;
325 solver->unsat = true;
327 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
328 if (invEdge != NULL) {
329 if (!invEdge->mustPos)
330 invEdge->polPos = false;
332 solver->unsat = true;
333 invEdge->mustNeg = true;
334 invEdge->polNeg = true;
337 if (edge->mustNeg && !edge->mustPos) {
338 edge->polPos = false;
341 deleteIterOrderEdge(iterator);
344 void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) {
345 VectorOrder ordervec;
346 initDefVectorOrder(&ordervec);
347 uint size = getSizeVectorBooleanOrder(&order->constraints);
348 for (uint i = 0; i < size; i++) {
349 BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i);
350 OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first);
351 OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second);
352 if (from->sccNum != to->sccNum) {
353 OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to);
355 replaceBooleanWithTrue(This, (Boolean *)orderconstraint);
356 } else if (edge->polNeg) {
357 replaceBooleanWithFalse(This, (Boolean *)orderconstraint);
359 //This case should only be possible if constraint isn't in AST
363 //Build new order and change constraint's order
364 Order *neworder = NULL;
365 if (getSizeVectorOrder(&ordervec) > from->sccNum)
366 neworder = getVectorOrder(&ordervec, from->sccNum);
367 if (neworder == NULL) {
368 Set *set = (Set *) allocMutableSet(order->set->type);
369 neworder = allocOrder(order->type, set);
370 pushVectorOrder(This->allOrders, neworder);
371 setExpandVectorOrder(&ordervec, from->sccNum, neworder);
373 if (from->status != ADDEDTOSET) {
374 from->status = ADDEDTOSET;
375 addElementMSet((MutableSet *)neworder->set, from->id);
377 if (to->status != ADDEDTOSET) {
378 to->status = ADDEDTOSET;
379 addElementMSet((MutableSet *)neworder->set, to->id);
381 orderconstraint->order = neworder;
382 addOrderConstraint(neworder, orderconstraint);
385 deleteVectorArrayOrder(&ordervec);
388 void orderAnalysis(CSolver *This) {
389 uint size = getSizeVectorOrder(This->allOrders);
390 for (uint i = 0; i < size; i++) {
391 Order *order = getVectorOrder(This->allOrders, i);
392 bool doDecompose=GETVARTUNABLE(This->tuner, order->type, DECOMPOSEORDER, &onoff);
396 OrderGraph *graph = buildOrderGraph(order);
397 if (order->type == PARTIAL) {
398 //Required to do SCC analysis for partial order graphs. It
399 //makes sure we don't incorrectly optimize graphs with negative
401 completePartialOrderGraph(graph);
405 bool mustReachGlobal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHGLOBAL, &onoff);
408 reachMustAnalysis(This, graph, false);
410 bool mustReachLocal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHLOCAL, &onoff);
412 if (mustReachLocal) {
413 //This pair of analysis is also optional
414 if (order->type == PARTIAL) {
415 localMustAnalysisPartial(This, graph);
417 localMustAnalysisTotal(This, graph);
421 bool mustReachPrune=GETVARTUNABLE(This->tuner, order->type, MUSTREACHPRUNE, &onoff);
424 removeMustBeTrueNodes(graph);
426 //This is needed for splitorder
427 computeStronglyConnectedComponentGraph(graph);
429 decomposeOrder(This, order, graph);
431 deleteOrderGraph(graph);