Merge from mainline (168000:168310).
[official-gcc/graphite-test-results.git] / gcc / omega.c
blobaee99e72a84f210d57f034eded93ca50516084ca
1 /* Source code for an implementation of the Omega test, an integer
2 programming algorithm for dependence analysis, by William Pugh,
3 appeared in Supercomputing '91 and CACM Aug 92.
5 This code has no license restrictions, and is considered public
6 domain.
8 Changes copyright (C) 2005, 2006, 2007, 2008, 2009,
9 2010 Free Software Foundation, Inc.
10 Contributed by Sebastian Pop <sebastian.pop@inria.fr>
12 This file is part of GCC.
14 GCC is free software; you can redistribute it and/or modify it under
15 the terms of the GNU General Public License as published by the Free
16 Software Foundation; either version 3, or (at your option) any later
17 version.
19 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20 WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING3. If not see
26 <http://www.gnu.org/licenses/>. */
28 /* For a detailed description, see "Constraint-Based Array Dependence
29 Analysis" William Pugh, David Wonnacott, TOPLAS'98 and David
30 Wonnacott's thesis:
31 ftp://ftp.cs.umd.edu/pub/omega/davewThesis/davewThesis.ps.gz
34 #include "config.h"
35 #include "system.h"
36 #include "coretypes.h"
37 #include "tree.h"
38 #include "diagnostic-core.h"
39 #include "tree-pass.h"
40 #include "omega.h"
42 /* When set to true, keep substitution variables. When set to false,
43 resurrect substitution variables (convert substitutions back to EQs). */
44 static bool omega_reduce_with_subs = true;
46 /* When set to true, omega_simplify_problem checks for problem with no
47 solutions, calling verify_omega_pb. */
48 static bool omega_verify_simplification = false;
50 /* When set to true, only produce a single simplified result. */
51 static bool omega_single_result = false;
53 /* Set return_single_result to 1 when omega_single_result is true. */
54 static int return_single_result = 0;
56 /* Hash table for equations generated by the solver. */
57 #define HASH_TABLE_SIZE PARAM_VALUE (PARAM_OMEGA_HASH_TABLE_SIZE)
58 #define MAX_KEYS PARAM_VALUE (PARAM_OMEGA_MAX_KEYS)
59 static eqn hash_master;
60 static int next_key;
61 static int hash_version = 0;
63 /* Set to true for making the solver enter in approximation mode. */
64 static bool in_approximate_mode = false;
66 /* When set to zero, the solver is allowed to add new equalities to
67 the problem to be solved. */
68 static int conservative = 0;
70 /* Set to omega_true when the problem was successfully reduced, set to
71 omega_unknown when the solver is unable to determine an answer. */
72 static enum omega_result omega_found_reduction;
74 /* Set to true when the solver is allowed to add omega_red equations. */
75 static bool create_color = false;
77 /* Set to nonzero when the problem to be solved can be reduced. */
78 static int may_be_red = 0;
80 /* When false, there should be no substitution equations in the
81 simplified problem. */
82 static int please_no_equalities_in_simplified_problems = 0;
84 /* Variables names for pretty printing. */
85 static char wild_name[200][40];
87 /* Pointer to the void problem. */
88 static omega_pb no_problem = (omega_pb) 0;
90 /* Pointer to the problem to be solved. */
91 static omega_pb original_problem = (omega_pb) 0;
94 /* Return the integer A divided by B. */
96 static inline int
97 int_div (int a, int b)
99 if (a > 0)
100 return a/b;
101 else
102 return -((-a + b - 1)/b);
105 /* Return the integer A modulo B. */
107 static inline int
108 int_mod (int a, int b)
110 return a - b * int_div (a, b);
113 /* For X and Y positive integers, return X multiplied by Y and check
114 that the result does not overflow. */
116 static inline int
117 check_pos_mul (int x, int y)
119 if (x != 0)
120 gcc_assert ((INT_MAX) / x > y);
122 return x * y;
125 /* Return X multiplied by Y and check that the result does not
126 overflow. */
128 static inline int
129 check_mul (int x, int y)
131 if (x >= 0)
133 if (y >= 0)
134 return check_pos_mul (x, y);
135 else
136 return -check_pos_mul (x, -y);
138 else if (y >= 0)
139 return -check_pos_mul (-x, y);
140 else
141 return check_pos_mul (-x, -y);
144 /* Test whether equation E is red. */
146 static inline bool
147 omega_eqn_is_red (eqn e, int desired_res)
149 return (desired_res == omega_simplify && e->color == omega_red);
152 /* Return a string for VARIABLE. */
154 static inline char *
155 omega_var_to_str (int variable)
157 if (0 <= variable && variable <= 20)
158 return wild_name[variable];
160 if (-20 < variable && variable < 0)
161 return wild_name[40 + variable];
163 /* Collapse all the entries that would have overflowed. */
164 return wild_name[21];
167 /* Return a string for variable I in problem PB. */
169 static inline char *
170 omega_variable_to_str (omega_pb pb, int i)
172 return omega_var_to_str (pb->var[i]);
175 /* Do nothing function: used for default initializations. */
177 void
178 omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
182 void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
184 /* Compute the greatest common divisor of A and B. */
186 static inline int
187 gcd (int b, int a)
189 if (b == 1)
190 return 1;
192 while (b != 0)
194 int t = b;
195 b = a % b;
196 a = t;
199 return a;
202 /* Print to FILE from PB equation E with all its coefficients
203 multiplied by C. */
205 static void
206 omega_print_term (FILE *file, omega_pb pb, eqn e, int c)
208 int i;
209 bool first = true;
210 int n = pb->num_vars;
211 int went_first = -1;
213 for (i = 1; i <= n; i++)
214 if (c * e->coef[i] > 0)
216 first = false;
217 went_first = i;
219 if (c * e->coef[i] == 1)
220 fprintf (file, "%s", omega_variable_to_str (pb, i));
221 else
222 fprintf (file, "%d * %s", c * e->coef[i],
223 omega_variable_to_str (pb, i));
224 break;
227 for (i = 1; i <= n; i++)
228 if (i != went_first && c * e->coef[i] != 0)
230 if (!first && c * e->coef[i] > 0)
231 fprintf (file, " + ");
233 first = false;
235 if (c * e->coef[i] == 1)
236 fprintf (file, "%s", omega_variable_to_str (pb, i));
237 else if (c * e->coef[i] == -1)
238 fprintf (file, " - %s", omega_variable_to_str (pb, i));
239 else
240 fprintf (file, "%d * %s", c * e->coef[i],
241 omega_variable_to_str (pb, i));
244 if (!first && c * e->coef[0] > 0)
245 fprintf (file, " + ");
247 if (first || c * e->coef[0] != 0)
248 fprintf (file, "%d", c * e->coef[0]);
251 /* Print to FILE the equation E of problem PB. */
253 void
254 omega_print_eqn (FILE *file, omega_pb pb, eqn e, bool test, int extra)
256 int i;
257 int n = pb->num_vars + extra;
258 bool is_lt = test && e->coef[0] == -1;
259 bool first;
261 if (test)
263 if (e->touched)
264 fprintf (file, "!");
266 else if (e->key != 0)
267 fprintf (file, "%d: ", e->key);
270 if (e->color == omega_red)
271 fprintf (file, "[");
273 first = true;
275 for (i = is_lt ? 1 : 0; i <= n; i++)
276 if (e->coef[i] < 0)
278 if (!first)
279 fprintf (file, " + ");
280 else
281 first = false;
283 if (i == 0)
284 fprintf (file, "%d", -e->coef[i]);
285 else if (e->coef[i] == -1)
286 fprintf (file, "%s", omega_variable_to_str (pb, i));
287 else
288 fprintf (file, "%d * %s", -e->coef[i],
289 omega_variable_to_str (pb, i));
292 if (first)
294 if (is_lt)
296 fprintf (file, "1");
297 is_lt = false;
299 else
300 fprintf (file, "0");
303 if (test == 0)
304 fprintf (file, " = ");
305 else if (is_lt)
306 fprintf (file, " < ");
307 else
308 fprintf (file, " <= ");
310 first = true;
312 for (i = 0; i <= n; i++)
313 if (e->coef[i] > 0)
315 if (!first)
316 fprintf (file, " + ");
317 else
318 first = false;
320 if (i == 0)
321 fprintf (file, "%d", e->coef[i]);
322 else if (e->coef[i] == 1)
323 fprintf (file, "%s", omega_variable_to_str (pb, i));
324 else
325 fprintf (file, "%d * %s", e->coef[i],
326 omega_variable_to_str (pb, i));
329 if (first)
330 fprintf (file, "0");
332 if (e->color == omega_red)
333 fprintf (file, "]");
336 /* Print to FILE all the variables of problem PB. */
338 static void
339 omega_print_vars (FILE *file, omega_pb pb)
341 int i;
343 fprintf (file, "variables = ");
345 if (pb->safe_vars > 0)
346 fprintf (file, "protected (");
348 for (i = 1; i <= pb->num_vars; i++)
350 fprintf (file, "%s", omega_variable_to_str (pb, i));
352 if (i == pb->safe_vars)
353 fprintf (file, ")");
355 if (i < pb->num_vars)
356 fprintf (file, ", ");
359 fprintf (file, "\n");
362 /* Debug problem PB. */
364 DEBUG_FUNCTION void
365 debug_omega_problem (omega_pb pb)
367 omega_print_problem (stderr, pb);
370 /* Print to FILE problem PB. */
372 void
373 omega_print_problem (FILE *file, omega_pb pb)
375 int e;
377 if (!pb->variables_initialized)
378 omega_initialize_variables (pb);
380 omega_print_vars (file, pb);
382 for (e = 0; e < pb->num_eqs; e++)
384 omega_print_eq (file, pb, &pb->eqs[e]);
385 fprintf (file, "\n");
388 fprintf (file, "Done with EQ\n");
390 for (e = 0; e < pb->num_geqs; e++)
392 omega_print_geq (file, pb, &pb->geqs[e]);
393 fprintf (file, "\n");
396 fprintf (file, "Done with GEQ\n");
398 for (e = 0; e < pb->num_subs; e++)
400 eqn eq = &pb->subs[e];
402 if (eq->color == omega_red)
403 fprintf (file, "[");
405 if (eq->key > 0)
406 fprintf (file, "%s := ", omega_var_to_str (eq->key));
407 else
408 fprintf (file, "#%d := ", eq->key);
410 omega_print_term (file, pb, eq, 1);
412 if (eq->color == omega_red)
413 fprintf (file, "]");
415 fprintf (file, "\n");
419 /* Return the number of equations in PB tagged omega_red. */
422 omega_count_red_equations (omega_pb pb)
424 int e, i;
425 int result = 0;
427 for (e = 0; e < pb->num_eqs; e++)
428 if (pb->eqs[e].color == omega_red)
430 for (i = pb->num_vars; i > 0; i--)
431 if (pb->geqs[e].coef[i])
432 break;
434 if (i == 0 && pb->geqs[e].coef[0] == 1)
435 return 0;
436 else
437 result += 2;
440 for (e = 0; e < pb->num_geqs; e++)
441 if (pb->geqs[e].color == omega_red)
442 result += 1;
444 for (e = 0; e < pb->num_subs; e++)
445 if (pb->subs[e].color == omega_red)
446 result += 2;
448 return result;
451 /* Print to FILE all the equations in PB that are tagged omega_red. */
453 void
454 omega_print_red_equations (FILE *file, omega_pb pb)
456 int e;
458 if (!pb->variables_initialized)
459 omega_initialize_variables (pb);
461 omega_print_vars (file, pb);
463 for (e = 0; e < pb->num_eqs; e++)
464 if (pb->eqs[e].color == omega_red)
466 omega_print_eq (file, pb, &pb->eqs[e]);
467 fprintf (file, "\n");
470 for (e = 0; e < pb->num_geqs; e++)
471 if (pb->geqs[e].color == omega_red)
473 omega_print_geq (file, pb, &pb->geqs[e]);
474 fprintf (file, "\n");
477 for (e = 0; e < pb->num_subs; e++)
478 if (pb->subs[e].color == omega_red)
480 eqn eq = &pb->subs[e];
481 fprintf (file, "[");
483 if (eq->key > 0)
484 fprintf (file, "%s := ", omega_var_to_str (eq->key));
485 else
486 fprintf (file, "#%d := ", eq->key);
488 omega_print_term (file, pb, eq, 1);
489 fprintf (file, "]\n");
493 /* Pretty print PB to FILE. */
495 void
496 omega_pretty_print_problem (FILE *file, omega_pb pb)
498 int e, v, v1, v2, v3, t;
499 bool *live = XNEWVEC (bool, OMEGA_MAX_GEQS);
500 int stuffPrinted = 0;
501 bool change;
503 typedef enum {
504 none, le, lt
505 } partial_order_type;
507 partial_order_type **po = XNEWVEC (partial_order_type *,
508 OMEGA_MAX_VARS * OMEGA_MAX_VARS);
509 int **po_eq = XNEWVEC (int *, OMEGA_MAX_VARS * OMEGA_MAX_VARS);
510 int *last_links = XNEWVEC (int, OMEGA_MAX_VARS);
511 int *first_links = XNEWVEC (int, OMEGA_MAX_VARS);
512 int *chain_length = XNEWVEC (int, OMEGA_MAX_VARS);
513 int *chain = XNEWVEC (int, OMEGA_MAX_VARS);
514 int i, m;
515 bool multiprint;
517 if (!pb->variables_initialized)
518 omega_initialize_variables (pb);
520 if (pb->num_vars > 0)
522 omega_eliminate_redundant (pb, false);
524 for (e = 0; e < pb->num_eqs; e++)
526 if (stuffPrinted)
527 fprintf (file, "; ");
529 stuffPrinted = 1;
530 omega_print_eq (file, pb, &pb->eqs[e]);
533 for (e = 0; e < pb->num_geqs; e++)
534 live[e] = true;
536 while (1)
538 for (v = 1; v <= pb->num_vars; v++)
540 last_links[v] = first_links[v] = 0;
541 chain_length[v] = 0;
543 for (v2 = 1; v2 <= pb->num_vars; v2++)
544 po[v][v2] = none;
547 for (e = 0; e < pb->num_geqs; e++)
548 if (live[e])
550 for (v = 1; v <= pb->num_vars; v++)
551 if (pb->geqs[e].coef[v] == 1)
552 first_links[v]++;
553 else if (pb->geqs[e].coef[v] == -1)
554 last_links[v]++;
556 v1 = pb->num_vars;
558 while (v1 > 0 && pb->geqs[e].coef[v1] == 0)
559 v1--;
561 v2 = v1 - 1;
563 while (v2 > 0 && pb->geqs[e].coef[v2] == 0)
564 v2--;
566 v3 = v2 - 1;
568 while (v3 > 0 && pb->geqs[e].coef[v3] == 0)
569 v3--;
571 if (pb->geqs[e].coef[0] > 0 || pb->geqs[e].coef[0] < -1
572 || v2 <= 0 || v3 > 0
573 || pb->geqs[e].coef[v1] * pb->geqs[e].coef[v2] != -1)
575 /* Not a partial order relation. */
577 else
579 if (pb->geqs[e].coef[v1] == 1)
581 v3 = v2;
582 v2 = v1;
583 v1 = v3;
586 /* Relation is v1 <= v2 or v1 < v2. */
587 po[v1][v2] = ((pb->geqs[e].coef[0] == 0) ? le : lt);
588 po_eq[v1][v2] = e;
591 for (v = 1; v <= pb->num_vars; v++)
592 chain_length[v] = last_links[v];
594 /* Just in case pb->num_vars <= 0. */
595 change = false;
596 for (t = 0; t < pb->num_vars; t++)
598 change = false;
600 for (v1 = 1; v1 <= pb->num_vars; v1++)
601 for (v2 = 1; v2 <= pb->num_vars; v2++)
602 if (po[v1][v2] != none &&
603 chain_length[v1] <= chain_length[v2])
605 chain_length[v1] = chain_length[v2] + 1;
606 change = true;
610 /* Caught in cycle. */
611 gcc_assert (!change);
613 for (v1 = 1; v1 <= pb->num_vars; v1++)
614 if (chain_length[v1] == 0)
615 first_links[v1] = 0;
617 v = 1;
619 for (v1 = 2; v1 <= pb->num_vars; v1++)
620 if (chain_length[v1] + first_links[v1] >
621 chain_length[v] + first_links[v])
622 v = v1;
624 if (chain_length[v] + first_links[v] == 0)
625 break;
627 if (stuffPrinted)
628 fprintf (file, "; ");
630 stuffPrinted = 1;
632 /* Chain starts at v. */
634 int tmp;
635 bool first = true;
637 for (e = 0; e < pb->num_geqs; e++)
638 if (live[e] && pb->geqs[e].coef[v] == 1)
640 if (!first)
641 fprintf (file, ", ");
643 tmp = pb->geqs[e].coef[v];
644 pb->geqs[e].coef[v] = 0;
645 omega_print_term (file, pb, &pb->geqs[e], -1);
646 pb->geqs[e].coef[v] = tmp;
647 live[e] = false;
648 first = false;
651 if (!first)
652 fprintf (file, " <= ");
655 /* Find chain. */
656 chain[0] = v;
657 m = 1;
658 while (1)
660 /* Print chain. */
661 for (v2 = 1; v2 <= pb->num_vars; v2++)
662 if (po[v][v2] && chain_length[v] == 1 + chain_length[v2])
663 break;
665 if (v2 > pb->num_vars)
666 break;
668 chain[m++] = v2;
669 v = v2;
672 fprintf (file, "%s", omega_variable_to_str (pb, chain[0]));
674 for (multiprint = false, i = 1; i < m; i++)
676 v = chain[i - 1];
677 v2 = chain[i];
679 if (po[v][v2] == le)
680 fprintf (file, " <= ");
681 else
682 fprintf (file, " < ");
684 fprintf (file, "%s", omega_variable_to_str (pb, v2));
685 live[po_eq[v][v2]] = false;
687 if (!multiprint && i < m - 1)
688 for (v3 = 1; v3 <= pb->num_vars; v3++)
690 if (v == v3 || v2 == v3
691 || po[v][v2] != po[v][v3]
692 || po[v2][chain[i + 1]] != po[v3][chain[i + 1]])
693 continue;
695 fprintf (file, ",%s", omega_variable_to_str (pb, v3));
696 live[po_eq[v][v3]] = false;
697 live[po_eq[v3][chain[i + 1]]] = false;
698 multiprint = true;
700 else
701 multiprint = false;
704 v = chain[m - 1];
705 /* Print last_links. */
707 int tmp;
708 bool first = true;
710 for (e = 0; e < pb->num_geqs; e++)
711 if (live[e] && pb->geqs[e].coef[v] == -1)
713 if (!first)
714 fprintf (file, ", ");
715 else
716 fprintf (file, " <= ");
718 tmp = pb->geqs[e].coef[v];
719 pb->geqs[e].coef[v] = 0;
720 omega_print_term (file, pb, &pb->geqs[e], 1);
721 pb->geqs[e].coef[v] = tmp;
722 live[e] = false;
723 first = false;
728 for (e = 0; e < pb->num_geqs; e++)
729 if (live[e])
731 if (stuffPrinted)
732 fprintf (file, "; ");
733 stuffPrinted = 1;
734 omega_print_geq (file, pb, &pb->geqs[e]);
737 for (e = 0; e < pb->num_subs; e++)
739 eqn eq = &pb->subs[e];
741 if (stuffPrinted)
742 fprintf (file, "; ");
744 stuffPrinted = 1;
746 if (eq->key > 0)
747 fprintf (file, "%s := ", omega_var_to_str (eq->key));
748 else
749 fprintf (file, "#%d := ", eq->key);
751 omega_print_term (file, pb, eq, 1);
755 free (live);
756 free (po);
757 free (po_eq);
758 free (last_links);
759 free (first_links);
760 free (chain_length);
761 free (chain);
764 /* Assign to variable I in PB the next wildcard name. The name of a
765 wildcard is a negative number. */
766 static int next_wild_card = 0;
768 static void
769 omega_name_wild_card (omega_pb pb, int i)
771 --next_wild_card;
772 if (next_wild_card < -PARAM_VALUE (PARAM_OMEGA_MAX_WILD_CARDS))
773 next_wild_card = -1;
774 pb->var[i] = next_wild_card;
777 /* Return the index of the last protected (or safe) variable in PB,
778 after having added a new wildcard variable. */
780 static int
781 omega_add_new_wild_card (omega_pb pb)
783 int e;
784 int i = ++pb->safe_vars;
785 pb->num_vars++;
787 /* Make a free place in the protected (safe) variables, by moving
788 the non protected variable pointed by "I" at the end, ie. at
789 offset pb->num_vars. */
790 if (pb->num_vars != i)
792 /* Move "I" for all the inequalities. */
793 for (e = pb->num_geqs - 1; e >= 0; e--)
795 if (pb->geqs[e].coef[i])
796 pb->geqs[e].touched = 1;
798 pb->geqs[e].coef[pb->num_vars] = pb->geqs[e].coef[i];
801 /* Move "I" for all the equalities. */
802 for (e = pb->num_eqs - 1; e >= 0; e--)
803 pb->eqs[e].coef[pb->num_vars] = pb->eqs[e].coef[i];
805 /* Move "I" for all the substitutions. */
806 for (e = pb->num_subs - 1; e >= 0; e--)
807 pb->subs[e].coef[pb->num_vars] = pb->subs[e].coef[i];
809 /* Move the identifier. */
810 pb->var[pb->num_vars] = pb->var[i];
813 /* Initialize at zero all the coefficients */
814 for (e = pb->num_geqs - 1; e >= 0; e--)
815 pb->geqs[e].coef[i] = 0;
817 for (e = pb->num_eqs - 1; e >= 0; e--)
818 pb->eqs[e].coef[i] = 0;
820 for (e = pb->num_subs - 1; e >= 0; e--)
821 pb->subs[e].coef[i] = 0;
823 /* And give it a name. */
824 omega_name_wild_card (pb, i);
825 return i;
828 /* Delete inequality E from problem PB that has N_VARS variables. */
830 static void
831 omega_delete_geq (omega_pb pb, int e, int n_vars)
833 if (dump_file && (dump_flags & TDF_DETAILS))
835 fprintf (dump_file, "Deleting %d (last:%d): ", e, pb->num_geqs - 1);
836 omega_print_geq (dump_file, pb, &pb->geqs[e]);
837 fprintf (dump_file, "\n");
840 if (e < pb->num_geqs - 1)
841 omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
843 pb->num_geqs--;
846 /* Delete extra inequality E from problem PB that has N_VARS
847 variables. */
849 static void
850 omega_delete_geq_extra (omega_pb pb, int e, int n_vars)
852 if (dump_file && (dump_flags & TDF_DETAILS))
854 fprintf (dump_file, "Deleting %d: ",e);
855 omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
856 fprintf (dump_file, "\n");
859 if (e < pb->num_geqs - 1)
860 omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
862 pb->num_geqs--;
866 /* Remove variable I from problem PB. */
868 static void
869 omega_delete_variable (omega_pb pb, int i)
871 int n_vars = pb->num_vars;
872 int e;
874 if (omega_safe_var_p (pb, i))
876 int j = pb->safe_vars;
878 for (e = pb->num_geqs - 1; e >= 0; e--)
880 pb->geqs[e].touched = 1;
881 pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
882 pb->geqs[e].coef[j] = pb->geqs[e].coef[n_vars];
885 for (e = pb->num_eqs - 1; e >= 0; e--)
887 pb->eqs[e].coef[i] = pb->eqs[e].coef[j];
888 pb->eqs[e].coef[j] = pb->eqs[e].coef[n_vars];
891 for (e = pb->num_subs - 1; e >= 0; e--)
893 pb->subs[e].coef[i] = pb->subs[e].coef[j];
894 pb->subs[e].coef[j] = pb->subs[e].coef[n_vars];
897 pb->var[i] = pb->var[j];
898 pb->var[j] = pb->var[n_vars];
900 else if (i < n_vars)
902 for (e = pb->num_geqs - 1; e >= 0; e--)
903 if (pb->geqs[e].coef[n_vars])
905 pb->geqs[e].coef[i] = pb->geqs[e].coef[n_vars];
906 pb->geqs[e].touched = 1;
909 for (e = pb->num_eqs - 1; e >= 0; e--)
910 pb->eqs[e].coef[i] = pb->eqs[e].coef[n_vars];
912 for (e = pb->num_subs - 1; e >= 0; e--)
913 pb->subs[e].coef[i] = pb->subs[e].coef[n_vars];
915 pb->var[i] = pb->var[n_vars];
918 if (omega_safe_var_p (pb, i))
919 pb->safe_vars--;
921 pb->num_vars--;
924 /* Because the coefficients of an equation are sparse, PACKING records
925 indices for non null coefficients. */
926 static int *packing;
928 /* Set up the coefficients of PACKING, following the coefficients of
929 equation EQN that has NUM_VARS variables. */
931 static inline int
932 setup_packing (eqn eqn, int num_vars)
934 int k;
935 int n = 0;
937 for (k = num_vars; k >= 0; k--)
938 if (eqn->coef[k])
939 packing[n++] = k;
941 return n;
944 /* Computes a linear combination of EQ and SUB at VAR with coefficient
945 C, such that EQ->coef[VAR] is set to 0. TOP_VAR is the number of
946 non null indices of SUB stored in PACKING. */
948 static inline void
949 omega_substitute_red_1 (eqn eq, eqn sub, int var, int c, bool *found_black,
950 int top_var)
952 if (eq->coef[var] != 0)
954 if (eq->color == omega_black)
955 *found_black = true;
956 else
958 int j, k = eq->coef[var];
960 eq->coef[var] = 0;
962 for (j = top_var; j >= 0; j--)
963 eq->coef[packing[j]] -= sub->coef[packing[j]] * k * c;
968 /* Substitute in PB variable VAR with "C * SUB". */
970 static void
971 omega_substitute_red (omega_pb pb, eqn sub, int var, int c, bool *found_black)
973 int e, top_var = setup_packing (sub, pb->num_vars);
975 *found_black = false;
977 if (dump_file && (dump_flags & TDF_DETAILS))
979 if (sub->color == omega_red)
980 fprintf (dump_file, "[");
982 fprintf (dump_file, "substituting using %s := ",
983 omega_variable_to_str (pb, var));
984 omega_print_term (dump_file, pb, sub, -c);
986 if (sub->color == omega_red)
987 fprintf (dump_file, "]");
989 fprintf (dump_file, "\n");
990 omega_print_vars (dump_file, pb);
993 for (e = pb->num_eqs - 1; e >= 0; e--)
995 eqn eqn = &(pb->eqs[e]);
997 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
999 if (dump_file && (dump_flags & TDF_DETAILS))
1001 omega_print_eq (dump_file, pb, eqn);
1002 fprintf (dump_file, "\n");
1006 for (e = pb->num_geqs - 1; e >= 0; e--)
1008 eqn eqn = &(pb->geqs[e]);
1010 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
1012 if (eqn->coef[var] && eqn->color == omega_red)
1013 eqn->touched = 1;
1015 if (dump_file && (dump_flags & TDF_DETAILS))
1017 omega_print_geq (dump_file, pb, eqn);
1018 fprintf (dump_file, "\n");
1022 for (e = pb->num_subs - 1; e >= 0; e--)
1024 eqn eqn = &(pb->subs[e]);
1026 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
1028 if (dump_file && (dump_flags & TDF_DETAILS))
1030 fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
1031 omega_print_term (dump_file, pb, eqn, 1);
1032 fprintf (dump_file, "\n");
1036 if (dump_file && (dump_flags & TDF_DETAILS))
1037 fprintf (dump_file, "---\n\n");
1039 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1040 *found_black = true;
1043 /* Substitute in PB variable VAR with "C * SUB". */
1045 static void
1046 omega_substitute (omega_pb pb, eqn sub, int var, int c)
1048 int e, j, j0;
1049 int top_var = setup_packing (sub, pb->num_vars);
1051 if (dump_file && (dump_flags & TDF_DETAILS))
1053 fprintf (dump_file, "substituting using %s := ",
1054 omega_variable_to_str (pb, var));
1055 omega_print_term (dump_file, pb, sub, -c);
1056 fprintf (dump_file, "\n");
1057 omega_print_vars (dump_file, pb);
1060 if (top_var < 0)
1062 for (e = pb->num_eqs - 1; e >= 0; e--)
1063 pb->eqs[e].coef[var] = 0;
1065 for (e = pb->num_geqs - 1; e >= 0; e--)
1066 if (pb->geqs[e].coef[var] != 0)
1068 pb->geqs[e].touched = 1;
1069 pb->geqs[e].coef[var] = 0;
1072 for (e = pb->num_subs - 1; e >= 0; e--)
1073 pb->subs[e].coef[var] = 0;
1075 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1077 int k;
1078 eqn eqn = &(pb->subs[pb->num_subs++]);
1080 for (k = pb->num_vars; k >= 0; k--)
1081 eqn->coef[k] = 0;
1083 eqn->key = pb->var[var];
1084 eqn->color = omega_black;
1087 else if (top_var == 0 && packing[0] == 0)
1089 c = -sub->coef[0] * c;
1091 for (e = pb->num_eqs - 1; e >= 0; e--)
1093 pb->eqs[e].coef[0] += pb->eqs[e].coef[var] * c;
1094 pb->eqs[e].coef[var] = 0;
1097 for (e = pb->num_geqs - 1; e >= 0; e--)
1098 if (pb->geqs[e].coef[var] != 0)
1100 pb->geqs[e].coef[0] += pb->geqs[e].coef[var] * c;
1101 pb->geqs[e].coef[var] = 0;
1102 pb->geqs[e].touched = 1;
1105 for (e = pb->num_subs - 1; e >= 0; e--)
1107 pb->subs[e].coef[0] += pb->subs[e].coef[var] * c;
1108 pb->subs[e].coef[var] = 0;
1111 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1113 int k;
1114 eqn eqn = &(pb->subs[pb->num_subs++]);
1116 for (k = pb->num_vars; k >= 1; k--)
1117 eqn->coef[k] = 0;
1119 eqn->coef[0] = c;
1120 eqn->key = pb->var[var];
1121 eqn->color = omega_black;
1124 if (dump_file && (dump_flags & TDF_DETAILS))
1126 fprintf (dump_file, "---\n\n");
1127 omega_print_problem (dump_file, pb);
1128 fprintf (dump_file, "===\n\n");
1131 else
1133 for (e = pb->num_eqs - 1; e >= 0; e--)
1135 eqn eqn = &(pb->eqs[e]);
1136 int k = eqn->coef[var];
1138 if (k != 0)
1140 k = c * k;
1141 eqn->coef[var] = 0;
1143 for (j = top_var; j >= 0; j--)
1145 j0 = packing[j];
1146 eqn->coef[j0] -= sub->coef[j0] * k;
1150 if (dump_file && (dump_flags & TDF_DETAILS))
1152 omega_print_eq (dump_file, pb, eqn);
1153 fprintf (dump_file, "\n");
1157 for (e = pb->num_geqs - 1; e >= 0; e--)
1159 eqn eqn = &(pb->geqs[e]);
1160 int k = eqn->coef[var];
1162 if (k != 0)
1164 k = c * k;
1165 eqn->touched = 1;
1166 eqn->coef[var] = 0;
1168 for (j = top_var; j >= 0; j--)
1170 j0 = packing[j];
1171 eqn->coef[j0] -= sub->coef[j0] * k;
1175 if (dump_file && (dump_flags & TDF_DETAILS))
1177 omega_print_geq (dump_file, pb, eqn);
1178 fprintf (dump_file, "\n");
1182 for (e = pb->num_subs - 1; e >= 0; e--)
1184 eqn eqn = &(pb->subs[e]);
1185 int k = eqn->coef[var];
1187 if (k != 0)
1189 k = c * k;
1190 eqn->coef[var] = 0;
1192 for (j = top_var; j >= 0; j--)
1194 j0 = packing[j];
1195 eqn->coef[j0] -= sub->coef[j0] * k;
1199 if (dump_file && (dump_flags & TDF_DETAILS))
1201 fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
1202 omega_print_term (dump_file, pb, eqn, 1);
1203 fprintf (dump_file, "\n");
1207 if (dump_file && (dump_flags & TDF_DETAILS))
1209 fprintf (dump_file, "---\n\n");
1210 omega_print_problem (dump_file, pb);
1211 fprintf (dump_file, "===\n\n");
1214 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1216 int k;
1217 eqn eqn = &(pb->subs[pb->num_subs++]);
1218 c = -c;
1220 for (k = pb->num_vars; k >= 0; k--)
1221 eqn->coef[k] = c * (sub->coef[k]);
1223 eqn->key = pb->var[var];
1224 eqn->color = sub->color;
1229 /* Solve e = factor alpha for x_j and substitute. */
1231 static void
1232 omega_do_mod (omega_pb pb, int factor, int e, int j)
1234 int k, i;
1235 eqn eq = omega_alloc_eqns (0, 1);
1236 int nfactor;
1237 bool kill_j = false;
1239 omega_copy_eqn (eq, &pb->eqs[e], pb->num_vars);
1241 for (k = pb->num_vars; k >= 0; k--)
1243 eq->coef[k] = int_mod (eq->coef[k], factor);
1245 if (2 * eq->coef[k] >= factor)
1246 eq->coef[k] -= factor;
1249 nfactor = eq->coef[j];
1251 if (omega_safe_var_p (pb, j) && !omega_wildcard_p (pb, j))
1253 i = omega_add_new_wild_card (pb);
1254 eq->coef[pb->num_vars] = eq->coef[i];
1255 eq->coef[j] = 0;
1256 eq->coef[i] = -factor;
1257 kill_j = true;
1259 else
1261 eq->coef[j] = -factor;
1262 if (!omega_wildcard_p (pb, j))
1263 omega_name_wild_card (pb, j);
1266 omega_substitute (pb, eq, j, nfactor);
1268 for (k = pb->num_vars; k >= 0; k--)
1269 pb->eqs[e].coef[k] = pb->eqs[e].coef[k] / factor;
1271 if (kill_j)
1272 omega_delete_variable (pb, j);
1274 if (dump_file && (dump_flags & TDF_DETAILS))
1276 fprintf (dump_file, "Mod-ing and normalizing produces:\n");
1277 omega_print_problem (dump_file, pb);
1280 omega_free_eqns (eq, 1);
1283 /* Multiplies by -1 inequality E. */
1285 void
1286 omega_negate_geq (omega_pb pb, int e)
1288 int i;
1290 for (i = pb->num_vars; i >= 0; i--)
1291 pb->geqs[e].coef[i] *= -1;
1293 pb->geqs[e].coef[0]--;
1294 pb->geqs[e].touched = 1;
1297 /* Returns OMEGA_TRUE when problem PB has a solution. */
1299 static enum omega_result
1300 verify_omega_pb (omega_pb pb)
1302 enum omega_result result;
1303 int e;
1304 bool any_color = false;
1305 omega_pb tmp_problem = XNEW (struct omega_pb_d);
1307 omega_copy_problem (tmp_problem, pb);
1308 tmp_problem->safe_vars = 0;
1309 tmp_problem->num_subs = 0;
1311 for (e = pb->num_geqs - 1; e >= 0; e--)
1312 if (pb->geqs[e].color == omega_red)
1314 any_color = true;
1315 break;
1318 if (please_no_equalities_in_simplified_problems)
1319 any_color = true;
1321 if (any_color)
1322 original_problem = no_problem;
1323 else
1324 original_problem = pb;
1326 if (dump_file && (dump_flags & TDF_DETAILS))
1328 fprintf (dump_file, "verifying problem");
1330 if (any_color)
1331 fprintf (dump_file, " (color mode)");
1333 fprintf (dump_file, " :\n");
1334 omega_print_problem (dump_file, pb);
1337 result = omega_solve_problem (tmp_problem, omega_unknown);
1338 original_problem = no_problem;
1339 free (tmp_problem);
1341 if (dump_file && (dump_flags & TDF_DETAILS))
1343 if (result != omega_false)
1344 fprintf (dump_file, "verified problem\n");
1345 else
1346 fprintf (dump_file, "disproved problem\n");
1347 omega_print_problem (dump_file, pb);
1350 return result;
1353 /* Add a new equality to problem PB at last position E. */
1355 static void
1356 adding_equality_constraint (omega_pb pb, int e)
1358 if (original_problem != no_problem
1359 && original_problem != pb
1360 && !conservative)
1362 int i, j;
1363 int e2 = original_problem->num_eqs++;
1365 if (dump_file && (dump_flags & TDF_DETAILS))
1366 fprintf (dump_file,
1367 "adding equality constraint %d to outer problem\n", e2);
1368 omega_init_eqn_zero (&original_problem->eqs[e2],
1369 original_problem->num_vars);
1371 for (i = pb->num_vars; i >= 1; i--)
1373 for (j = original_problem->num_vars; j >= 1; j--)
1374 if (original_problem->var[j] == pb->var[i])
1375 break;
1377 if (j <= 0)
1379 if (dump_file && (dump_flags & TDF_DETAILS))
1380 fprintf (dump_file, "retracting\n");
1381 original_problem->num_eqs--;
1382 return;
1384 original_problem->eqs[e2].coef[j] = pb->eqs[e].coef[i];
1387 original_problem->eqs[e2].coef[0] = pb->eqs[e].coef[0];
1389 if (dump_file && (dump_flags & TDF_DETAILS))
1390 omega_print_problem (dump_file, original_problem);
1394 static int *fast_lookup;
1395 static int *fast_lookup_red;
1397 typedef enum {
1398 normalize_false,
1399 normalize_uncoupled,
1400 normalize_coupled
1401 } normalize_return_type;
1403 /* Normalizes PB by removing redundant constraints. Returns
1404 normalize_false when the constraints system has no solution,
1405 otherwise returns normalize_coupled or normalize_uncoupled. */
1407 static normalize_return_type
1408 normalize_omega_problem (omega_pb pb)
1410 int e, i, j, k, n_vars;
1411 int coupled_subscripts = 0;
1413 n_vars = pb->num_vars;
1415 for (e = 0; e < pb->num_geqs; e++)
1417 if (!pb->geqs[e].touched)
1419 if (!single_var_geq (&pb->geqs[e], n_vars))
1420 coupled_subscripts = 1;
1422 else
1424 int g, top_var, i0, hashCode;
1425 int *p = &packing[0];
1427 for (k = 1; k <= n_vars; k++)
1428 if (pb->geqs[e].coef[k])
1429 *(p++) = k;
1431 top_var = (p - &packing[0]) - 1;
1433 if (top_var == -1)
1435 if (pb->geqs[e].coef[0] < 0)
1437 if (dump_file && (dump_flags & TDF_DETAILS))
1439 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1440 fprintf (dump_file, "\nequations have no solution \n");
1442 return normalize_false;
1445 omega_delete_geq (pb, e, n_vars);
1446 e--;
1447 continue;
1449 else if (top_var == 0)
1451 int singlevar = packing[0];
1453 g = pb->geqs[e].coef[singlevar];
1455 if (g > 0)
1457 pb->geqs[e].coef[singlevar] = 1;
1458 pb->geqs[e].key = singlevar;
1460 else
1462 g = -g;
1463 pb->geqs[e].coef[singlevar] = -1;
1464 pb->geqs[e].key = -singlevar;
1467 if (g > 1)
1468 pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1470 else
1472 int g2;
1473 int hash_key_multiplier = 31;
1475 coupled_subscripts = 1;
1476 i0 = top_var;
1477 i = packing[i0--];
1478 g = pb->geqs[e].coef[i];
1479 hashCode = g * (i + 3);
1481 if (g < 0)
1482 g = -g;
1484 for (; i0 >= 0; i0--)
1486 int x;
1488 i = packing[i0];
1489 x = pb->geqs[e].coef[i];
1490 hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1492 if (x < 0)
1493 x = -x;
1495 if (x == 1)
1497 g = 1;
1498 i0--;
1499 break;
1501 else
1502 g = gcd (x, g);
1505 for (; i0 >= 0; i0--)
1507 int x;
1508 i = packing[i0];
1509 x = pb->geqs[e].coef[i];
1510 hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1513 if (g > 1)
1515 pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1516 i0 = top_var;
1517 i = packing[i0--];
1518 pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1519 hashCode = pb->geqs[e].coef[i] * (i + 3);
1521 for (; i0 >= 0; i0--)
1523 i = packing[i0];
1524 pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1525 hashCode = hashCode * hash_key_multiplier * (i + 3)
1526 + pb->geqs[e].coef[i];
1530 g2 = abs (hashCode);
1532 if (dump_file && (dump_flags & TDF_DETAILS))
1534 fprintf (dump_file, "Hash code = %d, eqn = ", hashCode);
1535 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1536 fprintf (dump_file, "\n");
1539 j = g2 % HASH_TABLE_SIZE;
1541 do {
1542 eqn proto = &(hash_master[j]);
1544 if (proto->touched == g2)
1546 if (proto->coef[0] == top_var)
1548 if (hashCode >= 0)
1549 for (i0 = top_var; i0 >= 0; i0--)
1551 i = packing[i0];
1553 if (pb->geqs[e].coef[i] != proto->coef[i])
1554 break;
1556 else
1557 for (i0 = top_var; i0 >= 0; i0--)
1559 i = packing[i0];
1561 if (pb->geqs[e].coef[i] != -proto->coef[i])
1562 break;
1565 if (i0 < 0)
1567 if (hashCode >= 0)
1568 pb->geqs[e].key = proto->key;
1569 else
1570 pb->geqs[e].key = -proto->key;
1571 break;
1575 else if (proto->touched < 0)
1577 omega_init_eqn_zero (proto, pb->num_vars);
1578 if (hashCode >= 0)
1579 for (i0 = top_var; i0 >= 0; i0--)
1581 i = packing[i0];
1582 proto->coef[i] = pb->geqs[e].coef[i];
1584 else
1585 for (i0 = top_var; i0 >= 0; i0--)
1587 i = packing[i0];
1588 proto->coef[i] = -pb->geqs[e].coef[i];
1591 proto->coef[0] = top_var;
1592 proto->touched = g2;
1594 if (dump_file && (dump_flags & TDF_DETAILS))
1595 fprintf (dump_file, " constraint key = %d\n",
1596 next_key);
1598 proto->key = next_key++;
1600 /* Too many hash keys generated. */
1601 gcc_assert (proto->key <= MAX_KEYS);
1603 if (hashCode >= 0)
1604 pb->geqs[e].key = proto->key;
1605 else
1606 pb->geqs[e].key = -proto->key;
1608 break;
1611 j = (j + 1) % HASH_TABLE_SIZE;
1612 } while (1);
1615 pb->geqs[e].touched = 0;
1619 int eKey = pb->geqs[e].key;
1620 int e2;
1621 if (e > 0)
1623 int cTerm = pb->geqs[e].coef[0];
1624 e2 = fast_lookup[MAX_KEYS - eKey];
1626 if (e2 < e && pb->geqs[e2].key == -eKey
1627 && pb->geqs[e2].color == omega_black)
1629 if (pb->geqs[e2].coef[0] < -cTerm)
1631 if (dump_file && (dump_flags & TDF_DETAILS))
1633 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1634 fprintf (dump_file, "\n");
1635 omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1636 fprintf (dump_file,
1637 "\nequations have no solution \n");
1639 return normalize_false;
1642 if (pb->geqs[e2].coef[0] == -cTerm
1643 && (create_color
1644 || pb->geqs[e].color == omega_black))
1646 omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1647 pb->num_vars);
1648 if (pb->geqs[e].color == omega_black)
1649 adding_equality_constraint (pb, pb->num_eqs);
1650 pb->num_eqs++;
1651 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1655 e2 = fast_lookup_red[MAX_KEYS - eKey];
1657 if (e2 < e && pb->geqs[e2].key == -eKey
1658 && pb->geqs[e2].color == omega_red)
1660 if (pb->geqs[e2].coef[0] < -cTerm)
1662 if (dump_file && (dump_flags & TDF_DETAILS))
1664 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1665 fprintf (dump_file, "\n");
1666 omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1667 fprintf (dump_file,
1668 "\nequations have no solution \n");
1670 return normalize_false;
1673 if (pb->geqs[e2].coef[0] == -cTerm && create_color)
1675 omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1676 pb->num_vars);
1677 pb->eqs[pb->num_eqs].color = omega_red;
1678 pb->num_eqs++;
1679 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1683 e2 = fast_lookup[MAX_KEYS + eKey];
1685 if (e2 < e && pb->geqs[e2].key == eKey
1686 && pb->geqs[e2].color == omega_black)
1688 if (pb->geqs[e2].coef[0] > cTerm)
1690 if (pb->geqs[e].color == omega_black)
1692 if (dump_file && (dump_flags & TDF_DETAILS))
1694 fprintf (dump_file,
1695 "Removing Redundant Equation: ");
1696 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1697 fprintf (dump_file, "\n");
1698 fprintf (dump_file,
1699 "[a] Made Redundant by: ");
1700 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1701 fprintf (dump_file, "\n");
1703 pb->geqs[e2].coef[0] = cTerm;
1704 omega_delete_geq (pb, e, n_vars);
1705 e--;
1706 continue;
1709 else
1711 if (dump_file && (dump_flags & TDF_DETAILS))
1713 fprintf (dump_file, "Removing Redundant Equation: ");
1714 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1715 fprintf (dump_file, "\n");
1716 fprintf (dump_file, "[b] Made Redundant by: ");
1717 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1718 fprintf (dump_file, "\n");
1720 omega_delete_geq (pb, e, n_vars);
1721 e--;
1722 continue;
1726 e2 = fast_lookup_red[MAX_KEYS + eKey];
1728 if (e2 < e && pb->geqs[e2].key == eKey
1729 && pb->geqs[e2].color == omega_red)
1731 if (pb->geqs[e2].coef[0] >= cTerm)
1733 if (dump_file && (dump_flags & TDF_DETAILS))
1735 fprintf (dump_file, "Removing Redundant Equation: ");
1736 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1737 fprintf (dump_file, "\n");
1738 fprintf (dump_file, "[c] Made Redundant by: ");
1739 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1740 fprintf (dump_file, "\n");
1742 pb->geqs[e2].coef[0] = cTerm;
1743 pb->geqs[e2].color = pb->geqs[e].color;
1745 else if (pb->geqs[e].color == omega_red)
1747 if (dump_file && (dump_flags & TDF_DETAILS))
1749 fprintf (dump_file, "Removing Redundant Equation: ");
1750 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1751 fprintf (dump_file, "\n");
1752 fprintf (dump_file, "[d] Made Redundant by: ");
1753 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1754 fprintf (dump_file, "\n");
1757 omega_delete_geq (pb, e, n_vars);
1758 e--;
1759 continue;
1764 if (pb->geqs[e].color == omega_red)
1765 fast_lookup_red[MAX_KEYS + eKey] = e;
1766 else
1767 fast_lookup[MAX_KEYS + eKey] = e;
1771 create_color = false;
1772 return coupled_subscripts ? normalize_coupled : normalize_uncoupled;
1775 /* Divide the coefficients of EQN by their gcd. N_VARS is the number
1776 of variables in EQN. */
1778 static inline void
1779 divide_eqn_by_gcd (eqn eqn, int n_vars)
1781 int var, g = 0;
1783 for (var = n_vars; var >= 0; var--)
1784 g = gcd (abs (eqn->coef[var]), g);
1786 if (g)
1787 for (var = n_vars; var >= 0; var--)
1788 eqn->coef[var] = eqn->coef[var] / g;
1791 /* Rewrite some non-safe variables in function of protected
1792 wildcard variables. */
1794 static void
1795 cleanout_wildcards (omega_pb pb)
1797 int e, i, j;
1798 int n_vars = pb->num_vars;
1799 bool renormalize = false;
1801 for (e = pb->num_eqs - 1; e >= 0; e--)
1802 for (i = n_vars; !omega_safe_var_p (pb, i); i--)
1803 if (pb->eqs[e].coef[i] != 0)
1805 /* i is the last nonzero non-safe variable. */
1807 for (j = i - 1; !omega_safe_var_p (pb, j); j--)
1808 if (pb->eqs[e].coef[j] != 0)
1809 break;
1811 /* j is the next nonzero non-safe variable, or points
1812 to a safe variable: it is then a wildcard variable. */
1814 /* Clean it out. */
1815 if (omega_safe_var_p (pb, j))
1817 eqn sub = &(pb->eqs[e]);
1818 int c = pb->eqs[e].coef[i];
1819 int a = abs (c);
1820 int e2;
1822 if (dump_file && (dump_flags & TDF_DETAILS))
1824 fprintf (dump_file,
1825 "Found a single wild card equality: ");
1826 omega_print_eq (dump_file, pb, &pb->eqs[e]);
1827 fprintf (dump_file, "\n");
1828 omega_print_problem (dump_file, pb);
1831 for (e2 = pb->num_eqs - 1; e2 >= 0; e2--)
1832 if (e != e2 && pb->eqs[e2].coef[i]
1833 && (pb->eqs[e2].color == omega_red
1834 || (pb->eqs[e2].color == omega_black
1835 && pb->eqs[e].color == omega_black)))
1837 eqn eqn = &(pb->eqs[e2]);
1838 int var, k;
1840 for (var = n_vars; var >= 0; var--)
1841 eqn->coef[var] *= a;
1843 k = eqn->coef[i];
1845 for (var = n_vars; var >= 0; var--)
1846 eqn->coef[var] -= sub->coef[var] * k / c;
1848 eqn->coef[i] = 0;
1849 divide_eqn_by_gcd (eqn, n_vars);
1852 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
1853 if (pb->geqs[e2].coef[i]
1854 && (pb->geqs[e2].color == omega_red
1855 || (pb->eqs[e].color == omega_black
1856 && pb->geqs[e2].color == omega_black)))
1858 eqn eqn = &(pb->geqs[e2]);
1859 int var, k;
1861 for (var = n_vars; var >= 0; var--)
1862 eqn->coef[var] *= a;
1864 k = eqn->coef[i];
1866 for (var = n_vars; var >= 0; var--)
1867 eqn->coef[var] -= sub->coef[var] * k / c;
1869 eqn->coef[i] = 0;
1870 eqn->touched = 1;
1871 renormalize = true;
1874 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
1875 if (pb->subs[e2].coef[i]
1876 && (pb->subs[e2].color == omega_red
1877 || (pb->subs[e2].color == omega_black
1878 && pb->eqs[e].color == omega_black)))
1880 eqn eqn = &(pb->subs[e2]);
1881 int var, k;
1883 for (var = n_vars; var >= 0; var--)
1884 eqn->coef[var] *= a;
1886 k = eqn->coef[i];
1888 for (var = n_vars; var >= 0; var--)
1889 eqn->coef[var] -= sub->coef[var] * k / c;
1891 eqn->coef[i] = 0;
1892 divide_eqn_by_gcd (eqn, n_vars);
1895 if (dump_file && (dump_flags & TDF_DETAILS))
1897 fprintf (dump_file, "cleaned-out wildcard: ");
1898 omega_print_problem (dump_file, pb);
1900 break;
1904 if (renormalize)
1905 normalize_omega_problem (pb);
1908 /* Swap values contained in I and J. */
1910 static inline void
1911 swap (int *i, int *j)
1913 int tmp;
1914 tmp = *i;
1915 *i = *j;
1916 *j = tmp;
1919 /* Swap values contained in I and J. */
1921 static inline void
1922 bswap (bool *i, bool *j)
1924 bool tmp;
1925 tmp = *i;
1926 *i = *j;
1927 *j = tmp;
1930 /* Make variable IDX unprotected in PB, by swapping its index at the
1931 PB->safe_vars rank. */
1933 static inline void
1934 omega_unprotect_1 (omega_pb pb, int *idx, bool *unprotect)
1936 /* If IDX is protected... */
1937 if (*idx < pb->safe_vars)
1939 /* ... swap its index with the last non protected index. */
1940 int j = pb->safe_vars;
1941 int e;
1943 for (e = pb->num_geqs - 1; e >= 0; e--)
1945 pb->geqs[e].touched = 1;
1946 swap (&pb->geqs[e].coef[*idx], &pb->geqs[e].coef[j]);
1949 for (e = pb->num_eqs - 1; e >= 0; e--)
1950 swap (&pb->eqs[e].coef[*idx], &pb->eqs[e].coef[j]);
1952 for (e = pb->num_subs - 1; e >= 0; e--)
1953 swap (&pb->subs[e].coef[*idx], &pb->subs[e].coef[j]);
1955 if (unprotect)
1956 bswap (&unprotect[*idx], &unprotect[j]);
1958 swap (&pb->var[*idx], &pb->var[j]);
1959 pb->forwarding_address[pb->var[*idx]] = *idx;
1960 pb->forwarding_address[pb->var[j]] = j;
1961 (*idx)--;
1964 /* The variable at pb->safe_vars is also unprotected now. */
1965 pb->safe_vars--;
1968 /* During the Fourier-Motzkin elimination some variables are
1969 substituted with other variables. This function resurrects the
1970 substituted variables in PB. */
1972 static void
1973 resurrect_subs (omega_pb pb)
1975 if (pb->num_subs > 0
1976 && please_no_equalities_in_simplified_problems == 0)
1978 int i, e, m;
1980 if (dump_file && (dump_flags & TDF_DETAILS))
1982 fprintf (dump_file,
1983 "problem reduced, bringing variables back to life\n");
1984 omega_print_problem (dump_file, pb);
1987 for (i = 1; omega_safe_var_p (pb, i); i++)
1988 if (omega_wildcard_p (pb, i))
1989 omega_unprotect_1 (pb, &i, NULL);
1991 m = pb->num_subs;
1993 for (e = pb->num_geqs - 1; e >= 0; e--)
1994 if (single_var_geq (&pb->geqs[e], pb->num_vars))
1996 if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
1997 pb->geqs[e].key += (pb->geqs[e].key > 0 ? m : -m);
1999 else
2001 pb->geqs[e].touched = 1;
2002 pb->geqs[e].key = 0;
2005 for (i = pb->num_vars; !omega_safe_var_p (pb, i); i--)
2007 pb->var[i + m] = pb->var[i];
2009 for (e = pb->num_geqs - 1; e >= 0; e--)
2010 pb->geqs[e].coef[i + m] = pb->geqs[e].coef[i];
2012 for (e = pb->num_eqs - 1; e >= 0; e--)
2013 pb->eqs[e].coef[i + m] = pb->eqs[e].coef[i];
2015 for (e = pb->num_subs - 1; e >= 0; e--)
2016 pb->subs[e].coef[i + m] = pb->subs[e].coef[i];
2019 for (i = pb->safe_vars + m; !omega_safe_var_p (pb, i); i--)
2021 for (e = pb->num_geqs - 1; e >= 0; e--)
2022 pb->geqs[e].coef[i] = 0;
2024 for (e = pb->num_eqs - 1; e >= 0; e--)
2025 pb->eqs[e].coef[i] = 0;
2027 for (e = pb->num_subs - 1; e >= 0; e--)
2028 pb->subs[e].coef[i] = 0;
2031 pb->num_vars += m;
2033 for (e = pb->num_subs - 1; e >= 0; e--)
2035 pb->var[pb->safe_vars + 1 + e] = pb->subs[e].key;
2036 omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e]),
2037 pb->num_vars);
2038 pb->eqs[pb->num_eqs].coef[pb->safe_vars + 1 + e] = -1;
2039 pb->eqs[pb->num_eqs].color = omega_black;
2041 if (dump_file && (dump_flags & TDF_DETAILS))
2043 fprintf (dump_file, "brought back: ");
2044 omega_print_eq (dump_file, pb, &pb->eqs[pb->num_eqs]);
2045 fprintf (dump_file, "\n");
2048 pb->num_eqs++;
2049 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2052 pb->safe_vars += m;
2053 pb->num_subs = 0;
2055 if (dump_file && (dump_flags & TDF_DETAILS))
2057 fprintf (dump_file, "variables brought back to life\n");
2058 omega_print_problem (dump_file, pb);
2061 cleanout_wildcards (pb);
2065 static inline bool
2066 implies (unsigned int a, unsigned int b)
2068 return (a == (a & b));
2071 /* Eliminate redundant equations in PB. When EXPENSIVE is true, an
2072 extra step is performed. Returns omega_false when there exist no
2073 solution, omega_true otherwise. */
2075 enum omega_result
2076 omega_eliminate_redundant (omega_pb pb, bool expensive)
2078 int c, e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3;
2079 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2080 omega_pb tmp_problem;
2082 /* {P,Z,N}EQS = {Positive,Zero,Negative} Equations. */
2083 unsigned int *peqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2084 unsigned int *zeqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2085 unsigned int *neqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2087 /* PP = Possible Positives, PZ = Possible Zeros, PN = Possible Negatives */
2088 unsigned int pp, pz, pn;
2090 if (dump_file && (dump_flags & TDF_DETAILS))
2092 fprintf (dump_file, "in eliminate Redundant:\n");
2093 omega_print_problem (dump_file, pb);
2096 for (e = pb->num_geqs - 1; e >= 0; e--)
2098 int tmp = 1;
2100 is_dead[e] = false;
2101 peqs[e] = zeqs[e] = neqs[e] = 0;
2103 for (i = pb->num_vars; i >= 1; i--)
2105 if (pb->geqs[e].coef[i] > 0)
2106 peqs[e] |= tmp;
2107 else if (pb->geqs[e].coef[i] < 0)
2108 neqs[e] |= tmp;
2109 else
2110 zeqs[e] |= tmp;
2112 tmp <<= 1;
2117 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2118 if (!is_dead[e1])
2119 for (e2 = e1 - 1; e2 >= 0; e2--)
2120 if (!is_dead[e2])
2122 for (p = pb->num_vars; p > 1; p--)
2123 for (q = p - 1; q > 0; q--)
2124 if ((alpha = pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q]
2125 - pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]) != 0)
2126 goto foundPQ;
2128 continue;
2130 foundPQ:
2131 pz = ((zeqs[e1] & zeqs[e2]) | (peqs[e1] & neqs[e2])
2132 | (neqs[e1] & peqs[e2]));
2133 pp = peqs[e1] | peqs[e2];
2134 pn = neqs[e1] | neqs[e2];
2136 for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2137 if (e3 != e1 && e3 != e2)
2139 if (!implies (zeqs[e3], pz))
2140 goto nextE3;
2142 alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2143 - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2144 alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2145 - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2146 alpha3 = alpha;
2148 if (alpha1 * alpha2 <= 0)
2149 goto nextE3;
2151 if (alpha1 < 0)
2153 alpha1 = -alpha1;
2154 alpha2 = -alpha2;
2155 alpha3 = -alpha3;
2158 if (alpha3 > 0)
2160 /* Trying to prove e3 is redundant. */
2161 if (!implies (peqs[e3], pp)
2162 || !implies (neqs[e3], pn))
2163 goto nextE3;
2165 if (pb->geqs[e3].color == omega_black
2166 && (pb->geqs[e1].color == omega_red
2167 || pb->geqs[e2].color == omega_red))
2168 goto nextE3;
2170 for (k = pb->num_vars; k >= 1; k--)
2171 if (alpha3 * pb->geqs[e3].coef[k]
2172 != (alpha1 * pb->geqs[e1].coef[k]
2173 + alpha2 * pb->geqs[e2].coef[k]))
2174 goto nextE3;
2176 c = (alpha1 * pb->geqs[e1].coef[0]
2177 + alpha2 * pb->geqs[e2].coef[0]);
2179 if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2181 if (dump_file && (dump_flags & TDF_DETAILS))
2183 fprintf (dump_file,
2184 "found redundant inequality\n");
2185 fprintf (dump_file,
2186 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2187 alpha1, alpha2, alpha3);
2189 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2190 fprintf (dump_file, "\n");
2191 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2192 fprintf (dump_file, "\n=> ");
2193 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2194 fprintf (dump_file, "\n\n");
2197 is_dead[e3] = true;
2200 else
2202 /* Trying to prove e3 <= 0 and therefore e3 = 0,
2203 or trying to prove e3 < 0, and therefore the
2204 problem has no solutions. */
2205 if (!implies (peqs[e3], pn)
2206 || !implies (neqs[e3], pp))
2207 goto nextE3;
2209 if (pb->geqs[e1].color == omega_red
2210 || pb->geqs[e2].color == omega_red
2211 || pb->geqs[e3].color == omega_red)
2212 goto nextE3;
2214 /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */
2215 for (k = pb->num_vars; k >= 1; k--)
2216 if (alpha3 * pb->geqs[e3].coef[k]
2217 != (alpha1 * pb->geqs[e1].coef[k]
2218 + alpha2 * pb->geqs[e2].coef[k]))
2219 goto nextE3;
2221 c = (alpha1 * pb->geqs[e1].coef[0]
2222 + alpha2 * pb->geqs[e2].coef[0]);
2224 if (c < alpha3 * (pb->geqs[e3].coef[0]))
2226 /* We just proved e3 < 0, so no solutions exist. */
2227 if (dump_file && (dump_flags & TDF_DETAILS))
2229 fprintf (dump_file,
2230 "found implied over tight inequality\n");
2231 fprintf (dump_file,
2232 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2233 alpha1, alpha2, -alpha3);
2234 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2235 fprintf (dump_file, "\n");
2236 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2237 fprintf (dump_file, "\n=> not ");
2238 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2239 fprintf (dump_file, "\n\n");
2241 free (is_dead);
2242 free (peqs);
2243 free (zeqs);
2244 free (neqs);
2245 return omega_false;
2247 else if (c < alpha3 * (pb->geqs[e3].coef[0] - 1))
2249 /* We just proved that e3 <=0, so e3 = 0. */
2250 if (dump_file && (dump_flags & TDF_DETAILS))
2252 fprintf (dump_file,
2253 "found implied tight inequality\n");
2254 fprintf (dump_file,
2255 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2256 alpha1, alpha2, -alpha3);
2257 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2258 fprintf (dump_file, "\n");
2259 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2260 fprintf (dump_file, "\n=> inverse ");
2261 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2262 fprintf (dump_file, "\n\n");
2265 omega_copy_eqn (&pb->eqs[pb->num_eqs++],
2266 &pb->geqs[e3], pb->num_vars);
2267 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2268 adding_equality_constraint (pb, pb->num_eqs - 1);
2269 is_dead[e3] = true;
2272 nextE3:;
2276 /* Delete the inequalities that were marked as dead. */
2277 for (e = pb->num_geqs - 1; e >= 0; e--)
2278 if (is_dead[e])
2279 omega_delete_geq (pb, e, pb->num_vars);
2281 if (!expensive)
2282 goto eliminate_redundant_done;
2284 tmp_problem = XNEW (struct omega_pb_d);
2285 conservative++;
2287 for (e = pb->num_geqs - 1; e >= 0; e--)
2289 if (dump_file && (dump_flags & TDF_DETAILS))
2291 fprintf (dump_file,
2292 "checking equation %d to see if it is redundant: ", e);
2293 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2294 fprintf (dump_file, "\n");
2297 omega_copy_problem (tmp_problem, pb);
2298 omega_negate_geq (tmp_problem, e);
2299 tmp_problem->safe_vars = 0;
2300 tmp_problem->variables_freed = false;
2302 if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2303 omega_delete_geq (pb, e, pb->num_vars);
2306 free (tmp_problem);
2307 conservative--;
2309 if (!omega_reduce_with_subs)
2311 resurrect_subs (pb);
2312 gcc_assert (please_no_equalities_in_simplified_problems
2313 || pb->num_subs == 0);
2316 eliminate_redundant_done:
2317 free (is_dead);
2318 free (peqs);
2319 free (zeqs);
2320 free (neqs);
2321 return omega_true;
2324 /* For each inequality that has coefficients bigger than 20, try to
2325 create a new constraint that cannot be derived from the original
2326 constraint and that has smaller coefficients. Add the new
2327 constraint at the end of geqs. Return the number of inequalities
2328 that have been added to PB. */
2330 static int
2331 smooth_weird_equations (omega_pb pb)
2333 int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3;
2334 int c;
2335 int v;
2336 int result = 0;
2338 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2339 if (pb->geqs[e1].color == omega_black)
2341 int g = 999999;
2343 for (v = pb->num_vars; v >= 1; v--)
2344 if (pb->geqs[e1].coef[v] != 0 && abs (pb->geqs[e1].coef[v]) < g)
2345 g = abs (pb->geqs[e1].coef[v]);
2347 /* Magic number. */
2348 if (g > 20)
2350 e3 = pb->num_geqs;
2352 for (v = pb->num_vars; v >= 1; v--)
2353 pb->geqs[e3].coef[v] = int_div (6 * pb->geqs[e1].coef[v] + g / 2,
2356 pb->geqs[e3].color = omega_black;
2357 pb->geqs[e3].touched = 1;
2358 /* Magic number. */
2359 pb->geqs[e3].coef[0] = 9997;
2361 if (dump_file && (dump_flags & TDF_DETAILS))
2363 fprintf (dump_file, "Checking to see if we can derive: ");
2364 omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2365 fprintf (dump_file, "\n from: ");
2366 omega_print_geq (dump_file, pb, &pb->geqs[e1]);
2367 fprintf (dump_file, "\n");
2370 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
2371 if (e1 != e2 && pb->geqs[e2].color == omega_black)
2373 for (p = pb->num_vars; p > 1; p--)
2375 for (q = p - 1; q > 0; q--)
2377 alpha =
2378 (pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q] -
2379 pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]);
2380 if (alpha != 0)
2381 goto foundPQ;
2384 continue;
2386 foundPQ:
2388 alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2389 - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2390 alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2391 - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2392 alpha3 = alpha;
2394 if (alpha1 * alpha2 <= 0)
2395 continue;
2397 if (alpha1 < 0)
2399 alpha1 = -alpha1;
2400 alpha2 = -alpha2;
2401 alpha3 = -alpha3;
2404 if (alpha3 > 0)
2406 /* Try to prove e3 is redundant: verify
2407 alpha1*v1 + alpha2*v2 = alpha3*v3. */
2408 for (k = pb->num_vars; k >= 1; k--)
2409 if (alpha3 * pb->geqs[e3].coef[k]
2410 != (alpha1 * pb->geqs[e1].coef[k]
2411 + alpha2 * pb->geqs[e2].coef[k]))
2412 goto nextE2;
2414 c = alpha1 * pb->geqs[e1].coef[0]
2415 + alpha2 * pb->geqs[e2].coef[0];
2417 if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2418 pb->geqs[e3].coef[0] = int_div (c, alpha3);
2420 nextE2:;
2423 if (pb->geqs[e3].coef[0] < 9997)
2425 result++;
2426 pb->num_geqs++;
2428 if (dump_file && (dump_flags & TDF_DETAILS))
2430 fprintf (dump_file,
2431 "Smoothing weird equations; adding:\n");
2432 omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2433 fprintf (dump_file, "\nto:\n");
2434 omega_print_problem (dump_file, pb);
2435 fprintf (dump_file, "\n\n");
2440 return result;
2443 /* Replace tuples of inequalities, that define upper and lower half
2444 spaces, with an equation. */
2446 static void
2447 coalesce (omega_pb pb)
2449 int e, e2;
2450 int colors = 0;
2451 bool *is_dead;
2452 int found_something = 0;
2454 for (e = 0; e < pb->num_geqs; e++)
2455 if (pb->geqs[e].color == omega_red)
2456 colors++;
2458 if (colors < 2)
2459 return;
2461 is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2463 for (e = 0; e < pb->num_geqs; e++)
2464 is_dead[e] = false;
2466 for (e = 0; e < pb->num_geqs; e++)
2467 if (pb->geqs[e].color == omega_red
2468 && !pb->geqs[e].touched)
2469 for (e2 = e + 1; e2 < pb->num_geqs; e2++)
2470 if (!pb->geqs[e2].touched
2471 && pb->geqs[e].key == -pb->geqs[e2].key
2472 && pb->geqs[e].coef[0] == -pb->geqs[e2].coef[0]
2473 && pb->geqs[e2].color == omega_red)
2475 omega_copy_eqn (&pb->eqs[pb->num_eqs++], &pb->geqs[e],
2476 pb->num_vars);
2477 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2478 found_something++;
2479 is_dead[e] = true;
2480 is_dead[e2] = true;
2483 for (e = pb->num_geqs - 1; e >= 0; e--)
2484 if (is_dead[e])
2485 omega_delete_geq (pb, e, pb->num_vars);
2487 if (dump_file && (dump_flags & TDF_DETAILS) && found_something)
2489 fprintf (dump_file, "Coalesced pb->geqs into %d EQ's:\n",
2490 found_something);
2491 omega_print_problem (dump_file, pb);
2494 free (is_dead);
2497 /* Eliminate red inequalities from PB. When ELIMINATE_ALL is
2498 true, continue to eliminate all the red inequalities. */
2500 void
2501 omega_eliminate_red (omega_pb pb, bool eliminate_all)
2503 int e, e2, e3, i, j, k, a, alpha1, alpha2;
2504 int c = 0;
2505 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2506 int dead_count = 0;
2507 int red_found;
2508 omega_pb tmp_problem;
2510 if (dump_file && (dump_flags & TDF_DETAILS))
2512 fprintf (dump_file, "in eliminate RED:\n");
2513 omega_print_problem (dump_file, pb);
2516 if (pb->num_eqs > 0)
2517 omega_simplify_problem (pb);
2519 for (e = pb->num_geqs - 1; e >= 0; e--)
2520 is_dead[e] = false;
2522 for (e = pb->num_geqs - 1; e >= 0; e--)
2523 if (pb->geqs[e].color == omega_black && !is_dead[e])
2524 for (e2 = e - 1; e2 >= 0; e2--)
2525 if (pb->geqs[e2].color == omega_black
2526 && !is_dead[e2])
2528 a = 0;
2530 for (i = pb->num_vars; i > 1; i--)
2531 for (j = i - 1; j > 0; j--)
2532 if ((a = (pb->geqs[e].coef[i] * pb->geqs[e2].coef[j]
2533 - pb->geqs[e2].coef[i] * pb->geqs[e].coef[j])) != 0)
2534 goto found_pair;
2536 continue;
2538 found_pair:
2539 if (dump_file && (dump_flags & TDF_DETAILS))
2541 fprintf (dump_file,
2542 "found two equations to combine, i = %s, ",
2543 omega_variable_to_str (pb, i));
2544 fprintf (dump_file, "j = %s, alpha = %d\n",
2545 omega_variable_to_str (pb, j), a);
2546 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2547 fprintf (dump_file, "\n");
2548 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2549 fprintf (dump_file, "\n");
2552 for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2553 if (pb->geqs[e3].color == omega_red)
2555 alpha1 = (pb->geqs[e2].coef[j] * pb->geqs[e3].coef[i]
2556 - pb->geqs[e2].coef[i] * pb->geqs[e3].coef[j]);
2557 alpha2 = -(pb->geqs[e].coef[j] * pb->geqs[e3].coef[i]
2558 - pb->geqs[e].coef[i] * pb->geqs[e3].coef[j]);
2560 if ((a > 0 && alpha1 > 0 && alpha2 > 0)
2561 || (a < 0 && alpha1 < 0 && alpha2 < 0))
2563 if (dump_file && (dump_flags & TDF_DETAILS))
2565 fprintf (dump_file,
2566 "alpha1 = %d, alpha2 = %d;"
2567 "comparing against: ",
2568 alpha1, alpha2);
2569 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2570 fprintf (dump_file, "\n");
2573 for (k = pb->num_vars; k >= 0; k--)
2575 c = (alpha1 * pb->geqs[e].coef[k]
2576 + alpha2 * pb->geqs[e2].coef[k]);
2578 if (c != a * pb->geqs[e3].coef[k])
2579 break;
2581 if (dump_file && (dump_flags & TDF_DETAILS) && k > 0)
2582 fprintf (dump_file, " %s: %d, %d\n",
2583 omega_variable_to_str (pb, k), c,
2584 a * pb->geqs[e3].coef[k]);
2587 if (k < 0
2588 || (k == 0 &&
2589 ((a > 0 && c < a * pb->geqs[e3].coef[k])
2590 || (a < 0 && c > a * pb->geqs[e3].coef[k]))))
2592 if (dump_file && (dump_flags & TDF_DETAILS))
2594 dead_count++;
2595 fprintf (dump_file,
2596 "red equation#%d is dead "
2597 "(%d dead so far, %d remain)\n",
2598 e3, dead_count,
2599 pb->num_geqs - dead_count);
2600 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2601 fprintf (dump_file, "\n");
2602 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2603 fprintf (dump_file, "\n");
2604 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2605 fprintf (dump_file, "\n");
2607 is_dead[e3] = true;
2613 for (e = pb->num_geqs - 1; e >= 0; e--)
2614 if (is_dead[e])
2615 omega_delete_geq (pb, e, pb->num_vars);
2617 free (is_dead);
2619 if (dump_file && (dump_flags & TDF_DETAILS))
2621 fprintf (dump_file, "in eliminate RED, easy tests done:\n");
2622 omega_print_problem (dump_file, pb);
2625 for (red_found = 0, e = pb->num_geqs - 1; e >= 0; e--)
2626 if (pb->geqs[e].color == omega_red)
2627 red_found = 1;
2629 if (!red_found)
2631 if (dump_file && (dump_flags & TDF_DETAILS))
2632 fprintf (dump_file, "fast checks worked\n");
2634 if (!omega_reduce_with_subs)
2635 gcc_assert (please_no_equalities_in_simplified_problems
2636 || pb->num_subs == 0);
2638 return;
2641 if (!omega_verify_simplification
2642 && verify_omega_pb (pb) == omega_false)
2643 return;
2645 conservative++;
2646 tmp_problem = XNEW (struct omega_pb_d);
2648 for (e = pb->num_geqs - 1; e >= 0; e--)
2649 if (pb->geqs[e].color == omega_red)
2651 if (dump_file && (dump_flags & TDF_DETAILS))
2653 fprintf (dump_file,
2654 "checking equation %d to see if it is redundant: ", e);
2655 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2656 fprintf (dump_file, "\n");
2659 omega_copy_problem (tmp_problem, pb);
2660 omega_negate_geq (tmp_problem, e);
2661 tmp_problem->safe_vars = 0;
2662 tmp_problem->variables_freed = false;
2663 tmp_problem->num_subs = 0;
2665 if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2667 if (dump_file && (dump_flags & TDF_DETAILS))
2668 fprintf (dump_file, "it is redundant\n");
2669 omega_delete_geq (pb, e, pb->num_vars);
2671 else
2673 if (dump_file && (dump_flags & TDF_DETAILS))
2674 fprintf (dump_file, "it is not redundant\n");
2676 if (!eliminate_all)
2678 if (dump_file && (dump_flags & TDF_DETAILS))
2679 fprintf (dump_file, "no need to check other red equations\n");
2680 break;
2685 conservative--;
2686 free (tmp_problem);
2687 /* omega_simplify_problem (pb); */
2689 if (!omega_reduce_with_subs)
2690 gcc_assert (please_no_equalities_in_simplified_problems
2691 || pb->num_subs == 0);
2694 /* Transform some wildcard variables to non-safe variables. */
2696 static void
2697 chain_unprotect (omega_pb pb)
2699 int i, e;
2700 bool *unprotect = XNEWVEC (bool, OMEGA_MAX_VARS);
2702 for (i = 1; omega_safe_var_p (pb, i); i++)
2704 unprotect[i] = omega_wildcard_p (pb, i);
2706 for (e = pb->num_subs - 1; e >= 0; e--)
2707 if (pb->subs[e].coef[i])
2708 unprotect[i] = false;
2711 if (dump_file && (dump_flags & TDF_DETAILS))
2713 fprintf (dump_file, "Doing chain reaction unprotection\n");
2714 omega_print_problem (dump_file, pb);
2716 for (i = 1; omega_safe_var_p (pb, i); i++)
2717 if (unprotect[i])
2718 fprintf (dump_file, "unprotecting %s\n",
2719 omega_variable_to_str (pb, i));
2722 for (i = 1; omega_safe_var_p (pb, i); i++)
2723 if (unprotect[i])
2724 omega_unprotect_1 (pb, &i, unprotect);
2726 if (dump_file && (dump_flags & TDF_DETAILS))
2728 fprintf (dump_file, "After chain reactions\n");
2729 omega_print_problem (dump_file, pb);
2732 free (unprotect);
2735 /* Reduce problem PB. */
2737 static void
2738 omega_problem_reduced (omega_pb pb)
2740 if (omega_verify_simplification
2741 && !in_approximate_mode
2742 && verify_omega_pb (pb) == omega_false)
2743 return;
2745 if (PARAM_VALUE (PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS)
2746 && !omega_eliminate_redundant (pb, true))
2747 return;
2749 omega_found_reduction = omega_true;
2751 if (!please_no_equalities_in_simplified_problems)
2752 coalesce (pb);
2754 if (omega_reduce_with_subs
2755 || please_no_equalities_in_simplified_problems)
2756 chain_unprotect (pb);
2757 else
2758 resurrect_subs (pb);
2760 if (!return_single_result)
2762 int i;
2764 for (i = 1; omega_safe_var_p (pb, i); i++)
2765 pb->forwarding_address[pb->var[i]] = i;
2767 for (i = 0; i < pb->num_subs; i++)
2768 pb->forwarding_address[pb->subs[i].key] = -i - 1;
2770 (*omega_when_reduced) (pb);
2773 if (dump_file && (dump_flags & TDF_DETAILS))
2775 fprintf (dump_file, "-------------------------------------------\n");
2776 fprintf (dump_file, "problem reduced:\n");
2777 omega_print_problem (dump_file, pb);
2778 fprintf (dump_file, "-------------------------------------------\n");
2782 /* Eliminates all the free variables for problem PB, that is all the
2783 variables from FV to PB->NUM_VARS. */
2785 static void
2786 omega_free_eliminations (omega_pb pb, int fv)
2788 bool try_again = true;
2789 int i, e, e2;
2790 int n_vars = pb->num_vars;
2792 while (try_again)
2794 try_again = false;
2796 for (i = n_vars; i > fv; i--)
2798 for (e = pb->num_geqs - 1; e >= 0; e--)
2799 if (pb->geqs[e].coef[i])
2800 break;
2802 if (e < 0)
2803 e2 = e;
2804 else if (pb->geqs[e].coef[i] > 0)
2806 for (e2 = e - 1; e2 >= 0; e2--)
2807 if (pb->geqs[e2].coef[i] < 0)
2808 break;
2810 else
2812 for (e2 = e - 1; e2 >= 0; e2--)
2813 if (pb->geqs[e2].coef[i] > 0)
2814 break;
2817 if (e2 < 0)
2819 int e3;
2820 for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2821 if (pb->subs[e3].coef[i])
2822 break;
2824 if (e3 >= 0)
2825 continue;
2827 for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2828 if (pb->eqs[e3].coef[i])
2829 break;
2831 if (e3 >= 0)
2832 continue;
2834 if (dump_file && (dump_flags & TDF_DETAILS))
2835 fprintf (dump_file, "a free elimination of %s\n",
2836 omega_variable_to_str (pb, i));
2838 if (e >= 0)
2840 omega_delete_geq (pb, e, n_vars);
2842 for (e--; e >= 0; e--)
2843 if (pb->geqs[e].coef[i])
2844 omega_delete_geq (pb, e, n_vars);
2846 try_again = (i < n_vars);
2849 omega_delete_variable (pb, i);
2850 n_vars = pb->num_vars;
2855 if (dump_file && (dump_flags & TDF_DETAILS))
2857 fprintf (dump_file, "\nafter free eliminations:\n");
2858 omega_print_problem (dump_file, pb);
2859 fprintf (dump_file, "\n");
2863 /* Do free red eliminations. */
2865 static void
2866 free_red_eliminations (omega_pb pb)
2868 bool try_again = true;
2869 int i, e, e2;
2870 int n_vars = pb->num_vars;
2871 bool *is_red_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2872 bool *is_dead_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2873 bool *is_dead_geq = XNEWVEC (bool, OMEGA_MAX_GEQS);
2875 for (i = n_vars; i > 0; i--)
2877 is_red_var[i] = false;
2878 is_dead_var[i] = false;
2881 for (e = pb->num_geqs - 1; e >= 0; e--)
2883 is_dead_geq[e] = false;
2885 if (pb->geqs[e].color == omega_red)
2886 for (i = n_vars; i > 0; i--)
2887 if (pb->geqs[e].coef[i] != 0)
2888 is_red_var[i] = true;
2891 while (try_again)
2893 try_again = false;
2894 for (i = n_vars; i > 0; i--)
2895 if (!is_red_var[i] && !is_dead_var[i])
2897 for (e = pb->num_geqs - 1; e >= 0; e--)
2898 if (!is_dead_geq[e] && pb->geqs[e].coef[i])
2899 break;
2901 if (e < 0)
2902 e2 = e;
2903 else if (pb->geqs[e].coef[i] > 0)
2905 for (e2 = e - 1; e2 >= 0; e2--)
2906 if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] < 0)
2907 break;
2909 else
2911 for (e2 = e - 1; e2 >= 0; e2--)
2912 if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] > 0)
2913 break;
2916 if (e2 < 0)
2918 int e3;
2919 for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2920 if (pb->subs[e3].coef[i])
2921 break;
2923 if (e3 >= 0)
2924 continue;
2926 for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2927 if (pb->eqs[e3].coef[i])
2928 break;
2930 if (e3 >= 0)
2931 continue;
2933 if (dump_file && (dump_flags & TDF_DETAILS))
2934 fprintf (dump_file, "a free red elimination of %s\n",
2935 omega_variable_to_str (pb, i));
2937 for (; e >= 0; e--)
2938 if (pb->geqs[e].coef[i])
2939 is_dead_geq[e] = true;
2941 try_again = true;
2942 is_dead_var[i] = true;
2947 for (e = pb->num_geqs - 1; e >= 0; e--)
2948 if (is_dead_geq[e])
2949 omega_delete_geq (pb, e, n_vars);
2951 for (i = n_vars; i > 0; i--)
2952 if (is_dead_var[i])
2953 omega_delete_variable (pb, i);
2955 if (dump_file && (dump_flags & TDF_DETAILS))
2957 fprintf (dump_file, "\nafter free red eliminations:\n");
2958 omega_print_problem (dump_file, pb);
2959 fprintf (dump_file, "\n");
2962 free (is_red_var);
2963 free (is_dead_var);
2964 free (is_dead_geq);
2967 /* For equation EQ of the form "0 = EQN", insert in PB two
2968 inequalities "0 <= EQN" and "0 <= -EQN". */
2970 void
2971 omega_convert_eq_to_geqs (omega_pb pb, int eq)
2973 int i;
2975 if (dump_file && (dump_flags & TDF_DETAILS))
2976 fprintf (dump_file, "Converting Eq to Geqs\n");
2978 /* Insert "0 <= EQN". */
2979 omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2980 pb->geqs[pb->num_geqs].touched = 1;
2981 pb->num_geqs++;
2983 /* Insert "0 <= -EQN". */
2984 omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2985 pb->geqs[pb->num_geqs].touched = 1;
2987 for (i = 0; i <= pb->num_vars; i++)
2988 pb->geqs[pb->num_geqs].coef[i] *= -1;
2990 pb->num_geqs++;
2992 if (dump_file && (dump_flags & TDF_DETAILS))
2993 omega_print_problem (dump_file, pb);
2996 /* Eliminates variable I from PB. */
2998 static void
2999 omega_do_elimination (omega_pb pb, int e, int i)
3001 eqn sub = omega_alloc_eqns (0, 1);
3002 int c;
3003 int n_vars = pb->num_vars;
3005 if (dump_file && (dump_flags & TDF_DETAILS))
3006 fprintf (dump_file, "eliminating variable %s\n",
3007 omega_variable_to_str (pb, i));
3009 omega_copy_eqn (sub, &pb->eqs[e], pb->num_vars);
3010 c = sub->coef[i];
3011 sub->coef[i] = 0;
3012 if (c == 1 || c == -1)
3014 if (pb->eqs[e].color == omega_red)
3016 bool fB;
3017 omega_substitute_red (pb, sub, i, c, &fB);
3018 if (fB)
3019 omega_convert_eq_to_geqs (pb, e);
3020 else
3021 omega_delete_variable (pb, i);
3023 else
3025 omega_substitute (pb, sub, i, c);
3026 omega_delete_variable (pb, i);
3029 else
3031 int a = abs (c);
3032 int e2 = e;
3034 if (dump_file && (dump_flags & TDF_DETAILS))
3035 fprintf (dump_file, "performing non-exact elimination, c = %d\n", c);
3037 for (e = pb->num_eqs - 1; e >= 0; e--)
3038 if (pb->eqs[e].coef[i])
3040 eqn eqn = &(pb->eqs[e]);
3041 int j, k;
3042 for (j = n_vars; j >= 0; j--)
3043 eqn->coef[j] *= a;
3044 k = eqn->coef[i];
3045 eqn->coef[i] = 0;
3046 if (sub->color == omega_red)
3047 eqn->color = omega_red;
3048 for (j = n_vars; j >= 0; j--)
3049 eqn->coef[j] -= sub->coef[j] * k / c;
3052 for (e = pb->num_geqs - 1; e >= 0; e--)
3053 if (pb->geqs[e].coef[i])
3055 eqn eqn = &(pb->geqs[e]);
3056 int j, k;
3058 if (sub->color == omega_red)
3059 eqn->color = omega_red;
3061 for (j = n_vars; j >= 0; j--)
3062 eqn->coef[j] *= a;
3064 eqn->touched = 1;
3065 k = eqn->coef[i];
3066 eqn->coef[i] = 0;
3068 for (j = n_vars; j >= 0; j--)
3069 eqn->coef[j] -= sub->coef[j] * k / c;
3073 for (e = pb->num_subs - 1; e >= 0; e--)
3074 if (pb->subs[e].coef[i])
3076 eqn eqn = &(pb->subs[e]);
3077 int j, k;
3078 gcc_assert (0);
3079 gcc_assert (sub->color == omega_black);
3080 for (j = n_vars; j >= 0; j--)
3081 eqn->coef[j] *= a;
3082 k = eqn->coef[i];
3083 eqn->coef[i] = 0;
3084 for (j = n_vars; j >= 0; j--)
3085 eqn->coef[j] -= sub->coef[j] * k / c;
3088 if (in_approximate_mode)
3089 omega_delete_variable (pb, i);
3090 else
3091 omega_convert_eq_to_geqs (pb, e2);
3094 omega_free_eqns (sub, 1);
3097 /* Helper function for printing "sorry, no solution". */
3099 static inline enum omega_result
3100 omega_problem_has_no_solution (void)
3102 if (dump_file && (dump_flags & TDF_DETAILS))
3103 fprintf (dump_file, "\nequations have no solution \n");
3105 return omega_false;
3108 /* Helper function: solve equations in PB one at a time, following the
3109 DESIRED_RES result. */
3111 static enum omega_result
3112 omega_solve_eq (omega_pb pb, enum omega_result desired_res)
3114 int i, j, e;
3115 int g, g2;
3116 g = 0;
3119 if (dump_file && (dump_flags & TDF_DETAILS) && pb->num_eqs > 0)
3121 fprintf (dump_file, "\nomega_solve_eq (%d, %d)\n",
3122 desired_res, may_be_red);
3123 omega_print_problem (dump_file, pb);
3124 fprintf (dump_file, "\n");
3127 if (may_be_red)
3129 i = 0;
3130 j = pb->num_eqs - 1;
3132 while (1)
3134 eqn eq;
3136 while (i <= j && pb->eqs[i].color == omega_red)
3137 i++;
3139 while (i <= j && pb->eqs[j].color == omega_black)
3140 j--;
3142 if (i >= j)
3143 break;
3145 eq = omega_alloc_eqns (0, 1);
3146 omega_copy_eqn (eq, &pb->eqs[i], pb->num_vars);
3147 omega_copy_eqn (&pb->eqs[i], &pb->eqs[j], pb->num_vars);
3148 omega_copy_eqn (&pb->eqs[j], eq, pb->num_vars);
3149 omega_free_eqns (eq, 1);
3150 i++;
3151 j--;
3155 /* Eliminate all EQ equations */
3156 for (e = pb->num_eqs - 1; e >= 0; e--)
3158 eqn eqn = &(pb->eqs[e]);
3159 int sv;
3161 if (dump_file && (dump_flags & TDF_DETAILS))
3162 fprintf (dump_file, "----\n");
3164 for (i = pb->num_vars; i > 0; i--)
3165 if (eqn->coef[i])
3166 break;
3168 g = eqn->coef[i];
3170 for (j = i - 1; j > 0; j--)
3171 if (eqn->coef[j])
3172 break;
3174 /* i is the position of last nonzero coefficient,
3175 g is the coefficient of i,
3176 j is the position of next nonzero coefficient. */
3178 if (j == 0)
3180 if (eqn->coef[0] % g != 0)
3181 return omega_problem_has_no_solution ();
3183 eqn->coef[0] = eqn->coef[0] / g;
3184 eqn->coef[i] = 1;
3185 pb->num_eqs--;
3186 omega_do_elimination (pb, e, i);
3187 continue;
3190 else if (j == -1)
3192 if (eqn->coef[0] != 0)
3193 return omega_problem_has_no_solution ();
3195 pb->num_eqs--;
3196 continue;
3199 if (g < 0)
3200 g = -g;
3202 if (g == 1)
3204 pb->num_eqs--;
3205 omega_do_elimination (pb, e, i);
3208 else
3210 int k = j;
3211 bool promotion_possible =
3212 (omega_safe_var_p (pb, j)
3213 && pb->safe_vars + 1 == i
3214 && !omega_eqn_is_red (eqn, desired_res)
3215 && !in_approximate_mode);
3217 if (dump_file && (dump_flags & TDF_DETAILS) && promotion_possible)
3218 fprintf (dump_file, " Promotion possible\n");
3220 normalizeEQ:
3221 if (!omega_safe_var_p (pb, j))
3223 for (; g != 1 && !omega_safe_var_p (pb, j); j--)
3224 g = gcd (abs (eqn->coef[j]), g);
3225 g2 = g;
3227 else if (!omega_safe_var_p (pb, i))
3228 g2 = g;
3229 else
3230 g2 = 0;
3232 for (; g != 1 && j > 0; j--)
3233 g = gcd (abs (eqn->coef[j]), g);
3235 if (g > 1)
3237 if (eqn->coef[0] % g != 0)
3238 return omega_problem_has_no_solution ();
3240 for (j = 0; j <= pb->num_vars; j++)
3241 eqn->coef[j] /= g;
3243 g2 = g2 / g;
3246 if (g2 > 1)
3248 int e2;
3250 for (e2 = e - 1; e2 >= 0; e2--)
3251 if (pb->eqs[e2].coef[i])
3252 break;
3254 if (e2 == -1)
3255 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
3256 if (pb->geqs[e2].coef[i])
3257 break;
3259 if (e2 == -1)
3260 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
3261 if (pb->subs[e2].coef[i])
3262 break;
3264 if (e2 == -1)
3266 bool change = false;
3268 if (dump_file && (dump_flags & TDF_DETAILS))
3270 fprintf (dump_file, "Ha! We own it! \n");
3271 omega_print_eq (dump_file, pb, eqn);
3272 fprintf (dump_file, " \n");
3275 g = eqn->coef[i];
3276 g = abs (g);
3278 for (j = i - 1; j >= 0; j--)
3280 int t = int_mod (eqn->coef[j], g);
3282 if (2 * t >= g)
3283 t -= g;
3285 if (t != eqn->coef[j])
3287 eqn->coef[j] = t;
3288 change = true;
3292 if (!change)
3294 if (dump_file && (dump_flags & TDF_DETAILS))
3295 fprintf (dump_file, "So what?\n");
3298 else
3300 omega_name_wild_card (pb, i);
3302 if (dump_file && (dump_flags & TDF_DETAILS))
3304 omega_print_eq (dump_file, pb, eqn);
3305 fprintf (dump_file, " \n");
3308 e++;
3309 continue;
3314 if (promotion_possible)
3316 if (dump_file && (dump_flags & TDF_DETAILS))
3318 fprintf (dump_file, "promoting %s to safety\n",
3319 omega_variable_to_str (pb, i));
3320 omega_print_vars (dump_file, pb);
3323 pb->safe_vars++;
3325 if (!omega_wildcard_p (pb, i))
3326 omega_name_wild_card (pb, i);
3328 promotion_possible = false;
3329 j = k;
3330 goto normalizeEQ;
3333 if (g2 > 1 && !in_approximate_mode)
3335 if (pb->eqs[e].color == omega_red)
3337 if (dump_file && (dump_flags & TDF_DETAILS))
3338 fprintf (dump_file, "handling red equality\n");
3340 pb->num_eqs--;
3341 omega_do_elimination (pb, e, i);
3342 continue;
3345 if (dump_file && (dump_flags & TDF_DETAILS))
3347 fprintf (dump_file,
3348 "adding equation to handle safe variable \n");
3349 omega_print_eq (dump_file, pb, eqn);
3350 fprintf (dump_file, "\n----\n");
3351 omega_print_problem (dump_file, pb);
3352 fprintf (dump_file, "\n----\n");
3353 fprintf (dump_file, "\n----\n");
3356 i = omega_add_new_wild_card (pb);
3357 pb->num_eqs++;
3358 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
3359 omega_init_eqn_zero (&pb->eqs[e + 1], pb->num_vars);
3360 omega_copy_eqn (&pb->eqs[e + 1], eqn, pb->safe_vars);
3362 for (j = pb->num_vars; j >= 0; j--)
3364 pb->eqs[e + 1].coef[j] = int_mod (pb->eqs[e + 1].coef[j], g2);
3366 if (2 * pb->eqs[e + 1].coef[j] >= g2)
3367 pb->eqs[e + 1].coef[j] -= g2;
3370 pb->eqs[e + 1].coef[i] = g2;
3371 e += 2;
3373 if (dump_file && (dump_flags & TDF_DETAILS))
3374 omega_print_problem (dump_file, pb);
3376 continue;
3379 sv = pb->safe_vars;
3380 if (g2 == 0)
3381 sv = 0;
3383 /* Find variable to eliminate. */
3384 if (g2 > 1)
3386 gcc_assert (in_approximate_mode);
3388 if (dump_file && (dump_flags & TDF_DETAILS))
3390 fprintf (dump_file, "non-exact elimination: ");
3391 omega_print_eq (dump_file, pb, eqn);
3392 fprintf (dump_file, "\n");
3393 omega_print_problem (dump_file, pb);
3396 for (i = pb->num_vars; i > sv; i--)
3397 if (pb->eqs[e].coef[i] != 0)
3398 break;
3400 else
3401 for (i = pb->num_vars; i > sv; i--)
3402 if (pb->eqs[e].coef[i] == 1 || pb->eqs[e].coef[i] == -1)
3403 break;
3405 if (i > sv)
3407 pb->num_eqs--;
3408 omega_do_elimination (pb, e, i);
3410 if (dump_file && (dump_flags & TDF_DETAILS) && g2 > 1)
3412 fprintf (dump_file, "result of non-exact elimination:\n");
3413 omega_print_problem (dump_file, pb);
3416 else
3418 int factor = (INT_MAX);
3419 j = 0;
3421 if (dump_file && (dump_flags & TDF_DETAILS))
3422 fprintf (dump_file, "doing moding\n");
3424 for (i = pb->num_vars; i != sv; i--)
3425 if ((pb->eqs[e].coef[i] & 1) != 0)
3427 j = i;
3428 i--;
3430 for (; i != sv; i--)
3431 if ((pb->eqs[e].coef[i] & 1) != 0)
3432 break;
3434 break;
3437 if (j != 0 && i == sv)
3439 omega_do_mod (pb, 2, e, j);
3440 e++;
3441 continue;
3444 j = 0;
3445 for (i = pb->num_vars; i != sv; i--)
3446 if (pb->eqs[e].coef[i] != 0
3447 && factor > abs (pb->eqs[e].coef[i]) + 1)
3449 factor = abs (pb->eqs[e].coef[i]) + 1;
3450 j = i;
3453 if (j == sv)
3455 if (dump_file && (dump_flags & TDF_DETAILS))
3456 fprintf (dump_file, "should not have happened\n");
3457 gcc_assert (0);
3460 omega_do_mod (pb, factor, e, j);
3461 /* Go back and try this equation again. */
3462 e++;
3467 pb->num_eqs = 0;
3468 return omega_unknown;
3471 /* Transform an inequation E to an equality, then solve DIFF problems
3472 based on PB, and only differing by the constant part that is
3473 diminished by one, trying to figure out which of the constants
3474 satisfies PB. */
3476 static enum omega_result
3477 parallel_splinter (omega_pb pb, int e, int diff,
3478 enum omega_result desired_res)
3480 omega_pb tmp_problem;
3481 int i;
3483 if (dump_file && (dump_flags & TDF_DETAILS))
3485 fprintf (dump_file, "Using parallel splintering\n");
3486 omega_print_problem (dump_file, pb);
3489 tmp_problem = XNEW (struct omega_pb_d);
3490 omega_copy_eqn (&pb->eqs[0], &pb->geqs[e], pb->num_vars);
3491 pb->num_eqs = 1;
3493 for (i = 0; i <= diff; i++)
3495 omega_copy_problem (tmp_problem, pb);
3497 if (dump_file && (dump_flags & TDF_DETAILS))
3499 fprintf (dump_file, "Splinter # %i\n", i);
3500 omega_print_problem (dump_file, pb);
3503 if (omega_solve_problem (tmp_problem, desired_res) == omega_true)
3505 free (tmp_problem);
3506 return omega_true;
3509 pb->eqs[0].coef[0]--;
3512 free (tmp_problem);
3513 return omega_false;
3516 /* Helper function: solve equations one at a time. */
3518 static enum omega_result
3519 omega_solve_geq (omega_pb pb, enum omega_result desired_res)
3521 int i, e;
3522 int n_vars, fv;
3523 enum omega_result result;
3524 bool coupled_subscripts = false;
3525 bool smoothed = false;
3526 bool eliminate_again;
3527 bool tried_eliminating_redundant = false;
3529 if (desired_res != omega_simplify)
3531 pb->num_subs = 0;
3532 pb->safe_vars = 0;
3535 solve_geq_start:
3536 do {
3537 gcc_assert (desired_res == omega_simplify || pb->num_subs == 0);
3539 /* Verify that there are not too many inequalities. */
3540 gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
3542 if (dump_file && (dump_flags & TDF_DETAILS))
3544 fprintf (dump_file, "\nomega_solve_geq (%d,%d):\n",
3545 desired_res, please_no_equalities_in_simplified_problems);
3546 omega_print_problem (dump_file, pb);
3547 fprintf (dump_file, "\n");
3550 n_vars = pb->num_vars;
3552 if (n_vars == 1)
3554 enum omega_eqn_color u_color = omega_black;
3555 enum omega_eqn_color l_color = omega_black;
3556 int upper_bound = pos_infinity;
3557 int lower_bound = neg_infinity;
3559 for (e = pb->num_geqs - 1; e >= 0; e--)
3561 int a = pb->geqs[e].coef[1];
3562 int c = pb->geqs[e].coef[0];
3564 /* Our equation is ax + c >= 0, or ax >= -c, or c >= -ax. */
3565 if (a == 0)
3567 if (c < 0)
3568 return omega_problem_has_no_solution ();
3570 else if (a > 0)
3572 if (a != 1)
3573 c = int_div (c, a);
3575 if (lower_bound < -c
3576 || (lower_bound == -c
3577 && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3579 lower_bound = -c;
3580 l_color = pb->geqs[e].color;
3583 else
3585 if (a != -1)
3586 c = int_div (c, -a);
3588 if (upper_bound > c
3589 || (upper_bound == c
3590 && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3592 upper_bound = c;
3593 u_color = pb->geqs[e].color;
3598 if (dump_file && (dump_flags & TDF_DETAILS))
3600 fprintf (dump_file, "upper bound = %d\n", upper_bound);
3601 fprintf (dump_file, "lower bound = %d\n", lower_bound);
3604 if (lower_bound > upper_bound)
3605 return omega_problem_has_no_solution ();
3607 if (desired_res == omega_simplify)
3609 pb->num_geqs = 0;
3610 if (pb->safe_vars == 1)
3613 if (lower_bound == upper_bound
3614 && u_color == omega_black
3615 && l_color == omega_black)
3617 pb->eqs[0].coef[0] = -lower_bound;
3618 pb->eqs[0].coef[1] = 1;
3619 pb->eqs[0].color = omega_black;
3620 pb->num_eqs = 1;
3621 return omega_solve_problem (pb, desired_res);
3623 else
3625 if (lower_bound > neg_infinity)
3627 pb->geqs[0].coef[0] = -lower_bound;
3628 pb->geqs[0].coef[1] = 1;
3629 pb->geqs[0].key = 1;
3630 pb->geqs[0].color = l_color;
3631 pb->geqs[0].touched = 0;
3632 pb->num_geqs = 1;
3635 if (upper_bound < pos_infinity)
3637 pb->geqs[pb->num_geqs].coef[0] = upper_bound;
3638 pb->geqs[pb->num_geqs].coef[1] = -1;
3639 pb->geqs[pb->num_geqs].key = -1;
3640 pb->geqs[pb->num_geqs].color = u_color;
3641 pb->geqs[pb->num_geqs].touched = 0;
3642 pb->num_geqs++;
3646 else
3647 pb->num_vars = 0;
3649 omega_problem_reduced (pb);
3650 return omega_false;
3653 if (original_problem != no_problem
3654 && l_color == omega_black
3655 && u_color == omega_black
3656 && !conservative
3657 && lower_bound == upper_bound)
3659 pb->eqs[0].coef[0] = -lower_bound;
3660 pb->eqs[0].coef[1] = 1;
3661 pb->num_eqs = 1;
3662 adding_equality_constraint (pb, 0);
3665 return omega_true;
3668 if (!pb->variables_freed)
3670 pb->variables_freed = true;
3672 if (desired_res != omega_simplify)
3673 omega_free_eliminations (pb, 0);
3674 else
3675 omega_free_eliminations (pb, pb->safe_vars);
3677 n_vars = pb->num_vars;
3679 if (n_vars == 1)
3680 continue;
3683 switch (normalize_omega_problem (pb))
3685 case normalize_false:
3686 return omega_false;
3687 break;
3689 case normalize_coupled:
3690 coupled_subscripts = true;
3691 break;
3693 case normalize_uncoupled:
3694 coupled_subscripts = false;
3695 break;
3697 default:
3698 gcc_unreachable ();
3701 n_vars = pb->num_vars;
3703 if (dump_file && (dump_flags & TDF_DETAILS))
3705 fprintf (dump_file, "\nafter normalization:\n");
3706 omega_print_problem (dump_file, pb);
3707 fprintf (dump_file, "\n");
3708 fprintf (dump_file, "eliminating variable using Fourier-Motzkin.\n");
3711 do {
3712 int parallel_difference = INT_MAX;
3713 int best_parallel_eqn = -1;
3714 int minC, maxC, minCj = 0;
3715 int lower_bound_count = 0;
3716 int e2, Le = 0, Ue;
3717 bool possible_easy_int_solution;
3718 int max_splinters = 1;
3719 bool exact = false;
3720 bool lucky_exact = false;
3721 int best = (INT_MAX);
3722 int j = 0, jLe = 0, jLowerBoundCount = 0;
3725 eliminate_again = false;
3727 if (pb->num_eqs > 0)
3728 return omega_solve_problem (pb, desired_res);
3730 if (!coupled_subscripts)
3732 if (pb->safe_vars == 0)
3733 pb->num_geqs = 0;
3734 else
3735 for (e = pb->num_geqs - 1; e >= 0; e--)
3736 if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
3737 omega_delete_geq (pb, e, n_vars);
3739 pb->num_vars = pb->safe_vars;
3741 if (desired_res == omega_simplify)
3743 omega_problem_reduced (pb);
3744 return omega_false;
3747 return omega_true;
3750 if (desired_res != omega_simplify)
3751 fv = 0;
3752 else
3753 fv = pb->safe_vars;
3755 if (pb->num_geqs == 0)
3757 if (desired_res == omega_simplify)
3759 pb->num_vars = pb->safe_vars;
3760 omega_problem_reduced (pb);
3761 return omega_false;
3763 return omega_true;
3766 if (desired_res == omega_simplify && n_vars == pb->safe_vars)
3768 omega_problem_reduced (pb);
3769 return omega_false;
3772 if (pb->num_geqs > OMEGA_MAX_GEQS - 30
3773 || pb->num_geqs > 2 * n_vars * n_vars + 4 * n_vars + 10)
3775 if (dump_file && (dump_flags & TDF_DETAILS))
3776 fprintf (dump_file,
3777 "TOO MANY EQUATIONS; "
3778 "%d equations, %d variables, "
3779 "ELIMINATING REDUNDANT ONES\n",
3780 pb->num_geqs, n_vars);
3782 if (!omega_eliminate_redundant (pb, false))
3783 return omega_false;
3785 n_vars = pb->num_vars;
3787 if (pb->num_eqs > 0)
3788 return omega_solve_problem (pb, desired_res);
3790 if (dump_file && (dump_flags & TDF_DETAILS))
3791 fprintf (dump_file, "END ELIMINATION OF REDUNDANT EQUATIONS\n");
3794 if (desired_res != omega_simplify)
3795 fv = 0;
3796 else
3797 fv = pb->safe_vars;
3799 for (i = n_vars; i != fv; i--)
3801 int score;
3802 int ub = -2;
3803 int lb = -2;
3804 bool lucky = false;
3805 int upper_bound_count = 0;
3807 lower_bound_count = 0;
3808 minC = maxC = 0;
3810 for (e = pb->num_geqs - 1; e >= 0; e--)
3811 if (pb->geqs[e].coef[i] < 0)
3813 minC = MIN (minC, pb->geqs[e].coef[i]);
3814 upper_bound_count++;
3815 if (pb->geqs[e].coef[i] < -1)
3817 if (ub == -2)
3818 ub = e;
3819 else
3820 ub = -1;
3823 else if (pb->geqs[e].coef[i] > 0)
3825 maxC = MAX (maxC, pb->geqs[e].coef[i]);
3826 lower_bound_count++;
3827 Le = e;
3828 if (pb->geqs[e].coef[i] > 1)
3830 if (lb == -2)
3831 lb = e;
3832 else
3833 lb = -1;
3837 if (lower_bound_count == 0
3838 || upper_bound_count == 0)
3840 lower_bound_count = 0;
3841 break;
3844 if (ub >= 0 && lb >= 0
3845 && pb->geqs[lb].key == -pb->geqs[ub].key)
3847 int Lc = pb->geqs[lb].coef[i];
3848 int Uc = -pb->geqs[ub].coef[i];
3849 int diff =
3850 Lc * pb->geqs[ub].coef[0] + Uc * pb->geqs[lb].coef[0];
3851 lucky = (diff >= (Uc - 1) * (Lc - 1));
3854 if (maxC == 1
3855 || minC == -1
3856 || lucky
3857 || in_approximate_mode)
3859 score = upper_bound_count * lower_bound_count;
3861 if (dump_file && (dump_flags & TDF_DETAILS))
3862 fprintf (dump_file,
3863 "For %s, exact, score = %d*%d, range = %d ... %d,"
3864 "\nlucky = %d, in_approximate_mode=%d \n",
3865 omega_variable_to_str (pb, i),
3866 upper_bound_count,
3867 lower_bound_count, minC, maxC, lucky,
3868 in_approximate_mode);
3870 if (!exact
3871 || score < best)
3874 best = score;
3875 j = i;
3876 minCj = minC;
3877 jLe = Le;
3878 jLowerBoundCount = lower_bound_count;
3879 exact = true;
3880 lucky_exact = lucky;
3881 if (score == 1)
3882 break;
3885 else if (!exact)
3887 if (dump_file && (dump_flags & TDF_DETAILS))
3888 fprintf (dump_file,
3889 "For %s, non-exact, score = %d*%d,"
3890 "range = %d ... %d \n",
3891 omega_variable_to_str (pb, i),
3892 upper_bound_count,
3893 lower_bound_count, minC, maxC);
3895 score = maxC - minC;
3897 if (best > score)
3899 best = score;
3900 j = i;
3901 minCj = minC;
3902 jLe = Le;
3903 jLowerBoundCount = lower_bound_count;
3908 if (lower_bound_count == 0)
3910 omega_free_eliminations (pb, pb->safe_vars);
3911 n_vars = pb->num_vars;
3912 eliminate_again = true;
3913 continue;
3916 i = j;
3917 minC = minCj;
3918 Le = jLe;
3919 lower_bound_count = jLowerBoundCount;
3921 for (e = pb->num_geqs - 1; e >= 0; e--)
3922 if (pb->geqs[e].coef[i] > 0)
3924 if (pb->geqs[e].coef[i] == -minC)
3925 max_splinters += -minC - 1;
3926 else
3927 max_splinters +=
3928 check_pos_mul ((pb->geqs[e].coef[i] - 1),
3929 (-minC - 1)) / (-minC) + 1;
3932 /* #ifdef Omega3 */
3933 /* Trying to produce exact elimination by finding redundant
3934 constraints. */
3935 if (!exact && !tried_eliminating_redundant)
3937 omega_eliminate_redundant (pb, false);
3938 tried_eliminating_redundant = true;
3939 eliminate_again = true;
3940 continue;
3942 tried_eliminating_redundant = false;
3943 /* #endif */
3945 if (return_single_result && desired_res == omega_simplify && !exact)
3947 omega_problem_reduced (pb);
3948 return omega_true;
3951 /* #ifndef Omega3 */
3952 /* Trying to produce exact elimination by finding redundant
3953 constraints. */
3954 if (!exact && !tried_eliminating_redundant)
3956 omega_eliminate_redundant (pb, false);
3957 tried_eliminating_redundant = true;
3958 continue;
3960 tried_eliminating_redundant = false;
3961 /* #endif */
3963 if (!exact)
3965 int e1, e2;
3967 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
3968 if (pb->geqs[e1].color == omega_black)
3969 for (e2 = e1 - 1; e2 >= 0; e2--)
3970 if (pb->geqs[e2].color == omega_black
3971 && pb->geqs[e1].key == -pb->geqs[e2].key
3972 && ((pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3973 * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3974 / 2 < parallel_difference))
3976 parallel_difference =
3977 (pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3978 * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3979 / 2;
3980 best_parallel_eqn = e1;
3983 if (dump_file && (dump_flags & TDF_DETAILS)
3984 && best_parallel_eqn >= 0)
3986 fprintf (dump_file,
3987 "Possible parallel projection, diff = %d, in ",
3988 parallel_difference);
3989 omega_print_geq (dump_file, pb, &(pb->geqs[best_parallel_eqn]));
3990 fprintf (dump_file, "\n");
3991 omega_print_problem (dump_file, pb);
3995 if (dump_file && (dump_flags & TDF_DETAILS))
3997 fprintf (dump_file, "going to eliminate %s, (%d,%d,%d)\n",
3998 omega_variable_to_str (pb, i), i, minC,
3999 lower_bound_count);
4000 omega_print_problem (dump_file, pb);
4002 if (lucky_exact)
4003 fprintf (dump_file, "(a lucky exact elimination)\n");
4005 else if (exact)
4006 fprintf (dump_file, "(an exact elimination)\n");
4008 fprintf (dump_file, "Max # of splinters = %d\n", max_splinters);
4011 gcc_assert (max_splinters >= 1);
4013 if (!exact && desired_res == omega_simplify && best_parallel_eqn >= 0
4014 && parallel_difference <= max_splinters)
4015 return parallel_splinter (pb, best_parallel_eqn, parallel_difference,
4016 desired_res);
4018 smoothed = false;
4020 if (i != n_vars)
4022 int t;
4023 int j = pb->num_vars;
4025 if (dump_file && (dump_flags & TDF_DETAILS))
4027 fprintf (dump_file, "Swapping %d and %d\n", i, j);
4028 omega_print_problem (dump_file, pb);
4031 swap (&pb->var[i], &pb->var[j]);
4033 for (e = pb->num_geqs - 1; e >= 0; e--)
4034 if (pb->geqs[e].coef[i] != pb->geqs[e].coef[j])
4036 pb->geqs[e].touched = 1;
4037 t = pb->geqs[e].coef[i];
4038 pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
4039 pb->geqs[e].coef[j] = t;
4042 for (e = pb->num_subs - 1; e >= 0; e--)
4043 if (pb->subs[e].coef[i] != pb->subs[e].coef[j])
4045 t = pb->subs[e].coef[i];
4046 pb->subs[e].coef[i] = pb->subs[e].coef[j];
4047 pb->subs[e].coef[j] = t;
4050 if (dump_file && (dump_flags & TDF_DETAILS))
4052 fprintf (dump_file, "Swapping complete \n");
4053 omega_print_problem (dump_file, pb);
4054 fprintf (dump_file, "\n");
4057 i = j;
4060 else if (dump_file && (dump_flags & TDF_DETAILS))
4062 fprintf (dump_file, "No swap needed\n");
4063 omega_print_problem (dump_file, pb);
4066 pb->num_vars--;
4067 n_vars = pb->num_vars;
4069 if (exact)
4071 if (n_vars == 1)
4073 int upper_bound = pos_infinity;
4074 int lower_bound = neg_infinity;
4075 enum omega_eqn_color ub_color = omega_black;
4076 enum omega_eqn_color lb_color = omega_black;
4077 int topeqn = pb->num_geqs - 1;
4078 int Lc = pb->geqs[Le].coef[i];
4080 for (Le = topeqn; Le >= 0; Le--)
4081 if ((Lc = pb->geqs[Le].coef[i]) == 0)
4083 if (pb->geqs[Le].coef[1] == 1)
4085 int constantTerm = -pb->geqs[Le].coef[0];
4087 if (constantTerm > lower_bound ||
4088 (constantTerm == lower_bound &&
4089 !omega_eqn_is_red (&pb->geqs[Le], desired_res)))
4091 lower_bound = constantTerm;
4092 lb_color = pb->geqs[Le].color;
4095 if (dump_file && (dump_flags & TDF_DETAILS))
4097 if (pb->geqs[Le].color == omega_black)
4098 fprintf (dump_file, " :::=> %s >= %d\n",
4099 omega_variable_to_str (pb, 1),
4100 constantTerm);
4101 else
4102 fprintf (dump_file,
4103 " :::=> [%s >= %d]\n",
4104 omega_variable_to_str (pb, 1),
4105 constantTerm);
4108 else
4110 int constantTerm = pb->geqs[Le].coef[0];
4111 if (constantTerm < upper_bound ||
4112 (constantTerm == upper_bound
4113 && !omega_eqn_is_red (&pb->geqs[Le],
4114 desired_res)))
4116 upper_bound = constantTerm;
4117 ub_color = pb->geqs[Le].color;
4120 if (dump_file && (dump_flags & TDF_DETAILS))
4122 if (pb->geqs[Le].color == omega_black)
4123 fprintf (dump_file, " :::=> %s <= %d\n",
4124 omega_variable_to_str (pb, 1),
4125 constantTerm);
4126 else
4127 fprintf (dump_file,
4128 " :::=> [%s <= %d]\n",
4129 omega_variable_to_str (pb, 1),
4130 constantTerm);
4134 else if (Lc > 0)
4135 for (Ue = topeqn; Ue >= 0; Ue--)
4136 if (pb->geqs[Ue].coef[i] < 0
4137 && pb->geqs[Le].key != -pb->geqs[Ue].key)
4139 int Uc = -pb->geqs[Ue].coef[i];
4140 int coefficient = pb->geqs[Ue].coef[1] * Lc
4141 + pb->geqs[Le].coef[1] * Uc;
4142 int constantTerm = pb->geqs[Ue].coef[0] * Lc
4143 + pb->geqs[Le].coef[0] * Uc;
4145 if (dump_file && (dump_flags & TDF_DETAILS))
4147 omega_print_geq_extra (dump_file, pb,
4148 &(pb->geqs[Ue]));
4149 fprintf (dump_file, "\n");
4150 omega_print_geq_extra (dump_file, pb,
4151 &(pb->geqs[Le]));
4152 fprintf (dump_file, "\n");
4155 if (coefficient > 0)
4157 constantTerm = -int_div (constantTerm, coefficient);
4159 if (constantTerm > lower_bound
4160 || (constantTerm == lower_bound
4161 && (desired_res != omega_simplify
4162 || (pb->geqs[Ue].color == omega_black
4163 && pb->geqs[Le].color == omega_black))))
4165 lower_bound = constantTerm;
4166 lb_color = (pb->geqs[Ue].color == omega_red
4167 || pb->geqs[Le].color == omega_red)
4168 ? omega_red : omega_black;
4171 if (dump_file && (dump_flags & TDF_DETAILS))
4173 if (pb->geqs[Ue].color == omega_red
4174 || pb->geqs[Le].color == omega_red)
4175 fprintf (dump_file,
4176 " ::=> [%s >= %d]\n",
4177 omega_variable_to_str (pb, 1),
4178 constantTerm);
4179 else
4180 fprintf (dump_file,
4181 " ::=> %s >= %d\n",
4182 omega_variable_to_str (pb, 1),
4183 constantTerm);
4186 else
4188 constantTerm = int_div (constantTerm, -coefficient);
4189 if (constantTerm < upper_bound
4190 || (constantTerm == upper_bound
4191 && pb->geqs[Ue].color == omega_black
4192 && pb->geqs[Le].color == omega_black))
4194 upper_bound = constantTerm;
4195 ub_color = (pb->geqs[Ue].color == omega_red
4196 || pb->geqs[Le].color == omega_red)
4197 ? omega_red : omega_black;
4200 if (dump_file
4201 && (dump_flags & TDF_DETAILS))
4203 if (pb->geqs[Ue].color == omega_red
4204 || pb->geqs[Le].color == omega_red)
4205 fprintf (dump_file,
4206 " ::=> [%s <= %d]\n",
4207 omega_variable_to_str (pb, 1),
4208 constantTerm);
4209 else
4210 fprintf (dump_file,
4211 " ::=> %s <= %d\n",
4212 omega_variable_to_str (pb, 1),
4213 constantTerm);
4218 pb->num_geqs = 0;
4220 if (dump_file && (dump_flags & TDF_DETAILS))
4221 fprintf (dump_file,
4222 " therefore, %c%d <= %c%s%c <= %d%c\n",
4223 lb_color == omega_red ? '[' : ' ', lower_bound,
4224 (lb_color == omega_red && ub_color == omega_black)
4225 ? ']' : ' ',
4226 omega_variable_to_str (pb, 1),
4227 (lb_color == omega_black && ub_color == omega_red)
4228 ? '[' : ' ',
4229 upper_bound, ub_color == omega_red ? ']' : ' ');
4231 if (lower_bound > upper_bound)
4232 return omega_false;
4234 if (pb->safe_vars == 1)
4236 if (upper_bound == lower_bound
4237 && !(ub_color == omega_red || lb_color == omega_red)
4238 && !please_no_equalities_in_simplified_problems)
4240 pb->num_eqs++;
4241 pb->eqs[0].coef[1] = -1;
4242 pb->eqs[0].coef[0] = upper_bound;
4244 if (ub_color == omega_red
4245 || lb_color == omega_red)
4246 pb->eqs[0].color = omega_red;
4248 if (desired_res == omega_simplify
4249 && pb->eqs[0].color == omega_black)
4250 return omega_solve_problem (pb, desired_res);
4253 if (upper_bound != pos_infinity)
4255 pb->geqs[0].coef[1] = -1;
4256 pb->geqs[0].coef[0] = upper_bound;
4257 pb->geqs[0].color = ub_color;
4258 pb->geqs[0].key = -1;
4259 pb->geqs[0].touched = 0;
4260 pb->num_geqs++;
4263 if (lower_bound != neg_infinity)
4265 pb->geqs[pb->num_geqs].coef[1] = 1;
4266 pb->geqs[pb->num_geqs].coef[0] = -lower_bound;
4267 pb->geqs[pb->num_geqs].color = lb_color;
4268 pb->geqs[pb->num_geqs].key = 1;
4269 pb->geqs[pb->num_geqs].touched = 0;
4270 pb->num_geqs++;
4274 if (desired_res == omega_simplify)
4276 omega_problem_reduced (pb);
4277 return omega_false;
4279 else
4281 if (!conservative
4282 && (desired_res != omega_simplify
4283 || (lb_color == omega_black
4284 && ub_color == omega_black))
4285 && original_problem != no_problem
4286 && lower_bound == upper_bound)
4288 for (i = original_problem->num_vars; i >= 0; i--)
4289 if (original_problem->var[i] == pb->var[1])
4290 break;
4292 if (i == 0)
4293 break;
4295 e = original_problem->num_eqs++;
4296 omega_init_eqn_zero (&original_problem->eqs[e],
4297 original_problem->num_vars);
4298 original_problem->eqs[e].coef[i] = -1;
4299 original_problem->eqs[e].coef[0] = upper_bound;
4301 if (dump_file && (dump_flags & TDF_DETAILS))
4303 fprintf (dump_file,
4304 "adding equality %d to outer problem\n", e);
4305 omega_print_problem (dump_file, original_problem);
4308 return omega_true;
4312 eliminate_again = true;
4314 if (lower_bound_count == 1)
4316 eqn lbeqn = omega_alloc_eqns (0, 1);
4317 int Lc = pb->geqs[Le].coef[i];
4319 if (dump_file && (dump_flags & TDF_DETAILS))
4320 fprintf (dump_file, "an inplace elimination\n");
4322 omega_copy_eqn (lbeqn, &pb->geqs[Le], (n_vars + 1));
4323 omega_delete_geq_extra (pb, Le, n_vars + 1);
4325 for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4326 if (pb->geqs[Ue].coef[i] < 0)
4328 if (lbeqn->key == -pb->geqs[Ue].key)
4329 omega_delete_geq_extra (pb, Ue, n_vars + 1);
4330 else
4332 int k;
4333 int Uc = -pb->geqs[Ue].coef[i];
4334 pb->geqs[Ue].touched = 1;
4335 eliminate_again = false;
4337 if (lbeqn->color == omega_red)
4338 pb->geqs[Ue].color = omega_red;
4340 for (k = 0; k <= n_vars; k++)
4341 pb->geqs[Ue].coef[k] =
4342 check_mul (pb->geqs[Ue].coef[k], Lc) +
4343 check_mul (lbeqn->coef[k], Uc);
4345 if (dump_file && (dump_flags & TDF_DETAILS))
4347 omega_print_geq (dump_file, pb,
4348 &(pb->geqs[Ue]));
4349 fprintf (dump_file, "\n");
4354 omega_free_eqns (lbeqn, 1);
4355 continue;
4357 else
4359 int *dead_eqns = XNEWVEC (int, OMEGA_MAX_GEQS);
4360 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
4361 int num_dead = 0;
4362 int top_eqn = pb->num_geqs - 1;
4363 lower_bound_count--;
4365 if (dump_file && (dump_flags & TDF_DETAILS))
4366 fprintf (dump_file, "lower bound count = %d\n",
4367 lower_bound_count);
4369 for (Le = top_eqn; Le >= 0; Le--)
4370 if (pb->geqs[Le].coef[i] > 0)
4372 int Lc = pb->geqs[Le].coef[i];
4373 for (Ue = top_eqn; Ue >= 0; Ue--)
4374 if (pb->geqs[Ue].coef[i] < 0)
4376 if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4378 int k;
4379 int Uc = -pb->geqs[Ue].coef[i];
4381 if (num_dead == 0)
4382 e2 = pb->num_geqs++;
4383 else
4384 e2 = dead_eqns[--num_dead];
4386 gcc_assert (e2 < OMEGA_MAX_GEQS);
4388 if (dump_file && (dump_flags & TDF_DETAILS))
4390 fprintf (dump_file,
4391 "Le = %d, Ue = %d, gen = %d\n",
4392 Le, Ue, e2);
4393 omega_print_geq_extra (dump_file, pb,
4394 &(pb->geqs[Le]));
4395 fprintf (dump_file, "\n");
4396 omega_print_geq_extra (dump_file, pb,
4397 &(pb->geqs[Ue]));
4398 fprintf (dump_file, "\n");
4401 eliminate_again = false;
4403 for (k = n_vars; k >= 0; k--)
4404 pb->geqs[e2].coef[k] =
4405 check_mul (pb->geqs[Ue].coef[k], Lc) +
4406 check_mul (pb->geqs[Le].coef[k], Uc);
4408 pb->geqs[e2].coef[n_vars + 1] = 0;
4409 pb->geqs[e2].touched = 1;
4411 if (pb->geqs[Ue].color == omega_red
4412 || pb->geqs[Le].color == omega_red)
4413 pb->geqs[e2].color = omega_red;
4414 else
4415 pb->geqs[e2].color = omega_black;
4417 if (dump_file && (dump_flags & TDF_DETAILS))
4419 omega_print_geq (dump_file, pb,
4420 &(pb->geqs[e2]));
4421 fprintf (dump_file, "\n");
4425 if (lower_bound_count == 0)
4427 dead_eqns[num_dead++] = Ue;
4429 if (dump_file && (dump_flags & TDF_DETAILS))
4430 fprintf (dump_file, "Killed %d\n", Ue);
4434 lower_bound_count--;
4435 dead_eqns[num_dead++] = Le;
4437 if (dump_file && (dump_flags & TDF_DETAILS))
4438 fprintf (dump_file, "Killed %d\n", Le);
4441 for (e = pb->num_geqs - 1; e >= 0; e--)
4442 is_dead[e] = false;
4444 while (num_dead > 0)
4445 is_dead[dead_eqns[--num_dead]] = true;
4447 for (e = pb->num_geqs - 1; e >= 0; e--)
4448 if (is_dead[e])
4449 omega_delete_geq_extra (pb, e, n_vars + 1);
4451 free (dead_eqns);
4452 free (is_dead);
4453 continue;
4456 else
4458 omega_pb rS, iS;
4460 rS = omega_alloc_problem (0, 0);
4461 iS = omega_alloc_problem (0, 0);
4462 e2 = 0;
4463 possible_easy_int_solution = true;
4465 for (e = 0; e < pb->num_geqs; e++)
4466 if (pb->geqs[e].coef[i] == 0)
4468 omega_copy_eqn (&(rS->geqs[e2]), &pb->geqs[e],
4469 pb->num_vars);
4470 omega_copy_eqn (&(iS->geqs[e2]), &pb->geqs[e],
4471 pb->num_vars);
4473 if (dump_file && (dump_flags & TDF_DETAILS))
4475 int t;
4476 fprintf (dump_file, "Copying (%d, %d): ", i,
4477 pb->geqs[e].coef[i]);
4478 omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
4479 fprintf (dump_file, "\n");
4480 for (t = 0; t <= n_vars + 1; t++)
4481 fprintf (dump_file, "%d ", pb->geqs[e].coef[t]);
4482 fprintf (dump_file, "\n");
4485 e2++;
4486 gcc_assert (e2 < OMEGA_MAX_GEQS);
4489 for (Le = pb->num_geqs - 1; Le >= 0; Le--)
4490 if (pb->geqs[Le].coef[i] > 0)
4491 for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4492 if (pb->geqs[Ue].coef[i] < 0)
4494 int k;
4495 int Lc = pb->geqs[Le].coef[i];
4496 int Uc = -pb->geqs[Ue].coef[i];
4498 if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4501 rS->geqs[e2].touched = iS->geqs[e2].touched = 1;
4503 if (dump_file && (dump_flags & TDF_DETAILS))
4505 fprintf (dump_file, "---\n");
4506 fprintf (dump_file,
4507 "Le(Lc) = %d(%d_, Ue(Uc) = %d(%d), gen = %d\n",
4508 Le, Lc, Ue, Uc, e2);
4509 omega_print_geq_extra (dump_file, pb, &pb->geqs[Le]);
4510 fprintf (dump_file, "\n");
4511 omega_print_geq_extra (dump_file, pb, &pb->geqs[Ue]);
4512 fprintf (dump_file, "\n");
4515 if (Uc == Lc)
4517 for (k = n_vars; k >= 0; k--)
4518 iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4519 pb->geqs[Ue].coef[k] + pb->geqs[Le].coef[k];
4521 iS->geqs[e2].coef[0] -= (Uc - 1);
4523 else
4525 for (k = n_vars; k >= 0; k--)
4526 iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4527 check_mul (pb->geqs[Ue].coef[k], Lc) +
4528 check_mul (pb->geqs[Le].coef[k], Uc);
4530 iS->geqs[e2].coef[0] -= (Uc - 1) * (Lc - 1);
4533 if (pb->geqs[Ue].color == omega_red
4534 || pb->geqs[Le].color == omega_red)
4535 iS->geqs[e2].color = rS->geqs[e2].color = omega_red;
4536 else
4537 iS->geqs[e2].color = rS->geqs[e2].color = omega_black;
4539 if (dump_file && (dump_flags & TDF_DETAILS))
4541 omega_print_geq (dump_file, pb, &(rS->geqs[e2]));
4542 fprintf (dump_file, "\n");
4545 e2++;
4546 gcc_assert (e2 < OMEGA_MAX_GEQS);
4548 else if (pb->geqs[Ue].coef[0] * Lc +
4549 pb->geqs[Le].coef[0] * Uc -
4550 (Uc - 1) * (Lc - 1) < 0)
4551 possible_easy_int_solution = false;
4554 iS->variables_initialized = rS->variables_initialized = true;
4555 iS->num_vars = rS->num_vars = pb->num_vars;
4556 iS->num_geqs = rS->num_geqs = e2;
4557 iS->num_eqs = rS->num_eqs = 0;
4558 iS->num_subs = rS->num_subs = pb->num_subs;
4559 iS->safe_vars = rS->safe_vars = pb->safe_vars;
4561 for (e = n_vars; e >= 0; e--)
4562 rS->var[e] = pb->var[e];
4564 for (e = n_vars; e >= 0; e--)
4565 iS->var[e] = pb->var[e];
4567 for (e = pb->num_subs - 1; e >= 0; e--)
4569 omega_copy_eqn (&(rS->subs[e]), &(pb->subs[e]), pb->num_vars);
4570 omega_copy_eqn (&(iS->subs[e]), &(pb->subs[e]), pb->num_vars);
4573 pb->num_vars++;
4574 n_vars = pb->num_vars;
4576 if (desired_res != omega_true)
4578 if (original_problem == no_problem)
4580 original_problem = pb;
4581 result = omega_solve_geq (rS, omega_false);
4582 original_problem = no_problem;
4584 else
4585 result = omega_solve_geq (rS, omega_false);
4587 if (result == omega_false)
4589 free (rS);
4590 free (iS);
4591 return result;
4594 if (pb->num_eqs > 0)
4596 /* An equality constraint must have been found */
4597 free (rS);
4598 free (iS);
4599 return omega_solve_problem (pb, desired_res);
4603 if (desired_res != omega_false)
4605 int j;
4606 int lower_bounds = 0;
4607 int *lower_bound = XNEWVEC (int, OMEGA_MAX_GEQS);
4609 if (possible_easy_int_solution)
4611 conservative++;
4612 result = omega_solve_geq (iS, desired_res);
4613 conservative--;
4615 if (result != omega_false)
4617 free (rS);
4618 free (iS);
4619 free (lower_bound);
4620 return result;
4624 if (!exact && best_parallel_eqn >= 0
4625 && parallel_difference <= max_splinters)
4627 free (rS);
4628 free (iS);
4629 free (lower_bound);
4630 return parallel_splinter (pb, best_parallel_eqn,
4631 parallel_difference,
4632 desired_res);
4635 if (dump_file && (dump_flags & TDF_DETAILS))
4636 fprintf (dump_file, "have to do exact analysis\n");
4638 conservative++;
4640 for (e = 0; e < pb->num_geqs; e++)
4641 if (pb->geqs[e].coef[i] > 1)
4642 lower_bound[lower_bounds++] = e;
4644 /* Sort array LOWER_BOUND. */
4645 for (j = 0; j < lower_bounds; j++)
4647 int k, smallest = j;
4649 for (k = j + 1; k < lower_bounds; k++)
4650 if (pb->geqs[lower_bound[smallest]].coef[i] >
4651 pb->geqs[lower_bound[k]].coef[i])
4652 smallest = k;
4654 k = lower_bound[smallest];
4655 lower_bound[smallest] = lower_bound[j];
4656 lower_bound[j] = k;
4659 if (dump_file && (dump_flags & TDF_DETAILS))
4661 fprintf (dump_file, "lower bound coefficients = ");
4663 for (j = 0; j < lower_bounds; j++)
4664 fprintf (dump_file, " %d",
4665 pb->geqs[lower_bound[j]].coef[i]);
4667 fprintf (dump_file, "\n");
4670 for (j = 0; j < lower_bounds; j++)
4672 int max_incr;
4673 int c;
4674 int worst_lower_bound_constant = -minC;
4676 e = lower_bound[j];
4677 max_incr = (((pb->geqs[e].coef[i] - 1) *
4678 (worst_lower_bound_constant - 1) - 1)
4679 / worst_lower_bound_constant);
4680 /* max_incr += 2; */
4682 if (dump_file && (dump_flags & TDF_DETAILS))
4684 fprintf (dump_file, "for equation ");
4685 omega_print_geq (dump_file, pb, &pb->geqs[e]);
4686 fprintf (dump_file,
4687 "\ntry decrements from 0 to %d\n",
4688 max_incr);
4689 omega_print_problem (dump_file, pb);
4692 if (max_incr > 50 && !smoothed
4693 && smooth_weird_equations (pb))
4695 conservative--;
4696 free (rS);
4697 free (iS);
4698 smoothed = true;
4699 goto solve_geq_start;
4702 omega_copy_eqn (&pb->eqs[0], &pb->geqs[e],
4703 pb->num_vars);
4704 pb->eqs[0].color = omega_black;
4705 omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
4706 pb->geqs[e].touched = 1;
4707 pb->num_eqs = 1;
4709 for (c = max_incr; c >= 0; c--)
4711 if (dump_file && (dump_flags & TDF_DETAILS))
4713 fprintf (dump_file,
4714 "trying next decrement of %d\n",
4715 max_incr - c);
4716 omega_print_problem (dump_file, pb);
4719 omega_copy_problem (rS, pb);
4721 if (dump_file && (dump_flags & TDF_DETAILS))
4722 omega_print_problem (dump_file, rS);
4724 result = omega_solve_problem (rS, desired_res);
4726 if (result == omega_true)
4728 free (rS);
4729 free (iS);
4730 free (lower_bound);
4731 conservative--;
4732 return omega_true;
4735 pb->eqs[0].coef[0]--;
4738 if (j + 1 < lower_bounds)
4740 pb->num_eqs = 0;
4741 omega_copy_eqn (&pb->geqs[e], &pb->eqs[0],
4742 pb->num_vars);
4743 pb->geqs[e].touched = 1;
4744 pb->geqs[e].color = omega_black;
4745 omega_copy_problem (rS, pb);
4747 if (dump_file && (dump_flags & TDF_DETAILS))
4748 fprintf (dump_file,
4749 "exhausted lower bound, "
4750 "checking if still feasible ");
4752 result = omega_solve_problem (rS, omega_false);
4754 if (result == omega_false)
4755 break;
4759 if (dump_file && (dump_flags & TDF_DETAILS))
4760 fprintf (dump_file, "fall-off the end\n");
4762 free (rS);
4763 free (iS);
4764 free (lower_bound);
4765 conservative--;
4766 return omega_false;
4769 free (rS);
4770 free (iS);
4772 return omega_unknown;
4773 } while (eliminate_again);
4774 } while (1);
4777 /* Because the omega solver is recursive, this counter limits the
4778 recursion depth. */
4779 static int omega_solve_depth = 0;
4781 /* Return omega_true when the problem PB has a solution following the
4782 DESIRED_RES. */
4784 enum omega_result
4785 omega_solve_problem (omega_pb pb, enum omega_result desired_res)
4787 enum omega_result result;
4789 gcc_assert (pb->num_vars >= pb->safe_vars);
4790 omega_solve_depth++;
4792 if (desired_res != omega_simplify)
4793 pb->safe_vars = 0;
4795 if (omega_solve_depth > 50)
4797 if (dump_file && (dump_flags & TDF_DETAILS))
4799 fprintf (dump_file,
4800 "Solve depth = %d, in_approximate_mode = %d, aborting\n",
4801 omega_solve_depth, in_approximate_mode);
4802 omega_print_problem (dump_file, pb);
4804 gcc_assert (0);
4807 if (omega_solve_eq (pb, desired_res) == omega_false)
4809 omega_solve_depth--;
4810 return omega_false;
4813 if (in_approximate_mode && !pb->num_geqs)
4815 result = omega_true;
4816 pb->num_vars = pb->safe_vars;
4817 omega_problem_reduced (pb);
4819 else
4820 result = omega_solve_geq (pb, desired_res);
4822 omega_solve_depth--;
4824 if (!omega_reduce_with_subs)
4826 resurrect_subs (pb);
4827 gcc_assert (please_no_equalities_in_simplified_problems
4828 || !result || pb->num_subs == 0);
4831 return result;
4834 /* Return true if red equations constrain the set of possible solutions.
4835 We assume that there are solutions to the black equations by
4836 themselves, so if there is no solution to the combined problem, we
4837 return true. */
4839 bool
4840 omega_problem_has_red_equations (omega_pb pb)
4842 bool result;
4843 int e;
4844 int i;
4846 if (dump_file && (dump_flags & TDF_DETAILS))
4848 fprintf (dump_file, "Checking for red equations:\n");
4849 omega_print_problem (dump_file, pb);
4852 please_no_equalities_in_simplified_problems++;
4853 may_be_red++;
4855 if (omega_single_result)
4856 return_single_result++;
4858 create_color = true;
4859 result = (omega_simplify_problem (pb) == omega_false);
4861 if (omega_single_result)
4862 return_single_result--;
4864 may_be_red--;
4865 please_no_equalities_in_simplified_problems--;
4867 if (result)
4869 if (dump_file && (dump_flags & TDF_DETAILS))
4870 fprintf (dump_file, "Gist is FALSE\n");
4872 pb->num_subs = 0;
4873 pb->num_geqs = 0;
4874 pb->num_eqs = 1;
4875 pb->eqs[0].color = omega_red;
4877 for (i = pb->num_vars; i > 0; i--)
4878 pb->eqs[0].coef[i] = 0;
4880 pb->eqs[0].coef[0] = 1;
4881 return true;
4884 free_red_eliminations (pb);
4885 gcc_assert (pb->num_eqs == 0);
4887 for (e = pb->num_geqs - 1; e >= 0; e--)
4888 if (pb->geqs[e].color == omega_red)
4889 result = true;
4891 if (!result)
4892 return false;
4894 for (i = pb->safe_vars; i >= 1; i--)
4896 int ub = 0;
4897 int lb = 0;
4899 for (e = pb->num_geqs - 1; e >= 0; e--)
4901 if (pb->geqs[e].coef[i])
4903 if (pb->geqs[e].coef[i] > 0)
4904 lb |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4906 else
4907 ub |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4911 if (ub == 2 || lb == 2)
4914 if (dump_file && (dump_flags & TDF_DETAILS))
4915 fprintf (dump_file, "checks for upper/lower bounds worked!\n");
4917 if (!omega_reduce_with_subs)
4919 resurrect_subs (pb);
4920 gcc_assert (pb->num_subs == 0);
4923 return true;
4928 if (dump_file && (dump_flags & TDF_DETAILS))
4929 fprintf (dump_file,
4930 "*** Doing potentially expensive elimination tests "
4931 "for red equations\n");
4933 please_no_equalities_in_simplified_problems++;
4934 omega_eliminate_red (pb, true);
4935 please_no_equalities_in_simplified_problems--;
4937 result = false;
4938 gcc_assert (pb->num_eqs == 0);
4940 for (e = pb->num_geqs - 1; e >= 0; e--)
4941 if (pb->geqs[e].color == omega_red)
4942 result = true;
4944 if (dump_file && (dump_flags & TDF_DETAILS))
4946 if (!result)
4947 fprintf (dump_file,
4948 "******************** Redundant Red Equations eliminated!!\n");
4949 else
4950 fprintf (dump_file,
4951 "******************** Red Equations remain\n");
4953 omega_print_problem (dump_file, pb);
4956 if (!omega_reduce_with_subs)
4958 normalize_return_type r;
4960 resurrect_subs (pb);
4961 r = normalize_omega_problem (pb);
4962 gcc_assert (r != normalize_false);
4964 coalesce (pb);
4965 cleanout_wildcards (pb);
4966 gcc_assert (pb->num_subs == 0);
4969 return result;
4972 /* Calls omega_simplify_problem in approximate mode. */
4974 enum omega_result
4975 omega_simplify_approximate (omega_pb pb)
4977 enum omega_result result;
4979 if (dump_file && (dump_flags & TDF_DETAILS))
4980 fprintf (dump_file, "(Entering approximate mode\n");
4982 in_approximate_mode = true;
4983 result = omega_simplify_problem (pb);
4984 in_approximate_mode = false;
4986 gcc_assert (pb->num_vars == pb->safe_vars);
4987 if (!omega_reduce_with_subs)
4988 gcc_assert (pb->num_subs == 0);
4990 if (dump_file && (dump_flags & TDF_DETAILS))
4991 fprintf (dump_file, "Leaving approximate mode)\n");
4993 return result;
4997 /* Simplifies problem PB by eliminating redundant constraints and
4998 reducing the constraints system to a minimal form. Returns
4999 omega_true when the problem was successfully reduced, omega_unknown
5000 when the solver is unable to determine an answer. */
5002 enum omega_result
5003 omega_simplify_problem (omega_pb pb)
5005 int i;
5007 omega_found_reduction = omega_false;
5009 if (!pb->variables_initialized)
5010 omega_initialize_variables (pb);
5012 if (next_key * 3 > MAX_KEYS)
5014 int e;
5016 hash_version++;
5017 next_key = OMEGA_MAX_VARS + 1;
5019 for (e = pb->num_geqs - 1; e >= 0; e--)
5020 pb->geqs[e].touched = 1;
5022 for (i = 0; i < HASH_TABLE_SIZE; i++)
5023 hash_master[i].touched = -1;
5025 pb->hash_version = hash_version;
5028 else if (pb->hash_version != hash_version)
5030 int e;
5032 for (e = pb->num_geqs - 1; e >= 0; e--)
5033 pb->geqs[e].touched = 1;
5035 pb->hash_version = hash_version;
5038 if (pb->num_vars > pb->num_eqs + 3 * pb->safe_vars)
5039 omega_free_eliminations (pb, pb->safe_vars);
5041 if (!may_be_red && pb->num_subs == 0 && pb->safe_vars == 0)
5043 omega_found_reduction = omega_solve_problem (pb, omega_unknown);
5045 if (omega_found_reduction != omega_false
5046 && !return_single_result)
5048 pb->num_geqs = 0;
5049 pb->num_eqs = 0;
5050 (*omega_when_reduced) (pb);
5053 return omega_found_reduction;
5056 omega_solve_problem (pb, omega_simplify);
5058 if (omega_found_reduction != omega_false)
5060 for (i = 1; omega_safe_var_p (pb, i); i++)
5061 pb->forwarding_address[pb->var[i]] = i;
5063 for (i = 0; i < pb->num_subs; i++)
5064 pb->forwarding_address[pb->subs[i].key] = -i - 1;
5067 if (!omega_reduce_with_subs)
5068 gcc_assert (please_no_equalities_in_simplified_problems
5069 || omega_found_reduction == omega_false
5070 || pb->num_subs == 0);
5072 return omega_found_reduction;
5075 /* Make variable VAR unprotected: it then can be eliminated. */
5077 void
5078 omega_unprotect_variable (omega_pb pb, int var)
5080 int e, idx;
5081 idx = pb->forwarding_address[var];
5083 if (idx < 0)
5085 idx = -1 - idx;
5086 pb->num_subs--;
5088 if (idx < pb->num_subs)
5090 omega_copy_eqn (&pb->subs[idx], &pb->subs[pb->num_subs],
5091 pb->num_vars);
5092 pb->forwarding_address[pb->subs[idx].key] = -idx - 1;
5095 else
5097 int *bring_to_life = XNEWVEC (int, OMEGA_MAX_VARS);
5098 int e2;
5100 for (e = pb->num_subs - 1; e >= 0; e--)
5101 bring_to_life[e] = (pb->subs[e].coef[idx] != 0);
5103 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
5104 if (bring_to_life[e2])
5106 pb->num_vars++;
5107 pb->safe_vars++;
5109 if (pb->safe_vars < pb->num_vars)
5111 for (e = pb->num_geqs - 1; e >= 0; e--)
5113 pb->geqs[e].coef[pb->num_vars] =
5114 pb->geqs[e].coef[pb->safe_vars];
5116 pb->geqs[e].coef[pb->safe_vars] = 0;
5119 for (e = pb->num_eqs - 1; e >= 0; e--)
5121 pb->eqs[e].coef[pb->num_vars] =
5122 pb->eqs[e].coef[pb->safe_vars];
5124 pb->eqs[e].coef[pb->safe_vars] = 0;
5127 for (e = pb->num_subs - 1; e >= 0; e--)
5129 pb->subs[e].coef[pb->num_vars] =
5130 pb->subs[e].coef[pb->safe_vars];
5132 pb->subs[e].coef[pb->safe_vars] = 0;
5135 pb->var[pb->num_vars] = pb->var[pb->safe_vars];
5136 pb->forwarding_address[pb->var[pb->num_vars]] =
5137 pb->num_vars;
5139 else
5141 for (e = pb->num_geqs - 1; e >= 0; e--)
5142 pb->geqs[e].coef[pb->safe_vars] = 0;
5144 for (e = pb->num_eqs - 1; e >= 0; e--)
5145 pb->eqs[e].coef[pb->safe_vars] = 0;
5147 for (e = pb->num_subs - 1; e >= 0; e--)
5148 pb->subs[e].coef[pb->safe_vars] = 0;
5151 pb->var[pb->safe_vars] = pb->subs[e2].key;
5152 pb->forwarding_address[pb->subs[e2].key] = pb->safe_vars;
5154 omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e2]),
5155 pb->num_vars);
5156 pb->eqs[pb->num_eqs++].coef[pb->safe_vars] = -1;
5157 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5159 if (e2 < pb->num_subs - 1)
5160 omega_copy_eqn (&(pb->subs[e2]), &(pb->subs[pb->num_subs - 1]),
5161 pb->num_vars);
5163 pb->num_subs--;
5166 omega_unprotect_1 (pb, &idx, NULL);
5167 free (bring_to_life);
5170 chain_unprotect (pb);
5173 /* Unprotects VAR and simplifies PB. */
5175 enum omega_result
5176 omega_constrain_variable_sign (omega_pb pb, enum omega_eqn_color color,
5177 int var, int sign)
5179 int n_vars = pb->num_vars;
5180 int e, j;
5181 int k = pb->forwarding_address[var];
5183 if (k < 0)
5185 k = -1 - k;
5187 if (sign != 0)
5189 e = pb->num_geqs++;
5190 omega_copy_eqn (&pb->geqs[e], &pb->subs[k], pb->num_vars);
5192 for (j = 0; j <= n_vars; j++)
5193 pb->geqs[e].coef[j] *= sign;
5195 pb->geqs[e].coef[0]--;
5196 pb->geqs[e].touched = 1;
5197 pb->geqs[e].color = color;
5199 else
5201 e = pb->num_eqs++;
5202 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5203 omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5204 pb->eqs[e].color = color;
5207 else if (sign != 0)
5209 e = pb->num_geqs++;
5210 omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
5211 pb->geqs[e].coef[k] = sign;
5212 pb->geqs[e].coef[0] = -1;
5213 pb->geqs[e].touched = 1;
5214 pb->geqs[e].color = color;
5216 else
5218 e = pb->num_eqs++;
5219 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5220 omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5221 pb->eqs[e].coef[k] = 1;
5222 pb->eqs[e].color = color;
5225 omega_unprotect_variable (pb, var);
5226 return omega_simplify_problem (pb);
5229 /* Add an equation "VAR = VALUE" with COLOR to PB. */
5231 void
5232 omega_constrain_variable_value (omega_pb pb, enum omega_eqn_color color,
5233 int var, int value)
5235 int e;
5236 int k = pb->forwarding_address[var];
5238 if (k < 0)
5240 k = -1 - k;
5241 e = pb->num_eqs++;
5242 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5243 omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5244 pb->eqs[e].coef[0] -= value;
5246 else
5248 e = pb->num_eqs++;
5249 omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5250 pb->eqs[e].coef[k] = 1;
5251 pb->eqs[e].coef[0] = -value;
5254 pb->eqs[e].color = color;
5257 /* Return false when the upper and lower bounds are not coupled.
5258 Initialize the bounds LOWER_BOUND and UPPER_BOUND for the values of
5259 variable I. */
5261 bool
5262 omega_query_variable (omega_pb pb, int i, int *lower_bound, int *upper_bound)
5264 int n_vars = pb->num_vars;
5265 int e, j;
5266 bool is_simple;
5267 bool coupled = false;
5269 *lower_bound = neg_infinity;
5270 *upper_bound = pos_infinity;
5271 i = pb->forwarding_address[i];
5273 if (i < 0)
5275 i = -i - 1;
5277 for (j = 1; j <= n_vars; j++)
5278 if (pb->subs[i].coef[j] != 0)
5279 return true;
5281 *upper_bound = *lower_bound = pb->subs[i].coef[0];
5282 return false;
5285 for (e = pb->num_subs - 1; e >= 0; e--)
5286 if (pb->subs[e].coef[i] != 0)
5287 coupled = true;
5289 for (e = pb->num_eqs - 1; e >= 0; e--)
5290 if (pb->eqs[e].coef[i] != 0)
5292 is_simple = true;
5294 for (j = 1; j <= n_vars; j++)
5295 if (i != j && pb->eqs[e].coef[j] != 0)
5297 is_simple = false;
5298 coupled = true;
5299 break;
5302 if (!is_simple)
5303 continue;
5304 else
5306 *lower_bound = *upper_bound =
5307 -pb->eqs[e].coef[i] * pb->eqs[e].coef[0];
5308 return false;
5312 for (e = pb->num_geqs - 1; e >= 0; e--)
5313 if (pb->geqs[e].coef[i] != 0)
5315 if (pb->geqs[e].key == i)
5316 *lower_bound = MAX (*lower_bound, -pb->geqs[e].coef[0]);
5318 else if (pb->geqs[e].key == -i)
5319 *upper_bound = MIN (*upper_bound, pb->geqs[e].coef[0]);
5321 else
5322 coupled = true;
5325 return coupled;
5328 /* Sets the lower bound L and upper bound U for the values of variable
5329 I, and sets COULD_BE_ZERO to true if variable I might take value
5330 zero. LOWER_BOUND and UPPER_BOUND are bounds on the values of
5331 variable I. */
5333 static void
5334 query_coupled_variable (omega_pb pb, int i, int *l, int *u,
5335 bool *could_be_zero, int lower_bound, int upper_bound)
5337 int e, b1, b2;
5338 eqn eqn;
5339 int sign;
5340 int v;
5342 /* Preconditions. */
5343 gcc_assert (abs (pb->forwarding_address[i]) == 1
5344 && pb->num_vars + pb->num_subs == 2
5345 && pb->num_eqs + pb->num_subs == 1);
5347 /* Define variable I in terms of variable V. */
5348 if (pb->forwarding_address[i] == -1)
5350 eqn = &pb->subs[0];
5351 sign = 1;
5352 v = 1;
5354 else
5356 eqn = &pb->eqs[0];
5357 sign = -eqn->coef[1];
5358 v = 2;
5361 for (e = pb->num_geqs - 1; e >= 0; e--)
5362 if (pb->geqs[e].coef[v] != 0)
5364 if (pb->geqs[e].coef[v] == 1)
5365 lower_bound = MAX (lower_bound, -pb->geqs[e].coef[0]);
5367 else
5368 upper_bound = MIN (upper_bound, pb->geqs[e].coef[0]);
5371 if (lower_bound > upper_bound)
5373 *l = pos_infinity;
5374 *u = neg_infinity;
5375 *could_be_zero = 0;
5376 return;
5379 if (lower_bound == neg_infinity)
5381 if (eqn->coef[v] > 0)
5382 b1 = sign * neg_infinity;
5384 else
5385 b1 = -sign * neg_infinity;
5387 else
5388 b1 = sign * (eqn->coef[0] + eqn->coef[v] * lower_bound);
5390 if (upper_bound == pos_infinity)
5392 if (eqn->coef[v] > 0)
5393 b2 = sign * pos_infinity;
5395 else
5396 b2 = -sign * pos_infinity;
5398 else
5399 b2 = sign * (eqn->coef[0] + eqn->coef[v] * upper_bound);
5401 *l = MAX (*l, b1 <= b2 ? b1 : b2);
5402 *u = MIN (*u, b1 <= b2 ? b2 : b1);
5404 *could_be_zero = (*l <= 0 && 0 <= *u
5405 && int_mod (eqn->coef[0], abs (eqn->coef[v])) == 0);
5408 /* Return false when a lower bound L and an upper bound U for variable
5409 I in problem PB have been initialized. */
5411 bool
5412 omega_query_variable_bounds (omega_pb pb, int i, int *l, int *u)
5414 *l = neg_infinity;
5415 *u = pos_infinity;
5417 if (!omega_query_variable (pb, i, l, u)
5418 || (pb->num_vars == 1 && pb->forwarding_address[i] == 1))
5419 return false;
5421 if (abs (pb->forwarding_address[i]) == 1
5422 && pb->num_vars + pb->num_subs == 2
5423 && pb->num_eqs + pb->num_subs == 1)
5425 bool could_be_zero;
5426 query_coupled_variable (pb, i, l, u, &could_be_zero, neg_infinity,
5427 pos_infinity);
5428 return false;
5431 return true;
5434 /* For problem PB, return an integer that represents the classic data
5435 dependence direction in function of the DD_LT, DD_EQ and DD_GT bit
5436 masks that are added to the result. When DIST_KNOWN is true, DIST
5437 is set to the classic data dependence distance. LOWER_BOUND and
5438 UPPER_BOUND are bounds on the value of variable I, for example, it
5439 is possible to narrow the iteration domain with safe approximations
5440 of loop counts, and thus discard some data dependences that cannot
5441 occur. */
5444 omega_query_variable_signs (omega_pb pb, int i, int dd_lt,
5445 int dd_eq, int dd_gt, int lower_bound,
5446 int upper_bound, bool *dist_known, int *dist)
5448 int result;
5449 int l, u;
5450 bool could_be_zero;
5452 l = neg_infinity;
5453 u = pos_infinity;
5455 omega_query_variable (pb, i, &l, &u);
5456 query_coupled_variable (pb, i, &l, &u, &could_be_zero, lower_bound,
5457 upper_bound);
5458 result = 0;
5460 if (l < 0)
5461 result |= dd_gt;
5463 if (u > 0)
5464 result |= dd_lt;
5466 if (could_be_zero)
5467 result |= dd_eq;
5469 if (l == u)
5471 *dist_known = true;
5472 *dist = l;
5474 else
5475 *dist_known = false;
5477 return result;
5480 /* Initialize PB as an Omega problem with NVARS variables and NPROT
5481 safe variables. Safe variables are not eliminated during the
5482 Fourier-Motzkin elimination. Safe variables are all those
5483 variables that are placed at the beginning of the array of
5484 variables: P->var[0, ..., NPROT - 1]. */
5486 omega_pb
5487 omega_alloc_problem (int nvars, int nprot)
5489 omega_pb pb;
5491 gcc_assert (nvars <= OMEGA_MAX_VARS);
5492 omega_initialize ();
5494 /* Allocate and initialize PB. */
5495 pb = XCNEW (struct omega_pb_d);
5496 pb->var = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5497 pb->forwarding_address = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5498 pb->geqs = omega_alloc_eqns (0, OMEGA_MAX_GEQS);
5499 pb->eqs = omega_alloc_eqns (0, OMEGA_MAX_EQS);
5500 pb->subs = omega_alloc_eqns (0, OMEGA_MAX_VARS + 1);
5502 pb->hash_version = hash_version;
5503 pb->num_vars = nvars;
5504 pb->safe_vars = nprot;
5505 pb->variables_initialized = false;
5506 pb->variables_freed = false;
5507 pb->num_eqs = 0;
5508 pb->num_geqs = 0;
5509 pb->num_subs = 0;
5510 return pb;
5513 /* Keeps the state of the initialization. */
5514 static bool omega_initialized = false;
5516 /* Initialization of the Omega solver. */
5518 void
5519 omega_initialize (void)
5521 int i;
5523 if (omega_initialized)
5524 return;
5526 next_wild_card = 0;
5527 next_key = OMEGA_MAX_VARS + 1;
5528 packing = XCNEWVEC (int, OMEGA_MAX_VARS);
5529 fast_lookup = XCNEWVEC (int, MAX_KEYS * 2);
5530 fast_lookup_red = XCNEWVEC (int, MAX_KEYS * 2);
5531 hash_master = omega_alloc_eqns (0, HASH_TABLE_SIZE);
5533 for (i = 0; i < HASH_TABLE_SIZE; i++)
5534 hash_master[i].touched = -1;
5536 sprintf (wild_name[0], "1");
5537 sprintf (wild_name[1], "a");
5538 sprintf (wild_name[2], "b");
5539 sprintf (wild_name[3], "c");
5540 sprintf (wild_name[4], "d");
5541 sprintf (wild_name[5], "e");
5542 sprintf (wild_name[6], "f");
5543 sprintf (wild_name[7], "g");
5544 sprintf (wild_name[8], "h");
5545 sprintf (wild_name[9], "i");
5546 sprintf (wild_name[10], "j");
5547 sprintf (wild_name[11], "k");
5548 sprintf (wild_name[12], "l");
5549 sprintf (wild_name[13], "m");
5550 sprintf (wild_name[14], "n");
5551 sprintf (wild_name[15], "o");
5552 sprintf (wild_name[16], "p");
5553 sprintf (wild_name[17], "q");
5554 sprintf (wild_name[18], "r");
5555 sprintf (wild_name[19], "s");
5556 sprintf (wild_name[20], "t");
5557 sprintf (wild_name[40 - 1], "alpha");
5558 sprintf (wild_name[40 - 2], "beta");
5559 sprintf (wild_name[40 - 3], "gamma");
5560 sprintf (wild_name[40 - 4], "delta");
5561 sprintf (wild_name[40 - 5], "tau");
5562 sprintf (wild_name[40 - 6], "sigma");
5563 sprintf (wild_name[40 - 7], "chi");
5564 sprintf (wild_name[40 - 8], "omega");
5565 sprintf (wild_name[40 - 9], "pi");
5566 sprintf (wild_name[40 - 10], "ni");
5567 sprintf (wild_name[40 - 11], "Alpha");
5568 sprintf (wild_name[40 - 12], "Beta");
5569 sprintf (wild_name[40 - 13], "Gamma");
5570 sprintf (wild_name[40 - 14], "Delta");
5571 sprintf (wild_name[40 - 15], "Tau");
5572 sprintf (wild_name[40 - 16], "Sigma");
5573 sprintf (wild_name[40 - 17], "Chi");
5574 sprintf (wild_name[40 - 18], "Omega");
5575 sprintf (wild_name[40 - 19], "xxx");
5577 omega_initialized = true;