xref: /dflybsd-src/contrib/gcc-4.7/gcc/omega.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Source code for an implementation of the Omega test, an integer
2*e4b17023SJohn Marino    programming algorithm for dependence analysis, by William Pugh,
3*e4b17023SJohn Marino    appeared in Supercomputing '91 and CACM Aug 92.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino    This code has no license restrictions, and is considered public
6*e4b17023SJohn Marino    domain.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino    Changes copyright (C) 2005, 2006, 2007, 2008, 2009,
9*e4b17023SJohn Marino    2010 Free Software Foundation, Inc.
10*e4b17023SJohn Marino    Contributed by Sebastian Pop <sebastian.pop@inria.fr>
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino This file is part of GCC.
13*e4b17023SJohn Marino 
14*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
15*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
16*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
17*e4b17023SJohn Marino version.
18*e4b17023SJohn Marino 
19*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
20*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
21*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
22*e4b17023SJohn Marino for more details.
23*e4b17023SJohn Marino 
24*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
25*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
26*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino /* For a detailed description, see "Constraint-Based Array Dependence
29*e4b17023SJohn Marino    Analysis" William Pugh, David Wonnacott, TOPLAS'98 and David
30*e4b17023SJohn Marino    Wonnacott's thesis:
31*e4b17023SJohn Marino    ftp://ftp.cs.umd.edu/pub/omega/davewThesis/davewThesis.ps.gz
32*e4b17023SJohn Marino */
33*e4b17023SJohn Marino 
34*e4b17023SJohn Marino #include "config.h"
35*e4b17023SJohn Marino #include "system.h"
36*e4b17023SJohn Marino #include "coretypes.h"
37*e4b17023SJohn Marino #include "tree.h"
38*e4b17023SJohn Marino #include "diagnostic-core.h"
39*e4b17023SJohn Marino #include "tree-pass.h"
40*e4b17023SJohn Marino #include "omega.h"
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino /* When set to true, keep substitution variables.  When set to false,
43*e4b17023SJohn Marino    resurrect substitution variables (convert substitutions back to EQs).  */
44*e4b17023SJohn Marino static bool omega_reduce_with_subs = true;
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* When set to true, omega_simplify_problem checks for problem with no
47*e4b17023SJohn Marino    solutions, calling verify_omega_pb.  */
48*e4b17023SJohn Marino static bool omega_verify_simplification = false;
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* When set to true, only produce a single simplified result.  */
51*e4b17023SJohn Marino static bool omega_single_result = false;
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino /* Set return_single_result to 1 when omega_single_result is true.  */
54*e4b17023SJohn Marino static int return_single_result = 0;
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* Hash table for equations generated by the solver.  */
57*e4b17023SJohn Marino #define HASH_TABLE_SIZE PARAM_VALUE (PARAM_OMEGA_HASH_TABLE_SIZE)
58*e4b17023SJohn Marino #define MAX_KEYS PARAM_VALUE (PARAM_OMEGA_MAX_KEYS)
59*e4b17023SJohn Marino static eqn hash_master;
60*e4b17023SJohn Marino static int next_key;
61*e4b17023SJohn Marino static int hash_version = 0;
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino /* Set to true for making the solver enter in approximation mode.  */
64*e4b17023SJohn Marino static bool in_approximate_mode = false;
65*e4b17023SJohn Marino 
66*e4b17023SJohn Marino /* When set to zero, the solver is allowed to add new equalities to
67*e4b17023SJohn Marino    the problem to be solved.  */
68*e4b17023SJohn Marino static int conservative = 0;
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino /* Set to omega_true when the problem was successfully reduced, set to
71*e4b17023SJohn Marino    omega_unknown when the solver is unable to determine an answer.  */
72*e4b17023SJohn Marino static enum omega_result omega_found_reduction;
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino /* Set to true when the solver is allowed to add omega_red equations.  */
75*e4b17023SJohn Marino static bool create_color = false;
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino /* Set to nonzero when the problem to be solved can be reduced.  */
78*e4b17023SJohn Marino static int may_be_red = 0;
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino /* When false, there should be no substitution equations in the
81*e4b17023SJohn Marino    simplified problem.  */
82*e4b17023SJohn Marino static int please_no_equalities_in_simplified_problems = 0;
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino /* Variables names for pretty printing.  */
85*e4b17023SJohn Marino static char wild_name[200][40];
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino /* Pointer to the void problem.  */
88*e4b17023SJohn Marino static omega_pb no_problem = (omega_pb) 0;
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino /* Pointer to the problem to be solved.  */
91*e4b17023SJohn Marino static omega_pb original_problem = (omega_pb) 0;
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino /* Return the integer A divided by B.  */
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino static inline int
int_div(int a,int b)97*e4b17023SJohn Marino int_div (int a, int b)
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino   if (a > 0)
100*e4b17023SJohn Marino     return a/b;
101*e4b17023SJohn Marino   else
102*e4b17023SJohn Marino     return -((-a + b - 1)/b);
103*e4b17023SJohn Marino }
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino /* Return the integer A modulo B.  */
106*e4b17023SJohn Marino 
107*e4b17023SJohn Marino static inline int
int_mod(int a,int b)108*e4b17023SJohn Marino int_mod (int a, int b)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino   return a - b * int_div (a, b);
111*e4b17023SJohn Marino }
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino /* Test whether equation E is red.  */
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino static inline bool
omega_eqn_is_red(eqn e,int desired_res)116*e4b17023SJohn Marino omega_eqn_is_red (eqn e, int desired_res)
117*e4b17023SJohn Marino {
118*e4b17023SJohn Marino   return (desired_res == omega_simplify && e->color == omega_red);
119*e4b17023SJohn Marino }
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino /* Return a string for VARIABLE.  */
122*e4b17023SJohn Marino 
123*e4b17023SJohn Marino static inline char *
omega_var_to_str(int variable)124*e4b17023SJohn Marino omega_var_to_str (int variable)
125*e4b17023SJohn Marino {
126*e4b17023SJohn Marino   if (0 <= variable && variable <= 20)
127*e4b17023SJohn Marino     return wild_name[variable];
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino   if (-20 < variable && variable < 0)
130*e4b17023SJohn Marino     return wild_name[40 + variable];
131*e4b17023SJohn Marino 
132*e4b17023SJohn Marino   /* Collapse all the entries that would have overflowed.  */
133*e4b17023SJohn Marino   return wild_name[21];
134*e4b17023SJohn Marino }
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino /* Return a string for variable I in problem PB.  */
137*e4b17023SJohn Marino 
138*e4b17023SJohn Marino static inline char *
omega_variable_to_str(omega_pb pb,int i)139*e4b17023SJohn Marino omega_variable_to_str (omega_pb pb, int i)
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino   return omega_var_to_str (pb->var[i]);
142*e4b17023SJohn Marino }
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino /* Do nothing function: used for default initializations.  */
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino void
omega_no_procedure(omega_pb pb ATTRIBUTE_UNUSED)147*e4b17023SJohn Marino omega_no_procedure (omega_pb pb ATTRIBUTE_UNUSED)
148*e4b17023SJohn Marino {
149*e4b17023SJohn Marino }
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino void (*omega_when_reduced) (omega_pb) = omega_no_procedure;
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino /* Print to FILE from PB equation E with all its coefficients
154*e4b17023SJohn Marino    multiplied by C.  */
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino static void
omega_print_term(FILE * file,omega_pb pb,eqn e,int c)157*e4b17023SJohn Marino omega_print_term (FILE *file, omega_pb pb, eqn e, int c)
158*e4b17023SJohn Marino {
159*e4b17023SJohn Marino   int i;
160*e4b17023SJohn Marino   bool first = true;
161*e4b17023SJohn Marino   int n = pb->num_vars;
162*e4b17023SJohn Marino   int went_first = -1;
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   for (i = 1; i <= n; i++)
165*e4b17023SJohn Marino     if (c * e->coef[i] > 0)
166*e4b17023SJohn Marino       {
167*e4b17023SJohn Marino 	first = false;
168*e4b17023SJohn Marino 	went_first = i;
169*e4b17023SJohn Marino 
170*e4b17023SJohn Marino 	if (c * e->coef[i] == 1)
171*e4b17023SJohn Marino 	  fprintf (file, "%s", omega_variable_to_str (pb, i));
172*e4b17023SJohn Marino 	else
173*e4b17023SJohn Marino 	  fprintf (file, "%d * %s", c * e->coef[i],
174*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i));
175*e4b17023SJohn Marino 	break;
176*e4b17023SJohn Marino       }
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino   for (i = 1; i <= n; i++)
179*e4b17023SJohn Marino     if (i != went_first && c * e->coef[i] != 0)
180*e4b17023SJohn Marino       {
181*e4b17023SJohn Marino 	if (!first && c * e->coef[i] > 0)
182*e4b17023SJohn Marino 	  fprintf (file, " + ");
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino 	first = false;
185*e4b17023SJohn Marino 
186*e4b17023SJohn Marino 	if (c * e->coef[i] == 1)
187*e4b17023SJohn Marino 	  fprintf (file, "%s", omega_variable_to_str (pb, i));
188*e4b17023SJohn Marino 	else if (c * e->coef[i] == -1)
189*e4b17023SJohn Marino 	  fprintf (file, " - %s", omega_variable_to_str (pb, i));
190*e4b17023SJohn Marino 	else
191*e4b17023SJohn Marino 	  fprintf (file, "%d * %s", c * e->coef[i],
192*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i));
193*e4b17023SJohn Marino       }
194*e4b17023SJohn Marino 
195*e4b17023SJohn Marino   if (!first && c * e->coef[0] > 0)
196*e4b17023SJohn Marino     fprintf (file, " + ");
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino   if (first || c * e->coef[0] != 0)
199*e4b17023SJohn Marino     fprintf (file, "%d", c * e->coef[0]);
200*e4b17023SJohn Marino }
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino /* Print to FILE the equation E of problem PB.  */
203*e4b17023SJohn Marino 
204*e4b17023SJohn Marino void
omega_print_eqn(FILE * file,omega_pb pb,eqn e,bool test,int extra)205*e4b17023SJohn Marino omega_print_eqn (FILE *file, omega_pb pb, eqn e, bool test, int extra)
206*e4b17023SJohn Marino {
207*e4b17023SJohn Marino   int i;
208*e4b17023SJohn Marino   int n = pb->num_vars + extra;
209*e4b17023SJohn Marino   bool is_lt = test && e->coef[0] == -1;
210*e4b17023SJohn Marino   bool first;
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino   if (test)
213*e4b17023SJohn Marino     {
214*e4b17023SJohn Marino       if (e->touched)
215*e4b17023SJohn Marino 	fprintf (file, "!");
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino       else if (e->key != 0)
218*e4b17023SJohn Marino 	fprintf (file, "%d: ", e->key);
219*e4b17023SJohn Marino     }
220*e4b17023SJohn Marino 
221*e4b17023SJohn Marino   if (e->color == omega_red)
222*e4b17023SJohn Marino     fprintf (file, "[");
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino   first = true;
225*e4b17023SJohn Marino 
226*e4b17023SJohn Marino   for (i = is_lt ? 1 : 0; i <= n; i++)
227*e4b17023SJohn Marino     if (e->coef[i] < 0)
228*e4b17023SJohn Marino       {
229*e4b17023SJohn Marino 	if (!first)
230*e4b17023SJohn Marino 	  fprintf (file, " + ");
231*e4b17023SJohn Marino 	else
232*e4b17023SJohn Marino 	  first = false;
233*e4b17023SJohn Marino 
234*e4b17023SJohn Marino 	if (i == 0)
235*e4b17023SJohn Marino 	  fprintf (file, "%d", -e->coef[i]);
236*e4b17023SJohn Marino 	else if (e->coef[i] == -1)
237*e4b17023SJohn Marino 	  fprintf (file, "%s", omega_variable_to_str (pb, i));
238*e4b17023SJohn Marino 	else
239*e4b17023SJohn Marino 	  fprintf (file, "%d * %s", -e->coef[i],
240*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i));
241*e4b17023SJohn Marino       }
242*e4b17023SJohn Marino 
243*e4b17023SJohn Marino   if (first)
244*e4b17023SJohn Marino     {
245*e4b17023SJohn Marino       if (is_lt)
246*e4b17023SJohn Marino 	{
247*e4b17023SJohn Marino 	  fprintf (file, "1");
248*e4b17023SJohn Marino 	  is_lt = false;
249*e4b17023SJohn Marino 	}
250*e4b17023SJohn Marino       else
251*e4b17023SJohn Marino 	fprintf (file, "0");
252*e4b17023SJohn Marino     }
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino   if (test == 0)
255*e4b17023SJohn Marino     fprintf (file, " = ");
256*e4b17023SJohn Marino   else if (is_lt)
257*e4b17023SJohn Marino     fprintf (file, " < ");
258*e4b17023SJohn Marino   else
259*e4b17023SJohn Marino     fprintf (file, " <= ");
260*e4b17023SJohn Marino 
261*e4b17023SJohn Marino   first = true;
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino   for (i = 0; i <= n; i++)
264*e4b17023SJohn Marino     if (e->coef[i] > 0)
265*e4b17023SJohn Marino       {
266*e4b17023SJohn Marino 	if (!first)
267*e4b17023SJohn Marino 	  fprintf (file, " + ");
268*e4b17023SJohn Marino 	else
269*e4b17023SJohn Marino 	  first = false;
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino 	if (i == 0)
272*e4b17023SJohn Marino 	  fprintf (file, "%d", e->coef[i]);
273*e4b17023SJohn Marino 	else if (e->coef[i] == 1)
274*e4b17023SJohn Marino 	  fprintf (file, "%s", omega_variable_to_str (pb, i));
275*e4b17023SJohn Marino 	else
276*e4b17023SJohn Marino 	  fprintf (file, "%d * %s", e->coef[i],
277*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i));
278*e4b17023SJohn Marino       }
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino   if (first)
281*e4b17023SJohn Marino     fprintf (file, "0");
282*e4b17023SJohn Marino 
283*e4b17023SJohn Marino   if (e->color == omega_red)
284*e4b17023SJohn Marino     fprintf (file, "]");
285*e4b17023SJohn Marino }
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino /* Print to FILE all the variables of problem PB.  */
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino static void
omega_print_vars(FILE * file,omega_pb pb)290*e4b17023SJohn Marino omega_print_vars (FILE *file, omega_pb pb)
291*e4b17023SJohn Marino {
292*e4b17023SJohn Marino   int i;
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino   fprintf (file, "variables = ");
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino   if (pb->safe_vars > 0)
297*e4b17023SJohn Marino     fprintf (file, "protected (");
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino   for (i = 1; i <= pb->num_vars; i++)
300*e4b17023SJohn Marino     {
301*e4b17023SJohn Marino       fprintf (file, "%s", omega_variable_to_str (pb, i));
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino       if (i == pb->safe_vars)
304*e4b17023SJohn Marino 	fprintf (file, ")");
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino       if (i < pb->num_vars)
307*e4b17023SJohn Marino 	fprintf (file, ", ");
308*e4b17023SJohn Marino     }
309*e4b17023SJohn Marino 
310*e4b17023SJohn Marino   fprintf (file, "\n");
311*e4b17023SJohn Marino }
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino /* Debug problem PB.  */
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_omega_problem(omega_pb pb)316*e4b17023SJohn Marino debug_omega_problem (omega_pb pb)
317*e4b17023SJohn Marino {
318*e4b17023SJohn Marino   omega_print_problem (stderr, pb);
319*e4b17023SJohn Marino }
320*e4b17023SJohn Marino 
321*e4b17023SJohn Marino /* Print to FILE problem PB.  */
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino void
omega_print_problem(FILE * file,omega_pb pb)324*e4b17023SJohn Marino omega_print_problem (FILE *file, omega_pb pb)
325*e4b17023SJohn Marino {
326*e4b17023SJohn Marino   int e;
327*e4b17023SJohn Marino 
328*e4b17023SJohn Marino   if (!pb->variables_initialized)
329*e4b17023SJohn Marino     omega_initialize_variables (pb);
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino   omega_print_vars (file, pb);
332*e4b17023SJohn Marino 
333*e4b17023SJohn Marino   for (e = 0; e < pb->num_eqs; e++)
334*e4b17023SJohn Marino     {
335*e4b17023SJohn Marino       omega_print_eq (file, pb, &pb->eqs[e]);
336*e4b17023SJohn Marino       fprintf (file, "\n");
337*e4b17023SJohn Marino     }
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   fprintf (file, "Done with EQ\n");
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
342*e4b17023SJohn Marino     {
343*e4b17023SJohn Marino       omega_print_geq (file, pb, &pb->geqs[e]);
344*e4b17023SJohn Marino       fprintf (file, "\n");
345*e4b17023SJohn Marino     }
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino   fprintf (file, "Done with GEQ\n");
348*e4b17023SJohn Marino 
349*e4b17023SJohn Marino   for (e = 0; e < pb->num_subs; e++)
350*e4b17023SJohn Marino     {
351*e4b17023SJohn Marino       eqn eq = &pb->subs[e];
352*e4b17023SJohn Marino 
353*e4b17023SJohn Marino       if (eq->color == omega_red)
354*e4b17023SJohn Marino 	fprintf (file, "[");
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino       if (eq->key > 0)
357*e4b17023SJohn Marino 	fprintf (file, "%s := ", omega_var_to_str (eq->key));
358*e4b17023SJohn Marino       else
359*e4b17023SJohn Marino 	fprintf (file, "#%d := ", eq->key);
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino       omega_print_term (file, pb, eq, 1);
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino       if (eq->color == omega_red)
364*e4b17023SJohn Marino 	fprintf (file, "]");
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino       fprintf (file, "\n");
367*e4b17023SJohn Marino     }
368*e4b17023SJohn Marino }
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino /* Return the number of equations in PB tagged omega_red.  */
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino int
omega_count_red_equations(omega_pb pb)373*e4b17023SJohn Marino omega_count_red_equations (omega_pb pb)
374*e4b17023SJohn Marino {
375*e4b17023SJohn Marino   int e, i;
376*e4b17023SJohn Marino   int result = 0;
377*e4b17023SJohn Marino 
378*e4b17023SJohn Marino   for (e = 0; e < pb->num_eqs; e++)
379*e4b17023SJohn Marino     if (pb->eqs[e].color == omega_red)
380*e4b17023SJohn Marino       {
381*e4b17023SJohn Marino 	for (i = pb->num_vars; i > 0; i--)
382*e4b17023SJohn Marino 	  if (pb->geqs[e].coef[i])
383*e4b17023SJohn Marino 	    break;
384*e4b17023SJohn Marino 
385*e4b17023SJohn Marino 	if (i == 0 && pb->geqs[e].coef[0] == 1)
386*e4b17023SJohn Marino 	  return 0;
387*e4b17023SJohn Marino 	else
388*e4b17023SJohn Marino 	  result += 2;
389*e4b17023SJohn Marino       }
390*e4b17023SJohn Marino 
391*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
392*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
393*e4b17023SJohn Marino       result += 1;
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino   for (e = 0; e < pb->num_subs; e++)
396*e4b17023SJohn Marino     if (pb->subs[e].color == omega_red)
397*e4b17023SJohn Marino       result += 2;
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino   return result;
400*e4b17023SJohn Marino }
401*e4b17023SJohn Marino 
402*e4b17023SJohn Marino /* Print to FILE all the equations in PB that are tagged omega_red.  */
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino void
omega_print_red_equations(FILE * file,omega_pb pb)405*e4b17023SJohn Marino omega_print_red_equations (FILE *file, omega_pb pb)
406*e4b17023SJohn Marino {
407*e4b17023SJohn Marino   int e;
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino   if (!pb->variables_initialized)
410*e4b17023SJohn Marino     omega_initialize_variables (pb);
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino   omega_print_vars (file, pb);
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino   for (e = 0; e < pb->num_eqs; e++)
415*e4b17023SJohn Marino     if (pb->eqs[e].color == omega_red)
416*e4b17023SJohn Marino       {
417*e4b17023SJohn Marino 	omega_print_eq (file, pb, &pb->eqs[e]);
418*e4b17023SJohn Marino 	fprintf (file, "\n");
419*e4b17023SJohn Marino       }
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
422*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
423*e4b17023SJohn Marino       {
424*e4b17023SJohn Marino 	omega_print_geq (file, pb, &pb->geqs[e]);
425*e4b17023SJohn Marino 	fprintf (file, "\n");
426*e4b17023SJohn Marino       }
427*e4b17023SJohn Marino 
428*e4b17023SJohn Marino   for (e = 0; e < pb->num_subs; e++)
429*e4b17023SJohn Marino     if (pb->subs[e].color == omega_red)
430*e4b17023SJohn Marino       {
431*e4b17023SJohn Marino 	eqn eq = &pb->subs[e];
432*e4b17023SJohn Marino 	fprintf (file, "[");
433*e4b17023SJohn Marino 
434*e4b17023SJohn Marino 	if (eq->key > 0)
435*e4b17023SJohn Marino 	  fprintf (file, "%s := ", omega_var_to_str (eq->key));
436*e4b17023SJohn Marino 	else
437*e4b17023SJohn Marino 	  fprintf (file, "#%d := ", eq->key);
438*e4b17023SJohn Marino 
439*e4b17023SJohn Marino 	omega_print_term (file, pb, eq, 1);
440*e4b17023SJohn Marino 	fprintf (file, "]\n");
441*e4b17023SJohn Marino       }
442*e4b17023SJohn Marino }
443*e4b17023SJohn Marino 
444*e4b17023SJohn Marino /* Pretty print PB to FILE.  */
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino void
omega_pretty_print_problem(FILE * file,omega_pb pb)447*e4b17023SJohn Marino omega_pretty_print_problem (FILE *file, omega_pb pb)
448*e4b17023SJohn Marino {
449*e4b17023SJohn Marino   int e, v, v1, v2, v3, t;
450*e4b17023SJohn Marino   bool *live = XNEWVEC (bool, OMEGA_MAX_GEQS);
451*e4b17023SJohn Marino   int stuffPrinted = 0;
452*e4b17023SJohn Marino   bool change;
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino   typedef enum {
455*e4b17023SJohn Marino     none, le, lt
456*e4b17023SJohn Marino   } partial_order_type;
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino   partial_order_type **po = XNEWVEC (partial_order_type *,
459*e4b17023SJohn Marino 				     OMEGA_MAX_VARS * OMEGA_MAX_VARS);
460*e4b17023SJohn Marino   int **po_eq = XNEWVEC (int *, OMEGA_MAX_VARS * OMEGA_MAX_VARS);
461*e4b17023SJohn Marino   int *last_links = XNEWVEC (int, OMEGA_MAX_VARS);
462*e4b17023SJohn Marino   int *first_links = XNEWVEC (int, OMEGA_MAX_VARS);
463*e4b17023SJohn Marino   int *chain_length = XNEWVEC (int, OMEGA_MAX_VARS);
464*e4b17023SJohn Marino   int *chain = XNEWVEC (int, OMEGA_MAX_VARS);
465*e4b17023SJohn Marino   int i, m;
466*e4b17023SJohn Marino   bool multiprint;
467*e4b17023SJohn Marino 
468*e4b17023SJohn Marino   if (!pb->variables_initialized)
469*e4b17023SJohn Marino     omega_initialize_variables (pb);
470*e4b17023SJohn Marino 
471*e4b17023SJohn Marino   if (pb->num_vars > 0)
472*e4b17023SJohn Marino     {
473*e4b17023SJohn Marino       omega_eliminate_redundant (pb, false);
474*e4b17023SJohn Marino 
475*e4b17023SJohn Marino       for (e = 0; e < pb->num_eqs; e++)
476*e4b17023SJohn Marino 	{
477*e4b17023SJohn Marino 	  if (stuffPrinted)
478*e4b17023SJohn Marino 	    fprintf (file, "; ");
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino 	  stuffPrinted = 1;
481*e4b17023SJohn Marino 	  omega_print_eq (file, pb, &pb->eqs[e]);
482*e4b17023SJohn Marino 	}
483*e4b17023SJohn Marino 
484*e4b17023SJohn Marino       for (e = 0; e < pb->num_geqs; e++)
485*e4b17023SJohn Marino 	live[e] = true;
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino       while (1)
488*e4b17023SJohn Marino 	{
489*e4b17023SJohn Marino 	  for (v = 1; v <= pb->num_vars; v++)
490*e4b17023SJohn Marino 	    {
491*e4b17023SJohn Marino 	      last_links[v] = first_links[v] = 0;
492*e4b17023SJohn Marino 	      chain_length[v] = 0;
493*e4b17023SJohn Marino 
494*e4b17023SJohn Marino 	      for (v2 = 1; v2 <= pb->num_vars; v2++)
495*e4b17023SJohn Marino 		po[v][v2] = none;
496*e4b17023SJohn Marino 	    }
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino 	  for (e = 0; e < pb->num_geqs; e++)
499*e4b17023SJohn Marino 	    if (live[e])
500*e4b17023SJohn Marino 	      {
501*e4b17023SJohn Marino 		for (v = 1; v <= pb->num_vars; v++)
502*e4b17023SJohn Marino 		  if (pb->geqs[e].coef[v] == 1)
503*e4b17023SJohn Marino 		    first_links[v]++;
504*e4b17023SJohn Marino 		  else if (pb->geqs[e].coef[v] == -1)
505*e4b17023SJohn Marino 		    last_links[v]++;
506*e4b17023SJohn Marino 
507*e4b17023SJohn Marino 		v1 = pb->num_vars;
508*e4b17023SJohn Marino 
509*e4b17023SJohn Marino 		while (v1 > 0 && pb->geqs[e].coef[v1] == 0)
510*e4b17023SJohn Marino 		  v1--;
511*e4b17023SJohn Marino 
512*e4b17023SJohn Marino 		v2 = v1 - 1;
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino 		while (v2 > 0 && pb->geqs[e].coef[v2] == 0)
515*e4b17023SJohn Marino 		  v2--;
516*e4b17023SJohn Marino 
517*e4b17023SJohn Marino 		v3 = v2 - 1;
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino 		while (v3 > 0 && pb->geqs[e].coef[v3] == 0)
520*e4b17023SJohn Marino 		  v3--;
521*e4b17023SJohn Marino 
522*e4b17023SJohn Marino 		if (pb->geqs[e].coef[0] > 0 || pb->geqs[e].coef[0] < -1
523*e4b17023SJohn Marino 		    || v2 <= 0 || v3 > 0
524*e4b17023SJohn Marino 		    || pb->geqs[e].coef[v1] * pb->geqs[e].coef[v2] != -1)
525*e4b17023SJohn Marino 		  {
526*e4b17023SJohn Marino 		    /* Not a partial order relation.  */
527*e4b17023SJohn Marino 		  }
528*e4b17023SJohn Marino 		else
529*e4b17023SJohn Marino 		  {
530*e4b17023SJohn Marino 		    if (pb->geqs[e].coef[v1] == 1)
531*e4b17023SJohn Marino 		      {
532*e4b17023SJohn Marino 			v3 = v2;
533*e4b17023SJohn Marino 			v2 = v1;
534*e4b17023SJohn Marino 			v1 = v3;
535*e4b17023SJohn Marino 		      }
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino 		    /* Relation is v1 <= v2 or v1 < v2.  */
538*e4b17023SJohn Marino 		    po[v1][v2] = ((pb->geqs[e].coef[0] == 0) ? le : lt);
539*e4b17023SJohn Marino 		    po_eq[v1][v2] = e;
540*e4b17023SJohn Marino 		  }
541*e4b17023SJohn Marino 	      }
542*e4b17023SJohn Marino 	  for (v = 1; v <= pb->num_vars; v++)
543*e4b17023SJohn Marino 	    chain_length[v] = last_links[v];
544*e4b17023SJohn Marino 
545*e4b17023SJohn Marino 	  /* Just in case pb->num_vars <= 0.  */
546*e4b17023SJohn Marino 	  change = false;
547*e4b17023SJohn Marino 	  for (t = 0; t < pb->num_vars; t++)
548*e4b17023SJohn Marino 	    {
549*e4b17023SJohn Marino 	      change = false;
550*e4b17023SJohn Marino 
551*e4b17023SJohn Marino 	      for (v1 = 1; v1 <= pb->num_vars; v1++)
552*e4b17023SJohn Marino 		for (v2 = 1; v2 <= pb->num_vars; v2++)
553*e4b17023SJohn Marino 		  if (po[v1][v2] != none &&
554*e4b17023SJohn Marino 		      chain_length[v1] <= chain_length[v2])
555*e4b17023SJohn Marino 		    {
556*e4b17023SJohn Marino 		      chain_length[v1] = chain_length[v2] + 1;
557*e4b17023SJohn Marino 		      change = true;
558*e4b17023SJohn Marino 		    }
559*e4b17023SJohn Marino 	    }
560*e4b17023SJohn Marino 
561*e4b17023SJohn Marino 	  /* Caught in cycle.  */
562*e4b17023SJohn Marino 	  gcc_assert (!change);
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino 	  for (v1 = 1; v1 <= pb->num_vars; v1++)
565*e4b17023SJohn Marino 	    if (chain_length[v1] == 0)
566*e4b17023SJohn Marino 	      first_links[v1] = 0;
567*e4b17023SJohn Marino 
568*e4b17023SJohn Marino 	  v = 1;
569*e4b17023SJohn Marino 
570*e4b17023SJohn Marino 	  for (v1 = 2; v1 <= pb->num_vars; v1++)
571*e4b17023SJohn Marino 	    if (chain_length[v1] + first_links[v1] >
572*e4b17023SJohn Marino 		chain_length[v] + first_links[v])
573*e4b17023SJohn Marino 	      v = v1;
574*e4b17023SJohn Marino 
575*e4b17023SJohn Marino 	  if (chain_length[v] + first_links[v] == 0)
576*e4b17023SJohn Marino 	    break;
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino 	  if (stuffPrinted)
579*e4b17023SJohn Marino 	    fprintf (file, "; ");
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino 	  stuffPrinted = 1;
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino 	  /* Chain starts at v. */
584*e4b17023SJohn Marino 	  {
585*e4b17023SJohn Marino 	    int tmp;
586*e4b17023SJohn Marino 	    bool first = true;
587*e4b17023SJohn Marino 
588*e4b17023SJohn Marino 	    for (e = 0; e < pb->num_geqs; e++)
589*e4b17023SJohn Marino 	      if (live[e] && pb->geqs[e].coef[v] == 1)
590*e4b17023SJohn Marino 		{
591*e4b17023SJohn Marino 		  if (!first)
592*e4b17023SJohn Marino 		    fprintf (file, ", ");
593*e4b17023SJohn Marino 
594*e4b17023SJohn Marino 		  tmp = pb->geqs[e].coef[v];
595*e4b17023SJohn Marino 		  pb->geqs[e].coef[v] = 0;
596*e4b17023SJohn Marino 		  omega_print_term (file, pb, &pb->geqs[e], -1);
597*e4b17023SJohn Marino 		  pb->geqs[e].coef[v] = tmp;
598*e4b17023SJohn Marino 		  live[e] = false;
599*e4b17023SJohn Marino 		  first = false;
600*e4b17023SJohn Marino 		}
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino 	    if (!first)
603*e4b17023SJohn Marino 	      fprintf (file, " <= ");
604*e4b17023SJohn Marino 	  }
605*e4b17023SJohn Marino 
606*e4b17023SJohn Marino 	  /* Find chain.  */
607*e4b17023SJohn Marino 	  chain[0] = v;
608*e4b17023SJohn Marino 	  m = 1;
609*e4b17023SJohn Marino 	  while (1)
610*e4b17023SJohn Marino 	    {
611*e4b17023SJohn Marino 	      /* Print chain.  */
612*e4b17023SJohn Marino 	      for (v2 = 1; v2 <= pb->num_vars; v2++)
613*e4b17023SJohn Marino 		if (po[v][v2] && chain_length[v] == 1 + chain_length[v2])
614*e4b17023SJohn Marino 		  break;
615*e4b17023SJohn Marino 
616*e4b17023SJohn Marino 	      if (v2 > pb->num_vars)
617*e4b17023SJohn Marino 		break;
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino 	      chain[m++] = v2;
620*e4b17023SJohn Marino 	      v = v2;
621*e4b17023SJohn Marino 	    }
622*e4b17023SJohn Marino 
623*e4b17023SJohn Marino 	  fprintf (file, "%s", omega_variable_to_str (pb, chain[0]));
624*e4b17023SJohn Marino 
625*e4b17023SJohn Marino 	  for (multiprint = false, i = 1; i < m; i++)
626*e4b17023SJohn Marino 	    {
627*e4b17023SJohn Marino 	      v = chain[i - 1];
628*e4b17023SJohn Marino 	      v2 = chain[i];
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino 	      if (po[v][v2] == le)
631*e4b17023SJohn Marino 		fprintf (file, " <= ");
632*e4b17023SJohn Marino 	      else
633*e4b17023SJohn Marino 		fprintf (file, " < ");
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino 	      fprintf (file, "%s", omega_variable_to_str (pb, v2));
636*e4b17023SJohn Marino 	      live[po_eq[v][v2]] = false;
637*e4b17023SJohn Marino 
638*e4b17023SJohn Marino 	      if (!multiprint && i < m - 1)
639*e4b17023SJohn Marino 		for (v3 = 1; v3 <= pb->num_vars; v3++)
640*e4b17023SJohn Marino 		  {
641*e4b17023SJohn Marino 		    if (v == v3 || v2 == v3
642*e4b17023SJohn Marino 			|| po[v][v2] != po[v][v3]
643*e4b17023SJohn Marino 			|| po[v2][chain[i + 1]] != po[v3][chain[i + 1]])
644*e4b17023SJohn Marino 		      continue;
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino 		    fprintf (file, ",%s", omega_variable_to_str (pb, v3));
647*e4b17023SJohn Marino 		    live[po_eq[v][v3]] = false;
648*e4b17023SJohn Marino 		    live[po_eq[v3][chain[i + 1]]] = false;
649*e4b17023SJohn Marino 		    multiprint = true;
650*e4b17023SJohn Marino 		  }
651*e4b17023SJohn Marino 	      else
652*e4b17023SJohn Marino 		multiprint = false;
653*e4b17023SJohn Marino 	    }
654*e4b17023SJohn Marino 
655*e4b17023SJohn Marino 	  v = chain[m - 1];
656*e4b17023SJohn Marino 	  /* Print last_links.  */
657*e4b17023SJohn Marino 	  {
658*e4b17023SJohn Marino 	    int tmp;
659*e4b17023SJohn Marino 	    bool first = true;
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino 	    for (e = 0; e < pb->num_geqs; e++)
662*e4b17023SJohn Marino 	      if (live[e] && pb->geqs[e].coef[v] == -1)
663*e4b17023SJohn Marino 		{
664*e4b17023SJohn Marino 		  if (!first)
665*e4b17023SJohn Marino 		    fprintf (file, ", ");
666*e4b17023SJohn Marino 		  else
667*e4b17023SJohn Marino 		    fprintf (file, " <= ");
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino 		  tmp = pb->geqs[e].coef[v];
670*e4b17023SJohn Marino 		  pb->geqs[e].coef[v] = 0;
671*e4b17023SJohn Marino 		  omega_print_term (file, pb, &pb->geqs[e], 1);
672*e4b17023SJohn Marino 		  pb->geqs[e].coef[v] = tmp;
673*e4b17023SJohn Marino 		  live[e] = false;
674*e4b17023SJohn Marino 		  first = false;
675*e4b17023SJohn Marino 		}
676*e4b17023SJohn Marino 	  }
677*e4b17023SJohn Marino 	}
678*e4b17023SJohn Marino 
679*e4b17023SJohn Marino       for (e = 0; e < pb->num_geqs; e++)
680*e4b17023SJohn Marino 	if (live[e])
681*e4b17023SJohn Marino 	  {
682*e4b17023SJohn Marino 	    if (stuffPrinted)
683*e4b17023SJohn Marino 	      fprintf (file, "; ");
684*e4b17023SJohn Marino 	    stuffPrinted = 1;
685*e4b17023SJohn Marino 	    omega_print_geq (file, pb, &pb->geqs[e]);
686*e4b17023SJohn Marino 	  }
687*e4b17023SJohn Marino 
688*e4b17023SJohn Marino       for (e = 0; e < pb->num_subs; e++)
689*e4b17023SJohn Marino 	{
690*e4b17023SJohn Marino 	  eqn eq = &pb->subs[e];
691*e4b17023SJohn Marino 
692*e4b17023SJohn Marino 	  if (stuffPrinted)
693*e4b17023SJohn Marino 	    fprintf (file, "; ");
694*e4b17023SJohn Marino 
695*e4b17023SJohn Marino 	  stuffPrinted = 1;
696*e4b17023SJohn Marino 
697*e4b17023SJohn Marino 	  if (eq->key > 0)
698*e4b17023SJohn Marino 	    fprintf (file, "%s := ", omega_var_to_str (eq->key));
699*e4b17023SJohn Marino 	  else
700*e4b17023SJohn Marino 	    fprintf (file, "#%d := ", eq->key);
701*e4b17023SJohn Marino 
702*e4b17023SJohn Marino 	  omega_print_term (file, pb, eq, 1);
703*e4b17023SJohn Marino 	}
704*e4b17023SJohn Marino     }
705*e4b17023SJohn Marino 
706*e4b17023SJohn Marino   free (live);
707*e4b17023SJohn Marino   free (po);
708*e4b17023SJohn Marino   free (po_eq);
709*e4b17023SJohn Marino   free (last_links);
710*e4b17023SJohn Marino   free (first_links);
711*e4b17023SJohn Marino   free (chain_length);
712*e4b17023SJohn Marino   free (chain);
713*e4b17023SJohn Marino }
714*e4b17023SJohn Marino 
715*e4b17023SJohn Marino /* Assign to variable I in PB the next wildcard name.  The name of a
716*e4b17023SJohn Marino    wildcard is a negative number.  */
717*e4b17023SJohn Marino static int next_wild_card = 0;
718*e4b17023SJohn Marino 
719*e4b17023SJohn Marino static void
omega_name_wild_card(omega_pb pb,int i)720*e4b17023SJohn Marino omega_name_wild_card (omega_pb pb, int i)
721*e4b17023SJohn Marino {
722*e4b17023SJohn Marino   --next_wild_card;
723*e4b17023SJohn Marino   if (next_wild_card < -PARAM_VALUE (PARAM_OMEGA_MAX_WILD_CARDS))
724*e4b17023SJohn Marino     next_wild_card = -1;
725*e4b17023SJohn Marino   pb->var[i] = next_wild_card;
726*e4b17023SJohn Marino }
727*e4b17023SJohn Marino 
728*e4b17023SJohn Marino /* Return the index of the last protected (or safe) variable in PB,
729*e4b17023SJohn Marino    after having added a new wildcard variable.  */
730*e4b17023SJohn Marino 
731*e4b17023SJohn Marino static int
omega_add_new_wild_card(omega_pb pb)732*e4b17023SJohn Marino omega_add_new_wild_card (omega_pb pb)
733*e4b17023SJohn Marino {
734*e4b17023SJohn Marino   int e;
735*e4b17023SJohn Marino   int i = ++pb->safe_vars;
736*e4b17023SJohn Marino   pb->num_vars++;
737*e4b17023SJohn Marino 
738*e4b17023SJohn Marino   /* Make a free place in the protected (safe) variables, by moving
739*e4b17023SJohn Marino      the non protected variable pointed by "I" at the end, ie. at
740*e4b17023SJohn Marino      offset pb->num_vars.  */
741*e4b17023SJohn Marino   if (pb->num_vars != i)
742*e4b17023SJohn Marino     {
743*e4b17023SJohn Marino       /* Move "I" for all the inequalities.  */
744*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
745*e4b17023SJohn Marino 	{
746*e4b17023SJohn Marino 	  if (pb->geqs[e].coef[i])
747*e4b17023SJohn Marino 	    pb->geqs[e].touched = 1;
748*e4b17023SJohn Marino 
749*e4b17023SJohn Marino 	  pb->geqs[e].coef[pb->num_vars] = pb->geqs[e].coef[i];
750*e4b17023SJohn Marino 	}
751*e4b17023SJohn Marino 
752*e4b17023SJohn Marino       /* Move "I" for all the equalities.  */
753*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
754*e4b17023SJohn Marino 	pb->eqs[e].coef[pb->num_vars] = pb->eqs[e].coef[i];
755*e4b17023SJohn Marino 
756*e4b17023SJohn Marino       /* Move "I" for all the substitutions.  */
757*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
758*e4b17023SJohn Marino 	pb->subs[e].coef[pb->num_vars] = pb->subs[e].coef[i];
759*e4b17023SJohn Marino 
760*e4b17023SJohn Marino       /* Move the identifier.  */
761*e4b17023SJohn Marino       pb->var[pb->num_vars] = pb->var[i];
762*e4b17023SJohn Marino     }
763*e4b17023SJohn Marino 
764*e4b17023SJohn Marino   /* Initialize at zero all the coefficients  */
765*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
766*e4b17023SJohn Marino     pb->geqs[e].coef[i] = 0;
767*e4b17023SJohn Marino 
768*e4b17023SJohn Marino   for (e = pb->num_eqs - 1; e >= 0; e--)
769*e4b17023SJohn Marino     pb->eqs[e].coef[i] = 0;
770*e4b17023SJohn Marino 
771*e4b17023SJohn Marino   for (e = pb->num_subs - 1; e >= 0; e--)
772*e4b17023SJohn Marino     pb->subs[e].coef[i] = 0;
773*e4b17023SJohn Marino 
774*e4b17023SJohn Marino   /* And give it a name.  */
775*e4b17023SJohn Marino   omega_name_wild_card (pb, i);
776*e4b17023SJohn Marino   return i;
777*e4b17023SJohn Marino }
778*e4b17023SJohn Marino 
779*e4b17023SJohn Marino /* Delete inequality E from problem PB that has N_VARS variables.  */
780*e4b17023SJohn Marino 
781*e4b17023SJohn Marino static void
omega_delete_geq(omega_pb pb,int e,int n_vars)782*e4b17023SJohn Marino omega_delete_geq (omega_pb pb, int e, int n_vars)
783*e4b17023SJohn Marino {
784*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
785*e4b17023SJohn Marino     {
786*e4b17023SJohn Marino       fprintf (dump_file, "Deleting %d (last:%d): ", e, pb->num_geqs - 1);
787*e4b17023SJohn Marino       omega_print_geq (dump_file, pb, &pb->geqs[e]);
788*e4b17023SJohn Marino       fprintf (dump_file, "\n");
789*e4b17023SJohn Marino     }
790*e4b17023SJohn Marino 
791*e4b17023SJohn Marino   if (e < pb->num_geqs - 1)
792*e4b17023SJohn Marino     omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
793*e4b17023SJohn Marino 
794*e4b17023SJohn Marino   pb->num_geqs--;
795*e4b17023SJohn Marino }
796*e4b17023SJohn Marino 
797*e4b17023SJohn Marino /* Delete extra inequality E from problem PB that has N_VARS
798*e4b17023SJohn Marino    variables.  */
799*e4b17023SJohn Marino 
800*e4b17023SJohn Marino static void
omega_delete_geq_extra(omega_pb pb,int e,int n_vars)801*e4b17023SJohn Marino omega_delete_geq_extra (omega_pb pb, int e, int n_vars)
802*e4b17023SJohn Marino {
803*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
804*e4b17023SJohn Marino     {
805*e4b17023SJohn Marino       fprintf (dump_file, "Deleting %d: ",e);
806*e4b17023SJohn Marino       omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
807*e4b17023SJohn Marino       fprintf (dump_file, "\n");
808*e4b17023SJohn Marino     }
809*e4b17023SJohn Marino 
810*e4b17023SJohn Marino   if (e < pb->num_geqs - 1)
811*e4b17023SJohn Marino     omega_copy_eqn (&pb->geqs[e], &pb->geqs[pb->num_geqs - 1], n_vars);
812*e4b17023SJohn Marino 
813*e4b17023SJohn Marino   pb->num_geqs--;
814*e4b17023SJohn Marino }
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino 
817*e4b17023SJohn Marino /* Remove variable I from problem PB.  */
818*e4b17023SJohn Marino 
819*e4b17023SJohn Marino static void
omega_delete_variable(omega_pb pb,int i)820*e4b17023SJohn Marino omega_delete_variable (omega_pb pb, int i)
821*e4b17023SJohn Marino {
822*e4b17023SJohn Marino   int n_vars = pb->num_vars;
823*e4b17023SJohn Marino   int e;
824*e4b17023SJohn Marino 
825*e4b17023SJohn Marino   if (omega_safe_var_p (pb, i))
826*e4b17023SJohn Marino     {
827*e4b17023SJohn Marino       int j = pb->safe_vars;
828*e4b17023SJohn Marino 
829*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
830*e4b17023SJohn Marino 	{
831*e4b17023SJohn Marino 	  pb->geqs[e].touched = 1;
832*e4b17023SJohn Marino 	  pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
833*e4b17023SJohn Marino 	  pb->geqs[e].coef[j] = pb->geqs[e].coef[n_vars];
834*e4b17023SJohn Marino 	}
835*e4b17023SJohn Marino 
836*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
837*e4b17023SJohn Marino 	{
838*e4b17023SJohn Marino 	  pb->eqs[e].coef[i] = pb->eqs[e].coef[j];
839*e4b17023SJohn Marino 	  pb->eqs[e].coef[j] = pb->eqs[e].coef[n_vars];
840*e4b17023SJohn Marino 	}
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
843*e4b17023SJohn Marino 	{
844*e4b17023SJohn Marino 	  pb->subs[e].coef[i] = pb->subs[e].coef[j];
845*e4b17023SJohn Marino 	  pb->subs[e].coef[j] = pb->subs[e].coef[n_vars];
846*e4b17023SJohn Marino 	}
847*e4b17023SJohn Marino 
848*e4b17023SJohn Marino       pb->var[i] = pb->var[j];
849*e4b17023SJohn Marino       pb->var[j] = pb->var[n_vars];
850*e4b17023SJohn Marino     }
851*e4b17023SJohn Marino   else if (i < n_vars)
852*e4b17023SJohn Marino     {
853*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
854*e4b17023SJohn Marino 	if (pb->geqs[e].coef[n_vars])
855*e4b17023SJohn Marino 	  {
856*e4b17023SJohn Marino 	    pb->geqs[e].coef[i] = pb->geqs[e].coef[n_vars];
857*e4b17023SJohn Marino 	    pb->geqs[e].touched = 1;
858*e4b17023SJohn Marino 	  }
859*e4b17023SJohn Marino 
860*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
861*e4b17023SJohn Marino 	pb->eqs[e].coef[i] = pb->eqs[e].coef[n_vars];
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
864*e4b17023SJohn Marino 	pb->subs[e].coef[i] = pb->subs[e].coef[n_vars];
865*e4b17023SJohn Marino 
866*e4b17023SJohn Marino       pb->var[i] = pb->var[n_vars];
867*e4b17023SJohn Marino     }
868*e4b17023SJohn Marino 
869*e4b17023SJohn Marino   if (omega_safe_var_p (pb, i))
870*e4b17023SJohn Marino     pb->safe_vars--;
871*e4b17023SJohn Marino 
872*e4b17023SJohn Marino   pb->num_vars--;
873*e4b17023SJohn Marino }
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino /* Because the coefficients of an equation are sparse, PACKING records
876*e4b17023SJohn Marino    indices for non null coefficients.  */
877*e4b17023SJohn Marino static int *packing;
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino /* Set up the coefficients of PACKING, following the coefficients of
880*e4b17023SJohn Marino    equation EQN that has NUM_VARS variables.  */
881*e4b17023SJohn Marino 
882*e4b17023SJohn Marino static inline int
setup_packing(eqn eqn,int num_vars)883*e4b17023SJohn Marino setup_packing (eqn eqn, int num_vars)
884*e4b17023SJohn Marino {
885*e4b17023SJohn Marino   int k;
886*e4b17023SJohn Marino   int n = 0;
887*e4b17023SJohn Marino 
888*e4b17023SJohn Marino   for (k = num_vars; k >= 0; k--)
889*e4b17023SJohn Marino     if (eqn->coef[k])
890*e4b17023SJohn Marino       packing[n++] = k;
891*e4b17023SJohn Marino 
892*e4b17023SJohn Marino   return n;
893*e4b17023SJohn Marino }
894*e4b17023SJohn Marino 
895*e4b17023SJohn Marino /* Computes a linear combination of EQ and SUB at VAR with coefficient
896*e4b17023SJohn Marino    C, such that EQ->coef[VAR] is set to 0.  TOP_VAR is the number of
897*e4b17023SJohn Marino    non null indices of SUB stored in PACKING.  */
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino static inline void
omega_substitute_red_1(eqn eq,eqn sub,int var,int c,bool * found_black,int top_var)900*e4b17023SJohn Marino omega_substitute_red_1 (eqn eq, eqn sub, int var, int c, bool *found_black,
901*e4b17023SJohn Marino 			int top_var)
902*e4b17023SJohn Marino {
903*e4b17023SJohn Marino   if (eq->coef[var] != 0)
904*e4b17023SJohn Marino     {
905*e4b17023SJohn Marino       if (eq->color == omega_black)
906*e4b17023SJohn Marino 	*found_black = true;
907*e4b17023SJohn Marino       else
908*e4b17023SJohn Marino 	{
909*e4b17023SJohn Marino 	  int j, k = eq->coef[var];
910*e4b17023SJohn Marino 
911*e4b17023SJohn Marino 	  eq->coef[var] = 0;
912*e4b17023SJohn Marino 
913*e4b17023SJohn Marino 	  for (j = top_var; j >= 0; j--)
914*e4b17023SJohn Marino 	    eq->coef[packing[j]] -= sub->coef[packing[j]] * k * c;
915*e4b17023SJohn Marino 	}
916*e4b17023SJohn Marino     }
917*e4b17023SJohn Marino }
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino /* Substitute in PB variable VAR with "C * SUB".  */
920*e4b17023SJohn Marino 
921*e4b17023SJohn Marino static void
omega_substitute_red(omega_pb pb,eqn sub,int var,int c,bool * found_black)922*e4b17023SJohn Marino omega_substitute_red (omega_pb pb, eqn sub, int var, int c, bool *found_black)
923*e4b17023SJohn Marino {
924*e4b17023SJohn Marino   int e, top_var = setup_packing (sub, pb->num_vars);
925*e4b17023SJohn Marino 
926*e4b17023SJohn Marino   *found_black = false;
927*e4b17023SJohn Marino 
928*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
929*e4b17023SJohn Marino     {
930*e4b17023SJohn Marino       if (sub->color == omega_red)
931*e4b17023SJohn Marino 	fprintf (dump_file, "[");
932*e4b17023SJohn Marino 
933*e4b17023SJohn Marino       fprintf (dump_file, "substituting using %s := ",
934*e4b17023SJohn Marino 	       omega_variable_to_str (pb, var));
935*e4b17023SJohn Marino       omega_print_term (dump_file, pb, sub, -c);
936*e4b17023SJohn Marino 
937*e4b17023SJohn Marino       if (sub->color == omega_red)
938*e4b17023SJohn Marino 	fprintf (dump_file, "]");
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino       fprintf (dump_file, "\n");
941*e4b17023SJohn Marino       omega_print_vars (dump_file, pb);
942*e4b17023SJohn Marino     }
943*e4b17023SJohn Marino 
944*e4b17023SJohn Marino   for (e = pb->num_eqs - 1; e >= 0; e--)
945*e4b17023SJohn Marino     {
946*e4b17023SJohn Marino       eqn eqn = &(pb->eqs[e]);
947*e4b17023SJohn Marino 
948*e4b17023SJohn Marino       omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
951*e4b17023SJohn Marino 	{
952*e4b17023SJohn Marino 	  omega_print_eq (dump_file, pb, eqn);
953*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
954*e4b17023SJohn Marino 	}
955*e4b17023SJohn Marino     }
956*e4b17023SJohn Marino 
957*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
958*e4b17023SJohn Marino     {
959*e4b17023SJohn Marino       eqn eqn = &(pb->geqs[e]);
960*e4b17023SJohn Marino 
961*e4b17023SJohn Marino       omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino       if (eqn->coef[var] && eqn->color == omega_red)
964*e4b17023SJohn Marino 	eqn->touched = 1;
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
967*e4b17023SJohn Marino 	{
968*e4b17023SJohn Marino 	  omega_print_geq (dump_file, pb, eqn);
969*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
970*e4b17023SJohn Marino 	}
971*e4b17023SJohn Marino     }
972*e4b17023SJohn Marino 
973*e4b17023SJohn Marino   for (e = pb->num_subs - 1; e >= 0; e--)
974*e4b17023SJohn Marino     {
975*e4b17023SJohn Marino       eqn eqn = &(pb->subs[e]);
976*e4b17023SJohn Marino 
977*e4b17023SJohn Marino       omega_substitute_red_1 (eqn, sub, var, c, found_black, top_var);
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
980*e4b17023SJohn Marino 	{
981*e4b17023SJohn Marino 	  fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
982*e4b17023SJohn Marino 	  omega_print_term (dump_file, pb, eqn, 1);
983*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
984*e4b17023SJohn Marino 	}
985*e4b17023SJohn Marino     }
986*e4b17023SJohn Marino 
987*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
988*e4b17023SJohn Marino     fprintf (dump_file, "---\n\n");
989*e4b17023SJohn Marino 
990*e4b17023SJohn Marino   if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
991*e4b17023SJohn Marino     *found_black = true;
992*e4b17023SJohn Marino }
993*e4b17023SJohn Marino 
994*e4b17023SJohn Marino /* Substitute in PB variable VAR with "C * SUB".  */
995*e4b17023SJohn Marino 
996*e4b17023SJohn Marino static void
omega_substitute(omega_pb pb,eqn sub,int var,int c)997*e4b17023SJohn Marino omega_substitute (omega_pb pb, eqn sub, int var, int c)
998*e4b17023SJohn Marino {
999*e4b17023SJohn Marino   int e, j, j0;
1000*e4b17023SJohn Marino   int top_var = setup_packing (sub, pb->num_vars);
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1003*e4b17023SJohn Marino     {
1004*e4b17023SJohn Marino       fprintf (dump_file, "substituting using %s := ",
1005*e4b17023SJohn Marino 	       omega_variable_to_str (pb, var));
1006*e4b17023SJohn Marino       omega_print_term (dump_file, pb, sub, -c);
1007*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1008*e4b17023SJohn Marino       omega_print_vars (dump_file, pb);
1009*e4b17023SJohn Marino     }
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino   if (top_var < 0)
1012*e4b17023SJohn Marino     {
1013*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
1014*e4b17023SJohn Marino 	pb->eqs[e].coef[var] = 0;
1015*e4b17023SJohn Marino 
1016*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
1017*e4b17023SJohn Marino 	if (pb->geqs[e].coef[var] != 0)
1018*e4b17023SJohn Marino 	  {
1019*e4b17023SJohn Marino 	    pb->geqs[e].touched = 1;
1020*e4b17023SJohn Marino 	    pb->geqs[e].coef[var] = 0;
1021*e4b17023SJohn Marino 	  }
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
1024*e4b17023SJohn Marino 	pb->subs[e].coef[var] = 0;
1025*e4b17023SJohn Marino 
1026*e4b17023SJohn Marino       if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1027*e4b17023SJohn Marino 	{
1028*e4b17023SJohn Marino 	  int k;
1029*e4b17023SJohn Marino 	  eqn eqn = &(pb->subs[pb->num_subs++]);
1030*e4b17023SJohn Marino 
1031*e4b17023SJohn Marino 	  for (k = pb->num_vars; k >= 0; k--)
1032*e4b17023SJohn Marino 	    eqn->coef[k] = 0;
1033*e4b17023SJohn Marino 
1034*e4b17023SJohn Marino 	  eqn->key = pb->var[var];
1035*e4b17023SJohn Marino 	  eqn->color = omega_black;
1036*e4b17023SJohn Marino 	}
1037*e4b17023SJohn Marino     }
1038*e4b17023SJohn Marino   else if (top_var == 0 && packing[0] == 0)
1039*e4b17023SJohn Marino     {
1040*e4b17023SJohn Marino       c = -sub->coef[0] * c;
1041*e4b17023SJohn Marino 
1042*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
1043*e4b17023SJohn Marino 	{
1044*e4b17023SJohn Marino 	  pb->eqs[e].coef[0] += pb->eqs[e].coef[var] * c;
1045*e4b17023SJohn Marino 	  pb->eqs[e].coef[var] = 0;
1046*e4b17023SJohn Marino 	}
1047*e4b17023SJohn Marino 
1048*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
1049*e4b17023SJohn Marino 	if (pb->geqs[e].coef[var] != 0)
1050*e4b17023SJohn Marino 	  {
1051*e4b17023SJohn Marino 	    pb->geqs[e].coef[0] += pb->geqs[e].coef[var] * c;
1052*e4b17023SJohn Marino 	    pb->geqs[e].coef[var] = 0;
1053*e4b17023SJohn Marino 	    pb->geqs[e].touched = 1;
1054*e4b17023SJohn Marino 	  }
1055*e4b17023SJohn Marino 
1056*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
1057*e4b17023SJohn Marino 	{
1058*e4b17023SJohn Marino 	  pb->subs[e].coef[0] += pb->subs[e].coef[var] * c;
1059*e4b17023SJohn Marino 	  pb->subs[e].coef[var] = 0;
1060*e4b17023SJohn Marino 	}
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino       if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1063*e4b17023SJohn Marino 	{
1064*e4b17023SJohn Marino 	  int k;
1065*e4b17023SJohn Marino 	  eqn eqn = &(pb->subs[pb->num_subs++]);
1066*e4b17023SJohn Marino 
1067*e4b17023SJohn Marino 	  for (k = pb->num_vars; k >= 1; k--)
1068*e4b17023SJohn Marino 	    eqn->coef[k] = 0;
1069*e4b17023SJohn Marino 
1070*e4b17023SJohn Marino 	  eqn->coef[0] = c;
1071*e4b17023SJohn Marino 	  eqn->key = pb->var[var];
1072*e4b17023SJohn Marino 	  eqn->color = omega_black;
1073*e4b17023SJohn Marino 	}
1074*e4b17023SJohn Marino 
1075*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1076*e4b17023SJohn Marino 	{
1077*e4b17023SJohn Marino 	  fprintf (dump_file, "---\n\n");
1078*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
1079*e4b17023SJohn Marino 	  fprintf (dump_file, "===\n\n");
1080*e4b17023SJohn Marino 	}
1081*e4b17023SJohn Marino     }
1082*e4b17023SJohn Marino   else
1083*e4b17023SJohn Marino     {
1084*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
1085*e4b17023SJohn Marino 	{
1086*e4b17023SJohn Marino 	  eqn eqn = &(pb->eqs[e]);
1087*e4b17023SJohn Marino 	  int k = eqn->coef[var];
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino 	  if (k != 0)
1090*e4b17023SJohn Marino 	    {
1091*e4b17023SJohn Marino 	      k = c * k;
1092*e4b17023SJohn Marino 	      eqn->coef[var] = 0;
1093*e4b17023SJohn Marino 
1094*e4b17023SJohn Marino 	      for (j = top_var; j >= 0; j--)
1095*e4b17023SJohn Marino 		{
1096*e4b17023SJohn Marino 		  j0 = packing[j];
1097*e4b17023SJohn Marino 		  eqn->coef[j0] -= sub->coef[j0] * k;
1098*e4b17023SJohn Marino 		}
1099*e4b17023SJohn Marino 	    }
1100*e4b17023SJohn Marino 
1101*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1102*e4b17023SJohn Marino 	    {
1103*e4b17023SJohn Marino 	      omega_print_eq (dump_file, pb, eqn);
1104*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1105*e4b17023SJohn Marino 	    }
1106*e4b17023SJohn Marino 	}
1107*e4b17023SJohn Marino 
1108*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
1109*e4b17023SJohn Marino 	{
1110*e4b17023SJohn Marino 	  eqn eqn = &(pb->geqs[e]);
1111*e4b17023SJohn Marino 	  int k = eqn->coef[var];
1112*e4b17023SJohn Marino 
1113*e4b17023SJohn Marino 	  if (k != 0)
1114*e4b17023SJohn Marino 	    {
1115*e4b17023SJohn Marino 	      k = c * k;
1116*e4b17023SJohn Marino 	      eqn->touched = 1;
1117*e4b17023SJohn Marino 	      eqn->coef[var] = 0;
1118*e4b17023SJohn Marino 
1119*e4b17023SJohn Marino 	      for (j = top_var; j >= 0; j--)
1120*e4b17023SJohn Marino 		{
1121*e4b17023SJohn Marino 		  j0 = packing[j];
1122*e4b17023SJohn Marino 		  eqn->coef[j0] -= sub->coef[j0] * k;
1123*e4b17023SJohn Marino 		}
1124*e4b17023SJohn Marino 	    }
1125*e4b17023SJohn Marino 
1126*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1127*e4b17023SJohn Marino 	    {
1128*e4b17023SJohn Marino 	      omega_print_geq (dump_file, pb, eqn);
1129*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1130*e4b17023SJohn Marino 	    }
1131*e4b17023SJohn Marino 	}
1132*e4b17023SJohn Marino 
1133*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
1134*e4b17023SJohn Marino 	{
1135*e4b17023SJohn Marino 	  eqn eqn = &(pb->subs[e]);
1136*e4b17023SJohn Marino 	  int k = eqn->coef[var];
1137*e4b17023SJohn Marino 
1138*e4b17023SJohn Marino 	  if (k != 0)
1139*e4b17023SJohn Marino 	    {
1140*e4b17023SJohn Marino 	      k = c * k;
1141*e4b17023SJohn Marino 	      eqn->coef[var] = 0;
1142*e4b17023SJohn Marino 
1143*e4b17023SJohn Marino 	      for (j = top_var; j >= 0; j--)
1144*e4b17023SJohn Marino 		{
1145*e4b17023SJohn Marino 		  j0 = packing[j];
1146*e4b17023SJohn Marino 		  eqn->coef[j0] -= sub->coef[j0] * k;
1147*e4b17023SJohn Marino 		}
1148*e4b17023SJohn Marino 	    }
1149*e4b17023SJohn Marino 
1150*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1151*e4b17023SJohn Marino 	    {
1152*e4b17023SJohn Marino 	      fprintf (dump_file, "%s := ", omega_var_to_str (eqn->key));
1153*e4b17023SJohn Marino 	      omega_print_term (dump_file, pb, eqn, 1);
1154*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1155*e4b17023SJohn Marino 	    }
1156*e4b17023SJohn Marino 	}
1157*e4b17023SJohn Marino 
1158*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1159*e4b17023SJohn Marino 	{
1160*e4b17023SJohn Marino 	  fprintf (dump_file, "---\n\n");
1161*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
1162*e4b17023SJohn Marino 	  fprintf (dump_file, "===\n\n");
1163*e4b17023SJohn Marino 	}
1164*e4b17023SJohn Marino 
1165*e4b17023SJohn Marino       if (omega_safe_var_p (pb, var) && !omega_wildcard_p (pb, var))
1166*e4b17023SJohn Marino 	{
1167*e4b17023SJohn Marino 	  int k;
1168*e4b17023SJohn Marino 	  eqn eqn = &(pb->subs[pb->num_subs++]);
1169*e4b17023SJohn Marino 	  c = -c;
1170*e4b17023SJohn Marino 
1171*e4b17023SJohn Marino 	  for (k = pb->num_vars; k >= 0; k--)
1172*e4b17023SJohn Marino 	    eqn->coef[k] = c * (sub->coef[k]);
1173*e4b17023SJohn Marino 
1174*e4b17023SJohn Marino 	  eqn->key = pb->var[var];
1175*e4b17023SJohn Marino 	  eqn->color = sub->color;
1176*e4b17023SJohn Marino 	}
1177*e4b17023SJohn Marino     }
1178*e4b17023SJohn Marino }
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino /* Solve e = factor alpha for x_j and substitute.  */
1181*e4b17023SJohn Marino 
1182*e4b17023SJohn Marino static void
omega_do_mod(omega_pb pb,int factor,int e,int j)1183*e4b17023SJohn Marino omega_do_mod (omega_pb pb, int factor, int e, int j)
1184*e4b17023SJohn Marino {
1185*e4b17023SJohn Marino   int k, i;
1186*e4b17023SJohn Marino   eqn eq = omega_alloc_eqns (0, 1);
1187*e4b17023SJohn Marino   int nfactor;
1188*e4b17023SJohn Marino   bool kill_j = false;
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino   omega_copy_eqn (eq, &pb->eqs[e], pb->num_vars);
1191*e4b17023SJohn Marino 
1192*e4b17023SJohn Marino   for (k = pb->num_vars; k >= 0; k--)
1193*e4b17023SJohn Marino     {
1194*e4b17023SJohn Marino       eq->coef[k] = int_mod (eq->coef[k], factor);
1195*e4b17023SJohn Marino 
1196*e4b17023SJohn Marino       if (2 * eq->coef[k] >= factor)
1197*e4b17023SJohn Marino 	eq->coef[k] -= factor;
1198*e4b17023SJohn Marino     }
1199*e4b17023SJohn Marino 
1200*e4b17023SJohn Marino   nfactor = eq->coef[j];
1201*e4b17023SJohn Marino 
1202*e4b17023SJohn Marino   if (omega_safe_var_p (pb, j) && !omega_wildcard_p (pb, j))
1203*e4b17023SJohn Marino     {
1204*e4b17023SJohn Marino       i = omega_add_new_wild_card (pb);
1205*e4b17023SJohn Marino       eq->coef[pb->num_vars] = eq->coef[i];
1206*e4b17023SJohn Marino       eq->coef[j] = 0;
1207*e4b17023SJohn Marino       eq->coef[i] = -factor;
1208*e4b17023SJohn Marino       kill_j = true;
1209*e4b17023SJohn Marino     }
1210*e4b17023SJohn Marino   else
1211*e4b17023SJohn Marino     {
1212*e4b17023SJohn Marino       eq->coef[j] = -factor;
1213*e4b17023SJohn Marino       if (!omega_wildcard_p (pb, j))
1214*e4b17023SJohn Marino 	omega_name_wild_card (pb, j);
1215*e4b17023SJohn Marino     }
1216*e4b17023SJohn Marino 
1217*e4b17023SJohn Marino   omega_substitute (pb, eq, j, nfactor);
1218*e4b17023SJohn Marino 
1219*e4b17023SJohn Marino   for (k = pb->num_vars; k >= 0; k--)
1220*e4b17023SJohn Marino     pb->eqs[e].coef[k] = pb->eqs[e].coef[k] / factor;
1221*e4b17023SJohn Marino 
1222*e4b17023SJohn Marino   if (kill_j)
1223*e4b17023SJohn Marino     omega_delete_variable (pb, j);
1224*e4b17023SJohn Marino 
1225*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1226*e4b17023SJohn Marino     {
1227*e4b17023SJohn Marino       fprintf (dump_file, "Mod-ing and normalizing produces:\n");
1228*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
1229*e4b17023SJohn Marino     }
1230*e4b17023SJohn Marino 
1231*e4b17023SJohn Marino   omega_free_eqns (eq, 1);
1232*e4b17023SJohn Marino }
1233*e4b17023SJohn Marino 
1234*e4b17023SJohn Marino /* Multiplies by -1 inequality E.  */
1235*e4b17023SJohn Marino 
1236*e4b17023SJohn Marino void
omega_negate_geq(omega_pb pb,int e)1237*e4b17023SJohn Marino omega_negate_geq (omega_pb pb, int e)
1238*e4b17023SJohn Marino {
1239*e4b17023SJohn Marino   int i;
1240*e4b17023SJohn Marino 
1241*e4b17023SJohn Marino   for (i = pb->num_vars; i >= 0; i--)
1242*e4b17023SJohn Marino     pb->geqs[e].coef[i] *= -1;
1243*e4b17023SJohn Marino 
1244*e4b17023SJohn Marino   pb->geqs[e].coef[0]--;
1245*e4b17023SJohn Marino   pb->geqs[e].touched = 1;
1246*e4b17023SJohn Marino }
1247*e4b17023SJohn Marino 
1248*e4b17023SJohn Marino /* Returns OMEGA_TRUE when problem PB has a solution.  */
1249*e4b17023SJohn Marino 
1250*e4b17023SJohn Marino static enum omega_result
verify_omega_pb(omega_pb pb)1251*e4b17023SJohn Marino verify_omega_pb (omega_pb pb)
1252*e4b17023SJohn Marino {
1253*e4b17023SJohn Marino   enum omega_result result;
1254*e4b17023SJohn Marino   int e;
1255*e4b17023SJohn Marino   bool any_color = false;
1256*e4b17023SJohn Marino   omega_pb tmp_problem = XNEW (struct omega_pb_d);
1257*e4b17023SJohn Marino 
1258*e4b17023SJohn Marino   omega_copy_problem (tmp_problem, pb);
1259*e4b17023SJohn Marino   tmp_problem->safe_vars = 0;
1260*e4b17023SJohn Marino   tmp_problem->num_subs = 0;
1261*e4b17023SJohn Marino 
1262*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
1263*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
1264*e4b17023SJohn Marino       {
1265*e4b17023SJohn Marino 	any_color = true;
1266*e4b17023SJohn Marino 	break;
1267*e4b17023SJohn Marino       }
1268*e4b17023SJohn Marino 
1269*e4b17023SJohn Marino   if (please_no_equalities_in_simplified_problems)
1270*e4b17023SJohn Marino     any_color = true;
1271*e4b17023SJohn Marino 
1272*e4b17023SJohn Marino   if (any_color)
1273*e4b17023SJohn Marino     original_problem = no_problem;
1274*e4b17023SJohn Marino   else
1275*e4b17023SJohn Marino     original_problem = pb;
1276*e4b17023SJohn Marino 
1277*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1278*e4b17023SJohn Marino     {
1279*e4b17023SJohn Marino       fprintf (dump_file, "verifying problem");
1280*e4b17023SJohn Marino 
1281*e4b17023SJohn Marino       if (any_color)
1282*e4b17023SJohn Marino 	fprintf (dump_file, " (color mode)");
1283*e4b17023SJohn Marino 
1284*e4b17023SJohn Marino       fprintf (dump_file, " :\n");
1285*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
1286*e4b17023SJohn Marino     }
1287*e4b17023SJohn Marino 
1288*e4b17023SJohn Marino   result = omega_solve_problem (tmp_problem, omega_unknown);
1289*e4b17023SJohn Marino   original_problem = no_problem;
1290*e4b17023SJohn Marino   free (tmp_problem);
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1293*e4b17023SJohn Marino     {
1294*e4b17023SJohn Marino       if (result != omega_false)
1295*e4b17023SJohn Marino 	fprintf (dump_file, "verified problem\n");
1296*e4b17023SJohn Marino       else
1297*e4b17023SJohn Marino 	fprintf (dump_file, "disproved problem\n");
1298*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
1299*e4b17023SJohn Marino     }
1300*e4b17023SJohn Marino 
1301*e4b17023SJohn Marino   return result;
1302*e4b17023SJohn Marino }
1303*e4b17023SJohn Marino 
1304*e4b17023SJohn Marino /* Add a new equality to problem PB at last position E.  */
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino static void
adding_equality_constraint(omega_pb pb,int e)1307*e4b17023SJohn Marino adding_equality_constraint (omega_pb pb, int e)
1308*e4b17023SJohn Marino {
1309*e4b17023SJohn Marino   if (original_problem != no_problem
1310*e4b17023SJohn Marino       && original_problem != pb
1311*e4b17023SJohn Marino       && !conservative)
1312*e4b17023SJohn Marino     {
1313*e4b17023SJohn Marino       int i, j;
1314*e4b17023SJohn Marino       int e2 = original_problem->num_eqs++;
1315*e4b17023SJohn Marino 
1316*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1317*e4b17023SJohn Marino 	fprintf (dump_file,
1318*e4b17023SJohn Marino 		 "adding equality constraint %d to outer problem\n", e2);
1319*e4b17023SJohn Marino       omega_init_eqn_zero (&original_problem->eqs[e2],
1320*e4b17023SJohn Marino 			   original_problem->num_vars);
1321*e4b17023SJohn Marino 
1322*e4b17023SJohn Marino       for (i = pb->num_vars; i >= 1; i--)
1323*e4b17023SJohn Marino 	{
1324*e4b17023SJohn Marino 	  for (j = original_problem->num_vars; j >= 1; j--)
1325*e4b17023SJohn Marino 	    if (original_problem->var[j] == pb->var[i])
1326*e4b17023SJohn Marino 	      break;
1327*e4b17023SJohn Marino 
1328*e4b17023SJohn Marino 	  if (j <= 0)
1329*e4b17023SJohn Marino 	    {
1330*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1331*e4b17023SJohn Marino 		fprintf (dump_file, "retracting\n");
1332*e4b17023SJohn Marino 	      original_problem->num_eqs--;
1333*e4b17023SJohn Marino 	      return;
1334*e4b17023SJohn Marino 	    }
1335*e4b17023SJohn Marino 	  original_problem->eqs[e2].coef[j] = pb->eqs[e].coef[i];
1336*e4b17023SJohn Marino 	}
1337*e4b17023SJohn Marino 
1338*e4b17023SJohn Marino       original_problem->eqs[e2].coef[0] = pb->eqs[e].coef[0];
1339*e4b17023SJohn Marino 
1340*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1341*e4b17023SJohn Marino 	omega_print_problem (dump_file, original_problem);
1342*e4b17023SJohn Marino     }
1343*e4b17023SJohn Marino }
1344*e4b17023SJohn Marino 
1345*e4b17023SJohn Marino static int *fast_lookup;
1346*e4b17023SJohn Marino static int *fast_lookup_red;
1347*e4b17023SJohn Marino 
1348*e4b17023SJohn Marino typedef enum {
1349*e4b17023SJohn Marino   normalize_false,
1350*e4b17023SJohn Marino   normalize_uncoupled,
1351*e4b17023SJohn Marino   normalize_coupled
1352*e4b17023SJohn Marino } normalize_return_type;
1353*e4b17023SJohn Marino 
1354*e4b17023SJohn Marino /* Normalizes PB by removing redundant constraints.  Returns
1355*e4b17023SJohn Marino    normalize_false when the constraints system has no solution,
1356*e4b17023SJohn Marino    otherwise returns normalize_coupled or normalize_uncoupled.  */
1357*e4b17023SJohn Marino 
1358*e4b17023SJohn Marino static normalize_return_type
normalize_omega_problem(omega_pb pb)1359*e4b17023SJohn Marino normalize_omega_problem (omega_pb pb)
1360*e4b17023SJohn Marino {
1361*e4b17023SJohn Marino   int e, i, j, k, n_vars;
1362*e4b17023SJohn Marino   int coupled_subscripts = 0;
1363*e4b17023SJohn Marino 
1364*e4b17023SJohn Marino   n_vars = pb->num_vars;
1365*e4b17023SJohn Marino 
1366*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
1367*e4b17023SJohn Marino     {
1368*e4b17023SJohn Marino       if (!pb->geqs[e].touched)
1369*e4b17023SJohn Marino 	{
1370*e4b17023SJohn Marino 	  if (!single_var_geq (&pb->geqs[e], n_vars))
1371*e4b17023SJohn Marino 	    coupled_subscripts = 1;
1372*e4b17023SJohn Marino 	}
1373*e4b17023SJohn Marino       else
1374*e4b17023SJohn Marino 	{
1375*e4b17023SJohn Marino 	  int g, top_var, i0, hashCode;
1376*e4b17023SJohn Marino 	  int *p = &packing[0];
1377*e4b17023SJohn Marino 
1378*e4b17023SJohn Marino 	  for (k = 1; k <= n_vars; k++)
1379*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[k])
1380*e4b17023SJohn Marino 	      *(p++) = k;
1381*e4b17023SJohn Marino 
1382*e4b17023SJohn Marino 	  top_var = (p - &packing[0]) - 1;
1383*e4b17023SJohn Marino 
1384*e4b17023SJohn Marino 	  if (top_var == -1)
1385*e4b17023SJohn Marino 	    {
1386*e4b17023SJohn Marino 	      if (pb->geqs[e].coef[0] < 0)
1387*e4b17023SJohn Marino 		{
1388*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
1389*e4b17023SJohn Marino 		    {
1390*e4b17023SJohn Marino 		      omega_print_geq (dump_file, pb, &pb->geqs[e]);
1391*e4b17023SJohn Marino 		      fprintf (dump_file, "\nequations have no solution \n");
1392*e4b17023SJohn Marino 		    }
1393*e4b17023SJohn Marino 		  return normalize_false;
1394*e4b17023SJohn Marino 		}
1395*e4b17023SJohn Marino 
1396*e4b17023SJohn Marino 	      omega_delete_geq (pb, e, n_vars);
1397*e4b17023SJohn Marino 	      e--;
1398*e4b17023SJohn Marino 	      continue;
1399*e4b17023SJohn Marino 	    }
1400*e4b17023SJohn Marino 	  else if (top_var == 0)
1401*e4b17023SJohn Marino 	    {
1402*e4b17023SJohn Marino 	      int singlevar = packing[0];
1403*e4b17023SJohn Marino 
1404*e4b17023SJohn Marino 	      g = pb->geqs[e].coef[singlevar];
1405*e4b17023SJohn Marino 
1406*e4b17023SJohn Marino 	      if (g > 0)
1407*e4b17023SJohn Marino 		{
1408*e4b17023SJohn Marino 		  pb->geqs[e].coef[singlevar] = 1;
1409*e4b17023SJohn Marino 		  pb->geqs[e].key = singlevar;
1410*e4b17023SJohn Marino 		}
1411*e4b17023SJohn Marino 	      else
1412*e4b17023SJohn Marino 		{
1413*e4b17023SJohn Marino 		  g = -g;
1414*e4b17023SJohn Marino 		  pb->geqs[e].coef[singlevar] = -1;
1415*e4b17023SJohn Marino 		  pb->geqs[e].key = -singlevar;
1416*e4b17023SJohn Marino 		}
1417*e4b17023SJohn Marino 
1418*e4b17023SJohn Marino 	      if (g > 1)
1419*e4b17023SJohn Marino 		pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1420*e4b17023SJohn Marino 	    }
1421*e4b17023SJohn Marino 	  else
1422*e4b17023SJohn Marino 	    {
1423*e4b17023SJohn Marino 	      int g2;
1424*e4b17023SJohn Marino 	      int hash_key_multiplier = 31;
1425*e4b17023SJohn Marino 
1426*e4b17023SJohn Marino 	      coupled_subscripts = 1;
1427*e4b17023SJohn Marino 	      i0 = top_var;
1428*e4b17023SJohn Marino 	      i = packing[i0--];
1429*e4b17023SJohn Marino 	      g = pb->geqs[e].coef[i];
1430*e4b17023SJohn Marino 	      hashCode = g * (i + 3);
1431*e4b17023SJohn Marino 
1432*e4b17023SJohn Marino 	      if (g < 0)
1433*e4b17023SJohn Marino 		g = -g;
1434*e4b17023SJohn Marino 
1435*e4b17023SJohn Marino 	      for (; i0 >= 0; i0--)
1436*e4b17023SJohn Marino 		{
1437*e4b17023SJohn Marino 		  int x;
1438*e4b17023SJohn Marino 
1439*e4b17023SJohn Marino 		  i = packing[i0];
1440*e4b17023SJohn Marino 		  x = pb->geqs[e].coef[i];
1441*e4b17023SJohn Marino 		  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1442*e4b17023SJohn Marino 
1443*e4b17023SJohn Marino 		  if (x < 0)
1444*e4b17023SJohn Marino 		    x = -x;
1445*e4b17023SJohn Marino 
1446*e4b17023SJohn Marino 		  if (x == 1)
1447*e4b17023SJohn Marino 		    {
1448*e4b17023SJohn Marino 		      g = 1;
1449*e4b17023SJohn Marino 		      i0--;
1450*e4b17023SJohn Marino 		      break;
1451*e4b17023SJohn Marino 		    }
1452*e4b17023SJohn Marino 		  else
1453*e4b17023SJohn Marino 		    g = gcd (x, g);
1454*e4b17023SJohn Marino 		}
1455*e4b17023SJohn Marino 
1456*e4b17023SJohn Marino 	      for (; i0 >= 0; i0--)
1457*e4b17023SJohn Marino 		{
1458*e4b17023SJohn Marino 		  int x;
1459*e4b17023SJohn Marino 		  i = packing[i0];
1460*e4b17023SJohn Marino 		  x = pb->geqs[e].coef[i];
1461*e4b17023SJohn Marino 		  hashCode = hashCode * hash_key_multiplier * (i + 3) + x;
1462*e4b17023SJohn Marino 		}
1463*e4b17023SJohn Marino 
1464*e4b17023SJohn Marino 	      if (g > 1)
1465*e4b17023SJohn Marino 		{
1466*e4b17023SJohn Marino 		  pb->geqs[e].coef[0] = int_div (pb->geqs[e].coef[0], g);
1467*e4b17023SJohn Marino 		  i0 = top_var;
1468*e4b17023SJohn Marino 		  i = packing[i0--];
1469*e4b17023SJohn Marino 		  pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1470*e4b17023SJohn Marino 		  hashCode = pb->geqs[e].coef[i] * (i + 3);
1471*e4b17023SJohn Marino 
1472*e4b17023SJohn Marino 		  for (; i0 >= 0; i0--)
1473*e4b17023SJohn Marino 		    {
1474*e4b17023SJohn Marino 		      i = packing[i0];
1475*e4b17023SJohn Marino 		      pb->geqs[e].coef[i] = pb->geqs[e].coef[i] / g;
1476*e4b17023SJohn Marino 		      hashCode = hashCode * hash_key_multiplier * (i + 3)
1477*e4b17023SJohn Marino 			+ pb->geqs[e].coef[i];
1478*e4b17023SJohn Marino 		    }
1479*e4b17023SJohn Marino 		}
1480*e4b17023SJohn Marino 
1481*e4b17023SJohn Marino 	      g2 = abs (hashCode);
1482*e4b17023SJohn Marino 
1483*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1484*e4b17023SJohn Marino 		{
1485*e4b17023SJohn Marino 		  fprintf (dump_file, "Hash code = %d, eqn = ", hashCode);
1486*e4b17023SJohn Marino 		  omega_print_geq (dump_file, pb, &pb->geqs[e]);
1487*e4b17023SJohn Marino 		  fprintf (dump_file, "\n");
1488*e4b17023SJohn Marino 		}
1489*e4b17023SJohn Marino 
1490*e4b17023SJohn Marino 	      j = g2 % HASH_TABLE_SIZE;
1491*e4b17023SJohn Marino 
1492*e4b17023SJohn Marino 	      do {
1493*e4b17023SJohn Marino 		eqn proto = &(hash_master[j]);
1494*e4b17023SJohn Marino 
1495*e4b17023SJohn Marino 		if (proto->touched == g2)
1496*e4b17023SJohn Marino 		  {
1497*e4b17023SJohn Marino 		    if (proto->coef[0] == top_var)
1498*e4b17023SJohn Marino 		      {
1499*e4b17023SJohn Marino 			if (hashCode >= 0)
1500*e4b17023SJohn Marino 			  for (i0 = top_var; i0 >= 0; i0--)
1501*e4b17023SJohn Marino 			    {
1502*e4b17023SJohn Marino 			      i = packing[i0];
1503*e4b17023SJohn Marino 
1504*e4b17023SJohn Marino 			      if (pb->geqs[e].coef[i] != proto->coef[i])
1505*e4b17023SJohn Marino 				break;
1506*e4b17023SJohn Marino 			    }
1507*e4b17023SJohn Marino 			else
1508*e4b17023SJohn Marino 			  for (i0 = top_var; i0 >= 0; i0--)
1509*e4b17023SJohn Marino 			    {
1510*e4b17023SJohn Marino 			      i = packing[i0];
1511*e4b17023SJohn Marino 
1512*e4b17023SJohn Marino 			      if (pb->geqs[e].coef[i] != -proto->coef[i])
1513*e4b17023SJohn Marino 				break;
1514*e4b17023SJohn Marino 			    }
1515*e4b17023SJohn Marino 
1516*e4b17023SJohn Marino 			if (i0 < 0)
1517*e4b17023SJohn Marino 			  {
1518*e4b17023SJohn Marino 			    if (hashCode >= 0)
1519*e4b17023SJohn Marino 			      pb->geqs[e].key = proto->key;
1520*e4b17023SJohn Marino 			    else
1521*e4b17023SJohn Marino 			      pb->geqs[e].key = -proto->key;
1522*e4b17023SJohn Marino 			    break;
1523*e4b17023SJohn Marino 			  }
1524*e4b17023SJohn Marino 		      }
1525*e4b17023SJohn Marino 		  }
1526*e4b17023SJohn Marino 		else if (proto->touched < 0)
1527*e4b17023SJohn Marino 		  {
1528*e4b17023SJohn Marino 		    omega_init_eqn_zero (proto, pb->num_vars);
1529*e4b17023SJohn Marino 		    if (hashCode >= 0)
1530*e4b17023SJohn Marino 		      for (i0 = top_var; i0 >= 0; i0--)
1531*e4b17023SJohn Marino 			{
1532*e4b17023SJohn Marino 			  i = packing[i0];
1533*e4b17023SJohn Marino 			  proto->coef[i] = pb->geqs[e].coef[i];
1534*e4b17023SJohn Marino 			}
1535*e4b17023SJohn Marino 		    else
1536*e4b17023SJohn Marino 		      for (i0 = top_var; i0 >= 0; i0--)
1537*e4b17023SJohn Marino 			{
1538*e4b17023SJohn Marino 			  i = packing[i0];
1539*e4b17023SJohn Marino 			  proto->coef[i] = -pb->geqs[e].coef[i];
1540*e4b17023SJohn Marino 			}
1541*e4b17023SJohn Marino 
1542*e4b17023SJohn Marino 		    proto->coef[0] = top_var;
1543*e4b17023SJohn Marino 		    proto->touched = g2;
1544*e4b17023SJohn Marino 
1545*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1546*e4b17023SJohn Marino 		      fprintf (dump_file, " constraint key = %d\n",
1547*e4b17023SJohn Marino 			       next_key);
1548*e4b17023SJohn Marino 
1549*e4b17023SJohn Marino 		    proto->key = next_key++;
1550*e4b17023SJohn Marino 
1551*e4b17023SJohn Marino 		    /* Too many hash keys generated.  */
1552*e4b17023SJohn Marino 		    gcc_assert (proto->key <= MAX_KEYS);
1553*e4b17023SJohn Marino 
1554*e4b17023SJohn Marino 		    if (hashCode >= 0)
1555*e4b17023SJohn Marino 		      pb->geqs[e].key = proto->key;
1556*e4b17023SJohn Marino 		    else
1557*e4b17023SJohn Marino 		      pb->geqs[e].key = -proto->key;
1558*e4b17023SJohn Marino 
1559*e4b17023SJohn Marino 		    break;
1560*e4b17023SJohn Marino 		  }
1561*e4b17023SJohn Marino 
1562*e4b17023SJohn Marino 		j = (j + 1) % HASH_TABLE_SIZE;
1563*e4b17023SJohn Marino 	      } while (1);
1564*e4b17023SJohn Marino 	    }
1565*e4b17023SJohn Marino 
1566*e4b17023SJohn Marino 	  pb->geqs[e].touched = 0;
1567*e4b17023SJohn Marino 	}
1568*e4b17023SJohn Marino 
1569*e4b17023SJohn Marino       {
1570*e4b17023SJohn Marino 	int eKey = pb->geqs[e].key;
1571*e4b17023SJohn Marino 	int e2;
1572*e4b17023SJohn Marino 	if (e > 0)
1573*e4b17023SJohn Marino 	  {
1574*e4b17023SJohn Marino 	    int cTerm = pb->geqs[e].coef[0];
1575*e4b17023SJohn Marino 	    e2 = fast_lookup[MAX_KEYS - eKey];
1576*e4b17023SJohn Marino 
1577*e4b17023SJohn Marino 	    if (e2 < e && pb->geqs[e2].key == -eKey
1578*e4b17023SJohn Marino 		&& pb->geqs[e2].color == omega_black)
1579*e4b17023SJohn Marino 	      {
1580*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] < -cTerm)
1581*e4b17023SJohn Marino 		  {
1582*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1583*e4b17023SJohn Marino 		      {
1584*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &pb->geqs[e]);
1585*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1586*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1587*e4b17023SJohn Marino 			fprintf (dump_file,
1588*e4b17023SJohn Marino 				 "\nequations have no solution \n");
1589*e4b17023SJohn Marino 		      }
1590*e4b17023SJohn Marino 		    return normalize_false;
1591*e4b17023SJohn Marino 		  }
1592*e4b17023SJohn Marino 
1593*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] == -cTerm
1594*e4b17023SJohn Marino 		    && (create_color
1595*e4b17023SJohn Marino 			|| pb->geqs[e].color == omega_black))
1596*e4b17023SJohn Marino 		  {
1597*e4b17023SJohn Marino 		    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1598*e4b17023SJohn Marino 				    pb->num_vars);
1599*e4b17023SJohn Marino 		    if (pb->geqs[e].color == omega_black)
1600*e4b17023SJohn Marino 		      adding_equality_constraint (pb, pb->num_eqs);
1601*e4b17023SJohn Marino 		    pb->num_eqs++;
1602*e4b17023SJohn Marino 		    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1603*e4b17023SJohn Marino 		  }
1604*e4b17023SJohn Marino 	      }
1605*e4b17023SJohn Marino 
1606*e4b17023SJohn Marino 	    e2 = fast_lookup_red[MAX_KEYS - eKey];
1607*e4b17023SJohn Marino 
1608*e4b17023SJohn Marino 	    if (e2 < e && pb->geqs[e2].key == -eKey
1609*e4b17023SJohn Marino 		&& pb->geqs[e2].color == omega_red)
1610*e4b17023SJohn Marino 	      {
1611*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] < -cTerm)
1612*e4b17023SJohn Marino 		  {
1613*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1614*e4b17023SJohn Marino 		      {
1615*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &pb->geqs[e]);
1616*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1617*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &pb->geqs[e2]);
1618*e4b17023SJohn Marino 			fprintf (dump_file,
1619*e4b17023SJohn Marino 				 "\nequations have no solution \n");
1620*e4b17023SJohn Marino 		      }
1621*e4b17023SJohn Marino 		    return normalize_false;
1622*e4b17023SJohn Marino 		  }
1623*e4b17023SJohn Marino 
1624*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] == -cTerm && create_color)
1625*e4b17023SJohn Marino 		  {
1626*e4b17023SJohn Marino 		    omega_copy_eqn (&pb->eqs[pb->num_eqs], &pb->geqs[e],
1627*e4b17023SJohn Marino 				    pb->num_vars);
1628*e4b17023SJohn Marino 		    pb->eqs[pb->num_eqs].color = omega_red;
1629*e4b17023SJohn Marino 		    pb->num_eqs++;
1630*e4b17023SJohn Marino 		    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
1631*e4b17023SJohn Marino 		  }
1632*e4b17023SJohn Marino 	      }
1633*e4b17023SJohn Marino 
1634*e4b17023SJohn Marino 	    e2 = fast_lookup[MAX_KEYS + eKey];
1635*e4b17023SJohn Marino 
1636*e4b17023SJohn Marino 	    if (e2 < e && pb->geqs[e2].key == eKey
1637*e4b17023SJohn Marino 		&& pb->geqs[e2].color == omega_black)
1638*e4b17023SJohn Marino 	      {
1639*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] > cTerm)
1640*e4b17023SJohn Marino 		  {
1641*e4b17023SJohn Marino 		    if (pb->geqs[e].color == omega_black)
1642*e4b17023SJohn Marino 		      {
1643*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
1644*e4b17023SJohn Marino 			  {
1645*e4b17023SJohn Marino 			    fprintf (dump_file,
1646*e4b17023SJohn Marino 				     "Removing Redundant Equation: ");
1647*e4b17023SJohn Marino 			    omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1648*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
1649*e4b17023SJohn Marino 			    fprintf (dump_file,
1650*e4b17023SJohn Marino 				     "[a]      Made Redundant by: ");
1651*e4b17023SJohn Marino 			    omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1652*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
1653*e4b17023SJohn Marino 			  }
1654*e4b17023SJohn Marino 			pb->geqs[e2].coef[0] = cTerm;
1655*e4b17023SJohn Marino 			omega_delete_geq (pb, e, n_vars);
1656*e4b17023SJohn Marino 			e--;
1657*e4b17023SJohn Marino 			continue;
1658*e4b17023SJohn Marino 		      }
1659*e4b17023SJohn Marino 		  }
1660*e4b17023SJohn Marino 		else
1661*e4b17023SJohn Marino 		  {
1662*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1663*e4b17023SJohn Marino 		      {
1664*e4b17023SJohn Marino 			fprintf (dump_file, "Removing Redundant Equation: ");
1665*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1666*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1667*e4b17023SJohn Marino 			fprintf (dump_file, "[b]      Made Redundant by: ");
1668*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1669*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1670*e4b17023SJohn Marino 		      }
1671*e4b17023SJohn Marino 		    omega_delete_geq (pb, e, n_vars);
1672*e4b17023SJohn Marino 		    e--;
1673*e4b17023SJohn Marino 		    continue;
1674*e4b17023SJohn Marino 		  }
1675*e4b17023SJohn Marino 	      }
1676*e4b17023SJohn Marino 
1677*e4b17023SJohn Marino 	    e2 = fast_lookup_red[MAX_KEYS + eKey];
1678*e4b17023SJohn Marino 
1679*e4b17023SJohn Marino 	    if (e2 < e && pb->geqs[e2].key == eKey
1680*e4b17023SJohn Marino 		&& pb->geqs[e2].color == omega_red)
1681*e4b17023SJohn Marino 	      {
1682*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[0] >= cTerm)
1683*e4b17023SJohn Marino 		  {
1684*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1685*e4b17023SJohn Marino 		      {
1686*e4b17023SJohn Marino 			fprintf (dump_file, "Removing Redundant Equation: ");
1687*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1688*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1689*e4b17023SJohn Marino 			fprintf (dump_file, "[c]      Made Redundant by: ");
1690*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1691*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1692*e4b17023SJohn Marino 		      }
1693*e4b17023SJohn Marino 		    pb->geqs[e2].coef[0] = cTerm;
1694*e4b17023SJohn Marino 		    pb->geqs[e2].color = pb->geqs[e].color;
1695*e4b17023SJohn Marino 		  }
1696*e4b17023SJohn Marino 		else if (pb->geqs[e].color == omega_red)
1697*e4b17023SJohn Marino 		  {
1698*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
1699*e4b17023SJohn Marino 		      {
1700*e4b17023SJohn Marino 			fprintf (dump_file, "Removing Redundant Equation: ");
1701*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e]));
1702*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1703*e4b17023SJohn Marino 			fprintf (dump_file, "[d]      Made Redundant by: ");
1704*e4b17023SJohn Marino 			omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
1705*e4b17023SJohn Marino 			fprintf (dump_file, "\n");
1706*e4b17023SJohn Marino 		      }
1707*e4b17023SJohn Marino 		  }
1708*e4b17023SJohn Marino 		omega_delete_geq (pb, e, n_vars);
1709*e4b17023SJohn Marino 		e--;
1710*e4b17023SJohn Marino 		continue;
1711*e4b17023SJohn Marino 
1712*e4b17023SJohn Marino 	      }
1713*e4b17023SJohn Marino 	  }
1714*e4b17023SJohn Marino 
1715*e4b17023SJohn Marino 	if (pb->geqs[e].color == omega_red)
1716*e4b17023SJohn Marino 	  fast_lookup_red[MAX_KEYS + eKey] = e;
1717*e4b17023SJohn Marino 	else
1718*e4b17023SJohn Marino 	  fast_lookup[MAX_KEYS + eKey] = e;
1719*e4b17023SJohn Marino       }
1720*e4b17023SJohn Marino     }
1721*e4b17023SJohn Marino 
1722*e4b17023SJohn Marino   create_color = false;
1723*e4b17023SJohn Marino   return coupled_subscripts ? normalize_coupled : normalize_uncoupled;
1724*e4b17023SJohn Marino }
1725*e4b17023SJohn Marino 
1726*e4b17023SJohn Marino /* Divide the coefficients of EQN by their gcd.  N_VARS is the number
1727*e4b17023SJohn Marino    of variables in EQN.  */
1728*e4b17023SJohn Marino 
1729*e4b17023SJohn Marino static inline void
divide_eqn_by_gcd(eqn eqn,int n_vars)1730*e4b17023SJohn Marino divide_eqn_by_gcd (eqn eqn, int n_vars)
1731*e4b17023SJohn Marino {
1732*e4b17023SJohn Marino   int var, g = 0;
1733*e4b17023SJohn Marino 
1734*e4b17023SJohn Marino   for (var = n_vars; var >= 0; var--)
1735*e4b17023SJohn Marino     g = gcd (abs (eqn->coef[var]), g);
1736*e4b17023SJohn Marino 
1737*e4b17023SJohn Marino   if (g)
1738*e4b17023SJohn Marino     for (var = n_vars; var >= 0; var--)
1739*e4b17023SJohn Marino       eqn->coef[var] = eqn->coef[var] / g;
1740*e4b17023SJohn Marino }
1741*e4b17023SJohn Marino 
1742*e4b17023SJohn Marino /* Rewrite some non-safe variables in function of protected
1743*e4b17023SJohn Marino    wildcard variables.  */
1744*e4b17023SJohn Marino 
1745*e4b17023SJohn Marino static void
cleanout_wildcards(omega_pb pb)1746*e4b17023SJohn Marino cleanout_wildcards (omega_pb pb)
1747*e4b17023SJohn Marino {
1748*e4b17023SJohn Marino   int e, i, j;
1749*e4b17023SJohn Marino   int n_vars = pb->num_vars;
1750*e4b17023SJohn Marino   bool renormalize = false;
1751*e4b17023SJohn Marino 
1752*e4b17023SJohn Marino   for (e = pb->num_eqs - 1; e >= 0; e--)
1753*e4b17023SJohn Marino     for (i = n_vars; !omega_safe_var_p (pb, i); i--)
1754*e4b17023SJohn Marino       if (pb->eqs[e].coef[i] != 0)
1755*e4b17023SJohn Marino 	{
1756*e4b17023SJohn Marino 	  /* i is the last nonzero non-safe variable.  */
1757*e4b17023SJohn Marino 
1758*e4b17023SJohn Marino 	  for (j = i - 1; !omega_safe_var_p (pb, j); j--)
1759*e4b17023SJohn Marino 	    if (pb->eqs[e].coef[j] != 0)
1760*e4b17023SJohn Marino 	      break;
1761*e4b17023SJohn Marino 
1762*e4b17023SJohn Marino 	  /* j is the next nonzero non-safe variable, or points
1763*e4b17023SJohn Marino 	     to a safe variable: it is then a wildcard variable.  */
1764*e4b17023SJohn Marino 
1765*e4b17023SJohn Marino 	  /* Clean it out.  */
1766*e4b17023SJohn Marino 	  if (omega_safe_var_p (pb, j))
1767*e4b17023SJohn Marino 	    {
1768*e4b17023SJohn Marino 	      eqn sub = &(pb->eqs[e]);
1769*e4b17023SJohn Marino 	      int c = pb->eqs[e].coef[i];
1770*e4b17023SJohn Marino 	      int a = abs (c);
1771*e4b17023SJohn Marino 	      int e2;
1772*e4b17023SJohn Marino 
1773*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1774*e4b17023SJohn Marino 		{
1775*e4b17023SJohn Marino 		  fprintf (dump_file,
1776*e4b17023SJohn Marino 			   "Found a single wild card equality: ");
1777*e4b17023SJohn Marino 		  omega_print_eq (dump_file, pb, &pb->eqs[e]);
1778*e4b17023SJohn Marino 		  fprintf (dump_file, "\n");
1779*e4b17023SJohn Marino 		  omega_print_problem (dump_file, pb);
1780*e4b17023SJohn Marino 		}
1781*e4b17023SJohn Marino 
1782*e4b17023SJohn Marino 	      for (e2 = pb->num_eqs - 1; e2 >= 0; e2--)
1783*e4b17023SJohn Marino 		if (e != e2 && pb->eqs[e2].coef[i]
1784*e4b17023SJohn Marino 		    && (pb->eqs[e2].color == omega_red
1785*e4b17023SJohn Marino 			|| (pb->eqs[e2].color == omega_black
1786*e4b17023SJohn Marino 			    && pb->eqs[e].color == omega_black)))
1787*e4b17023SJohn Marino 		  {
1788*e4b17023SJohn Marino 		    eqn eqn = &(pb->eqs[e2]);
1789*e4b17023SJohn Marino 		    int var, k;
1790*e4b17023SJohn Marino 
1791*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1792*e4b17023SJohn Marino 		      eqn->coef[var] *= a;
1793*e4b17023SJohn Marino 
1794*e4b17023SJohn Marino 		    k = eqn->coef[i];
1795*e4b17023SJohn Marino 
1796*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1797*e4b17023SJohn Marino 		      eqn->coef[var] -= sub->coef[var] * k / c;
1798*e4b17023SJohn Marino 
1799*e4b17023SJohn Marino 		    eqn->coef[i] = 0;
1800*e4b17023SJohn Marino 		    divide_eqn_by_gcd (eqn, n_vars);
1801*e4b17023SJohn Marino 		  }
1802*e4b17023SJohn Marino 
1803*e4b17023SJohn Marino 	      for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
1804*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[i]
1805*e4b17023SJohn Marino 		    && (pb->geqs[e2].color == omega_red
1806*e4b17023SJohn Marino 			|| (pb->eqs[e].color == omega_black
1807*e4b17023SJohn Marino 			    && pb->geqs[e2].color == omega_black)))
1808*e4b17023SJohn Marino 		  {
1809*e4b17023SJohn Marino 		    eqn eqn = &(pb->geqs[e2]);
1810*e4b17023SJohn Marino 		    int var, k;
1811*e4b17023SJohn Marino 
1812*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1813*e4b17023SJohn Marino 		      eqn->coef[var] *= a;
1814*e4b17023SJohn Marino 
1815*e4b17023SJohn Marino 		    k = eqn->coef[i];
1816*e4b17023SJohn Marino 
1817*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1818*e4b17023SJohn Marino 		      eqn->coef[var] -= sub->coef[var] * k / c;
1819*e4b17023SJohn Marino 
1820*e4b17023SJohn Marino 		    eqn->coef[i] = 0;
1821*e4b17023SJohn Marino 		    eqn->touched = 1;
1822*e4b17023SJohn Marino 		    renormalize = true;
1823*e4b17023SJohn Marino 		  }
1824*e4b17023SJohn Marino 
1825*e4b17023SJohn Marino 	      for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
1826*e4b17023SJohn Marino 		if (pb->subs[e2].coef[i]
1827*e4b17023SJohn Marino 		    && (pb->subs[e2].color == omega_red
1828*e4b17023SJohn Marino 			|| (pb->subs[e2].color == omega_black
1829*e4b17023SJohn Marino 			    && pb->eqs[e].color == omega_black)))
1830*e4b17023SJohn Marino 		  {
1831*e4b17023SJohn Marino 		    eqn eqn = &(pb->subs[e2]);
1832*e4b17023SJohn Marino 		    int var, k;
1833*e4b17023SJohn Marino 
1834*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1835*e4b17023SJohn Marino 		      eqn->coef[var] *= a;
1836*e4b17023SJohn Marino 
1837*e4b17023SJohn Marino 		    k = eqn->coef[i];
1838*e4b17023SJohn Marino 
1839*e4b17023SJohn Marino 		    for (var = n_vars; var >= 0; var--)
1840*e4b17023SJohn Marino 		      eqn->coef[var] -= sub->coef[var] * k / c;
1841*e4b17023SJohn Marino 
1842*e4b17023SJohn Marino 		    eqn->coef[i] = 0;
1843*e4b17023SJohn Marino 		    divide_eqn_by_gcd (eqn, n_vars);
1844*e4b17023SJohn Marino 		  }
1845*e4b17023SJohn Marino 
1846*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1847*e4b17023SJohn Marino 		{
1848*e4b17023SJohn Marino 		  fprintf (dump_file, "cleaned-out wildcard: ");
1849*e4b17023SJohn Marino 		  omega_print_problem (dump_file, pb);
1850*e4b17023SJohn Marino 		}
1851*e4b17023SJohn Marino 	      break;
1852*e4b17023SJohn Marino 	    }
1853*e4b17023SJohn Marino 	}
1854*e4b17023SJohn Marino 
1855*e4b17023SJohn Marino   if (renormalize)
1856*e4b17023SJohn Marino     normalize_omega_problem (pb);
1857*e4b17023SJohn Marino }
1858*e4b17023SJohn Marino 
1859*e4b17023SJohn Marino /* Swap values contained in I and J.  */
1860*e4b17023SJohn Marino 
1861*e4b17023SJohn Marino static inline void
swap(int * i,int * j)1862*e4b17023SJohn Marino swap (int *i, int *j)
1863*e4b17023SJohn Marino {
1864*e4b17023SJohn Marino   int tmp;
1865*e4b17023SJohn Marino   tmp = *i;
1866*e4b17023SJohn Marino   *i = *j;
1867*e4b17023SJohn Marino   *j = tmp;
1868*e4b17023SJohn Marino }
1869*e4b17023SJohn Marino 
1870*e4b17023SJohn Marino /* Swap values contained in I and J.  */
1871*e4b17023SJohn Marino 
1872*e4b17023SJohn Marino static inline void
bswap(bool * i,bool * j)1873*e4b17023SJohn Marino bswap (bool *i, bool *j)
1874*e4b17023SJohn Marino {
1875*e4b17023SJohn Marino   bool tmp;
1876*e4b17023SJohn Marino   tmp = *i;
1877*e4b17023SJohn Marino   *i = *j;
1878*e4b17023SJohn Marino   *j = tmp;
1879*e4b17023SJohn Marino }
1880*e4b17023SJohn Marino 
1881*e4b17023SJohn Marino /* Make variable IDX unprotected in PB, by swapping its index at the
1882*e4b17023SJohn Marino    PB->safe_vars rank.  */
1883*e4b17023SJohn Marino 
1884*e4b17023SJohn Marino static inline void
omega_unprotect_1(omega_pb pb,int * idx,bool * unprotect)1885*e4b17023SJohn Marino omega_unprotect_1 (omega_pb pb, int *idx, bool *unprotect)
1886*e4b17023SJohn Marino {
1887*e4b17023SJohn Marino   /* If IDX is protected...  */
1888*e4b17023SJohn Marino   if (*idx < pb->safe_vars)
1889*e4b17023SJohn Marino     {
1890*e4b17023SJohn Marino       /* ... swap its index with the last non protected index.  */
1891*e4b17023SJohn Marino       int j = pb->safe_vars;
1892*e4b17023SJohn Marino       int e;
1893*e4b17023SJohn Marino 
1894*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
1895*e4b17023SJohn Marino 	{
1896*e4b17023SJohn Marino 	  pb->geqs[e].touched = 1;
1897*e4b17023SJohn Marino 	  swap (&pb->geqs[e].coef[*idx], &pb->geqs[e].coef[j]);
1898*e4b17023SJohn Marino 	}
1899*e4b17023SJohn Marino 
1900*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
1901*e4b17023SJohn Marino 	swap (&pb->eqs[e].coef[*idx], &pb->eqs[e].coef[j]);
1902*e4b17023SJohn Marino 
1903*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
1904*e4b17023SJohn Marino 	swap (&pb->subs[e].coef[*idx], &pb->subs[e].coef[j]);
1905*e4b17023SJohn Marino 
1906*e4b17023SJohn Marino       if (unprotect)
1907*e4b17023SJohn Marino 	bswap (&unprotect[*idx], &unprotect[j]);
1908*e4b17023SJohn Marino 
1909*e4b17023SJohn Marino       swap (&pb->var[*idx], &pb->var[j]);
1910*e4b17023SJohn Marino       pb->forwarding_address[pb->var[*idx]] = *idx;
1911*e4b17023SJohn Marino       pb->forwarding_address[pb->var[j]] = j;
1912*e4b17023SJohn Marino       (*idx)--;
1913*e4b17023SJohn Marino     }
1914*e4b17023SJohn Marino 
1915*e4b17023SJohn Marino   /* The variable at pb->safe_vars is also unprotected now.  */
1916*e4b17023SJohn Marino   pb->safe_vars--;
1917*e4b17023SJohn Marino }
1918*e4b17023SJohn Marino 
1919*e4b17023SJohn Marino /* During the Fourier-Motzkin elimination some variables are
1920*e4b17023SJohn Marino    substituted with other variables.  This function resurrects the
1921*e4b17023SJohn Marino    substituted variables in PB.  */
1922*e4b17023SJohn Marino 
1923*e4b17023SJohn Marino static void
resurrect_subs(omega_pb pb)1924*e4b17023SJohn Marino resurrect_subs (omega_pb pb)
1925*e4b17023SJohn Marino {
1926*e4b17023SJohn Marino   if (pb->num_subs > 0
1927*e4b17023SJohn Marino       && please_no_equalities_in_simplified_problems == 0)
1928*e4b17023SJohn Marino     {
1929*e4b17023SJohn Marino       int i, e, m;
1930*e4b17023SJohn Marino 
1931*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1932*e4b17023SJohn Marino 	{
1933*e4b17023SJohn Marino 	  fprintf (dump_file,
1934*e4b17023SJohn Marino 		   "problem reduced, bringing variables back to life\n");
1935*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
1936*e4b17023SJohn Marino 	}
1937*e4b17023SJohn Marino 
1938*e4b17023SJohn Marino       for (i = 1; omega_safe_var_p (pb, i); i++)
1939*e4b17023SJohn Marino 	if (omega_wildcard_p (pb, i))
1940*e4b17023SJohn Marino 	  omega_unprotect_1 (pb, &i, NULL);
1941*e4b17023SJohn Marino 
1942*e4b17023SJohn Marino       m = pb->num_subs;
1943*e4b17023SJohn Marino 
1944*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
1945*e4b17023SJohn Marino 	if (single_var_geq (&pb->geqs[e], pb->num_vars))
1946*e4b17023SJohn Marino 	  {
1947*e4b17023SJohn Marino 	    if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
1948*e4b17023SJohn Marino 	      pb->geqs[e].key += (pb->geqs[e].key > 0 ? m : -m);
1949*e4b17023SJohn Marino 	  }
1950*e4b17023SJohn Marino 	else
1951*e4b17023SJohn Marino 	  {
1952*e4b17023SJohn Marino 	    pb->geqs[e].touched = 1;
1953*e4b17023SJohn Marino 	    pb->geqs[e].key = 0;
1954*e4b17023SJohn Marino 	  }
1955*e4b17023SJohn Marino 
1956*e4b17023SJohn Marino       for (i = pb->num_vars; !omega_safe_var_p (pb, i); i--)
1957*e4b17023SJohn Marino 	{
1958*e4b17023SJohn Marino 	  pb->var[i + m] = pb->var[i];
1959*e4b17023SJohn Marino 
1960*e4b17023SJohn Marino 	  for (e = pb->num_geqs - 1; e >= 0; e--)
1961*e4b17023SJohn Marino 	    pb->geqs[e].coef[i + m] = pb->geqs[e].coef[i];
1962*e4b17023SJohn Marino 
1963*e4b17023SJohn Marino 	  for (e = pb->num_eqs - 1; e >= 0; e--)
1964*e4b17023SJohn Marino 	    pb->eqs[e].coef[i + m] = pb->eqs[e].coef[i];
1965*e4b17023SJohn Marino 
1966*e4b17023SJohn Marino 	  for (e = pb->num_subs - 1; e >= 0; e--)
1967*e4b17023SJohn Marino 	    pb->subs[e].coef[i + m] = pb->subs[e].coef[i];
1968*e4b17023SJohn Marino 	}
1969*e4b17023SJohn Marino 
1970*e4b17023SJohn Marino       for (i = pb->safe_vars + m; !omega_safe_var_p (pb, i); i--)
1971*e4b17023SJohn Marino 	{
1972*e4b17023SJohn Marino 	  for (e = pb->num_geqs - 1; e >= 0; e--)
1973*e4b17023SJohn Marino 	    pb->geqs[e].coef[i] = 0;
1974*e4b17023SJohn Marino 
1975*e4b17023SJohn Marino 	  for (e = pb->num_eqs - 1; e >= 0; e--)
1976*e4b17023SJohn Marino 	    pb->eqs[e].coef[i] = 0;
1977*e4b17023SJohn Marino 
1978*e4b17023SJohn Marino 	  for (e = pb->num_subs - 1; e >= 0; e--)
1979*e4b17023SJohn Marino 	    pb->subs[e].coef[i] = 0;
1980*e4b17023SJohn Marino 	}
1981*e4b17023SJohn Marino 
1982*e4b17023SJohn Marino       pb->num_vars += m;
1983*e4b17023SJohn Marino 
1984*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
1985*e4b17023SJohn Marino 	{
1986*e4b17023SJohn Marino 	  pb->var[pb->safe_vars + 1 + e] = pb->subs[e].key;
1987*e4b17023SJohn Marino 	  omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e]),
1988*e4b17023SJohn Marino 			  pb->num_vars);
1989*e4b17023SJohn Marino 	  pb->eqs[pb->num_eqs].coef[pb->safe_vars + 1 + e] = -1;
1990*e4b17023SJohn Marino 	  pb->eqs[pb->num_eqs].color = omega_black;
1991*e4b17023SJohn Marino 
1992*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
1993*e4b17023SJohn Marino 	    {
1994*e4b17023SJohn Marino 	      fprintf (dump_file, "brought back: ");
1995*e4b17023SJohn Marino 	      omega_print_eq (dump_file, pb, &pb->eqs[pb->num_eqs]);
1996*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1997*e4b17023SJohn Marino 	    }
1998*e4b17023SJohn Marino 
1999*e4b17023SJohn Marino 	  pb->num_eqs++;
2000*e4b17023SJohn Marino 	  gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2001*e4b17023SJohn Marino 	}
2002*e4b17023SJohn Marino 
2003*e4b17023SJohn Marino       pb->safe_vars += m;
2004*e4b17023SJohn Marino       pb->num_subs = 0;
2005*e4b17023SJohn Marino 
2006*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2007*e4b17023SJohn Marino 	{
2008*e4b17023SJohn Marino 	  fprintf (dump_file, "variables brought back to life\n");
2009*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
2010*e4b17023SJohn Marino 	}
2011*e4b17023SJohn Marino 
2012*e4b17023SJohn Marino       cleanout_wildcards (pb);
2013*e4b17023SJohn Marino     }
2014*e4b17023SJohn Marino }
2015*e4b17023SJohn Marino 
2016*e4b17023SJohn Marino static inline bool
implies(unsigned int a,unsigned int b)2017*e4b17023SJohn Marino implies (unsigned int a, unsigned int b)
2018*e4b17023SJohn Marino {
2019*e4b17023SJohn Marino   return (a == (a & b));
2020*e4b17023SJohn Marino }
2021*e4b17023SJohn Marino 
2022*e4b17023SJohn Marino /* Eliminate redundant equations in PB.  When EXPENSIVE is true, an
2023*e4b17023SJohn Marino    extra step is performed.  Returns omega_false when there exist no
2024*e4b17023SJohn Marino    solution, omega_true otherwise.  */
2025*e4b17023SJohn Marino 
2026*e4b17023SJohn Marino enum omega_result
omega_eliminate_redundant(omega_pb pb,bool expensive)2027*e4b17023SJohn Marino omega_eliminate_redundant (omega_pb pb, bool expensive)
2028*e4b17023SJohn Marino {
2029*e4b17023SJohn Marino   int c, e, e1, e2, e3, p, q, i, k, alpha, alpha1, alpha2, alpha3;
2030*e4b17023SJohn Marino   bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2031*e4b17023SJohn Marino   omega_pb tmp_problem;
2032*e4b17023SJohn Marino 
2033*e4b17023SJohn Marino   /* {P,Z,N}EQS = {Positive,Zero,Negative} Equations.  */
2034*e4b17023SJohn Marino   unsigned int *peqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2035*e4b17023SJohn Marino   unsigned int *zeqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2036*e4b17023SJohn Marino   unsigned int *neqs = XNEWVEC (unsigned int, OMEGA_MAX_GEQS);
2037*e4b17023SJohn Marino 
2038*e4b17023SJohn Marino   /* PP = Possible Positives, PZ = Possible Zeros, PN = Possible Negatives */
2039*e4b17023SJohn Marino   unsigned int pp, pz, pn;
2040*e4b17023SJohn Marino 
2041*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2042*e4b17023SJohn Marino     {
2043*e4b17023SJohn Marino       fprintf (dump_file, "in eliminate Redundant:\n");
2044*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2045*e4b17023SJohn Marino     }
2046*e4b17023SJohn Marino 
2047*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2048*e4b17023SJohn Marino     {
2049*e4b17023SJohn Marino       int tmp = 1;
2050*e4b17023SJohn Marino 
2051*e4b17023SJohn Marino       is_dead[e] = false;
2052*e4b17023SJohn Marino       peqs[e] = zeqs[e] = neqs[e] = 0;
2053*e4b17023SJohn Marino 
2054*e4b17023SJohn Marino       for (i = pb->num_vars; i >= 1; i--)
2055*e4b17023SJohn Marino 	{
2056*e4b17023SJohn Marino 	  if (pb->geqs[e].coef[i] > 0)
2057*e4b17023SJohn Marino 	    peqs[e] |= tmp;
2058*e4b17023SJohn Marino 	  else if (pb->geqs[e].coef[i] < 0)
2059*e4b17023SJohn Marino 	    neqs[e] |= tmp;
2060*e4b17023SJohn Marino 	  else
2061*e4b17023SJohn Marino 	    zeqs[e] |= tmp;
2062*e4b17023SJohn Marino 
2063*e4b17023SJohn Marino 	  tmp <<= 1;
2064*e4b17023SJohn Marino 	}
2065*e4b17023SJohn Marino     }
2066*e4b17023SJohn Marino 
2067*e4b17023SJohn Marino 
2068*e4b17023SJohn Marino   for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2069*e4b17023SJohn Marino     if (!is_dead[e1])
2070*e4b17023SJohn Marino       for (e2 = e1 - 1; e2 >= 0; e2--)
2071*e4b17023SJohn Marino 	if (!is_dead[e2])
2072*e4b17023SJohn Marino 	  {
2073*e4b17023SJohn Marino 	    for (p = pb->num_vars; p > 1; p--)
2074*e4b17023SJohn Marino 	      for (q = p - 1; q > 0; q--)
2075*e4b17023SJohn Marino 		if ((alpha = pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q]
2076*e4b17023SJohn Marino 		     - pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]) != 0)
2077*e4b17023SJohn Marino 		  goto foundPQ;
2078*e4b17023SJohn Marino 
2079*e4b17023SJohn Marino 	    continue;
2080*e4b17023SJohn Marino 
2081*e4b17023SJohn Marino 	  foundPQ:
2082*e4b17023SJohn Marino 	    pz = ((zeqs[e1] & zeqs[e2]) | (peqs[e1] & neqs[e2])
2083*e4b17023SJohn Marino 		  | (neqs[e1] & peqs[e2]));
2084*e4b17023SJohn Marino 	    pp = peqs[e1] | peqs[e2];
2085*e4b17023SJohn Marino 	    pn = neqs[e1] | neqs[e2];
2086*e4b17023SJohn Marino 
2087*e4b17023SJohn Marino 	    for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2088*e4b17023SJohn Marino 	      if (e3 != e1 && e3 != e2)
2089*e4b17023SJohn Marino 		{
2090*e4b17023SJohn Marino 		  if (!implies (zeqs[e3], pz))
2091*e4b17023SJohn Marino 		    goto nextE3;
2092*e4b17023SJohn Marino 
2093*e4b17023SJohn Marino 		  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2094*e4b17023SJohn Marino 			    - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2095*e4b17023SJohn Marino 		  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2096*e4b17023SJohn Marino 			     - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2097*e4b17023SJohn Marino 		  alpha3 = alpha;
2098*e4b17023SJohn Marino 
2099*e4b17023SJohn Marino 		  if (alpha1 * alpha2 <= 0)
2100*e4b17023SJohn Marino 		    goto nextE3;
2101*e4b17023SJohn Marino 
2102*e4b17023SJohn Marino 		  if (alpha1 < 0)
2103*e4b17023SJohn Marino 		    {
2104*e4b17023SJohn Marino 		      alpha1 = -alpha1;
2105*e4b17023SJohn Marino 		      alpha2 = -alpha2;
2106*e4b17023SJohn Marino 		      alpha3 = -alpha3;
2107*e4b17023SJohn Marino 		    }
2108*e4b17023SJohn Marino 
2109*e4b17023SJohn Marino 		  if (alpha3 > 0)
2110*e4b17023SJohn Marino 		    {
2111*e4b17023SJohn Marino 		      /* Trying to prove e3 is redundant.  */
2112*e4b17023SJohn Marino 		      if (!implies (peqs[e3], pp)
2113*e4b17023SJohn Marino 			  || !implies (neqs[e3], pn))
2114*e4b17023SJohn Marino 			goto nextE3;
2115*e4b17023SJohn Marino 
2116*e4b17023SJohn Marino 		      if (pb->geqs[e3].color == omega_black
2117*e4b17023SJohn Marino 			  && (pb->geqs[e1].color == omega_red
2118*e4b17023SJohn Marino 			      || pb->geqs[e2].color == omega_red))
2119*e4b17023SJohn Marino 			goto nextE3;
2120*e4b17023SJohn Marino 
2121*e4b17023SJohn Marino 		      for (k = pb->num_vars; k >= 1; k--)
2122*e4b17023SJohn Marino 			if (alpha3 * pb->geqs[e3].coef[k]
2123*e4b17023SJohn Marino 			    != (alpha1 * pb->geqs[e1].coef[k]
2124*e4b17023SJohn Marino 				+ alpha2 * pb->geqs[e2].coef[k]))
2125*e4b17023SJohn Marino 			  goto nextE3;
2126*e4b17023SJohn Marino 
2127*e4b17023SJohn Marino 		      c = (alpha1 * pb->geqs[e1].coef[0]
2128*e4b17023SJohn Marino 			   + alpha2 * pb->geqs[e2].coef[0]);
2129*e4b17023SJohn Marino 
2130*e4b17023SJohn Marino 		      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2131*e4b17023SJohn Marino 			{
2132*e4b17023SJohn Marino 			  if (dump_file && (dump_flags & TDF_DETAILS))
2133*e4b17023SJohn Marino 			    {
2134*e4b17023SJohn Marino 			      fprintf (dump_file,
2135*e4b17023SJohn Marino 				       "found redundant inequality\n");
2136*e4b17023SJohn Marino 			      fprintf (dump_file,
2137*e4b17023SJohn Marino 				       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2138*e4b17023SJohn Marino 				       alpha1, alpha2, alpha3);
2139*e4b17023SJohn Marino 
2140*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2141*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2142*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2143*e4b17023SJohn Marino 			      fprintf (dump_file, "\n=> ");
2144*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2145*e4b17023SJohn Marino 			      fprintf (dump_file, "\n\n");
2146*e4b17023SJohn Marino 			    }
2147*e4b17023SJohn Marino 
2148*e4b17023SJohn Marino 			  is_dead[e3] = true;
2149*e4b17023SJohn Marino 			}
2150*e4b17023SJohn Marino 		    }
2151*e4b17023SJohn Marino 		  else
2152*e4b17023SJohn Marino 		    {
2153*e4b17023SJohn Marino 		      /* Trying to prove e3 <= 0 and therefore e3 = 0,
2154*e4b17023SJohn Marino 		        or trying to prove e3 < 0, and therefore the
2155*e4b17023SJohn Marino 		        problem has no solutions.  */
2156*e4b17023SJohn Marino 		      if (!implies (peqs[e3], pn)
2157*e4b17023SJohn Marino 			  || !implies (neqs[e3], pp))
2158*e4b17023SJohn Marino 			goto nextE3;
2159*e4b17023SJohn Marino 
2160*e4b17023SJohn Marino 		      if (pb->geqs[e1].color == omega_red
2161*e4b17023SJohn Marino 			  || pb->geqs[e2].color == omega_red
2162*e4b17023SJohn Marino 			  || pb->geqs[e3].color == omega_red)
2163*e4b17023SJohn Marino 			goto nextE3;
2164*e4b17023SJohn Marino 
2165*e4b17023SJohn Marino 		      /* verify alpha1*v1+alpha2*v2 = alpha3*v3 */
2166*e4b17023SJohn Marino 		      for (k = pb->num_vars; k >= 1; k--)
2167*e4b17023SJohn Marino 			if (alpha3 * pb->geqs[e3].coef[k]
2168*e4b17023SJohn Marino 			    != (alpha1 * pb->geqs[e1].coef[k]
2169*e4b17023SJohn Marino 				+ alpha2 * pb->geqs[e2].coef[k]))
2170*e4b17023SJohn Marino 			  goto nextE3;
2171*e4b17023SJohn Marino 
2172*e4b17023SJohn Marino 		      c = (alpha1 * pb->geqs[e1].coef[0]
2173*e4b17023SJohn Marino 			   + alpha2 * pb->geqs[e2].coef[0]);
2174*e4b17023SJohn Marino 
2175*e4b17023SJohn Marino 		      if (c < alpha3 * (pb->geqs[e3].coef[0]))
2176*e4b17023SJohn Marino 			{
2177*e4b17023SJohn Marino 			  /* We just proved e3 < 0, so no solutions exist.  */
2178*e4b17023SJohn Marino 			  if (dump_file && (dump_flags & TDF_DETAILS))
2179*e4b17023SJohn Marino 			    {
2180*e4b17023SJohn Marino 			      fprintf (dump_file,
2181*e4b17023SJohn Marino 				       "found implied over tight inequality\n");
2182*e4b17023SJohn Marino 			      fprintf (dump_file,
2183*e4b17023SJohn Marino 				       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2184*e4b17023SJohn Marino 				       alpha1, alpha2, -alpha3);
2185*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2186*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2187*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2188*e4b17023SJohn Marino 			      fprintf (dump_file, "\n=> not ");
2189*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2190*e4b17023SJohn Marino 			      fprintf (dump_file, "\n\n");
2191*e4b17023SJohn Marino 			    }
2192*e4b17023SJohn Marino 			  free (is_dead);
2193*e4b17023SJohn Marino 			  free (peqs);
2194*e4b17023SJohn Marino 			  free (zeqs);
2195*e4b17023SJohn Marino 			  free (neqs);
2196*e4b17023SJohn Marino 			  return omega_false;
2197*e4b17023SJohn Marino 			}
2198*e4b17023SJohn Marino 		      else if (c < alpha3 * (pb->geqs[e3].coef[0] - 1))
2199*e4b17023SJohn Marino 			{
2200*e4b17023SJohn Marino 			  /* We just proved that e3 <=0, so e3 = 0.  */
2201*e4b17023SJohn Marino 			  if (dump_file && (dump_flags & TDF_DETAILS))
2202*e4b17023SJohn Marino 			    {
2203*e4b17023SJohn Marino 			      fprintf (dump_file,
2204*e4b17023SJohn Marino 				       "found implied tight inequality\n");
2205*e4b17023SJohn Marino 			      fprintf (dump_file,
2206*e4b17023SJohn Marino 				       "alpha1, alpha2, alpha3 = %d,%d,%d\n",
2207*e4b17023SJohn Marino 				       alpha1, alpha2, -alpha3);
2208*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e1]));
2209*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2210*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2211*e4b17023SJohn Marino 			      fprintf (dump_file, "\n=> inverse ");
2212*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2213*e4b17023SJohn Marino 			      fprintf (dump_file, "\n\n");
2214*e4b17023SJohn Marino 			    }
2215*e4b17023SJohn Marino 
2216*e4b17023SJohn Marino 			  omega_copy_eqn (&pb->eqs[pb->num_eqs++],
2217*e4b17023SJohn Marino 					  &pb->geqs[e3], pb->num_vars);
2218*e4b17023SJohn Marino 			  gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2219*e4b17023SJohn Marino 			  adding_equality_constraint (pb, pb->num_eqs - 1);
2220*e4b17023SJohn Marino 			  is_dead[e3] = true;
2221*e4b17023SJohn Marino 			}
2222*e4b17023SJohn Marino 		    }
2223*e4b17023SJohn Marino 		nextE3:;
2224*e4b17023SJohn Marino 		}
2225*e4b17023SJohn Marino 	  }
2226*e4b17023SJohn Marino 
2227*e4b17023SJohn Marino   /* Delete the inequalities that were marked as dead.  */
2228*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2229*e4b17023SJohn Marino     if (is_dead[e])
2230*e4b17023SJohn Marino       omega_delete_geq (pb, e, pb->num_vars);
2231*e4b17023SJohn Marino 
2232*e4b17023SJohn Marino   if (!expensive)
2233*e4b17023SJohn Marino     goto eliminate_redundant_done;
2234*e4b17023SJohn Marino 
2235*e4b17023SJohn Marino   tmp_problem = XNEW (struct omega_pb_d);
2236*e4b17023SJohn Marino   conservative++;
2237*e4b17023SJohn Marino 
2238*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2239*e4b17023SJohn Marino     {
2240*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2241*e4b17023SJohn Marino 	{
2242*e4b17023SJohn Marino 	  fprintf (dump_file,
2243*e4b17023SJohn Marino 		   "checking equation %d to see if it is redundant: ", e);
2244*e4b17023SJohn Marino 	  omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2245*e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
2246*e4b17023SJohn Marino 	}
2247*e4b17023SJohn Marino 
2248*e4b17023SJohn Marino       omega_copy_problem (tmp_problem, pb);
2249*e4b17023SJohn Marino       omega_negate_geq (tmp_problem, e);
2250*e4b17023SJohn Marino       tmp_problem->safe_vars = 0;
2251*e4b17023SJohn Marino       tmp_problem->variables_freed = false;
2252*e4b17023SJohn Marino 
2253*e4b17023SJohn Marino       if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2254*e4b17023SJohn Marino 	omega_delete_geq (pb, e, pb->num_vars);
2255*e4b17023SJohn Marino     }
2256*e4b17023SJohn Marino 
2257*e4b17023SJohn Marino   free (tmp_problem);
2258*e4b17023SJohn Marino   conservative--;
2259*e4b17023SJohn Marino 
2260*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
2261*e4b17023SJohn Marino     {
2262*e4b17023SJohn Marino       resurrect_subs (pb);
2263*e4b17023SJohn Marino       gcc_assert (please_no_equalities_in_simplified_problems
2264*e4b17023SJohn Marino 		  || pb->num_subs == 0);
2265*e4b17023SJohn Marino     }
2266*e4b17023SJohn Marino 
2267*e4b17023SJohn Marino  eliminate_redundant_done:
2268*e4b17023SJohn Marino   free (is_dead);
2269*e4b17023SJohn Marino   free (peqs);
2270*e4b17023SJohn Marino   free (zeqs);
2271*e4b17023SJohn Marino   free (neqs);
2272*e4b17023SJohn Marino   return omega_true;
2273*e4b17023SJohn Marino }
2274*e4b17023SJohn Marino 
2275*e4b17023SJohn Marino /* For each inequality that has coefficients bigger than 20, try to
2276*e4b17023SJohn Marino    create a new constraint that cannot be derived from the original
2277*e4b17023SJohn Marino    constraint and that has smaller coefficients.  Add the new
2278*e4b17023SJohn Marino    constraint at the end of geqs.  Return the number of inequalities
2279*e4b17023SJohn Marino    that have been added to PB.  */
2280*e4b17023SJohn Marino 
2281*e4b17023SJohn Marino static int
smooth_weird_equations(omega_pb pb)2282*e4b17023SJohn Marino smooth_weird_equations (omega_pb pb)
2283*e4b17023SJohn Marino {
2284*e4b17023SJohn Marino   int e1, e2, e3, p, q, k, alpha, alpha1, alpha2, alpha3;
2285*e4b17023SJohn Marino   int c;
2286*e4b17023SJohn Marino   int v;
2287*e4b17023SJohn Marino   int result = 0;
2288*e4b17023SJohn Marino 
2289*e4b17023SJohn Marino   for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
2290*e4b17023SJohn Marino     if (pb->geqs[e1].color == omega_black)
2291*e4b17023SJohn Marino       {
2292*e4b17023SJohn Marino 	int g = 999999;
2293*e4b17023SJohn Marino 
2294*e4b17023SJohn Marino 	for (v = pb->num_vars; v >= 1; v--)
2295*e4b17023SJohn Marino 	  if (pb->geqs[e1].coef[v] != 0 && abs (pb->geqs[e1].coef[v]) < g)
2296*e4b17023SJohn Marino 	    g = abs (pb->geqs[e1].coef[v]);
2297*e4b17023SJohn Marino 
2298*e4b17023SJohn Marino 	/* Magic number.  */
2299*e4b17023SJohn Marino 	if (g > 20)
2300*e4b17023SJohn Marino 	  {
2301*e4b17023SJohn Marino 	    e3 = pb->num_geqs;
2302*e4b17023SJohn Marino 
2303*e4b17023SJohn Marino 	    for (v = pb->num_vars; v >= 1; v--)
2304*e4b17023SJohn Marino 	      pb->geqs[e3].coef[v] = int_div (6 * pb->geqs[e1].coef[v] + g / 2,
2305*e4b17023SJohn Marino 					      g);
2306*e4b17023SJohn Marino 
2307*e4b17023SJohn Marino 	    pb->geqs[e3].color = omega_black;
2308*e4b17023SJohn Marino 	    pb->geqs[e3].touched = 1;
2309*e4b17023SJohn Marino 	    /* Magic number.  */
2310*e4b17023SJohn Marino 	    pb->geqs[e3].coef[0] = 9997;
2311*e4b17023SJohn Marino 
2312*e4b17023SJohn Marino 	    if (dump_file && (dump_flags & TDF_DETAILS))
2313*e4b17023SJohn Marino 	      {
2314*e4b17023SJohn Marino 		fprintf (dump_file, "Checking to see if we can derive: ");
2315*e4b17023SJohn Marino 		omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2316*e4b17023SJohn Marino 		fprintf (dump_file, "\n from: ");
2317*e4b17023SJohn Marino 		omega_print_geq (dump_file, pb, &pb->geqs[e1]);
2318*e4b17023SJohn Marino 		fprintf (dump_file, "\n");
2319*e4b17023SJohn Marino 	      }
2320*e4b17023SJohn Marino 
2321*e4b17023SJohn Marino 	    for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
2322*e4b17023SJohn Marino 	      if (e1 != e2 && pb->geqs[e2].color == omega_black)
2323*e4b17023SJohn Marino 		{
2324*e4b17023SJohn Marino 		  for (p = pb->num_vars; p > 1; p--)
2325*e4b17023SJohn Marino 		    {
2326*e4b17023SJohn Marino 		      for (q = p - 1; q > 0; q--)
2327*e4b17023SJohn Marino 			{
2328*e4b17023SJohn Marino 			  alpha =
2329*e4b17023SJohn Marino 			    (pb->geqs[e1].coef[p] * pb->geqs[e2].coef[q] -
2330*e4b17023SJohn Marino 			     pb->geqs[e2].coef[p] * pb->geqs[e1].coef[q]);
2331*e4b17023SJohn Marino 			  if (alpha != 0)
2332*e4b17023SJohn Marino 			    goto foundPQ;
2333*e4b17023SJohn Marino 			}
2334*e4b17023SJohn Marino 		    }
2335*e4b17023SJohn Marino 		  continue;
2336*e4b17023SJohn Marino 
2337*e4b17023SJohn Marino 		foundPQ:
2338*e4b17023SJohn Marino 
2339*e4b17023SJohn Marino 		  alpha1 = (pb->geqs[e2].coef[q] * pb->geqs[e3].coef[p]
2340*e4b17023SJohn Marino 			    - pb->geqs[e2].coef[p] * pb->geqs[e3].coef[q]);
2341*e4b17023SJohn Marino 		  alpha2 = -(pb->geqs[e1].coef[q] * pb->geqs[e3].coef[p]
2342*e4b17023SJohn Marino 			     - pb->geqs[e1].coef[p] * pb->geqs[e3].coef[q]);
2343*e4b17023SJohn Marino 		  alpha3 = alpha;
2344*e4b17023SJohn Marino 
2345*e4b17023SJohn Marino 		  if (alpha1 * alpha2 <= 0)
2346*e4b17023SJohn Marino 		    continue;
2347*e4b17023SJohn Marino 
2348*e4b17023SJohn Marino 		  if (alpha1 < 0)
2349*e4b17023SJohn Marino 		    {
2350*e4b17023SJohn Marino 		      alpha1 = -alpha1;
2351*e4b17023SJohn Marino 		      alpha2 = -alpha2;
2352*e4b17023SJohn Marino 		      alpha3 = -alpha3;
2353*e4b17023SJohn Marino 		    }
2354*e4b17023SJohn Marino 
2355*e4b17023SJohn Marino 		  if (alpha3 > 0)
2356*e4b17023SJohn Marino 		    {
2357*e4b17023SJohn Marino 		      /* Try to prove e3 is redundant: verify
2358*e4b17023SJohn Marino 			 alpha1*v1 + alpha2*v2 = alpha3*v3.  */
2359*e4b17023SJohn Marino 		      for (k = pb->num_vars; k >= 1; k--)
2360*e4b17023SJohn Marino 			if (alpha3 * pb->geqs[e3].coef[k]
2361*e4b17023SJohn Marino 			    != (alpha1 * pb->geqs[e1].coef[k]
2362*e4b17023SJohn Marino 				+ alpha2 * pb->geqs[e2].coef[k]))
2363*e4b17023SJohn Marino 			  goto nextE2;
2364*e4b17023SJohn Marino 
2365*e4b17023SJohn Marino 		      c = alpha1 * pb->geqs[e1].coef[0]
2366*e4b17023SJohn Marino 			+ alpha2 * pb->geqs[e2].coef[0];
2367*e4b17023SJohn Marino 
2368*e4b17023SJohn Marino 		      if (c < alpha3 * (pb->geqs[e3].coef[0] + 1))
2369*e4b17023SJohn Marino 			pb->geqs[e3].coef[0] = int_div (c, alpha3);
2370*e4b17023SJohn Marino 		    }
2371*e4b17023SJohn Marino 		nextE2:;
2372*e4b17023SJohn Marino 		}
2373*e4b17023SJohn Marino 
2374*e4b17023SJohn Marino 	    if (pb->geqs[e3].coef[0] < 9997)
2375*e4b17023SJohn Marino 	      {
2376*e4b17023SJohn Marino 		result++;
2377*e4b17023SJohn Marino 		pb->num_geqs++;
2378*e4b17023SJohn Marino 
2379*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
2380*e4b17023SJohn Marino 		  {
2381*e4b17023SJohn Marino 		    fprintf (dump_file,
2382*e4b17023SJohn Marino 			     "Smoothing weird equations; adding:\n");
2383*e4b17023SJohn Marino 		    omega_print_geq (dump_file, pb, &pb->geqs[e3]);
2384*e4b17023SJohn Marino 		    fprintf (dump_file, "\nto:\n");
2385*e4b17023SJohn Marino 		    omega_print_problem (dump_file, pb);
2386*e4b17023SJohn Marino 		    fprintf (dump_file, "\n\n");
2387*e4b17023SJohn Marino 		  }
2388*e4b17023SJohn Marino 	      }
2389*e4b17023SJohn Marino 	  }
2390*e4b17023SJohn Marino       }
2391*e4b17023SJohn Marino   return result;
2392*e4b17023SJohn Marino }
2393*e4b17023SJohn Marino 
2394*e4b17023SJohn Marino /* Replace tuples of inequalities, that define upper and lower half
2395*e4b17023SJohn Marino    spaces, with an equation.  */
2396*e4b17023SJohn Marino 
2397*e4b17023SJohn Marino static void
coalesce(omega_pb pb)2398*e4b17023SJohn Marino coalesce (omega_pb pb)
2399*e4b17023SJohn Marino {
2400*e4b17023SJohn Marino   int e, e2;
2401*e4b17023SJohn Marino   int colors = 0;
2402*e4b17023SJohn Marino   bool *is_dead;
2403*e4b17023SJohn Marino   int found_something = 0;
2404*e4b17023SJohn Marino 
2405*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
2406*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
2407*e4b17023SJohn Marino       colors++;
2408*e4b17023SJohn Marino 
2409*e4b17023SJohn Marino   if (colors < 2)
2410*e4b17023SJohn Marino     return;
2411*e4b17023SJohn Marino 
2412*e4b17023SJohn Marino   is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2413*e4b17023SJohn Marino 
2414*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
2415*e4b17023SJohn Marino     is_dead[e] = false;
2416*e4b17023SJohn Marino 
2417*e4b17023SJohn Marino   for (e = 0; e < pb->num_geqs; e++)
2418*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red
2419*e4b17023SJohn Marino 	&& !pb->geqs[e].touched)
2420*e4b17023SJohn Marino       for (e2 = e + 1; e2 < pb->num_geqs; e2++)
2421*e4b17023SJohn Marino 	if (!pb->geqs[e2].touched
2422*e4b17023SJohn Marino 	    && pb->geqs[e].key == -pb->geqs[e2].key
2423*e4b17023SJohn Marino 	    && pb->geqs[e].coef[0] == -pb->geqs[e2].coef[0]
2424*e4b17023SJohn Marino 	    && pb->geqs[e2].color == omega_red)
2425*e4b17023SJohn Marino 	  {
2426*e4b17023SJohn Marino 	    omega_copy_eqn (&pb->eqs[pb->num_eqs++], &pb->geqs[e],
2427*e4b17023SJohn Marino 			    pb->num_vars);
2428*e4b17023SJohn Marino 	    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
2429*e4b17023SJohn Marino 	    found_something++;
2430*e4b17023SJohn Marino 	    is_dead[e] = true;
2431*e4b17023SJohn Marino 	    is_dead[e2] = true;
2432*e4b17023SJohn Marino 	  }
2433*e4b17023SJohn Marino 
2434*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2435*e4b17023SJohn Marino     if (is_dead[e])
2436*e4b17023SJohn Marino       omega_delete_geq (pb, e, pb->num_vars);
2437*e4b17023SJohn Marino 
2438*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS) && found_something)
2439*e4b17023SJohn Marino     {
2440*e4b17023SJohn Marino       fprintf (dump_file, "Coalesced pb->geqs into %d EQ's:\n",
2441*e4b17023SJohn Marino 	       found_something);
2442*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2443*e4b17023SJohn Marino     }
2444*e4b17023SJohn Marino 
2445*e4b17023SJohn Marino   free (is_dead);
2446*e4b17023SJohn Marino }
2447*e4b17023SJohn Marino 
2448*e4b17023SJohn Marino /* Eliminate red inequalities from PB.  When ELIMINATE_ALL is
2449*e4b17023SJohn Marino    true, continue to eliminate all the red inequalities.  */
2450*e4b17023SJohn Marino 
2451*e4b17023SJohn Marino void
omega_eliminate_red(omega_pb pb,bool eliminate_all)2452*e4b17023SJohn Marino omega_eliminate_red (omega_pb pb, bool eliminate_all)
2453*e4b17023SJohn Marino {
2454*e4b17023SJohn Marino   int e, e2, e3, i, j, k, a, alpha1, alpha2;
2455*e4b17023SJohn Marino   int c = 0;
2456*e4b17023SJohn Marino   bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
2457*e4b17023SJohn Marino   int dead_count = 0;
2458*e4b17023SJohn Marino   int red_found;
2459*e4b17023SJohn Marino   omega_pb tmp_problem;
2460*e4b17023SJohn Marino 
2461*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2462*e4b17023SJohn Marino     {
2463*e4b17023SJohn Marino       fprintf (dump_file, "in eliminate RED:\n");
2464*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2465*e4b17023SJohn Marino     }
2466*e4b17023SJohn Marino 
2467*e4b17023SJohn Marino   if (pb->num_eqs > 0)
2468*e4b17023SJohn Marino     omega_simplify_problem (pb);
2469*e4b17023SJohn Marino 
2470*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2471*e4b17023SJohn Marino     is_dead[e] = false;
2472*e4b17023SJohn Marino 
2473*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2474*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_black && !is_dead[e])
2475*e4b17023SJohn Marino       for (e2 = e - 1; e2 >= 0; e2--)
2476*e4b17023SJohn Marino 	if (pb->geqs[e2].color == omega_black
2477*e4b17023SJohn Marino 	    && !is_dead[e2])
2478*e4b17023SJohn Marino 	  {
2479*e4b17023SJohn Marino 	    a = 0;
2480*e4b17023SJohn Marino 
2481*e4b17023SJohn Marino 	    for (i = pb->num_vars; i > 1; i--)
2482*e4b17023SJohn Marino 	      for (j = i - 1; j > 0; j--)
2483*e4b17023SJohn Marino 		if ((a = (pb->geqs[e].coef[i] * pb->geqs[e2].coef[j]
2484*e4b17023SJohn Marino 			  - pb->geqs[e2].coef[i] * pb->geqs[e].coef[j])) != 0)
2485*e4b17023SJohn Marino 		  goto found_pair;
2486*e4b17023SJohn Marino 
2487*e4b17023SJohn Marino 	    continue;
2488*e4b17023SJohn Marino 
2489*e4b17023SJohn Marino 	  found_pair:
2490*e4b17023SJohn Marino 	    if (dump_file && (dump_flags & TDF_DETAILS))
2491*e4b17023SJohn Marino 	      {
2492*e4b17023SJohn Marino 		fprintf (dump_file,
2493*e4b17023SJohn Marino 			 "found two equations to combine, i = %s, ",
2494*e4b17023SJohn Marino 			 omega_variable_to_str (pb, i));
2495*e4b17023SJohn Marino 		fprintf (dump_file, "j = %s, alpha = %d\n",
2496*e4b17023SJohn Marino 			 omega_variable_to_str (pb, j), a);
2497*e4b17023SJohn Marino 		omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2498*e4b17023SJohn Marino 		fprintf (dump_file, "\n");
2499*e4b17023SJohn Marino 		omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2500*e4b17023SJohn Marino 		fprintf (dump_file, "\n");
2501*e4b17023SJohn Marino 	      }
2502*e4b17023SJohn Marino 
2503*e4b17023SJohn Marino 	    for (e3 = pb->num_geqs - 1; e3 >= 0; e3--)
2504*e4b17023SJohn Marino 	      if (pb->geqs[e3].color == omega_red)
2505*e4b17023SJohn Marino 		{
2506*e4b17023SJohn Marino 		  alpha1 = (pb->geqs[e2].coef[j] * pb->geqs[e3].coef[i]
2507*e4b17023SJohn Marino 			    - pb->geqs[e2].coef[i] * pb->geqs[e3].coef[j]);
2508*e4b17023SJohn Marino 		  alpha2 = -(pb->geqs[e].coef[j] * pb->geqs[e3].coef[i]
2509*e4b17023SJohn Marino 			     - pb->geqs[e].coef[i] * pb->geqs[e3].coef[j]);
2510*e4b17023SJohn Marino 
2511*e4b17023SJohn Marino 		  if ((a > 0 && alpha1 > 0 && alpha2 > 0)
2512*e4b17023SJohn Marino 		      || (a < 0 && alpha1 < 0 && alpha2 < 0))
2513*e4b17023SJohn Marino 		    {
2514*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
2515*e4b17023SJohn Marino 			{
2516*e4b17023SJohn Marino 			  fprintf (dump_file,
2517*e4b17023SJohn Marino 				   "alpha1 = %d, alpha2 = %d;"
2518*e4b17023SJohn Marino 				   "comparing against: ",
2519*e4b17023SJohn Marino 				   alpha1, alpha2);
2520*e4b17023SJohn Marino 			  omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2521*e4b17023SJohn Marino 			  fprintf (dump_file, "\n");
2522*e4b17023SJohn Marino 			}
2523*e4b17023SJohn Marino 
2524*e4b17023SJohn Marino 		      for (k = pb->num_vars; k >= 0; k--)
2525*e4b17023SJohn Marino 			{
2526*e4b17023SJohn Marino 			  c = (alpha1 * pb->geqs[e].coef[k]
2527*e4b17023SJohn Marino 			       + alpha2 * pb->geqs[e2].coef[k]);
2528*e4b17023SJohn Marino 
2529*e4b17023SJohn Marino 			  if (c != a * pb->geqs[e3].coef[k])
2530*e4b17023SJohn Marino 			    break;
2531*e4b17023SJohn Marino 
2532*e4b17023SJohn Marino 			  if (dump_file && (dump_flags & TDF_DETAILS) && k > 0)
2533*e4b17023SJohn Marino 			    fprintf (dump_file, " %s: %d, %d\n",
2534*e4b17023SJohn Marino 				     omega_variable_to_str (pb, k), c,
2535*e4b17023SJohn Marino 				     a * pb->geqs[e3].coef[k]);
2536*e4b17023SJohn Marino 			}
2537*e4b17023SJohn Marino 
2538*e4b17023SJohn Marino 		      if (k < 0
2539*e4b17023SJohn Marino 			  || (k == 0 &&
2540*e4b17023SJohn Marino 			      ((a > 0 && c < a * pb->geqs[e3].coef[k])
2541*e4b17023SJohn Marino 			       || (a < 0 && c > a * pb->geqs[e3].coef[k]))))
2542*e4b17023SJohn Marino 			{
2543*e4b17023SJohn Marino 			  if (dump_file && (dump_flags & TDF_DETAILS))
2544*e4b17023SJohn Marino 			    {
2545*e4b17023SJohn Marino 			      dead_count++;
2546*e4b17023SJohn Marino 			      fprintf (dump_file,
2547*e4b17023SJohn Marino 				       "red equation#%d is dead "
2548*e4b17023SJohn Marino 				       "(%d dead so far, %d remain)\n",
2549*e4b17023SJohn Marino 				       e3, dead_count,
2550*e4b17023SJohn Marino 				       pb->num_geqs - dead_count);
2551*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2552*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2553*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e2]));
2554*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2555*e4b17023SJohn Marino 			      omega_print_geq (dump_file, pb, &(pb->geqs[e3]));
2556*e4b17023SJohn Marino 			      fprintf (dump_file, "\n");
2557*e4b17023SJohn Marino 			    }
2558*e4b17023SJohn Marino 			  is_dead[e3] = true;
2559*e4b17023SJohn Marino 			}
2560*e4b17023SJohn Marino 		    }
2561*e4b17023SJohn Marino 		}
2562*e4b17023SJohn Marino 	  }
2563*e4b17023SJohn Marino 
2564*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2565*e4b17023SJohn Marino     if (is_dead[e])
2566*e4b17023SJohn Marino       omega_delete_geq (pb, e, pb->num_vars);
2567*e4b17023SJohn Marino 
2568*e4b17023SJohn Marino   free (is_dead);
2569*e4b17023SJohn Marino 
2570*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2571*e4b17023SJohn Marino     {
2572*e4b17023SJohn Marino       fprintf (dump_file, "in eliminate RED, easy tests done:\n");
2573*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2574*e4b17023SJohn Marino     }
2575*e4b17023SJohn Marino 
2576*e4b17023SJohn Marino   for (red_found = 0, e = pb->num_geqs - 1; e >= 0; e--)
2577*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
2578*e4b17023SJohn Marino       red_found = 1;
2579*e4b17023SJohn Marino 
2580*e4b17023SJohn Marino   if (!red_found)
2581*e4b17023SJohn Marino     {
2582*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2583*e4b17023SJohn Marino 	fprintf (dump_file, "fast checks worked\n");
2584*e4b17023SJohn Marino 
2585*e4b17023SJohn Marino       if (!omega_reduce_with_subs)
2586*e4b17023SJohn Marino 	gcc_assert (please_no_equalities_in_simplified_problems
2587*e4b17023SJohn Marino 		    || pb->num_subs == 0);
2588*e4b17023SJohn Marino 
2589*e4b17023SJohn Marino       return;
2590*e4b17023SJohn Marino     }
2591*e4b17023SJohn Marino 
2592*e4b17023SJohn Marino   if (!omega_verify_simplification
2593*e4b17023SJohn Marino       && verify_omega_pb (pb) == omega_false)
2594*e4b17023SJohn Marino     return;
2595*e4b17023SJohn Marino 
2596*e4b17023SJohn Marino   conservative++;
2597*e4b17023SJohn Marino   tmp_problem = XNEW (struct omega_pb_d);
2598*e4b17023SJohn Marino 
2599*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2600*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
2601*e4b17023SJohn Marino       {
2602*e4b17023SJohn Marino 	if (dump_file && (dump_flags & TDF_DETAILS))
2603*e4b17023SJohn Marino 	  {
2604*e4b17023SJohn Marino 	    fprintf (dump_file,
2605*e4b17023SJohn Marino 		     "checking equation %d to see if it is redundant: ", e);
2606*e4b17023SJohn Marino 	    omega_print_geq (dump_file, pb, &(pb->geqs[e]));
2607*e4b17023SJohn Marino 	    fprintf (dump_file, "\n");
2608*e4b17023SJohn Marino 	  }
2609*e4b17023SJohn Marino 
2610*e4b17023SJohn Marino 	omega_copy_problem (tmp_problem, pb);
2611*e4b17023SJohn Marino 	omega_negate_geq (tmp_problem, e);
2612*e4b17023SJohn Marino 	tmp_problem->safe_vars = 0;
2613*e4b17023SJohn Marino 	tmp_problem->variables_freed = false;
2614*e4b17023SJohn Marino 	tmp_problem->num_subs = 0;
2615*e4b17023SJohn Marino 
2616*e4b17023SJohn Marino 	if (omega_solve_problem (tmp_problem, omega_false) == omega_false)
2617*e4b17023SJohn Marino 	  {
2618*e4b17023SJohn Marino 	    if (dump_file && (dump_flags & TDF_DETAILS))
2619*e4b17023SJohn Marino 	      fprintf (dump_file, "it is redundant\n");
2620*e4b17023SJohn Marino 	    omega_delete_geq (pb, e, pb->num_vars);
2621*e4b17023SJohn Marino 	  }
2622*e4b17023SJohn Marino 	else
2623*e4b17023SJohn Marino 	  {
2624*e4b17023SJohn Marino 	    if (dump_file && (dump_flags & TDF_DETAILS))
2625*e4b17023SJohn Marino 	      fprintf (dump_file, "it is not redundant\n");
2626*e4b17023SJohn Marino 
2627*e4b17023SJohn Marino 	    if (!eliminate_all)
2628*e4b17023SJohn Marino 	      {
2629*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
2630*e4b17023SJohn Marino 		  fprintf (dump_file, "no need to check other red equations\n");
2631*e4b17023SJohn Marino 		break;
2632*e4b17023SJohn Marino 	      }
2633*e4b17023SJohn Marino 	  }
2634*e4b17023SJohn Marino       }
2635*e4b17023SJohn Marino 
2636*e4b17023SJohn Marino   conservative--;
2637*e4b17023SJohn Marino   free (tmp_problem);
2638*e4b17023SJohn Marino   /* omega_simplify_problem (pb); */
2639*e4b17023SJohn Marino 
2640*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
2641*e4b17023SJohn Marino     gcc_assert (please_no_equalities_in_simplified_problems
2642*e4b17023SJohn Marino 		|| pb->num_subs == 0);
2643*e4b17023SJohn Marino }
2644*e4b17023SJohn Marino 
2645*e4b17023SJohn Marino /* Transform some wildcard variables to non-safe variables.  */
2646*e4b17023SJohn Marino 
2647*e4b17023SJohn Marino static void
chain_unprotect(omega_pb pb)2648*e4b17023SJohn Marino chain_unprotect (omega_pb pb)
2649*e4b17023SJohn Marino {
2650*e4b17023SJohn Marino   int i, e;
2651*e4b17023SJohn Marino   bool *unprotect = XNEWVEC (bool, OMEGA_MAX_VARS);
2652*e4b17023SJohn Marino 
2653*e4b17023SJohn Marino   for (i = 1; omega_safe_var_p (pb, i); i++)
2654*e4b17023SJohn Marino     {
2655*e4b17023SJohn Marino       unprotect[i] = omega_wildcard_p (pb, i);
2656*e4b17023SJohn Marino 
2657*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
2658*e4b17023SJohn Marino 	if (pb->subs[e].coef[i])
2659*e4b17023SJohn Marino 	  unprotect[i] = false;
2660*e4b17023SJohn Marino     }
2661*e4b17023SJohn Marino 
2662*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2663*e4b17023SJohn Marino     {
2664*e4b17023SJohn Marino       fprintf (dump_file, "Doing chain reaction unprotection\n");
2665*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2666*e4b17023SJohn Marino 
2667*e4b17023SJohn Marino       for (i = 1; omega_safe_var_p (pb, i); i++)
2668*e4b17023SJohn Marino 	if (unprotect[i])
2669*e4b17023SJohn Marino 	  fprintf (dump_file, "unprotecting %s\n",
2670*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i));
2671*e4b17023SJohn Marino     }
2672*e4b17023SJohn Marino 
2673*e4b17023SJohn Marino   for (i = 1; omega_safe_var_p (pb, i); i++)
2674*e4b17023SJohn Marino     if (unprotect[i])
2675*e4b17023SJohn Marino       omega_unprotect_1 (pb, &i, unprotect);
2676*e4b17023SJohn Marino 
2677*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2678*e4b17023SJohn Marino     {
2679*e4b17023SJohn Marino       fprintf (dump_file, "After chain reactions\n");
2680*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2681*e4b17023SJohn Marino     }
2682*e4b17023SJohn Marino 
2683*e4b17023SJohn Marino   free (unprotect);
2684*e4b17023SJohn Marino }
2685*e4b17023SJohn Marino 
2686*e4b17023SJohn Marino /* Reduce problem PB.  */
2687*e4b17023SJohn Marino 
2688*e4b17023SJohn Marino static void
omega_problem_reduced(omega_pb pb)2689*e4b17023SJohn Marino omega_problem_reduced (omega_pb pb)
2690*e4b17023SJohn Marino {
2691*e4b17023SJohn Marino   if (omega_verify_simplification
2692*e4b17023SJohn Marino       && !in_approximate_mode
2693*e4b17023SJohn Marino       && verify_omega_pb (pb) == omega_false)
2694*e4b17023SJohn Marino     return;
2695*e4b17023SJohn Marino 
2696*e4b17023SJohn Marino   if (PARAM_VALUE (PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS)
2697*e4b17023SJohn Marino       && !omega_eliminate_redundant (pb, true))
2698*e4b17023SJohn Marino     return;
2699*e4b17023SJohn Marino 
2700*e4b17023SJohn Marino   omega_found_reduction = omega_true;
2701*e4b17023SJohn Marino 
2702*e4b17023SJohn Marino   if (!please_no_equalities_in_simplified_problems)
2703*e4b17023SJohn Marino     coalesce (pb);
2704*e4b17023SJohn Marino 
2705*e4b17023SJohn Marino   if (omega_reduce_with_subs
2706*e4b17023SJohn Marino       || please_no_equalities_in_simplified_problems)
2707*e4b17023SJohn Marino     chain_unprotect (pb);
2708*e4b17023SJohn Marino   else
2709*e4b17023SJohn Marino     resurrect_subs (pb);
2710*e4b17023SJohn Marino 
2711*e4b17023SJohn Marino   if (!return_single_result)
2712*e4b17023SJohn Marino     {
2713*e4b17023SJohn Marino       int i;
2714*e4b17023SJohn Marino 
2715*e4b17023SJohn Marino       for (i = 1; omega_safe_var_p (pb, i); i++)
2716*e4b17023SJohn Marino 	pb->forwarding_address[pb->var[i]] = i;
2717*e4b17023SJohn Marino 
2718*e4b17023SJohn Marino       for (i = 0; i < pb->num_subs; i++)
2719*e4b17023SJohn Marino 	pb->forwarding_address[pb->subs[i].key] = -i - 1;
2720*e4b17023SJohn Marino 
2721*e4b17023SJohn Marino       (*omega_when_reduced) (pb);
2722*e4b17023SJohn Marino     }
2723*e4b17023SJohn Marino 
2724*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2725*e4b17023SJohn Marino     {
2726*e4b17023SJohn Marino       fprintf (dump_file, "-------------------------------------------\n");
2727*e4b17023SJohn Marino       fprintf (dump_file, "problem reduced:\n");
2728*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2729*e4b17023SJohn Marino       fprintf (dump_file, "-------------------------------------------\n");
2730*e4b17023SJohn Marino     }
2731*e4b17023SJohn Marino }
2732*e4b17023SJohn Marino 
2733*e4b17023SJohn Marino /* Eliminates all the free variables for problem PB, that is all the
2734*e4b17023SJohn Marino    variables from FV to PB->NUM_VARS.  */
2735*e4b17023SJohn Marino 
2736*e4b17023SJohn Marino static void
omega_free_eliminations(omega_pb pb,int fv)2737*e4b17023SJohn Marino omega_free_eliminations (omega_pb pb, int fv)
2738*e4b17023SJohn Marino {
2739*e4b17023SJohn Marino   bool try_again = true;
2740*e4b17023SJohn Marino   int i, e, e2;
2741*e4b17023SJohn Marino   int n_vars = pb->num_vars;
2742*e4b17023SJohn Marino 
2743*e4b17023SJohn Marino   while (try_again)
2744*e4b17023SJohn Marino     {
2745*e4b17023SJohn Marino       try_again = false;
2746*e4b17023SJohn Marino 
2747*e4b17023SJohn Marino       for (i = n_vars; i > fv; i--)
2748*e4b17023SJohn Marino 	{
2749*e4b17023SJohn Marino 	  for (e = pb->num_geqs - 1; e >= 0; e--)
2750*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[i])
2751*e4b17023SJohn Marino 	      break;
2752*e4b17023SJohn Marino 
2753*e4b17023SJohn Marino 	  if (e < 0)
2754*e4b17023SJohn Marino 	    e2 = e;
2755*e4b17023SJohn Marino 	  else if (pb->geqs[e].coef[i] > 0)
2756*e4b17023SJohn Marino 	    {
2757*e4b17023SJohn Marino 	      for (e2 = e - 1; e2 >= 0; e2--)
2758*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[i] < 0)
2759*e4b17023SJohn Marino 		  break;
2760*e4b17023SJohn Marino 	    }
2761*e4b17023SJohn Marino 	  else
2762*e4b17023SJohn Marino 	    {
2763*e4b17023SJohn Marino 	      for (e2 = e - 1; e2 >= 0; e2--)
2764*e4b17023SJohn Marino 		if (pb->geqs[e2].coef[i] > 0)
2765*e4b17023SJohn Marino 		  break;
2766*e4b17023SJohn Marino 	    }
2767*e4b17023SJohn Marino 
2768*e4b17023SJohn Marino 	  if (e2 < 0)
2769*e4b17023SJohn Marino 	    {
2770*e4b17023SJohn Marino 	      int e3;
2771*e4b17023SJohn Marino 	      for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2772*e4b17023SJohn Marino 		if (pb->subs[e3].coef[i])
2773*e4b17023SJohn Marino 		  break;
2774*e4b17023SJohn Marino 
2775*e4b17023SJohn Marino 	      if (e3 >= 0)
2776*e4b17023SJohn Marino 		continue;
2777*e4b17023SJohn Marino 
2778*e4b17023SJohn Marino 	      for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2779*e4b17023SJohn Marino 		if (pb->eqs[e3].coef[i])
2780*e4b17023SJohn Marino 		  break;
2781*e4b17023SJohn Marino 
2782*e4b17023SJohn Marino 	      if (e3 >= 0)
2783*e4b17023SJohn Marino 		continue;
2784*e4b17023SJohn Marino 
2785*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
2786*e4b17023SJohn Marino 		fprintf (dump_file, "a free elimination of %s\n",
2787*e4b17023SJohn Marino 			 omega_variable_to_str (pb, i));
2788*e4b17023SJohn Marino 
2789*e4b17023SJohn Marino 	      if (e >= 0)
2790*e4b17023SJohn Marino 		{
2791*e4b17023SJohn Marino 		  omega_delete_geq (pb, e, n_vars);
2792*e4b17023SJohn Marino 
2793*e4b17023SJohn Marino 		  for (e--; e >= 0; e--)
2794*e4b17023SJohn Marino 		    if (pb->geqs[e].coef[i])
2795*e4b17023SJohn Marino 		      omega_delete_geq (pb, e, n_vars);
2796*e4b17023SJohn Marino 
2797*e4b17023SJohn Marino 		  try_again = (i < n_vars);
2798*e4b17023SJohn Marino 		}
2799*e4b17023SJohn Marino 
2800*e4b17023SJohn Marino 	      omega_delete_variable (pb, i);
2801*e4b17023SJohn Marino 	      n_vars = pb->num_vars;
2802*e4b17023SJohn Marino 	    }
2803*e4b17023SJohn Marino 	}
2804*e4b17023SJohn Marino     }
2805*e4b17023SJohn Marino 
2806*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2807*e4b17023SJohn Marino     {
2808*e4b17023SJohn Marino       fprintf (dump_file, "\nafter free eliminations:\n");
2809*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2810*e4b17023SJohn Marino       fprintf (dump_file, "\n");
2811*e4b17023SJohn Marino     }
2812*e4b17023SJohn Marino }
2813*e4b17023SJohn Marino 
2814*e4b17023SJohn Marino /* Do free red eliminations.  */
2815*e4b17023SJohn Marino 
2816*e4b17023SJohn Marino static void
free_red_eliminations(omega_pb pb)2817*e4b17023SJohn Marino free_red_eliminations (omega_pb pb)
2818*e4b17023SJohn Marino {
2819*e4b17023SJohn Marino   bool try_again = true;
2820*e4b17023SJohn Marino   int i, e, e2;
2821*e4b17023SJohn Marino   int n_vars = pb->num_vars;
2822*e4b17023SJohn Marino   bool *is_red_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2823*e4b17023SJohn Marino   bool *is_dead_var = XNEWVEC (bool, OMEGA_MAX_VARS);
2824*e4b17023SJohn Marino   bool *is_dead_geq = XNEWVEC (bool, OMEGA_MAX_GEQS);
2825*e4b17023SJohn Marino 
2826*e4b17023SJohn Marino   for (i = n_vars; i > 0; i--)
2827*e4b17023SJohn Marino     {
2828*e4b17023SJohn Marino       is_red_var[i] = false;
2829*e4b17023SJohn Marino       is_dead_var[i] = false;
2830*e4b17023SJohn Marino     }
2831*e4b17023SJohn Marino 
2832*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2833*e4b17023SJohn Marino     {
2834*e4b17023SJohn Marino       is_dead_geq[e] = false;
2835*e4b17023SJohn Marino 
2836*e4b17023SJohn Marino       if (pb->geqs[e].color == omega_red)
2837*e4b17023SJohn Marino 	for (i = n_vars; i > 0; i--)
2838*e4b17023SJohn Marino 	  if (pb->geqs[e].coef[i] != 0)
2839*e4b17023SJohn Marino 	    is_red_var[i] = true;
2840*e4b17023SJohn Marino     }
2841*e4b17023SJohn Marino 
2842*e4b17023SJohn Marino   while (try_again)
2843*e4b17023SJohn Marino     {
2844*e4b17023SJohn Marino       try_again = false;
2845*e4b17023SJohn Marino       for (i = n_vars; i > 0; i--)
2846*e4b17023SJohn Marino 	if (!is_red_var[i] && !is_dead_var[i])
2847*e4b17023SJohn Marino 	  {
2848*e4b17023SJohn Marino 	    for (e = pb->num_geqs - 1; e >= 0; e--)
2849*e4b17023SJohn Marino 	      if (!is_dead_geq[e] && pb->geqs[e].coef[i])
2850*e4b17023SJohn Marino 		break;
2851*e4b17023SJohn Marino 
2852*e4b17023SJohn Marino 	    if (e < 0)
2853*e4b17023SJohn Marino 	      e2 = e;
2854*e4b17023SJohn Marino 	    else if (pb->geqs[e].coef[i] > 0)
2855*e4b17023SJohn Marino 	      {
2856*e4b17023SJohn Marino 		for (e2 = e - 1; e2 >= 0; e2--)
2857*e4b17023SJohn Marino 		  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] < 0)
2858*e4b17023SJohn Marino 		    break;
2859*e4b17023SJohn Marino 	      }
2860*e4b17023SJohn Marino 	    else
2861*e4b17023SJohn Marino 	      {
2862*e4b17023SJohn Marino 		for (e2 = e - 1; e2 >= 0; e2--)
2863*e4b17023SJohn Marino 		  if (!is_dead_geq[e2] && pb->geqs[e2].coef[i] > 0)
2864*e4b17023SJohn Marino 		    break;
2865*e4b17023SJohn Marino 	      }
2866*e4b17023SJohn Marino 
2867*e4b17023SJohn Marino 	    if (e2 < 0)
2868*e4b17023SJohn Marino 	      {
2869*e4b17023SJohn Marino 		int e3;
2870*e4b17023SJohn Marino 		for (e3 = pb->num_subs - 1; e3 >= 0; e3--)
2871*e4b17023SJohn Marino 		  if (pb->subs[e3].coef[i])
2872*e4b17023SJohn Marino 		    break;
2873*e4b17023SJohn Marino 
2874*e4b17023SJohn Marino 		if (e3 >= 0)
2875*e4b17023SJohn Marino 		  continue;
2876*e4b17023SJohn Marino 
2877*e4b17023SJohn Marino 		for (e3 = pb->num_eqs - 1; e3 >= 0; e3--)
2878*e4b17023SJohn Marino 		  if (pb->eqs[e3].coef[i])
2879*e4b17023SJohn Marino 		    break;
2880*e4b17023SJohn Marino 
2881*e4b17023SJohn Marino 		if (e3 >= 0)
2882*e4b17023SJohn Marino 		  continue;
2883*e4b17023SJohn Marino 
2884*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
2885*e4b17023SJohn Marino 		  fprintf (dump_file, "a free red elimination of %s\n",
2886*e4b17023SJohn Marino 			   omega_variable_to_str (pb, i));
2887*e4b17023SJohn Marino 
2888*e4b17023SJohn Marino 		for (; e >= 0; e--)
2889*e4b17023SJohn Marino 		  if (pb->geqs[e].coef[i])
2890*e4b17023SJohn Marino 		    is_dead_geq[e] = true;
2891*e4b17023SJohn Marino 
2892*e4b17023SJohn Marino 		try_again = true;
2893*e4b17023SJohn Marino 		is_dead_var[i] = true;
2894*e4b17023SJohn Marino 	      }
2895*e4b17023SJohn Marino 	  }
2896*e4b17023SJohn Marino     }
2897*e4b17023SJohn Marino 
2898*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
2899*e4b17023SJohn Marino     if (is_dead_geq[e])
2900*e4b17023SJohn Marino       omega_delete_geq (pb, e, n_vars);
2901*e4b17023SJohn Marino 
2902*e4b17023SJohn Marino   for (i = n_vars; i > 0; i--)
2903*e4b17023SJohn Marino     if (is_dead_var[i])
2904*e4b17023SJohn Marino       omega_delete_variable (pb, i);
2905*e4b17023SJohn Marino 
2906*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2907*e4b17023SJohn Marino     {
2908*e4b17023SJohn Marino       fprintf (dump_file, "\nafter free red eliminations:\n");
2909*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
2910*e4b17023SJohn Marino       fprintf (dump_file, "\n");
2911*e4b17023SJohn Marino     }
2912*e4b17023SJohn Marino 
2913*e4b17023SJohn Marino   free (is_red_var);
2914*e4b17023SJohn Marino   free (is_dead_var);
2915*e4b17023SJohn Marino   free (is_dead_geq);
2916*e4b17023SJohn Marino }
2917*e4b17023SJohn Marino 
2918*e4b17023SJohn Marino /* For equation EQ of the form "0 = EQN", insert in PB two
2919*e4b17023SJohn Marino    inequalities "0 <= EQN" and "0 <= -EQN".  */
2920*e4b17023SJohn Marino 
2921*e4b17023SJohn Marino void
omega_convert_eq_to_geqs(omega_pb pb,int eq)2922*e4b17023SJohn Marino omega_convert_eq_to_geqs (omega_pb pb, int eq)
2923*e4b17023SJohn Marino {
2924*e4b17023SJohn Marino   int i;
2925*e4b17023SJohn Marino 
2926*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2927*e4b17023SJohn Marino     fprintf (dump_file, "Converting Eq to Geqs\n");
2928*e4b17023SJohn Marino 
2929*e4b17023SJohn Marino   /* Insert "0 <= EQN".  */
2930*e4b17023SJohn Marino   omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2931*e4b17023SJohn Marino   pb->geqs[pb->num_geqs].touched = 1;
2932*e4b17023SJohn Marino   pb->num_geqs++;
2933*e4b17023SJohn Marino 
2934*e4b17023SJohn Marino   /* Insert "0 <= -EQN".  */
2935*e4b17023SJohn Marino   omega_copy_eqn (&pb->geqs[pb->num_geqs], &pb->eqs[eq], pb->num_vars);
2936*e4b17023SJohn Marino   pb->geqs[pb->num_geqs].touched = 1;
2937*e4b17023SJohn Marino 
2938*e4b17023SJohn Marino   for (i = 0; i <= pb->num_vars; i++)
2939*e4b17023SJohn Marino     pb->geqs[pb->num_geqs].coef[i] *= -1;
2940*e4b17023SJohn Marino 
2941*e4b17023SJohn Marino   pb->num_geqs++;
2942*e4b17023SJohn Marino 
2943*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2944*e4b17023SJohn Marino     omega_print_problem (dump_file, pb);
2945*e4b17023SJohn Marino }
2946*e4b17023SJohn Marino 
2947*e4b17023SJohn Marino /* Eliminates variable I from PB.  */
2948*e4b17023SJohn Marino 
2949*e4b17023SJohn Marino static void
omega_do_elimination(omega_pb pb,int e,int i)2950*e4b17023SJohn Marino omega_do_elimination (omega_pb pb, int e, int i)
2951*e4b17023SJohn Marino {
2952*e4b17023SJohn Marino   eqn sub = omega_alloc_eqns (0, 1);
2953*e4b17023SJohn Marino   int c;
2954*e4b17023SJohn Marino   int n_vars = pb->num_vars;
2955*e4b17023SJohn Marino 
2956*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2957*e4b17023SJohn Marino     fprintf (dump_file, "eliminating variable %s\n",
2958*e4b17023SJohn Marino 	     omega_variable_to_str (pb, i));
2959*e4b17023SJohn Marino 
2960*e4b17023SJohn Marino   omega_copy_eqn (sub, &pb->eqs[e], pb->num_vars);
2961*e4b17023SJohn Marino   c = sub->coef[i];
2962*e4b17023SJohn Marino   sub->coef[i] = 0;
2963*e4b17023SJohn Marino   if (c == 1 || c == -1)
2964*e4b17023SJohn Marino     {
2965*e4b17023SJohn Marino       if (pb->eqs[e].color == omega_red)
2966*e4b17023SJohn Marino 	{
2967*e4b17023SJohn Marino 	  bool fB;
2968*e4b17023SJohn Marino 	  omega_substitute_red (pb, sub, i, c, &fB);
2969*e4b17023SJohn Marino 	  if (fB)
2970*e4b17023SJohn Marino 	    omega_convert_eq_to_geqs (pb, e);
2971*e4b17023SJohn Marino 	  else
2972*e4b17023SJohn Marino 	    omega_delete_variable (pb, i);
2973*e4b17023SJohn Marino 	}
2974*e4b17023SJohn Marino       else
2975*e4b17023SJohn Marino 	{
2976*e4b17023SJohn Marino 	  omega_substitute (pb, sub, i, c);
2977*e4b17023SJohn Marino 	  omega_delete_variable (pb, i);
2978*e4b17023SJohn Marino 	}
2979*e4b17023SJohn Marino     }
2980*e4b17023SJohn Marino   else
2981*e4b17023SJohn Marino     {
2982*e4b17023SJohn Marino       int a = abs (c);
2983*e4b17023SJohn Marino       int e2 = e;
2984*e4b17023SJohn Marino 
2985*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2986*e4b17023SJohn Marino 	fprintf (dump_file, "performing non-exact elimination, c = %d\n", c);
2987*e4b17023SJohn Marino 
2988*e4b17023SJohn Marino       for (e = pb->num_eqs - 1; e >= 0; e--)
2989*e4b17023SJohn Marino 	if (pb->eqs[e].coef[i])
2990*e4b17023SJohn Marino 	  {
2991*e4b17023SJohn Marino 	    eqn eqn = &(pb->eqs[e]);
2992*e4b17023SJohn Marino 	    int j, k;
2993*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
2994*e4b17023SJohn Marino 	      eqn->coef[j] *= a;
2995*e4b17023SJohn Marino 	    k = eqn->coef[i];
2996*e4b17023SJohn Marino 	    eqn->coef[i] = 0;
2997*e4b17023SJohn Marino 	    if (sub->color == omega_red)
2998*e4b17023SJohn Marino 	      eqn->color = omega_red;
2999*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
3000*e4b17023SJohn Marino 	      eqn->coef[j] -= sub->coef[j] * k / c;
3001*e4b17023SJohn Marino 	  }
3002*e4b17023SJohn Marino 
3003*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
3004*e4b17023SJohn Marino 	if (pb->geqs[e].coef[i])
3005*e4b17023SJohn Marino 	  {
3006*e4b17023SJohn Marino 	    eqn eqn = &(pb->geqs[e]);
3007*e4b17023SJohn Marino 	    int j, k;
3008*e4b17023SJohn Marino 
3009*e4b17023SJohn Marino 	    if (sub->color == omega_red)
3010*e4b17023SJohn Marino 	      eqn->color = omega_red;
3011*e4b17023SJohn Marino 
3012*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
3013*e4b17023SJohn Marino 	      eqn->coef[j] *= a;
3014*e4b17023SJohn Marino 
3015*e4b17023SJohn Marino 	    eqn->touched = 1;
3016*e4b17023SJohn Marino 	    k = eqn->coef[i];
3017*e4b17023SJohn Marino 	    eqn->coef[i] = 0;
3018*e4b17023SJohn Marino 
3019*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
3020*e4b17023SJohn Marino 	      eqn->coef[j] -= sub->coef[j] * k / c;
3021*e4b17023SJohn Marino 
3022*e4b17023SJohn Marino 	  }
3023*e4b17023SJohn Marino 
3024*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
3025*e4b17023SJohn Marino 	if (pb->subs[e].coef[i])
3026*e4b17023SJohn Marino 	  {
3027*e4b17023SJohn Marino 	    eqn eqn = &(pb->subs[e]);
3028*e4b17023SJohn Marino 	    int j, k;
3029*e4b17023SJohn Marino 	    gcc_assert (0);
3030*e4b17023SJohn Marino 	    gcc_assert (sub->color == omega_black);
3031*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
3032*e4b17023SJohn Marino 	      eqn->coef[j] *= a;
3033*e4b17023SJohn Marino 	    k = eqn->coef[i];
3034*e4b17023SJohn Marino 	    eqn->coef[i] = 0;
3035*e4b17023SJohn Marino 	    for (j = n_vars; j >= 0; j--)
3036*e4b17023SJohn Marino 	      eqn->coef[j] -= sub->coef[j] * k / c;
3037*e4b17023SJohn Marino 	  }
3038*e4b17023SJohn Marino 
3039*e4b17023SJohn Marino       if (in_approximate_mode)
3040*e4b17023SJohn Marino 	omega_delete_variable (pb, i);
3041*e4b17023SJohn Marino       else
3042*e4b17023SJohn Marino 	omega_convert_eq_to_geqs (pb, e2);
3043*e4b17023SJohn Marino     }
3044*e4b17023SJohn Marino 
3045*e4b17023SJohn Marino   omega_free_eqns (sub, 1);
3046*e4b17023SJohn Marino }
3047*e4b17023SJohn Marino 
3048*e4b17023SJohn Marino /* Helper function for printing "sorry, no solution".  */
3049*e4b17023SJohn Marino 
3050*e4b17023SJohn Marino static inline enum omega_result
omega_problem_has_no_solution(void)3051*e4b17023SJohn Marino omega_problem_has_no_solution (void)
3052*e4b17023SJohn Marino {
3053*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3054*e4b17023SJohn Marino     fprintf (dump_file, "\nequations have no solution \n");
3055*e4b17023SJohn Marino 
3056*e4b17023SJohn Marino   return omega_false;
3057*e4b17023SJohn Marino }
3058*e4b17023SJohn Marino 
3059*e4b17023SJohn Marino /* Helper function: solve equations in PB one at a time, following the
3060*e4b17023SJohn Marino    DESIRED_RES result.  */
3061*e4b17023SJohn Marino 
3062*e4b17023SJohn Marino static enum omega_result
omega_solve_eq(omega_pb pb,enum omega_result desired_res)3063*e4b17023SJohn Marino omega_solve_eq (omega_pb pb, enum omega_result desired_res)
3064*e4b17023SJohn Marino {
3065*e4b17023SJohn Marino   int i, j, e;
3066*e4b17023SJohn Marino   int g, g2;
3067*e4b17023SJohn Marino   g = 0;
3068*e4b17023SJohn Marino 
3069*e4b17023SJohn Marino 
3070*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS) && pb->num_eqs > 0)
3071*e4b17023SJohn Marino     {
3072*e4b17023SJohn Marino       fprintf (dump_file, "\nomega_solve_eq (%d, %d)\n",
3073*e4b17023SJohn Marino 	       desired_res, may_be_red);
3074*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
3075*e4b17023SJohn Marino       fprintf (dump_file, "\n");
3076*e4b17023SJohn Marino     }
3077*e4b17023SJohn Marino 
3078*e4b17023SJohn Marino   if (may_be_red)
3079*e4b17023SJohn Marino     {
3080*e4b17023SJohn Marino       i = 0;
3081*e4b17023SJohn Marino       j = pb->num_eqs - 1;
3082*e4b17023SJohn Marino 
3083*e4b17023SJohn Marino       while (1)
3084*e4b17023SJohn Marino 	{
3085*e4b17023SJohn Marino 	  eqn eq;
3086*e4b17023SJohn Marino 
3087*e4b17023SJohn Marino 	  while (i <= j && pb->eqs[i].color == omega_red)
3088*e4b17023SJohn Marino 	    i++;
3089*e4b17023SJohn Marino 
3090*e4b17023SJohn Marino 	  while (i <= j && pb->eqs[j].color == omega_black)
3091*e4b17023SJohn Marino 	    j--;
3092*e4b17023SJohn Marino 
3093*e4b17023SJohn Marino 	  if (i >= j)
3094*e4b17023SJohn Marino 	    break;
3095*e4b17023SJohn Marino 
3096*e4b17023SJohn Marino 	  eq = omega_alloc_eqns (0, 1);
3097*e4b17023SJohn Marino 	  omega_copy_eqn (eq, &pb->eqs[i], pb->num_vars);
3098*e4b17023SJohn Marino 	  omega_copy_eqn (&pb->eqs[i], &pb->eqs[j], pb->num_vars);
3099*e4b17023SJohn Marino 	  omega_copy_eqn (&pb->eqs[j], eq, pb->num_vars);
3100*e4b17023SJohn Marino 	  omega_free_eqns (eq, 1);
3101*e4b17023SJohn Marino 	  i++;
3102*e4b17023SJohn Marino 	  j--;
3103*e4b17023SJohn Marino 	}
3104*e4b17023SJohn Marino     }
3105*e4b17023SJohn Marino 
3106*e4b17023SJohn Marino   /* Eliminate all EQ equations */
3107*e4b17023SJohn Marino   for (e = pb->num_eqs - 1; e >= 0; e--)
3108*e4b17023SJohn Marino     {
3109*e4b17023SJohn Marino       eqn eqn = &(pb->eqs[e]);
3110*e4b17023SJohn Marino       int sv;
3111*e4b17023SJohn Marino 
3112*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3113*e4b17023SJohn Marino 	fprintf (dump_file, "----\n");
3114*e4b17023SJohn Marino 
3115*e4b17023SJohn Marino       for (i = pb->num_vars; i > 0; i--)
3116*e4b17023SJohn Marino 	if (eqn->coef[i])
3117*e4b17023SJohn Marino 	  break;
3118*e4b17023SJohn Marino 
3119*e4b17023SJohn Marino       g = eqn->coef[i];
3120*e4b17023SJohn Marino 
3121*e4b17023SJohn Marino       for (j = i - 1; j > 0; j--)
3122*e4b17023SJohn Marino 	if (eqn->coef[j])
3123*e4b17023SJohn Marino 	  break;
3124*e4b17023SJohn Marino 
3125*e4b17023SJohn Marino       /* i is the position of last nonzero coefficient,
3126*e4b17023SJohn Marino 	 g is the coefficient of i,
3127*e4b17023SJohn Marino 	 j is the position of next nonzero coefficient.  */
3128*e4b17023SJohn Marino 
3129*e4b17023SJohn Marino       if (j == 0)
3130*e4b17023SJohn Marino 	{
3131*e4b17023SJohn Marino 	  if (eqn->coef[0] % g != 0)
3132*e4b17023SJohn Marino 	    return omega_problem_has_no_solution ();
3133*e4b17023SJohn Marino 
3134*e4b17023SJohn Marino 	  eqn->coef[0] = eqn->coef[0] / g;
3135*e4b17023SJohn Marino 	  eqn->coef[i] = 1;
3136*e4b17023SJohn Marino 	  pb->num_eqs--;
3137*e4b17023SJohn Marino 	  omega_do_elimination (pb, e, i);
3138*e4b17023SJohn Marino 	  continue;
3139*e4b17023SJohn Marino 	}
3140*e4b17023SJohn Marino 
3141*e4b17023SJohn Marino       else if (j == -1)
3142*e4b17023SJohn Marino 	{
3143*e4b17023SJohn Marino 	  if (eqn->coef[0] != 0)
3144*e4b17023SJohn Marino 	    return omega_problem_has_no_solution ();
3145*e4b17023SJohn Marino 
3146*e4b17023SJohn Marino 	  pb->num_eqs--;
3147*e4b17023SJohn Marino 	  continue;
3148*e4b17023SJohn Marino 	}
3149*e4b17023SJohn Marino 
3150*e4b17023SJohn Marino       if (g < 0)
3151*e4b17023SJohn Marino 	g = -g;
3152*e4b17023SJohn Marino 
3153*e4b17023SJohn Marino       if (g == 1)
3154*e4b17023SJohn Marino 	{
3155*e4b17023SJohn Marino 	  pb->num_eqs--;
3156*e4b17023SJohn Marino 	  omega_do_elimination (pb, e, i);
3157*e4b17023SJohn Marino 	}
3158*e4b17023SJohn Marino 
3159*e4b17023SJohn Marino       else
3160*e4b17023SJohn Marino 	{
3161*e4b17023SJohn Marino 	  int k = j;
3162*e4b17023SJohn Marino 	  bool promotion_possible =
3163*e4b17023SJohn Marino 	    (omega_safe_var_p (pb, j)
3164*e4b17023SJohn Marino 	     && pb->safe_vars + 1 == i
3165*e4b17023SJohn Marino 	     && !omega_eqn_is_red (eqn, desired_res)
3166*e4b17023SJohn Marino 	     && !in_approximate_mode);
3167*e4b17023SJohn Marino 
3168*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS) && promotion_possible)
3169*e4b17023SJohn Marino 	    fprintf (dump_file, " Promotion possible\n");
3170*e4b17023SJohn Marino 
3171*e4b17023SJohn Marino 	normalizeEQ:
3172*e4b17023SJohn Marino 	  if (!omega_safe_var_p (pb, j))
3173*e4b17023SJohn Marino 	    {
3174*e4b17023SJohn Marino 	      for (; g != 1 && !omega_safe_var_p (pb, j); j--)
3175*e4b17023SJohn Marino 		g = gcd (abs (eqn->coef[j]), g);
3176*e4b17023SJohn Marino 	      g2 = g;
3177*e4b17023SJohn Marino 	    }
3178*e4b17023SJohn Marino 	  else if (!omega_safe_var_p (pb, i))
3179*e4b17023SJohn Marino 	    g2 = g;
3180*e4b17023SJohn Marino 	  else
3181*e4b17023SJohn Marino 	    g2 = 0;
3182*e4b17023SJohn Marino 
3183*e4b17023SJohn Marino 	  for (; g != 1 && j > 0; j--)
3184*e4b17023SJohn Marino 	    g = gcd (abs (eqn->coef[j]), g);
3185*e4b17023SJohn Marino 
3186*e4b17023SJohn Marino 	  if (g > 1)
3187*e4b17023SJohn Marino 	    {
3188*e4b17023SJohn Marino 	      if (eqn->coef[0] % g != 0)
3189*e4b17023SJohn Marino 		return omega_problem_has_no_solution ();
3190*e4b17023SJohn Marino 
3191*e4b17023SJohn Marino 	      for (j = 0; j <= pb->num_vars; j++)
3192*e4b17023SJohn Marino 		eqn->coef[j] /= g;
3193*e4b17023SJohn Marino 
3194*e4b17023SJohn Marino 	      g2 = g2 / g;
3195*e4b17023SJohn Marino 	    }
3196*e4b17023SJohn Marino 
3197*e4b17023SJohn Marino 	  if (g2 > 1)
3198*e4b17023SJohn Marino 	    {
3199*e4b17023SJohn Marino 	      int e2;
3200*e4b17023SJohn Marino 
3201*e4b17023SJohn Marino 	      for (e2 = e - 1; e2 >= 0; e2--)
3202*e4b17023SJohn Marino 		if (pb->eqs[e2].coef[i])
3203*e4b17023SJohn Marino 		  break;
3204*e4b17023SJohn Marino 
3205*e4b17023SJohn Marino 	      if (e2 == -1)
3206*e4b17023SJohn Marino 		for (e2 = pb->num_geqs - 1; e2 >= 0; e2--)
3207*e4b17023SJohn Marino 		  if (pb->geqs[e2].coef[i])
3208*e4b17023SJohn Marino 		    break;
3209*e4b17023SJohn Marino 
3210*e4b17023SJohn Marino 	      if (e2 == -1)
3211*e4b17023SJohn Marino 		for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
3212*e4b17023SJohn Marino 		  if (pb->subs[e2].coef[i])
3213*e4b17023SJohn Marino 		    break;
3214*e4b17023SJohn Marino 
3215*e4b17023SJohn Marino 	      if (e2 == -1)
3216*e4b17023SJohn Marino 		{
3217*e4b17023SJohn Marino 		  bool change = false;
3218*e4b17023SJohn Marino 
3219*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
3220*e4b17023SJohn Marino 		    {
3221*e4b17023SJohn Marino 		      fprintf (dump_file, "Ha! We own it! \n");
3222*e4b17023SJohn Marino 		      omega_print_eq (dump_file, pb, eqn);
3223*e4b17023SJohn Marino 		      fprintf (dump_file, " \n");
3224*e4b17023SJohn Marino 		    }
3225*e4b17023SJohn Marino 
3226*e4b17023SJohn Marino 		  g = eqn->coef[i];
3227*e4b17023SJohn Marino 		  g = abs (g);
3228*e4b17023SJohn Marino 
3229*e4b17023SJohn Marino 		  for (j = i - 1; j >= 0; j--)
3230*e4b17023SJohn Marino 		    {
3231*e4b17023SJohn Marino 		      int t = int_mod (eqn->coef[j], g);
3232*e4b17023SJohn Marino 
3233*e4b17023SJohn Marino 		      if (2 * t >= g)
3234*e4b17023SJohn Marino 			t -= g;
3235*e4b17023SJohn Marino 
3236*e4b17023SJohn Marino 		      if (t != eqn->coef[j])
3237*e4b17023SJohn Marino 			{
3238*e4b17023SJohn Marino 			  eqn->coef[j] = t;
3239*e4b17023SJohn Marino 			  change = true;
3240*e4b17023SJohn Marino 			}
3241*e4b17023SJohn Marino 		    }
3242*e4b17023SJohn Marino 
3243*e4b17023SJohn Marino 		  if (!change)
3244*e4b17023SJohn Marino 		    {
3245*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
3246*e4b17023SJohn Marino 			fprintf (dump_file, "So what?\n");
3247*e4b17023SJohn Marino 		    }
3248*e4b17023SJohn Marino 
3249*e4b17023SJohn Marino 		  else
3250*e4b17023SJohn Marino 		    {
3251*e4b17023SJohn Marino 		      omega_name_wild_card (pb, i);
3252*e4b17023SJohn Marino 
3253*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
3254*e4b17023SJohn Marino 			{
3255*e4b17023SJohn Marino 			  omega_print_eq (dump_file, pb, eqn);
3256*e4b17023SJohn Marino 			  fprintf (dump_file, " \n");
3257*e4b17023SJohn Marino 			}
3258*e4b17023SJohn Marino 
3259*e4b17023SJohn Marino 		      e++;
3260*e4b17023SJohn Marino 		      continue;
3261*e4b17023SJohn Marino 		    }
3262*e4b17023SJohn Marino 		}
3263*e4b17023SJohn Marino 	    }
3264*e4b17023SJohn Marino 
3265*e4b17023SJohn Marino 	  if (promotion_possible)
3266*e4b17023SJohn Marino 	    {
3267*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3268*e4b17023SJohn Marino 		{
3269*e4b17023SJohn Marino 		  fprintf (dump_file, "promoting %s to safety\n",
3270*e4b17023SJohn Marino 			   omega_variable_to_str (pb, i));
3271*e4b17023SJohn Marino 		  omega_print_vars (dump_file, pb);
3272*e4b17023SJohn Marino 		}
3273*e4b17023SJohn Marino 
3274*e4b17023SJohn Marino 	      pb->safe_vars++;
3275*e4b17023SJohn Marino 
3276*e4b17023SJohn Marino 	      if (!omega_wildcard_p (pb, i))
3277*e4b17023SJohn Marino 		omega_name_wild_card (pb, i);
3278*e4b17023SJohn Marino 
3279*e4b17023SJohn Marino 	      promotion_possible = false;
3280*e4b17023SJohn Marino 	      j = k;
3281*e4b17023SJohn Marino 	      goto normalizeEQ;
3282*e4b17023SJohn Marino 	    }
3283*e4b17023SJohn Marino 
3284*e4b17023SJohn Marino 	  if (g2 > 1 && !in_approximate_mode)
3285*e4b17023SJohn Marino 	    {
3286*e4b17023SJohn Marino 	      if (pb->eqs[e].color == omega_red)
3287*e4b17023SJohn Marino 		{
3288*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
3289*e4b17023SJohn Marino 		    fprintf (dump_file, "handling red equality\n");
3290*e4b17023SJohn Marino 
3291*e4b17023SJohn Marino 		  pb->num_eqs--;
3292*e4b17023SJohn Marino 		  omega_do_elimination (pb, e, i);
3293*e4b17023SJohn Marino 		  continue;
3294*e4b17023SJohn Marino 		}
3295*e4b17023SJohn Marino 
3296*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3297*e4b17023SJohn Marino 		{
3298*e4b17023SJohn Marino 		  fprintf (dump_file,
3299*e4b17023SJohn Marino 			   "adding equation to handle safe variable \n");
3300*e4b17023SJohn Marino 		  omega_print_eq (dump_file, pb, eqn);
3301*e4b17023SJohn Marino 		  fprintf (dump_file, "\n----\n");
3302*e4b17023SJohn Marino 		  omega_print_problem (dump_file, pb);
3303*e4b17023SJohn Marino 		  fprintf (dump_file, "\n----\n");
3304*e4b17023SJohn Marino 		  fprintf (dump_file, "\n----\n");
3305*e4b17023SJohn Marino 		}
3306*e4b17023SJohn Marino 
3307*e4b17023SJohn Marino 	      i = omega_add_new_wild_card (pb);
3308*e4b17023SJohn Marino 	      pb->num_eqs++;
3309*e4b17023SJohn Marino 	      gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
3310*e4b17023SJohn Marino 	      omega_init_eqn_zero (&pb->eqs[e + 1], pb->num_vars);
3311*e4b17023SJohn Marino 	      omega_copy_eqn (&pb->eqs[e + 1], eqn, pb->safe_vars);
3312*e4b17023SJohn Marino 
3313*e4b17023SJohn Marino 	      for (j = pb->num_vars; j >= 0; j--)
3314*e4b17023SJohn Marino 		{
3315*e4b17023SJohn Marino 		  pb->eqs[e + 1].coef[j] = int_mod (pb->eqs[e + 1].coef[j], g2);
3316*e4b17023SJohn Marino 
3317*e4b17023SJohn Marino 		  if (2 * pb->eqs[e + 1].coef[j] >= g2)
3318*e4b17023SJohn Marino 		    pb->eqs[e + 1].coef[j] -= g2;
3319*e4b17023SJohn Marino 		}
3320*e4b17023SJohn Marino 
3321*e4b17023SJohn Marino 	      pb->eqs[e + 1].coef[i] = g2;
3322*e4b17023SJohn Marino 	      e += 2;
3323*e4b17023SJohn Marino 
3324*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3325*e4b17023SJohn Marino 		omega_print_problem (dump_file, pb);
3326*e4b17023SJohn Marino 
3327*e4b17023SJohn Marino 	      continue;
3328*e4b17023SJohn Marino 	    }
3329*e4b17023SJohn Marino 
3330*e4b17023SJohn Marino 	  sv = pb->safe_vars;
3331*e4b17023SJohn Marino 	  if (g2 == 0)
3332*e4b17023SJohn Marino 	    sv = 0;
3333*e4b17023SJohn Marino 
3334*e4b17023SJohn Marino 	  /* Find variable to eliminate.  */
3335*e4b17023SJohn Marino 	  if (g2 > 1)
3336*e4b17023SJohn Marino 	    {
3337*e4b17023SJohn Marino 	      gcc_assert (in_approximate_mode);
3338*e4b17023SJohn Marino 
3339*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3340*e4b17023SJohn Marino 		{
3341*e4b17023SJohn Marino 		  fprintf (dump_file, "non-exact elimination: ");
3342*e4b17023SJohn Marino 		  omega_print_eq (dump_file, pb, eqn);
3343*e4b17023SJohn Marino 		  fprintf (dump_file, "\n");
3344*e4b17023SJohn Marino 		  omega_print_problem (dump_file, pb);
3345*e4b17023SJohn Marino 		}
3346*e4b17023SJohn Marino 
3347*e4b17023SJohn Marino 	      for (i = pb->num_vars; i > sv; i--)
3348*e4b17023SJohn Marino 		if (pb->eqs[e].coef[i] != 0)
3349*e4b17023SJohn Marino 		  break;
3350*e4b17023SJohn Marino 	    }
3351*e4b17023SJohn Marino 	  else
3352*e4b17023SJohn Marino 	    for (i = pb->num_vars; i > sv; i--)
3353*e4b17023SJohn Marino 	      if (pb->eqs[e].coef[i] == 1 || pb->eqs[e].coef[i] == -1)
3354*e4b17023SJohn Marino 		break;
3355*e4b17023SJohn Marino 
3356*e4b17023SJohn Marino 	  if (i > sv)
3357*e4b17023SJohn Marino 	    {
3358*e4b17023SJohn Marino 	      pb->num_eqs--;
3359*e4b17023SJohn Marino 	      omega_do_elimination (pb, e, i);
3360*e4b17023SJohn Marino 
3361*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS) && g2 > 1)
3362*e4b17023SJohn Marino 		{
3363*e4b17023SJohn Marino 		  fprintf (dump_file, "result of non-exact elimination:\n");
3364*e4b17023SJohn Marino 		  omega_print_problem (dump_file, pb);
3365*e4b17023SJohn Marino 		}
3366*e4b17023SJohn Marino 	    }
3367*e4b17023SJohn Marino 	  else
3368*e4b17023SJohn Marino 	    {
3369*e4b17023SJohn Marino 	      int factor = (INT_MAX);
3370*e4b17023SJohn Marino 	      j = 0;
3371*e4b17023SJohn Marino 
3372*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3373*e4b17023SJohn Marino 		fprintf (dump_file, "doing moding\n");
3374*e4b17023SJohn Marino 
3375*e4b17023SJohn Marino 	      for (i = pb->num_vars; i != sv; i--)
3376*e4b17023SJohn Marino 		if ((pb->eqs[e].coef[i] & 1) != 0)
3377*e4b17023SJohn Marino 		  {
3378*e4b17023SJohn Marino 		    j = i;
3379*e4b17023SJohn Marino 		    i--;
3380*e4b17023SJohn Marino 
3381*e4b17023SJohn Marino 		    for (; i != sv; i--)
3382*e4b17023SJohn Marino 		      if ((pb->eqs[e].coef[i] & 1) != 0)
3383*e4b17023SJohn Marino 			break;
3384*e4b17023SJohn Marino 
3385*e4b17023SJohn Marino 		    break;
3386*e4b17023SJohn Marino 		  }
3387*e4b17023SJohn Marino 
3388*e4b17023SJohn Marino 	      if (j != 0 && i == sv)
3389*e4b17023SJohn Marino 		{
3390*e4b17023SJohn Marino 		  omega_do_mod (pb, 2, e, j);
3391*e4b17023SJohn Marino 		  e++;
3392*e4b17023SJohn Marino 		  continue;
3393*e4b17023SJohn Marino 		}
3394*e4b17023SJohn Marino 
3395*e4b17023SJohn Marino 	      j = 0;
3396*e4b17023SJohn Marino 	      for (i = pb->num_vars; i != sv; i--)
3397*e4b17023SJohn Marino 		if (pb->eqs[e].coef[i] != 0
3398*e4b17023SJohn Marino 		    && factor > abs (pb->eqs[e].coef[i]) + 1)
3399*e4b17023SJohn Marino 		  {
3400*e4b17023SJohn Marino 		    factor = abs (pb->eqs[e].coef[i]) + 1;
3401*e4b17023SJohn Marino 		    j = i;
3402*e4b17023SJohn Marino 		  }
3403*e4b17023SJohn Marino 
3404*e4b17023SJohn Marino 	      if (j == sv)
3405*e4b17023SJohn Marino 		{
3406*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
3407*e4b17023SJohn Marino 		    fprintf (dump_file, "should not have happened\n");
3408*e4b17023SJohn Marino 		  gcc_assert (0);
3409*e4b17023SJohn Marino 		}
3410*e4b17023SJohn Marino 
3411*e4b17023SJohn Marino 	      omega_do_mod (pb, factor, e, j);
3412*e4b17023SJohn Marino 	      /* Go back and try this equation again.  */
3413*e4b17023SJohn Marino 	      e++;
3414*e4b17023SJohn Marino 	    }
3415*e4b17023SJohn Marino 	}
3416*e4b17023SJohn Marino     }
3417*e4b17023SJohn Marino 
3418*e4b17023SJohn Marino   pb->num_eqs = 0;
3419*e4b17023SJohn Marino   return omega_unknown;
3420*e4b17023SJohn Marino }
3421*e4b17023SJohn Marino 
3422*e4b17023SJohn Marino /* Transform an inequation E to an equality, then solve DIFF problems
3423*e4b17023SJohn Marino    based on PB, and only differing by the constant part that is
3424*e4b17023SJohn Marino    diminished by one, trying to figure out which of the constants
3425*e4b17023SJohn Marino    satisfies PB.    */
3426*e4b17023SJohn Marino 
3427*e4b17023SJohn Marino static enum omega_result
parallel_splinter(omega_pb pb,int e,int diff,enum omega_result desired_res)3428*e4b17023SJohn Marino parallel_splinter (omega_pb pb, int e, int diff,
3429*e4b17023SJohn Marino 		   enum omega_result desired_res)
3430*e4b17023SJohn Marino {
3431*e4b17023SJohn Marino   omega_pb tmp_problem;
3432*e4b17023SJohn Marino   int i;
3433*e4b17023SJohn Marino 
3434*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3435*e4b17023SJohn Marino     {
3436*e4b17023SJohn Marino       fprintf (dump_file, "Using parallel splintering\n");
3437*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
3438*e4b17023SJohn Marino     }
3439*e4b17023SJohn Marino 
3440*e4b17023SJohn Marino   tmp_problem = XNEW (struct omega_pb_d);
3441*e4b17023SJohn Marino   omega_copy_eqn (&pb->eqs[0], &pb->geqs[e], pb->num_vars);
3442*e4b17023SJohn Marino   pb->num_eqs = 1;
3443*e4b17023SJohn Marino 
3444*e4b17023SJohn Marino   for (i = 0; i <= diff; i++)
3445*e4b17023SJohn Marino     {
3446*e4b17023SJohn Marino       omega_copy_problem (tmp_problem, pb);
3447*e4b17023SJohn Marino 
3448*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3449*e4b17023SJohn Marino 	{
3450*e4b17023SJohn Marino 	  fprintf (dump_file, "Splinter # %i\n", i);
3451*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
3452*e4b17023SJohn Marino 	}
3453*e4b17023SJohn Marino 
3454*e4b17023SJohn Marino       if (omega_solve_problem (tmp_problem, desired_res) == omega_true)
3455*e4b17023SJohn Marino 	{
3456*e4b17023SJohn Marino 	  free (tmp_problem);
3457*e4b17023SJohn Marino 	  return omega_true;
3458*e4b17023SJohn Marino 	}
3459*e4b17023SJohn Marino 
3460*e4b17023SJohn Marino       pb->eqs[0].coef[0]--;
3461*e4b17023SJohn Marino     }
3462*e4b17023SJohn Marino 
3463*e4b17023SJohn Marino   free (tmp_problem);
3464*e4b17023SJohn Marino   return omega_false;
3465*e4b17023SJohn Marino }
3466*e4b17023SJohn Marino 
3467*e4b17023SJohn Marino /* Helper function: solve equations one at a time.  */
3468*e4b17023SJohn Marino 
3469*e4b17023SJohn Marino static enum omega_result
omega_solve_geq(omega_pb pb,enum omega_result desired_res)3470*e4b17023SJohn Marino omega_solve_geq (omega_pb pb, enum omega_result desired_res)
3471*e4b17023SJohn Marino {
3472*e4b17023SJohn Marino   int i, e;
3473*e4b17023SJohn Marino   int n_vars, fv;
3474*e4b17023SJohn Marino   enum omega_result result;
3475*e4b17023SJohn Marino   bool coupled_subscripts = false;
3476*e4b17023SJohn Marino   bool smoothed = false;
3477*e4b17023SJohn Marino   bool eliminate_again;
3478*e4b17023SJohn Marino   bool tried_eliminating_redundant = false;
3479*e4b17023SJohn Marino 
3480*e4b17023SJohn Marino   if (desired_res != omega_simplify)
3481*e4b17023SJohn Marino     {
3482*e4b17023SJohn Marino       pb->num_subs = 0;
3483*e4b17023SJohn Marino       pb->safe_vars = 0;
3484*e4b17023SJohn Marino     }
3485*e4b17023SJohn Marino 
3486*e4b17023SJohn Marino  solve_geq_start:
3487*e4b17023SJohn Marino   do {
3488*e4b17023SJohn Marino     gcc_assert (desired_res == omega_simplify || pb->num_subs == 0);
3489*e4b17023SJohn Marino 
3490*e4b17023SJohn Marino     /* Verify that there are not too many inequalities.  */
3491*e4b17023SJohn Marino     gcc_assert (pb->num_geqs <= OMEGA_MAX_GEQS);
3492*e4b17023SJohn Marino 
3493*e4b17023SJohn Marino     if (dump_file && (dump_flags & TDF_DETAILS))
3494*e4b17023SJohn Marino       {
3495*e4b17023SJohn Marino 	fprintf (dump_file, "\nomega_solve_geq (%d,%d):\n",
3496*e4b17023SJohn Marino 		 desired_res, please_no_equalities_in_simplified_problems);
3497*e4b17023SJohn Marino 	omega_print_problem (dump_file, pb);
3498*e4b17023SJohn Marino 	fprintf (dump_file, "\n");
3499*e4b17023SJohn Marino       }
3500*e4b17023SJohn Marino 
3501*e4b17023SJohn Marino     n_vars = pb->num_vars;
3502*e4b17023SJohn Marino 
3503*e4b17023SJohn Marino     if (n_vars == 1)
3504*e4b17023SJohn Marino       {
3505*e4b17023SJohn Marino 	enum omega_eqn_color u_color = omega_black;
3506*e4b17023SJohn Marino 	enum omega_eqn_color l_color = omega_black;
3507*e4b17023SJohn Marino 	int upper_bound = pos_infinity;
3508*e4b17023SJohn Marino 	int lower_bound = neg_infinity;
3509*e4b17023SJohn Marino 
3510*e4b17023SJohn Marino 	for (e = pb->num_geqs - 1; e >= 0; e--)
3511*e4b17023SJohn Marino 	  {
3512*e4b17023SJohn Marino 	    int a = pb->geqs[e].coef[1];
3513*e4b17023SJohn Marino 	    int c = pb->geqs[e].coef[0];
3514*e4b17023SJohn Marino 
3515*e4b17023SJohn Marino 	    /* Our equation is ax + c >= 0, or ax >= -c, or c >= -ax.  */
3516*e4b17023SJohn Marino 	    if (a == 0)
3517*e4b17023SJohn Marino 	      {
3518*e4b17023SJohn Marino 		if (c < 0)
3519*e4b17023SJohn Marino 		  return omega_problem_has_no_solution ();
3520*e4b17023SJohn Marino 	      }
3521*e4b17023SJohn Marino 	    else if (a > 0)
3522*e4b17023SJohn Marino 	      {
3523*e4b17023SJohn Marino 		if (a != 1)
3524*e4b17023SJohn Marino 		  c = int_div (c, a);
3525*e4b17023SJohn Marino 
3526*e4b17023SJohn Marino 		if (lower_bound < -c
3527*e4b17023SJohn Marino 		    || (lower_bound == -c
3528*e4b17023SJohn Marino 			&& !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3529*e4b17023SJohn Marino 		  {
3530*e4b17023SJohn Marino 		    lower_bound = -c;
3531*e4b17023SJohn Marino 		    l_color = pb->geqs[e].color;
3532*e4b17023SJohn Marino 		  }
3533*e4b17023SJohn Marino 	      }
3534*e4b17023SJohn Marino 	    else
3535*e4b17023SJohn Marino 	      {
3536*e4b17023SJohn Marino 		if (a != -1)
3537*e4b17023SJohn Marino 		  c = int_div (c, -a);
3538*e4b17023SJohn Marino 
3539*e4b17023SJohn Marino 		if (upper_bound > c
3540*e4b17023SJohn Marino 		    || (upper_bound == c
3541*e4b17023SJohn Marino 			&& !omega_eqn_is_red (&pb->geqs[e], desired_res)))
3542*e4b17023SJohn Marino 		  {
3543*e4b17023SJohn Marino 		    upper_bound = c;
3544*e4b17023SJohn Marino 		    u_color = pb->geqs[e].color;
3545*e4b17023SJohn Marino 		  }
3546*e4b17023SJohn Marino 	      }
3547*e4b17023SJohn Marino 	  }
3548*e4b17023SJohn Marino 
3549*e4b17023SJohn Marino 	if (dump_file && (dump_flags & TDF_DETAILS))
3550*e4b17023SJohn Marino 	  {
3551*e4b17023SJohn Marino 	    fprintf (dump_file, "upper bound = %d\n", upper_bound);
3552*e4b17023SJohn Marino 	    fprintf (dump_file, "lower bound = %d\n", lower_bound);
3553*e4b17023SJohn Marino 	  }
3554*e4b17023SJohn Marino 
3555*e4b17023SJohn Marino 	if (lower_bound > upper_bound)
3556*e4b17023SJohn Marino 	  return omega_problem_has_no_solution ();
3557*e4b17023SJohn Marino 
3558*e4b17023SJohn Marino 	if (desired_res == omega_simplify)
3559*e4b17023SJohn Marino 	  {
3560*e4b17023SJohn Marino 	    pb->num_geqs = 0;
3561*e4b17023SJohn Marino 	    if (pb->safe_vars == 1)
3562*e4b17023SJohn Marino 	      {
3563*e4b17023SJohn Marino 
3564*e4b17023SJohn Marino 		if (lower_bound == upper_bound
3565*e4b17023SJohn Marino 		    && u_color == omega_black
3566*e4b17023SJohn Marino 		    && l_color == omega_black)
3567*e4b17023SJohn Marino 		  {
3568*e4b17023SJohn Marino 		    pb->eqs[0].coef[0] = -lower_bound;
3569*e4b17023SJohn Marino 		    pb->eqs[0].coef[1] = 1;
3570*e4b17023SJohn Marino 		    pb->eqs[0].color = omega_black;
3571*e4b17023SJohn Marino 		    pb->num_eqs = 1;
3572*e4b17023SJohn Marino 		    return omega_solve_problem (pb, desired_res);
3573*e4b17023SJohn Marino 		  }
3574*e4b17023SJohn Marino 		else
3575*e4b17023SJohn Marino 		  {
3576*e4b17023SJohn Marino 		    if (lower_bound > neg_infinity)
3577*e4b17023SJohn Marino 		      {
3578*e4b17023SJohn Marino 			pb->geqs[0].coef[0] = -lower_bound;
3579*e4b17023SJohn Marino 			pb->geqs[0].coef[1] = 1;
3580*e4b17023SJohn Marino 			pb->geqs[0].key = 1;
3581*e4b17023SJohn Marino 			pb->geqs[0].color = l_color;
3582*e4b17023SJohn Marino 			pb->geqs[0].touched = 0;
3583*e4b17023SJohn Marino 			pb->num_geqs = 1;
3584*e4b17023SJohn Marino 		      }
3585*e4b17023SJohn Marino 
3586*e4b17023SJohn Marino 		    if (upper_bound < pos_infinity)
3587*e4b17023SJohn Marino 		      {
3588*e4b17023SJohn Marino 			pb->geqs[pb->num_geqs].coef[0] = upper_bound;
3589*e4b17023SJohn Marino 			pb->geqs[pb->num_geqs].coef[1] = -1;
3590*e4b17023SJohn Marino 			pb->geqs[pb->num_geqs].key = -1;
3591*e4b17023SJohn Marino 			pb->geqs[pb->num_geqs].color = u_color;
3592*e4b17023SJohn Marino 			pb->geqs[pb->num_geqs].touched = 0;
3593*e4b17023SJohn Marino 			pb->num_geqs++;
3594*e4b17023SJohn Marino 		      }
3595*e4b17023SJohn Marino 		  }
3596*e4b17023SJohn Marino 	      }
3597*e4b17023SJohn Marino 	    else
3598*e4b17023SJohn Marino 	      pb->num_vars = 0;
3599*e4b17023SJohn Marino 
3600*e4b17023SJohn Marino 	    omega_problem_reduced (pb);
3601*e4b17023SJohn Marino 	    return omega_false;
3602*e4b17023SJohn Marino 	  }
3603*e4b17023SJohn Marino 
3604*e4b17023SJohn Marino 	if (original_problem != no_problem
3605*e4b17023SJohn Marino 	    && l_color == omega_black
3606*e4b17023SJohn Marino 	    && u_color == omega_black
3607*e4b17023SJohn Marino 	    && !conservative
3608*e4b17023SJohn Marino 	    && lower_bound == upper_bound)
3609*e4b17023SJohn Marino 	  {
3610*e4b17023SJohn Marino 	    pb->eqs[0].coef[0] = -lower_bound;
3611*e4b17023SJohn Marino 	    pb->eqs[0].coef[1] = 1;
3612*e4b17023SJohn Marino 	    pb->num_eqs = 1;
3613*e4b17023SJohn Marino 	    adding_equality_constraint (pb, 0);
3614*e4b17023SJohn Marino 	  }
3615*e4b17023SJohn Marino 
3616*e4b17023SJohn Marino 	return omega_true;
3617*e4b17023SJohn Marino       }
3618*e4b17023SJohn Marino 
3619*e4b17023SJohn Marino     if (!pb->variables_freed)
3620*e4b17023SJohn Marino       {
3621*e4b17023SJohn Marino 	pb->variables_freed = true;
3622*e4b17023SJohn Marino 
3623*e4b17023SJohn Marino 	if (desired_res != omega_simplify)
3624*e4b17023SJohn Marino 	  omega_free_eliminations (pb, 0);
3625*e4b17023SJohn Marino 	else
3626*e4b17023SJohn Marino 	  omega_free_eliminations (pb, pb->safe_vars);
3627*e4b17023SJohn Marino 
3628*e4b17023SJohn Marino 	n_vars = pb->num_vars;
3629*e4b17023SJohn Marino 
3630*e4b17023SJohn Marino 	if (n_vars == 1)
3631*e4b17023SJohn Marino 	  continue;
3632*e4b17023SJohn Marino       }
3633*e4b17023SJohn Marino 
3634*e4b17023SJohn Marino     switch (normalize_omega_problem (pb))
3635*e4b17023SJohn Marino       {
3636*e4b17023SJohn Marino       case normalize_false:
3637*e4b17023SJohn Marino 	return omega_false;
3638*e4b17023SJohn Marino 	break;
3639*e4b17023SJohn Marino 
3640*e4b17023SJohn Marino       case normalize_coupled:
3641*e4b17023SJohn Marino 	coupled_subscripts = true;
3642*e4b17023SJohn Marino 	break;
3643*e4b17023SJohn Marino 
3644*e4b17023SJohn Marino       case normalize_uncoupled:
3645*e4b17023SJohn Marino 	coupled_subscripts = false;
3646*e4b17023SJohn Marino 	break;
3647*e4b17023SJohn Marino 
3648*e4b17023SJohn Marino       default:
3649*e4b17023SJohn Marino 	gcc_unreachable ();
3650*e4b17023SJohn Marino       }
3651*e4b17023SJohn Marino 
3652*e4b17023SJohn Marino     n_vars = pb->num_vars;
3653*e4b17023SJohn Marino 
3654*e4b17023SJohn Marino     if (dump_file && (dump_flags & TDF_DETAILS))
3655*e4b17023SJohn Marino       {
3656*e4b17023SJohn Marino 	fprintf (dump_file, "\nafter normalization:\n");
3657*e4b17023SJohn Marino 	omega_print_problem (dump_file, pb);
3658*e4b17023SJohn Marino 	fprintf (dump_file, "\n");
3659*e4b17023SJohn Marino 	fprintf (dump_file, "eliminating variable using Fourier-Motzkin.\n");
3660*e4b17023SJohn Marino       }
3661*e4b17023SJohn Marino 
3662*e4b17023SJohn Marino     do {
3663*e4b17023SJohn Marino       int parallel_difference = INT_MAX;
3664*e4b17023SJohn Marino       int best_parallel_eqn = -1;
3665*e4b17023SJohn Marino       int minC, maxC, minCj = 0;
3666*e4b17023SJohn Marino       int lower_bound_count = 0;
3667*e4b17023SJohn Marino       int e2, Le = 0, Ue;
3668*e4b17023SJohn Marino       bool possible_easy_int_solution;
3669*e4b17023SJohn Marino       int max_splinters = 1;
3670*e4b17023SJohn Marino       bool exact = false;
3671*e4b17023SJohn Marino       bool lucky_exact = false;
3672*e4b17023SJohn Marino       int best = (INT_MAX);
3673*e4b17023SJohn Marino       int j = 0, jLe = 0, jLowerBoundCount = 0;
3674*e4b17023SJohn Marino 
3675*e4b17023SJohn Marino 
3676*e4b17023SJohn Marino       eliminate_again = false;
3677*e4b17023SJohn Marino 
3678*e4b17023SJohn Marino       if (pb->num_eqs > 0)
3679*e4b17023SJohn Marino 	return omega_solve_problem (pb, desired_res);
3680*e4b17023SJohn Marino 
3681*e4b17023SJohn Marino       if (!coupled_subscripts)
3682*e4b17023SJohn Marino 	{
3683*e4b17023SJohn Marino 	  if (pb->safe_vars == 0)
3684*e4b17023SJohn Marino 	    pb->num_geqs = 0;
3685*e4b17023SJohn Marino 	  else
3686*e4b17023SJohn Marino 	    for (e = pb->num_geqs - 1; e >= 0; e--)
3687*e4b17023SJohn Marino 	      if (!omega_safe_var_p (pb, abs (pb->geqs[e].key)))
3688*e4b17023SJohn Marino 		omega_delete_geq (pb, e, n_vars);
3689*e4b17023SJohn Marino 
3690*e4b17023SJohn Marino 	  pb->num_vars = pb->safe_vars;
3691*e4b17023SJohn Marino 
3692*e4b17023SJohn Marino 	  if (desired_res == omega_simplify)
3693*e4b17023SJohn Marino 	    {
3694*e4b17023SJohn Marino 	      omega_problem_reduced (pb);
3695*e4b17023SJohn Marino 	      return omega_false;
3696*e4b17023SJohn Marino 	    }
3697*e4b17023SJohn Marino 
3698*e4b17023SJohn Marino 	  return omega_true;
3699*e4b17023SJohn Marino 	}
3700*e4b17023SJohn Marino 
3701*e4b17023SJohn Marino       if (desired_res != omega_simplify)
3702*e4b17023SJohn Marino 	fv = 0;
3703*e4b17023SJohn Marino       else
3704*e4b17023SJohn Marino 	fv = pb->safe_vars;
3705*e4b17023SJohn Marino 
3706*e4b17023SJohn Marino       if (pb->num_geqs == 0)
3707*e4b17023SJohn Marino 	{
3708*e4b17023SJohn Marino 	  if (desired_res == omega_simplify)
3709*e4b17023SJohn Marino 	    {
3710*e4b17023SJohn Marino 	      pb->num_vars = pb->safe_vars;
3711*e4b17023SJohn Marino 	      omega_problem_reduced (pb);
3712*e4b17023SJohn Marino 	      return omega_false;
3713*e4b17023SJohn Marino 	    }
3714*e4b17023SJohn Marino 	  return omega_true;
3715*e4b17023SJohn Marino 	}
3716*e4b17023SJohn Marino 
3717*e4b17023SJohn Marino       if (desired_res == omega_simplify && n_vars == pb->safe_vars)
3718*e4b17023SJohn Marino 	{
3719*e4b17023SJohn Marino 	  omega_problem_reduced (pb);
3720*e4b17023SJohn Marino 	  return omega_false;
3721*e4b17023SJohn Marino 	}
3722*e4b17023SJohn Marino 
3723*e4b17023SJohn Marino       if (pb->num_geqs > OMEGA_MAX_GEQS - 30
3724*e4b17023SJohn Marino 	  || pb->num_geqs > 2 * n_vars * n_vars + 4 * n_vars + 10)
3725*e4b17023SJohn Marino 	{
3726*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
3727*e4b17023SJohn Marino 	    fprintf (dump_file,
3728*e4b17023SJohn Marino 		     "TOO MANY EQUATIONS; "
3729*e4b17023SJohn Marino 		     "%d equations, %d variables, "
3730*e4b17023SJohn Marino 		     "ELIMINATING REDUNDANT ONES\n",
3731*e4b17023SJohn Marino 		     pb->num_geqs, n_vars);
3732*e4b17023SJohn Marino 
3733*e4b17023SJohn Marino 	  if (!omega_eliminate_redundant (pb, false))
3734*e4b17023SJohn Marino 	    return omega_false;
3735*e4b17023SJohn Marino 
3736*e4b17023SJohn Marino 	  n_vars = pb->num_vars;
3737*e4b17023SJohn Marino 
3738*e4b17023SJohn Marino 	  if (pb->num_eqs > 0)
3739*e4b17023SJohn Marino 	    return omega_solve_problem (pb, desired_res);
3740*e4b17023SJohn Marino 
3741*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
3742*e4b17023SJohn Marino 	    fprintf (dump_file, "END ELIMINATION OF REDUNDANT EQUATIONS\n");
3743*e4b17023SJohn Marino 	}
3744*e4b17023SJohn Marino 
3745*e4b17023SJohn Marino       if (desired_res != omega_simplify)
3746*e4b17023SJohn Marino 	fv = 0;
3747*e4b17023SJohn Marino       else
3748*e4b17023SJohn Marino 	fv = pb->safe_vars;
3749*e4b17023SJohn Marino 
3750*e4b17023SJohn Marino       for (i = n_vars; i != fv; i--)
3751*e4b17023SJohn Marino 	{
3752*e4b17023SJohn Marino 	  int score;
3753*e4b17023SJohn Marino 	  int ub = -2;
3754*e4b17023SJohn Marino 	  int lb = -2;
3755*e4b17023SJohn Marino 	  bool lucky = false;
3756*e4b17023SJohn Marino 	  int upper_bound_count = 0;
3757*e4b17023SJohn Marino 
3758*e4b17023SJohn Marino 	  lower_bound_count = 0;
3759*e4b17023SJohn Marino 	  minC = maxC = 0;
3760*e4b17023SJohn Marino 
3761*e4b17023SJohn Marino 	  for (e = pb->num_geqs - 1; e >= 0; e--)
3762*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[i] < 0)
3763*e4b17023SJohn Marino 	      {
3764*e4b17023SJohn Marino 		minC = MIN (minC, pb->geqs[e].coef[i]);
3765*e4b17023SJohn Marino 		upper_bound_count++;
3766*e4b17023SJohn Marino 		if (pb->geqs[e].coef[i] < -1)
3767*e4b17023SJohn Marino 		  {
3768*e4b17023SJohn Marino 		    if (ub == -2)
3769*e4b17023SJohn Marino 		      ub = e;
3770*e4b17023SJohn Marino 		    else
3771*e4b17023SJohn Marino 		      ub = -1;
3772*e4b17023SJohn Marino 		  }
3773*e4b17023SJohn Marino 	      }
3774*e4b17023SJohn Marino 	    else if (pb->geqs[e].coef[i] > 0)
3775*e4b17023SJohn Marino 	      {
3776*e4b17023SJohn Marino 		maxC = MAX (maxC, pb->geqs[e].coef[i]);
3777*e4b17023SJohn Marino 		lower_bound_count++;
3778*e4b17023SJohn Marino 		Le = e;
3779*e4b17023SJohn Marino 		if (pb->geqs[e].coef[i] > 1)
3780*e4b17023SJohn Marino 		  {
3781*e4b17023SJohn Marino 		    if (lb == -2)
3782*e4b17023SJohn Marino 		      lb = e;
3783*e4b17023SJohn Marino 		    else
3784*e4b17023SJohn Marino 		      lb = -1;
3785*e4b17023SJohn Marino 		  }
3786*e4b17023SJohn Marino 	      }
3787*e4b17023SJohn Marino 
3788*e4b17023SJohn Marino 	  if (lower_bound_count == 0
3789*e4b17023SJohn Marino 	      || upper_bound_count == 0)
3790*e4b17023SJohn Marino 	    {
3791*e4b17023SJohn Marino 	      lower_bound_count = 0;
3792*e4b17023SJohn Marino 	      break;
3793*e4b17023SJohn Marino 	    }
3794*e4b17023SJohn Marino 
3795*e4b17023SJohn Marino 	  if (ub >= 0 && lb >= 0
3796*e4b17023SJohn Marino 	      && pb->geqs[lb].key == -pb->geqs[ub].key)
3797*e4b17023SJohn Marino 	    {
3798*e4b17023SJohn Marino 	      int Lc = pb->geqs[lb].coef[i];
3799*e4b17023SJohn Marino 	      int Uc = -pb->geqs[ub].coef[i];
3800*e4b17023SJohn Marino 	      int diff =
3801*e4b17023SJohn Marino 		Lc * pb->geqs[ub].coef[0] + Uc * pb->geqs[lb].coef[0];
3802*e4b17023SJohn Marino 	      lucky = (diff >= (Uc - 1) * (Lc - 1));
3803*e4b17023SJohn Marino 	    }
3804*e4b17023SJohn Marino 
3805*e4b17023SJohn Marino 	  if (maxC == 1
3806*e4b17023SJohn Marino 	      || minC == -1
3807*e4b17023SJohn Marino 	      || lucky
3808*e4b17023SJohn Marino 	      || in_approximate_mode)
3809*e4b17023SJohn Marino 	    {
3810*e4b17023SJohn Marino 	      score = upper_bound_count * lower_bound_count;
3811*e4b17023SJohn Marino 
3812*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3813*e4b17023SJohn Marino 		fprintf (dump_file,
3814*e4b17023SJohn Marino 			 "For %s, exact, score = %d*%d, range = %d ... %d,"
3815*e4b17023SJohn Marino 			 "\nlucky = %d, in_approximate_mode=%d \n",
3816*e4b17023SJohn Marino 			 omega_variable_to_str (pb, i),
3817*e4b17023SJohn Marino 			 upper_bound_count,
3818*e4b17023SJohn Marino 			 lower_bound_count, minC, maxC, lucky,
3819*e4b17023SJohn Marino 			 in_approximate_mode);
3820*e4b17023SJohn Marino 
3821*e4b17023SJohn Marino 	      if (!exact
3822*e4b17023SJohn Marino 		  || score < best)
3823*e4b17023SJohn Marino 		{
3824*e4b17023SJohn Marino 
3825*e4b17023SJohn Marino 		  best = score;
3826*e4b17023SJohn Marino 		  j = i;
3827*e4b17023SJohn Marino 		  minCj = minC;
3828*e4b17023SJohn Marino 		  jLe = Le;
3829*e4b17023SJohn Marino 		  jLowerBoundCount = lower_bound_count;
3830*e4b17023SJohn Marino 		  exact = true;
3831*e4b17023SJohn Marino 		  lucky_exact = lucky;
3832*e4b17023SJohn Marino 		  if (score == 1)
3833*e4b17023SJohn Marino 		    break;
3834*e4b17023SJohn Marino 		}
3835*e4b17023SJohn Marino 	    }
3836*e4b17023SJohn Marino 	  else if (!exact)
3837*e4b17023SJohn Marino 	    {
3838*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
3839*e4b17023SJohn Marino 		fprintf (dump_file,
3840*e4b17023SJohn Marino 			 "For %s, non-exact, score = %d*%d,"
3841*e4b17023SJohn Marino 			 "range = %d ... %d \n",
3842*e4b17023SJohn Marino 			 omega_variable_to_str (pb, i),
3843*e4b17023SJohn Marino 			 upper_bound_count,
3844*e4b17023SJohn Marino 			 lower_bound_count, minC, maxC);
3845*e4b17023SJohn Marino 
3846*e4b17023SJohn Marino 	      score = maxC - minC;
3847*e4b17023SJohn Marino 
3848*e4b17023SJohn Marino 	      if (best > score)
3849*e4b17023SJohn Marino 		{
3850*e4b17023SJohn Marino 		  best = score;
3851*e4b17023SJohn Marino 		  j = i;
3852*e4b17023SJohn Marino 		  minCj = minC;
3853*e4b17023SJohn Marino 		  jLe = Le;
3854*e4b17023SJohn Marino 		  jLowerBoundCount = lower_bound_count;
3855*e4b17023SJohn Marino 		}
3856*e4b17023SJohn Marino 	    }
3857*e4b17023SJohn Marino 	}
3858*e4b17023SJohn Marino 
3859*e4b17023SJohn Marino       if (lower_bound_count == 0)
3860*e4b17023SJohn Marino 	{
3861*e4b17023SJohn Marino 	  omega_free_eliminations (pb, pb->safe_vars);
3862*e4b17023SJohn Marino 	  n_vars = pb->num_vars;
3863*e4b17023SJohn Marino 	  eliminate_again = true;
3864*e4b17023SJohn Marino 	  continue;
3865*e4b17023SJohn Marino 	}
3866*e4b17023SJohn Marino 
3867*e4b17023SJohn Marino       i = j;
3868*e4b17023SJohn Marino       minC = minCj;
3869*e4b17023SJohn Marino       Le = jLe;
3870*e4b17023SJohn Marino       lower_bound_count = jLowerBoundCount;
3871*e4b17023SJohn Marino 
3872*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
3873*e4b17023SJohn Marino 	if (pb->geqs[e].coef[i] > 0)
3874*e4b17023SJohn Marino 	  {
3875*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[i] == -minC)
3876*e4b17023SJohn Marino 	      max_splinters += -minC - 1;
3877*e4b17023SJohn Marino 	    else
3878*e4b17023SJohn Marino 	      max_splinters +=
3879*e4b17023SJohn Marino 		pos_mul_hwi ((pb->geqs[e].coef[i] - 1),
3880*e4b17023SJohn Marino 			     (-minC - 1)) / (-minC) + 1;
3881*e4b17023SJohn Marino 	  }
3882*e4b17023SJohn Marino 
3883*e4b17023SJohn Marino       /* #ifdef Omega3 */
3884*e4b17023SJohn Marino       /* Trying to produce exact elimination by finding redundant
3885*e4b17023SJohn Marino 	 constraints.  */
3886*e4b17023SJohn Marino       if (!exact && !tried_eliminating_redundant)
3887*e4b17023SJohn Marino 	{
3888*e4b17023SJohn Marino 	  omega_eliminate_redundant (pb, false);
3889*e4b17023SJohn Marino 	  tried_eliminating_redundant = true;
3890*e4b17023SJohn Marino 	  eliminate_again = true;
3891*e4b17023SJohn Marino 	  continue;
3892*e4b17023SJohn Marino 	}
3893*e4b17023SJohn Marino       tried_eliminating_redundant = false;
3894*e4b17023SJohn Marino       /* #endif */
3895*e4b17023SJohn Marino 
3896*e4b17023SJohn Marino       if (return_single_result && desired_res == omega_simplify && !exact)
3897*e4b17023SJohn Marino 	{
3898*e4b17023SJohn Marino 	  omega_problem_reduced (pb);
3899*e4b17023SJohn Marino 	  return omega_true;
3900*e4b17023SJohn Marino 	}
3901*e4b17023SJohn Marino 
3902*e4b17023SJohn Marino       /* #ifndef Omega3 */
3903*e4b17023SJohn Marino       /* Trying to produce exact elimination by finding redundant
3904*e4b17023SJohn Marino 	 constraints.  */
3905*e4b17023SJohn Marino       if (!exact && !tried_eliminating_redundant)
3906*e4b17023SJohn Marino 	{
3907*e4b17023SJohn Marino 	  omega_eliminate_redundant (pb, false);
3908*e4b17023SJohn Marino 	  tried_eliminating_redundant = true;
3909*e4b17023SJohn Marino 	  continue;
3910*e4b17023SJohn Marino 	}
3911*e4b17023SJohn Marino       tried_eliminating_redundant = false;
3912*e4b17023SJohn Marino       /* #endif */
3913*e4b17023SJohn Marino 
3914*e4b17023SJohn Marino       if (!exact)
3915*e4b17023SJohn Marino 	{
3916*e4b17023SJohn Marino 	  int e1, e2;
3917*e4b17023SJohn Marino 
3918*e4b17023SJohn Marino 	  for (e1 = pb->num_geqs - 1; e1 >= 0; e1--)
3919*e4b17023SJohn Marino 	    if (pb->geqs[e1].color == omega_black)
3920*e4b17023SJohn Marino 	      for (e2 = e1 - 1; e2 >= 0; e2--)
3921*e4b17023SJohn Marino 		if (pb->geqs[e2].color == omega_black
3922*e4b17023SJohn Marino 		    && pb->geqs[e1].key == -pb->geqs[e2].key
3923*e4b17023SJohn Marino 		    && ((pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3924*e4b17023SJohn Marino 			* (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3925*e4b17023SJohn Marino 			/ 2 < parallel_difference))
3926*e4b17023SJohn Marino 		  {
3927*e4b17023SJohn Marino 		    parallel_difference =
3928*e4b17023SJohn Marino 		      (pb->geqs[e1].coef[0] + pb->geqs[e2].coef[0])
3929*e4b17023SJohn Marino 		      * (3 - single_var_geq (&pb->geqs[e1], pb->num_vars))
3930*e4b17023SJohn Marino 		      / 2;
3931*e4b17023SJohn Marino 		    best_parallel_eqn = e1;
3932*e4b17023SJohn Marino 		  }
3933*e4b17023SJohn Marino 
3934*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS)
3935*e4b17023SJohn Marino 	      && best_parallel_eqn >= 0)
3936*e4b17023SJohn Marino 	    {
3937*e4b17023SJohn Marino 	      fprintf (dump_file,
3938*e4b17023SJohn Marino 		       "Possible parallel projection, diff = %d, in ",
3939*e4b17023SJohn Marino 		       parallel_difference);
3940*e4b17023SJohn Marino 	      omega_print_geq (dump_file, pb, &(pb->geqs[best_parallel_eqn]));
3941*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
3942*e4b17023SJohn Marino 	      omega_print_problem (dump_file, pb);
3943*e4b17023SJohn Marino 	    }
3944*e4b17023SJohn Marino 	}
3945*e4b17023SJohn Marino 
3946*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
3947*e4b17023SJohn Marino 	{
3948*e4b17023SJohn Marino 	  fprintf (dump_file, "going to eliminate %s, (%d,%d,%d)\n",
3949*e4b17023SJohn Marino 		   omega_variable_to_str (pb, i), i, minC,
3950*e4b17023SJohn Marino 		   lower_bound_count);
3951*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
3952*e4b17023SJohn Marino 
3953*e4b17023SJohn Marino 	  if (lucky_exact)
3954*e4b17023SJohn Marino 	    fprintf (dump_file, "(a lucky exact elimination)\n");
3955*e4b17023SJohn Marino 
3956*e4b17023SJohn Marino 	  else if (exact)
3957*e4b17023SJohn Marino 	    fprintf (dump_file, "(an exact elimination)\n");
3958*e4b17023SJohn Marino 
3959*e4b17023SJohn Marino 	  fprintf (dump_file, "Max # of splinters = %d\n", max_splinters);
3960*e4b17023SJohn Marino 	}
3961*e4b17023SJohn Marino 
3962*e4b17023SJohn Marino       gcc_assert (max_splinters >= 1);
3963*e4b17023SJohn Marino 
3964*e4b17023SJohn Marino       if (!exact && desired_res == omega_simplify && best_parallel_eqn >= 0
3965*e4b17023SJohn Marino 	  && parallel_difference <= max_splinters)
3966*e4b17023SJohn Marino 	return parallel_splinter (pb, best_parallel_eqn, parallel_difference,
3967*e4b17023SJohn Marino 				  desired_res);
3968*e4b17023SJohn Marino 
3969*e4b17023SJohn Marino       smoothed = false;
3970*e4b17023SJohn Marino 
3971*e4b17023SJohn Marino       if (i != n_vars)
3972*e4b17023SJohn Marino 	{
3973*e4b17023SJohn Marino 	  int t;
3974*e4b17023SJohn Marino 	  int j = pb->num_vars;
3975*e4b17023SJohn Marino 
3976*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
3977*e4b17023SJohn Marino 	    {
3978*e4b17023SJohn Marino 	      fprintf (dump_file, "Swapping %d and %d\n", i, j);
3979*e4b17023SJohn Marino 	      omega_print_problem (dump_file, pb);
3980*e4b17023SJohn Marino 	    }
3981*e4b17023SJohn Marino 
3982*e4b17023SJohn Marino 	  swap (&pb->var[i], &pb->var[j]);
3983*e4b17023SJohn Marino 
3984*e4b17023SJohn Marino 	  for (e = pb->num_geqs - 1; e >= 0; e--)
3985*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[i] != pb->geqs[e].coef[j])
3986*e4b17023SJohn Marino 	      {
3987*e4b17023SJohn Marino 		pb->geqs[e].touched = 1;
3988*e4b17023SJohn Marino 		t = pb->geqs[e].coef[i];
3989*e4b17023SJohn Marino 		pb->geqs[e].coef[i] = pb->geqs[e].coef[j];
3990*e4b17023SJohn Marino 		pb->geqs[e].coef[j] = t;
3991*e4b17023SJohn Marino 	      }
3992*e4b17023SJohn Marino 
3993*e4b17023SJohn Marino 	  for (e = pb->num_subs - 1; e >= 0; e--)
3994*e4b17023SJohn Marino 	    if (pb->subs[e].coef[i] != pb->subs[e].coef[j])
3995*e4b17023SJohn Marino 	      {
3996*e4b17023SJohn Marino 		t = pb->subs[e].coef[i];
3997*e4b17023SJohn Marino 		pb->subs[e].coef[i] = pb->subs[e].coef[j];
3998*e4b17023SJohn Marino 		pb->subs[e].coef[j] = t;
3999*e4b17023SJohn Marino 	      }
4000*e4b17023SJohn Marino 
4001*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
4002*e4b17023SJohn Marino 	    {
4003*e4b17023SJohn Marino 	      fprintf (dump_file, "Swapping complete \n");
4004*e4b17023SJohn Marino 	      omega_print_problem (dump_file, pb);
4005*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
4006*e4b17023SJohn Marino 	    }
4007*e4b17023SJohn Marino 
4008*e4b17023SJohn Marino 	  i = j;
4009*e4b17023SJohn Marino 	}
4010*e4b17023SJohn Marino 
4011*e4b17023SJohn Marino       else if (dump_file && (dump_flags & TDF_DETAILS))
4012*e4b17023SJohn Marino 	{
4013*e4b17023SJohn Marino 	  fprintf (dump_file, "No swap needed\n");
4014*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
4015*e4b17023SJohn Marino 	}
4016*e4b17023SJohn Marino 
4017*e4b17023SJohn Marino       pb->num_vars--;
4018*e4b17023SJohn Marino       n_vars = pb->num_vars;
4019*e4b17023SJohn Marino 
4020*e4b17023SJohn Marino       if (exact)
4021*e4b17023SJohn Marino 	{
4022*e4b17023SJohn Marino 	  if (n_vars == 1)
4023*e4b17023SJohn Marino 	    {
4024*e4b17023SJohn Marino 	      int upper_bound = pos_infinity;
4025*e4b17023SJohn Marino 	      int lower_bound = neg_infinity;
4026*e4b17023SJohn Marino 	      enum omega_eqn_color ub_color = omega_black;
4027*e4b17023SJohn Marino 	      enum omega_eqn_color lb_color = omega_black;
4028*e4b17023SJohn Marino 	      int topeqn = pb->num_geqs - 1;
4029*e4b17023SJohn Marino 	      int Lc = pb->geqs[Le].coef[i];
4030*e4b17023SJohn Marino 
4031*e4b17023SJohn Marino 	      for (Le = topeqn; Le >= 0; Le--)
4032*e4b17023SJohn Marino 		if ((Lc = pb->geqs[Le].coef[i]) == 0)
4033*e4b17023SJohn Marino 		  {
4034*e4b17023SJohn Marino 		    if (pb->geqs[Le].coef[1] == 1)
4035*e4b17023SJohn Marino 		      {
4036*e4b17023SJohn Marino 			int constantTerm = -pb->geqs[Le].coef[0];
4037*e4b17023SJohn Marino 
4038*e4b17023SJohn Marino 			if (constantTerm > lower_bound ||
4039*e4b17023SJohn Marino 			    (constantTerm == lower_bound &&
4040*e4b17023SJohn Marino 			     !omega_eqn_is_red (&pb->geqs[Le], desired_res)))
4041*e4b17023SJohn Marino 			  {
4042*e4b17023SJohn Marino 			    lower_bound = constantTerm;
4043*e4b17023SJohn Marino 			    lb_color = pb->geqs[Le].color;
4044*e4b17023SJohn Marino 			  }
4045*e4b17023SJohn Marino 
4046*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4047*e4b17023SJohn Marino 			  {
4048*e4b17023SJohn Marino 			    if (pb->geqs[Le].color == omega_black)
4049*e4b17023SJohn Marino 			      fprintf (dump_file, " :::=> %s >= %d\n",
4050*e4b17023SJohn Marino 				       omega_variable_to_str (pb, 1),
4051*e4b17023SJohn Marino 				       constantTerm);
4052*e4b17023SJohn Marino 			    else
4053*e4b17023SJohn Marino 			      fprintf (dump_file,
4054*e4b17023SJohn Marino 				       " :::=> [%s >= %d]\n",
4055*e4b17023SJohn Marino 				       omega_variable_to_str (pb, 1),
4056*e4b17023SJohn Marino 				       constantTerm);
4057*e4b17023SJohn Marino 			  }
4058*e4b17023SJohn Marino 		      }
4059*e4b17023SJohn Marino 		    else
4060*e4b17023SJohn Marino 		      {
4061*e4b17023SJohn Marino 			int constantTerm = pb->geqs[Le].coef[0];
4062*e4b17023SJohn Marino 			if (constantTerm < upper_bound ||
4063*e4b17023SJohn Marino 			    (constantTerm == upper_bound
4064*e4b17023SJohn Marino 			     && !omega_eqn_is_red (&pb->geqs[Le],
4065*e4b17023SJohn Marino 						   desired_res)))
4066*e4b17023SJohn Marino 			  {
4067*e4b17023SJohn Marino 			    upper_bound = constantTerm;
4068*e4b17023SJohn Marino 			    ub_color = pb->geqs[Le].color;
4069*e4b17023SJohn Marino 			  }
4070*e4b17023SJohn Marino 
4071*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4072*e4b17023SJohn Marino 			  {
4073*e4b17023SJohn Marino 			    if (pb->geqs[Le].color == omega_black)
4074*e4b17023SJohn Marino 			      fprintf (dump_file, " :::=> %s <= %d\n",
4075*e4b17023SJohn Marino 				       omega_variable_to_str (pb, 1),
4076*e4b17023SJohn Marino 				       constantTerm);
4077*e4b17023SJohn Marino 			    else
4078*e4b17023SJohn Marino 			      fprintf (dump_file,
4079*e4b17023SJohn Marino 				       " :::=> [%s <= %d]\n",
4080*e4b17023SJohn Marino 				       omega_variable_to_str (pb, 1),
4081*e4b17023SJohn Marino 				       constantTerm);
4082*e4b17023SJohn Marino 			  }
4083*e4b17023SJohn Marino 		      }
4084*e4b17023SJohn Marino 		  }
4085*e4b17023SJohn Marino 		else if (Lc > 0)
4086*e4b17023SJohn Marino 		  for (Ue = topeqn; Ue >= 0; Ue--)
4087*e4b17023SJohn Marino 		    if (pb->geqs[Ue].coef[i] < 0
4088*e4b17023SJohn Marino 			&& pb->geqs[Le].key != -pb->geqs[Ue].key)
4089*e4b17023SJohn Marino 		      {
4090*e4b17023SJohn Marino 			int Uc = -pb->geqs[Ue].coef[i];
4091*e4b17023SJohn Marino 			int coefficient = pb->geqs[Ue].coef[1] * Lc
4092*e4b17023SJohn Marino 			  + pb->geqs[Le].coef[1] * Uc;
4093*e4b17023SJohn Marino 			int constantTerm = pb->geqs[Ue].coef[0] * Lc
4094*e4b17023SJohn Marino 			  + pb->geqs[Le].coef[0] * Uc;
4095*e4b17023SJohn Marino 
4096*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4097*e4b17023SJohn Marino 			  {
4098*e4b17023SJohn Marino 			    omega_print_geq_extra (dump_file, pb,
4099*e4b17023SJohn Marino 						   &(pb->geqs[Ue]));
4100*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4101*e4b17023SJohn Marino 			    omega_print_geq_extra (dump_file, pb,
4102*e4b17023SJohn Marino 						   &(pb->geqs[Le]));
4103*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4104*e4b17023SJohn Marino 			  }
4105*e4b17023SJohn Marino 
4106*e4b17023SJohn Marino 			if (coefficient > 0)
4107*e4b17023SJohn Marino 			  {
4108*e4b17023SJohn Marino 			    constantTerm = -int_div (constantTerm, coefficient);
4109*e4b17023SJohn Marino 
4110*e4b17023SJohn Marino 			    if (constantTerm > lower_bound
4111*e4b17023SJohn Marino 				|| (constantTerm == lower_bound
4112*e4b17023SJohn Marino 				    && (desired_res != omega_simplify
4113*e4b17023SJohn Marino 					|| (pb->geqs[Ue].color == omega_black
4114*e4b17023SJohn Marino 					    && pb->geqs[Le].color == omega_black))))
4115*e4b17023SJohn Marino 			      {
4116*e4b17023SJohn Marino 				lower_bound = constantTerm;
4117*e4b17023SJohn Marino 				lb_color = (pb->geqs[Ue].color == omega_red
4118*e4b17023SJohn Marino 					    || pb->geqs[Le].color == omega_red)
4119*e4b17023SJohn Marino 				  ? omega_red : omega_black;
4120*e4b17023SJohn Marino 			      }
4121*e4b17023SJohn Marino 
4122*e4b17023SJohn Marino 			    if (dump_file && (dump_flags & TDF_DETAILS))
4123*e4b17023SJohn Marino 			      {
4124*e4b17023SJohn Marino 				if (pb->geqs[Ue].color == omega_red
4125*e4b17023SJohn Marino 				    || pb->geqs[Le].color == omega_red)
4126*e4b17023SJohn Marino 				  fprintf (dump_file,
4127*e4b17023SJohn Marino 					   " ::=> [%s >= %d]\n",
4128*e4b17023SJohn Marino 					   omega_variable_to_str (pb, 1),
4129*e4b17023SJohn Marino 					   constantTerm);
4130*e4b17023SJohn Marino 				else
4131*e4b17023SJohn Marino 				  fprintf (dump_file,
4132*e4b17023SJohn Marino 					   " ::=> %s >= %d\n",
4133*e4b17023SJohn Marino 					   omega_variable_to_str (pb, 1),
4134*e4b17023SJohn Marino 					   constantTerm);
4135*e4b17023SJohn Marino 			      }
4136*e4b17023SJohn Marino 			  }
4137*e4b17023SJohn Marino 			else
4138*e4b17023SJohn Marino 			  {
4139*e4b17023SJohn Marino 			    constantTerm = int_div (constantTerm, -coefficient);
4140*e4b17023SJohn Marino 			    if (constantTerm < upper_bound
4141*e4b17023SJohn Marino 				|| (constantTerm == upper_bound
4142*e4b17023SJohn Marino 				    && pb->geqs[Ue].color == omega_black
4143*e4b17023SJohn Marino 				    && pb->geqs[Le].color == omega_black))
4144*e4b17023SJohn Marino 			      {
4145*e4b17023SJohn Marino 				upper_bound = constantTerm;
4146*e4b17023SJohn Marino 				ub_color = (pb->geqs[Ue].color == omega_red
4147*e4b17023SJohn Marino 					    || pb->geqs[Le].color == omega_red)
4148*e4b17023SJohn Marino 				  ? omega_red : omega_black;
4149*e4b17023SJohn Marino 			      }
4150*e4b17023SJohn Marino 
4151*e4b17023SJohn Marino 			    if (dump_file
4152*e4b17023SJohn Marino 				&& (dump_flags & TDF_DETAILS))
4153*e4b17023SJohn Marino 			      {
4154*e4b17023SJohn Marino 				if (pb->geqs[Ue].color == omega_red
4155*e4b17023SJohn Marino 				    || pb->geqs[Le].color == omega_red)
4156*e4b17023SJohn Marino 				  fprintf (dump_file,
4157*e4b17023SJohn Marino 					   " ::=> [%s <= %d]\n",
4158*e4b17023SJohn Marino 					   omega_variable_to_str (pb, 1),
4159*e4b17023SJohn Marino 					   constantTerm);
4160*e4b17023SJohn Marino 				else
4161*e4b17023SJohn Marino 				  fprintf (dump_file,
4162*e4b17023SJohn Marino 					   " ::=> %s <= %d\n",
4163*e4b17023SJohn Marino 					   omega_variable_to_str (pb, 1),
4164*e4b17023SJohn Marino 					   constantTerm);
4165*e4b17023SJohn Marino 			      }
4166*e4b17023SJohn Marino 			  }
4167*e4b17023SJohn Marino 		      }
4168*e4b17023SJohn Marino 
4169*e4b17023SJohn Marino 	      pb->num_geqs = 0;
4170*e4b17023SJohn Marino 
4171*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4172*e4b17023SJohn Marino 		fprintf (dump_file,
4173*e4b17023SJohn Marino 			 " therefore, %c%d <= %c%s%c <= %d%c\n",
4174*e4b17023SJohn Marino 			 lb_color == omega_red ? '[' : ' ', lower_bound,
4175*e4b17023SJohn Marino 			 (lb_color == omega_red && ub_color == omega_black)
4176*e4b17023SJohn Marino 			 ? ']' : ' ',
4177*e4b17023SJohn Marino 			 omega_variable_to_str (pb, 1),
4178*e4b17023SJohn Marino 			 (lb_color == omega_black && ub_color == omega_red)
4179*e4b17023SJohn Marino 			 ? '[' : ' ',
4180*e4b17023SJohn Marino 			 upper_bound, ub_color == omega_red ? ']' : ' ');
4181*e4b17023SJohn Marino 
4182*e4b17023SJohn Marino 	      if (lower_bound > upper_bound)
4183*e4b17023SJohn Marino 		return omega_false;
4184*e4b17023SJohn Marino 
4185*e4b17023SJohn Marino 	      if (pb->safe_vars == 1)
4186*e4b17023SJohn Marino 		{
4187*e4b17023SJohn Marino 		  if (upper_bound == lower_bound
4188*e4b17023SJohn Marino 		      && !(ub_color == omega_red || lb_color == omega_red)
4189*e4b17023SJohn Marino 		      && !please_no_equalities_in_simplified_problems)
4190*e4b17023SJohn Marino 		    {
4191*e4b17023SJohn Marino 		      pb->num_eqs++;
4192*e4b17023SJohn Marino 		      pb->eqs[0].coef[1] = -1;
4193*e4b17023SJohn Marino 		      pb->eqs[0].coef[0] = upper_bound;
4194*e4b17023SJohn Marino 
4195*e4b17023SJohn Marino 		      if (ub_color == omega_red
4196*e4b17023SJohn Marino 			  || lb_color == omega_red)
4197*e4b17023SJohn Marino 			pb->eqs[0].color = omega_red;
4198*e4b17023SJohn Marino 
4199*e4b17023SJohn Marino 		      if (desired_res == omega_simplify
4200*e4b17023SJohn Marino 			  && pb->eqs[0].color == omega_black)
4201*e4b17023SJohn Marino 			return omega_solve_problem (pb, desired_res);
4202*e4b17023SJohn Marino 		    }
4203*e4b17023SJohn Marino 
4204*e4b17023SJohn Marino 		  if (upper_bound != pos_infinity)
4205*e4b17023SJohn Marino 		    {
4206*e4b17023SJohn Marino 		      pb->geqs[0].coef[1] = -1;
4207*e4b17023SJohn Marino 		      pb->geqs[0].coef[0] = upper_bound;
4208*e4b17023SJohn Marino 		      pb->geqs[0].color = ub_color;
4209*e4b17023SJohn Marino 		      pb->geqs[0].key = -1;
4210*e4b17023SJohn Marino 		      pb->geqs[0].touched = 0;
4211*e4b17023SJohn Marino 		      pb->num_geqs++;
4212*e4b17023SJohn Marino 		    }
4213*e4b17023SJohn Marino 
4214*e4b17023SJohn Marino 		  if (lower_bound != neg_infinity)
4215*e4b17023SJohn Marino 		    {
4216*e4b17023SJohn Marino 		      pb->geqs[pb->num_geqs].coef[1] = 1;
4217*e4b17023SJohn Marino 		      pb->geqs[pb->num_geqs].coef[0] = -lower_bound;
4218*e4b17023SJohn Marino 		      pb->geqs[pb->num_geqs].color = lb_color;
4219*e4b17023SJohn Marino 		      pb->geqs[pb->num_geqs].key = 1;
4220*e4b17023SJohn Marino 		      pb->geqs[pb->num_geqs].touched = 0;
4221*e4b17023SJohn Marino 		      pb->num_geqs++;
4222*e4b17023SJohn Marino 		    }
4223*e4b17023SJohn Marino 		}
4224*e4b17023SJohn Marino 
4225*e4b17023SJohn Marino 	      if (desired_res == omega_simplify)
4226*e4b17023SJohn Marino 		{
4227*e4b17023SJohn Marino 		  omega_problem_reduced (pb);
4228*e4b17023SJohn Marino 		  return omega_false;
4229*e4b17023SJohn Marino 		}
4230*e4b17023SJohn Marino 	      else
4231*e4b17023SJohn Marino 		{
4232*e4b17023SJohn Marino 		  if (!conservative
4233*e4b17023SJohn Marino 		      && (desired_res != omega_simplify
4234*e4b17023SJohn Marino 			  || (lb_color == omega_black
4235*e4b17023SJohn Marino 			      && ub_color == omega_black))
4236*e4b17023SJohn Marino 		      && original_problem != no_problem
4237*e4b17023SJohn Marino 		      && lower_bound == upper_bound)
4238*e4b17023SJohn Marino 		    {
4239*e4b17023SJohn Marino 		      for (i = original_problem->num_vars; i >= 0; i--)
4240*e4b17023SJohn Marino 			if (original_problem->var[i] == pb->var[1])
4241*e4b17023SJohn Marino 			  break;
4242*e4b17023SJohn Marino 
4243*e4b17023SJohn Marino 		      if (i == 0)
4244*e4b17023SJohn Marino 			break;
4245*e4b17023SJohn Marino 
4246*e4b17023SJohn Marino 		      e = original_problem->num_eqs++;
4247*e4b17023SJohn Marino 		      omega_init_eqn_zero (&original_problem->eqs[e],
4248*e4b17023SJohn Marino 					   original_problem->num_vars);
4249*e4b17023SJohn Marino 		      original_problem->eqs[e].coef[i] = -1;
4250*e4b17023SJohn Marino 		      original_problem->eqs[e].coef[0] = upper_bound;
4251*e4b17023SJohn Marino 
4252*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
4253*e4b17023SJohn Marino 			{
4254*e4b17023SJohn Marino 			  fprintf (dump_file,
4255*e4b17023SJohn Marino 				   "adding equality %d to outer problem\n", e);
4256*e4b17023SJohn Marino 			  omega_print_problem (dump_file, original_problem);
4257*e4b17023SJohn Marino 			}
4258*e4b17023SJohn Marino 		    }
4259*e4b17023SJohn Marino 		  return omega_true;
4260*e4b17023SJohn Marino 		}
4261*e4b17023SJohn Marino 	    }
4262*e4b17023SJohn Marino 
4263*e4b17023SJohn Marino 	  eliminate_again = true;
4264*e4b17023SJohn Marino 
4265*e4b17023SJohn Marino 	  if (lower_bound_count == 1)
4266*e4b17023SJohn Marino 	    {
4267*e4b17023SJohn Marino 	      eqn lbeqn = omega_alloc_eqns (0, 1);
4268*e4b17023SJohn Marino 	      int Lc = pb->geqs[Le].coef[i];
4269*e4b17023SJohn Marino 
4270*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4271*e4b17023SJohn Marino 		fprintf (dump_file, "an inplace elimination\n");
4272*e4b17023SJohn Marino 
4273*e4b17023SJohn Marino 	      omega_copy_eqn (lbeqn, &pb->geqs[Le], (n_vars + 1));
4274*e4b17023SJohn Marino 	      omega_delete_geq_extra (pb, Le, n_vars + 1);
4275*e4b17023SJohn Marino 
4276*e4b17023SJohn Marino 	      for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4277*e4b17023SJohn Marino 		if (pb->geqs[Ue].coef[i] < 0)
4278*e4b17023SJohn Marino 		  {
4279*e4b17023SJohn Marino 		    if (lbeqn->key == -pb->geqs[Ue].key)
4280*e4b17023SJohn Marino 		      omega_delete_geq_extra (pb, Ue, n_vars + 1);
4281*e4b17023SJohn Marino 		    else
4282*e4b17023SJohn Marino 		      {
4283*e4b17023SJohn Marino 			int k;
4284*e4b17023SJohn Marino 			int Uc = -pb->geqs[Ue].coef[i];
4285*e4b17023SJohn Marino 			pb->geqs[Ue].touched = 1;
4286*e4b17023SJohn Marino 			eliminate_again = false;
4287*e4b17023SJohn Marino 
4288*e4b17023SJohn Marino 			if (lbeqn->color == omega_red)
4289*e4b17023SJohn Marino 			  pb->geqs[Ue].color = omega_red;
4290*e4b17023SJohn Marino 
4291*e4b17023SJohn Marino 			for (k = 0; k <= n_vars; k++)
4292*e4b17023SJohn Marino 			  pb->geqs[Ue].coef[k] =
4293*e4b17023SJohn Marino 			    mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4294*e4b17023SJohn Marino 			    mul_hwi (lbeqn->coef[k], Uc);
4295*e4b17023SJohn Marino 
4296*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4297*e4b17023SJohn Marino 			  {
4298*e4b17023SJohn Marino 			    omega_print_geq (dump_file, pb,
4299*e4b17023SJohn Marino 					     &(pb->geqs[Ue]));
4300*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4301*e4b17023SJohn Marino 			  }
4302*e4b17023SJohn Marino 		      }
4303*e4b17023SJohn Marino 		  }
4304*e4b17023SJohn Marino 
4305*e4b17023SJohn Marino 	      omega_free_eqns (lbeqn, 1);
4306*e4b17023SJohn Marino 	      continue;
4307*e4b17023SJohn Marino 	    }
4308*e4b17023SJohn Marino 	  else
4309*e4b17023SJohn Marino 	    {
4310*e4b17023SJohn Marino 	      int *dead_eqns = XNEWVEC (int, OMEGA_MAX_GEQS);
4311*e4b17023SJohn Marino 	      bool *is_dead = XNEWVEC (bool, OMEGA_MAX_GEQS);
4312*e4b17023SJohn Marino 	      int num_dead = 0;
4313*e4b17023SJohn Marino 	      int top_eqn = pb->num_geqs - 1;
4314*e4b17023SJohn Marino 	      lower_bound_count--;
4315*e4b17023SJohn Marino 
4316*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4317*e4b17023SJohn Marino 		fprintf (dump_file, "lower bound count = %d\n",
4318*e4b17023SJohn Marino 			 lower_bound_count);
4319*e4b17023SJohn Marino 
4320*e4b17023SJohn Marino 	      for (Le = top_eqn; Le >= 0; Le--)
4321*e4b17023SJohn Marino 		if (pb->geqs[Le].coef[i] > 0)
4322*e4b17023SJohn Marino 		  {
4323*e4b17023SJohn Marino 		    int Lc = pb->geqs[Le].coef[i];
4324*e4b17023SJohn Marino 		    for (Ue = top_eqn; Ue >= 0; Ue--)
4325*e4b17023SJohn Marino 		      if (pb->geqs[Ue].coef[i] < 0)
4326*e4b17023SJohn Marino 			{
4327*e4b17023SJohn Marino 			  if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4328*e4b17023SJohn Marino 			    {
4329*e4b17023SJohn Marino 			      int k;
4330*e4b17023SJohn Marino 			      int Uc = -pb->geqs[Ue].coef[i];
4331*e4b17023SJohn Marino 
4332*e4b17023SJohn Marino 			      if (num_dead == 0)
4333*e4b17023SJohn Marino 				e2 = pb->num_geqs++;
4334*e4b17023SJohn Marino 			      else
4335*e4b17023SJohn Marino 				e2 = dead_eqns[--num_dead];
4336*e4b17023SJohn Marino 
4337*e4b17023SJohn Marino 			      gcc_assert (e2 < OMEGA_MAX_GEQS);
4338*e4b17023SJohn Marino 
4339*e4b17023SJohn Marino 			      if (dump_file && (dump_flags & TDF_DETAILS))
4340*e4b17023SJohn Marino 				{
4341*e4b17023SJohn Marino 				  fprintf (dump_file,
4342*e4b17023SJohn Marino 					   "Le = %d, Ue = %d, gen = %d\n",
4343*e4b17023SJohn Marino 					   Le, Ue, e2);
4344*e4b17023SJohn Marino 				  omega_print_geq_extra (dump_file, pb,
4345*e4b17023SJohn Marino 							 &(pb->geqs[Le]));
4346*e4b17023SJohn Marino 				  fprintf (dump_file, "\n");
4347*e4b17023SJohn Marino 				  omega_print_geq_extra (dump_file, pb,
4348*e4b17023SJohn Marino 							 &(pb->geqs[Ue]));
4349*e4b17023SJohn Marino 				  fprintf (dump_file, "\n");
4350*e4b17023SJohn Marino 				}
4351*e4b17023SJohn Marino 
4352*e4b17023SJohn Marino 			      eliminate_again = false;
4353*e4b17023SJohn Marino 
4354*e4b17023SJohn Marino 			      for (k = n_vars; k >= 0; k--)
4355*e4b17023SJohn Marino 				pb->geqs[e2].coef[k] =
4356*e4b17023SJohn Marino 				  mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4357*e4b17023SJohn Marino 				  mul_hwi (pb->geqs[Le].coef[k], Uc);
4358*e4b17023SJohn Marino 
4359*e4b17023SJohn Marino 			      pb->geqs[e2].coef[n_vars + 1] = 0;
4360*e4b17023SJohn Marino 			      pb->geqs[e2].touched = 1;
4361*e4b17023SJohn Marino 
4362*e4b17023SJohn Marino 			      if (pb->geqs[Ue].color == omega_red
4363*e4b17023SJohn Marino 				  || pb->geqs[Le].color == omega_red)
4364*e4b17023SJohn Marino 				pb->geqs[e2].color = omega_red;
4365*e4b17023SJohn Marino 			      else
4366*e4b17023SJohn Marino 				pb->geqs[e2].color = omega_black;
4367*e4b17023SJohn Marino 
4368*e4b17023SJohn Marino 			      if (dump_file && (dump_flags & TDF_DETAILS))
4369*e4b17023SJohn Marino 				{
4370*e4b17023SJohn Marino 				  omega_print_geq (dump_file, pb,
4371*e4b17023SJohn Marino 						   &(pb->geqs[e2]));
4372*e4b17023SJohn Marino 				  fprintf (dump_file, "\n");
4373*e4b17023SJohn Marino 				}
4374*e4b17023SJohn Marino 			    }
4375*e4b17023SJohn Marino 
4376*e4b17023SJohn Marino 			  if (lower_bound_count == 0)
4377*e4b17023SJohn Marino 			    {
4378*e4b17023SJohn Marino 			      dead_eqns[num_dead++] = Ue;
4379*e4b17023SJohn Marino 
4380*e4b17023SJohn Marino 			      if (dump_file && (dump_flags & TDF_DETAILS))
4381*e4b17023SJohn Marino 				fprintf (dump_file, "Killed %d\n", Ue);
4382*e4b17023SJohn Marino 			    }
4383*e4b17023SJohn Marino 			}
4384*e4b17023SJohn Marino 
4385*e4b17023SJohn Marino 		    lower_bound_count--;
4386*e4b17023SJohn Marino 		    dead_eqns[num_dead++] = Le;
4387*e4b17023SJohn Marino 
4388*e4b17023SJohn Marino 		    if (dump_file && (dump_flags & TDF_DETAILS))
4389*e4b17023SJohn Marino 		      fprintf (dump_file, "Killed %d\n", Le);
4390*e4b17023SJohn Marino 		  }
4391*e4b17023SJohn Marino 
4392*e4b17023SJohn Marino 	      for (e = pb->num_geqs - 1; e >= 0; e--)
4393*e4b17023SJohn Marino 		is_dead[e] = false;
4394*e4b17023SJohn Marino 
4395*e4b17023SJohn Marino 	      while (num_dead > 0)
4396*e4b17023SJohn Marino 		is_dead[dead_eqns[--num_dead]] = true;
4397*e4b17023SJohn Marino 
4398*e4b17023SJohn Marino 	      for (e = pb->num_geqs - 1; e >= 0; e--)
4399*e4b17023SJohn Marino 		if (is_dead[e])
4400*e4b17023SJohn Marino 		  omega_delete_geq_extra (pb, e, n_vars + 1);
4401*e4b17023SJohn Marino 
4402*e4b17023SJohn Marino 	      free (dead_eqns);
4403*e4b17023SJohn Marino 	      free (is_dead);
4404*e4b17023SJohn Marino 	      continue;
4405*e4b17023SJohn Marino 	    }
4406*e4b17023SJohn Marino 	}
4407*e4b17023SJohn Marino       else
4408*e4b17023SJohn Marino 	{
4409*e4b17023SJohn Marino 	  omega_pb rS, iS;
4410*e4b17023SJohn Marino 
4411*e4b17023SJohn Marino 	  rS = omega_alloc_problem (0, 0);
4412*e4b17023SJohn Marino 	  iS = omega_alloc_problem (0, 0);
4413*e4b17023SJohn Marino 	  e2 = 0;
4414*e4b17023SJohn Marino 	  possible_easy_int_solution = true;
4415*e4b17023SJohn Marino 
4416*e4b17023SJohn Marino 	  for (e = 0; e < pb->num_geqs; e++)
4417*e4b17023SJohn Marino 	    if (pb->geqs[e].coef[i] == 0)
4418*e4b17023SJohn Marino 	      {
4419*e4b17023SJohn Marino 		omega_copy_eqn (&(rS->geqs[e2]), &pb->geqs[e],
4420*e4b17023SJohn Marino 				pb->num_vars);
4421*e4b17023SJohn Marino 		omega_copy_eqn (&(iS->geqs[e2]), &pb->geqs[e],
4422*e4b17023SJohn Marino 				pb->num_vars);
4423*e4b17023SJohn Marino 
4424*e4b17023SJohn Marino 		if (dump_file && (dump_flags & TDF_DETAILS))
4425*e4b17023SJohn Marino 		  {
4426*e4b17023SJohn Marino 		    int t;
4427*e4b17023SJohn Marino 		    fprintf (dump_file, "Copying (%d, %d): ", i,
4428*e4b17023SJohn Marino 			     pb->geqs[e].coef[i]);
4429*e4b17023SJohn Marino 		    omega_print_geq_extra (dump_file, pb, &pb->geqs[e]);
4430*e4b17023SJohn Marino 		    fprintf (dump_file, "\n");
4431*e4b17023SJohn Marino 		    for (t = 0; t <= n_vars + 1; t++)
4432*e4b17023SJohn Marino 		      fprintf (dump_file, "%d ", pb->geqs[e].coef[t]);
4433*e4b17023SJohn Marino 		    fprintf (dump_file, "\n");
4434*e4b17023SJohn Marino 
4435*e4b17023SJohn Marino 		  }
4436*e4b17023SJohn Marino 		e2++;
4437*e4b17023SJohn Marino 		gcc_assert (e2 < OMEGA_MAX_GEQS);
4438*e4b17023SJohn Marino 	      }
4439*e4b17023SJohn Marino 
4440*e4b17023SJohn Marino 	  for (Le = pb->num_geqs - 1; Le >= 0; Le--)
4441*e4b17023SJohn Marino 	    if (pb->geqs[Le].coef[i] > 0)
4442*e4b17023SJohn Marino 	      for (Ue = pb->num_geqs - 1; Ue >= 0; Ue--)
4443*e4b17023SJohn Marino 		if (pb->geqs[Ue].coef[i] < 0)
4444*e4b17023SJohn Marino 		  {
4445*e4b17023SJohn Marino 		    int k;
4446*e4b17023SJohn Marino 		    int Lc = pb->geqs[Le].coef[i];
4447*e4b17023SJohn Marino 		    int Uc = -pb->geqs[Ue].coef[i];
4448*e4b17023SJohn Marino 
4449*e4b17023SJohn Marino 		    if (pb->geqs[Le].key != -pb->geqs[Ue].key)
4450*e4b17023SJohn Marino 		      {
4451*e4b17023SJohn Marino 
4452*e4b17023SJohn Marino 			rS->geqs[e2].touched = iS->geqs[e2].touched = 1;
4453*e4b17023SJohn Marino 
4454*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4455*e4b17023SJohn Marino 			  {
4456*e4b17023SJohn Marino 			    fprintf (dump_file, "---\n");
4457*e4b17023SJohn Marino 			    fprintf (dump_file,
4458*e4b17023SJohn Marino 				     "Le(Lc) = %d(%d_, Ue(Uc) = %d(%d), gen = %d\n",
4459*e4b17023SJohn Marino 				     Le, Lc, Ue, Uc, e2);
4460*e4b17023SJohn Marino 			    omega_print_geq_extra (dump_file, pb, &pb->geqs[Le]);
4461*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4462*e4b17023SJohn Marino 			    omega_print_geq_extra (dump_file, pb, &pb->geqs[Ue]);
4463*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4464*e4b17023SJohn Marino 			  }
4465*e4b17023SJohn Marino 
4466*e4b17023SJohn Marino 			if (Uc == Lc)
4467*e4b17023SJohn Marino 			  {
4468*e4b17023SJohn Marino 			    for (k = n_vars; k >= 0; k--)
4469*e4b17023SJohn Marino 			      iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4470*e4b17023SJohn Marino 				pb->geqs[Ue].coef[k] + pb->geqs[Le].coef[k];
4471*e4b17023SJohn Marino 
4472*e4b17023SJohn Marino 			    iS->geqs[e2].coef[0] -= (Uc - 1);
4473*e4b17023SJohn Marino 			  }
4474*e4b17023SJohn Marino 			else
4475*e4b17023SJohn Marino 			  {
4476*e4b17023SJohn Marino 			    for (k = n_vars; k >= 0; k--)
4477*e4b17023SJohn Marino 			      iS->geqs[e2].coef[k] = rS->geqs[e2].coef[k] =
4478*e4b17023SJohn Marino 				mul_hwi (pb->geqs[Ue].coef[k], Lc) +
4479*e4b17023SJohn Marino 				mul_hwi (pb->geqs[Le].coef[k], Uc);
4480*e4b17023SJohn Marino 
4481*e4b17023SJohn Marino 			    iS->geqs[e2].coef[0] -= (Uc - 1) * (Lc - 1);
4482*e4b17023SJohn Marino 			  }
4483*e4b17023SJohn Marino 
4484*e4b17023SJohn Marino 			if (pb->geqs[Ue].color == omega_red
4485*e4b17023SJohn Marino 			    || pb->geqs[Le].color == omega_red)
4486*e4b17023SJohn Marino 			  iS->geqs[e2].color = rS->geqs[e2].color = omega_red;
4487*e4b17023SJohn Marino 			else
4488*e4b17023SJohn Marino 			  iS->geqs[e2].color = rS->geqs[e2].color = omega_black;
4489*e4b17023SJohn Marino 
4490*e4b17023SJohn Marino 			if (dump_file && (dump_flags & TDF_DETAILS))
4491*e4b17023SJohn Marino 			  {
4492*e4b17023SJohn Marino 			    omega_print_geq (dump_file, pb, &(rS->geqs[e2]));
4493*e4b17023SJohn Marino 			    fprintf (dump_file, "\n");
4494*e4b17023SJohn Marino 			  }
4495*e4b17023SJohn Marino 
4496*e4b17023SJohn Marino 			e2++;
4497*e4b17023SJohn Marino 			gcc_assert (e2 < OMEGA_MAX_GEQS);
4498*e4b17023SJohn Marino 		      }
4499*e4b17023SJohn Marino 		    else if (pb->geqs[Ue].coef[0] * Lc +
4500*e4b17023SJohn Marino 			     pb->geqs[Le].coef[0] * Uc -
4501*e4b17023SJohn Marino 			     (Uc - 1) * (Lc - 1) < 0)
4502*e4b17023SJohn Marino 		      possible_easy_int_solution = false;
4503*e4b17023SJohn Marino 		  }
4504*e4b17023SJohn Marino 
4505*e4b17023SJohn Marino 	  iS->variables_initialized = rS->variables_initialized = true;
4506*e4b17023SJohn Marino 	  iS->num_vars = rS->num_vars = pb->num_vars;
4507*e4b17023SJohn Marino 	  iS->num_geqs = rS->num_geqs = e2;
4508*e4b17023SJohn Marino 	  iS->num_eqs = rS->num_eqs = 0;
4509*e4b17023SJohn Marino 	  iS->num_subs = rS->num_subs = pb->num_subs;
4510*e4b17023SJohn Marino 	  iS->safe_vars = rS->safe_vars = pb->safe_vars;
4511*e4b17023SJohn Marino 
4512*e4b17023SJohn Marino 	  for (e = n_vars; e >= 0; e--)
4513*e4b17023SJohn Marino 	    rS->var[e] = pb->var[e];
4514*e4b17023SJohn Marino 
4515*e4b17023SJohn Marino 	  for (e = n_vars; e >= 0; e--)
4516*e4b17023SJohn Marino 	    iS->var[e] = pb->var[e];
4517*e4b17023SJohn Marino 
4518*e4b17023SJohn Marino 	  for (e = pb->num_subs - 1; e >= 0; e--)
4519*e4b17023SJohn Marino 	    {
4520*e4b17023SJohn Marino 	      omega_copy_eqn (&(rS->subs[e]), &(pb->subs[e]), pb->num_vars);
4521*e4b17023SJohn Marino 	      omega_copy_eqn (&(iS->subs[e]), &(pb->subs[e]), pb->num_vars);
4522*e4b17023SJohn Marino 	    }
4523*e4b17023SJohn Marino 
4524*e4b17023SJohn Marino 	  pb->num_vars++;
4525*e4b17023SJohn Marino 	  n_vars = pb->num_vars;
4526*e4b17023SJohn Marino 
4527*e4b17023SJohn Marino 	  if (desired_res != omega_true)
4528*e4b17023SJohn Marino 	    {
4529*e4b17023SJohn Marino 	      if (original_problem == no_problem)
4530*e4b17023SJohn Marino 		{
4531*e4b17023SJohn Marino 		  original_problem = pb;
4532*e4b17023SJohn Marino 		  result = omega_solve_geq (rS, omega_false);
4533*e4b17023SJohn Marino 		  original_problem = no_problem;
4534*e4b17023SJohn Marino 		}
4535*e4b17023SJohn Marino 	      else
4536*e4b17023SJohn Marino 		result = omega_solve_geq (rS, omega_false);
4537*e4b17023SJohn Marino 
4538*e4b17023SJohn Marino 	      if (result == omega_false)
4539*e4b17023SJohn Marino 		{
4540*e4b17023SJohn Marino 		  free (rS);
4541*e4b17023SJohn Marino 		  free (iS);
4542*e4b17023SJohn Marino 		  return result;
4543*e4b17023SJohn Marino 		}
4544*e4b17023SJohn Marino 
4545*e4b17023SJohn Marino 	      if (pb->num_eqs > 0)
4546*e4b17023SJohn Marino 		{
4547*e4b17023SJohn Marino 		  /* An equality constraint must have been found */
4548*e4b17023SJohn Marino 		  free (rS);
4549*e4b17023SJohn Marino 		  free (iS);
4550*e4b17023SJohn Marino 		  return omega_solve_problem (pb, desired_res);
4551*e4b17023SJohn Marino 		}
4552*e4b17023SJohn Marino 	    }
4553*e4b17023SJohn Marino 
4554*e4b17023SJohn Marino 	  if (desired_res != omega_false)
4555*e4b17023SJohn Marino 	    {
4556*e4b17023SJohn Marino 	      int j;
4557*e4b17023SJohn Marino 	      int lower_bounds = 0;
4558*e4b17023SJohn Marino 	      int *lower_bound = XNEWVEC (int, OMEGA_MAX_GEQS);
4559*e4b17023SJohn Marino 
4560*e4b17023SJohn Marino 	      if (possible_easy_int_solution)
4561*e4b17023SJohn Marino 		{
4562*e4b17023SJohn Marino 		  conservative++;
4563*e4b17023SJohn Marino 		  result = omega_solve_geq (iS, desired_res);
4564*e4b17023SJohn Marino 		  conservative--;
4565*e4b17023SJohn Marino 
4566*e4b17023SJohn Marino 		  if (result != omega_false)
4567*e4b17023SJohn Marino 		    {
4568*e4b17023SJohn Marino 		      free (rS);
4569*e4b17023SJohn Marino 		      free (iS);
4570*e4b17023SJohn Marino 		      free (lower_bound);
4571*e4b17023SJohn Marino 		      return result;
4572*e4b17023SJohn Marino 		    }
4573*e4b17023SJohn Marino 		}
4574*e4b17023SJohn Marino 
4575*e4b17023SJohn Marino 	      if (!exact && best_parallel_eqn >= 0
4576*e4b17023SJohn Marino 		  && parallel_difference <= max_splinters)
4577*e4b17023SJohn Marino 		{
4578*e4b17023SJohn Marino 		  free (rS);
4579*e4b17023SJohn Marino 		  free (iS);
4580*e4b17023SJohn Marino 		  free (lower_bound);
4581*e4b17023SJohn Marino 		  return parallel_splinter (pb, best_parallel_eqn,
4582*e4b17023SJohn Marino 					    parallel_difference,
4583*e4b17023SJohn Marino 					    desired_res);
4584*e4b17023SJohn Marino 		}
4585*e4b17023SJohn Marino 
4586*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4587*e4b17023SJohn Marino 		fprintf (dump_file, "have to do exact analysis\n");
4588*e4b17023SJohn Marino 
4589*e4b17023SJohn Marino 	      conservative++;
4590*e4b17023SJohn Marino 
4591*e4b17023SJohn Marino 	      for (e = 0; e < pb->num_geqs; e++)
4592*e4b17023SJohn Marino 		if (pb->geqs[e].coef[i] > 1)
4593*e4b17023SJohn Marino 		  lower_bound[lower_bounds++] = e;
4594*e4b17023SJohn Marino 
4595*e4b17023SJohn Marino 	      /* Sort array LOWER_BOUND.  */
4596*e4b17023SJohn Marino 	      for (j = 0; j < lower_bounds; j++)
4597*e4b17023SJohn Marino 		{
4598*e4b17023SJohn Marino 		  int k, smallest = j;
4599*e4b17023SJohn Marino 
4600*e4b17023SJohn Marino 		  for (k = j + 1; k < lower_bounds; k++)
4601*e4b17023SJohn Marino 		    if (pb->geqs[lower_bound[smallest]].coef[i] >
4602*e4b17023SJohn Marino 			pb->geqs[lower_bound[k]].coef[i])
4603*e4b17023SJohn Marino 		      smallest = k;
4604*e4b17023SJohn Marino 
4605*e4b17023SJohn Marino 		  k = lower_bound[smallest];
4606*e4b17023SJohn Marino 		  lower_bound[smallest] = lower_bound[j];
4607*e4b17023SJohn Marino 		  lower_bound[j] = k;
4608*e4b17023SJohn Marino 		}
4609*e4b17023SJohn Marino 
4610*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4611*e4b17023SJohn Marino 		{
4612*e4b17023SJohn Marino 		  fprintf (dump_file, "lower bound coefficients = ");
4613*e4b17023SJohn Marino 
4614*e4b17023SJohn Marino 		  for (j = 0; j < lower_bounds; j++)
4615*e4b17023SJohn Marino 		    fprintf (dump_file, " %d",
4616*e4b17023SJohn Marino 			     pb->geqs[lower_bound[j]].coef[i]);
4617*e4b17023SJohn Marino 
4618*e4b17023SJohn Marino 		  fprintf (dump_file, "\n");
4619*e4b17023SJohn Marino 		}
4620*e4b17023SJohn Marino 
4621*e4b17023SJohn Marino 	      for (j = 0; j < lower_bounds; j++)
4622*e4b17023SJohn Marino 		{
4623*e4b17023SJohn Marino 		  int max_incr;
4624*e4b17023SJohn Marino 		  int c;
4625*e4b17023SJohn Marino 		  int worst_lower_bound_constant = -minC;
4626*e4b17023SJohn Marino 
4627*e4b17023SJohn Marino 		  e = lower_bound[j];
4628*e4b17023SJohn Marino 		  max_incr = (((pb->geqs[e].coef[i] - 1) *
4629*e4b17023SJohn Marino 			       (worst_lower_bound_constant - 1) - 1)
4630*e4b17023SJohn Marino 			      / worst_lower_bound_constant);
4631*e4b17023SJohn Marino 		  /* max_incr += 2; */
4632*e4b17023SJohn Marino 
4633*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
4634*e4b17023SJohn Marino 		    {
4635*e4b17023SJohn Marino 		      fprintf (dump_file, "for equation ");
4636*e4b17023SJohn Marino 		      omega_print_geq (dump_file, pb, &pb->geqs[e]);
4637*e4b17023SJohn Marino 		      fprintf (dump_file,
4638*e4b17023SJohn Marino 			       "\ntry decrements from 0 to %d\n",
4639*e4b17023SJohn Marino 			       max_incr);
4640*e4b17023SJohn Marino 		      omega_print_problem (dump_file, pb);
4641*e4b17023SJohn Marino 		    }
4642*e4b17023SJohn Marino 
4643*e4b17023SJohn Marino 		  if (max_incr > 50 && !smoothed
4644*e4b17023SJohn Marino 		      && smooth_weird_equations (pb))
4645*e4b17023SJohn Marino 		    {
4646*e4b17023SJohn Marino 		      conservative--;
4647*e4b17023SJohn Marino 		      free (rS);
4648*e4b17023SJohn Marino 		      free (iS);
4649*e4b17023SJohn Marino 		      smoothed = true;
4650*e4b17023SJohn Marino 		      goto solve_geq_start;
4651*e4b17023SJohn Marino 		    }
4652*e4b17023SJohn Marino 
4653*e4b17023SJohn Marino 		  omega_copy_eqn (&pb->eqs[0], &pb->geqs[e],
4654*e4b17023SJohn Marino 				  pb->num_vars);
4655*e4b17023SJohn Marino 		  pb->eqs[0].color = omega_black;
4656*e4b17023SJohn Marino 		  omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
4657*e4b17023SJohn Marino 		  pb->geqs[e].touched = 1;
4658*e4b17023SJohn Marino 		  pb->num_eqs = 1;
4659*e4b17023SJohn Marino 
4660*e4b17023SJohn Marino 		  for (c = max_incr; c >= 0; c--)
4661*e4b17023SJohn Marino 		    {
4662*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
4663*e4b17023SJohn Marino 			{
4664*e4b17023SJohn Marino 			  fprintf (dump_file,
4665*e4b17023SJohn Marino 				   "trying next decrement of %d\n",
4666*e4b17023SJohn Marino 				   max_incr - c);
4667*e4b17023SJohn Marino 			  omega_print_problem (dump_file, pb);
4668*e4b17023SJohn Marino 			}
4669*e4b17023SJohn Marino 
4670*e4b17023SJohn Marino 		      omega_copy_problem (rS, pb);
4671*e4b17023SJohn Marino 
4672*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
4673*e4b17023SJohn Marino 			omega_print_problem (dump_file, rS);
4674*e4b17023SJohn Marino 
4675*e4b17023SJohn Marino 		      result = omega_solve_problem (rS, desired_res);
4676*e4b17023SJohn Marino 
4677*e4b17023SJohn Marino 		      if (result == omega_true)
4678*e4b17023SJohn Marino 			{
4679*e4b17023SJohn Marino 			  free (rS);
4680*e4b17023SJohn Marino 			  free (iS);
4681*e4b17023SJohn Marino 			  free (lower_bound);
4682*e4b17023SJohn Marino 			  conservative--;
4683*e4b17023SJohn Marino 			  return omega_true;
4684*e4b17023SJohn Marino 			}
4685*e4b17023SJohn Marino 
4686*e4b17023SJohn Marino 		      pb->eqs[0].coef[0]--;
4687*e4b17023SJohn Marino 		    }
4688*e4b17023SJohn Marino 
4689*e4b17023SJohn Marino 		  if (j + 1 < lower_bounds)
4690*e4b17023SJohn Marino 		    {
4691*e4b17023SJohn Marino 		      pb->num_eqs = 0;
4692*e4b17023SJohn Marino 		      omega_copy_eqn (&pb->geqs[e], &pb->eqs[0],
4693*e4b17023SJohn Marino 				      pb->num_vars);
4694*e4b17023SJohn Marino 		      pb->geqs[e].touched = 1;
4695*e4b17023SJohn Marino 		      pb->geqs[e].color = omega_black;
4696*e4b17023SJohn Marino 		      omega_copy_problem (rS, pb);
4697*e4b17023SJohn Marino 
4698*e4b17023SJohn Marino 		      if (dump_file && (dump_flags & TDF_DETAILS))
4699*e4b17023SJohn Marino 			fprintf (dump_file,
4700*e4b17023SJohn Marino 				 "exhausted lower bound, "
4701*e4b17023SJohn Marino 				 "checking if still feasible ");
4702*e4b17023SJohn Marino 
4703*e4b17023SJohn Marino 		      result = omega_solve_problem (rS, omega_false);
4704*e4b17023SJohn Marino 
4705*e4b17023SJohn Marino 		      if (result == omega_false)
4706*e4b17023SJohn Marino 			break;
4707*e4b17023SJohn Marino 		    }
4708*e4b17023SJohn Marino 		}
4709*e4b17023SJohn Marino 
4710*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4711*e4b17023SJohn Marino 		fprintf (dump_file, "fall-off the end\n");
4712*e4b17023SJohn Marino 
4713*e4b17023SJohn Marino 	      free (rS);
4714*e4b17023SJohn Marino 	      free (iS);
4715*e4b17023SJohn Marino 	      free (lower_bound);
4716*e4b17023SJohn Marino 	      conservative--;
4717*e4b17023SJohn Marino 	      return omega_false;
4718*e4b17023SJohn Marino 	    }
4719*e4b17023SJohn Marino 
4720*e4b17023SJohn Marino 	  free (rS);
4721*e4b17023SJohn Marino 	  free (iS);
4722*e4b17023SJohn Marino 	}
4723*e4b17023SJohn Marino       return omega_unknown;
4724*e4b17023SJohn Marino     } while (eliminate_again);
4725*e4b17023SJohn Marino   } while (1);
4726*e4b17023SJohn Marino }
4727*e4b17023SJohn Marino 
4728*e4b17023SJohn Marino /* Because the omega solver is recursive, this counter limits the
4729*e4b17023SJohn Marino    recursion depth.  */
4730*e4b17023SJohn Marino static int omega_solve_depth = 0;
4731*e4b17023SJohn Marino 
4732*e4b17023SJohn Marino /* Return omega_true when the problem PB has a solution following the
4733*e4b17023SJohn Marino    DESIRED_RES.  */
4734*e4b17023SJohn Marino 
4735*e4b17023SJohn Marino enum omega_result
omega_solve_problem(omega_pb pb,enum omega_result desired_res)4736*e4b17023SJohn Marino omega_solve_problem (omega_pb pb, enum omega_result desired_res)
4737*e4b17023SJohn Marino {
4738*e4b17023SJohn Marino   enum omega_result result;
4739*e4b17023SJohn Marino 
4740*e4b17023SJohn Marino   gcc_assert (pb->num_vars >= pb->safe_vars);
4741*e4b17023SJohn Marino   omega_solve_depth++;
4742*e4b17023SJohn Marino 
4743*e4b17023SJohn Marino   if (desired_res != omega_simplify)
4744*e4b17023SJohn Marino     pb->safe_vars = 0;
4745*e4b17023SJohn Marino 
4746*e4b17023SJohn Marino   if (omega_solve_depth > 50)
4747*e4b17023SJohn Marino     {
4748*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
4749*e4b17023SJohn Marino 	{
4750*e4b17023SJohn Marino 	  fprintf (dump_file,
4751*e4b17023SJohn Marino 		   "Solve depth = %d, in_approximate_mode = %d, aborting\n",
4752*e4b17023SJohn Marino 		   omega_solve_depth, in_approximate_mode);
4753*e4b17023SJohn Marino 	  omega_print_problem (dump_file, pb);
4754*e4b17023SJohn Marino 	}
4755*e4b17023SJohn Marino       gcc_assert (0);
4756*e4b17023SJohn Marino     }
4757*e4b17023SJohn Marino 
4758*e4b17023SJohn Marino   if (omega_solve_eq (pb, desired_res) == omega_false)
4759*e4b17023SJohn Marino     {
4760*e4b17023SJohn Marino       omega_solve_depth--;
4761*e4b17023SJohn Marino       return omega_false;
4762*e4b17023SJohn Marino     }
4763*e4b17023SJohn Marino 
4764*e4b17023SJohn Marino   if (in_approximate_mode && !pb->num_geqs)
4765*e4b17023SJohn Marino     {
4766*e4b17023SJohn Marino       result = omega_true;
4767*e4b17023SJohn Marino       pb->num_vars = pb->safe_vars;
4768*e4b17023SJohn Marino       omega_problem_reduced (pb);
4769*e4b17023SJohn Marino     }
4770*e4b17023SJohn Marino   else
4771*e4b17023SJohn Marino     result = omega_solve_geq (pb, desired_res);
4772*e4b17023SJohn Marino 
4773*e4b17023SJohn Marino   omega_solve_depth--;
4774*e4b17023SJohn Marino 
4775*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
4776*e4b17023SJohn Marino     {
4777*e4b17023SJohn Marino       resurrect_subs (pb);
4778*e4b17023SJohn Marino       gcc_assert (please_no_equalities_in_simplified_problems
4779*e4b17023SJohn Marino 		  || !result || pb->num_subs == 0);
4780*e4b17023SJohn Marino     }
4781*e4b17023SJohn Marino 
4782*e4b17023SJohn Marino   return result;
4783*e4b17023SJohn Marino }
4784*e4b17023SJohn Marino 
4785*e4b17023SJohn Marino /* Return true if red equations constrain the set of possible solutions.
4786*e4b17023SJohn Marino    We assume that there are solutions to the black equations by
4787*e4b17023SJohn Marino    themselves, so if there is no solution to the combined problem, we
4788*e4b17023SJohn Marino    return true.  */
4789*e4b17023SJohn Marino 
4790*e4b17023SJohn Marino bool
omega_problem_has_red_equations(omega_pb pb)4791*e4b17023SJohn Marino omega_problem_has_red_equations (omega_pb pb)
4792*e4b17023SJohn Marino {
4793*e4b17023SJohn Marino   bool result;
4794*e4b17023SJohn Marino   int e;
4795*e4b17023SJohn Marino   int i;
4796*e4b17023SJohn Marino 
4797*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4798*e4b17023SJohn Marino     {
4799*e4b17023SJohn Marino       fprintf (dump_file, "Checking for red equations:\n");
4800*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
4801*e4b17023SJohn Marino     }
4802*e4b17023SJohn Marino 
4803*e4b17023SJohn Marino   please_no_equalities_in_simplified_problems++;
4804*e4b17023SJohn Marino   may_be_red++;
4805*e4b17023SJohn Marino 
4806*e4b17023SJohn Marino   if (omega_single_result)
4807*e4b17023SJohn Marino     return_single_result++;
4808*e4b17023SJohn Marino 
4809*e4b17023SJohn Marino   create_color = true;
4810*e4b17023SJohn Marino   result = (omega_simplify_problem (pb) == omega_false);
4811*e4b17023SJohn Marino 
4812*e4b17023SJohn Marino   if (omega_single_result)
4813*e4b17023SJohn Marino     return_single_result--;
4814*e4b17023SJohn Marino 
4815*e4b17023SJohn Marino   may_be_red--;
4816*e4b17023SJohn Marino   please_no_equalities_in_simplified_problems--;
4817*e4b17023SJohn Marino 
4818*e4b17023SJohn Marino   if (result)
4819*e4b17023SJohn Marino     {
4820*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
4821*e4b17023SJohn Marino       	fprintf (dump_file, "Gist is FALSE\n");
4822*e4b17023SJohn Marino 
4823*e4b17023SJohn Marino       pb->num_subs = 0;
4824*e4b17023SJohn Marino       pb->num_geqs = 0;
4825*e4b17023SJohn Marino       pb->num_eqs = 1;
4826*e4b17023SJohn Marino       pb->eqs[0].color = omega_red;
4827*e4b17023SJohn Marino 
4828*e4b17023SJohn Marino       for (i = pb->num_vars; i > 0; i--)
4829*e4b17023SJohn Marino 	pb->eqs[0].coef[i] = 0;
4830*e4b17023SJohn Marino 
4831*e4b17023SJohn Marino       pb->eqs[0].coef[0] = 1;
4832*e4b17023SJohn Marino       return true;
4833*e4b17023SJohn Marino     }
4834*e4b17023SJohn Marino 
4835*e4b17023SJohn Marino   free_red_eliminations (pb);
4836*e4b17023SJohn Marino   gcc_assert (pb->num_eqs == 0);
4837*e4b17023SJohn Marino 
4838*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
4839*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
4840*e4b17023SJohn Marino       result = true;
4841*e4b17023SJohn Marino 
4842*e4b17023SJohn Marino   if (!result)
4843*e4b17023SJohn Marino     return false;
4844*e4b17023SJohn Marino 
4845*e4b17023SJohn Marino   for (i = pb->safe_vars; i >= 1; i--)
4846*e4b17023SJohn Marino     {
4847*e4b17023SJohn Marino       int ub = 0;
4848*e4b17023SJohn Marino       int lb = 0;
4849*e4b17023SJohn Marino 
4850*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
4851*e4b17023SJohn Marino 	{
4852*e4b17023SJohn Marino 	  if (pb->geqs[e].coef[i])
4853*e4b17023SJohn Marino 	    {
4854*e4b17023SJohn Marino 	      if (pb->geqs[e].coef[i] > 0)
4855*e4b17023SJohn Marino 		lb |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4856*e4b17023SJohn Marino 
4857*e4b17023SJohn Marino 	      else
4858*e4b17023SJohn Marino 		ub |= (1 + (pb->geqs[e].color == omega_red ? 1 : 0));
4859*e4b17023SJohn Marino 	    }
4860*e4b17023SJohn Marino 	}
4861*e4b17023SJohn Marino 
4862*e4b17023SJohn Marino       if (ub == 2 || lb == 2)
4863*e4b17023SJohn Marino 	{
4864*e4b17023SJohn Marino 
4865*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
4866*e4b17023SJohn Marino 	    fprintf (dump_file, "checks for upper/lower bounds worked!\n");
4867*e4b17023SJohn Marino 
4868*e4b17023SJohn Marino 	  if (!omega_reduce_with_subs)
4869*e4b17023SJohn Marino 	    {
4870*e4b17023SJohn Marino 	      resurrect_subs (pb);
4871*e4b17023SJohn Marino 	      gcc_assert (pb->num_subs == 0);
4872*e4b17023SJohn Marino 	    }
4873*e4b17023SJohn Marino 
4874*e4b17023SJohn Marino 	  return true;
4875*e4b17023SJohn Marino 	}
4876*e4b17023SJohn Marino     }
4877*e4b17023SJohn Marino 
4878*e4b17023SJohn Marino 
4879*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4880*e4b17023SJohn Marino     fprintf (dump_file,
4881*e4b17023SJohn Marino 	     "*** Doing potentially expensive elimination tests "
4882*e4b17023SJohn Marino 	     "for red equations\n");
4883*e4b17023SJohn Marino 
4884*e4b17023SJohn Marino   please_no_equalities_in_simplified_problems++;
4885*e4b17023SJohn Marino   omega_eliminate_red (pb, true);
4886*e4b17023SJohn Marino   please_no_equalities_in_simplified_problems--;
4887*e4b17023SJohn Marino 
4888*e4b17023SJohn Marino   result = false;
4889*e4b17023SJohn Marino   gcc_assert (pb->num_eqs == 0);
4890*e4b17023SJohn Marino 
4891*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
4892*e4b17023SJohn Marino     if (pb->geqs[e].color == omega_red)
4893*e4b17023SJohn Marino       result = true;
4894*e4b17023SJohn Marino 
4895*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4896*e4b17023SJohn Marino     {
4897*e4b17023SJohn Marino       if (!result)
4898*e4b17023SJohn Marino 	fprintf (dump_file,
4899*e4b17023SJohn Marino 		 "******************** Redundant Red Equations eliminated!!\n");
4900*e4b17023SJohn Marino       else
4901*e4b17023SJohn Marino 	fprintf (dump_file,
4902*e4b17023SJohn Marino 		 "******************** Red Equations remain\n");
4903*e4b17023SJohn Marino 
4904*e4b17023SJohn Marino       omega_print_problem (dump_file, pb);
4905*e4b17023SJohn Marino     }
4906*e4b17023SJohn Marino 
4907*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
4908*e4b17023SJohn Marino     {
4909*e4b17023SJohn Marino       normalize_return_type r;
4910*e4b17023SJohn Marino 
4911*e4b17023SJohn Marino       resurrect_subs (pb);
4912*e4b17023SJohn Marino       r = normalize_omega_problem (pb);
4913*e4b17023SJohn Marino       gcc_assert (r != normalize_false);
4914*e4b17023SJohn Marino 
4915*e4b17023SJohn Marino       coalesce (pb);
4916*e4b17023SJohn Marino       cleanout_wildcards (pb);
4917*e4b17023SJohn Marino       gcc_assert (pb->num_subs == 0);
4918*e4b17023SJohn Marino     }
4919*e4b17023SJohn Marino 
4920*e4b17023SJohn Marino   return result;
4921*e4b17023SJohn Marino }
4922*e4b17023SJohn Marino 
4923*e4b17023SJohn Marino /* Calls omega_simplify_problem in approximate mode.  */
4924*e4b17023SJohn Marino 
4925*e4b17023SJohn Marino enum omega_result
omega_simplify_approximate(omega_pb pb)4926*e4b17023SJohn Marino omega_simplify_approximate (omega_pb pb)
4927*e4b17023SJohn Marino {
4928*e4b17023SJohn Marino   enum omega_result result;
4929*e4b17023SJohn Marino 
4930*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4931*e4b17023SJohn Marino     fprintf (dump_file, "(Entering approximate mode\n");
4932*e4b17023SJohn Marino 
4933*e4b17023SJohn Marino   in_approximate_mode = true;
4934*e4b17023SJohn Marino   result = omega_simplify_problem (pb);
4935*e4b17023SJohn Marino   in_approximate_mode = false;
4936*e4b17023SJohn Marino 
4937*e4b17023SJohn Marino   gcc_assert (pb->num_vars == pb->safe_vars);
4938*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
4939*e4b17023SJohn Marino     gcc_assert (pb->num_subs == 0);
4940*e4b17023SJohn Marino 
4941*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4942*e4b17023SJohn Marino     fprintf (dump_file, "Leaving approximate mode)\n");
4943*e4b17023SJohn Marino 
4944*e4b17023SJohn Marino   return result;
4945*e4b17023SJohn Marino }
4946*e4b17023SJohn Marino 
4947*e4b17023SJohn Marino 
4948*e4b17023SJohn Marino /* Simplifies problem PB by eliminating redundant constraints and
4949*e4b17023SJohn Marino    reducing the constraints system to a minimal form.  Returns
4950*e4b17023SJohn Marino    omega_true when the problem was successfully reduced, omega_unknown
4951*e4b17023SJohn Marino    when the solver is unable to determine an answer.  */
4952*e4b17023SJohn Marino 
4953*e4b17023SJohn Marino enum omega_result
omega_simplify_problem(omega_pb pb)4954*e4b17023SJohn Marino omega_simplify_problem (omega_pb pb)
4955*e4b17023SJohn Marino {
4956*e4b17023SJohn Marino   int i;
4957*e4b17023SJohn Marino 
4958*e4b17023SJohn Marino   omega_found_reduction = omega_false;
4959*e4b17023SJohn Marino 
4960*e4b17023SJohn Marino   if (!pb->variables_initialized)
4961*e4b17023SJohn Marino     omega_initialize_variables (pb);
4962*e4b17023SJohn Marino 
4963*e4b17023SJohn Marino   if (next_key * 3 > MAX_KEYS)
4964*e4b17023SJohn Marino     {
4965*e4b17023SJohn Marino       int e;
4966*e4b17023SJohn Marino 
4967*e4b17023SJohn Marino       hash_version++;
4968*e4b17023SJohn Marino       next_key = OMEGA_MAX_VARS + 1;
4969*e4b17023SJohn Marino 
4970*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
4971*e4b17023SJohn Marino 	pb->geqs[e].touched = 1;
4972*e4b17023SJohn Marino 
4973*e4b17023SJohn Marino       for (i = 0; i < HASH_TABLE_SIZE; i++)
4974*e4b17023SJohn Marino 	hash_master[i].touched = -1;
4975*e4b17023SJohn Marino 
4976*e4b17023SJohn Marino       pb->hash_version = hash_version;
4977*e4b17023SJohn Marino     }
4978*e4b17023SJohn Marino 
4979*e4b17023SJohn Marino   else if (pb->hash_version != hash_version)
4980*e4b17023SJohn Marino     {
4981*e4b17023SJohn Marino       int e;
4982*e4b17023SJohn Marino 
4983*e4b17023SJohn Marino       for (e = pb->num_geqs - 1; e >= 0; e--)
4984*e4b17023SJohn Marino 	pb->geqs[e].touched = 1;
4985*e4b17023SJohn Marino 
4986*e4b17023SJohn Marino       pb->hash_version = hash_version;
4987*e4b17023SJohn Marino     }
4988*e4b17023SJohn Marino 
4989*e4b17023SJohn Marino   if (pb->num_vars > pb->num_eqs + 3 * pb->safe_vars)
4990*e4b17023SJohn Marino     omega_free_eliminations (pb, pb->safe_vars);
4991*e4b17023SJohn Marino 
4992*e4b17023SJohn Marino   if (!may_be_red && pb->num_subs == 0 && pb->safe_vars == 0)
4993*e4b17023SJohn Marino     {
4994*e4b17023SJohn Marino       omega_found_reduction = omega_solve_problem (pb, omega_unknown);
4995*e4b17023SJohn Marino 
4996*e4b17023SJohn Marino       if (omega_found_reduction != omega_false
4997*e4b17023SJohn Marino 	  && !return_single_result)
4998*e4b17023SJohn Marino 	{
4999*e4b17023SJohn Marino 	  pb->num_geqs = 0;
5000*e4b17023SJohn Marino 	  pb->num_eqs = 0;
5001*e4b17023SJohn Marino 	  (*omega_when_reduced) (pb);
5002*e4b17023SJohn Marino 	}
5003*e4b17023SJohn Marino 
5004*e4b17023SJohn Marino       return omega_found_reduction;
5005*e4b17023SJohn Marino     }
5006*e4b17023SJohn Marino 
5007*e4b17023SJohn Marino   omega_solve_problem (pb, omega_simplify);
5008*e4b17023SJohn Marino 
5009*e4b17023SJohn Marino   if (omega_found_reduction != omega_false)
5010*e4b17023SJohn Marino     {
5011*e4b17023SJohn Marino       for (i = 1; omega_safe_var_p (pb, i); i++)
5012*e4b17023SJohn Marino 	pb->forwarding_address[pb->var[i]] = i;
5013*e4b17023SJohn Marino 
5014*e4b17023SJohn Marino       for (i = 0; i < pb->num_subs; i++)
5015*e4b17023SJohn Marino 	pb->forwarding_address[pb->subs[i].key] = -i - 1;
5016*e4b17023SJohn Marino     }
5017*e4b17023SJohn Marino 
5018*e4b17023SJohn Marino   if (!omega_reduce_with_subs)
5019*e4b17023SJohn Marino     gcc_assert (please_no_equalities_in_simplified_problems
5020*e4b17023SJohn Marino 		|| omega_found_reduction == omega_false
5021*e4b17023SJohn Marino 		|| pb->num_subs == 0);
5022*e4b17023SJohn Marino 
5023*e4b17023SJohn Marino   return omega_found_reduction;
5024*e4b17023SJohn Marino }
5025*e4b17023SJohn Marino 
5026*e4b17023SJohn Marino /* Make variable VAR unprotected: it then can be eliminated.  */
5027*e4b17023SJohn Marino 
5028*e4b17023SJohn Marino void
omega_unprotect_variable(omega_pb pb,int var)5029*e4b17023SJohn Marino omega_unprotect_variable (omega_pb pb, int var)
5030*e4b17023SJohn Marino {
5031*e4b17023SJohn Marino   int e, idx;
5032*e4b17023SJohn Marino   idx = pb->forwarding_address[var];
5033*e4b17023SJohn Marino 
5034*e4b17023SJohn Marino   if (idx < 0)
5035*e4b17023SJohn Marino     {
5036*e4b17023SJohn Marino       idx = -1 - idx;
5037*e4b17023SJohn Marino       pb->num_subs--;
5038*e4b17023SJohn Marino 
5039*e4b17023SJohn Marino       if (idx < pb->num_subs)
5040*e4b17023SJohn Marino 	{
5041*e4b17023SJohn Marino 	  omega_copy_eqn (&pb->subs[idx], &pb->subs[pb->num_subs],
5042*e4b17023SJohn Marino 			  pb->num_vars);
5043*e4b17023SJohn Marino 	  pb->forwarding_address[pb->subs[idx].key] = -idx - 1;
5044*e4b17023SJohn Marino 	}
5045*e4b17023SJohn Marino     }
5046*e4b17023SJohn Marino   else
5047*e4b17023SJohn Marino     {
5048*e4b17023SJohn Marino       int *bring_to_life = XNEWVEC (int, OMEGA_MAX_VARS);
5049*e4b17023SJohn Marino       int e2;
5050*e4b17023SJohn Marino 
5051*e4b17023SJohn Marino       for (e = pb->num_subs - 1; e >= 0; e--)
5052*e4b17023SJohn Marino 	bring_to_life[e] = (pb->subs[e].coef[idx] != 0);
5053*e4b17023SJohn Marino 
5054*e4b17023SJohn Marino       for (e2 = pb->num_subs - 1; e2 >= 0; e2--)
5055*e4b17023SJohn Marino 	if (bring_to_life[e2])
5056*e4b17023SJohn Marino 	  {
5057*e4b17023SJohn Marino 	    pb->num_vars++;
5058*e4b17023SJohn Marino 	    pb->safe_vars++;
5059*e4b17023SJohn Marino 
5060*e4b17023SJohn Marino 	    if (pb->safe_vars < pb->num_vars)
5061*e4b17023SJohn Marino 	      {
5062*e4b17023SJohn Marino 		for (e = pb->num_geqs - 1; e >= 0; e--)
5063*e4b17023SJohn Marino 		  {
5064*e4b17023SJohn Marino 		    pb->geqs[e].coef[pb->num_vars] =
5065*e4b17023SJohn Marino 		      pb->geqs[e].coef[pb->safe_vars];
5066*e4b17023SJohn Marino 
5067*e4b17023SJohn Marino 		    pb->geqs[e].coef[pb->safe_vars] = 0;
5068*e4b17023SJohn Marino 		  }
5069*e4b17023SJohn Marino 
5070*e4b17023SJohn Marino 		for (e = pb->num_eqs - 1; e >= 0; e--)
5071*e4b17023SJohn Marino 		  {
5072*e4b17023SJohn Marino 		    pb->eqs[e].coef[pb->num_vars] =
5073*e4b17023SJohn Marino 		      pb->eqs[e].coef[pb->safe_vars];
5074*e4b17023SJohn Marino 
5075*e4b17023SJohn Marino 		    pb->eqs[e].coef[pb->safe_vars] = 0;
5076*e4b17023SJohn Marino 		  }
5077*e4b17023SJohn Marino 
5078*e4b17023SJohn Marino 		for (e = pb->num_subs - 1; e >= 0; e--)
5079*e4b17023SJohn Marino 		  {
5080*e4b17023SJohn Marino 		    pb->subs[e].coef[pb->num_vars] =
5081*e4b17023SJohn Marino 		      pb->subs[e].coef[pb->safe_vars];
5082*e4b17023SJohn Marino 
5083*e4b17023SJohn Marino 		    pb->subs[e].coef[pb->safe_vars] = 0;
5084*e4b17023SJohn Marino 		  }
5085*e4b17023SJohn Marino 
5086*e4b17023SJohn Marino 		pb->var[pb->num_vars] = pb->var[pb->safe_vars];
5087*e4b17023SJohn Marino 		pb->forwarding_address[pb->var[pb->num_vars]] =
5088*e4b17023SJohn Marino 		  pb->num_vars;
5089*e4b17023SJohn Marino 	      }
5090*e4b17023SJohn Marino 	    else
5091*e4b17023SJohn Marino 	      {
5092*e4b17023SJohn Marino 		for (e = pb->num_geqs - 1; e >= 0; e--)
5093*e4b17023SJohn Marino 		  pb->geqs[e].coef[pb->safe_vars] = 0;
5094*e4b17023SJohn Marino 
5095*e4b17023SJohn Marino 		for (e = pb->num_eqs - 1; e >= 0; e--)
5096*e4b17023SJohn Marino 		  pb->eqs[e].coef[pb->safe_vars] = 0;
5097*e4b17023SJohn Marino 
5098*e4b17023SJohn Marino 		for (e = pb->num_subs - 1; e >= 0; e--)
5099*e4b17023SJohn Marino 		  pb->subs[e].coef[pb->safe_vars] = 0;
5100*e4b17023SJohn Marino 	      }
5101*e4b17023SJohn Marino 
5102*e4b17023SJohn Marino 	    pb->var[pb->safe_vars] = pb->subs[e2].key;
5103*e4b17023SJohn Marino 	    pb->forwarding_address[pb->subs[e2].key] = pb->safe_vars;
5104*e4b17023SJohn Marino 
5105*e4b17023SJohn Marino 	    omega_copy_eqn (&(pb->eqs[pb->num_eqs]), &(pb->subs[e2]),
5106*e4b17023SJohn Marino 			    pb->num_vars);
5107*e4b17023SJohn Marino 	    pb->eqs[pb->num_eqs++].coef[pb->safe_vars] = -1;
5108*e4b17023SJohn Marino 	    gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5109*e4b17023SJohn Marino 
5110*e4b17023SJohn Marino 	    if (e2 < pb->num_subs - 1)
5111*e4b17023SJohn Marino 	      omega_copy_eqn (&(pb->subs[e2]), &(pb->subs[pb->num_subs - 1]),
5112*e4b17023SJohn Marino 			      pb->num_vars);
5113*e4b17023SJohn Marino 
5114*e4b17023SJohn Marino 	    pb->num_subs--;
5115*e4b17023SJohn Marino 	  }
5116*e4b17023SJohn Marino 
5117*e4b17023SJohn Marino       omega_unprotect_1 (pb, &idx, NULL);
5118*e4b17023SJohn Marino       free (bring_to_life);
5119*e4b17023SJohn Marino     }
5120*e4b17023SJohn Marino 
5121*e4b17023SJohn Marino   chain_unprotect (pb);
5122*e4b17023SJohn Marino }
5123*e4b17023SJohn Marino 
5124*e4b17023SJohn Marino /* Unprotects VAR and simplifies PB.  */
5125*e4b17023SJohn Marino 
5126*e4b17023SJohn Marino enum omega_result
omega_constrain_variable_sign(omega_pb pb,enum omega_eqn_color color,int var,int sign)5127*e4b17023SJohn Marino omega_constrain_variable_sign (omega_pb pb, enum omega_eqn_color color,
5128*e4b17023SJohn Marino 			       int var, int sign)
5129*e4b17023SJohn Marino {
5130*e4b17023SJohn Marino   int n_vars = pb->num_vars;
5131*e4b17023SJohn Marino   int e, j;
5132*e4b17023SJohn Marino   int k = pb->forwarding_address[var];
5133*e4b17023SJohn Marino 
5134*e4b17023SJohn Marino   if (k < 0)
5135*e4b17023SJohn Marino     {
5136*e4b17023SJohn Marino       k = -1 - k;
5137*e4b17023SJohn Marino 
5138*e4b17023SJohn Marino       if (sign != 0)
5139*e4b17023SJohn Marino 	{
5140*e4b17023SJohn Marino 	  e = pb->num_geqs++;
5141*e4b17023SJohn Marino 	  omega_copy_eqn (&pb->geqs[e], &pb->subs[k], pb->num_vars);
5142*e4b17023SJohn Marino 
5143*e4b17023SJohn Marino 	  for (j = 0; j <= n_vars; j++)
5144*e4b17023SJohn Marino 	    pb->geqs[e].coef[j] *= sign;
5145*e4b17023SJohn Marino 
5146*e4b17023SJohn Marino 	  pb->geqs[e].coef[0]--;
5147*e4b17023SJohn Marino 	  pb->geqs[e].touched = 1;
5148*e4b17023SJohn Marino 	  pb->geqs[e].color = color;
5149*e4b17023SJohn Marino 	}
5150*e4b17023SJohn Marino       else
5151*e4b17023SJohn Marino 	{
5152*e4b17023SJohn Marino 	  e = pb->num_eqs++;
5153*e4b17023SJohn Marino 	  gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5154*e4b17023SJohn Marino 	  omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5155*e4b17023SJohn Marino 	  pb->eqs[e].color = color;
5156*e4b17023SJohn Marino 	}
5157*e4b17023SJohn Marino     }
5158*e4b17023SJohn Marino   else if (sign != 0)
5159*e4b17023SJohn Marino     {
5160*e4b17023SJohn Marino       e = pb->num_geqs++;
5161*e4b17023SJohn Marino       omega_init_eqn_zero (&pb->geqs[e], pb->num_vars);
5162*e4b17023SJohn Marino       pb->geqs[e].coef[k] = sign;
5163*e4b17023SJohn Marino       pb->geqs[e].coef[0] = -1;
5164*e4b17023SJohn Marino       pb->geqs[e].touched = 1;
5165*e4b17023SJohn Marino       pb->geqs[e].color = color;
5166*e4b17023SJohn Marino     }
5167*e4b17023SJohn Marino   else
5168*e4b17023SJohn Marino     {
5169*e4b17023SJohn Marino       e = pb->num_eqs++;
5170*e4b17023SJohn Marino       gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5171*e4b17023SJohn Marino       omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5172*e4b17023SJohn Marino       pb->eqs[e].coef[k] = 1;
5173*e4b17023SJohn Marino       pb->eqs[e].color = color;
5174*e4b17023SJohn Marino     }
5175*e4b17023SJohn Marino 
5176*e4b17023SJohn Marino   omega_unprotect_variable (pb, var);
5177*e4b17023SJohn Marino   return omega_simplify_problem (pb);
5178*e4b17023SJohn Marino }
5179*e4b17023SJohn Marino 
5180*e4b17023SJohn Marino /* Add an equation "VAR = VALUE" with COLOR to PB.  */
5181*e4b17023SJohn Marino 
5182*e4b17023SJohn Marino void
omega_constrain_variable_value(omega_pb pb,enum omega_eqn_color color,int var,int value)5183*e4b17023SJohn Marino omega_constrain_variable_value (omega_pb pb, enum omega_eqn_color color,
5184*e4b17023SJohn Marino 				int var, int value)
5185*e4b17023SJohn Marino {
5186*e4b17023SJohn Marino   int e;
5187*e4b17023SJohn Marino   int k = pb->forwarding_address[var];
5188*e4b17023SJohn Marino 
5189*e4b17023SJohn Marino   if (k < 0)
5190*e4b17023SJohn Marino     {
5191*e4b17023SJohn Marino       k = -1 - k;
5192*e4b17023SJohn Marino       e = pb->num_eqs++;
5193*e4b17023SJohn Marino       gcc_assert (pb->num_eqs <= OMEGA_MAX_EQS);
5194*e4b17023SJohn Marino       omega_copy_eqn (&pb->eqs[e], &pb->subs[k], pb->num_vars);
5195*e4b17023SJohn Marino       pb->eqs[e].coef[0] -= value;
5196*e4b17023SJohn Marino     }
5197*e4b17023SJohn Marino   else
5198*e4b17023SJohn Marino     {
5199*e4b17023SJohn Marino       e = pb->num_eqs++;
5200*e4b17023SJohn Marino       omega_init_eqn_zero (&pb->eqs[e], pb->num_vars);
5201*e4b17023SJohn Marino       pb->eqs[e].coef[k] = 1;
5202*e4b17023SJohn Marino       pb->eqs[e].coef[0] = -value;
5203*e4b17023SJohn Marino     }
5204*e4b17023SJohn Marino 
5205*e4b17023SJohn Marino   pb->eqs[e].color = color;
5206*e4b17023SJohn Marino }
5207*e4b17023SJohn Marino 
5208*e4b17023SJohn Marino /* Return false when the upper and lower bounds are not coupled.
5209*e4b17023SJohn Marino    Initialize the bounds LOWER_BOUND and UPPER_BOUND for the values of
5210*e4b17023SJohn Marino    variable I.  */
5211*e4b17023SJohn Marino 
5212*e4b17023SJohn Marino bool
omega_query_variable(omega_pb pb,int i,int * lower_bound,int * upper_bound)5213*e4b17023SJohn Marino omega_query_variable (omega_pb pb, int i, int *lower_bound, int *upper_bound)
5214*e4b17023SJohn Marino {
5215*e4b17023SJohn Marino   int n_vars = pb->num_vars;
5216*e4b17023SJohn Marino   int e, j;
5217*e4b17023SJohn Marino   bool is_simple;
5218*e4b17023SJohn Marino   bool coupled = false;
5219*e4b17023SJohn Marino 
5220*e4b17023SJohn Marino   *lower_bound = neg_infinity;
5221*e4b17023SJohn Marino   *upper_bound = pos_infinity;
5222*e4b17023SJohn Marino   i = pb->forwarding_address[i];
5223*e4b17023SJohn Marino 
5224*e4b17023SJohn Marino   if (i < 0)
5225*e4b17023SJohn Marino     {
5226*e4b17023SJohn Marino       i = -i - 1;
5227*e4b17023SJohn Marino 
5228*e4b17023SJohn Marino       for (j = 1; j <= n_vars; j++)
5229*e4b17023SJohn Marino 	if (pb->subs[i].coef[j] != 0)
5230*e4b17023SJohn Marino 	  return true;
5231*e4b17023SJohn Marino 
5232*e4b17023SJohn Marino       *upper_bound = *lower_bound = pb->subs[i].coef[0];
5233*e4b17023SJohn Marino       return false;
5234*e4b17023SJohn Marino     }
5235*e4b17023SJohn Marino 
5236*e4b17023SJohn Marino   for (e = pb->num_subs - 1; e >= 0; e--)
5237*e4b17023SJohn Marino     if (pb->subs[e].coef[i] != 0)
5238*e4b17023SJohn Marino       coupled = true;
5239*e4b17023SJohn Marino 
5240*e4b17023SJohn Marino   for (e = pb->num_eqs - 1; e >= 0; e--)
5241*e4b17023SJohn Marino     if (pb->eqs[e].coef[i] != 0)
5242*e4b17023SJohn Marino       {
5243*e4b17023SJohn Marino 	is_simple = true;
5244*e4b17023SJohn Marino 
5245*e4b17023SJohn Marino 	for (j = 1; j <= n_vars; j++)
5246*e4b17023SJohn Marino 	  if (i != j && pb->eqs[e].coef[j] != 0)
5247*e4b17023SJohn Marino 	    {
5248*e4b17023SJohn Marino 	      is_simple = false;
5249*e4b17023SJohn Marino 	      coupled = true;
5250*e4b17023SJohn Marino 	      break;
5251*e4b17023SJohn Marino 	    }
5252*e4b17023SJohn Marino 
5253*e4b17023SJohn Marino 	if (!is_simple)
5254*e4b17023SJohn Marino 	  continue;
5255*e4b17023SJohn Marino 	else
5256*e4b17023SJohn Marino 	  {
5257*e4b17023SJohn Marino 	    *lower_bound = *upper_bound =
5258*e4b17023SJohn Marino 	      -pb->eqs[e].coef[i] * pb->eqs[e].coef[0];
5259*e4b17023SJohn Marino 	    return false;
5260*e4b17023SJohn Marino 	  }
5261*e4b17023SJohn Marino       }
5262*e4b17023SJohn Marino 
5263*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
5264*e4b17023SJohn Marino     if (pb->geqs[e].coef[i] != 0)
5265*e4b17023SJohn Marino       {
5266*e4b17023SJohn Marino 	if (pb->geqs[e].key == i)
5267*e4b17023SJohn Marino 	  *lower_bound = MAX (*lower_bound, -pb->geqs[e].coef[0]);
5268*e4b17023SJohn Marino 
5269*e4b17023SJohn Marino 	else if (pb->geqs[e].key == -i)
5270*e4b17023SJohn Marino 	  *upper_bound = MIN (*upper_bound, pb->geqs[e].coef[0]);
5271*e4b17023SJohn Marino 
5272*e4b17023SJohn Marino 	else
5273*e4b17023SJohn Marino 	  coupled = true;
5274*e4b17023SJohn Marino       }
5275*e4b17023SJohn Marino 
5276*e4b17023SJohn Marino   return coupled;
5277*e4b17023SJohn Marino }
5278*e4b17023SJohn Marino 
5279*e4b17023SJohn Marino /* Sets the lower bound L and upper bound U for the values of variable
5280*e4b17023SJohn Marino    I, and sets COULD_BE_ZERO to true if variable I might take value
5281*e4b17023SJohn Marino    zero.  LOWER_BOUND and UPPER_BOUND are bounds on the values of
5282*e4b17023SJohn Marino    variable I.  */
5283*e4b17023SJohn Marino 
5284*e4b17023SJohn Marino static void
query_coupled_variable(omega_pb pb,int i,int * l,int * u,bool * could_be_zero,int lower_bound,int upper_bound)5285*e4b17023SJohn Marino query_coupled_variable (omega_pb pb, int i, int *l, int *u,
5286*e4b17023SJohn Marino 			bool *could_be_zero, int lower_bound, int upper_bound)
5287*e4b17023SJohn Marino {
5288*e4b17023SJohn Marino   int e, b1, b2;
5289*e4b17023SJohn Marino   eqn eqn;
5290*e4b17023SJohn Marino   int sign;
5291*e4b17023SJohn Marino   int v;
5292*e4b17023SJohn Marino 
5293*e4b17023SJohn Marino   /* Preconditions.  */
5294*e4b17023SJohn Marino   gcc_assert (abs (pb->forwarding_address[i]) == 1
5295*e4b17023SJohn Marino 	      && pb->num_vars + pb->num_subs == 2
5296*e4b17023SJohn Marino 	      && pb->num_eqs + pb->num_subs == 1);
5297*e4b17023SJohn Marino 
5298*e4b17023SJohn Marino   /* Define variable I in terms of variable V.  */
5299*e4b17023SJohn Marino   if (pb->forwarding_address[i] == -1)
5300*e4b17023SJohn Marino     {
5301*e4b17023SJohn Marino       eqn = &pb->subs[0];
5302*e4b17023SJohn Marino       sign = 1;
5303*e4b17023SJohn Marino       v = 1;
5304*e4b17023SJohn Marino     }
5305*e4b17023SJohn Marino   else
5306*e4b17023SJohn Marino     {
5307*e4b17023SJohn Marino       eqn = &pb->eqs[0];
5308*e4b17023SJohn Marino       sign = -eqn->coef[1];
5309*e4b17023SJohn Marino       v = 2;
5310*e4b17023SJohn Marino     }
5311*e4b17023SJohn Marino 
5312*e4b17023SJohn Marino   for (e = pb->num_geqs - 1; e >= 0; e--)
5313*e4b17023SJohn Marino     if (pb->geqs[e].coef[v] != 0)
5314*e4b17023SJohn Marino       {
5315*e4b17023SJohn Marino 	if (pb->geqs[e].coef[v] == 1)
5316*e4b17023SJohn Marino 	  lower_bound = MAX (lower_bound, -pb->geqs[e].coef[0]);
5317*e4b17023SJohn Marino 
5318*e4b17023SJohn Marino 	else
5319*e4b17023SJohn Marino 	  upper_bound = MIN (upper_bound, pb->geqs[e].coef[0]);
5320*e4b17023SJohn Marino       }
5321*e4b17023SJohn Marino 
5322*e4b17023SJohn Marino   if (lower_bound > upper_bound)
5323*e4b17023SJohn Marino     {
5324*e4b17023SJohn Marino       *l = pos_infinity;
5325*e4b17023SJohn Marino       *u = neg_infinity;
5326*e4b17023SJohn Marino       *could_be_zero = 0;
5327*e4b17023SJohn Marino       return;
5328*e4b17023SJohn Marino     }
5329*e4b17023SJohn Marino 
5330*e4b17023SJohn Marino   if (lower_bound == neg_infinity)
5331*e4b17023SJohn Marino     {
5332*e4b17023SJohn Marino       if (eqn->coef[v] > 0)
5333*e4b17023SJohn Marino 	b1 = sign * neg_infinity;
5334*e4b17023SJohn Marino 
5335*e4b17023SJohn Marino       else
5336*e4b17023SJohn Marino 	b1 = -sign * neg_infinity;
5337*e4b17023SJohn Marino     }
5338*e4b17023SJohn Marino   else
5339*e4b17023SJohn Marino     b1 = sign * (eqn->coef[0] + eqn->coef[v] * lower_bound);
5340*e4b17023SJohn Marino 
5341*e4b17023SJohn Marino   if (upper_bound == pos_infinity)
5342*e4b17023SJohn Marino     {
5343*e4b17023SJohn Marino       if (eqn->coef[v] > 0)
5344*e4b17023SJohn Marino 	b2 = sign * pos_infinity;
5345*e4b17023SJohn Marino 
5346*e4b17023SJohn Marino       else
5347*e4b17023SJohn Marino 	b2 = -sign * pos_infinity;
5348*e4b17023SJohn Marino     }
5349*e4b17023SJohn Marino   else
5350*e4b17023SJohn Marino     b2 = sign * (eqn->coef[0] + eqn->coef[v] * upper_bound);
5351*e4b17023SJohn Marino 
5352*e4b17023SJohn Marino   *l = MAX (*l, b1 <= b2 ? b1 : b2);
5353*e4b17023SJohn Marino   *u = MIN (*u, b1 <= b2 ? b2 : b1);
5354*e4b17023SJohn Marino 
5355*e4b17023SJohn Marino   *could_be_zero = (*l <= 0 && 0 <= *u
5356*e4b17023SJohn Marino 		    && int_mod (eqn->coef[0], abs (eqn->coef[v])) == 0);
5357*e4b17023SJohn Marino }
5358*e4b17023SJohn Marino 
5359*e4b17023SJohn Marino /* Return false when a lower bound L and an upper bound U for variable
5360*e4b17023SJohn Marino    I in problem PB have been initialized.  */
5361*e4b17023SJohn Marino 
5362*e4b17023SJohn Marino bool
omega_query_variable_bounds(omega_pb pb,int i,int * l,int * u)5363*e4b17023SJohn Marino omega_query_variable_bounds (omega_pb pb, int i, int *l, int *u)
5364*e4b17023SJohn Marino {
5365*e4b17023SJohn Marino   *l = neg_infinity;
5366*e4b17023SJohn Marino   *u = pos_infinity;
5367*e4b17023SJohn Marino 
5368*e4b17023SJohn Marino   if (!omega_query_variable (pb, i, l, u)
5369*e4b17023SJohn Marino       || (pb->num_vars == 1 && pb->forwarding_address[i] == 1))
5370*e4b17023SJohn Marino     return false;
5371*e4b17023SJohn Marino 
5372*e4b17023SJohn Marino   if (abs (pb->forwarding_address[i]) == 1
5373*e4b17023SJohn Marino       && pb->num_vars + pb->num_subs == 2
5374*e4b17023SJohn Marino       && pb->num_eqs + pb->num_subs == 1)
5375*e4b17023SJohn Marino     {
5376*e4b17023SJohn Marino       bool could_be_zero;
5377*e4b17023SJohn Marino       query_coupled_variable (pb, i, l, u, &could_be_zero, neg_infinity,
5378*e4b17023SJohn Marino 			      pos_infinity);
5379*e4b17023SJohn Marino       return false;
5380*e4b17023SJohn Marino     }
5381*e4b17023SJohn Marino 
5382*e4b17023SJohn Marino   return true;
5383*e4b17023SJohn Marino }
5384*e4b17023SJohn Marino 
5385*e4b17023SJohn Marino /* For problem PB, return an integer that represents the classic data
5386*e4b17023SJohn Marino    dependence direction in function of the DD_LT, DD_EQ and DD_GT bit
5387*e4b17023SJohn Marino    masks that are added to the result.  When DIST_KNOWN is true, DIST
5388*e4b17023SJohn Marino    is set to the classic data dependence distance.  LOWER_BOUND and
5389*e4b17023SJohn Marino    UPPER_BOUND are bounds on the value of variable I, for example, it
5390*e4b17023SJohn Marino    is possible to narrow the iteration domain with safe approximations
5391*e4b17023SJohn Marino    of loop counts, and thus discard some data dependences that cannot
5392*e4b17023SJohn Marino    occur.  */
5393*e4b17023SJohn Marino 
5394*e4b17023SJohn Marino int
omega_query_variable_signs(omega_pb pb,int i,int dd_lt,int dd_eq,int dd_gt,int lower_bound,int upper_bound,bool * dist_known,int * dist)5395*e4b17023SJohn Marino omega_query_variable_signs (omega_pb pb, int i, int dd_lt,
5396*e4b17023SJohn Marino 			    int dd_eq, int dd_gt, int lower_bound,
5397*e4b17023SJohn Marino 			    int upper_bound, bool *dist_known, int *dist)
5398*e4b17023SJohn Marino {
5399*e4b17023SJohn Marino   int result;
5400*e4b17023SJohn Marino   int l, u;
5401*e4b17023SJohn Marino   bool could_be_zero;
5402*e4b17023SJohn Marino 
5403*e4b17023SJohn Marino   l = neg_infinity;
5404*e4b17023SJohn Marino   u = pos_infinity;
5405*e4b17023SJohn Marino 
5406*e4b17023SJohn Marino   omega_query_variable (pb, i, &l, &u);
5407*e4b17023SJohn Marino   query_coupled_variable (pb, i, &l, &u, &could_be_zero, lower_bound,
5408*e4b17023SJohn Marino 			  upper_bound);
5409*e4b17023SJohn Marino   result = 0;
5410*e4b17023SJohn Marino 
5411*e4b17023SJohn Marino   if (l < 0)
5412*e4b17023SJohn Marino     result |= dd_gt;
5413*e4b17023SJohn Marino 
5414*e4b17023SJohn Marino   if (u > 0)
5415*e4b17023SJohn Marino     result |= dd_lt;
5416*e4b17023SJohn Marino 
5417*e4b17023SJohn Marino   if (could_be_zero)
5418*e4b17023SJohn Marino     result |= dd_eq;
5419*e4b17023SJohn Marino 
5420*e4b17023SJohn Marino   if (l == u)
5421*e4b17023SJohn Marino     {
5422*e4b17023SJohn Marino       *dist_known = true;
5423*e4b17023SJohn Marino       *dist = l;
5424*e4b17023SJohn Marino     }
5425*e4b17023SJohn Marino   else
5426*e4b17023SJohn Marino     *dist_known = false;
5427*e4b17023SJohn Marino 
5428*e4b17023SJohn Marino   return result;
5429*e4b17023SJohn Marino }
5430*e4b17023SJohn Marino 
5431*e4b17023SJohn Marino /* Initialize PB as an Omega problem with NVARS variables and NPROT
5432*e4b17023SJohn Marino    safe variables.  Safe variables are not eliminated during the
5433*e4b17023SJohn Marino    Fourier-Motzkin elimination.  Safe variables are all those
5434*e4b17023SJohn Marino    variables that are placed at the beginning of the array of
5435*e4b17023SJohn Marino    variables: P->var[0, ..., NPROT - 1].  */
5436*e4b17023SJohn Marino 
5437*e4b17023SJohn Marino omega_pb
omega_alloc_problem(int nvars,int nprot)5438*e4b17023SJohn Marino omega_alloc_problem (int nvars, int nprot)
5439*e4b17023SJohn Marino {
5440*e4b17023SJohn Marino   omega_pb pb;
5441*e4b17023SJohn Marino 
5442*e4b17023SJohn Marino   gcc_assert (nvars <= OMEGA_MAX_VARS);
5443*e4b17023SJohn Marino   omega_initialize ();
5444*e4b17023SJohn Marino 
5445*e4b17023SJohn Marino   /* Allocate and initialize PB.  */
5446*e4b17023SJohn Marino   pb = XCNEW (struct omega_pb_d);
5447*e4b17023SJohn Marino   pb->var = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5448*e4b17023SJohn Marino   pb->forwarding_address = XCNEWVEC (int, OMEGA_MAX_VARS + 2);
5449*e4b17023SJohn Marino   pb->geqs = omega_alloc_eqns (0, OMEGA_MAX_GEQS);
5450*e4b17023SJohn Marino   pb->eqs = omega_alloc_eqns (0, OMEGA_MAX_EQS);
5451*e4b17023SJohn Marino   pb->subs = omega_alloc_eqns (0, OMEGA_MAX_VARS + 1);
5452*e4b17023SJohn Marino 
5453*e4b17023SJohn Marino   pb->hash_version = hash_version;
5454*e4b17023SJohn Marino   pb->num_vars = nvars;
5455*e4b17023SJohn Marino   pb->safe_vars = nprot;
5456*e4b17023SJohn Marino   pb->variables_initialized = false;
5457*e4b17023SJohn Marino   pb->variables_freed = false;
5458*e4b17023SJohn Marino   pb->num_eqs = 0;
5459*e4b17023SJohn Marino   pb->num_geqs = 0;
5460*e4b17023SJohn Marino   pb->num_subs = 0;
5461*e4b17023SJohn Marino   return pb;
5462*e4b17023SJohn Marino }
5463*e4b17023SJohn Marino 
5464*e4b17023SJohn Marino /* Keeps the state of the initialization.  */
5465*e4b17023SJohn Marino static bool omega_initialized = false;
5466*e4b17023SJohn Marino 
5467*e4b17023SJohn Marino /* Initialization of the Omega solver.  */
5468*e4b17023SJohn Marino 
5469*e4b17023SJohn Marino void
omega_initialize(void)5470*e4b17023SJohn Marino omega_initialize (void)
5471*e4b17023SJohn Marino {
5472*e4b17023SJohn Marino   int i;
5473*e4b17023SJohn Marino 
5474*e4b17023SJohn Marino   if (omega_initialized)
5475*e4b17023SJohn Marino     return;
5476*e4b17023SJohn Marino 
5477*e4b17023SJohn Marino   next_wild_card = 0;
5478*e4b17023SJohn Marino   next_key = OMEGA_MAX_VARS + 1;
5479*e4b17023SJohn Marino   packing = XCNEWVEC (int, OMEGA_MAX_VARS);
5480*e4b17023SJohn Marino   fast_lookup = XCNEWVEC (int, MAX_KEYS * 2);
5481*e4b17023SJohn Marino   fast_lookup_red = XCNEWVEC (int, MAX_KEYS * 2);
5482*e4b17023SJohn Marino   hash_master = omega_alloc_eqns (0, HASH_TABLE_SIZE);
5483*e4b17023SJohn Marino 
5484*e4b17023SJohn Marino   for (i = 0; i < HASH_TABLE_SIZE; i++)
5485*e4b17023SJohn Marino     hash_master[i].touched = -1;
5486*e4b17023SJohn Marino 
5487*e4b17023SJohn Marino   sprintf (wild_name[0], "1");
5488*e4b17023SJohn Marino   sprintf (wild_name[1], "a");
5489*e4b17023SJohn Marino   sprintf (wild_name[2], "b");
5490*e4b17023SJohn Marino   sprintf (wild_name[3], "c");
5491*e4b17023SJohn Marino   sprintf (wild_name[4], "d");
5492*e4b17023SJohn Marino   sprintf (wild_name[5], "e");
5493*e4b17023SJohn Marino   sprintf (wild_name[6], "f");
5494*e4b17023SJohn Marino   sprintf (wild_name[7], "g");
5495*e4b17023SJohn Marino   sprintf (wild_name[8], "h");
5496*e4b17023SJohn Marino   sprintf (wild_name[9], "i");
5497*e4b17023SJohn Marino   sprintf (wild_name[10], "j");
5498*e4b17023SJohn Marino   sprintf (wild_name[11], "k");
5499*e4b17023SJohn Marino   sprintf (wild_name[12], "l");
5500*e4b17023SJohn Marino   sprintf (wild_name[13], "m");
5501*e4b17023SJohn Marino   sprintf (wild_name[14], "n");
5502*e4b17023SJohn Marino   sprintf (wild_name[15], "o");
5503*e4b17023SJohn Marino   sprintf (wild_name[16], "p");
5504*e4b17023SJohn Marino   sprintf (wild_name[17], "q");
5505*e4b17023SJohn Marino   sprintf (wild_name[18], "r");
5506*e4b17023SJohn Marino   sprintf (wild_name[19], "s");
5507*e4b17023SJohn Marino   sprintf (wild_name[20], "t");
5508*e4b17023SJohn Marino   sprintf (wild_name[40 - 1], "alpha");
5509*e4b17023SJohn Marino   sprintf (wild_name[40 - 2], "beta");
5510*e4b17023SJohn Marino   sprintf (wild_name[40 - 3], "gamma");
5511*e4b17023SJohn Marino   sprintf (wild_name[40 - 4], "delta");
5512*e4b17023SJohn Marino   sprintf (wild_name[40 - 5], "tau");
5513*e4b17023SJohn Marino   sprintf (wild_name[40 - 6], "sigma");
5514*e4b17023SJohn Marino   sprintf (wild_name[40 - 7], "chi");
5515*e4b17023SJohn Marino   sprintf (wild_name[40 - 8], "omega");
5516*e4b17023SJohn Marino   sprintf (wild_name[40 - 9], "pi");
5517*e4b17023SJohn Marino   sprintf (wild_name[40 - 10], "ni");
5518*e4b17023SJohn Marino   sprintf (wild_name[40 - 11], "Alpha");
5519*e4b17023SJohn Marino   sprintf (wild_name[40 - 12], "Beta");
5520*e4b17023SJohn Marino   sprintf (wild_name[40 - 13], "Gamma");
5521*e4b17023SJohn Marino   sprintf (wild_name[40 - 14], "Delta");
5522*e4b17023SJohn Marino   sprintf (wild_name[40 - 15], "Tau");
5523*e4b17023SJohn Marino   sprintf (wild_name[40 - 16], "Sigma");
5524*e4b17023SJohn Marino   sprintf (wild_name[40 - 17], "Chi");
5525*e4b17023SJohn Marino   sprintf (wild_name[40 - 18], "Omega");
5526*e4b17023SJohn Marino   sprintf (wild_name[40 - 19], "xxx");
5527*e4b17023SJohn Marino 
5528*e4b17023SJohn Marino   omega_initialized = true;
5529*e4b17023SJohn Marino }
5530