gcc/ChangeLog
[official-gcc.git] / gcc / omega.c
blob8829a71a91db5e9cf85414311637d8c87df89e29
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-2013 Free Software Foundation, Inc.
9 Contributed by Sebastian Pop <sebastian.pop@inria.fr>
11 This file is part of GCC.
13 GCC is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free
15 Software Foundation; either version 3, or (at your option) any later
16 version.
18 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
19 WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
23 You should have received a copy of the GNU General Public License
24 along with GCC; see the file COPYING3. If not see
25 <http://www.gnu.org/licenses/>. */
27 /* For a detailed description, see "Constraint-Based Array Dependence
28 Analysis" William Pugh, David Wonnacott, TOPLAS'98 and David
29 Wonnacott's thesis:
30 ftp://ftp.cs.umd.edu/pub/omega/davewThesis/davewThesis.ps.gz
33 #include "config.h"
34 #include "system.h"
35 #include "coretypes.h"
36 #include "tree.h"
37 #include "diagnostic-core.h"
38 #include "dumpfile.h"
39 #include "omega.h"
41 /* When set to true, keep substitution variables. When set to false,
42 resurrect substitution variables (convert substitutions back to EQs). */
43 static bool omega_reduce_with_subs = true;
45 /* When set to true, omega_simplify_problem checks for problem with no
46 solutions, calling verify_omega_pb. */
47 static bool omega_verify_simplification = false;
49 /* When set to true, only produce a single simplified result. */
50 static bool omega_single_result = false;
52 /* Set return_single_result to 1 when omega_single_result is true. */
53 static int return_single_result = 0;
55 /* Hash table for equations generated by the solver. */
56 #define HASH_TABLE_SIZE PARAM_VALUE (PARAM_OMEGA_HASH_TABLE_SIZE)
57 #define MAX_KEYS PARAM_VALUE (PARAM_OMEGA_MAX_KEYS)
58 static eqn hash_master;
59 static int next_key;
60 static int hash_version = 0;
62 /* Set to true for making the solver enter in approximation mode. */
63 static bool in_approximate_mode = false;
65 /* When set to zero, the solver is allowed to add new equalities to
66 the problem to be solved. */
67 static int conservative = 0;
69 /* Set to omega_true when the problem was successfully reduced, set to
70 omega_unknown when the solver is unable to determine an answer. */
71 static enum omega_result omega_found_reduction;
73 /* Set to true when the solver is allowed to add omega_red equations. */
74 static bool create_color = false;
76 /* Set to nonzero when the problem to be solved can be reduced. */
77 static int may_be_red = 0;
79 /* When false, there should be no substitution equations in the
80 simplified problem. */
81 static int please_no_equalities_in_simplified_problems = 0;
83 /* Variables names for pretty printing. */
84 static char wild_name[200][40];
86 /* Pointer to the void problem. */
87 static omega_pb no_problem = (omega_pb) 0;
89 /* Pointer to the problem to be solved. */
90 static omega_pb original_problem = (omega_pb) 0;
93 /* Return the integer A divided by B. */
95 static inline int
96 int_div (int a, int b)
98 if (a > 0)
99 return a/b;
100 else
101 return -((-a + b - 1)/b);
104 /* Return the integer A modulo B. */
106 static inline int
107 int_mod (int a, int b)
109 return a - b * int_div (a, b);
112 /* Test whether equation E is red. */
114 static inline bool
115 omega_eqn_is_red (eqn e, int desired_res)
117 return (desired_res == omega_simplify && e->color == omega_red);
120 /* Return a string for VARIABLE. */
122 static inline char *
123 omega_var_to_str (int variable)
125 if (0 <= variable && variable <= 20)
126 return wild_name[variable];
128 if (-20 < variable && variable < 0)
129 return wild_name[40 + variable];
131 /* Collapse all the entries that would have overflowed. */
132 return wild_name[21];
135 /* Return a string for variable I in problem PB. */
137 static inline char *
138 omega_variable_to_str (omega_pb pb, int i)
140 return omega_var_to_str (pb->var[i]);
143 /* Do nothing function: used for default initializations. */
145 void
146 omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
150 void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
152 /* Print to FILE from PB equation E with all its coefficients
153 multiplied by C. */
155 static void
156 omega_print_term (FILE *file, omega_pb pb, eqn e, int c)
158 int i;
159 bool first = true;
160 int n = pb->num_vars;
161 int went_first = -1;
163 for (i = 1; i <= n; i++)
164 if (c * e->coef[i] > 0)
166 first = false;
167 went_first = i;
169 if (c * e->coef[i] == 1)
170 fprintf (file, "%s", omega_variable_to_str (pb, i));
171 else
172 fprintf (file, "%d * %s", c * e->coef[i],
173 omega_variable_to_str (pb, i));
174 break;
177 for (i = 1; i <= n; i++)
178 if (i != went_first && c * e->coef[i] != 0)
180 if (!first && c * e->coef[i] > 0)
181 fprintf (file, " + ");
183 first = false;
185 if (c * e->coef[i] == 1)
186 fprintf (file, "%s", omega_variable_to_str (pb, i));
187 else if (c * e->coef[i] == -1)
188 fprintf (file, " - %s", omega_variable_to_str (pb, i));
189 else
190 fprintf (file, "%d * %s", c * e->coef[i],
191 omega_variable_to_str (pb, i));
194 if (!first && c * e->coef[0] > 0)
195 fprintf (file, " + ");
197 if (first || c * e->coef[0] != 0)
198 fprintf (file, "%d", c * e->coef[0]);
201 /* Print to FILE the equation E of problem PB. */
203 void
204 omega_print_eqn (FILE *file, omega_pb pb, eqn e, bool test, int extra)
206 int i;
207 int n = pb->num_vars + extra;
208 bool is_lt = test && e->coef[0] == -1;
209 bool first;
211 if (test)
213 if (e->touched)
214 fprintf (file, "!");
216 else if (e->key != 0)
217 fprintf (file, "%d: ", e->key);
220 if (e->color == omega_red)
221 fprintf (file, "[");
223 first = true;
225 for (i = is_lt ? 1 : 0; i <= n; i++)
226 if (e->coef[i] < 0)
228 if (!first)
229 fprintf (file, " + ");
230 else
231 first = false;
233 if (i == 0)
234 fprintf (file, "%d", -e->coef[i]);
235 else if (e->coef[i] == -1)
236 fprintf (file, "%s", omega_variable_to_str (pb, i));
237 else
238 fprintf (file, "%d * %s", -e->coef[i],
239 omega_variable_to_str (pb, i));
242 if (first)
244 if (is_lt)
246 fprintf (file, "1");
247 is_lt = false;
249 else
250 fprintf (file, "0");
253 if (test == 0)
254 fprintf (file, " = ");
255 else if (is_lt)
256 fprintf (file, " < ");
257 else
258 fprintf (file, " <= ");
260 first = true;
262 for (i = 0; i <= n; i++)
263 if (e->coef[i] > 0)
265 if (!first)
266 fprintf (file, " + ");
267 else
268 first = false;
270 if (i == 0)
271 fprintf (file, "%d", e->coef[i]);
272 else if (e->coef[i] == 1)
273 fprintf (file, "%s", omega_variable_to_str (pb, i));
274 else
275 fprintf (file, "%d * %s", e->coef[i],
276 omega_variable_to_str (pb, i));
279 if (first)
280 fprintf (file, "0");
282 if (e->color == omega_red)
283 fprintf (file, "]");
286 /* Print to FILE all the variables of problem PB. */
288 static void
289 omega_print_vars (FILE *file, omega_pb pb)
291 int i;
293 fprintf (file, "variables = ");
295 if (pb->safe_vars > 0)
296 fprintf (file, "protected (");
298 for (i = 1; i <= pb->num_vars; i++)
300 fprintf (file, "%s", omega_variable_to_str (pb, i));
302 if (i == pb->safe_vars)
303 fprintf (file, ")");
305 if (i < pb->num_vars)
306 fprintf (file, ", ");
309 fprintf (file, "\n");
312 /* Dump problem PB. */
314 DEBUG_FUNCTION void
315 debug (omega_pb_d &ref)
317 omega_print_problem (stderr, &ref);
320 DEBUG_FUNCTION void
321 debug (omega_pb_d *ptr)
323 if (ptr)
324 debug (*ptr);
325 else
326 fprintf (stderr, "<nil>\n");
329 /* Debug problem PB. */
331 DEBUG_FUNCTION void
332 debug_omega_problem (omega_pb pb)
334 omega_print_problem (stderr, pb);
337 /* Print to FILE problem PB. */
339 void
340 omega_print_problem (FILE *file, omega_pb pb)
342 int e;
344 if (!pb->variables_initialized)
345 omega_initialize_variables (pb);
347 omega_print_vars (file, pb);
349 for (e = 0; e < pb->num_eqs; e++)
351 omega_print_eq (file, pb, &pb->eqs[e]);
352 fprintf (file, "\n");
355 fprintf (file, "Done with EQ\n");
357 for (e = 0; e < pb->num_geqs; e++)
359 omega_print_geq (file, pb, &pb->geqs[e]);
360 fprintf (file, "\n");
363 fprintf (file, "Done with GEQ\n");
365 for (e = 0; e < pb->num_subs; e++)
367 eqn eq = &pb->subs[e];
369 if (eq->color == omega_red)
370 fprintf (file, "[");
372 if (eq->key > 0)
373 fprintf (file, "%s := ", omega_var_to_str (eq->key));
374 else
375 fprintf (file, "#%d := ", eq->key);
377 omega_print_term (file, pb, eq, 1);
379 if (eq->color == omega_red)
380 fprintf (file, "]");
382 fprintf (file, "\n");
386 /* Return the number of equations in PB tagged omega_red. */
389 omega_count_red_equations (omega_pb pb)
391 int e, i;
392 int result = 0;
394 for (e = 0; e < pb->num_eqs; e++)
395 if (pb->eqs[e].color == omega_red)
397 for (i = pb->num_vars; i > 0; i--)
398 if (pb->geqs[e].coef[i])
399 break;
401 if (i == 0 && pb->geqs[e].coef[0] == 1)
402 return 0;
403 else
404 result += 2;
407 for (e = 0; e < pb->num_geqs; e++)
408 if (pb->geqs[e].color == omega_red)
409 result += 1;
411 for (e = 0; e < pb->num_subs; e++)
412 if (pb->subs[e].color == omega_red)
413 result += 2;
415 return result;
418 /* Print to FILE all the equations in PB that are tagged omega_red. */
420 void
421 omega_print_red_equations (FILE *file, omega_pb pb)
423 int e;
425 if (!pb->variables_initialized)
426 omega_initialize_variables (pb);
428 omega_print_vars (file, pb);
430 for (e = 0; e < pb->num_eqs; e++)
431 if (pb->eqs[e].color == omega_red)
433 omega_print_eq (file, pb, &pb->eqs[e]);
434 fprintf (file, "\n");
437 for (e = 0; e < pb->num_geqs; e++)
438 if (pb->geqs[e].color == omega_red)
440 omega_print_geq (file, pb, &pb->geqs[e]);
441 fprintf (file, "\n");
444 for (e = 0; e < pb->num_subs; e++)
445 if (pb->subs[e].color == omega_red)
447 eqn eq = &pb->subs[e];
448 fprintf (file, "[");
450 if (eq->key > 0)
451 fprintf (file, "%s := ", omega_var_to_str (eq->key));
452 else
453 fprintf (file, "#%d := ", eq->key);
455 omega_print_term (file, pb, eq, 1);
456 fprintf (file, "]\n");
460 /* Pretty print PB to FILE. */
462 void
463 omega_pretty_print_problem (FILE *file, omega_pb pb)
465 int e, v, v1, v2, v3, t;
466 bool *live = XNEWVEC (bool, OMEGA_MAX_GEQS);
467 int stuffPrinted = 0;
468 bool change;
470 typedef enum {
471 none, le, lt
472 } partial_order_type;
474 partial_order_type **po = XNEWVEC (partial_order_type *,
475 OMEGA_MAX_VARS * OMEGA_MAX_VARS);
476 int **po_eq = XNEWVEC (int *, OMEGA_MAX_VARS * OMEGA_MAX_VARS);
477 int *last_links = XNEWVEC (int, OMEGA_MAX_VARS);
478 int *first_links = XNEWVEC (int, OMEGA_MAX_VARS);
479 int *chain_length = XNEWVEC (int, OMEGA_MAX_VARS);
480 int *chain = XNEWVEC (int, OMEGA_MAX_VARS);
481 int i, m;
482 bool multiprint;
484 if (!pb->variables_initialized)
485 omega_initialize_variables (pb);
487 if (pb->num_vars > 0)
489 omega_eliminate_redundant (pb, false);
491 for (e = 0; e < pb->num_eqs; e++)
493 if (stuffPrinted)
494 fprintf (file, "; ");
496 stuffPrinted = 1;
497 omega_print_eq (file, pb, &pb->eqs[e]);
500 for (e = 0; e < pb->num_geqs; e++)
501 live[e] = true;
503 while (1)
505 for (v = 1; v <= pb->num_vars; v++)
507 last_links[v] = first_links[v] = 0;
508 chain_length[v] = 0;
510 for (v2 = 1; v2 <= pb->num_vars; v2++)
511 po[v][v2] = none;
514 for (e = 0; e < pb->num_geqs; e++)
515 if (live[e])
517 for (v = 1; v <= pb->num_vars; v++)
518 if (pb->geqs[e].coef[v] == 1)
519 first_links[v]++;
520 else if (pb->geqs[e].coef[v] == -1)
521 last_links[v]++;
523 v1 = pb->num_vars;
525 while (v1 > 0 && pb->geqs[e].coef[v1] == 0)
526 v1--;
528 v2 = v1 - 1;
530 while (v2 > 0 && pb->geqs[e].coef[v2] == 0)
531 v2--;
533 v3 = v2 - 1;
535 while (v3 > 0 && pb->geqs[e].coef[v3] == 0)
536 v3--;
538 if (pb->geqs[e].coef[0] > 0 || pb->geqs[e].coef[0] < -1
539 || v2 <= 0 || v3 > 0
540 || pb->geqs[e].coef[v1] * pb->geqs[e].coef[v2] != -1)
542 /* Not a partial order relation. */
544 else
546 if (pb->geqs[e].coef[v1] == 1)
548 v3 = v2;
549 v2 = v1;
550 v1 = v3;
553 /* Relation is v1 <= v2 or v1 < v2. */
554 po[v1][v2] = ((pb->geqs[e].coef[0] == 0) ? le : lt);
555 po_eq[v1][v2] = e;
558 for (v = 1; v <= pb->num_vars; v++)
559 chain_length[v] = last_links[v];
561 /* Just in case pb->num_vars <= 0. */
562 change = false;
563 for (t = 0; t < pb->num_vars; t++)
565 change = false;
567 for (v1 = 1; v1 <= pb->num_vars; v1++)
568 for (v2 = 1; v2 <= pb->num_vars; v2++)
569 if (po[v1][v2] != none &&
570 chain_length[v1] <= chain_length[v2])
572 chain_length[v1] = chain_length[v2] + 1;
573 change = true;
577 /* Caught in cycle. */
578 gcc_assert (!change);
580 for (v1 = 1; v1 <= pb->num_vars; v1++)
581 if (chain_length[v1] == 0)
582 first_links[v1] = 0;
584 v = 1;
586 for (v1 = 2; v1 <= pb->num_vars; v1++)
587 if (chain_length[v1] + first_links[v1] >
588 chain_length[v] + first_links[v])
589 v = v1;
591 if (chain_length[v] + first_links[v] == 0)
592 break;
594 if (stuffPrinted)
595 fprintf (file, "; ");
597 stuffPrinted = 1;
599 /* Chain starts at v. */
601 int tmp;
602 bool first = true;
604 for (e = 0; e < pb->num_geqs; e++)
605 if (live[e] && pb->geqs[e].coef[v] == 1)
607 if (!first)
608 fprintf (file, ", ");
610 tmp = pb->geqs[e].coef[v];
611 pb->geqs[e].coef[v] = 0;
612 omega_print_term (file, pb, &pb->geqs[e], -1);
613 pb->geqs[e].coef[v] = tmp;
614 live[e] = false;
615 first = false;
618 if (!first)
619 fprintf (file, " <= ");
622 /* Find chain. */
623 chain[0] = v;
624 m = 1;
625 while (1)
627 /* Print chain. */
628 for (v2 = 1; v2 <= pb->num_vars; v2++)
629 if (po[v][v2] && chain_length[v] == 1 + chain_length[v2])
630 break;
632 if (v2 > pb->num_vars)
633 break;
635 chain[m++] = v2;
636 v = v2;
639 fprintf (file, "%s", omega_variable_to_str (pb, chain[0]));
641 for (multiprint = false, i = 1; i < m; i++)
643 v = chain[i - 1];
644 v2 = chain[i];
646 if (po[v][v2] == le)
647 fprintf (file, " <= ");
648 else
649 fprintf (file, " < ");
651 fprintf (file, "%s", omega_variable_to_str (pb, v2));
652 live[po_eq[v][v2]] = false;
654 if (!multiprint && i < m - 1)
655 for (v3 = 1; v3 <= pb->num_vars; v3++)
657 if (v == v3 || v2 == v3
658 || po[v][v2] != po[v][v3]
659 || po[v2][chain[i + 1]] != po[v3][chain[i + 1]])
660 continue;
662 fprintf (file, ",%s", omega_variable_to_str (pb, v3));
663 live[po_eq[v][v3]] = false;
664 live[po_eq[v3][chain[i + 1]]] = false;
665 multiprint = true;
667 else
668 multiprint = false;
671 v = chain[m - 1];
672 /* Print last_links. */
674 int tmp;
675 bool first = true;
677 for (e = 0; e < pb->num_geqs; e++)
678 if (live[e] && pb->geqs[e].coef[v] == -1)
680 if (!first)
681 fprintf (file, ", ");
682 else
683 fprintf (file, " <= ");
685 tmp = pb->geqs[e].coef[v];
686 pb->geqs[e].coef[v] = 0;
687 omega_print_term (file, pb, &pb->geqs[e], 1);
688 pb->geqs[e].coef[v] = tmp;
689 live[e] = false;
690 first = false;
695 for (e = 0; e < pb->num_geqs; e++)
696 if (live[e])
698 if (stuffPrinted)
699 fprintf (file, "; ");
700 stuffPrinted = 1;
701 omega_print_geq (file, pb, &pb->geqs[e]);
704 for (e = 0; e < pb->num_subs; e++)
706 eqn eq = &pb->subs[e];
708 if (stuffPrinted)
709 fprintf (file, "; ");
711 stuffPrinted = 1;
713 if (eq->key > 0)
714 fprintf (file, "%s := ", omega_var_to_str (eq->key));
715 else
716 fprintf (file, "#%d := ", eq->key);
718 omega_print_term (file, pb, eq, 1);
722 free (live);
723 free (po);
724 free (po_eq);
725 free (last_links);
726 free (first_links);
727 free (chain_length);
728 free (chain);
731 /* Assign to variable I in PB the next wildcard name. The name of a
732 wildcard is a negative number. */
733 static int next_wild_card = 0;
735 static void
736 omega_name_wild_card (omega_pb pb, int i)
738 --next_wild_card;
739 if (next_wild_card < -PARAM_VALUE (PARAM_OMEGA_MAX_WILD_CARDS))
740 next_wild_card = -1;
741 pb->var[i] = next_wild_card;
744 /* Return the index of the last protected (or safe) variable in PB,
745 after having added a new wildcard variable. */
747 static int
748 omega_add_new_wild_card (omega_pb pb)
750 int e;
751 int i = ++pb->safe_vars;
752 pb->num_vars++;
754 /* Make a free place in the protected (safe) variables, by moving
755 the non protected variable pointed by "I" at the end, ie. at
756 offset pb->num_vars. */
757 if (pb->num_vars != i)
759 /* Move "I" for all the inequalities. */
760 for (e = pb->num_geqs - 1; e >= 0; e--)
762 if (pb->geqs[e].coef[i])
763 pb->geqs[e].touched = 1;
765 pb->geqs[e].coef[pb->num_vars] = pb->geqs[e].coef[i];
768 /* Move "I" for all the equalities. */
769 for (e = pb->num_eqs - 1; e >= 0; e--)
770 pb->eqs[e].coef[pb->num_vars] = pb->eqs[e].coef[i];
772 /* Move "I" for all the substitutions. */
773 for (e = pb->num_subs - 1; e >= 0; e--)
774 pb->subs[e].coef[pb->num_vars] = pb->subs[e].coef[i];
776 /* Move the identifier. */
777 pb->var[pb->num_vars] = pb->var[i];
780 /* Initialize at zero all the coefficients */
781 for (e = pb->num_geqs - 1; e >= 0; e--)
782 pb->geqs[e].coef[i] = 0;
784 for (e = pb->num_eqs - 1; e >= 0; e--)
785 pb->eqs[e].coef[i] = 0;
787 for (e = pb->num_subs - 1; e >= 0; e--)
788 pb->subs[e].coef[i] = 0;
790 /* And give it a name. */
791 omega_name_wild_card (pb, i);
792 return i;
795 /* Delete inequality E from problem PB that has N_VARS variables. */
797 static void
798 omega_delete_geq (omega_pb pb, int e, int n_vars)
800 if (dump_file && (dump_flags & TDF_DETAILS))
802 fprintf (dump_file, "Deleting %d (last:%d): ", e, pb->num_geqs - 1);
803 omega_print_geq (dump_file, pb, &pb->geqs[e]);
804 fprintf (dump_file, "\n");
807 if (e < pb->num_geqs - 1)
808 omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
810 pb->num_geqs--;
813 /* Delete extra inequality E from problem PB that has N_VARS
814 variables. */
816 static void
817 omega_delete_geq_extra (omega_pb pb, int e, int n_vars)
819 if (dump_file && (dump_flags & TDF_DETAILS))
821 fprintf (dump_file, "Deleting %d: ",e);
822 omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
823 fprintf (dump_file, "\n");
826 if (e < pb->num_geqs - 1)
827 omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
829 pb->num_geqs--;
833 /* Remove variable I from problem PB. */
835 static void
836 omega_delete_variable (omega_pb pb, int i)
838 int n_vars = pb->num_vars;
839 int e;
841 if (omega_safe_var_p (pb, i))
843 int j = pb->safe_vars;
845 for (e = pb->num_geqs - 1; e >= 0; e--)
847 pb->geqs[e].touched = 1;
848 pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
849 pb->geqs[e].coef[j] = pb->geqs[e].coef[n_vars];
852 for (e = pb->num_eqs - 1; e >= 0; e--)
854 pb->eqs[e].coef[i] = pb->eqs[e].coef[j];
855 pb->eqs[e].coef[j] = pb->eqs[e].coef[n_vars];
858 for (e = pb->num_subs - 1; e >= 0; e--)
860 pb->subs[e].coef[i] = pb->subs[e].coef[j];
861 pb->subs[e].coef[j] = pb->subs[e].coef[n_vars];
864 pb->var[i] = pb->var[j];
865 pb->var[j] = pb->var[n_vars];
867 else if (i < n_vars)
869 for (e = pb->num_geqs - 1; e >= 0; e--)
870 if (pb->geqs[e].coef[n_vars])
872 pb->geqs[e].coef[i] = pb->geqs[e].coef[n_vars];
873 pb->geqs[e].touched = 1;
876 for (e = pb->num_eqs - 1; e >= 0; e--)
877 pb->eqs[e].coef[i] = pb->eqs[e].coef[n_vars];
879 for (e = pb->num_subs - 1; e >= 0; e--)
880 pb->subs[e].coef[i] = pb->subs[e].coef[n_vars];
882 pb->var[i] = pb->var[n_vars];
885 if (omega_safe_var_p (pb, i))
886 pb->safe_vars--;
888 pb->num_vars--;
891 /* Because the coefficients of an equation are sparse, PACKING records
892 indices for non null coefficients. */
893 static int *packing;
895 /* Set up the coefficients of PACKING, following the coefficients of
896 equation EQN that has NUM_VARS variables. */
898 static inline int
899 setup_packing (eqn eqn, int num_vars)
901 int k;
902 int n = 0;
904 for (k = num_vars; k >= 0; k--)
905 if (eqn->coef[k])
906 packing[n++] = k;
908 return n;
911 /* Computes a linear combination of EQ and SUB at VAR with coefficient
912 C, such that EQ->coef[VAR] is set to 0. TOP_VAR is the number of
913 non null indices of SUB stored in PACKING. */
915 static inline void
916 omega_substitute_red_1 (eqn eq, eqn sub, int var, int c, bool *found_black,
917 int top_var)
919 if (eq->coef[var] != 0)
921 if (eq->color == omega_black)
922 *found_black = true;
923 else
925 int j, k = eq->coef[var];
927 eq->coef[var] = 0;
929 for (j = top_var; j >= 0; j--)
930 eq->coef[packing[j]] -= sub->coef[packing[j]] * k * c;
935 /* Substitute in PB variable VAR with "C * SUB". */
937 static void
938 omega_substitute_red (omega_pb pb, eqn sub, int var, int c, bool *found_black)
940 int e, top_var = setup_packing (sub, pb->num_vars);
942 *found_black = false;
944 if (dump_file && (dump_flags & TDF_DETAILS))
946 if (sub->color == omega_red)
947 fprintf (dump_file, "[");
949 fprintf (dump_file, "substituting using %s := ",
950 omega_variable_to_str (pb, var));
951 omega_print_term (dump_file, pb, sub, -c);
953 if (sub->color == omega_red)
954 fprintf (dump_file, "]");
956 fprintf (dump_file, "\n");
957 omega_print_vars (dump_file, pb);
960 for (e = pb->num_eqs - 1; e >= 0; e--)
962 eqn eqn = &(pb->eqs[e]);
964 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
966 if (dump_file && (dump_flags & TDF_DETAILS))
968 omega_print_eq (dump_file, pb, eqn);
969 fprintf (dump_file, "\n");
973 for (e = pb->num_geqs - 1; e >= 0; e--)
975 eqn eqn = &(pb->geqs[e]);
977 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
979 if (eqn->coef[var] && eqn->color == omega_red)
980 eqn->touched = 1;
982 if (dump_file && (dump_flags & TDF_DETAILS))
984 omega_print_geq (dump_file, pb, eqn);
985 fprintf (dump_file, "\n");
989 for (e = pb->num_subs - 1; e >= 0; e--)
991 eqn eqn = &(pb->subs[e]);
993 omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
995 if (dump_file && (dump_flags & TDF_DETAILS))
997 fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
998 omega_print_term (dump_file, pb, eqn, 1);
999 fprintf (dump_file, "\n");
1003 if (dump_file && (dump_flags & TDF_DETAILS))
1004 fprintf (dump_file, "---\n\n");
1006 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1007 *found_black = true;
1010 /* Substitute in PB variable VAR with "C * SUB". */
1012 static void
1013 omega_substitute (omega_pb pb, eqn sub, int var, int c)
1015 int e, j, j0;
1016 int top_var = setup_packing (sub, pb->num_vars);
1018 if (dump_file && (dump_flags & TDF_DETAILS))
1020 fprintf (dump_file, "substituting using %s := ",
1021 omega_variable_to_str (pb, var));
1022 omega_print_term (dump_file, pb, sub, -c);
1023 fprintf (dump_file, "\n");
1024 omega_print_vars (dump_file, pb);
1027 if (top_var < 0)
1029 for (e = pb->num_eqs - 1; e >= 0; e--)
1030 pb->eqs[e].coef[var] = 0;
1032 for (e = pb->num_geqs - 1; e >= 0; e--)
1033 if (pb->geqs[e].coef[var] != 0)
1035 pb->geqs[e].touched = 1;
1036 pb->geqs[e].coef[var] = 0;
1039 for (e = pb->num_subs - 1; e >= 0; e--)
1040 pb->subs[e].coef[var] = 0;
1042 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1044 int k;
1045 eqn eqn = &(pb->subs[pb->num_subs++]);
1047 for (k = pb->num_vars; k >= 0; k--)
1048 eqn->coef[k] = 0;
1050 eqn->key = pb->var[var];
1051 eqn->color = omega_black;
1054 else if (top_var == 0 && packing[0] == 0)
1056 c = -sub->coef[0] * c;
1058 for (e = pb->num_eqs - 1; e >= 0; e--)
1060 pb->eqs[e].coef[0] += pb->eqs[e].coef[var] * c;
1061 pb->eqs[e].coef[var] = 0;
1064 for (e = pb->num_geqs - 1; e >= 0; e--)
1065 if (pb->geqs[e].coef[var] != 0)
1067 pb->geqs[e].coef[0] += pb->geqs[e].coef[var] * c;
1068 pb->geqs[e].coef[var] = 0;
1069 pb->geqs[e].touched = 1;
1072 for (e = pb->num_subs - 1; e >= 0; e--)
1074 pb->subs[e].coef[0] += pb->subs[e].coef[var] * c;
1075 pb->subs[e].coef[var] = 0;
1078 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1080 int k;
1081 eqn eqn = &(pb->subs[pb->num_subs++]);
1083 for (k = pb->num_vars; k >= 1; k--)
1084 eqn->coef[k] = 0;
1086 eqn->coef[0] = c;
1087 eqn->key = pb->var[var];
1088 eqn->color = omega_black;
1091 if (dump_file && (dump_flags & TDF_DETAILS))
1093 fprintf (dump_file, "---\n\n");
1094 omega_print_problem (dump_file, pb);
1095 fprintf (dump_file, "===\n\n");
1098 else
1100 for (e = pb->num_eqs - 1; e >= 0; e--)
1102 eqn eqn = &(pb->eqs[e]);
1103 int k = eqn->coef[var];
1105 if (k != 0)
1107 k = c * k;
1108 eqn->coef[var] = 0;
1110 for (j = top_var; j >= 0; j--)
1112 j0 = packing[j];
1113 eqn->coef[j0] -= sub->coef[j0] * k;
1117 if (dump_file && (dump_flags & TDF_DETAILS))
1119 omega_print_eq (dump_file, pb, eqn);
1120 fprintf (dump_file, "\n");
1124 for (e = pb->num_geqs - 1; e >= 0; e--)
1126 eqn eqn = &(pb->geqs[e]);
1127 int k = eqn->coef[var];
1129 if (k != 0)
1131 k = c * k;
1132 eqn->touched = 1;
1133 eqn->coef[var] = 0;
1135 for (j = top_var; j >= 0; j--)
1137 j0 = packing[j];
1138 eqn->coef[j0] -= sub->coef[j0] * k;
1142 if (dump_file && (dump_flags & TDF_DETAILS))
1144 omega_print_geq (dump_file, pb, eqn);
1145 fprintf (dump_file, "\n");
1149 for (e = pb->num_subs - 1; e >= 0; e--)
1151 eqn eqn = &(pb->subs[e]);
1152 int k = eqn->coef[var];
1154 if (k != 0)
1156 k = c * k;
1157 eqn->coef[var] = 0;
1159 for (j = top_var; j >= 0; j--)
1161 j0 = packing[j];
1162 eqn->coef[j0] -= sub->coef[j0] * k;
1166 if (dump_file && (dump_flags & TDF_DETAILS))
1168 fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
1169 omega_print_term (dump_file, pb, eqn, 1);
1170 fprintf (dump_file, "\n");
1174 if (dump_file && (dump_flags & TDF_DETAILS))
1176 fprintf (dump_file, "---\n\n");
1177 omega_print_problem (dump_file, pb);
1178 fprintf (dump_file, "===\n\n");
1181 if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1183 int k;
1184 eqn eqn = &(pb->subs[pb->num_subs++]);
1185 c = -c;
1187 for (k = pb->num_vars; k >= 0; k--)
1188 eqn->coef[k] = c * (sub->coef[k]);
1190 eqn->key = pb->var[var];
1191 eqn->color = sub->color;
1196 /* Solve e = factor alpha for x_j and substitute. */
1198 static void
1199 omega_do_mod (omega_pb pb, int factor, int e, int j)
1201 int k, i;
1202 eqn eq = omega_alloc_eqns (0, 1);
1203 int nfactor;
1204 bool kill_j = false;
1206 omega_copy_eqn (eq, &pb->eqs[e], pb->num_vars);
1208 for (k = pb->num_vars; k >= 0; k--)
1210 eq->coef[k] = int_mod (eq->coef[k], factor);
1212 if (2 * eq->coef[k] >= factor)
1213 eq->coef[k] -= factor;
1216 nfactor = eq->coef[j];
1218 if (omega_safe_var_p (pb, j) && !omega_wildcard_p (pb, j))
1220 i = omega_add_new_wild_card (pb);
1221 eq->coef[pb->num_vars] = eq->coef[i];
1222 eq->coef[j] = 0;
1223 eq->coef[i] = -factor;
1224 kill_j = true;
1226 else
1228 eq->coef[j] = -factor;
1229 if (!omega_wildcard_p (pb, j))
1230 omega_name_wild_card (pb, j);
1233 omega_substitute (pb, eq, j, nfactor);
1235 for (k = pb->num_vars; k >= 0; k--)
1236 pb->eqs[e].coef[k] = pb->eqs[e].coef[k] / factor;
1238 if (kill_j)
1239 omega_delete_variable (pb, j);
1241 if (dump_file && (dump_flags & TDF_DETAILS))
1243 fprintf (dump_file, "Mod-ing and normalizing produces:\n");
1244 omega_print_problem (dump_file, pb);
1247 omega_free_eqns (eq, 1);
1250 /* Multiplies by -1 inequality E. */
1252 void
1253 omega_negate_geq (omega_pb pb, int e)
1255 int i;
1257 for (i = pb->num_vars; i >= 0; i--)
1258 pb->geqs[e].coef[i] *= -1;
1260 pb->geqs[e].coef[0]--;
1261 pb->geqs[e].touched = 1;
1264 /* Returns OMEGA_TRUE when problem PB has a solution. */
1266 static enum omega_result
1267 verify_omega_pb (omega_pb pb)
1269 enum omega_result result;
1270 int e;
1271 bool any_color = false;
1272 omega_pb tmp_problem = XNEW (struct omega_pb_d);
1274 omega_copy_problem (tmp_problem, pb);
1275 tmp_problem->safe_vars = 0;
1276 tmp_problem->num_subs = 0;
1278 for (e = pb->num_geqs - 1; e >= 0; e--)
1279 if (pb->geqs[e].color == omega_red)
1281 any_color = true;
1282 break;
1285 if (please_no_equalities_in_simplified_problems)
1286 any_color = true;
1288 if (any_color)
1289 original_problem = no_problem;
1290 else
1291 original_problem = pb;
1293 if (dump_file && (dump_flags & TDF_DETAILS))
1295 fprintf (dump_file, "verifying problem");
1297 if (any_color)
1298 fprintf (dump_file, " (color mode)");
1300 fprintf (dump_file, " :\n");
1301 omega_print_problem (dump_file, pb);
1304 result = omega_solve_problem (tmp_problem, omega_unknown);
1305 original_problem = no_problem;
1306 free (tmp_problem);
1308 if (dump_file && (dump_flags & TDF_DETAILS))
1310 if (result != omega_false)
1311 fprintf (dump_file, "verified problem\n");
1312 else
1313 fprintf (dump_file, "disproved problem\n");
1314 omega_print_problem (dump_file, pb);
1317 return result;
1320 /* Add a new equality to problem PB at last position E. */
1322 static void
1323 adding_equality_constraint (omega_pb pb, int e)
1325 if (original_problem != no_problem
1326 && original_problem != pb
1327 && !conservative)
1329 int i, j;
1330 int e2 = original_problem->num_eqs++;
1332 if (dump_file && (dump_flags & TDF_DETAILS))
1333 fprintf (dump_file,
1334 "adding equality constraint %d to outer problem\n", e2);
1335 omega_init_eqn_zero (&original_problem->eqs[e2],
1336 original_problem->num_vars);
1338 for (i = pb->num_vars; i >= 1; i--)
1340 for (j = original_problem->num_vars; j >= 1; j--)
1341 if (original_problem->var[j] == pb->var[i])
1342 break;
1344 if (j <= 0)
1346 if (dump_file && (dump_flags & TDF_DETAILS))
1347 fprintf (dump_file, "retracting\n");
1348 original_problem->num_eqs--;
1349 return;
1351 original_problem->eqs[e2].coef[j] = pb->eqs[e].coef[i];
1354 original_problem->eqs[e2].coef[0] = pb->eqs[e].coef[0];
1356 if (dump_file && (dump_flags & TDF_DETAILS))
1357 omega_print_problem (dump_file, original_problem);
1361 static int *fast_lookup;
1362 static int *fast_lookup_red;
1364 typedef enum {
1365 normalize_false,
1366 normalize_uncoupled,
1367 normalize_coupled
1368 } normalize_return_type;
1370 /* Normalizes PB by removing redundant constraints. Returns
1371 normalize_false when the constraints system has no solution,
1372 otherwise returns normalize_coupled or normalize_uncoupled. */
1374 static normalize_return_type
1375 normalize_omega_problem (omega_pb pb)
1377 int e, i, j, k, n_vars;
1378 int coupled_subscripts = 0;
1380 n_vars = pb->num_vars;
1382 for (e = 0; e < pb->num_geqs; e++)
1384 if (!pb->geqs[e].touched)
1386 if (!single_var_geq (&pb->geqs[e], n_vars))
1387 coupled_subscripts = 1;
1389 else
1391 int g, top_var, i0, hashCode;
1392 int *p = &packing[0];
1394 for (k = 1; k <= n_vars; k++)
1395 if (pb->geqs[e].coef[k])
1396 *(p++) = k;
1398 top_var = (p - &packing[0]) - 1;
1400 if (top_var == -1)
1402 if (pb->geqs[e].coef[0] < 0)
1404 if (dump_file && (dump_flags & TDF_DETAILS))
1406 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1407 fprintf (dump_file, "\nequations have no solution \n");
1409 return normalize_false;
1412 omega_delete_geq (pb, e, n_vars);
1413 e--;
1414 continue;
1416 else if (top_var == 0)
1418 int singlevar = packing[0];
1420 g = pb->geqs[e].coef[singlevar];
1422 if (g > 0)
1424 pb->geqs[e].coef[singlevar] = 1;
1425 pb->geqs[e].key = singlevar;
1427 else
1429 g = -g;
1430 pb->geqs[e].coef[singlevar] = -1;
1431 pb->geqs[e].key = -singlevar;
1434 if (g > 1)
1435 pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1437 else
1439 int g2;
1440 int hash_key_multiplier = 31;
1442 coupled_subscripts = 1;
1443 i0 = top_var;
1444 i = packing[i0--];
1445 g = pb->geqs[e].coef[i];
1446 hashCode = g * (i + 3);
1448 if (g < 0)
1449 g = -g;
1451 for (; i0 >= 0; i0--)
1453 int x;
1455 i = packing[i0];
1456 x = pb->geqs[e].coef[i];
1457 hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1459 if (x < 0)
1460 x = -x;
1462 if (x == 1)
1464 g = 1;
1465 i0--;
1466 break;
1468 else
1469 g = gcd (x, g);
1472 for (; i0 >= 0; i0--)
1474 int x;
1475 i = packing[i0];
1476 x = pb->geqs[e].coef[i];
1477 hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1480 if (g > 1)
1482 pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1483 i0 = top_var;
1484 i = packing[i0--];
1485 pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1486 hashCode = pb->geqs[e].coef[i] * (i + 3);
1488 for (; i0 >= 0; i0--)
1490 i = packing[i0];
1491 pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1492 hashCode = hashCode * hash_key_multiplier * (i + 3)
1493 + pb->geqs[e].coef[i];
1497 g2 = abs (hashCode);
1499 if (dump_file && (dump_flags & TDF_DETAILS))
1501 fprintf (dump_file, "Hash code = %d, eqn = ", hashCode);
1502 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1503 fprintf (dump_file, "\n");
1506 j = g2 % HASH_TABLE_SIZE;
1508 do {
1509 eqn proto = &(hash_master[j]);
1511 if (proto->touched == g2)
1513 if (proto->coef[0] == top_var)
1515 if (hashCode >= 0)
1516 for (i0 = top_var; i0 >= 0; i0--)
1518 i = packing[i0];
1520 if (pb->geqs[e].coef[i] != proto->coef[i])
1521 break;
1523 else
1524 for (i0 = top_var; i0 >= 0; i0--)
1526 i = packing[i0];
1528 if (pb->geqs[e].coef[i] != -proto->coef[i])
1529 break;
1532 if (i0 < 0)
1534 if (hashCode >= 0)
1535 pb->geqs[e].key = proto->key;
1536 else
1537 pb->geqs[e].key = -proto->key;
1538 break;
1542 else if (proto->touched < 0)
1544 omega_init_eqn_zero (proto, pb->num_vars);
1545 if (hashCode >= 0)
1546 for (i0 = top_var; i0 >= 0; i0--)
1548 i = packing[i0];
1549 proto->coef[i] = pb->geqs[e].coef[i];
1551 else
1552 for (i0 = top_var; i0 >= 0; i0--)
1554 i = packing[i0];
1555 proto->coef[i] = -pb->geqs[e].coef[i];
1558 proto->coef[0] = top_var;
1559 proto->touched = g2;
1561 if (dump_file && (dump_flags & TDF_DETAILS))
1562 fprintf (dump_file, " constraint key = %d\n",
1563 next_key);
1565 proto->key = next_key++;
1567 /* Too many hash keys generated. */
1568 gcc_assert (proto->key <= MAX_KEYS);
1570 if (hashCode >= 0)
1571 pb->geqs[e].key = proto->key;
1572 else
1573 pb->geqs[e].key = -proto->key;
1575 break;
1578 j = (j + 1) % HASH_TABLE_SIZE;
1579 } while (1);
1582 pb->geqs[e].touched = 0;
1586 int eKey = pb->geqs[e].key;
1587 int e2;
1588 if (e > 0)
1590 int cTerm = pb->geqs[e].coef[0];
1591 e2 = fast_lookup[MAX_KEYS - eKey];
1593 if (e2 < e && pb->geqs[e2].key == -eKey
1594 && pb->geqs[e2].color == omega_black)
1596 if (pb->geqs[e2].coef[0] < -cTerm)
1598 if (dump_file && (dump_flags & TDF_DETAILS))
1600 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1601 fprintf (dump_file, "\n");
1602 omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1603 fprintf (dump_file,
1604 "\nequations have no solution \n");
1606 return normalize_false;
1609 if (pb->geqs[e2].coef[0] == -cTerm
1610 && (create_color
1611 || pb->geqs[e].color == omega_black))
1613 omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1614 pb->num_vars);
1615 if (pb->geqs[e].color == omega_black)
1616 adding_equality_constraint (pb, pb->num_eqs);
1617 pb->num_eqs++;
1618 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1622 e2 = fast_lookup_red[MAX_KEYS - eKey];
1624 if (e2 < e && pb->geqs[e2].key == -eKey
1625 && pb->geqs[e2].color == omega_red)
1627 if (pb->geqs[e2].coef[0] < -cTerm)
1629 if (dump_file && (dump_flags & TDF_DETAILS))
1631 omega_print_geq (dump_file, pb, &pb->geqs[e]);
1632 fprintf (dump_file, "\n");
1633 omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1634 fprintf (dump_file,
1635 "\nequations have no solution \n");
1637 return normalize_false;
1640 if (pb->geqs[e2].coef[0] == -cTerm && create_color)
1642 omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1643 pb->num_vars);
1644 pb->eqs[pb->num_eqs].color = omega_red;
1645 pb->num_eqs++;
1646 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1650 e2 = fast_lookup[MAX_KEYS + eKey];
1652 if (e2 < e && pb->geqs[e2].key == eKey
1653 && pb->geqs[e2].color == omega_black)
1655 if (pb->geqs[e2].coef[0] > cTerm)
1657 if (pb->geqs[e].color == omega_black)
1659 if (dump_file && (dump_flags & TDF_DETAILS))
1661 fprintf (dump_file,
1662 "Removing Redundant Equation: ");
1663 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1664 fprintf (dump_file, "\n");
1665 fprintf (dump_file,
1666 "[a] Made Redundant by: ");
1667 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1668 fprintf (dump_file, "\n");
1670 pb->geqs[e2].coef[0] = cTerm;
1671 omega_delete_geq (pb, e, n_vars);
1672 e--;
1673 continue;
1676 else
1678 if (dump_file && (dump_flags & TDF_DETAILS))
1680 fprintf (dump_file, "Removing Redundant Equation: ");
1681 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1682 fprintf (dump_file, "\n");
1683 fprintf (dump_file, "[b] Made Redundant by: ");
1684 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1685 fprintf (dump_file, "\n");
1687 omega_delete_geq (pb, e, n_vars);
1688 e--;
1689 continue;
1693 e2 = fast_lookup_red[MAX_KEYS + eKey];
1695 if (e2 < e && pb->geqs[e2].key == eKey
1696 && pb->geqs[e2].color == omega_red)
1698 if (pb->geqs[e2].coef[0] >= cTerm)
1700 if (dump_file && (dump_flags & TDF_DETAILS))
1702 fprintf (dump_file, "Removing Redundant Equation: ");
1703 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1704 fprintf (dump_file, "\n");
1705 fprintf (dump_file, "[c] Made Redundant by: ");
1706 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1707 fprintf (dump_file, "\n");
1709 pb->geqs[e2].coef[0] = cTerm;
1710 pb->geqs[e2].color = pb->geqs[e].color;
1712 else if (pb->geqs[e].color == omega_red)
1714 if (dump_file && (dump_flags & TDF_DETAILS))
1716 fprintf (dump_file, "Removing Redundant Equation: ");
1717 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1718 fprintf (dump_file, "\n");
1719 fprintf (dump_file, "[d] Made Redundant by: ");
1720 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1721 fprintf (dump_file, "\n");
1724 omega_delete_geq (pb, e, n_vars);
1725 e--;
1726 continue;
1731 if (pb->geqs[e].color == omega_red)
1732 fast_lookup_red[MAX_KEYS + eKey] = e;
1733 else
1734 fast_lookup[MAX_KEYS + eKey] = e;
1738 create_color = false;
1739 return coupled_subscripts ? normalize_coupled : normalize_uncoupled;
1742 /* Divide the coefficients of EQN by their gcd. N_VARS is the number
1743 of variables in EQN. */
1745 static inline void
1746 divide_eqn_by_gcd (eqn eqn, int n_vars)
1748 int var, g = 0;
1750 for (var = n_vars; var >= 0; var--)
1751 g = gcd (abs (eqn->coef[var]), g);
1753 if (g)
1754 for (var = n_vars; var >= 0; var--)
1755 eqn->coef[var] = eqn->coef[var] / g;
1758 /* Rewrite some non-safe variables in function of protected
1759 wildcard variables. */
1761 static void
1762 cleanout_wildcards (omega_pb pb)
1764 int e, i, j;
1765 int n_vars = pb->num_vars;
1766 bool renormalize = false;
1768 for (e = pb->num_eqs - 1; e >= 0; e--)
1769 for (i = n_vars; !omega_safe_var_p (pb, i); i--)
1770 if (pb->eqs[e].coef[i] != 0)
1772 /* i is the last nonzero non-safe variable. */
1774 for (j = i - 1; !omega_safe_var_p (pb, j); j--)
1775 if (pb->eqs[e].coef[j] != 0)
1776 break;
1778 /* j is the next nonzero non-safe variable, or points
1779 to a safe variable: it is then a wildcard variable. */
1781 /* Clean it out. */
1782 if (omega_safe_var_p (pb, j))
1784 eqn sub = &(pb->eqs[e]);
1785 int c = pb->eqs[e].coef[i];
1786 int a = abs (c);
1787 int e2;
1789 if (dump_file && (dump_flags & TDF_DETAILS))
1791 fprintf (dump_file,
1792 "Found a single wild card equality: ");
1793 omega_print_eq (dump_file, pb, &pb->eqs[e]);
1794 fprintf (dump_file, "\n");
1795 omega_print_problem (dump_file, pb);
1798 for (e2 = pb->num_eqs - 1; e2 >= 0; e2--)
1799 if (e != e2 && pb->eqs[e2].coef[i]
1800 && (pb->eqs[e2].color == omega_red
1801 || (pb->eqs[e2].color == omega_black
1802 && pb->eqs[e].color == omega_black)))
1804 eqn eqn = &(pb->eqs[e2]);
1805 int var, k;
1807 for (var = n_vars; var >= 0; var--)
1808 eqn->coef[var] *= a;
1810 k = eqn->coef[i];
1812 for (var = n_vars; var >= 0; var--)
1813 eqn->coef[var] -= sub->coef[var] * k / c;
1815 eqn->coef[i] = 0;
1816 divide_eqn_by_gcd (eqn, n_vars);
1819 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
1820 if (pb->geqs[e2].coef[i]
1821 && (pb->geqs[e2].color == omega_red
1822 || (pb->eqs[e].color == omega_black
1823 && pb->geqs[e2].color == omega_black)))
1825 eqn eqn = &(pb->geqs[e2]);
1826 int var, k;
1828 for (var = n_vars; var >= 0; var--)
1829 eqn->coef[var] *= a;
1831 k = eqn->coef[i];
1833 for (var = n_vars; var >= 0; var--)
1834 eqn->coef[var] -= sub->coef[var] * k / c;
1836 eqn->coef[i] = 0;
1837 eqn->touched = 1;
1838 renormalize = true;
1841 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
1842 if (pb->subs[e2].coef[i]
1843 && (pb->subs[e2].color == omega_red
1844 || (pb->subs[e2].color == omega_black
1845 && pb->eqs[e].color == omega_black)))
1847 eqn eqn = &(pb->subs[e2]);
1848 int var, k;
1850 for (var = n_vars; var >= 0; var--)
1851 eqn->coef[var] *= a;
1853 k = eqn->coef[i];
1855 for (var = n_vars; var >= 0; var--)
1856 eqn->coef[var] -= sub->coef[var] * k / c;
1858 eqn->coef[i] = 0;
1859 divide_eqn_by_gcd (eqn, n_vars);
1862 if (dump_file && (dump_flags & TDF_DETAILS))
1864 fprintf (dump_file, "cleaned-out wildcard: ");
1865 omega_print_problem (dump_file, pb);
1867 break;
1871 if (renormalize)
1872 normalize_omega_problem (pb);
1875 /* Swap values contained in I and J. */
1877 static inline void
1878 swap (int *i, int *j)
1880 int tmp;
1881 tmp = *i;
1882 *i = *j;
1883 *j = tmp;
1886 /* Swap values contained in I and J. */
1888 static inline void
1889 bswap (bool *i, bool *j)
1891 bool tmp;
1892 tmp = *i;
1893 *i = *j;
1894 *j = tmp;
1897 /* Make variable IDX unprotected in PB, by swapping its index at the
1898 PB->safe_vars rank. */
1900 static inline void
1901 omega_unprotect_1 (omega_pb pb, int *idx, bool *unprotect)
1903 /* If IDX is protected... */
1904 if (*idx < pb->safe_vars)
1906 /* ... swap its index with the last non protected index. */
1907 int j = pb->safe_vars;
1908 int e;
1910 for (e = pb->num_geqs - 1; e >= 0; e--)
1912 pb->geqs[e].touched = 1;
1913 swap (&pb->geqs[e].coef[*idx], &pb->geqs[e].coef[j]);
1916 for (e = pb->num_eqs - 1; e >= 0; e--)
1917 swap (&pb->eqs[e].coef[*idx], &pb->eqs[e].coef[j]);
1919 for (e = pb->num_subs - 1; e >= 0; e--)
1920 swap (&pb->subs[e].coef[*idx], &pb->subs[e].coef[j]);
1922 if (unprotect)
1923 bswap (&unprotect[*idx], &unprotect[j]);
1925 swap (&pb->var[*idx], &pb->var[j]);
1926 pb->forwarding_address[pb->var[*idx]] = *idx;
1927 pb->forwarding_address[pb->var[j]] = j;
1928 (*idx)--;
1931 /* The variable at pb->safe_vars is also unprotected now. */
1932 pb->safe_vars--;
1935 /* During the Fourier-Motzkin elimination some variables are
1936 substituted with other variables. This function resurrects the
1937 substituted variables in PB. */
1939 static void
1940 resurrect_subs (omega_pb pb)
1942 if (pb->num_subs > 0
1943 && please_no_equalities_in_simplified_problems == 0)
1945 int i, e, m;
1947 if (dump_file && (dump_flags & TDF_DETAILS))
1949 fprintf (dump_file,
1950 "problem reduced, bringing variables back to life\n");
1951 omega_print_problem (dump_file, pb);
1954 for (i = 1; omega_safe_var_p (pb, i); i++)
1955 if (omega_wildcard_p (pb, i))
1956 omega_unprotect_1 (pb, &i, NULL);
1958 m = pb->num_subs;
1960 for (e = pb->num_geqs - 1; e >= 0; e--)
1961 if (single_var_geq (&pb->geqs[e], pb->num_vars))
1963 if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
1964 pb->geqs[e].key += (pb->geqs[e].key > 0 ? m : -m);
1966 else
1968 pb->geqs[e].touched = 1;
1969 pb->geqs[e].key = 0;
1972 for (i = pb->num_vars; !omega_safe_var_p (pb, i); i--)
1974 pb->var[i + m] = pb->var[i];
1976 for (e = pb->num_geqs - 1; e >= 0; e--)
1977 pb->geqs[e].coef[i + m] = pb->geqs[e].coef[i];
1979 for (e = pb->num_eqs - 1; e >= 0; e--)
1980 pb->eqs[e].coef[i + m] = pb->eqs[e].coef[i];
1982 for (e = pb->num_subs - 1; e >= 0; e--)
1983 pb->subs[e].coef[i + m] = pb->subs[e].coef[i];
1986 for (i = pb->safe_vars + m; !omega_safe_var_p (pb, i); i--)
1988 for (e = pb->num_geqs - 1; e >= 0; e--)
1989 pb->geqs[e].coef[i] = 0;
1991 for (e = pb->num_eqs - 1; e >= 0; e--)
1992 pb->eqs[e].coef[i] = 0;
1994 for (e = pb->num_subs - 1; e >= 0; e--)
1995 pb->subs[e].coef[i] = 0;
1998 pb->num_vars += m;
2000 for (e = pb->num_subs - 1; e >= 0; e--)
2002 pb->var[pb->safe_vars + 1 + e] = pb->subs[e].key;
2003 omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e]),
2004 pb->num_vars);
2005 pb->eqs[pb->num_eqs].coef[pb->safe_vars + 1 + e] = -1;
2006 pb->eqs[pb->num_eqs].color = omega_black;
2008 if (dump_file && (dump_flags & TDF_DETAILS))
2010 fprintf (dump_file, "brought back: ");
2011 omega_print_eq (dump_file, pb, &pb->eqs[pb->num_eqs]);
2012 fprintf (dump_file, "\n");
2015 pb->num_eqs++;
2016 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2019 pb->safe_vars += m;
2020 pb->num_subs = 0;
2022 if (dump_file && (dump_flags & TDF_DETAILS))
2024 fprintf (dump_file, "variables brought back to life\n");
2025 omega_print_problem (dump_file, pb);
2028 cleanout_wildcards (pb);
2032 static inline bool
2033 implies (unsigned int a, unsigned int b)
2035 return (a == (a & b));
2038 /* Eliminate redundant equations in PB. When EXPENSIVE is true, an
2039 extra step is performed. Returns omega_false when there exist no
2040 solution, omega_true otherwise. */
2042 enum omega_result
2043 omega_eliminate_redundant (omega_pb pb, bool expensive)
2045 int c, e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3;
2046 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2047 omega_pb tmp_problem;
2049 /* {P,Z,N}EQS = {Positive,Zero,Negative} Equations. */
2050 unsigned int *peqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2051 unsigned int *zeqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2052 unsigned int *neqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2054 /* PP = Possible Positives, PZ = Possible Zeros, PN = Possible Negatives */
2055 unsigned int pp, pz, pn;
2057 if (dump_file && (dump_flags & TDF_DETAILS))
2059 fprintf (dump_file, "in eliminate Redundant:\n");
2060 omega_print_problem (dump_file, pb);
2063 for (e = pb->num_geqs - 1; e >= 0; e--)
2065 int tmp = 1;
2067 is_dead[e] = false;
2068 peqs[e] = zeqs[e] = neqs[e] = 0;
2070 for (i = pb->num_vars; i >= 1; i--)
2072 if (pb->geqs[e].coef[i] > 0)
2073 peqs[e] |= tmp;
2074 else if (pb->geqs[e].coef[i] < 0)
2075 neqs[e] |= tmp;
2076 else
2077 zeqs[e] |= tmp;
2079 tmp <<= 1;
2084 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2085 if (!is_dead[e1])
2086 for (e2 = e1 - 1; e2 >= 0; e2--)
2087 if (!is_dead[e2])
2089 for (p = pb->num_vars; p > 1; p--)
2090 for (q = p - 1; q > 0; q--)
2091 if ((alpha = pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q]
2092 - pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]) != 0)
2093 goto foundPQ;
2095 continue;
2097 foundPQ:
2098 pz = ((zeqs[e1] & zeqs[e2]) | (peqs[e1] & neqs[e2])
2099 | (neqs[e1] & peqs[e2]));
2100 pp = peqs[e1] | peqs[e2];
2101 pn = neqs[e1] | neqs[e2];
2103 for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2104 if (e3 != e1 && e3 != e2)
2106 if (!implies (zeqs[e3], pz))
2107 goto nextE3;
2109 alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2110 - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2111 alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2112 - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2113 alpha3 = alpha;
2115 if (alpha1 * alpha2 <= 0)
2116 goto nextE3;
2118 if (alpha1 < 0)
2120 alpha1 = -alpha1;
2121 alpha2 = -alpha2;
2122 alpha3 = -alpha3;
2125 if (alpha3 > 0)
2127 /* Trying to prove e3 is redundant. */
2128 if (!implies (peqs[e3], pp)
2129 || !implies (neqs[e3], pn))
2130 goto nextE3;
2132 if (pb->geqs[e3].color == omega_black
2133 && (pb->geqs[e1].color == omega_red
2134 || pb->geqs[e2].color == omega_red))
2135 goto nextE3;
2137 for (k = pb->num_vars; k >= 1; k--)
2138 if (alpha3 * pb->geqs[e3].coef[k]
2139 != (alpha1 * pb->geqs[e1].coef[k]
2140 + alpha2 * pb->geqs[e2].coef[k]))
2141 goto nextE3;
2143 c = (alpha1 * pb->geqs[e1].coef[0]
2144 + alpha2 * pb->geqs[e2].coef[0]);
2146 if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2148 if (dump_file && (dump_flags & TDF_DETAILS))
2150 fprintf (dump_file,
2151 "found redundant inequality\n");
2152 fprintf (dump_file,
2153 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2154 alpha1, alpha2, alpha3);
2156 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2157 fprintf (dump_file, "\n");
2158 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2159 fprintf (dump_file, "\n=> ");
2160 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2161 fprintf (dump_file, "\n\n");
2164 is_dead[e3] = true;
2167 else
2169 /* Trying to prove e3 <= 0 and therefore e3 = 0,
2170 or trying to prove e3 < 0, and therefore the
2171 problem has no solutions. */
2172 if (!implies (peqs[e3], pn)
2173 || !implies (neqs[e3], pp))
2174 goto nextE3;
2176 if (pb->geqs[e1].color == omega_red
2177 || pb->geqs[e2].color == omega_red
2178 || pb->geqs[e3].color == omega_red)
2179 goto nextE3;
2181 /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */
2182 for (k = pb->num_vars; k >= 1; k--)
2183 if (alpha3 * pb->geqs[e3].coef[k]
2184 != (alpha1 * pb->geqs[e1].coef[k]
2185 + alpha2 * pb->geqs[e2].coef[k]))
2186 goto nextE3;
2188 c = (alpha1 * pb->geqs[e1].coef[0]
2189 + alpha2 * pb->geqs[e2].coef[0]);
2191 if (c < alpha3 * (pb->geqs[e3].coef[0]))
2193 /* We just proved e3 < 0, so no solutions exist. */
2194 if (dump_file && (dump_flags & TDF_DETAILS))
2196 fprintf (dump_file,
2197 "found implied over tight inequality\n");
2198 fprintf (dump_file,
2199 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2200 alpha1, alpha2, -alpha3);
2201 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2202 fprintf (dump_file, "\n");
2203 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2204 fprintf (dump_file, "\n=> not ");
2205 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2206 fprintf (dump_file, "\n\n");
2208 free (is_dead);
2209 free (peqs);
2210 free (zeqs);
2211 free (neqs);
2212 return omega_false;
2214 else if (c < alpha3 * (pb->geqs[e3].coef[0] - 1))
2216 /* We just proved that e3 <=0, so e3 = 0. */
2217 if (dump_file && (dump_flags & TDF_DETAILS))
2219 fprintf (dump_file,
2220 "found implied tight inequality\n");
2221 fprintf (dump_file,
2222 "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2223 alpha1, alpha2, -alpha3);
2224 omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2225 fprintf (dump_file, "\n");
2226 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2227 fprintf (dump_file, "\n=> inverse ");
2228 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2229 fprintf (dump_file, "\n\n");
2232 omega_copy_eqn (&pb->eqs[pb->num_eqs++],
2233 &pb->geqs[e3], pb->num_vars);
2234 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2235 adding_equality_constraint (pb, pb->num_eqs - 1);
2236 is_dead[e3] = true;
2239 nextE3:;
2243 /* Delete the inequalities that were marked as dead. */
2244 for (e = pb->num_geqs - 1; e >= 0; e--)
2245 if (is_dead[e])
2246 omega_delete_geq (pb, e, pb->num_vars);
2248 if (!expensive)
2249 goto eliminate_redundant_done;
2251 tmp_problem = XNEW (struct omega_pb_d);
2252 conservative++;
2254 for (e = pb->num_geqs - 1; e >= 0; e--)
2256 if (dump_file && (dump_flags & TDF_DETAILS))
2258 fprintf (dump_file,
2259 "checking equation %d to see if it is redundant: ", e);
2260 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2261 fprintf (dump_file, "\n");
2264 omega_copy_problem (tmp_problem, pb);
2265 omega_negate_geq (tmp_problem, e);
2266 tmp_problem->safe_vars = 0;
2267 tmp_problem->variables_freed = false;
2269 if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2270 omega_delete_geq (pb, e, pb->num_vars);
2273 free (tmp_problem);
2274 conservative--;
2276 if (!omega_reduce_with_subs)
2278 resurrect_subs (pb);
2279 gcc_assert (please_no_equalities_in_simplified_problems
2280 || pb->num_subs == 0);
2283 eliminate_redundant_done:
2284 free (is_dead);
2285 free (peqs);
2286 free (zeqs);
2287 free (neqs);
2288 return omega_true;
2291 /* For each inequality that has coefficients bigger than 20, try to
2292 create a new constraint that cannot be derived from the original
2293 constraint and that has smaller coefficients. Add the new
2294 constraint at the end of geqs. Return the number of inequalities
2295 that have been added to PB. */
2297 static int
2298 smooth_weird_equations (omega_pb pb)
2300 int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3;
2301 int c;
2302 int v;
2303 int result = 0;
2305 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2306 if (pb->geqs[e1].color == omega_black)
2308 int g = 999999;
2310 for (v = pb->num_vars; v >= 1; v--)
2311 if (pb->geqs[e1].coef[v] != 0 && abs (pb->geqs[e1].coef[v]) < g)
2312 g = abs (pb->geqs[e1].coef[v]);
2314 /* Magic number. */
2315 if (g > 20)
2317 e3 = pb->num_geqs;
2319 for (v = pb->num_vars; v >= 1; v--)
2320 pb->geqs[e3].coef[v] = int_div (6 * pb->geqs[e1].coef[v] + g / 2,
2323 pb->geqs[e3].color = omega_black;
2324 pb->geqs[e3].touched = 1;
2325 /* Magic number. */
2326 pb->geqs[e3].coef[0] = 9997;
2328 if (dump_file && (dump_flags & TDF_DETAILS))
2330 fprintf (dump_file, "Checking to see if we can derive: ");
2331 omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2332 fprintf (dump_file, "\n from: ");
2333 omega_print_geq (dump_file, pb, &pb->geqs[e1]);
2334 fprintf (dump_file, "\n");
2337 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
2338 if (e1 != e2 && pb->geqs[e2].color == omega_black)
2340 for (p = pb->num_vars; p > 1; p--)
2342 for (q = p - 1; q > 0; q--)
2344 alpha =
2345 (pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q] -
2346 pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]);
2347 if (alpha != 0)
2348 goto foundPQ;
2351 continue;
2353 foundPQ:
2355 alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2356 - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2357 alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2358 - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2359 alpha3 = alpha;
2361 if (alpha1 * alpha2 <= 0)
2362 continue;
2364 if (alpha1 < 0)
2366 alpha1 = -alpha1;
2367 alpha2 = -alpha2;
2368 alpha3 = -alpha3;
2371 if (alpha3 > 0)
2373 /* Try to prove e3 is redundant: verify
2374 alpha1*v1 + alpha2*v2 = alpha3*v3. */
2375 for (k = pb->num_vars; k >= 1; k--)
2376 if (alpha3 * pb->geqs[e3].coef[k]
2377 != (alpha1 * pb->geqs[e1].coef[k]
2378 + alpha2 * pb->geqs[e2].coef[k]))
2379 goto nextE2;
2381 c = alpha1 * pb->geqs[e1].coef[0]
2382 + alpha2 * pb->geqs[e2].coef[0];
2384 if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2385 pb->geqs[e3].coef[0] = int_div (c, alpha3);
2387 nextE2:;
2390 if (pb->geqs[e3].coef[0] < 9997)
2392 result++;
2393 pb->num_geqs++;
2395 if (dump_file && (dump_flags & TDF_DETAILS))
2397 fprintf (dump_file,
2398 "Smoothing weird equations; adding:\n");
2399 omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2400 fprintf (dump_file, "\nto:\n");
2401 omega_print_problem (dump_file, pb);
2402 fprintf (dump_file, "\n\n");
2407 return result;
2410 /* Replace tuples of inequalities, that define upper and lower half
2411 spaces, with an equation. */
2413 static void
2414 coalesce (omega_pb pb)
2416 int e, e2;
2417 int colors = 0;
2418 bool *is_dead;
2419 int found_something = 0;
2421 for (e = 0; e < pb->num_geqs; e++)
2422 if (pb->geqs[e].color == omega_red)
2423 colors++;
2425 if (colors < 2)
2426 return;
2428 is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2430 for (e = 0; e < pb->num_geqs; e++)
2431 is_dead[e] = false;
2433 for (e = 0; e < pb->num_geqs; e++)
2434 if (pb->geqs[e].color == omega_red
2435 && !pb->geqs[e].touched)
2436 for (e2 = e + 1; e2 < pb->num_geqs; e2++)
2437 if (!pb->geqs[e2].touched
2438 && pb->geqs[e].key == -pb->geqs[e2].key
2439 && pb->geqs[e].coef[0] == -pb->geqs[e2].coef[0]
2440 && pb->geqs[e2].color == omega_red)
2442 omega_copy_eqn (&pb->eqs[pb->num_eqs++], &pb->geqs[e],
2443 pb->num_vars);
2444 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2445 found_something++;
2446 is_dead[e] = true;
2447 is_dead[e2] = true;
2450 for (e = pb->num_geqs - 1; e >= 0; e--)
2451 if (is_dead[e])
2452 omega_delete_geq (pb, e, pb->num_vars);
2454 if (dump_file && (dump_flags & TDF_DETAILS) && found_something)
2456 fprintf (dump_file, "Coalesced pb->geqs into %d EQ's:\n",
2457 found_something);
2458 omega_print_problem (dump_file, pb);
2461 free (is_dead);
2464 /* Eliminate red inequalities from PB. When ELIMINATE_ALL is
2465 true, continue to eliminate all the red inequalities. */
2467 void
2468 omega_eliminate_red (omega_pb pb, bool eliminate_all)
2470 int e, e2, e3, i, j, k, a, alpha1, alpha2;
2471 int c = 0;
2472 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2473 int dead_count = 0;
2474 int red_found;
2475 omega_pb tmp_problem;
2477 if (dump_file && (dump_flags & TDF_DETAILS))
2479 fprintf (dump_file, "in eliminate RED:\n");
2480 omega_print_problem (dump_file, pb);
2483 if (pb->num_eqs > 0)
2484 omega_simplify_problem (pb);
2486 for (e = pb->num_geqs - 1; e >= 0; e--)
2487 is_dead[e] = false;
2489 for (e = pb->num_geqs - 1; e >= 0; e--)
2490 if (pb->geqs[e].color == omega_black && !is_dead[e])
2491 for (e2 = e - 1; e2 >= 0; e2--)
2492 if (pb->geqs[e2].color == omega_black
2493 && !is_dead[e2])
2495 a = 0;
2497 for (i = pb->num_vars; i > 1; i--)
2498 for (j = i - 1; j > 0; j--)
2499 if ((a = (pb->geqs[e].coef[i] * pb->geqs[e2].coef[j]
2500 - pb->geqs[e2].coef[i] * pb->geqs[e].coef[j])) != 0)
2501 goto found_pair;
2503 continue;
2505 found_pair:
2506 if (dump_file && (dump_flags & TDF_DETAILS))
2508 fprintf (dump_file,
2509 "found two equations to combine, i = %s, ",
2510 omega_variable_to_str (pb, i));
2511 fprintf (dump_file, "j = %s, alpha = %d\n",
2512 omega_variable_to_str (pb, j), a);
2513 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2514 fprintf (dump_file, "\n");
2515 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2516 fprintf (dump_file, "\n");
2519 for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2520 if (pb->geqs[e3].color == omega_red)
2522 alpha1 = (pb->geqs[e2].coef[j] * pb->geqs[e3].coef[i]
2523 - pb->geqs[e2].coef[i] * pb->geqs[e3].coef[j]);
2524 alpha2 = -(pb->geqs[e].coef[j] * pb->geqs[e3].coef[i]
2525 - pb->geqs[e].coef[i] * pb->geqs[e3].coef[j]);
2527 if ((a > 0 && alpha1 > 0 && alpha2 > 0)
2528 || (a < 0 && alpha1 < 0 && alpha2 < 0))
2530 if (dump_file && (dump_flags & TDF_DETAILS))
2532 fprintf (dump_file,
2533 "alpha1 = %d, alpha2 = %d;"
2534 "comparing against: ",
2535 alpha1, alpha2);
2536 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2537 fprintf (dump_file, "\n");
2540 for (k = pb->num_vars; k >= 0; k--)
2542 c = (alpha1 * pb->geqs[e].coef[k]
2543 + alpha2 * pb->geqs[e2].coef[k]);
2545 if (c != a * pb->geqs[e3].coef[k])
2546 break;
2548 if (dump_file && (dump_flags & TDF_DETAILS) && k > 0)
2549 fprintf (dump_file, " %s: %d, %d\n",
2550 omega_variable_to_str (pb, k), c,
2551 a * pb->geqs[e3].coef[k]);
2554 if (k < 0
2555 || (k == 0 &&
2556 ((a > 0 && c < a * pb->geqs[e3].coef[k])
2557 || (a < 0 && c > a * pb->geqs[e3].coef[k]))))
2559 if (dump_file && (dump_flags & TDF_DETAILS))
2561 dead_count++;
2562 fprintf (dump_file,
2563 "red equation#%d is dead "
2564 "(%d dead so far, %d remain)\n",
2565 e3, dead_count,
2566 pb->num_geqs - dead_count);
2567 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2568 fprintf (dump_file, "\n");
2569 omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2570 fprintf (dump_file, "\n");
2571 omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2572 fprintf (dump_file, "\n");
2574 is_dead[e3] = true;
2580 for (e = pb->num_geqs - 1; e >= 0; e--)
2581 if (is_dead[e])
2582 omega_delete_geq (pb, e, pb->num_vars);
2584 free (is_dead);
2586 if (dump_file && (dump_flags & TDF_DETAILS))
2588 fprintf (dump_file, "in eliminate RED, easy tests done:\n");
2589 omega_print_problem (dump_file, pb);
2592 for (red_found = 0, e = pb->num_geqs - 1; e >= 0; e--)
2593 if (pb->geqs[e].color == omega_red)
2594 red_found = 1;
2596 if (!red_found)
2598 if (dump_file && (dump_flags & TDF_DETAILS))
2599 fprintf (dump_file, "fast checks worked\n");
2601 if (!omega_reduce_with_subs)
2602 gcc_assert (please_no_equalities_in_simplified_problems
2603 || pb->num_subs == 0);
2605 return;
2608 if (!omega_verify_simplification
2609 && verify_omega_pb (pb) == omega_false)
2610 return;
2612 conservative++;
2613 tmp_problem = XNEW (struct omega_pb_d);
2615 for (e = pb->num_geqs - 1; e >= 0; e--)
2616 if (pb->geqs[e].color == omega_red)
2618 if (dump_file && (dump_flags & TDF_DETAILS))
2620 fprintf (dump_file,
2621 "checking equation %d to see if it is redundant: ", e);
2622 omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2623 fprintf (dump_file, "\n");
2626 omega_copy_problem (tmp_problem, pb);
2627 omega_negate_geq (tmp_problem, e);
2628 tmp_problem->safe_vars = 0;
2629 tmp_problem->variables_freed = false;
2630 tmp_problem->num_subs = 0;
2632 if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2634 if (dump_file && (dump_flags & TDF_DETAILS))
2635 fprintf (dump_file, "it is redundant\n");
2636 omega_delete_geq (pb, e, pb->num_vars);
2638 else
2640 if (dump_file && (dump_flags & TDF_DETAILS))
2641 fprintf (dump_file, "it is not redundant\n");
2643 if (!eliminate_all)
2645 if (dump_file && (dump_flags & TDF_DETAILS))
2646 fprintf (dump_file, "no need to check other red equations\n");
2647 break;
2652 conservative--;
2653 free (tmp_problem);
2654 /* omega_simplify_problem (pb); */
2656 if (!omega_reduce_with_subs)
2657 gcc_assert (please_no_equalities_in_simplified_problems
2658 || pb->num_subs == 0);
2661 /* Transform some wildcard variables to non-safe variables. */
2663 static void
2664 chain_unprotect (omega_pb pb)
2666 int i, e;
2667 bool *unprotect = XNEWVEC (bool, OMEGA_MAX_VARS);
2669 for (i = 1; omega_safe_var_p (pb, i); i++)
2671 unprotect[i] = omega_wildcard_p (pb, i);
2673 for (e = pb->num_subs - 1; e >= 0; e--)
2674 if (pb->subs[e].coef[i])
2675 unprotect[i] = false;
2678 if (dump_file && (dump_flags & TDF_DETAILS))
2680 fprintf (dump_file, "Doing chain reaction unprotection\n");
2681 omega_print_problem (dump_file, pb);
2683 for (i = 1; omega_safe_var_p (pb, i); i++)
2684 if (unprotect[i])
2685 fprintf (dump_file, "unprotecting %s\n",
2686 omega_variable_to_str (pb, i));
2689 for (i = 1; omega_safe_var_p (pb, i); i++)
2690 if (unprotect[i])
2691 omega_unprotect_1 (pb, &i, unprotect);
2693 if (dump_file && (dump_flags & TDF_DETAILS))
2695 fprintf (dump_file, "After chain reactions\n");
2696 omega_print_problem (dump_file, pb);
2699 free (unprotect);
2702 /* Reduce problem PB. */
2704 static void
2705 omega_problem_reduced (omega_pb pb)
2707 if (omega_verify_simplification
2708 && !in_approximate_mode
2709 && verify_omega_pb (pb) == omega_false)
2710 return;
2712 if (PARAM_VALUE (PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS)
2713 && !omega_eliminate_redundant (pb, true))
2714 return;
2716 omega_found_reduction = omega_true;
2718 if (!please_no_equalities_in_simplified_problems)
2719 coalesce (pb);
2721 if (omega_reduce_with_subs
2722 || please_no_equalities_in_simplified_problems)
2723 chain_unprotect (pb);
2724 else
2725 resurrect_subs (pb);
2727 if (!return_single_result)
2729 int i;
2731 for (i = 1; omega_safe_var_p (pb, i); i++)
2732 pb->forwarding_address[pb->var[i]] = i;
2734 for (i = 0; i < pb->num_subs; i++)
2735 pb->forwarding_address[pb->subs[i].key] = -i - 1;
2737 (*omega_when_reduced) (pb);
2740 if (dump_file && (dump_flags & TDF_DETAILS))
2742 fprintf (dump_file, "-------------------------------------------\n");
2743 fprintf (dump_file, "problem reduced:\n");
2744 omega_print_problem (dump_file, pb);
2745 fprintf (dump_file, "-------------------------------------------\n");
2749 /* Eliminates all the free variables for problem PB, that is all the
2750 variables from FV to PB->NUM_VARS. */
2752 static void
2753 omega_free_eliminations (omega_pb pb, int fv)
2755 bool try_again = true;
2756 int i, e, e2;
2757 int n_vars = pb->num_vars;
2759 while (try_again)
2761 try_again = false;
2763 for (i = n_vars; i > fv; i--)
2765 for (e = pb->num_geqs - 1; e >= 0; e--)
2766 if (pb->geqs[e].coef[i])
2767 break;
2769 if (e < 0)
2770 e2 = e;
2771 else if (pb->geqs[e].coef[i] > 0)
2773 for (e2 = e - 1; e2 >= 0; e2--)
2774 if (pb->geqs[e2].coef[i] < 0)
2775 break;
2777 else
2779 for (e2 = e - 1; e2 >= 0; e2--)
2780 if (pb->geqs[e2].coef[i] > 0)
2781 break;
2784 if (e2 < 0)
2786 int e3;
2787 for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2788 if (pb->subs[e3].coef[i])
2789 break;
2791 if (e3 >= 0)
2792 continue;
2794 for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2795 if (pb->eqs[e3].coef[i])
2796 break;
2798 if (e3 >= 0)
2799 continue;
2801 if (dump_file && (dump_flags & TDF_DETAILS))
2802 fprintf (dump_file, "a free elimination of %s\n",
2803 omega_variable_to_str (pb, i));
2805 if (e >= 0)
2807 omega_delete_geq (pb, e, n_vars);
2809 for (e--; e >= 0; e--)
2810 if (pb->geqs[e].coef[i])
2811 omega_delete_geq (pb, e, n_vars);
2813 try_again = (i < n_vars);
2816 omega_delete_variable (pb, i);
2817 n_vars = pb->num_vars;
2822 if (dump_file && (dump_flags & TDF_DETAILS))
2824 fprintf (dump_file, "\nafter free eliminations:\n");
2825 omega_print_problem (dump_file, pb);
2826 fprintf (dump_file, "\n");
2830 /* Do free red eliminations. */
2832 static void
2833 free_red_eliminations (omega_pb pb)
2835 bool try_again = true;
2836 int i, e, e2;
2837 int n_vars = pb->num_vars;
2838 bool *is_red_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2839 bool *is_dead_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2840 bool *is_dead_geq = XNEWVEC (bool, OMEGA_MAX_GEQS);
2842 for (i = n_vars; i > 0; i--)
2844 is_red_var[i] = false;
2845 is_dead_var[i] = false;
2848 for (e = pb->num_geqs - 1; e >= 0; e--)
2850 is_dead_geq[e] = false;
2852 if (pb->geqs[e].color == omega_red)
2853 for (i = n_vars; i > 0; i--)
2854 if (pb->geqs[e].coef[i] != 0)
2855 is_red_var[i] = true;
2858 while (try_again)
2860 try_again = false;
2861 for (i = n_vars; i > 0; i--)
2862 if (!is_red_var[i] && !is_dead_var[i])
2864 for (e = pb->num_geqs - 1; e >= 0; e--)
2865 if (!is_dead_geq[e] && pb->geqs[e].coef[i])
2866 break;
2868 if (e < 0)
2869 e2 = e;
2870 else if (pb->geqs[e].coef[i] > 0)
2872 for (e2 = e - 1; e2 >= 0; e2--)
2873 if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] < 0)
2874 break;
2876 else
2878 for (e2 = e - 1; e2 >= 0; e2--)
2879 if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] > 0)
2880 break;
2883 if (e2 < 0)
2885 int e3;
2886 for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2887 if (pb->subs[e3].coef[i])
2888 break;
2890 if (e3 >= 0)
2891 continue;
2893 for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2894 if (pb->eqs[e3].coef[i])
2895 break;
2897 if (e3 >= 0)
2898 continue;
2900 if (dump_file && (dump_flags & TDF_DETAILS))
2901 fprintf (dump_file, "a free red elimination of %s\n",
2902 omega_variable_to_str (pb, i));
2904 for (; e >= 0; e--)
2905 if (pb->geqs[e].coef[i])
2906 is_dead_geq[e] = true;
2908 try_again = true;
2909 is_dead_var[i] = true;
2914 for (e = pb->num_geqs - 1; e >= 0; e--)
2915 if (is_dead_geq[e])
2916 omega_delete_geq (pb, e, n_vars);
2918 for (i = n_vars; i > 0; i--)
2919 if (is_dead_var[i])
2920 omega_delete_variable (pb, i);
2922 if (dump_file && (dump_flags & TDF_DETAILS))
2924 fprintf (dump_file, "\nafter free red eliminations:\n");
2925 omega_print_problem (dump_file, pb);
2926 fprintf (dump_file, "\n");
2929 free (is_red_var);
2930 free (is_dead_var);
2931 free (is_dead_geq);
2934 /* For equation EQ of the form "0 = EQN", insert in PB two
2935 inequalities "0 <= EQN" and "0 <= -EQN". */
2937 void
2938 omega_convert_eq_to_geqs (omega_pb pb, int eq)
2940 int i;
2942 if (dump_file && (dump_flags & TDF_DETAILS))
2943 fprintf (dump_file, "Converting Eq to Geqs\n");
2945 /* Insert "0 <= EQN". */
2946 omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2947 pb->geqs[pb->num_geqs].touched = 1;
2948 pb->num_geqs++;
2950 /* Insert "0 <= -EQN". */
2951 omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2952 pb->geqs[pb->num_geqs].touched = 1;
2954 for (i = 0; i <= pb->num_vars; i++)
2955 pb->geqs[pb->num_geqs].coef[i] *= -1;
2957 pb->num_geqs++;
2959 if (dump_file && (dump_flags & TDF_DETAILS))
2960 omega_print_problem (dump_file, pb);
2963 /* Eliminates variable I from PB. */
2965 static void
2966 omega_do_elimination (omega_pb pb, int e, int i)
2968 eqn sub = omega_alloc_eqns (0, 1);
2969 int c;
2970 int n_vars = pb->num_vars;
2972 if (dump_file && (dump_flags & TDF_DETAILS))
2973 fprintf (dump_file, "eliminating variable %s\n",
2974 omega_variable_to_str (pb, i));
2976 omega_copy_eqn (sub, &pb->eqs[e], pb->num_vars);
2977 c = sub->coef[i];
2978 sub->coef[i] = 0;
2979 if (c == 1 || c == -1)
2981 if (pb->eqs[e].color == omega_red)
2983 bool fB;
2984 omega_substitute_red (pb, sub, i, c, &fB);
2985 if (fB)
2986 omega_convert_eq_to_geqs (pb, e);
2987 else
2988 omega_delete_variable (pb, i);
2990 else
2992 omega_substitute (pb, sub, i, c);
2993 omega_delete_variable (pb, i);
2996 else
2998 int a = abs (c);
2999 int e2 = e;
3001 if (dump_file && (dump_flags & TDF_DETAILS))
3002 fprintf (dump_file, "performing non-exact elimination, c = %d\n", c);
3004 for (e = pb->num_eqs - 1; e >= 0; e--)
3005 if (pb->eqs[e].coef[i])
3007 eqn eqn = &(pb->eqs[e]);
3008 int j, k;
3009 for (j = n_vars; j >= 0; j--)
3010 eqn->coef[j] *= a;
3011 k = eqn->coef[i];
3012 eqn->coef[i] = 0;
3013 if (sub->color == omega_red)
3014 eqn->color = omega_red;
3015 for (j = n_vars; j >= 0; j--)
3016 eqn->coef[j] -= sub->coef[j] * k / c;
3019 for (e = pb->num_geqs - 1; e >= 0; e--)
3020 if (pb->geqs[e].coef[i])
3022 eqn eqn = &(pb->geqs[e]);
3023 int j, k;
3025 if (sub->color == omega_red)
3026 eqn->color = omega_red;
3028 for (j = n_vars; j >= 0; j--)
3029 eqn->coef[j] *= a;
3031 eqn->touched = 1;
3032 k = eqn->coef[i];
3033 eqn->coef[i] = 0;
3035 for (j = n_vars; j >= 0; j--)
3036 eqn->coef[j] -= sub->coef[j] * k / c;
3040 for (e = pb->num_subs - 1; e >= 0; e--)
3041 if (pb->subs[e].coef[i])
3043 eqn eqn = &(pb->subs[e]);
3044 int j, k;
3045 gcc_assert (0);
3046 gcc_assert (sub->color == omega_black);
3047 for (j = n_vars; j >= 0; j--)
3048 eqn->coef[j] *= a;
3049 k = eqn->coef[i];
3050 eqn->coef[i] = 0;
3051 for (j = n_vars; j >= 0; j--)
3052 eqn->coef[j] -= sub->coef[j] * k / c;
3055 if (in_approximate_mode)
3056 omega_delete_variable (pb, i);
3057 else
3058 omega_convert_eq_to_geqs (pb, e2);
3061 omega_free_eqns (sub, 1);
3064 /* Helper function for printing "sorry, no solution". */
3066 static inline enum omega_result
3067 omega_problem_has_no_solution (void)
3069 if (dump_file && (dump_flags & TDF_DETAILS))
3070 fprintf (dump_file, "\nequations have no solution \n");
3072 return omega_false;
3075 /* Helper function: solve equations in PB one at a time, following the
3076 DESIRED_RES result. */
3078 static enum omega_result
3079 omega_solve_eq (omega_pb pb, enum omega_result desired_res)
3081 int i, j, e;
3082 int g, g2;
3083 g = 0;
3086 if (dump_file && (dump_flags & TDF_DETAILS) && pb->num_eqs > 0)
3088 fprintf (dump_file, "\nomega_solve_eq (%d, %d)\n",
3089 desired_res, may_be_red);
3090 omega_print_problem (dump_file, pb);
3091 fprintf (dump_file, "\n");
3094 if (may_be_red)
3096 i = 0;
3097 j = pb->num_eqs - 1;
3099 while (1)
3101 eqn eq;
3103 while (i <= j && pb->eqs[i].color == omega_red)
3104 i++;
3106 while (i <= j && pb->eqs[j].color == omega_black)
3107 j--;
3109 if (i >= j)
3110 break;
3112 eq = omega_alloc_eqns (0, 1);
3113 omega_copy_eqn (eq, &pb->eqs[i], pb->num_vars);
3114 omega_copy_eqn (&pb->eqs[i], &pb->eqs[j], pb->num_vars);
3115 omega_copy_eqn (&pb->eqs[j], eq, pb->num_vars);
3116 omega_free_eqns (eq, 1);
3117 i++;
3118 j--;
3122 /* Eliminate all EQ equations */
3123 for (e = pb->num_eqs - 1; e >= 0; e--)
3125 eqn eqn = &(pb->eqs[e]);
3126 int sv;
3128 if (dump_file && (dump_flags & TDF_DETAILS))
3129 fprintf (dump_file, "----\n");
3131 for (i = pb->num_vars; i > 0; i--)
3132 if (eqn->coef[i])
3133 break;
3135 g = eqn->coef[i];
3137 for (j = i - 1; j > 0; j--)
3138 if (eqn->coef[j])
3139 break;
3141 /* i is the position of last nonzero coefficient,
3142 g is the coefficient of i,
3143 j is the position of next nonzero coefficient. */
3145 if (j == 0)
3147 if (eqn->coef[0] % g != 0)
3148 return omega_problem_has_no_solution ();
3150 eqn->coef[0] = eqn->coef[0] / g;
3151 eqn->coef[i] = 1;
3152 pb->num_eqs--;
3153 omega_do_elimination (pb, e, i);
3154 continue;
3157 else if (j == -1)
3159 if (eqn->coef[0] != 0)
3160 return omega_problem_has_no_solution ();
3162 pb->num_eqs--;
3163 continue;
3166 if (g < 0)
3167 g = -g;
3169 if (g == 1)
3171 pb->num_eqs--;
3172 omega_do_elimination (pb, e, i);
3175 else
3177 int k = j;
3178 bool promotion_possible =
3179 (omega_safe_var_p (pb, j)
3180 && pb->safe_vars + 1 == i
3181 && !omega_eqn_is_red (eqn, desired_res)
3182 && !in_approximate_mode);
3184 if (dump_file && (dump_flags & TDF_DETAILS) && promotion_possible)
3185 fprintf (dump_file, " Promotion possible\n");
3187 normalizeEQ:
3188 if (!omega_safe_var_p (pb, j))
3190 for (; g != 1 && !omega_safe_var_p (pb, j); j--)
3191 g = gcd (abs (eqn->coef[j]), g);
3192 g2 = g;
3194 else if (!omega_safe_var_p (pb, i))
3195 g2 = g;
3196 else
3197 g2 = 0;
3199 for (; g != 1 && j > 0; j--)
3200 g = gcd (abs (eqn->coef[j]), g);
3202 if (g > 1)
3204 if (eqn->coef[0] % g != 0)
3205 return omega_problem_has_no_solution ();
3207 for (j = 0; j <= pb->num_vars; j++)
3208 eqn->coef[j] /= g;
3210 g2 = g2 / g;
3213 if (g2 > 1)
3215 int e2;
3217 for (e2 = e - 1; e2 >= 0; e2--)
3218 if (pb->eqs[e2].coef[i])
3219 break;
3221 if (e2 == -1)
3222 for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
3223 if (pb->geqs[e2].coef[i])
3224 break;
3226 if (e2 == -1)
3227 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
3228 if (pb->subs[e2].coef[i])
3229 break;
3231 if (e2 == -1)
3233 bool change = false;
3235 if (dump_file && (dump_flags & TDF_DETAILS))
3237 fprintf (dump_file, "Ha! We own it! \n");
3238 omega_print_eq (dump_file, pb, eqn);
3239 fprintf (dump_file, " \n");
3242 g = eqn->coef[i];
3243 g = abs (g);
3245 for (j = i - 1; j >= 0; j--)
3247 int t = int_mod (eqn->coef[j], g);
3249 if (2 * t >= g)
3250 t -= g;
3252 if (t != eqn->coef[j])
3254 eqn->coef[j] = t;
3255 change = true;
3259 if (!change)
3261 if (dump_file && (dump_flags & TDF_DETAILS))
3262 fprintf (dump_file, "So what?\n");
3265 else
3267 omega_name_wild_card (pb, i);
3269 if (dump_file && (dump_flags & TDF_DETAILS))
3271 omega_print_eq (dump_file, pb, eqn);
3272 fprintf (dump_file, " \n");
3275 e++;
3276 continue;
3281 if (promotion_possible)
3283 if (dump_file && (dump_flags & TDF_DETAILS))
3285 fprintf (dump_file, "promoting %s to safety\n",
3286 omega_variable_to_str (pb, i));
3287 omega_print_vars (dump_file, pb);
3290 pb->safe_vars++;
3292 if (!omega_wildcard_p (pb, i))
3293 omega_name_wild_card (pb, i);
3295 promotion_possible = false;
3296 j = k;
3297 goto normalizeEQ;
3300 if (g2 > 1 && !in_approximate_mode)
3302 if (pb->eqs[e].color == omega_red)
3304 if (dump_file && (dump_flags & TDF_DETAILS))
3305 fprintf (dump_file, "handling red equality\n");
3307 pb->num_eqs--;
3308 omega_do_elimination (pb, e, i);
3309 continue;
3312 if (dump_file && (dump_flags & TDF_DETAILS))
3314 fprintf (dump_file,
3315 "adding equation to handle safe variable \n");
3316 omega_print_eq (dump_file, pb, eqn);
3317 fprintf (dump_file, "\n----\n");
3318 omega_print_problem (dump_file, pb);
3319 fprintf (dump_file, "\n----\n");
3320 fprintf (dump_file, "\n----\n");
3323 i = omega_add_new_wild_card (pb);
3324 pb->num_eqs++;
3325 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
3326 omega_init_eqn_zero (&pb->eqs[e + 1], pb->num_vars);
3327 omega_copy_eqn (&pb->eqs[e + 1], eqn, pb->safe_vars);
3329 for (j = pb->num_vars; j >= 0; j--)
3331 pb->eqs[e + 1].coef[j] = int_mod (pb->eqs[e + 1].coef[j], g2);
3333 if (2 * pb->eqs[e + 1].coef[j] >= g2)
3334 pb->eqs[e + 1].coef[j] -= g2;
3337 pb->eqs[e + 1].coef[i] = g2;
3338 e += 2;
3340 if (dump_file && (dump_flags & TDF_DETAILS))
3341 omega_print_problem (dump_file, pb);
3343 continue;
3346 sv = pb->safe_vars;
3347 if (g2 == 0)
3348 sv = 0;
3350 /* Find variable to eliminate. */
3351 if (g2 > 1)
3353 gcc_assert (in_approximate_mode);
3355 if (dump_file && (dump_flags & TDF_DETAILS))
3357 fprintf (dump_file, "non-exact elimination: ");
3358 omega_print_eq (dump_file, pb, eqn);
3359 fprintf (dump_file, "\n");
3360 omega_print_problem (dump_file, pb);
3363 for (i = pb->num_vars; i > sv; i--)
3364 if (pb->eqs[e].coef[i] != 0)
3365 break;
3367 else
3368 for (i = pb->num_vars; i > sv; i--)
3369 if (pb->eqs[e].coef[i] == 1 || pb->eqs[e].coef[i] == -1)
3370 break;
3372 if (i > sv)
3374 pb->num_eqs--;
3375 omega_do_elimination (pb, e, i);
3377 if (dump_file && (dump_flags & TDF_DETAILS) && g2 > 1)
3379 fprintf (dump_file, "result of non-exact elimination:\n");
3380 omega_print_problem (dump_file, pb);
3383 else
3385 int factor = (INT_MAX);
3386 j = 0;
3388 if (dump_file && (dump_flags & TDF_DETAILS))
3389 fprintf (dump_file, "doing moding\n");
3391 for (i = pb->num_vars; i != sv; i--)
3392 if ((pb->eqs[e].coef[i] & 1) != 0)
3394 j = i;
3395 i--;
3397 for (; i != sv; i--)
3398 if ((pb->eqs[e].coef[i] & 1) != 0)
3399 break;
3401 break;
3404 if (j != 0 && i == sv)
3406 omega_do_mod (pb, 2, e, j);
3407 e++;
3408 continue;
3411 j = 0;
3412 for (i = pb->num_vars; i != sv; i--)
3413 if (pb->eqs[e].coef[i] != 0
3414 && factor > abs (pb->eqs[e].coef[i]) + 1)
3416 factor = abs (pb->eqs[e].coef[i]) + 1;
3417 j = i;
3420 if (j == sv)
3422 if (dump_file && (dump_flags & TDF_DETAILS))
3423 fprintf (dump_file, "should not have happened\n");
3424 gcc_assert (0);
3427 omega_do_mod (pb, factor, e, j);
3428 /* Go back and try this equation again. */
3429 e++;
3434 pb->num_eqs = 0;
3435 return omega_unknown;
3438 /* Transform an inequation E to an equality, then solve DIFF problems
3439 based on PB, and only differing by the constant part that is
3440 diminished by one, trying to figure out which of the constants
3441 satisfies PB. */
3443 static enum omega_result
3444 parallel_splinter (omega_pb pb, int e, int diff,
3445 enum omega_result desired_res)
3447 omega_pb tmp_problem;
3448 int i;
3450 if (dump_file && (dump_flags & TDF_DETAILS))
3452 fprintf (dump_file, "Using parallel splintering\n");
3453 omega_print_problem (dump_file, pb);
3456 tmp_problem = XNEW (struct omega_pb_d);
3457 omega_copy_eqn (&pb->eqs[0], &pb->geqs[e], pb->num_vars);
3458 pb->num_eqs = 1;
3460 for (i = 0; i <= diff; i++)
3462 omega_copy_problem (tmp_problem, pb);
3464 if (dump_file && (dump_flags & TDF_DETAILS))
3466 fprintf (dump_file, "Splinter # %i\n", i);
3467 omega_print_problem (dump_file, pb);
3470 if (omega_solve_problem (tmp_problem, desired_res) == omega_true)
3472 free (tmp_problem);
3473 return omega_true;
3476 pb->eqs[0].coef[0]--;
3479 free (tmp_problem);
3480 return omega_false;
3483 /* Helper function: solve equations one at a time. */
3485 static enum omega_result
3486 omega_solve_geq (omega_pb pb, enum omega_result desired_res)
3488 int i, e;
3489 int n_vars, fv;
3490 enum omega_result result;
3491 bool coupled_subscripts = false;
3492 bool smoothed = false;
3493 bool eliminate_again;
3494 bool tried_eliminating_redundant = false;
3496 if (desired_res != omega_simplify)
3498 pb->num_subs = 0;
3499 pb->safe_vars = 0;
3502 solve_geq_start:
3503 do {
3504 gcc_assert (desired_res == omega_simplify || pb->num_subs == 0);
3506 /* Verify that there are not too many inequalities. */
3507 gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
3509 if (dump_file && (dump_flags & TDF_DETAILS))
3511 fprintf (dump_file, "\nomega_solve_geq (%d,%d):\n",
3512 desired_res, please_no_equalities_in_simplified_problems);
3513 omega_print_problem (dump_file, pb);
3514 fprintf (dump_file, "\n");
3517 n_vars = pb->num_vars;
3519 if (n_vars == 1)
3521 enum omega_eqn_color u_color = omega_black;
3522 enum omega_eqn_color l_color = omega_black;
3523 int upper_bound = pos_infinity;
3524 int lower_bound = neg_infinity;
3526 for (e = pb->num_geqs - 1; e >= 0; e--)
3528 int a = pb->geqs[e].coef[1];
3529 int c = pb->geqs[e].coef[0];
3531 /* Our equation is ax + c >= 0, or ax >= -c, or c >= -ax. */
3532 if (a == 0)
3534 if (c < 0)
3535 return omega_problem_has_no_solution ();
3537 else if (a > 0)
3539 if (a != 1)
3540 c = int_div (c, a);
3542 if (lower_bound < -c
3543 || (lower_bound == -c
3544 && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3546 lower_bound = -c;
3547 l_color = pb->geqs[e].color;
3550 else
3552 if (a != -1)
3553 c = int_div (c, -a);
3555 if (upper_bound > c
3556 || (upper_bound == c
3557 && !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3559 upper_bound = c;
3560 u_color = pb->geqs[e].color;
3565 if (dump_file && (dump_flags & TDF_DETAILS))
3567 fprintf (dump_file, "upper bound = %d\n", upper_bound);
3568 fprintf (dump_file, "lower bound = %d\n", lower_bound);
3571 if (lower_bound > upper_bound)
3572 return omega_problem_has_no_solution ();
3574 if (desired_res == omega_simplify)
3576 pb->num_geqs = 0;
3577 if (pb->safe_vars == 1)
3580 if (lower_bound == upper_bound
3581 && u_color == omega_black
3582 && l_color == omega_black)
3584 pb->eqs[0].coef[0] = -lower_bound;
3585 pb->eqs[0].coef[1] = 1;
3586 pb->eqs[0].color = omega_black;
3587 pb->num_eqs = 1;
3588 return omega_solve_problem (pb, desired_res);
3590 else
3592 if (lower_bound > neg_infinity)
3594 pb->geqs[0].coef[0] = -lower_bound;
3595 pb->geqs[0].coef[1] = 1;
3596 pb->geqs[0].key = 1;
3597 pb->geqs[0].color = l_color;
3598 pb->geqs[0].touched = 0;
3599 pb->num_geqs = 1;
3602 if (upper_bound < pos_infinity)
3604 pb->geqs[pb->num_geqs].coef[0] = upper_bound;
3605 pb->geqs[pb->num_geqs].coef[1] = -1;
3606 pb->geqs[pb->num_geqs].key = -1;
3607 pb->geqs[pb->num_geqs].color = u_color;
3608 pb->geqs[pb->num_geqs].touched = 0;
3609 pb->num_geqs++;
3613 else
3614 pb->num_vars = 0;
3616 omega_problem_reduced (pb);
3617 return omega_false;
3620 if (original_problem != no_problem
3621 && l_color == omega_black
3622 && u_color == omega_black
3623 && !conservative
3624 && lower_bound == upper_bound)
3626 pb->eqs[0].coef[0] = -lower_bound;
3627 pb->eqs[0].coef[1] = 1;
3628 pb->num_eqs = 1;
3629 adding_equality_constraint (pb, 0);
3632 return omega_true;
3635 if (!pb->variables_freed)
3637 pb->variables_freed = true;
3639 if (desired_res != omega_simplify)
3640 omega_free_eliminations (pb, 0);
3641 else
3642 omega_free_eliminations (pb, pb->safe_vars);
3644 n_vars = pb->num_vars;
3646 if (n_vars == 1)
3647 continue;
3650 switch (normalize_omega_problem (pb))
3652 case normalize_false:
3653 return omega_false;
3654 break;
3656 case normalize_coupled:
3657 coupled_subscripts = true;
3658 break;
3660 case normalize_uncoupled:
3661 coupled_subscripts = false;
3662 break;
3664 default:
3665 gcc_unreachable ();
3668 n_vars = pb->num_vars;
3670 if (dump_file && (dump_flags & TDF_DETAILS))
3672 fprintf (dump_file, "\nafter normalization:\n");
3673 omega_print_problem (dump_file, pb);
3674 fprintf (dump_file, "\n");
3675 fprintf (dump_file, "eliminating variable using Fourier-Motzkin.\n");
3678 do {
3679 int parallel_difference = INT_MAX;
3680 int best_parallel_eqn = -1;
3681 int minC, maxC, minCj = 0;
3682 int lower_bound_count = 0;
3683 int e2, Le = 0, Ue;
3684 bool possible_easy_int_solution;
3685 int max_splinters = 1;
3686 bool exact = false;
3687 bool lucky_exact = false;
3688 int best = (INT_MAX);
3689 int j = 0, jLe = 0, jLowerBoundCount = 0;
3692 eliminate_again = false;
3694 if (pb->num_eqs > 0)
3695 return omega_solve_problem (pb, desired_res);
3697 if (!coupled_subscripts)
3699 if (pb->safe_vars == 0)
3700 pb->num_geqs = 0;
3701 else
3702 for (e = pb->num_geqs - 1; e >= 0; e--)
3703 if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
3704 omega_delete_geq (pb, e, n_vars);
3706 pb->num_vars = pb->safe_vars;
3708 if (desired_res == omega_simplify)
3710 omega_problem_reduced (pb);
3711 return omega_false;
3714 return omega_true;
3717 if (desired_res != omega_simplify)
3718 fv = 0;
3719 else
3720 fv = pb->safe_vars;
3722 if (pb->num_geqs == 0)
3724 if (desired_res == omega_simplify)
3726 pb->num_vars = pb->safe_vars;
3727 omega_problem_reduced (pb);
3728 return omega_false;
3730 return omega_true;
3733 if (desired_res == omega_simplify && n_vars == pb->safe_vars)
3735 omega_problem_reduced (pb);
3736 return omega_false;
3739 if (pb->num_geqs > OMEGA_MAX_GEQS - 30
3740 || pb->num_geqs > 2 * n_vars * n_vars + 4 * n_vars + 10)
3742 if (dump_file && (dump_flags & TDF_DETAILS))
3743 fprintf (dump_file,
3744 "TOO MANY EQUATIONS; "
3745 "%d equations, %d variables, "
3746 "ELIMINATING REDUNDANT ONES\n",
3747 pb->num_geqs, n_vars);
3749 if (!omega_eliminate_redundant (pb, false))
3750 return omega_false;
3752 n_vars = pb->num_vars;
3754 if (pb->num_eqs > 0)
3755 return omega_solve_problem (pb, desired_res);
3757 if (dump_file && (dump_flags & TDF_DETAILS))
3758 fprintf (dump_file, "END ELIMINATION OF REDUNDANT EQUATIONS\n");
3761 if (desired_res != omega_simplify)
3762 fv = 0;
3763 else
3764 fv = pb->safe_vars;
3766 for (i = n_vars; i != fv; i--)
3768 int score;
3769 int ub = -2;
3770 int lb = -2;
3771 bool lucky = false;
3772 int upper_bound_count = 0;
3774 lower_bound_count = 0;
3775 minC = maxC = 0;
3777 for (e = pb->num_geqs - 1; e >= 0; e--)
3778 if (pb->geqs[e].coef[i] < 0)
3780 minC = MIN (minC, pb->geqs[e].coef[i]);
3781 upper_bound_count++;
3782 if (pb->geqs[e].coef[i] < -1)
3784 if (ub == -2)
3785 ub = e;
3786 else
3787 ub = -1;
3790 else if (pb->geqs[e].coef[i] > 0)
3792 maxC = MAX (maxC, pb->geqs[e].coef[i]);
3793 lower_bound_count++;
3794 Le = e;
3795 if (pb->geqs[e].coef[i] > 1)
3797 if (lb == -2)
3798 lb = e;
3799 else
3800 lb = -1;
3804 if (lower_bound_count == 0
3805 || upper_bound_count == 0)
3807 lower_bound_count = 0;
3808 break;
3811 if (ub >= 0 && lb >= 0
3812 && pb->geqs[lb].key == -pb->geqs[ub].key)
3814 int Lc = pb->geqs[lb].coef[i];
3815 int Uc = -pb->geqs[ub].coef[i];
3816 int diff =
3817 Lc * pb->geqs[ub].coef[0] + Uc * pb->geqs[lb].coef[0];
3818 lucky = (diff >= (Uc - 1) * (Lc - 1));
3821 if (maxC == 1
3822 || minC == -1
3823 || lucky
3824 || in_approximate_mode)
3826 score = upper_bound_count * lower_bound_count;
3828 if (dump_file && (dump_flags & TDF_DETAILS))
3829 fprintf (dump_file,
3830 "For %s, exact, score = %d*%d, range = %d ... %d,"
3831 "\nlucky = %d, in_approximate_mode=%d \n",
3832 omega_variable_to_str (pb, i),
3833 upper_bound_count,
3834 lower_bound_count, minC, maxC, lucky,
3835 in_approximate_mode);
3837 if (!exact
3838 || score < best)
3841 best = score;
3842 j = i;
3843 minCj = minC;
3844 jLe = Le;
3845 jLowerBoundCount = lower_bound_count;
3846 exact = true;
3847 lucky_exact = lucky;
3848 if (score == 1)
3849 break;
3852 else if (!exact)
3854 if (dump_file && (dump_flags & TDF_DETAILS))
3855 fprintf (dump_file,
3856 "For %s, non-exact, score = %d*%d,"
3857 "range = %d ... %d \n",
3858 omega_variable_to_str (pb, i),
3859 upper_bound_count,
3860 lower_bound_count, minC, maxC);
3862 score = maxC - minC;
3864 if (best > score)
3866 best = score;
3867 j = i;
3868 minCj = minC;
3869 jLe = Le;
3870 jLowerBoundCount = lower_bound_count;
3875 if (lower_bound_count == 0)
3877 omega_free_eliminations (pb, pb->safe_vars);
3878 n_vars = pb->num_vars;
3879 eliminate_again = true;
3880 continue;
3883 i = j;
3884 minC = minCj;
3885 Le = jLe;
3886 lower_bound_count = jLowerBoundCount;
3888 for (e = pb->num_geqs - 1; e >= 0; e--)
3889 if (pb->geqs[e].coef[i] > 0)
3891 if (pb->geqs[e].coef[i] == -minC)
3892 max_splinters += -minC - 1;
3893 else
3894 max_splinters +=
3895 pos_mul_hwi ((pb->geqs[e].coef[i] - 1),
3896 (-minC - 1)) / (-minC) + 1;
3899 /* #ifdef Omega3 */
3900 /* Trying to produce exact elimination by finding redundant
3901 constraints. */
3902 if (!exact && !tried_eliminating_redundant)
3904 omega_eliminate_redundant (pb, false);
3905 tried_eliminating_redundant = true;
3906 eliminate_again = true;
3907 continue;
3909 tried_eliminating_redundant = false;
3910 /* #endif */
3912 if (return_single_result && desired_res == omega_simplify && !exact)
3914 omega_problem_reduced (pb);
3915 return omega_true;
3918 /* #ifndef Omega3 */
3919 /* Trying to produce exact elimination by finding redundant
3920 constraints. */
3921 if (!exact && !tried_eliminating_redundant)
3923 omega_eliminate_redundant (pb, false);
3924 tried_eliminating_redundant = true;
3925 continue;
3927 tried_eliminating_redundant = false;
3928 /* #endif */
3930 if (!exact)
3932 int e1, e2;
3934 for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
3935 if (pb->geqs[e1].color == omega_black)
3936 for (e2 = e1 - 1; e2 >= 0; e2--)
3937 if (pb->geqs[e2].color == omega_black
3938 && pb->geqs[e1].key == -pb->geqs[e2].key
3939 && ((pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3940 * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3941 / 2 < parallel_difference))
3943 parallel_difference =
3944 (pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3945 * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3946 / 2;
3947 best_parallel_eqn = e1;
3950 if (dump_file && (dump_flags & TDF_DETAILS)
3951 && best_parallel_eqn >= 0)
3953 fprintf (dump_file,
3954 "Possible parallel projection, diff = %d, in ",
3955 parallel_difference);
3956 omega_print_geq (dump_file, pb, &(pb->geqs[best_parallel_eqn]));
3957 fprintf (dump_file, "\n");
3958 omega_print_problem (dump_file, pb);
3962 if (dump_file && (dump_flags & TDF_DETAILS))
3964 fprintf (dump_file, "going to eliminate %s, (%d,%d,%d)\n",
3965 omega_variable_to_str (pb, i), i, minC,
3966 lower_bound_count);
3967 omega_print_problem (dump_file, pb);
3969 if (lucky_exact)
3970 fprintf (dump_file, "(a lucky exact elimination)\n");
3972 else if (exact)
3973 fprintf (dump_file, "(an exact elimination)\n");
3975 fprintf (dump_file, "Max # of splinters = %d\n", max_splinters);
3978 gcc_assert (max_splinters >= 1);
3980 if (!exact && desired_res == omega_simplify && best_parallel_eqn >= 0
3981 && parallel_difference <= max_splinters)
3982 return parallel_splinter (pb, best_parallel_eqn, parallel_difference,
3983 desired_res);
3985 smoothed = false;
3987 if (i != n_vars)
3989 int t;
3990 int j = pb->num_vars;
3992 if (dump_file && (dump_flags & TDF_DETAILS))
3994 fprintf (dump_file, "Swapping %d and %d\n", i, j);
3995 omega_print_problem (dump_file, pb);
3998 swap (&pb->var[i], &pb->var[j]);
4000 for (e = pb->num_geqs - 1; e >= 0; e--)
4001 if (pb->geqs[e].coef[i] != pb->geqs[e].coef[j])
4003 pb->geqs[e].touched = 1;
4004 t = pb->geqs[e].coef[i];
4005 pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
4006 pb->geqs[e].coef[j] = t;
4009 for (e = pb->num_subs - 1; e >= 0; e--)
4010 if (pb->subs[e].coef[i] != pb->subs[e].coef[j])
4012 t = pb->subs[e].coef[i];
4013 pb->subs[e].coef[i] = pb->subs[e].coef[j];
4014 pb->subs[e].coef[j] = t;
4017 if (dump_file && (dump_flags & TDF_DETAILS))
4019 fprintf (dump_file, "Swapping complete \n");
4020 omega_print_problem (dump_file, pb);
4021 fprintf (dump_file, "\n");
4024 i = j;
4027 else if (dump_file && (dump_flags & TDF_DETAILS))
4029 fprintf (dump_file, "No swap needed\n");
4030 omega_print_problem (dump_file, pb);
4033 pb->num_vars--;
4034 n_vars = pb->num_vars;
4036 if (exact)
4038 if (n_vars == 1)
4040 int upper_bound = pos_infinity;
4041 int lower_bound = neg_infinity;
4042 enum omega_eqn_color ub_color = omega_black;
4043 enum omega_eqn_color lb_color = omega_black;
4044 int topeqn = pb->num_geqs - 1;
4045 int Lc = pb->geqs[Le].coef[i];
4047 for (Le = topeqn; Le >= 0; Le--)
4048 if ((Lc = pb->geqs[Le].coef[i]) == 0)
4050 if (pb->geqs[Le].coef[1] == 1)
4052 int constantTerm = -pb->geqs[Le].coef[0];
4054 if (constantTerm > lower_bound ||
4055 (constantTerm == lower_bound &&
4056 !omega_eqn_is_red (&pb->geqs[Le], desired_res)))
4058 lower_bound = constantTerm;
4059 lb_color = pb->geqs[Le].color;
4062 if (dump_file && (dump_flags & TDF_DETAILS))
4064 if (pb->geqs[Le].color == omega_black)
4065 fprintf (dump_file, " :::=> %s >= %d\n",
4066 omega_variable_to_str (pb, 1),
4067 constantTerm);
4068 else
4069 fprintf (dump_file,
4070 " :::=> [%s >= %d]\n",
4071 omega_variable_to_str (pb, 1),
4072 constantTerm);
4075 else
4077 int constantTerm = pb->geqs[Le].coef[0];
4078 if (constantTerm < upper_bound ||
4079 (constantTerm == upper_bound
4080 && !omega_eqn_is_red (&pb->geqs[Le],
4081 desired_res)))
4083 upper_bound = constantTerm;
4084 ub_color = pb->geqs[Le].color;
4087 if (dump_file && (dump_flags & TDF_DETAILS))
4089 if (pb->geqs[Le].color == omega_black)
4090 fprintf (dump_file, " :::=> %s <= %d\n",
4091 omega_variable_to_str (pb, 1),
4092 constantTerm);
4093 else
4094 fprintf (dump_file,
4095 " :::=> [%s <= %d]\n",
4096 omega_variable_to_str (pb, 1),
4097 constantTerm);
4101 else if (Lc > 0)
4102 for (Ue = topeqn; Ue >= 0; Ue--)
4103 if (pb->geqs[Ue].coef[i] < 0
4104 && pb->geqs[Le].key != -pb->geqs[Ue].key)
4106 int Uc = -pb->geqs[Ue].coef[i];
4107 int coefficient = pb->geqs[Ue].coef[1] * Lc
4108 + pb->geqs[Le].coef[1] * Uc;
4109 int constantTerm = pb->geqs[Ue].coef[0] * Lc
4110 + pb->geqs[Le].coef[0] * Uc;
4112 if (dump_file && (dump_flags & TDF_DETAILS))
4114 omega_print_geq_extra (dump_file, pb,
4115 &(pb->geqs[Ue]));
4116 fprintf (dump_file, "\n");
4117 omega_print_geq_extra (dump_file, pb,
4118 &(pb->geqs[Le]));
4119 fprintf (dump_file, "\n");
4122 if (coefficient > 0)
4124 constantTerm = -int_div (constantTerm, coefficient);
4126 if (constantTerm > lower_bound
4127 || (constantTerm == lower_bound
4128 && (desired_res != omega_simplify
4129 || (pb->geqs[Ue].color == omega_black
4130 && pb->geqs[Le].color == omega_black))))
4132 lower_bound = constantTerm;
4133 lb_color = (pb->geqs[Ue].color == omega_red
4134 || pb->geqs[Le].color == omega_red)
4135 ? omega_red : omega_black;
4138 if (dump_file && (dump_flags & TDF_DETAILS))
4140 if (pb->geqs[Ue].color == omega_red
4141 || pb->geqs[Le].color == omega_red)
4142 fprintf (dump_file,
4143 " ::=> [%s >= %d]\n",
4144 omega_variable_to_str (pb, 1),
4145 constantTerm);
4146 else
4147 fprintf (dump_file,
4148 " ::=> %s >= %d\n",
4149 omega_variable_to_str (pb, 1),
4150 constantTerm);
4153 else
4155 constantTerm = int_div (constantTerm, -coefficient);
4156 if (constantTerm < upper_bound
4157 || (constantTerm == upper_bound
4158 && pb->geqs[Ue].color == omega_black
4159 && pb->geqs[Le].color == omega_black))
4161 upper_bound = constantTerm;
4162 ub_color = (pb->geqs[Ue].color == omega_red
4163 || pb->geqs[Le].color == omega_red)
4164 ? omega_red : omega_black;
4167 if (dump_file
4168 && (dump_flags & TDF_DETAILS))
4170 if (pb->geqs[Ue].color == omega_red
4171 || pb->geqs[Le].color == omega_red)
4172 fprintf (dump_file,
4173 " ::=> [%s <= %d]\n",
4174 omega_variable_to_str (pb, 1),
4175 constantTerm);
4176 else
4177 fprintf (dump_file,
4178 " ::=> %s <= %d\n",
4179 omega_variable_to_str (pb, 1),
4180 constantTerm);
4185 pb->num_geqs = 0;
4187 if (dump_file && (dump_flags & TDF_DETAILS))
4188 fprintf (dump_file,
4189 " therefore, %c%d <= %c%s%c <= %d%c\n",
4190 lb_color == omega_red ? '[' : ' ', lower_bound,
4191 (lb_color == omega_red && ub_color == omega_black)
4192 ? ']' : ' ',
4193 omega_variable_to_str (pb, 1),
4194 (lb_color == omega_black && ub_color == omega_red)
4195 ? '[' : ' ',
4196 upper_bound, ub_color == omega_red ? ']' : ' ');
4198 if (lower_bound > upper_bound)
4199 return omega_false;
4201 if (pb->safe_vars == 1)
4203 if (upper_bound == lower_bound
4204 && !(ub_color == omega_red || lb_color == omega_red)
4205 && !please_no_equalities_in_simplified_problems)
4207 pb->num_eqs++;
4208 pb->eqs[0].coef[1] = -1;
4209 pb->eqs[0].coef[0] = upper_bound;
4211 if (ub_color == omega_red
4212 || lb_color == omega_red)
4213 pb->eqs[0].color = omega_red;
4215 if (desired_res == omega_simplify
4216 && pb->eqs[0].color == omega_black)
4217 return omega_solve_problem (pb, desired_res);
4220 if (upper_bound != pos_infinity)
4222 pb->geqs[0].coef[1] = -1;
4223 pb->geqs[0].coef[0] = upper_bound;
4224 pb->geqs[0].color = ub_color;
4225 pb->geqs[0].key = -1;
4226 pb->geqs[0].touched = 0;
4227 pb->num_geqs++;
4230 if (lower_bound != neg_infinity)
4232 pb->geqs[pb->num_geqs].coef[1] = 1;
4233 pb->geqs[pb->num_geqs].coef[0] = -lower_bound;
4234 pb->geqs[pb->num_geqs].color = lb_color;
4235 pb->geqs[pb->num_geqs].key = 1;
4236 pb->geqs[pb->num_geqs].touched = 0;
4237 pb->num_geqs++;
4241 if (desired_res == omega_simplify)
4243 omega_problem_reduced (pb);
4244 return omega_false;
4246 else
4248 if (!conservative
4249 && (desired_res != omega_simplify
4250 || (lb_color == omega_black
4251 && ub_color == omega_black))
4252 && original_problem != no_problem
4253 && lower_bound == upper_bound)
4255 for (i = original_problem->num_vars; i >= 0; i--)
4256 if (original_problem->var[i] == pb->var[1])
4257 break;
4259 if (i == 0)
4260 break;
4262 e = original_problem->num_eqs++;
4263 omega_init_eqn_zero (&original_problem->eqs[e],
4264 original_problem->num_vars);
4265 original_problem->eqs[e].coef[i] = -1;
4266 original_problem->eqs[e].coef[0] = upper_bound;
4268 if (dump_file && (dump_flags & TDF_DETAILS))
4270 fprintf (dump_file,
4271 "adding equality %d to outer problem\n", e);
4272 omega_print_problem (dump_file, original_problem);
4275 return omega_true;
4279 eliminate_again = true;
4281 if (lower_bound_count == 1)
4283 eqn lbeqn = omega_alloc_eqns (0, 1);
4284 int Lc = pb->geqs[Le].coef[i];
4286 if (dump_file && (dump_flags & TDF_DETAILS))
4287 fprintf (dump_file, "an inplace elimination\n");
4289 omega_copy_eqn (lbeqn, &pb->geqs[Le], (n_vars + 1));
4290 omega_delete_geq_extra (pb, Le, n_vars + 1);
4292 for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4293 if (pb->geqs[Ue].coef[i] < 0)
4295 if (lbeqn->key == -pb->geqs[Ue].key)
4296 omega_delete_geq_extra (pb, Ue, n_vars + 1);
4297 else
4299 int k;
4300 int Uc = -pb->geqs[Ue].coef[i];
4301 pb->geqs[Ue].touched = 1;
4302 eliminate_again = false;
4304 if (lbeqn->color == omega_red)
4305 pb->geqs[Ue].color = omega_red;
4307 for (k = 0; k <= n_vars; k++)
4308 pb->geqs[Ue].coef[k] =
4309 mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4310 mul_hwi (lbeqn->coef[k], Uc);
4312 if (dump_file && (dump_flags & TDF_DETAILS))
4314 omega_print_geq (dump_file, pb,
4315 &(pb->geqs[Ue]));
4316 fprintf (dump_file, "\n");
4321 omega_free_eqns (lbeqn, 1);
4322 continue;
4324 else
4326 int *dead_eqns = XNEWVEC (int, OMEGA_MAX_GEQS);
4327 bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
4328 int num_dead = 0;
4329 int top_eqn = pb->num_geqs - 1;
4330 lower_bound_count--;
4332 if (dump_file && (dump_flags & TDF_DETAILS))
4333 fprintf (dump_file, "lower bound count = %d\n",
4334 lower_bound_count);
4336 for (Le = top_eqn; Le >= 0; Le--)
4337 if (pb->geqs[Le].coef[i] > 0)
4339 int Lc = pb->geqs[Le].coef[i];
4340 for (Ue = top_eqn; Ue >= 0; Ue--)
4341 if (pb->geqs[Ue].coef[i] < 0)
4343 if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4345 int k;
4346 int Uc = -pb->geqs[Ue].coef[i];
4348 if (num_dead == 0)
4349 e2 = pb->num_geqs++;
4350 else
4351 e2 = dead_eqns[--num_dead];
4353 gcc_assert (e2 < OMEGA_MAX_GEQS);
4355 if (dump_file && (dump_flags & TDF_DETAILS))
4357 fprintf (dump_file,
4358 "Le = %d, Ue = %d, gen = %d\n",
4359 Le, Ue, e2);
4360 omega_print_geq_extra (dump_file, pb,
4361 &(pb->geqs[Le]));
4362 fprintf (dump_file, "\n");
4363 omega_print_geq_extra (dump_file, pb,
4364 &(pb->geqs[Ue]));
4365 fprintf (dump_file, "\n");
4368 eliminate_again = false;
4370 for (k = n_vars; k >= 0; k--)
4371 pb->geqs[e2].coef[k] =
4372 mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4373 mul_hwi (pb->geqs[Le].coef[k], Uc);
4375 pb->geqs[e2].coef[n_vars + 1] = 0;
4376 pb->geqs[e2].touched = 1;
4378 if (pb->geqs[Ue].color == omega_red
4379 || pb->geqs[Le].color == omega_red)
4380 pb->geqs[e2].color = omega_red;
4381 else
4382 pb->geqs[e2].color = omega_black;
4384 if (dump_file && (dump_flags & TDF_DETAILS))
4386 omega_print_geq (dump_file, pb,
4387 &(pb->geqs[e2]));
4388 fprintf (dump_file, "\n");
4392 if (lower_bound_count == 0)
4394 dead_eqns[num_dead++] = Ue;
4396 if (dump_file && (dump_flags & TDF_DETAILS))
4397 fprintf (dump_file, "Killed %d\n", Ue);
4401 lower_bound_count--;
4402 dead_eqns[num_dead++] = Le;
4404 if (dump_file && (dump_flags & TDF_DETAILS))
4405 fprintf (dump_file, "Killed %d\n", Le);
4408 for (e = pb->num_geqs - 1; e >= 0; e--)
4409 is_dead[e] = false;
4411 while (num_dead > 0)
4412 is_dead[dead_eqns[--num_dead]] = true;
4414 for (e = pb->num_geqs - 1; e >= 0; e--)
4415 if (is_dead[e])
4416 omega_delete_geq_extra (pb, e, n_vars + 1);
4418 free (dead_eqns);
4419 free (is_dead);
4420 continue;
4423 else
4425 omega_pb rS, iS;
4427 rS = omega_alloc_problem (0, 0);
4428 iS = omega_alloc_problem (0, 0);
4429 e2 = 0;
4430 possible_easy_int_solution = true;
4432 for (e = 0; e < pb->num_geqs; e++)
4433 if (pb->geqs[e].coef[i] == 0)
4435 omega_copy_eqn (&(rS->geqs[e2]), &pb->geqs[e],
4436 pb->num_vars);
4437 omega_copy_eqn (&(iS->geqs[e2]), &pb->geqs[e],
4438 pb->num_vars);
4440 if (dump_file && (dump_flags & TDF_DETAILS))
4442 int t;
4443 fprintf (dump_file, "Copying (%d, %d): ", i,
4444 pb->geqs[e].coef[i]);
4445 omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
4446 fprintf (dump_file, "\n");
4447 for (t = 0; t <= n_vars + 1; t++)
4448 fprintf (dump_file, "%d ", pb->geqs[e].coef[t]);
4449 fprintf (dump_file, "\n");
4452 e2++;
4453 gcc_assert (e2 < OMEGA_MAX_GEQS);
4456 for (Le = pb->num_geqs - 1; Le >= 0; Le--)
4457 if (pb->geqs[Le].coef[i] > 0)
4458 for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4459 if (pb->geqs[Ue].coef[i] < 0)
4461 int k;
4462 int Lc = pb->geqs[Le].coef[i];
4463 int Uc = -pb->geqs[Ue].coef[i];
4465 if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4468 rS->geqs[e2].touched = iS->geqs[e2].touched = 1;
4470 if (dump_file && (dump_flags & TDF_DETAILS))
4472 fprintf (dump_file, "---\n");
4473 fprintf (dump_file,
4474 "Le(Lc) = %d(%d_, Ue(Uc) = %d(%d), gen = %d\n",
4475 Le, Lc, Ue, Uc, e2);
4476 omega_print_geq_extra (dump_file, pb, &pb->geqs[Le]);
4477 fprintf (dump_file, "\n");
4478 omega_print_geq_extra (dump_file, pb, &pb->geqs[Ue]);
4479 fprintf (dump_file, "\n");
4482 if (Uc == Lc)
4484 for (k = n_vars; k >= 0; k--)
4485 iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4486 pb->geqs[Ue].coef[k] + pb->geqs[Le].coef[k];
4488 iS->geqs[e2].coef[0] -= (Uc - 1);
4490 else
4492 for (k = n_vars; k >= 0; k--)
4493 iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4494 mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4495 mul_hwi (pb->geqs[Le].coef[k], Uc);
4497 iS->geqs[e2].coef[0] -= (Uc - 1) * (Lc - 1);
4500 if (pb->geqs[Ue].color == omega_red
4501 || pb->geqs[Le].color == omega_red)
4502 iS->geqs[e2].color = rS->geqs[e2].color = omega_red;
4503 else
4504 iS->geqs[e2].color = rS->geqs[e2].color = omega_black;
4506 if (dump_file && (dump_flags & TDF_DETAILS))
4508 omega_print_geq (dump_file, pb, &(rS->geqs[e2]));
4509 fprintf (dump_file, "\n");
4512 e2++;
4513 gcc_assert (e2 < OMEGA_MAX_GEQS);
4515 else if (pb->geqs[Ue].coef[0] * Lc +
4516 pb->geqs[Le].coef[0] * Uc -
4517 (Uc - 1) * (Lc - 1) < 0)
4518 possible_easy_int_solution = false;
4521 iS->variables_initialized = rS->variables_initialized = true;
4522 iS->num_vars = rS->num_vars = pb->num_vars;
4523 iS->num_geqs = rS->num_geqs = e2;
4524 iS->num_eqs = rS->num_eqs = 0;
4525 iS->num_subs = rS->num_subs = pb->num_subs;
4526 iS->safe_vars = rS->safe_vars = pb->safe_vars;
4528 for (e = n_vars; e >= 0; e--)
4529 rS->var[e] = pb->var[e];
4531 for (e = n_vars; e >= 0; e--)
4532 iS->var[e] = pb->var[e];
4534 for (e = pb->num_subs - 1; e >= 0; e--)
4536 omega_copy_eqn (&(rS->subs[e]), &(pb->subs[e]), pb->num_vars);
4537 omega_copy_eqn (&(iS->subs[e]), &(pb->subs[e]), pb->num_vars);
4540 pb->num_vars++;
4541 n_vars = pb->num_vars;
4543 if (desired_res != omega_true)
4545 if (original_problem == no_problem)
4547 original_problem = pb;
4548 result = omega_solve_geq (rS, omega_false);
4549 original_problem = no_problem;
4551 else
4552 result = omega_solve_geq (rS, omega_false);
4554 if (result == omega_false)
4556 free (rS);
4557 free (iS);
4558 return result;
4561 if (pb->num_eqs > 0)
4563 /* An equality constraint must have been found */
4564 free (rS);
4565 free (iS);
4566 return omega_solve_problem (pb, desired_res);
4570 if (desired_res != omega_false)
4572 int j;
4573 int lower_bounds = 0;
4574 int *lower_bound = XNEWVEC (int, OMEGA_MAX_GEQS);
4576 if (possible_easy_int_solution)
4578 conservative++;
4579 result = omega_solve_geq (iS, desired_res);
4580 conservative--;
4582 if (result != omega_false)
4584 free (rS);
4585 free (iS);
4586 free (lower_bound);
4587 return result;
4591 if (!exact && best_parallel_eqn >= 0
4592 && parallel_difference <= max_splinters)
4594 free (rS);
4595 free (iS);
4596 free (lower_bound);
4597 return parallel_splinter (pb, best_parallel_eqn,
4598 parallel_difference,
4599 desired_res);
4602 if (dump_file && (dump_flags & TDF_DETAILS))
4603 fprintf (dump_file, "have to do exact analysis\n");
4605 conservative++;
4607 for (e = 0; e < pb->num_geqs; e++)
4608 if (pb->geqs[e].coef[i] > 1)
4609 lower_bound[lower_bounds++] = e;
4611 /* Sort array LOWER_BOUND. */
4612 for (j = 0; j < lower_bounds; j++)
4614 int k, smallest = j;
4616 for (k = j + 1; k < lower_bounds; k++)
4617 if (pb->geqs[lower_bound[smallest]].coef[i] >
4618 pb->geqs[lower_bound[k]].coef[i])
4619 smallest = k;
4621 k = lower_bound[smallest];
4622 lower_bound[smallest] = lower_bound[j];
4623 lower_bound[j] = k;
4626 if (dump_file && (dump_flags & TDF_DETAILS))
4628 fprintf (dump_file, "lower bound coefficients = ");
4630 for (j = 0; j < lower_bounds; j++)
4631 fprintf (dump_file, " %d",
4632 pb->geqs[lower_bound[j]].coef[i]);
4634 fprintf (dump_file, "\n");
4637 for (j = 0; j < lower_bounds; j++)
4639 int max_incr;
4640 int c;
4641 int worst_lower_bound_constant = -minC;
4643 e = lower_bound[j];
4644 max_incr = (((pb->geqs[e].coef[i] - 1) *
4645 (worst_lower_bound_constant - 1) - 1)
4646 / worst_lower_bound_constant);
4647 /* max_incr += 2; */
4649 if (dump_file && (dump_flags & TDF_DETAILS))
4651 fprintf (dump_file, "for equation ");
4652 omega_print_geq (dump_file, pb, &pb->geqs[e]);
4653 fprintf (dump_file,
4654 "\ntry decrements from 0 to %d\n",
4655 max_incr);
4656 omega_print_problem (dump_file, pb);
4659 if (max_incr > 50 && !smoothed
4660 && smooth_weird_equations (pb))
4662 conservative--;
4663 free (rS);
4664 free (iS);
4665 smoothed = true;
4666 goto solve_geq_start;
4669 omega_copy_eqn (&pb->eqs[0], &pb->geqs[e],
4670 pb->num_vars);
4671 pb->eqs[0].color = omega_black;
4672 omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
4673 pb->geqs[e].touched = 1;
4674 pb->num_eqs = 1;
4676 for (c = max_incr; c >= 0; c--)
4678 if (dump_file && (dump_flags & TDF_DETAILS))
4680 fprintf (dump_file,
4681 "trying next decrement of %d\n",
4682 max_incr - c);
4683 omega_print_problem (dump_file, pb);
4686 omega_copy_problem (rS, pb);
4688 if (dump_file && (dump_flags & TDF_DETAILS))
4689 omega_print_problem (dump_file, rS);
4691 result = omega_solve_problem (rS, desired_res);
4693 if (result == omega_true)
4695 free (rS);
4696 free (iS);
4697 free (lower_bound);
4698 conservative--;
4699 return omega_true;
4702 pb->eqs[0].coef[0]--;
4705 if (j + 1 < lower_bounds)
4707 pb->num_eqs = 0;
4708 omega_copy_eqn (&pb->geqs[e], &pb->eqs[0],
4709 pb->num_vars);
4710 pb->geqs[e].touched = 1;
4711 pb->geqs[e].color = omega_black;
4712 omega_copy_problem (rS, pb);
4714 if (dump_file && (dump_flags & TDF_DETAILS))
4715 fprintf (dump_file,
4716 "exhausted lower bound, "
4717 "checking if still feasible ");
4719 result = omega_solve_problem (rS, omega_false);
4721 if (result == omega_false)
4722 break;
4726 if (dump_file && (dump_flags & TDF_DETAILS))
4727 fprintf (dump_file, "fall-off the end\n");
4729 free (rS);
4730 free (iS);
4731 free (lower_bound);
4732 conservative--;
4733 return omega_false;
4736 free (rS);
4737 free (iS);
4739 return omega_unknown;
4740 } while (eliminate_again);
4741 } while (1);
4744 /* Because the omega solver is recursive, this counter limits the
4745 recursion depth. */
4746 static int omega_solve_depth = 0;
4748 /* Return omega_true when the problem PB has a solution following the
4749 DESIRED_RES. */
4751 enum omega_result
4752 omega_solve_problem (omega_pb pb, enum omega_result desired_res)
4754 enum omega_result result;
4756 gcc_assert (pb->num_vars >= pb->safe_vars);
4757 omega_solve_depth++;
4759 if (desired_res != omega_simplify)
4760 pb->safe_vars = 0;
4762 if (omega_solve_depth > 50)
4764 if (dump_file && (dump_flags & TDF_DETAILS))
4766 fprintf (dump_file,
4767 "Solve depth = %d, in_approximate_mode = %d, aborting\n",
4768 omega_solve_depth, in_approximate_mode);
4769 omega_print_problem (dump_file, pb);
4771 gcc_assert (0);
4774 if (omega_solve_eq (pb, desired_res) == omega_false)
4776 omega_solve_depth--;
4777 return omega_false;
4780 if (in_approximate_mode && !pb->num_geqs)
4782 result = omega_true;
4783 pb->num_vars = pb->safe_vars;
4784 omega_problem_reduced (pb);
4786 else
4787 result = omega_solve_geq (pb, desired_res);
4789 omega_solve_depth--;
4791 if (!omega_reduce_with_subs)
4793 resurrect_subs (pb);
4794 gcc_assert (please_no_equalities_in_simplified_problems
4795 || !result || pb->num_subs == 0);
4798 return result;
4801 /* Return true if red equations constrain the set of possible solutions.
4802 We assume that there are solutions to the black equations by
4803 themselves, so if there is no solution to the combined problem, we
4804 return true. */
4806 bool
4807 omega_problem_has_red_equations (omega_pb pb)
4809 bool result;
4810 int e;
4811 int i;
4813 if (dump_file && (dump_flags & TDF_DETAILS))
4815 fprintf (dump_file, "Checking for red equations:\n");
4816 omega_print_problem (dump_file, pb);
4819 please_no_equalities_in_simplified_problems++;
4820 may_be_red++;
4822 if (omega_single_result)
4823 return_single_result++;
4825 create_color = true;
4826 result = (omega_simplify_problem (pb) == omega_false);
4828 if (omega_single_result)
4829 return_single_result--;
4831 may_be_red--;
4832 please_no_equalities_in_simplified_problems--;
4834 if (result)
4836 if (dump_file && (dump_flags & TDF_DETAILS))
4837 fprintf (dump_file, "Gist is FALSE\n");
4839 pb->num_subs = 0;
4840 pb->num_geqs = 0;
4841 pb->num_eqs = 1;
4842 pb->eqs[0].color = omega_red;
4844 for (i = pb->num_vars; i > 0; i--)
4845 pb->eqs[0].coef[i] = 0;
4847 pb->eqs[0].coef[0] = 1;
4848 return true;
4851 free_red_eliminations (pb);
4852 gcc_assert (pb->num_eqs == 0);
4854 for (e = pb->num_geqs - 1; e >= 0; e--)
4855 if (pb->geqs[e].color == omega_red)
4856 result = true;
4858 if (!result)
4859 return false;
4861 for (i = pb->safe_vars; i >= 1; i--)
4863 int ub = 0;
4864 int lb = 0;
4866 for (e = pb->num_geqs - 1; e >= 0; e--)
4868 if (pb->geqs[e].coef[i])
4870 if (pb->geqs[e].coef[i] > 0)
4871 lb |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4873 else
4874 ub |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4878 if (ub == 2 || lb == 2)
4881 if (dump_file && (dump_flags & TDF_DETAILS))
4882 fprintf (dump_file, "checks for upper/lower bounds worked!\n");
4884 if (!omega_reduce_with_subs)
4886 resurrect_subs (pb);
4887 gcc_assert (pb->num_subs == 0);
4890 return true;
4895 if (dump_file && (dump_flags & TDF_DETAILS))
4896 fprintf (dump_file,
4897 "*** Doing potentially expensive elimination tests "
4898 "for red equations\n");
4900 please_no_equalities_in_simplified_problems++;
4901 omega_eliminate_red (pb, true);
4902 please_no_equalities_in_simplified_problems--;
4904 result = false;
4905 gcc_assert (pb->num_eqs == 0);
4907 for (e = pb->num_geqs - 1; e >= 0; e--)
4908 if (pb->geqs[e].color == omega_red)
4909 result = true;
4911 if (dump_file && (dump_flags & TDF_DETAILS))
4913 if (!result)
4914 fprintf (dump_file,
4915 "******************** Redundant Red Equations eliminated!!\n");
4916 else
4917 fprintf (dump_file,
4918 "******************** Red Equations remain\n");
4920 omega_print_problem (dump_file, pb);
4923 if (!omega_reduce_with_subs)
4925 normalize_return_type r;
4927 resurrect_subs (pb);
4928 r = normalize_omega_problem (pb);
4929 gcc_assert (r != normalize_false);
4931 coalesce (pb);
4932 cleanout_wildcards (pb);
4933 gcc_assert (pb->num_subs == 0);
4936 return result;
4939 /* Calls omega_simplify_problem in approximate mode. */
4941 enum omega_result
4942 omega_simplify_approximate (omega_pb pb)
4944 enum omega_result result;
4946 if (dump_file && (dump_flags & TDF_DETAILS))
4947 fprintf (dump_file, "(Entering approximate mode\n");
4949 in_approximate_mode = true;
4950 result = omega_simplify_problem (pb);
4951 in_approximate_mode = false;
4953 gcc_assert (pb->num_vars == pb->safe_vars);
4954 if (!omega_reduce_with_subs)
4955 gcc_assert (pb->num_subs == 0);
4957 if (dump_file && (dump_flags & TDF_DETAILS))
4958 fprintf (dump_file, "Leaving approximate mode)\n");
4960 return result;
4964 /* Simplifies problem PB by eliminating redundant constraints and
4965 reducing the constraints system to a minimal form. Returns
4966 omega_true when the problem was successfully reduced, omega_unknown
4967 when the solver is unable to determine an answer. */
4969 enum omega_result
4970 omega_simplify_problem (omega_pb pb)
4972 int i;
4974 omega_found_reduction = omega_false;
4976 if (!pb->variables_initialized)
4977 omega_initialize_variables (pb);
4979 if (next_key * 3 > MAX_KEYS)
4981 int e;
4983 hash_version++;
4984 next_key = OMEGA_MAX_VARS + 1;
4986 for (e = pb->num_geqs - 1; e >= 0; e--)
4987 pb->geqs[e].touched = 1;
4989 for (i = 0; i < HASH_TABLE_SIZE; i++)
4990 hash_master[i].touched = -1;
4992 pb->hash_version = hash_version;
4995 else if (pb->hash_version != hash_version)
4997 int e;
4999 for (e = pb->num_geqs - 1; e >= 0; e--)
5000 pb->geqs[e].touched = 1;
5002 pb->hash_version = hash_version;
5005 if (pb->num_vars > pb->num_eqs + 3 * pb->safe_vars)
5006 omega_free_eliminations (pb, pb->safe_vars);
5008 if (!may_be_red && pb->num_subs == 0 && pb->safe_vars == 0)
5010 omega_found_reduction = omega_solve_problem (pb, omega_unknown);
5012 if (omega_found_reduction != omega_false
5013 && !return_single_result)
5015 pb->num_geqs = 0;
5016 pb->num_eqs = 0;
5017 (*omega_when_reduced) (pb);
5020 return omega_found_reduction;
5023 omega_solve_problem (pb, omega_simplify);
5025 if (omega_found_reduction != omega_false)
5027 for (i = 1; omega_safe_var_p (pb, i); i++)
5028 pb->forwarding_address[pb->var[i]] = i;
5030 for (i = 0; i < pb->num_subs; i++)
5031 pb->forwarding_address[pb->subs[i].key] = -i - 1;
5034 if (!omega_reduce_with_subs)
5035 gcc_assert (please_no_equalities_in_simplified_problems
5036 || omega_found_reduction == omega_false
5037 || pb->num_subs == 0);
5039 return omega_found_reduction;
5042 /* Make variable VAR unprotected: it then can be eliminated. */
5044 void
5045 omega_unprotect_variable (omega_pb pb, int var)
5047 int e, idx;
5048 idx = pb->forwarding_address[var];
5050 if (idx < 0)
5052 idx = -1 - idx;
5053 pb->num_subs--;
5055 if (idx < pb->num_subs)
5057 omega_copy_eqn (&pb->subs[idx], &pb->subs[pb->num_subs],
5058 pb->num_vars);
5059 pb->forwarding_address[pb->subs[idx].key] = -idx - 1;
5062 else
5064 int *bring_to_life = XNEWVEC (int, OMEGA_MAX_VARS);
5065 int e2;
5067 for (e = pb->num_subs - 1; e >= 0; e--)
5068 bring_to_life[e] = (pb->subs[e].coef[idx] != 0);
5070 for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
5071 if (bring_to_life[e2])
5073 pb->num_vars++;
5074 pb->safe_vars++;
5076 if (pb->safe_vars < pb->num_vars)
5078 for (e = pb->num_geqs - 1; e >= 0; e--)
5080 pb->geqs[e].coef[pb->num_vars] =
5081 pb->geqs[e].coef[pb->safe_vars];
5083 pb->geqs[e].coef[pb->safe_vars] = 0;
5086 for (e = pb->num_eqs - 1; e >= 0; e--)
5088 pb->eqs[e].coef[pb->num_vars] =
5089 pb->eqs[e].coef[pb->safe_vars];
5091 pb->eqs[e].coef[pb->safe_vars] = 0;
5094 for (e = pb->num_subs - 1; e >= 0; e--)
5096 pb->subs[e].coef[pb->num_vars] =
5097 pb->subs[e].coef[pb->safe_vars];
5099 pb->subs[e].coef[pb->safe_vars] = 0;
5102 pb->var[pb->num_vars] = pb->var[pb->safe_vars];
5103 pb->forwarding_address[pb->var[pb->num_vars]] =
5104 pb->num_vars;
5106 else
5108 for (e = pb->num_geqs - 1; e >= 0; e--)
5109 pb->geqs[e].coef[pb->safe_vars] = 0;
5111 for (e = pb->num_eqs - 1; e >= 0; e--)
5112 pb->eqs[e].coef[pb->safe_vars] = 0;
5114 for (e = pb->num_subs - 1; e >= 0; e--)
5115 pb->subs[e].coef[pb->safe_vars] = 0;
5118 pb->var[pb->safe_vars] = pb->subs[e2].key;
5119 pb->forwarding_address[pb->subs[e2].key] = pb->safe_vars;
5121 omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e2]),
5122 pb->num_vars);
5123 pb->eqs[pb->num_eqs++].coef[pb->safe_vars] = -1;
5124 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5126 if (e2 < pb->num_subs - 1)
5127 omega_copy_eqn (&(pb->subs[e2]), &(pb->subs[pb->num_subs - 1]),
5128 pb->num_vars);
5130 pb->num_subs--;
5133 omega_unprotect_1 (pb, &idx, NULL);
5134 free (bring_to_life);
5137 chain_unprotect (pb);
5140 /* Unprotects VAR and simplifies PB. */
5142 enum omega_result
5143 omega_constrain_variable_sign (omega_pb pb, enum omega_eqn_color color,
5144 int var, int sign)
5146 int n_vars = pb->num_vars;
5147 int e, j;
5148 int k = pb->forwarding_address[var];
5150 if (k < 0)
5152 k = -1 - k;
5154 if (sign != 0)
5156 e = pb->num_geqs++;
5157 omega_copy_eqn (&pb->geqs[e], &pb->subs[k], pb->num_vars);
5159 for (j = 0; j <= n_vars; j++)
5160 pb->geqs[e].coef[j] *= sign;
5162 pb->geqs[e].coef[0]--;
5163 pb->geqs[e].touched = 1;
5164 pb->geqs[e].color = color;
5166 else
5168 e = pb->num_eqs++;
5169 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5170 omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5171 pb->eqs[e].color = color;
5174 else if (sign != 0)
5176 e = pb->num_geqs++;
5177 omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
5178 pb->geqs[e].coef[k] = sign;
5179 pb->geqs[e].coef[0] = -1;
5180 pb->geqs[e].touched = 1;
5181 pb->geqs[e].color = color;
5183 else
5185 e = pb->num_eqs++;
5186 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5187 omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5188 pb->eqs[e].coef[k] = 1;
5189 pb->eqs[e].color = color;
5192 omega_unprotect_variable (pb, var);
5193 return omega_simplify_problem (pb);
5196 /* Add an equation "VAR = VALUE" with COLOR to PB. */
5198 void
5199 omega_constrain_variable_value (omega_pb pb, enum omega_eqn_color color,
5200 int var, int value)
5202 int e;
5203 int k = pb->forwarding_address[var];
5205 if (k < 0)
5207 k = -1 - k;
5208 e = pb->num_eqs++;
5209 gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5210 omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5211 pb->eqs[e].coef[0] -= value;
5213 else
5215 e = pb->num_eqs++;
5216 omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5217 pb->eqs[e].coef[k] = 1;
5218 pb->eqs[e].coef[0] = -value;
5221 pb->eqs[e].color = color;
5224 /* Return false when the upper and lower bounds are not coupled.
5225 Initialize the bounds LOWER_BOUND and UPPER_BOUND for the values of
5226 variable I. */
5228 bool
5229 omega_query_variable (omega_pb pb, int i, int *lower_bound, int *upper_bound)
5231 int n_vars = pb->num_vars;
5232 int e, j;
5233 bool is_simple;
5234 bool coupled = false;
5236 *lower_bound = neg_infinity;
5237 *upper_bound = pos_infinity;
5238 i = pb->forwarding_address[i];
5240 if (i < 0)
5242 i = -i - 1;
5244 for (j = 1; j <= n_vars; j++)
5245 if (pb->subs[i].coef[j] != 0)
5246 return true;
5248 *upper_bound = *lower_bound = pb->subs[i].coef[0];
5249 return false;
5252 for (e = pb->num_subs - 1; e >= 0; e--)
5253 if (pb->subs[e].coef[i] != 0)
5254 coupled = true;
5256 for (e = pb->num_eqs - 1; e >= 0; e--)
5257 if (pb->eqs[e].coef[i] != 0)
5259 is_simple = true;
5261 for (j = 1; j <= n_vars; j++)
5262 if (i != j && pb->eqs[e].coef[j] != 0)
5264 is_simple = false;
5265 coupled = true;
5266 break;
5269 if (!is_simple)
5270 continue;
5271 else
5273 *lower_bound = *upper_bound =
5274 -pb->eqs[e].coef[i] * pb->eqs[e].coef[0];
5275 return false;
5279 for (e = pb->num_geqs - 1; e >= 0; e--)
5280 if (pb->geqs[e].coef[i] != 0)
5282 if (pb->geqs[e].key == i)
5283 *lower_bound = MAX (*lower_bound, -pb->geqs[e].coef[0]);
5285 else if (pb->geqs[e].key == -i)
5286 *upper_bound = MIN (*upper_bound, pb->geqs[e].coef[0]);
5288 else
5289 coupled = true;
5292 return coupled;
5295 /* Sets the lower bound L and upper bound U for the values of variable
5296 I, and sets COULD_BE_ZERO to true if variable I might take value
5297 zero. LOWER_BOUND and UPPER_BOUND are bounds on the values of
5298 variable I. */
5300 static void
5301 query_coupled_variable (omega_pb pb, int i, int *l, int *u,
5302 bool *could_be_zero, int lower_bound, int upper_bound)
5304 int e, b1, b2;
5305 eqn eqn;
5306 int sign;
5307 int v;
5309 /* Preconditions. */
5310 gcc_assert (abs (pb->forwarding_address[i]) == 1
5311 && pb->num_vars + pb->num_subs == 2
5312 && pb->num_eqs + pb->num_subs == 1);
5314 /* Define variable I in terms of variable V. */
5315 if (pb->forwarding_address[i] == -1)
5317 eqn = &pb->subs[0];
5318 sign = 1;
5319 v = 1;
5321 else
5323 eqn = &pb->eqs[0];
5324 sign = -eqn->coef[1];
5325 v = 2;
5328 for (e = pb->num_geqs - 1; e >= 0; e--)
5329 if (pb->geqs[e].coef[v] != 0)
5331 if (pb->geqs[e].coef[v] == 1)
5332 lower_bound = MAX (lower_bound, -pb->geqs[e].coef[0]);
5334 else
5335 upper_bound = MIN (upper_bound, pb->geqs[e].coef[0]);
5338 if (lower_bound > upper_bound)
5340 *l = pos_infinity;
5341 *u = neg_infinity;
5342 *could_be_zero = 0;
5343 return;
5346 if (lower_bound == neg_infinity)
5348 if (eqn->coef[v] > 0)
5349 b1 = sign * neg_infinity;
5351 else
5352 b1 = -sign * neg_infinity;
5354 else
5355 b1 = sign * (eqn->coef[0] + eqn->coef[v] * lower_bound);
5357 if (upper_bound == pos_infinity)
5359 if (eqn->coef[v] > 0)
5360 b2 = sign * pos_infinity;
5362 else
5363 b2 = -sign * pos_infinity;
5365 else
5366 b2 = sign * (eqn->coef[0] + eqn->coef[v] * upper_bound);
5368 *l = MAX (*l, b1 <= b2 ? b1 : b2);
5369 *u = MIN (*u, b1 <= b2 ? b2 : b1);
5371 *could_be_zero = (*l <= 0 && 0 <= *u
5372 && int_mod (eqn->coef[0], abs (eqn->coef[v])) == 0);
5375 /* Return false when a lower bound L and an upper bound U for variable
5376 I in problem PB have been initialized. */
5378 bool
5379 omega_query_variable_bounds (omega_pb pb, int i, int *l, int *u)
5381 *l = neg_infinity;
5382 *u = pos_infinity;
5384 if (!omega_query_variable (pb, i, l, u)
5385 || (pb->num_vars == 1 && pb->forwarding_address[i] == 1))
5386 return false;
5388 if (abs (pb->forwarding_address[i]) == 1
5389 && pb->num_vars + pb->num_subs == 2
5390 && pb->num_eqs + pb->num_subs == 1)
5392 bool could_be_zero;
5393 query_coupled_variable (pb, i, l, u, &could_be_zero, neg_infinity,
5394 pos_infinity);
5395 return false;
5398 return true;
5401 /* For problem PB, return an integer that represents the classic data
5402 dependence direction in function of the DD_LT, DD_EQ and DD_GT bit
5403 masks that are added to the result. When DIST_KNOWN is true, DIST
5404 is set to the classic data dependence distance. LOWER_BOUND and
5405 UPPER_BOUND are bounds on the value of variable I, for example, it
5406 is possible to narrow the iteration domain with safe approximations
5407 of loop counts, and thus discard some data dependences that cannot
5408 occur. */
5411 omega_query_variable_signs (omega_pb pb, int i, int dd_lt,
5412 int dd_eq, int dd_gt, int lower_bound,
5413 int upper_bound, bool *dist_known, int *dist)
5415 int result;
5416 int l, u;
5417 bool could_be_zero;
5419 l = neg_infinity;
5420 u = pos_infinity;
5422 omega_query_variable (pb, i, &l, &u);
5423 query_coupled_variable (pb, i, &l, &u, &could_be_zero, lower_bound,
5424 upper_bound);
5425 result = 0;
5427 if (l < 0)
5428 result |= dd_gt;
5430 if (u > 0)
5431 result |= dd_lt;
5433 if (could_be_zero)
5434 result |= dd_eq;
5436 if (l == u)
5438 *dist_known = true;
5439 *dist = l;
5441 else
5442 *dist_known = false;
5444 return result;
5447 /* Initialize PB as an Omega problem with NVARS variables and NPROT
5448 safe variables. Safe variables are not eliminated during the
5449 Fourier-Motzkin elimination. Safe variables are all those
5450 variables that are placed at the beginning of the array of
5451 variables: P->var[0, ..., NPROT - 1]. */
5453 omega_pb
5454 omega_alloc_problem (int nvars, int nprot)
5456 omega_pb pb;
5458 gcc_assert (nvars <= OMEGA_MAX_VARS);
5459 omega_initialize ();
5461 /* Allocate and initialize PB. */
5462 pb = XCNEW (struct omega_pb_d);
5463 pb->var = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5464 pb->forwarding_address = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5465 pb->geqs = omega_alloc_eqns (0, OMEGA_MAX_GEQS);
5466 pb->eqs = omega_alloc_eqns (0, OMEGA_MAX_EQS);
5467 pb->subs = omega_alloc_eqns (0, OMEGA_MAX_VARS + 1);
5469 pb->hash_version = hash_version;
5470 pb->num_vars = nvars;
5471 pb->safe_vars = nprot;
5472 pb->variables_initialized = false;
5473 pb->variables_freed = false;
5474 pb->num_eqs = 0;
5475 pb->num_geqs = 0;
5476 pb->num_subs = 0;
5477 return pb;
5480 /* Keeps the state of the initialization. */
5481 static bool omega_initialized = false;
5483 /* Initialization of the Omega solver. */
5485 void
5486 omega_initialize (void)
5488 int i;
5490 if (omega_initialized)
5491 return;
5493 next_wild_card = 0;
5494 next_key = OMEGA_MAX_VARS + 1;
5495 packing = XCNEWVEC (int, OMEGA_MAX_VARS);
5496 fast_lookup = XCNEWVEC (int, MAX_KEYS * 2);
5497 fast_lookup_red = XCNEWVEC (int, MAX_KEYS * 2);
5498 hash_master = omega_alloc_eqns (0, HASH_TABLE_SIZE);
5500 for (i = 0; i < HASH_TABLE_SIZE; i++)
5501 hash_master[i].touched = -1;
5503 sprintf (wild_name[0], "1");
5504 sprintf (wild_name[1], "a");
5505 sprintf (wild_name[2], "b");
5506 sprintf (wild_name[3], "c");
5507 sprintf (wild_name[4], "d");
5508 sprintf (wild_name[5], "e");
5509 sprintf (wild_name[6], "f");
5510 sprintf (wild_name[7], "g");
5511 sprintf (wild_name[8], "h");
5512 sprintf (wild_name[9], "i");
5513 sprintf (wild_name[10], "j");
5514 sprintf (wild_name[11], "k");
5515 sprintf (wild_name[12], "l");
5516 sprintf (wild_name[13], "m");
5517 sprintf (wild_name[14], "n");
5518 sprintf (wild_name[15], "o");
5519 sprintf (wild_name[16], "p");
5520 sprintf (wild_name[17], "q");
5521 sprintf (wild_name[18], "r");
5522 sprintf (wild_name[19], "s");
5523 sprintf (wild_name[20], "t");
5524 sprintf (wild_name[40 - 1], "alpha");
5525 sprintf (wild_name[40 - 2], "beta");
5526 sprintf (wild_name[40 - 3], "gamma");
5527 sprintf (wild_name[40 - 4], "delta");
5528 sprintf (wild_name[40 - 5], "tau");
5529 sprintf (wild_name[40 - 6], "sigma");
5530 sprintf (wild_name[40 - 7], "chi");
5531 sprintf (wild_name[40 - 8], "omega");
5532 sprintf (wild_name[40 - 9], "pi");
5533 sprintf (wild_name[40 - 10], "ni");
5534 sprintf (wild_name[40 - 11], "Alpha");
5535 sprintf (wild_name[40 - 12], "Beta");
5536 sprintf (wild_name[40 - 13], "Gamma");
5537 sprintf (wild_name[40 - 14], "Delta");
5538 sprintf (wild_name[40 - 15], "Tau");
5539 sprintf (wild_name[40 - 16], "Sigma");
5540 sprintf (wild_name[40 - 17], "Chi");
5541 sprintf (wild_name[40 - 18], "Omega");
5542 sprintf (wild_name[40 - 19], "xxx");
5544 omega_initialized = true;