xref: /dragonfly/contrib/gcc-4.7/gcc/tree-chrec.c (revision e4b17023)
1*e4b17023SJohn Marino /* Chains of recurrences.
2*e4b17023SJohn Marino    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino /* This file implements operations on chains of recurrences.  Chains
23*e4b17023SJohn Marino    of recurrences are used for modeling evolution functions of scalar
24*e4b17023SJohn Marino    variables.
25*e4b17023SJohn Marino */
26*e4b17023SJohn Marino 
27*e4b17023SJohn Marino #include "config.h"
28*e4b17023SJohn Marino #include "system.h"
29*e4b17023SJohn Marino #include "coretypes.h"
30*e4b17023SJohn Marino #include "tree-pretty-print.h"
31*e4b17023SJohn Marino #include "cfgloop.h"
32*e4b17023SJohn Marino #include "tree-flow.h"
33*e4b17023SJohn Marino #include "tree-chrec.h"
34*e4b17023SJohn Marino #include "tree-pass.h"
35*e4b17023SJohn Marino #include "params.h"
36*e4b17023SJohn Marino #include "tree-scalar-evolution.h"
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino /* Extended folder for chrecs.  */
39*e4b17023SJohn Marino 
40*e4b17023SJohn Marino /* Determines whether CST is not a constant evolution.  */
41*e4b17023SJohn Marino 
42*e4b17023SJohn Marino static inline bool
is_not_constant_evolution(const_tree cst)43*e4b17023SJohn Marino is_not_constant_evolution (const_tree cst)
44*e4b17023SJohn Marino {
45*e4b17023SJohn Marino   return (TREE_CODE (cst) == POLYNOMIAL_CHREC);
46*e4b17023SJohn Marino }
47*e4b17023SJohn Marino 
48*e4b17023SJohn Marino /* Fold CODE for a polynomial function and a constant.  */
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino static inline tree
chrec_fold_poly_cst(enum tree_code code,tree type,tree poly,tree cst)51*e4b17023SJohn Marino chrec_fold_poly_cst (enum tree_code code,
52*e4b17023SJohn Marino 		     tree type,
53*e4b17023SJohn Marino 		     tree poly,
54*e4b17023SJohn Marino 		     tree cst)
55*e4b17023SJohn Marino {
56*e4b17023SJohn Marino   gcc_assert (poly);
57*e4b17023SJohn Marino   gcc_assert (cst);
58*e4b17023SJohn Marino   gcc_assert (TREE_CODE (poly) == POLYNOMIAL_CHREC);
59*e4b17023SJohn Marino   gcc_assert (!is_not_constant_evolution (cst));
60*e4b17023SJohn Marino   gcc_assert (type == chrec_type (poly));
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino   switch (code)
63*e4b17023SJohn Marino     {
64*e4b17023SJohn Marino     case PLUS_EXPR:
65*e4b17023SJohn Marino       return build_polynomial_chrec
66*e4b17023SJohn Marino 	(CHREC_VARIABLE (poly),
67*e4b17023SJohn Marino 	 chrec_fold_plus (type, CHREC_LEFT (poly), cst),
68*e4b17023SJohn Marino 	 CHREC_RIGHT (poly));
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino     case MINUS_EXPR:
71*e4b17023SJohn Marino       return build_polynomial_chrec
72*e4b17023SJohn Marino 	(CHREC_VARIABLE (poly),
73*e4b17023SJohn Marino 	 chrec_fold_minus (type, CHREC_LEFT (poly), cst),
74*e4b17023SJohn Marino 	 CHREC_RIGHT (poly));
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino     case MULT_EXPR:
77*e4b17023SJohn Marino       return build_polynomial_chrec
78*e4b17023SJohn Marino 	(CHREC_VARIABLE (poly),
79*e4b17023SJohn Marino 	 chrec_fold_multiply (type, CHREC_LEFT (poly), cst),
80*e4b17023SJohn Marino 	 chrec_fold_multiply (type, CHREC_RIGHT (poly), cst));
81*e4b17023SJohn Marino 
82*e4b17023SJohn Marino     default:
83*e4b17023SJohn Marino       return chrec_dont_know;
84*e4b17023SJohn Marino     }
85*e4b17023SJohn Marino }
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino /* Fold the addition of two polynomial functions.  */
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino static inline tree
chrec_fold_plus_poly_poly(enum tree_code code,tree type,tree poly0,tree poly1)90*e4b17023SJohn Marino chrec_fold_plus_poly_poly (enum tree_code code,
91*e4b17023SJohn Marino 			   tree type,
92*e4b17023SJohn Marino 			   tree poly0,
93*e4b17023SJohn Marino 			   tree poly1)
94*e4b17023SJohn Marino {
95*e4b17023SJohn Marino   tree left, right;
96*e4b17023SJohn Marino   struct loop *loop0 = get_chrec_loop (poly0);
97*e4b17023SJohn Marino   struct loop *loop1 = get_chrec_loop (poly1);
98*e4b17023SJohn Marino   tree rtype = code == POINTER_PLUS_EXPR ? chrec_type (poly1) : type;
99*e4b17023SJohn Marino 
100*e4b17023SJohn Marino   gcc_assert (poly0);
101*e4b17023SJohn Marino   gcc_assert (poly1);
102*e4b17023SJohn Marino   gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC);
103*e4b17023SJohn Marino   gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC);
104*e4b17023SJohn Marino   if (POINTER_TYPE_P (chrec_type (poly0)))
105*e4b17023SJohn Marino     gcc_assert (ptrofftype_p (chrec_type (poly1)));
106*e4b17023SJohn Marino   else
107*e4b17023SJohn Marino     gcc_assert (chrec_type (poly0) == chrec_type (poly1));
108*e4b17023SJohn Marino   gcc_assert (type == chrec_type (poly0));
109*e4b17023SJohn Marino 
110*e4b17023SJohn Marino   /*
111*e4b17023SJohn Marino     {a, +, b}_1 + {c, +, d}_2  ->  {{a, +, b}_1 + c, +, d}_2,
112*e4b17023SJohn Marino     {a, +, b}_2 + {c, +, d}_1  ->  {{c, +, d}_1 + a, +, b}_2,
113*e4b17023SJohn Marino     {a, +, b}_x + {c, +, d}_x  ->  {a+c, +, b+d}_x.  */
114*e4b17023SJohn Marino   if (flow_loop_nested_p (loop0, loop1))
115*e4b17023SJohn Marino     {
116*e4b17023SJohn Marino       if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
117*e4b17023SJohn Marino 	return build_polynomial_chrec
118*e4b17023SJohn Marino 	  (CHREC_VARIABLE (poly1),
119*e4b17023SJohn Marino 	   chrec_fold_plus (type, poly0, CHREC_LEFT (poly1)),
120*e4b17023SJohn Marino 	   CHREC_RIGHT (poly1));
121*e4b17023SJohn Marino       else
122*e4b17023SJohn Marino 	return build_polynomial_chrec
123*e4b17023SJohn Marino 	  (CHREC_VARIABLE (poly1),
124*e4b17023SJohn Marino 	   chrec_fold_minus (type, poly0, CHREC_LEFT (poly1)),
125*e4b17023SJohn Marino 	   chrec_fold_multiply (type, CHREC_RIGHT (poly1),
126*e4b17023SJohn Marino 				SCALAR_FLOAT_TYPE_P (type)
127*e4b17023SJohn Marino 				? build_real (type, dconstm1)
128*e4b17023SJohn Marino 				: build_int_cst_type (type, -1)));
129*e4b17023SJohn Marino     }
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino   if (flow_loop_nested_p (loop1, loop0))
132*e4b17023SJohn Marino     {
133*e4b17023SJohn Marino       if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
134*e4b17023SJohn Marino 	return build_polynomial_chrec
135*e4b17023SJohn Marino 	  (CHREC_VARIABLE (poly0),
136*e4b17023SJohn Marino 	   chrec_fold_plus (type, CHREC_LEFT (poly0), poly1),
137*e4b17023SJohn Marino 	   CHREC_RIGHT (poly0));
138*e4b17023SJohn Marino       else
139*e4b17023SJohn Marino 	return build_polynomial_chrec
140*e4b17023SJohn Marino 	  (CHREC_VARIABLE (poly0),
141*e4b17023SJohn Marino 	   chrec_fold_minus (type, CHREC_LEFT (poly0), poly1),
142*e4b17023SJohn Marino 	   CHREC_RIGHT (poly0));
143*e4b17023SJohn Marino     }
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino   /* This function should never be called for chrecs of loops that
146*e4b17023SJohn Marino      do not belong to the same loop nest.  */
147*e4b17023SJohn Marino   gcc_assert (loop0 == loop1);
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino   if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
150*e4b17023SJohn Marino     {
151*e4b17023SJohn Marino       left = chrec_fold_plus
152*e4b17023SJohn Marino 	(type, CHREC_LEFT (poly0), CHREC_LEFT (poly1));
153*e4b17023SJohn Marino       right = chrec_fold_plus
154*e4b17023SJohn Marino 	(rtype, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1));
155*e4b17023SJohn Marino     }
156*e4b17023SJohn Marino   else
157*e4b17023SJohn Marino     {
158*e4b17023SJohn Marino       left = chrec_fold_minus
159*e4b17023SJohn Marino 	(type, CHREC_LEFT (poly0), CHREC_LEFT (poly1));
160*e4b17023SJohn Marino       right = chrec_fold_minus
161*e4b17023SJohn Marino 	(type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1));
162*e4b17023SJohn Marino     }
163*e4b17023SJohn Marino 
164*e4b17023SJohn Marino   if (chrec_zerop (right))
165*e4b17023SJohn Marino     return left;
166*e4b17023SJohn Marino   else
167*e4b17023SJohn Marino     return build_polynomial_chrec
168*e4b17023SJohn Marino       (CHREC_VARIABLE (poly0), left, right);
169*e4b17023SJohn Marino }
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino /* Fold the multiplication of two polynomial functions.  */
174*e4b17023SJohn Marino 
175*e4b17023SJohn Marino static inline tree
chrec_fold_multiply_poly_poly(tree type,tree poly0,tree poly1)176*e4b17023SJohn Marino chrec_fold_multiply_poly_poly (tree type,
177*e4b17023SJohn Marino 			       tree poly0,
178*e4b17023SJohn Marino 			       tree poly1)
179*e4b17023SJohn Marino {
180*e4b17023SJohn Marino   tree t0, t1, t2;
181*e4b17023SJohn Marino   int var;
182*e4b17023SJohn Marino   struct loop *loop0 = get_chrec_loop (poly0);
183*e4b17023SJohn Marino   struct loop *loop1 = get_chrec_loop (poly1);
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino   gcc_assert (poly0);
186*e4b17023SJohn Marino   gcc_assert (poly1);
187*e4b17023SJohn Marino   gcc_assert (TREE_CODE (poly0) == POLYNOMIAL_CHREC);
188*e4b17023SJohn Marino   gcc_assert (TREE_CODE (poly1) == POLYNOMIAL_CHREC);
189*e4b17023SJohn Marino   gcc_assert (chrec_type (poly0) == chrec_type (poly1));
190*e4b17023SJohn Marino   gcc_assert (type == chrec_type (poly0));
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino   /* {a, +, b}_1 * {c, +, d}_2  ->  {c*{a, +, b}_1, +, d}_2,
193*e4b17023SJohn Marino      {a, +, b}_2 * {c, +, d}_1  ->  {a*{c, +, d}_1, +, b}_2,
194*e4b17023SJohn Marino      {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
195*e4b17023SJohn Marino   if (flow_loop_nested_p (loop0, loop1))
196*e4b17023SJohn Marino     /* poly0 is a constant wrt. poly1.  */
197*e4b17023SJohn Marino     return build_polynomial_chrec
198*e4b17023SJohn Marino       (CHREC_VARIABLE (poly1),
199*e4b17023SJohn Marino        chrec_fold_multiply (type, CHREC_LEFT (poly1), poly0),
200*e4b17023SJohn Marino        CHREC_RIGHT (poly1));
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino   if (flow_loop_nested_p (loop1, loop0))
203*e4b17023SJohn Marino     /* poly1 is a constant wrt. poly0.  */
204*e4b17023SJohn Marino     return build_polynomial_chrec
205*e4b17023SJohn Marino       (CHREC_VARIABLE (poly0),
206*e4b17023SJohn Marino        chrec_fold_multiply (type, CHREC_LEFT (poly0), poly1),
207*e4b17023SJohn Marino        CHREC_RIGHT (poly0));
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino   gcc_assert (loop0 == loop1);
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   /* poly0 and poly1 are two polynomials in the same variable,
212*e4b17023SJohn Marino      {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino   /* "a*c".  */
215*e4b17023SJohn Marino   t0 = chrec_fold_multiply (type, CHREC_LEFT (poly0), CHREC_LEFT (poly1));
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino   /* "a*d + b*c".  */
218*e4b17023SJohn Marino   t1 = chrec_fold_multiply (type, CHREC_LEFT (poly0), CHREC_RIGHT (poly1));
219*e4b17023SJohn Marino   t1 = chrec_fold_plus (type, t1, chrec_fold_multiply (type,
220*e4b17023SJohn Marino 						       CHREC_RIGHT (poly0),
221*e4b17023SJohn Marino 						       CHREC_LEFT (poly1)));
222*e4b17023SJohn Marino   /* "b*d".  */
223*e4b17023SJohn Marino   t2 = chrec_fold_multiply (type, CHREC_RIGHT (poly0), CHREC_RIGHT (poly1));
224*e4b17023SJohn Marino   /* "a*d + b*c + b*d".  */
225*e4b17023SJohn Marino   t1 = chrec_fold_plus (type, t1, t2);
226*e4b17023SJohn Marino   /* "2*b*d".  */
227*e4b17023SJohn Marino   t2 = chrec_fold_multiply (type, SCALAR_FLOAT_TYPE_P (type)
228*e4b17023SJohn Marino 			    ? build_real (type, dconst2)
229*e4b17023SJohn Marino 			    : build_int_cst (type, 2), t2);
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino   var = CHREC_VARIABLE (poly0);
232*e4b17023SJohn Marino   return build_polynomial_chrec (var, t0,
233*e4b17023SJohn Marino 				 build_polynomial_chrec (var, t1, t2));
234*e4b17023SJohn Marino }
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino /* When the operands are automatically_generated_chrec_p, the fold has
237*e4b17023SJohn Marino    to respect the semantics of the operands.  */
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino static inline tree
chrec_fold_automatically_generated_operands(tree op0,tree op1)240*e4b17023SJohn Marino chrec_fold_automatically_generated_operands (tree op0,
241*e4b17023SJohn Marino 					     tree op1)
242*e4b17023SJohn Marino {
243*e4b17023SJohn Marino   if (op0 == chrec_dont_know
244*e4b17023SJohn Marino       || op1 == chrec_dont_know)
245*e4b17023SJohn Marino     return chrec_dont_know;
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino   if (op0 == chrec_known
248*e4b17023SJohn Marino       || op1 == chrec_known)
249*e4b17023SJohn Marino     return chrec_known;
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino   if (op0 == chrec_not_analyzed_yet
252*e4b17023SJohn Marino       || op1 == chrec_not_analyzed_yet)
253*e4b17023SJohn Marino     return chrec_not_analyzed_yet;
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   /* The default case produces a safe result.  */
256*e4b17023SJohn Marino   return chrec_dont_know;
257*e4b17023SJohn Marino }
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino /* Fold the addition of two chrecs.  */
260*e4b17023SJohn Marino 
261*e4b17023SJohn Marino static tree
chrec_fold_plus_1(enum tree_code code,tree type,tree op0,tree op1)262*e4b17023SJohn Marino chrec_fold_plus_1 (enum tree_code code, tree type,
263*e4b17023SJohn Marino 		   tree op0, tree op1)
264*e4b17023SJohn Marino {
265*e4b17023SJohn Marino   if (automatically_generated_chrec_p (op0)
266*e4b17023SJohn Marino       || automatically_generated_chrec_p (op1))
267*e4b17023SJohn Marino     return chrec_fold_automatically_generated_operands (op0, op1);
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino   switch (TREE_CODE (op0))
270*e4b17023SJohn Marino     {
271*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
272*e4b17023SJohn Marino       switch (TREE_CODE (op1))
273*e4b17023SJohn Marino 	{
274*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
275*e4b17023SJohn Marino 	  return chrec_fold_plus_poly_poly (code, type, op0, op1);
276*e4b17023SJohn Marino 
277*e4b17023SJohn Marino 	CASE_CONVERT:
278*e4b17023SJohn Marino 	  if (tree_contains_chrecs (op1, NULL))
279*e4b17023SJohn Marino 	    return chrec_dont_know;
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino 	default:
282*e4b17023SJohn Marino 	  if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
283*e4b17023SJohn Marino 	    return build_polynomial_chrec
284*e4b17023SJohn Marino 	      (CHREC_VARIABLE (op0),
285*e4b17023SJohn Marino 	       chrec_fold_plus (type, CHREC_LEFT (op0), op1),
286*e4b17023SJohn Marino 	       CHREC_RIGHT (op0));
287*e4b17023SJohn Marino 	  else
288*e4b17023SJohn Marino 	    return build_polynomial_chrec
289*e4b17023SJohn Marino 	      (CHREC_VARIABLE (op0),
290*e4b17023SJohn Marino 	       chrec_fold_minus (type, CHREC_LEFT (op0), op1),
291*e4b17023SJohn Marino 	       CHREC_RIGHT (op0));
292*e4b17023SJohn Marino 	}
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino     CASE_CONVERT:
295*e4b17023SJohn Marino       if (tree_contains_chrecs (op0, NULL))
296*e4b17023SJohn Marino 	return chrec_dont_know;
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino     default:
299*e4b17023SJohn Marino       switch (TREE_CODE (op1))
300*e4b17023SJohn Marino 	{
301*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
302*e4b17023SJohn Marino 	  if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
303*e4b17023SJohn Marino 	    return build_polynomial_chrec
304*e4b17023SJohn Marino 	      (CHREC_VARIABLE (op1),
305*e4b17023SJohn Marino 	       chrec_fold_plus (type, op0, CHREC_LEFT (op1)),
306*e4b17023SJohn Marino 	       CHREC_RIGHT (op1));
307*e4b17023SJohn Marino 	  else
308*e4b17023SJohn Marino 	    return build_polynomial_chrec
309*e4b17023SJohn Marino 	      (CHREC_VARIABLE (op1),
310*e4b17023SJohn Marino 	       chrec_fold_minus (type, op0, CHREC_LEFT (op1)),
311*e4b17023SJohn Marino 	       chrec_fold_multiply (type, CHREC_RIGHT (op1),
312*e4b17023SJohn Marino 				    SCALAR_FLOAT_TYPE_P (type)
313*e4b17023SJohn Marino 				    ? build_real (type, dconstm1)
314*e4b17023SJohn Marino 				    : build_int_cst_type (type, -1)));
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino 	CASE_CONVERT:
317*e4b17023SJohn Marino 	  if (tree_contains_chrecs (op1, NULL))
318*e4b17023SJohn Marino 	    return chrec_dont_know;
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino 	default:
321*e4b17023SJohn Marino 	  {
322*e4b17023SJohn Marino 	    int size = 0;
323*e4b17023SJohn Marino 	    if ((tree_contains_chrecs (op0, &size)
324*e4b17023SJohn Marino 		 || tree_contains_chrecs (op1, &size))
325*e4b17023SJohn Marino 		&& size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
326*e4b17023SJohn Marino 	      return build2 (code, type, op0, op1);
327*e4b17023SJohn Marino 	    else if (size < PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
328*e4b17023SJohn Marino 	      {
329*e4b17023SJohn Marino 		if (code == POINTER_PLUS_EXPR)
330*e4b17023SJohn Marino 		  return fold_build_pointer_plus (fold_convert (type, op0),
331*e4b17023SJohn Marino 						  op1);
332*e4b17023SJohn Marino 		else
333*e4b17023SJohn Marino 		  return fold_build2 (code, type,
334*e4b17023SJohn Marino 				      fold_convert (type, op0),
335*e4b17023SJohn Marino 				      fold_convert (type, op1));
336*e4b17023SJohn Marino 	      }
337*e4b17023SJohn Marino 	    else
338*e4b17023SJohn Marino 	      return chrec_dont_know;
339*e4b17023SJohn Marino 	  }
340*e4b17023SJohn Marino 	}
341*e4b17023SJohn Marino     }
342*e4b17023SJohn Marino }
343*e4b17023SJohn Marino 
344*e4b17023SJohn Marino /* Fold the addition of two chrecs.  */
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino tree
chrec_fold_plus(tree type,tree op0,tree op1)347*e4b17023SJohn Marino chrec_fold_plus (tree type,
348*e4b17023SJohn Marino 		 tree op0,
349*e4b17023SJohn Marino 		 tree op1)
350*e4b17023SJohn Marino {
351*e4b17023SJohn Marino   enum tree_code code;
352*e4b17023SJohn Marino   if (automatically_generated_chrec_p (op0)
353*e4b17023SJohn Marino       || automatically_generated_chrec_p (op1))
354*e4b17023SJohn Marino     return chrec_fold_automatically_generated_operands (op0, op1);
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino   if (integer_zerop (op0))
357*e4b17023SJohn Marino     return chrec_convert (type, op1, NULL);
358*e4b17023SJohn Marino   if (integer_zerop (op1))
359*e4b17023SJohn Marino     return chrec_convert (type, op0, NULL);
360*e4b17023SJohn Marino 
361*e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
362*e4b17023SJohn Marino     code = POINTER_PLUS_EXPR;
363*e4b17023SJohn Marino   else
364*e4b17023SJohn Marino     code = PLUS_EXPR;
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino   return chrec_fold_plus_1 (code, type, op0, op1);
367*e4b17023SJohn Marino }
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino /* Fold the subtraction of two chrecs.  */
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino tree
chrec_fold_minus(tree type,tree op0,tree op1)372*e4b17023SJohn Marino chrec_fold_minus (tree type,
373*e4b17023SJohn Marino 		  tree op0,
374*e4b17023SJohn Marino 		  tree op1)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino   if (automatically_generated_chrec_p (op0)
377*e4b17023SJohn Marino       || automatically_generated_chrec_p (op1))
378*e4b17023SJohn Marino     return chrec_fold_automatically_generated_operands (op0, op1);
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino   if (integer_zerop (op1))
381*e4b17023SJohn Marino     return op0;
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino   return chrec_fold_plus_1 (MINUS_EXPR, type, op0, op1);
384*e4b17023SJohn Marino }
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino /* Fold the multiplication of two chrecs.  */
387*e4b17023SJohn Marino 
388*e4b17023SJohn Marino tree
chrec_fold_multiply(tree type,tree op0,tree op1)389*e4b17023SJohn Marino chrec_fold_multiply (tree type,
390*e4b17023SJohn Marino 		     tree op0,
391*e4b17023SJohn Marino 		     tree op1)
392*e4b17023SJohn Marino {
393*e4b17023SJohn Marino   if (automatically_generated_chrec_p (op0)
394*e4b17023SJohn Marino       || automatically_generated_chrec_p (op1))
395*e4b17023SJohn Marino     return chrec_fold_automatically_generated_operands (op0, op1);
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino   switch (TREE_CODE (op0))
398*e4b17023SJohn Marino     {
399*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
400*e4b17023SJohn Marino       switch (TREE_CODE (op1))
401*e4b17023SJohn Marino 	{
402*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
403*e4b17023SJohn Marino 	  return chrec_fold_multiply_poly_poly (type, op0, op1);
404*e4b17023SJohn Marino 
405*e4b17023SJohn Marino 	CASE_CONVERT:
406*e4b17023SJohn Marino 	  if (tree_contains_chrecs (op1, NULL))
407*e4b17023SJohn Marino 	    return chrec_dont_know;
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino 	default:
410*e4b17023SJohn Marino 	  if (integer_onep (op1))
411*e4b17023SJohn Marino 	    return op0;
412*e4b17023SJohn Marino 	  if (integer_zerop (op1))
413*e4b17023SJohn Marino 	    return build_int_cst (type, 0);
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino 	  return build_polynomial_chrec
416*e4b17023SJohn Marino 	    (CHREC_VARIABLE (op0),
417*e4b17023SJohn Marino 	     chrec_fold_multiply (type, CHREC_LEFT (op0), op1),
418*e4b17023SJohn Marino 	     chrec_fold_multiply (type, CHREC_RIGHT (op0), op1));
419*e4b17023SJohn Marino 	}
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino     CASE_CONVERT:
422*e4b17023SJohn Marino       if (tree_contains_chrecs (op0, NULL))
423*e4b17023SJohn Marino 	return chrec_dont_know;
424*e4b17023SJohn Marino 
425*e4b17023SJohn Marino     default:
426*e4b17023SJohn Marino       if (integer_onep (op0))
427*e4b17023SJohn Marino 	return op1;
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino       if (integer_zerop (op0))
430*e4b17023SJohn Marino     	return build_int_cst (type, 0);
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino       switch (TREE_CODE (op1))
433*e4b17023SJohn Marino 	{
434*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
435*e4b17023SJohn Marino 	  return build_polynomial_chrec
436*e4b17023SJohn Marino 	    (CHREC_VARIABLE (op1),
437*e4b17023SJohn Marino 	     chrec_fold_multiply (type, CHREC_LEFT (op1), op0),
438*e4b17023SJohn Marino 	     chrec_fold_multiply (type, CHREC_RIGHT (op1), op0));
439*e4b17023SJohn Marino 
440*e4b17023SJohn Marino 	CASE_CONVERT:
441*e4b17023SJohn Marino 	  if (tree_contains_chrecs (op1, NULL))
442*e4b17023SJohn Marino 	    return chrec_dont_know;
443*e4b17023SJohn Marino 
444*e4b17023SJohn Marino 	default:
445*e4b17023SJohn Marino 	  if (integer_onep (op1))
446*e4b17023SJohn Marino 	    return op0;
447*e4b17023SJohn Marino 	  if (integer_zerop (op1))
448*e4b17023SJohn Marino 	    return build_int_cst (type, 0);
449*e4b17023SJohn Marino 	  return fold_build2 (MULT_EXPR, type, op0, op1);
450*e4b17023SJohn Marino 	}
451*e4b17023SJohn Marino     }
452*e4b17023SJohn Marino }
453*e4b17023SJohn Marino 
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino /* Operations.  */
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino /* Evaluate the binomial coefficient.  Return NULL_TREE if the intermediate
459*e4b17023SJohn Marino    calculation overflows, otherwise return C(n,k) with type TYPE.  */
460*e4b17023SJohn Marino 
461*e4b17023SJohn Marino static tree
tree_fold_binomial(tree type,tree n,unsigned int k)462*e4b17023SJohn Marino tree_fold_binomial (tree type, tree n, unsigned int k)
463*e4b17023SJohn Marino {
464*e4b17023SJohn Marino   unsigned HOST_WIDE_INT lidx, lnum, ldenom, lres, ldum;
465*e4b17023SJohn Marino   HOST_WIDE_INT hidx, hnum, hdenom, hres, hdum;
466*e4b17023SJohn Marino   unsigned int i;
467*e4b17023SJohn Marino   tree res;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino   /* Handle the most frequent cases.  */
470*e4b17023SJohn Marino   if (k == 0)
471*e4b17023SJohn Marino     return build_int_cst (type, 1);
472*e4b17023SJohn Marino   if (k == 1)
473*e4b17023SJohn Marino     return fold_convert (type, n);
474*e4b17023SJohn Marino 
475*e4b17023SJohn Marino   /* Check that k <= n.  */
476*e4b17023SJohn Marino   if (TREE_INT_CST_HIGH (n) == 0
477*e4b17023SJohn Marino       && TREE_INT_CST_LOW (n) < k)
478*e4b17023SJohn Marino     return NULL_TREE;
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino   /* Numerator = n.  */
481*e4b17023SJohn Marino   lnum = TREE_INT_CST_LOW (n);
482*e4b17023SJohn Marino   hnum = TREE_INT_CST_HIGH (n);
483*e4b17023SJohn Marino 
484*e4b17023SJohn Marino   /* Denominator = 2.  */
485*e4b17023SJohn Marino   ldenom = 2;
486*e4b17023SJohn Marino   hdenom = 0;
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino   /* Index = Numerator-1.  */
489*e4b17023SJohn Marino   if (lnum == 0)
490*e4b17023SJohn Marino     {
491*e4b17023SJohn Marino       hidx = hnum - 1;
492*e4b17023SJohn Marino       lidx = ~ (unsigned HOST_WIDE_INT) 0;
493*e4b17023SJohn Marino     }
494*e4b17023SJohn Marino   else
495*e4b17023SJohn Marino     {
496*e4b17023SJohn Marino       hidx = hnum;
497*e4b17023SJohn Marino       lidx = lnum - 1;
498*e4b17023SJohn Marino     }
499*e4b17023SJohn Marino 
500*e4b17023SJohn Marino   /* Numerator = Numerator*Index = n*(n-1).  */
501*e4b17023SJohn Marino   if (mul_double (lnum, hnum, lidx, hidx, &lnum, &hnum))
502*e4b17023SJohn Marino     return NULL_TREE;
503*e4b17023SJohn Marino 
504*e4b17023SJohn Marino   for (i = 3; i <= k; i++)
505*e4b17023SJohn Marino     {
506*e4b17023SJohn Marino       /* Index--.  */
507*e4b17023SJohn Marino       if (lidx == 0)
508*e4b17023SJohn Marino 	{
509*e4b17023SJohn Marino 	  hidx--;
510*e4b17023SJohn Marino 	  lidx = ~ (unsigned HOST_WIDE_INT) 0;
511*e4b17023SJohn Marino 	}
512*e4b17023SJohn Marino       else
513*e4b17023SJohn Marino         lidx--;
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino       /* Numerator *= Index.  */
516*e4b17023SJohn Marino       if (mul_double (lnum, hnum, lidx, hidx, &lnum, &hnum))
517*e4b17023SJohn Marino 	return NULL_TREE;
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino       /* Denominator *= i.  */
520*e4b17023SJohn Marino       mul_double (ldenom, hdenom, i, 0, &ldenom, &hdenom);
521*e4b17023SJohn Marino     }
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino   /* Result = Numerator / Denominator.  */
524*e4b17023SJohn Marino   div_and_round_double (EXACT_DIV_EXPR, 1, lnum, hnum, ldenom, hdenom,
525*e4b17023SJohn Marino 			&lres, &hres, &ldum, &hdum);
526*e4b17023SJohn Marino 
527*e4b17023SJohn Marino   res = build_int_cst_wide (type, lres, hres);
528*e4b17023SJohn Marino   return int_fits_type_p (res, type) ? res : NULL_TREE;
529*e4b17023SJohn Marino }
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino /* Helper function.  Use the Newton's interpolating formula for
532*e4b17023SJohn Marino    evaluating the value of the evolution function.  */
533*e4b17023SJohn Marino 
534*e4b17023SJohn Marino static tree
chrec_evaluate(unsigned var,tree chrec,tree n,unsigned int k)535*e4b17023SJohn Marino chrec_evaluate (unsigned var, tree chrec, tree n, unsigned int k)
536*e4b17023SJohn Marino {
537*e4b17023SJohn Marino   tree arg0, arg1, binomial_n_k;
538*e4b17023SJohn Marino   tree type = TREE_TYPE (chrec);
539*e4b17023SJohn Marino   struct loop *var_loop = get_loop (var);
540*e4b17023SJohn Marino 
541*e4b17023SJohn Marino   while (TREE_CODE (chrec) == POLYNOMIAL_CHREC
542*e4b17023SJohn Marino 	 && flow_loop_nested_p (var_loop, get_chrec_loop (chrec)))
543*e4b17023SJohn Marino     chrec = CHREC_LEFT (chrec);
544*e4b17023SJohn Marino 
545*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
546*e4b17023SJohn Marino       && CHREC_VARIABLE (chrec) == var)
547*e4b17023SJohn Marino     {
548*e4b17023SJohn Marino       arg1 = chrec_evaluate (var, CHREC_RIGHT (chrec), n, k + 1);
549*e4b17023SJohn Marino       if (arg1 == chrec_dont_know)
550*e4b17023SJohn Marino 	return chrec_dont_know;
551*e4b17023SJohn Marino       binomial_n_k = tree_fold_binomial (type, n, k);
552*e4b17023SJohn Marino       if (!binomial_n_k)
553*e4b17023SJohn Marino 	return chrec_dont_know;
554*e4b17023SJohn Marino       arg0 = fold_build2 (MULT_EXPR, type,
555*e4b17023SJohn Marino 			  CHREC_LEFT (chrec), binomial_n_k);
556*e4b17023SJohn Marino       return chrec_fold_plus (type, arg0, arg1);
557*e4b17023SJohn Marino     }
558*e4b17023SJohn Marino 
559*e4b17023SJohn Marino   binomial_n_k = tree_fold_binomial (type, n, k);
560*e4b17023SJohn Marino   if (!binomial_n_k)
561*e4b17023SJohn Marino     return chrec_dont_know;
562*e4b17023SJohn Marino 
563*e4b17023SJohn Marino   return fold_build2 (MULT_EXPR, type, chrec, binomial_n_k);
564*e4b17023SJohn Marino }
565*e4b17023SJohn Marino 
566*e4b17023SJohn Marino /* Evaluates "CHREC (X)" when the varying variable is VAR.
567*e4b17023SJohn Marino    Example:  Given the following parameters,
568*e4b17023SJohn Marino 
569*e4b17023SJohn Marino    var = 1
570*e4b17023SJohn Marino    chrec = {3, +, 4}_1
571*e4b17023SJohn Marino    x = 10
572*e4b17023SJohn Marino 
573*e4b17023SJohn Marino    The result is given by the Newton's interpolating formula:
574*e4b17023SJohn Marino    3 * \binom{10}{0} + 4 * \binom{10}{1}.
575*e4b17023SJohn Marino */
576*e4b17023SJohn Marino 
577*e4b17023SJohn Marino tree
chrec_apply(unsigned var,tree chrec,tree x)578*e4b17023SJohn Marino chrec_apply (unsigned var,
579*e4b17023SJohn Marino 	     tree chrec,
580*e4b17023SJohn Marino 	     tree x)
581*e4b17023SJohn Marino {
582*e4b17023SJohn Marino   tree type = chrec_type (chrec);
583*e4b17023SJohn Marino   tree res = chrec_dont_know;
584*e4b17023SJohn Marino 
585*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec)
586*e4b17023SJohn Marino       || automatically_generated_chrec_p (x)
587*e4b17023SJohn Marino 
588*e4b17023SJohn Marino       /* When the symbols are defined in an outer loop, it is possible
589*e4b17023SJohn Marino 	 to symbolically compute the apply, since the symbols are
590*e4b17023SJohn Marino 	 constants with respect to the varying loop.  */
591*e4b17023SJohn Marino       || chrec_contains_symbols_defined_in_loop (chrec, var))
592*e4b17023SJohn Marino     return chrec_dont_know;
593*e4b17023SJohn Marino 
594*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_SCEV))
595*e4b17023SJohn Marino     fprintf (dump_file, "(chrec_apply \n");
596*e4b17023SJohn Marino 
597*e4b17023SJohn Marino   if (TREE_CODE (x) == INTEGER_CST && SCALAR_FLOAT_TYPE_P (type))
598*e4b17023SJohn Marino     x = build_real_from_int_cst (type, x);
599*e4b17023SJohn Marino 
600*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
601*e4b17023SJohn Marino     {
602*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
603*e4b17023SJohn Marino       if (evolution_function_is_affine_p (chrec))
604*e4b17023SJohn Marino 	{
605*e4b17023SJohn Marino 	  if (CHREC_VARIABLE (chrec) != var)
606*e4b17023SJohn Marino 	    return build_polynomial_chrec
607*e4b17023SJohn Marino 	      (CHREC_VARIABLE (chrec),
608*e4b17023SJohn Marino 	       chrec_apply (var, CHREC_LEFT (chrec), x),
609*e4b17023SJohn Marino 	       chrec_apply (var, CHREC_RIGHT (chrec), x));
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino 	  /* "{a, +, b} (x)"  ->  "a + b*x".  */
612*e4b17023SJohn Marino 	  x = chrec_convert_rhs (type, x, NULL);
613*e4b17023SJohn Marino 	  res = chrec_fold_multiply (TREE_TYPE (x), CHREC_RIGHT (chrec), x);
614*e4b17023SJohn Marino 	  res = chrec_fold_plus (type, CHREC_LEFT (chrec), res);
615*e4b17023SJohn Marino 	}
616*e4b17023SJohn Marino       else if (TREE_CODE (x) == INTEGER_CST
617*e4b17023SJohn Marino 	       && tree_int_cst_sgn (x) == 1)
618*e4b17023SJohn Marino 	/* testsuite/.../ssa-chrec-38.c.  */
619*e4b17023SJohn Marino 	res = chrec_evaluate (var, chrec, x, 0);
620*e4b17023SJohn Marino       else
621*e4b17023SJohn Marino 	res = chrec_dont_know;
622*e4b17023SJohn Marino       break;
623*e4b17023SJohn Marino 
624*e4b17023SJohn Marino     CASE_CONVERT:
625*e4b17023SJohn Marino       res = chrec_convert (TREE_TYPE (chrec),
626*e4b17023SJohn Marino 			   chrec_apply (var, TREE_OPERAND (chrec, 0), x),
627*e4b17023SJohn Marino 			   NULL);
628*e4b17023SJohn Marino       break;
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino     default:
631*e4b17023SJohn Marino       res = chrec;
632*e4b17023SJohn Marino       break;
633*e4b17023SJohn Marino     }
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_SCEV))
636*e4b17023SJohn Marino     {
637*e4b17023SJohn Marino       fprintf (dump_file, "  (varying_loop = %d\n", var);
638*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (chrec = ");
639*e4b17023SJohn Marino       print_generic_expr (dump_file, chrec, 0);
640*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (x = ");
641*e4b17023SJohn Marino       print_generic_expr (dump_file, x, 0);
642*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (res = ");
643*e4b17023SJohn Marino       print_generic_expr (dump_file, res, 0);
644*e4b17023SJohn Marino       fprintf (dump_file, "))\n");
645*e4b17023SJohn Marino     }
646*e4b17023SJohn Marino 
647*e4b17023SJohn Marino   return res;
648*e4b17023SJohn Marino }
649*e4b17023SJohn Marino 
650*e4b17023SJohn Marino /* For a given CHREC and an induction variable map IV_MAP that maps
651*e4b17023SJohn Marino    (loop->num, expr) for every loop number of the current_loops an
652*e4b17023SJohn Marino    expression, calls chrec_apply when the expression is not NULL.  */
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino tree
chrec_apply_map(tree chrec,VEC (tree,heap)* iv_map)655*e4b17023SJohn Marino chrec_apply_map (tree chrec, VEC (tree, heap) *iv_map)
656*e4b17023SJohn Marino {
657*e4b17023SJohn Marino   int i;
658*e4b17023SJohn Marino   tree expr;
659*e4b17023SJohn Marino 
660*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, iv_map, i, expr)
661*e4b17023SJohn Marino     if (expr)
662*e4b17023SJohn Marino       chrec = chrec_apply (i, chrec, expr);
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino   return chrec;
665*e4b17023SJohn Marino }
666*e4b17023SJohn Marino 
667*e4b17023SJohn Marino /* Replaces the initial condition in CHREC with INIT_COND.  */
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino tree
chrec_replace_initial_condition(tree chrec,tree init_cond)670*e4b17023SJohn Marino chrec_replace_initial_condition (tree chrec,
671*e4b17023SJohn Marino 				 tree init_cond)
672*e4b17023SJohn Marino {
673*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
674*e4b17023SJohn Marino     return chrec;
675*e4b17023SJohn Marino 
676*e4b17023SJohn Marino   gcc_assert (chrec_type (chrec) == chrec_type (init_cond));
677*e4b17023SJohn Marino 
678*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
679*e4b17023SJohn Marino     {
680*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
681*e4b17023SJohn Marino       return build_polynomial_chrec
682*e4b17023SJohn Marino 	(CHREC_VARIABLE (chrec),
683*e4b17023SJohn Marino 	 chrec_replace_initial_condition (CHREC_LEFT (chrec), init_cond),
684*e4b17023SJohn Marino 	 CHREC_RIGHT (chrec));
685*e4b17023SJohn Marino 
686*e4b17023SJohn Marino     default:
687*e4b17023SJohn Marino       return init_cond;
688*e4b17023SJohn Marino     }
689*e4b17023SJohn Marino }
690*e4b17023SJohn Marino 
691*e4b17023SJohn Marino /* Returns the initial condition of a given CHREC.  */
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino tree
initial_condition(tree chrec)694*e4b17023SJohn Marino initial_condition (tree chrec)
695*e4b17023SJohn Marino {
696*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
697*e4b17023SJohn Marino     return chrec;
698*e4b17023SJohn Marino 
699*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
700*e4b17023SJohn Marino     return initial_condition (CHREC_LEFT (chrec));
701*e4b17023SJohn Marino   else
702*e4b17023SJohn Marino     return chrec;
703*e4b17023SJohn Marino }
704*e4b17023SJohn Marino 
705*e4b17023SJohn Marino /* Returns a univariate function that represents the evolution in
706*e4b17023SJohn Marino    LOOP_NUM.  Mask the evolution of any other loop.  */
707*e4b17023SJohn Marino 
708*e4b17023SJohn Marino tree
hide_evolution_in_other_loops_than_loop(tree chrec,unsigned loop_num)709*e4b17023SJohn Marino hide_evolution_in_other_loops_than_loop (tree chrec,
710*e4b17023SJohn Marino 					 unsigned loop_num)
711*e4b17023SJohn Marino {
712*e4b17023SJohn Marino   struct loop *loop = get_loop (loop_num), *chloop;
713*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
714*e4b17023SJohn Marino     return chrec;
715*e4b17023SJohn Marino 
716*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
717*e4b17023SJohn Marino     {
718*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
719*e4b17023SJohn Marino       chloop = get_chrec_loop (chrec);
720*e4b17023SJohn Marino 
721*e4b17023SJohn Marino       if (chloop == loop)
722*e4b17023SJohn Marino 	return build_polynomial_chrec
723*e4b17023SJohn Marino 	  (loop_num,
724*e4b17023SJohn Marino 	   hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec),
725*e4b17023SJohn Marino 						    loop_num),
726*e4b17023SJohn Marino 	   CHREC_RIGHT (chrec));
727*e4b17023SJohn Marino 
728*e4b17023SJohn Marino       else if (flow_loop_nested_p (chloop, loop))
729*e4b17023SJohn Marino 	/* There is no evolution in this loop.  */
730*e4b17023SJohn Marino 	return initial_condition (chrec);
731*e4b17023SJohn Marino 
732*e4b17023SJohn Marino       else
733*e4b17023SJohn Marino 	{
734*e4b17023SJohn Marino 	  gcc_assert (flow_loop_nested_p (loop, chloop));
735*e4b17023SJohn Marino 	  return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec),
736*e4b17023SJohn Marino 							  loop_num);
737*e4b17023SJohn Marino 	}
738*e4b17023SJohn Marino 
739*e4b17023SJohn Marino     default:
740*e4b17023SJohn Marino       return chrec;
741*e4b17023SJohn Marino     }
742*e4b17023SJohn Marino }
743*e4b17023SJohn Marino 
744*e4b17023SJohn Marino /* Returns the evolution part of CHREC in LOOP_NUM when RIGHT is
745*e4b17023SJohn Marino    true, otherwise returns the initial condition in LOOP_NUM.  */
746*e4b17023SJohn Marino 
747*e4b17023SJohn Marino static tree
chrec_component_in_loop_num(tree chrec,unsigned loop_num,bool right)748*e4b17023SJohn Marino chrec_component_in_loop_num (tree chrec,
749*e4b17023SJohn Marino 			     unsigned loop_num,
750*e4b17023SJohn Marino 			     bool right)
751*e4b17023SJohn Marino {
752*e4b17023SJohn Marino   tree component;
753*e4b17023SJohn Marino   struct loop *loop = get_loop (loop_num), *chloop;
754*e4b17023SJohn Marino 
755*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
756*e4b17023SJohn Marino     return chrec;
757*e4b17023SJohn Marino 
758*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
759*e4b17023SJohn Marino     {
760*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
761*e4b17023SJohn Marino       chloop = get_chrec_loop (chrec);
762*e4b17023SJohn Marino 
763*e4b17023SJohn Marino       if (chloop == loop)
764*e4b17023SJohn Marino 	{
765*e4b17023SJohn Marino 	  if (right)
766*e4b17023SJohn Marino 	    component = CHREC_RIGHT (chrec);
767*e4b17023SJohn Marino 	  else
768*e4b17023SJohn Marino 	    component = CHREC_LEFT (chrec);
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino 	  if (TREE_CODE (CHREC_LEFT (chrec)) != POLYNOMIAL_CHREC
771*e4b17023SJohn Marino 	      || CHREC_VARIABLE (CHREC_LEFT (chrec)) != CHREC_VARIABLE (chrec))
772*e4b17023SJohn Marino 	    return component;
773*e4b17023SJohn Marino 
774*e4b17023SJohn Marino 	  else
775*e4b17023SJohn Marino 	    return build_polynomial_chrec
776*e4b17023SJohn Marino 	      (loop_num,
777*e4b17023SJohn Marino 	       chrec_component_in_loop_num (CHREC_LEFT (chrec),
778*e4b17023SJohn Marino 					    loop_num,
779*e4b17023SJohn Marino 					    right),
780*e4b17023SJohn Marino 	       component);
781*e4b17023SJohn Marino 	}
782*e4b17023SJohn Marino 
783*e4b17023SJohn Marino       else if (flow_loop_nested_p (chloop, loop))
784*e4b17023SJohn Marino 	/* There is no evolution part in this loop.  */
785*e4b17023SJohn Marino 	return NULL_TREE;
786*e4b17023SJohn Marino 
787*e4b17023SJohn Marino       else
788*e4b17023SJohn Marino 	{
789*e4b17023SJohn Marino 	  gcc_assert (flow_loop_nested_p (loop, chloop));
790*e4b17023SJohn Marino 	  return chrec_component_in_loop_num (CHREC_LEFT (chrec),
791*e4b17023SJohn Marino 					      loop_num,
792*e4b17023SJohn Marino 					      right);
793*e4b17023SJohn Marino 	}
794*e4b17023SJohn Marino 
795*e4b17023SJohn Marino      default:
796*e4b17023SJohn Marino       if (right)
797*e4b17023SJohn Marino 	return NULL_TREE;
798*e4b17023SJohn Marino       else
799*e4b17023SJohn Marino 	return chrec;
800*e4b17023SJohn Marino     }
801*e4b17023SJohn Marino }
802*e4b17023SJohn Marino 
803*e4b17023SJohn Marino /* Returns the evolution part in LOOP_NUM.  Example: the call
804*e4b17023SJohn Marino    evolution_part_in_loop_num ({{0, +, 1}_1, +, 2}_1, 1) returns
805*e4b17023SJohn Marino    {1, +, 2}_1  */
806*e4b17023SJohn Marino 
807*e4b17023SJohn Marino tree
evolution_part_in_loop_num(tree chrec,unsigned loop_num)808*e4b17023SJohn Marino evolution_part_in_loop_num (tree chrec,
809*e4b17023SJohn Marino 			    unsigned loop_num)
810*e4b17023SJohn Marino {
811*e4b17023SJohn Marino   return chrec_component_in_loop_num (chrec, loop_num, true);
812*e4b17023SJohn Marino }
813*e4b17023SJohn Marino 
814*e4b17023SJohn Marino /* Returns the initial condition in LOOP_NUM.  Example: the call
815*e4b17023SJohn Marino    initial_condition_in_loop_num ({{0, +, 1}_1, +, 2}_2, 2) returns
816*e4b17023SJohn Marino    {0, +, 1}_1  */
817*e4b17023SJohn Marino 
818*e4b17023SJohn Marino tree
initial_condition_in_loop_num(tree chrec,unsigned loop_num)819*e4b17023SJohn Marino initial_condition_in_loop_num (tree chrec,
820*e4b17023SJohn Marino 			       unsigned loop_num)
821*e4b17023SJohn Marino {
822*e4b17023SJohn Marino   return chrec_component_in_loop_num (chrec, loop_num, false);
823*e4b17023SJohn Marino }
824*e4b17023SJohn Marino 
825*e4b17023SJohn Marino /* Set or reset the evolution of CHREC to NEW_EVOL in loop LOOP_NUM.
826*e4b17023SJohn Marino    This function is essentially used for setting the evolution to
827*e4b17023SJohn Marino    chrec_dont_know, for example after having determined that it is
828*e4b17023SJohn Marino    impossible to say how many times a loop will execute.  */
829*e4b17023SJohn Marino 
830*e4b17023SJohn Marino tree
reset_evolution_in_loop(unsigned loop_num,tree chrec,tree new_evol)831*e4b17023SJohn Marino reset_evolution_in_loop (unsigned loop_num,
832*e4b17023SJohn Marino 			 tree chrec,
833*e4b17023SJohn Marino 			 tree new_evol)
834*e4b17023SJohn Marino {
835*e4b17023SJohn Marino   struct loop *loop = get_loop (loop_num);
836*e4b17023SJohn Marino 
837*e4b17023SJohn Marino   if (POINTER_TYPE_P (chrec_type (chrec)))
838*e4b17023SJohn Marino     gcc_assert (ptrofftype_p (chrec_type (new_evol)));
839*e4b17023SJohn Marino   else
840*e4b17023SJohn Marino     gcc_assert (chrec_type (chrec) == chrec_type (new_evol));
841*e4b17023SJohn Marino 
842*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
843*e4b17023SJohn Marino       && flow_loop_nested_p (loop, get_chrec_loop (chrec)))
844*e4b17023SJohn Marino     {
845*e4b17023SJohn Marino       tree left = reset_evolution_in_loop (loop_num, CHREC_LEFT (chrec),
846*e4b17023SJohn Marino 					   new_evol);
847*e4b17023SJohn Marino       tree right = reset_evolution_in_loop (loop_num, CHREC_RIGHT (chrec),
848*e4b17023SJohn Marino 					    new_evol);
849*e4b17023SJohn Marino       return build3 (POLYNOMIAL_CHREC, TREE_TYPE (left),
850*e4b17023SJohn Marino 		     CHREC_VAR (chrec), left, right);
851*e4b17023SJohn Marino     }
852*e4b17023SJohn Marino 
853*e4b17023SJohn Marino   while (TREE_CODE (chrec) == POLYNOMIAL_CHREC
854*e4b17023SJohn Marino 	 && CHREC_VARIABLE (chrec) == loop_num)
855*e4b17023SJohn Marino     chrec = CHREC_LEFT (chrec);
856*e4b17023SJohn Marino 
857*e4b17023SJohn Marino   return build_polynomial_chrec (loop_num, chrec, new_evol);
858*e4b17023SJohn Marino }
859*e4b17023SJohn Marino 
860*e4b17023SJohn Marino /* Merges two evolution functions that were found by following two
861*e4b17023SJohn Marino    alternate paths of a conditional expression.  */
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino tree
chrec_merge(tree chrec1,tree chrec2)864*e4b17023SJohn Marino chrec_merge (tree chrec1,
865*e4b17023SJohn Marino 	     tree chrec2)
866*e4b17023SJohn Marino {
867*e4b17023SJohn Marino   if (chrec1 == chrec_dont_know
868*e4b17023SJohn Marino       || chrec2 == chrec_dont_know)
869*e4b17023SJohn Marino     return chrec_dont_know;
870*e4b17023SJohn Marino 
871*e4b17023SJohn Marino   if (chrec1 == chrec_known
872*e4b17023SJohn Marino       || chrec2 == chrec_known)
873*e4b17023SJohn Marino     return chrec_known;
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino   if (chrec1 == chrec_not_analyzed_yet)
876*e4b17023SJohn Marino     return chrec2;
877*e4b17023SJohn Marino   if (chrec2 == chrec_not_analyzed_yet)
878*e4b17023SJohn Marino     return chrec1;
879*e4b17023SJohn Marino 
880*e4b17023SJohn Marino   if (eq_evolutions_p (chrec1, chrec2))
881*e4b17023SJohn Marino     return chrec1;
882*e4b17023SJohn Marino 
883*e4b17023SJohn Marino   return chrec_dont_know;
884*e4b17023SJohn Marino }
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino 
887*e4b17023SJohn Marino 
888*e4b17023SJohn Marino /* Observers.  */
889*e4b17023SJohn Marino 
890*e4b17023SJohn Marino /* Helper function for is_multivariate_chrec.  */
891*e4b17023SJohn Marino 
892*e4b17023SJohn Marino static bool
is_multivariate_chrec_rec(const_tree chrec,unsigned int rec_var)893*e4b17023SJohn Marino is_multivariate_chrec_rec (const_tree chrec, unsigned int rec_var)
894*e4b17023SJohn Marino {
895*e4b17023SJohn Marino   if (chrec == NULL_TREE)
896*e4b17023SJohn Marino     return false;
897*e4b17023SJohn Marino 
898*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
899*e4b17023SJohn Marino     {
900*e4b17023SJohn Marino       if (CHREC_VARIABLE (chrec) != rec_var)
901*e4b17023SJohn Marino 	return true;
902*e4b17023SJohn Marino       else
903*e4b17023SJohn Marino 	return (is_multivariate_chrec_rec (CHREC_LEFT (chrec), rec_var)
904*e4b17023SJohn Marino 		|| is_multivariate_chrec_rec (CHREC_RIGHT (chrec), rec_var));
905*e4b17023SJohn Marino     }
906*e4b17023SJohn Marino   else
907*e4b17023SJohn Marino     return false;
908*e4b17023SJohn Marino }
909*e4b17023SJohn Marino 
910*e4b17023SJohn Marino /* Determine whether the given chrec is multivariate or not.  */
911*e4b17023SJohn Marino 
912*e4b17023SJohn Marino bool
is_multivariate_chrec(const_tree chrec)913*e4b17023SJohn Marino is_multivariate_chrec (const_tree chrec)
914*e4b17023SJohn Marino {
915*e4b17023SJohn Marino   if (chrec == NULL_TREE)
916*e4b17023SJohn Marino     return false;
917*e4b17023SJohn Marino 
918*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
919*e4b17023SJohn Marino     return (is_multivariate_chrec_rec (CHREC_LEFT (chrec),
920*e4b17023SJohn Marino 				       CHREC_VARIABLE (chrec))
921*e4b17023SJohn Marino 	    || is_multivariate_chrec_rec (CHREC_RIGHT (chrec),
922*e4b17023SJohn Marino 					  CHREC_VARIABLE (chrec)));
923*e4b17023SJohn Marino   else
924*e4b17023SJohn Marino     return false;
925*e4b17023SJohn Marino }
926*e4b17023SJohn Marino 
927*e4b17023SJohn Marino /* Determines whether the chrec contains symbolic names or not.  */
928*e4b17023SJohn Marino 
929*e4b17023SJohn Marino bool
chrec_contains_symbols(const_tree chrec)930*e4b17023SJohn Marino chrec_contains_symbols (const_tree chrec)
931*e4b17023SJohn Marino {
932*e4b17023SJohn Marino   int i, n;
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino   if (chrec == NULL_TREE)
935*e4b17023SJohn Marino     return false;
936*e4b17023SJohn Marino 
937*e4b17023SJohn Marino   if (TREE_CODE (chrec) == SSA_NAME
938*e4b17023SJohn Marino       || TREE_CODE (chrec) == VAR_DECL
939*e4b17023SJohn Marino       || TREE_CODE (chrec) == PARM_DECL
940*e4b17023SJohn Marino       || TREE_CODE (chrec) == FUNCTION_DECL
941*e4b17023SJohn Marino       || TREE_CODE (chrec) == LABEL_DECL
942*e4b17023SJohn Marino       || TREE_CODE (chrec) == RESULT_DECL
943*e4b17023SJohn Marino       || TREE_CODE (chrec) == FIELD_DECL)
944*e4b17023SJohn Marino     return true;
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino   n = TREE_OPERAND_LENGTH (chrec);
947*e4b17023SJohn Marino   for (i = 0; i < n; i++)
948*e4b17023SJohn Marino     if (chrec_contains_symbols (TREE_OPERAND (chrec, i)))
949*e4b17023SJohn Marino       return true;
950*e4b17023SJohn Marino   return false;
951*e4b17023SJohn Marino }
952*e4b17023SJohn Marino 
953*e4b17023SJohn Marino /* Determines whether the chrec contains undetermined coefficients.  */
954*e4b17023SJohn Marino 
955*e4b17023SJohn Marino bool
chrec_contains_undetermined(const_tree chrec)956*e4b17023SJohn Marino chrec_contains_undetermined (const_tree chrec)
957*e4b17023SJohn Marino {
958*e4b17023SJohn Marino   int i, n;
959*e4b17023SJohn Marino 
960*e4b17023SJohn Marino   if (chrec == chrec_dont_know)
961*e4b17023SJohn Marino     return true;
962*e4b17023SJohn Marino 
963*e4b17023SJohn Marino   if (chrec == NULL_TREE)
964*e4b17023SJohn Marino     return false;
965*e4b17023SJohn Marino 
966*e4b17023SJohn Marino   n = TREE_OPERAND_LENGTH (chrec);
967*e4b17023SJohn Marino   for (i = 0; i < n; i++)
968*e4b17023SJohn Marino     if (chrec_contains_undetermined (TREE_OPERAND (chrec, i)))
969*e4b17023SJohn Marino       return true;
970*e4b17023SJohn Marino   return false;
971*e4b17023SJohn Marino }
972*e4b17023SJohn Marino 
973*e4b17023SJohn Marino /* Determines whether the tree EXPR contains chrecs, and increment
974*e4b17023SJohn Marino    SIZE if it is not a NULL pointer by an estimation of the depth of
975*e4b17023SJohn Marino    the tree.  */
976*e4b17023SJohn Marino 
977*e4b17023SJohn Marino bool
tree_contains_chrecs(const_tree expr,int * size)978*e4b17023SJohn Marino tree_contains_chrecs (const_tree expr, int *size)
979*e4b17023SJohn Marino {
980*e4b17023SJohn Marino   int i, n;
981*e4b17023SJohn Marino 
982*e4b17023SJohn Marino   if (expr == NULL_TREE)
983*e4b17023SJohn Marino     return false;
984*e4b17023SJohn Marino 
985*e4b17023SJohn Marino   if (size)
986*e4b17023SJohn Marino     (*size)++;
987*e4b17023SJohn Marino 
988*e4b17023SJohn Marino   if (tree_is_chrec (expr))
989*e4b17023SJohn Marino     return true;
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino   n = TREE_OPERAND_LENGTH (expr);
992*e4b17023SJohn Marino   for (i = 0; i < n; i++)
993*e4b17023SJohn Marino     if (tree_contains_chrecs (TREE_OPERAND (expr, i), size))
994*e4b17023SJohn Marino       return true;
995*e4b17023SJohn Marino   return false;
996*e4b17023SJohn Marino }
997*e4b17023SJohn Marino 
998*e4b17023SJohn Marino /* Recursive helper function.  */
999*e4b17023SJohn Marino 
1000*e4b17023SJohn Marino static bool
evolution_function_is_invariant_rec_p(tree chrec,int loopnum)1001*e4b17023SJohn Marino evolution_function_is_invariant_rec_p (tree chrec, int loopnum)
1002*e4b17023SJohn Marino {
1003*e4b17023SJohn Marino   if (evolution_function_is_constant_p (chrec))
1004*e4b17023SJohn Marino     return true;
1005*e4b17023SJohn Marino 
1006*e4b17023SJohn Marino   if (TREE_CODE (chrec) == SSA_NAME
1007*e4b17023SJohn Marino       && (loopnum == 0
1008*e4b17023SJohn Marino 	  || expr_invariant_in_loop_p (get_loop (loopnum), chrec)))
1009*e4b17023SJohn Marino     return true;
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino   if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
1012*e4b17023SJohn Marino     {
1013*e4b17023SJohn Marino       if (CHREC_VARIABLE (chrec) == (unsigned) loopnum
1014*e4b17023SJohn Marino 	  || flow_loop_nested_p (get_loop (loopnum),
1015*e4b17023SJohn Marino 				 get_loop (CHREC_VARIABLE (chrec)))
1016*e4b17023SJohn Marino 	  || !evolution_function_is_invariant_rec_p (CHREC_RIGHT (chrec),
1017*e4b17023SJohn Marino 						     loopnum)
1018*e4b17023SJohn Marino 	  || !evolution_function_is_invariant_rec_p (CHREC_LEFT (chrec),
1019*e4b17023SJohn Marino 						     loopnum))
1020*e4b17023SJohn Marino 	return false;
1021*e4b17023SJohn Marino       return true;
1022*e4b17023SJohn Marino     }
1023*e4b17023SJohn Marino 
1024*e4b17023SJohn Marino   switch (TREE_OPERAND_LENGTH (chrec))
1025*e4b17023SJohn Marino     {
1026*e4b17023SJohn Marino     case 2:
1027*e4b17023SJohn Marino       if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 1),
1028*e4b17023SJohn Marino 						  loopnum))
1029*e4b17023SJohn Marino 	return false;
1030*e4b17023SJohn Marino 
1031*e4b17023SJohn Marino     case 1:
1032*e4b17023SJohn Marino       if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 0),
1033*e4b17023SJohn Marino 						  loopnum))
1034*e4b17023SJohn Marino 	return false;
1035*e4b17023SJohn Marino       return true;
1036*e4b17023SJohn Marino 
1037*e4b17023SJohn Marino     default:
1038*e4b17023SJohn Marino       return false;
1039*e4b17023SJohn Marino     }
1040*e4b17023SJohn Marino 
1041*e4b17023SJohn Marino   return false;
1042*e4b17023SJohn Marino }
1043*e4b17023SJohn Marino 
1044*e4b17023SJohn Marino /* Return true if CHREC is invariant in loop LOOPNUM, false otherwise. */
1045*e4b17023SJohn Marino 
1046*e4b17023SJohn Marino bool
evolution_function_is_invariant_p(tree chrec,int loopnum)1047*e4b17023SJohn Marino evolution_function_is_invariant_p (tree chrec, int loopnum)
1048*e4b17023SJohn Marino {
1049*e4b17023SJohn Marino   return evolution_function_is_invariant_rec_p (chrec, loopnum);
1050*e4b17023SJohn Marino }
1051*e4b17023SJohn Marino 
1052*e4b17023SJohn Marino /* Determine whether the given tree is an affine multivariate
1053*e4b17023SJohn Marino    evolution.  */
1054*e4b17023SJohn Marino 
1055*e4b17023SJohn Marino bool
evolution_function_is_affine_multivariate_p(const_tree chrec,int loopnum)1056*e4b17023SJohn Marino evolution_function_is_affine_multivariate_p (const_tree chrec, int loopnum)
1057*e4b17023SJohn Marino {
1058*e4b17023SJohn Marino   if (chrec == NULL_TREE)
1059*e4b17023SJohn Marino     return false;
1060*e4b17023SJohn Marino 
1061*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
1062*e4b17023SJohn Marino     {
1063*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1064*e4b17023SJohn Marino       if (evolution_function_is_invariant_rec_p (CHREC_LEFT (chrec), loopnum))
1065*e4b17023SJohn Marino 	{
1066*e4b17023SJohn Marino 	  if (evolution_function_is_invariant_rec_p (CHREC_RIGHT (chrec), loopnum))
1067*e4b17023SJohn Marino 	    return true;
1068*e4b17023SJohn Marino 	  else
1069*e4b17023SJohn Marino 	    {
1070*e4b17023SJohn Marino 	      if (TREE_CODE (CHREC_RIGHT (chrec)) == POLYNOMIAL_CHREC
1071*e4b17023SJohn Marino 		  && CHREC_VARIABLE (CHREC_RIGHT (chrec))
1072*e4b17023SJohn Marino 		     != CHREC_VARIABLE (chrec)
1073*e4b17023SJohn Marino 		  && evolution_function_is_affine_multivariate_p
1074*e4b17023SJohn Marino 		  (CHREC_RIGHT (chrec), loopnum))
1075*e4b17023SJohn Marino 		return true;
1076*e4b17023SJohn Marino 	      else
1077*e4b17023SJohn Marino 		return false;
1078*e4b17023SJohn Marino 	    }
1079*e4b17023SJohn Marino 	}
1080*e4b17023SJohn Marino       else
1081*e4b17023SJohn Marino 	{
1082*e4b17023SJohn Marino 	  if (evolution_function_is_invariant_rec_p (CHREC_RIGHT (chrec), loopnum)
1083*e4b17023SJohn Marino 	      && TREE_CODE (CHREC_LEFT (chrec)) == POLYNOMIAL_CHREC
1084*e4b17023SJohn Marino 	      && CHREC_VARIABLE (CHREC_LEFT (chrec)) != CHREC_VARIABLE (chrec)
1085*e4b17023SJohn Marino 	      && evolution_function_is_affine_multivariate_p
1086*e4b17023SJohn Marino 	      (CHREC_LEFT (chrec), loopnum))
1087*e4b17023SJohn Marino 	    return true;
1088*e4b17023SJohn Marino 	  else
1089*e4b17023SJohn Marino 	    return false;
1090*e4b17023SJohn Marino 	}
1091*e4b17023SJohn Marino 
1092*e4b17023SJohn Marino     default:
1093*e4b17023SJohn Marino       return false;
1094*e4b17023SJohn Marino     }
1095*e4b17023SJohn Marino }
1096*e4b17023SJohn Marino 
1097*e4b17023SJohn Marino /* Determine whether the given tree is a function in zero or one
1098*e4b17023SJohn Marino    variables.  */
1099*e4b17023SJohn Marino 
1100*e4b17023SJohn Marino bool
evolution_function_is_univariate_p(const_tree chrec)1101*e4b17023SJohn Marino evolution_function_is_univariate_p (const_tree chrec)
1102*e4b17023SJohn Marino {
1103*e4b17023SJohn Marino   if (chrec == NULL_TREE)
1104*e4b17023SJohn Marino     return true;
1105*e4b17023SJohn Marino 
1106*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
1107*e4b17023SJohn Marino     {
1108*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1109*e4b17023SJohn Marino       switch (TREE_CODE (CHREC_LEFT (chrec)))
1110*e4b17023SJohn Marino 	{
1111*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
1112*e4b17023SJohn Marino 	  if (CHREC_VARIABLE (chrec) != CHREC_VARIABLE (CHREC_LEFT (chrec)))
1113*e4b17023SJohn Marino 	    return false;
1114*e4b17023SJohn Marino 	  if (!evolution_function_is_univariate_p (CHREC_LEFT (chrec)))
1115*e4b17023SJohn Marino 	    return false;
1116*e4b17023SJohn Marino 	  break;
1117*e4b17023SJohn Marino 
1118*e4b17023SJohn Marino 	default:
1119*e4b17023SJohn Marino 	  if (tree_contains_chrecs (CHREC_LEFT (chrec), NULL))
1120*e4b17023SJohn Marino 	    return false;
1121*e4b17023SJohn Marino 	  break;
1122*e4b17023SJohn Marino 	}
1123*e4b17023SJohn Marino 
1124*e4b17023SJohn Marino       switch (TREE_CODE (CHREC_RIGHT (chrec)))
1125*e4b17023SJohn Marino 	{
1126*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
1127*e4b17023SJohn Marino 	  if (CHREC_VARIABLE (chrec) != CHREC_VARIABLE (CHREC_RIGHT (chrec)))
1128*e4b17023SJohn Marino 	    return false;
1129*e4b17023SJohn Marino 	  if (!evolution_function_is_univariate_p (CHREC_RIGHT (chrec)))
1130*e4b17023SJohn Marino 	    return false;
1131*e4b17023SJohn Marino 	  break;
1132*e4b17023SJohn Marino 
1133*e4b17023SJohn Marino 	default:
1134*e4b17023SJohn Marino 	  if (tree_contains_chrecs (CHREC_RIGHT (chrec), NULL))
1135*e4b17023SJohn Marino 	    return false;
1136*e4b17023SJohn Marino 	  break;
1137*e4b17023SJohn Marino 	}
1138*e4b17023SJohn Marino 
1139*e4b17023SJohn Marino     default:
1140*e4b17023SJohn Marino       return true;
1141*e4b17023SJohn Marino     }
1142*e4b17023SJohn Marino }
1143*e4b17023SJohn Marino 
1144*e4b17023SJohn Marino /* Returns the number of variables of CHREC.  Example: the call
1145*e4b17023SJohn Marino    nb_vars_in_chrec ({{0, +, 1}_5, +, 2}_6) returns 2.  */
1146*e4b17023SJohn Marino 
1147*e4b17023SJohn Marino unsigned
nb_vars_in_chrec(tree chrec)1148*e4b17023SJohn Marino nb_vars_in_chrec (tree chrec)
1149*e4b17023SJohn Marino {
1150*e4b17023SJohn Marino   if (chrec == NULL_TREE)
1151*e4b17023SJohn Marino     return 0;
1152*e4b17023SJohn Marino 
1153*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
1154*e4b17023SJohn Marino     {
1155*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1156*e4b17023SJohn Marino       return 1 + nb_vars_in_chrec
1157*e4b17023SJohn Marino 	(initial_condition_in_loop_num (chrec, CHREC_VARIABLE (chrec)));
1158*e4b17023SJohn Marino 
1159*e4b17023SJohn Marino     default:
1160*e4b17023SJohn Marino       return 0;
1161*e4b17023SJohn Marino     }
1162*e4b17023SJohn Marino }
1163*e4b17023SJohn Marino 
1164*e4b17023SJohn Marino static tree chrec_convert_1 (tree, tree, gimple, bool);
1165*e4b17023SJohn Marino 
1166*e4b17023SJohn Marino /* Converts BASE and STEP of affine scev to TYPE.  LOOP is the loop whose iv
1167*e4b17023SJohn Marino    the scev corresponds to.  AT_STMT is the statement at that the scev is
1168*e4b17023SJohn Marino    evaluated.  USE_OVERFLOW_SEMANTICS is true if this function should assume that
1169*e4b17023SJohn Marino    the rules for overflow of the given language apply (e.g., that signed
1170*e4b17023SJohn Marino    arithmetics in C does not overflow) -- i.e., to use them to avoid unnecessary
1171*e4b17023SJohn Marino    tests, but also to enforce that the result follows them.  Returns true if the
1172*e4b17023SJohn Marino    conversion succeeded, false otherwise.  */
1173*e4b17023SJohn Marino 
1174*e4b17023SJohn Marino bool
convert_affine_scev(struct loop * loop,tree type,tree * base,tree * step,gimple at_stmt,bool use_overflow_semantics)1175*e4b17023SJohn Marino convert_affine_scev (struct loop *loop, tree type,
1176*e4b17023SJohn Marino 		     tree *base, tree *step, gimple at_stmt,
1177*e4b17023SJohn Marino 		     bool use_overflow_semantics)
1178*e4b17023SJohn Marino {
1179*e4b17023SJohn Marino   tree ct = TREE_TYPE (*step);
1180*e4b17023SJohn Marino   bool enforce_overflow_semantics;
1181*e4b17023SJohn Marino   bool must_check_src_overflow, must_check_rslt_overflow;
1182*e4b17023SJohn Marino   tree new_base, new_step;
1183*e4b17023SJohn Marino   tree step_type = POINTER_TYPE_P (type) ? sizetype : type;
1184*e4b17023SJohn Marino 
1185*e4b17023SJohn Marino   /* In general,
1186*e4b17023SJohn Marino      (TYPE) (BASE + STEP * i) = (TYPE) BASE + (TYPE -- sign extend) STEP * i,
1187*e4b17023SJohn Marino      but we must check some assumptions.
1188*e4b17023SJohn Marino 
1189*e4b17023SJohn Marino      1) If [BASE, +, STEP] wraps, the equation is not valid when precision
1190*e4b17023SJohn Marino         of CT is smaller than the precision of TYPE.  For example, when we
1191*e4b17023SJohn Marino 	cast unsigned char [254, +, 1] to unsigned, the values on left side
1192*e4b17023SJohn Marino 	are 254, 255, 0, 1, ..., but those on the right side are
1193*e4b17023SJohn Marino 	254, 255, 256, 257, ...
1194*e4b17023SJohn Marino      2) In case that we must also preserve the fact that signed ivs do not
1195*e4b17023SJohn Marino         overflow, we must additionally check that the new iv does not wrap.
1196*e4b17023SJohn Marino 	For example, unsigned char [125, +, 1] casted to signed char could
1197*e4b17023SJohn Marino 	become a wrapping variable with values 125, 126, 127, -128, -127, ...,
1198*e4b17023SJohn Marino 	which would confuse optimizers that assume that this does not
1199*e4b17023SJohn Marino 	happen.  */
1200*e4b17023SJohn Marino   must_check_src_overflow = TYPE_PRECISION (ct) < TYPE_PRECISION (type);
1201*e4b17023SJohn Marino 
1202*e4b17023SJohn Marino   enforce_overflow_semantics = (use_overflow_semantics
1203*e4b17023SJohn Marino 				&& nowrap_type_p (type));
1204*e4b17023SJohn Marino   if (enforce_overflow_semantics)
1205*e4b17023SJohn Marino     {
1206*e4b17023SJohn Marino       /* We can avoid checking whether the result overflows in the following
1207*e4b17023SJohn Marino 	 cases:
1208*e4b17023SJohn Marino 
1209*e4b17023SJohn Marino 	 -- must_check_src_overflow is true, and the range of TYPE is superset
1210*e4b17023SJohn Marino 	    of the range of CT -- i.e., in all cases except if CT signed and
1211*e4b17023SJohn Marino 	    TYPE unsigned.
1212*e4b17023SJohn Marino          -- both CT and TYPE have the same precision and signedness, and we
1213*e4b17023SJohn Marino 	    verify instead that the source does not overflow (this may be
1214*e4b17023SJohn Marino 	    easier than verifying it for the result, as we may use the
1215*e4b17023SJohn Marino 	    information about the semantics of overflow in CT).  */
1216*e4b17023SJohn Marino       if (must_check_src_overflow)
1217*e4b17023SJohn Marino 	{
1218*e4b17023SJohn Marino 	  if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (ct))
1219*e4b17023SJohn Marino 	    must_check_rslt_overflow = true;
1220*e4b17023SJohn Marino 	  else
1221*e4b17023SJohn Marino 	    must_check_rslt_overflow = false;
1222*e4b17023SJohn Marino 	}
1223*e4b17023SJohn Marino       else if (TYPE_UNSIGNED (ct) == TYPE_UNSIGNED (type)
1224*e4b17023SJohn Marino 	       && TYPE_PRECISION (ct) == TYPE_PRECISION (type))
1225*e4b17023SJohn Marino 	{
1226*e4b17023SJohn Marino 	  must_check_rslt_overflow = false;
1227*e4b17023SJohn Marino 	  must_check_src_overflow = true;
1228*e4b17023SJohn Marino 	}
1229*e4b17023SJohn Marino       else
1230*e4b17023SJohn Marino 	must_check_rslt_overflow = true;
1231*e4b17023SJohn Marino     }
1232*e4b17023SJohn Marino   else
1233*e4b17023SJohn Marino     must_check_rslt_overflow = false;
1234*e4b17023SJohn Marino 
1235*e4b17023SJohn Marino   if (must_check_src_overflow
1236*e4b17023SJohn Marino       && scev_probably_wraps_p (*base, *step, at_stmt, loop,
1237*e4b17023SJohn Marino 				use_overflow_semantics))
1238*e4b17023SJohn Marino     return false;
1239*e4b17023SJohn Marino 
1240*e4b17023SJohn Marino   new_base = chrec_convert_1 (type, *base, at_stmt,
1241*e4b17023SJohn Marino 			      use_overflow_semantics);
1242*e4b17023SJohn Marino   /* The step must be sign extended, regardless of the signedness
1243*e4b17023SJohn Marino      of CT and TYPE.  This only needs to be handled specially when
1244*e4b17023SJohn Marino      CT is unsigned -- to avoid e.g. unsigned char [100, +, 255]
1245*e4b17023SJohn Marino      (with values 100, 99, 98, ...) from becoming signed or unsigned
1246*e4b17023SJohn Marino      [100, +, 255] with values 100, 355, ...; the sign-extension is
1247*e4b17023SJohn Marino      performed by default when CT is signed.  */
1248*e4b17023SJohn Marino   new_step = *step;
1249*e4b17023SJohn Marino   if (TYPE_PRECISION (step_type) > TYPE_PRECISION (ct) && TYPE_UNSIGNED (ct))
1250*e4b17023SJohn Marino     {
1251*e4b17023SJohn Marino       tree signed_ct = build_nonstandard_integer_type (TYPE_PRECISION (ct), 0);
1252*e4b17023SJohn Marino       new_step = chrec_convert_1 (signed_ct, new_step, at_stmt,
1253*e4b17023SJohn Marino                                   use_overflow_semantics);
1254*e4b17023SJohn Marino     }
1255*e4b17023SJohn Marino   new_step = chrec_convert_1 (step_type, new_step, at_stmt, use_overflow_semantics);
1256*e4b17023SJohn Marino 
1257*e4b17023SJohn Marino   if (automatically_generated_chrec_p (new_base)
1258*e4b17023SJohn Marino       || automatically_generated_chrec_p (new_step))
1259*e4b17023SJohn Marino     return false;
1260*e4b17023SJohn Marino 
1261*e4b17023SJohn Marino   if (must_check_rslt_overflow
1262*e4b17023SJohn Marino       /* Note that in this case we cannot use the fact that signed variables
1263*e4b17023SJohn Marino 	 do not overflow, as this is what we are verifying for the new iv.  */
1264*e4b17023SJohn Marino       && scev_probably_wraps_p (new_base, new_step, at_stmt, loop, false))
1265*e4b17023SJohn Marino     return false;
1266*e4b17023SJohn Marino 
1267*e4b17023SJohn Marino   *base = new_base;
1268*e4b17023SJohn Marino   *step = new_step;
1269*e4b17023SJohn Marino   return true;
1270*e4b17023SJohn Marino }
1271*e4b17023SJohn Marino 
1272*e4b17023SJohn Marino 
1273*e4b17023SJohn Marino /* Convert CHREC for the right hand side of a CHREC.
1274*e4b17023SJohn Marino    The increment for a pointer type is always sizetype.  */
1275*e4b17023SJohn Marino 
1276*e4b17023SJohn Marino tree
chrec_convert_rhs(tree type,tree chrec,gimple at_stmt)1277*e4b17023SJohn Marino chrec_convert_rhs (tree type, tree chrec, gimple at_stmt)
1278*e4b17023SJohn Marino {
1279*e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
1280*e4b17023SJohn Marino     type = sizetype;
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino   return chrec_convert (type, chrec, at_stmt);
1283*e4b17023SJohn Marino }
1284*e4b17023SJohn Marino 
1285*e4b17023SJohn Marino /* Convert CHREC to TYPE.  When the analyzer knows the context in
1286*e4b17023SJohn Marino    which the CHREC is built, it sets AT_STMT to the statement that
1287*e4b17023SJohn Marino    contains the definition of the analyzed variable, otherwise the
1288*e4b17023SJohn Marino    conversion is less accurate: the information is used for
1289*e4b17023SJohn Marino    determining a more accurate estimation of the number of iterations.
1290*e4b17023SJohn Marino    By default AT_STMT could be safely set to NULL_TREE.
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino    The following rule is always true: TREE_TYPE (chrec) ==
1293*e4b17023SJohn Marino    TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE (CHREC_RIGHT (chrec)).
1294*e4b17023SJohn Marino    An example of what could happen when adding two chrecs and the type
1295*e4b17023SJohn Marino    of the CHREC_RIGHT is different than CHREC_LEFT is:
1296*e4b17023SJohn Marino 
1297*e4b17023SJohn Marino    {(uint) 0, +, (uchar) 10} +
1298*e4b17023SJohn Marino    {(uint) 0, +, (uchar) 250}
1299*e4b17023SJohn Marino 
1300*e4b17023SJohn Marino    that would produce a wrong result if CHREC_RIGHT is not (uint):
1301*e4b17023SJohn Marino 
1302*e4b17023SJohn Marino    {(uint) 0, +, (uchar) 4}
1303*e4b17023SJohn Marino 
1304*e4b17023SJohn Marino    instead of
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino    {(uint) 0, +, (uint) 260}
1307*e4b17023SJohn Marino */
1308*e4b17023SJohn Marino 
1309*e4b17023SJohn Marino tree
chrec_convert(tree type,tree chrec,gimple at_stmt)1310*e4b17023SJohn Marino chrec_convert (tree type, tree chrec, gimple at_stmt)
1311*e4b17023SJohn Marino {
1312*e4b17023SJohn Marino   return chrec_convert_1 (type, chrec, at_stmt, true);
1313*e4b17023SJohn Marino }
1314*e4b17023SJohn Marino 
1315*e4b17023SJohn Marino /* Convert CHREC to TYPE.  When the analyzer knows the context in
1316*e4b17023SJohn Marino    which the CHREC is built, it sets AT_STMT to the statement that
1317*e4b17023SJohn Marino    contains the definition of the analyzed variable, otherwise the
1318*e4b17023SJohn Marino    conversion is less accurate: the information is used for
1319*e4b17023SJohn Marino    determining a more accurate estimation of the number of iterations.
1320*e4b17023SJohn Marino    By default AT_STMT could be safely set to NULL_TREE.
1321*e4b17023SJohn Marino 
1322*e4b17023SJohn Marino    USE_OVERFLOW_SEMANTICS is true if this function should assume that
1323*e4b17023SJohn Marino    the rules for overflow of the given language apply (e.g., that signed
1324*e4b17023SJohn Marino    arithmetics in C does not overflow) -- i.e., to use them to avoid unnecessary
1325*e4b17023SJohn Marino    tests, but also to enforce that the result follows them.  */
1326*e4b17023SJohn Marino 
1327*e4b17023SJohn Marino static tree
chrec_convert_1(tree type,tree chrec,gimple at_stmt,bool use_overflow_semantics)1328*e4b17023SJohn Marino chrec_convert_1 (tree type, tree chrec, gimple at_stmt,
1329*e4b17023SJohn Marino 		 bool use_overflow_semantics)
1330*e4b17023SJohn Marino {
1331*e4b17023SJohn Marino   tree ct, res;
1332*e4b17023SJohn Marino   tree base, step;
1333*e4b17023SJohn Marino   struct loop *loop;
1334*e4b17023SJohn Marino 
1335*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
1336*e4b17023SJohn Marino     return chrec;
1337*e4b17023SJohn Marino 
1338*e4b17023SJohn Marino   ct = chrec_type (chrec);
1339*e4b17023SJohn Marino   if (ct == type)
1340*e4b17023SJohn Marino     return chrec;
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   if (!evolution_function_is_affine_p (chrec))
1343*e4b17023SJohn Marino     goto keep_cast;
1344*e4b17023SJohn Marino 
1345*e4b17023SJohn Marino   loop = get_chrec_loop (chrec);
1346*e4b17023SJohn Marino   base = CHREC_LEFT (chrec);
1347*e4b17023SJohn Marino   step = CHREC_RIGHT (chrec);
1348*e4b17023SJohn Marino 
1349*e4b17023SJohn Marino   if (convert_affine_scev (loop, type, &base, &step, at_stmt,
1350*e4b17023SJohn Marino 			   use_overflow_semantics))
1351*e4b17023SJohn Marino     return build_polynomial_chrec (loop->num, base, step);
1352*e4b17023SJohn Marino 
1353*e4b17023SJohn Marino   /* If we cannot propagate the cast inside the chrec, just keep the cast.  */
1354*e4b17023SJohn Marino keep_cast:
1355*e4b17023SJohn Marino   /* Fold will not canonicalize (long)(i - 1) to (long)i - 1 because that
1356*e4b17023SJohn Marino      may be more expensive.  We do want to perform this optimization here
1357*e4b17023SJohn Marino      though for canonicalization reasons.  */
1358*e4b17023SJohn Marino   if (use_overflow_semantics
1359*e4b17023SJohn Marino       && (TREE_CODE (chrec) == PLUS_EXPR
1360*e4b17023SJohn Marino 	  || TREE_CODE (chrec) == MINUS_EXPR)
1361*e4b17023SJohn Marino       && TREE_CODE (type) == INTEGER_TYPE
1362*e4b17023SJohn Marino       && TREE_CODE (ct) == INTEGER_TYPE
1363*e4b17023SJohn Marino       && TYPE_PRECISION (type) > TYPE_PRECISION (ct)
1364*e4b17023SJohn Marino       && TYPE_OVERFLOW_UNDEFINED (ct))
1365*e4b17023SJohn Marino     res = fold_build2 (TREE_CODE (chrec), type,
1366*e4b17023SJohn Marino 		       fold_convert (type, TREE_OPERAND (chrec, 0)),
1367*e4b17023SJohn Marino 		       fold_convert (type, TREE_OPERAND (chrec, 1)));
1368*e4b17023SJohn Marino   else
1369*e4b17023SJohn Marino     res = fold_convert (type, chrec);
1370*e4b17023SJohn Marino 
1371*e4b17023SJohn Marino   /* Don't propagate overflows.  */
1372*e4b17023SJohn Marino   if (CONSTANT_CLASS_P (res))
1373*e4b17023SJohn Marino     TREE_OVERFLOW (res) = 0;
1374*e4b17023SJohn Marino 
1375*e4b17023SJohn Marino   /* But reject constants that don't fit in their type after conversion.
1376*e4b17023SJohn Marino      This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
1377*e4b17023SJohn Marino      natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
1378*e4b17023SJohn Marino      and can cause problems later when computing niters of loops.  Note
1379*e4b17023SJohn Marino      that we don't do the check before converting because we don't want
1380*e4b17023SJohn Marino      to reject conversions of negative chrecs to unsigned types.  */
1381*e4b17023SJohn Marino   if (TREE_CODE (res) == INTEGER_CST
1382*e4b17023SJohn Marino       && TREE_CODE (type) == INTEGER_TYPE
1383*e4b17023SJohn Marino       && !int_fits_type_p (res, type))
1384*e4b17023SJohn Marino     res = chrec_dont_know;
1385*e4b17023SJohn Marino 
1386*e4b17023SJohn Marino   return res;
1387*e4b17023SJohn Marino }
1388*e4b17023SJohn Marino 
1389*e4b17023SJohn Marino /* Convert CHREC to TYPE, without regard to signed overflows.  Returns the new
1390*e4b17023SJohn Marino    chrec if something else than what chrec_convert would do happens, NULL_TREE
1391*e4b17023SJohn Marino    otherwise.  */
1392*e4b17023SJohn Marino 
1393*e4b17023SJohn Marino tree
chrec_convert_aggressive(tree type,tree chrec)1394*e4b17023SJohn Marino chrec_convert_aggressive (tree type, tree chrec)
1395*e4b17023SJohn Marino {
1396*e4b17023SJohn Marino   tree inner_type, left, right, lc, rc, rtype;
1397*e4b17023SJohn Marino 
1398*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec)
1399*e4b17023SJohn Marino       || TREE_CODE (chrec) != POLYNOMIAL_CHREC)
1400*e4b17023SJohn Marino     return NULL_TREE;
1401*e4b17023SJohn Marino 
1402*e4b17023SJohn Marino   inner_type = TREE_TYPE (chrec);
1403*e4b17023SJohn Marino   if (TYPE_PRECISION (type) > TYPE_PRECISION (inner_type))
1404*e4b17023SJohn Marino     return NULL_TREE;
1405*e4b17023SJohn Marino 
1406*e4b17023SJohn Marino   rtype = POINTER_TYPE_P (type) ? sizetype : type;
1407*e4b17023SJohn Marino 
1408*e4b17023SJohn Marino   left = CHREC_LEFT (chrec);
1409*e4b17023SJohn Marino   right = CHREC_RIGHT (chrec);
1410*e4b17023SJohn Marino   lc = chrec_convert_aggressive (type, left);
1411*e4b17023SJohn Marino   if (!lc)
1412*e4b17023SJohn Marino     lc = chrec_convert (type, left, NULL);
1413*e4b17023SJohn Marino   rc = chrec_convert_aggressive (rtype, right);
1414*e4b17023SJohn Marino   if (!rc)
1415*e4b17023SJohn Marino     rc = chrec_convert (rtype, right, NULL);
1416*e4b17023SJohn Marino 
1417*e4b17023SJohn Marino   return build_polynomial_chrec (CHREC_VARIABLE (chrec), lc, rc);
1418*e4b17023SJohn Marino }
1419*e4b17023SJohn Marino 
1420*e4b17023SJohn Marino /* Returns true when CHREC0 == CHREC1.  */
1421*e4b17023SJohn Marino 
1422*e4b17023SJohn Marino bool
eq_evolutions_p(const_tree chrec0,const_tree chrec1)1423*e4b17023SJohn Marino eq_evolutions_p (const_tree chrec0, const_tree chrec1)
1424*e4b17023SJohn Marino {
1425*e4b17023SJohn Marino   if (chrec0 == NULL_TREE
1426*e4b17023SJohn Marino       || chrec1 == NULL_TREE
1427*e4b17023SJohn Marino       || TREE_CODE (chrec0) != TREE_CODE (chrec1))
1428*e4b17023SJohn Marino     return false;
1429*e4b17023SJohn Marino 
1430*e4b17023SJohn Marino   if (chrec0 == chrec1)
1431*e4b17023SJohn Marino     return true;
1432*e4b17023SJohn Marino 
1433*e4b17023SJohn Marino   switch (TREE_CODE (chrec0))
1434*e4b17023SJohn Marino     {
1435*e4b17023SJohn Marino     case INTEGER_CST:
1436*e4b17023SJohn Marino       return operand_equal_p (chrec0, chrec1, 0);
1437*e4b17023SJohn Marino 
1438*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1439*e4b17023SJohn Marino       return (CHREC_VARIABLE (chrec0) == CHREC_VARIABLE (chrec1)
1440*e4b17023SJohn Marino 	      && eq_evolutions_p (CHREC_LEFT (chrec0), CHREC_LEFT (chrec1))
1441*e4b17023SJohn Marino 	      && eq_evolutions_p (CHREC_RIGHT (chrec0), CHREC_RIGHT (chrec1)));
1442*e4b17023SJohn Marino 
1443*e4b17023SJohn Marino     case PLUS_EXPR:
1444*e4b17023SJohn Marino     case MULT_EXPR:
1445*e4b17023SJohn Marino     case MINUS_EXPR:
1446*e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
1447*e4b17023SJohn Marino       return eq_evolutions_p (TREE_OPERAND (chrec0, 0),
1448*e4b17023SJohn Marino 			      TREE_OPERAND (chrec1, 0))
1449*e4b17023SJohn Marino 	  && eq_evolutions_p (TREE_OPERAND (chrec0, 1),
1450*e4b17023SJohn Marino 			      TREE_OPERAND (chrec1, 1));
1451*e4b17023SJohn Marino 
1452*e4b17023SJohn Marino     default:
1453*e4b17023SJohn Marino       return false;
1454*e4b17023SJohn Marino     }
1455*e4b17023SJohn Marino }
1456*e4b17023SJohn Marino 
1457*e4b17023SJohn Marino /* Returns EV_GROWS if CHREC grows (assuming that it does not overflow),
1458*e4b17023SJohn Marino    EV_DECREASES if it decreases, and EV_UNKNOWN if we cannot determine
1459*e4b17023SJohn Marino    which of these cases happens.  */
1460*e4b17023SJohn Marino 
1461*e4b17023SJohn Marino enum ev_direction
scev_direction(const_tree chrec)1462*e4b17023SJohn Marino scev_direction (const_tree chrec)
1463*e4b17023SJohn Marino {
1464*e4b17023SJohn Marino   const_tree step;
1465*e4b17023SJohn Marino 
1466*e4b17023SJohn Marino   if (!evolution_function_is_affine_p (chrec))
1467*e4b17023SJohn Marino     return EV_DIR_UNKNOWN;
1468*e4b17023SJohn Marino 
1469*e4b17023SJohn Marino   step = CHREC_RIGHT (chrec);
1470*e4b17023SJohn Marino   if (TREE_CODE (step) != INTEGER_CST)
1471*e4b17023SJohn Marino     return EV_DIR_UNKNOWN;
1472*e4b17023SJohn Marino 
1473*e4b17023SJohn Marino   if (tree_int_cst_sign_bit (step))
1474*e4b17023SJohn Marino     return EV_DIR_DECREASES;
1475*e4b17023SJohn Marino   else
1476*e4b17023SJohn Marino     return EV_DIR_GROWS;
1477*e4b17023SJohn Marino }
1478*e4b17023SJohn Marino 
1479*e4b17023SJohn Marino /* Iterates over all the components of SCEV, and calls CBCK.  */
1480*e4b17023SJohn Marino 
1481*e4b17023SJohn Marino void
for_each_scev_op(tree * scev,bool (* cbck)(tree *,void *),void * data)1482*e4b17023SJohn Marino for_each_scev_op (tree *scev, bool (*cbck) (tree *, void *), void *data)
1483*e4b17023SJohn Marino {
1484*e4b17023SJohn Marino   switch (TREE_CODE_LENGTH (TREE_CODE (*scev)))
1485*e4b17023SJohn Marino     {
1486*e4b17023SJohn Marino     case 3:
1487*e4b17023SJohn Marino       for_each_scev_op (&TREE_OPERAND (*scev, 2), cbck, data);
1488*e4b17023SJohn Marino 
1489*e4b17023SJohn Marino     case 2:
1490*e4b17023SJohn Marino       for_each_scev_op (&TREE_OPERAND (*scev, 1), cbck, data);
1491*e4b17023SJohn Marino 
1492*e4b17023SJohn Marino     case 1:
1493*e4b17023SJohn Marino       for_each_scev_op (&TREE_OPERAND (*scev, 0), cbck, data);
1494*e4b17023SJohn Marino 
1495*e4b17023SJohn Marino     default:
1496*e4b17023SJohn Marino       cbck (scev, data);
1497*e4b17023SJohn Marino       break;
1498*e4b17023SJohn Marino     }
1499*e4b17023SJohn Marino }
1500*e4b17023SJohn Marino 
1501*e4b17023SJohn Marino /* Returns true when the operation can be part of a linear
1502*e4b17023SJohn Marino    expression.  */
1503*e4b17023SJohn Marino 
1504*e4b17023SJohn Marino static inline bool
operator_is_linear(tree scev)1505*e4b17023SJohn Marino operator_is_linear (tree scev)
1506*e4b17023SJohn Marino {
1507*e4b17023SJohn Marino   switch (TREE_CODE (scev))
1508*e4b17023SJohn Marino     {
1509*e4b17023SJohn Marino     case INTEGER_CST:
1510*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1511*e4b17023SJohn Marino     case PLUS_EXPR:
1512*e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
1513*e4b17023SJohn Marino     case MULT_EXPR:
1514*e4b17023SJohn Marino     case MINUS_EXPR:
1515*e4b17023SJohn Marino     case NEGATE_EXPR:
1516*e4b17023SJohn Marino     case SSA_NAME:
1517*e4b17023SJohn Marino     case NON_LVALUE_EXPR:
1518*e4b17023SJohn Marino     case BIT_NOT_EXPR:
1519*e4b17023SJohn Marino     CASE_CONVERT:
1520*e4b17023SJohn Marino       return true;
1521*e4b17023SJohn Marino 
1522*e4b17023SJohn Marino     default:
1523*e4b17023SJohn Marino       return false;
1524*e4b17023SJohn Marino     }
1525*e4b17023SJohn Marino }
1526*e4b17023SJohn Marino 
1527*e4b17023SJohn Marino /* Return true when SCEV is a linear expression.  Linear expressions
1528*e4b17023SJohn Marino    can contain additions, substractions and multiplications.
1529*e4b17023SJohn Marino    Multiplications are restricted to constant scaling: "cst * x".  */
1530*e4b17023SJohn Marino 
1531*e4b17023SJohn Marino bool
scev_is_linear_expression(tree scev)1532*e4b17023SJohn Marino scev_is_linear_expression (tree scev)
1533*e4b17023SJohn Marino {
1534*e4b17023SJohn Marino   if (scev == NULL
1535*e4b17023SJohn Marino       || !operator_is_linear (scev))
1536*e4b17023SJohn Marino     return false;
1537*e4b17023SJohn Marino 
1538*e4b17023SJohn Marino   if (TREE_CODE (scev) == MULT_EXPR)
1539*e4b17023SJohn Marino     return !(tree_contains_chrecs (TREE_OPERAND (scev, 0), NULL)
1540*e4b17023SJohn Marino 	     && tree_contains_chrecs (TREE_OPERAND (scev, 1), NULL));
1541*e4b17023SJohn Marino 
1542*e4b17023SJohn Marino   if (TREE_CODE (scev) == POLYNOMIAL_CHREC
1543*e4b17023SJohn Marino       && !evolution_function_is_affine_multivariate_p (scev, CHREC_VARIABLE (scev)))
1544*e4b17023SJohn Marino     return false;
1545*e4b17023SJohn Marino 
1546*e4b17023SJohn Marino   switch (TREE_CODE_LENGTH (TREE_CODE (scev)))
1547*e4b17023SJohn Marino     {
1548*e4b17023SJohn Marino     case 3:
1549*e4b17023SJohn Marino       return scev_is_linear_expression (TREE_OPERAND (scev, 0))
1550*e4b17023SJohn Marino 	&& scev_is_linear_expression (TREE_OPERAND (scev, 1))
1551*e4b17023SJohn Marino 	&& scev_is_linear_expression (TREE_OPERAND (scev, 2));
1552*e4b17023SJohn Marino 
1553*e4b17023SJohn Marino     case 2:
1554*e4b17023SJohn Marino       return scev_is_linear_expression (TREE_OPERAND (scev, 0))
1555*e4b17023SJohn Marino 	&& scev_is_linear_expression (TREE_OPERAND (scev, 1));
1556*e4b17023SJohn Marino 
1557*e4b17023SJohn Marino     case 1:
1558*e4b17023SJohn Marino       return scev_is_linear_expression (TREE_OPERAND (scev, 0));
1559*e4b17023SJohn Marino 
1560*e4b17023SJohn Marino     case 0:
1561*e4b17023SJohn Marino       return true;
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino     default:
1564*e4b17023SJohn Marino       return false;
1565*e4b17023SJohn Marino     }
1566*e4b17023SJohn Marino }
1567*e4b17023SJohn Marino 
1568*e4b17023SJohn Marino /* Determines whether the expression CHREC contains only interger consts
1569*e4b17023SJohn Marino    in the right parts.  */
1570*e4b17023SJohn Marino 
1571*e4b17023SJohn Marino bool
evolution_function_right_is_integer_cst(const_tree chrec)1572*e4b17023SJohn Marino evolution_function_right_is_integer_cst (const_tree chrec)
1573*e4b17023SJohn Marino {
1574*e4b17023SJohn Marino   if (chrec == NULL_TREE)
1575*e4b17023SJohn Marino     return false;
1576*e4b17023SJohn Marino 
1577*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
1578*e4b17023SJohn Marino     {
1579*e4b17023SJohn Marino     case INTEGER_CST:
1580*e4b17023SJohn Marino       return true;
1581*e4b17023SJohn Marino 
1582*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1583*e4b17023SJohn Marino       return TREE_CODE (CHREC_RIGHT (chrec)) == INTEGER_CST
1584*e4b17023SJohn Marino 	&& (TREE_CODE (CHREC_LEFT (chrec)) != POLYNOMIAL_CHREC
1585*e4b17023SJohn Marino 	    || evolution_function_right_is_integer_cst (CHREC_LEFT (chrec)));
1586*e4b17023SJohn Marino 
1587*e4b17023SJohn Marino     CASE_CONVERT:
1588*e4b17023SJohn Marino       return evolution_function_right_is_integer_cst (TREE_OPERAND (chrec, 0));
1589*e4b17023SJohn Marino 
1590*e4b17023SJohn Marino     default:
1591*e4b17023SJohn Marino       return false;
1592*e4b17023SJohn Marino     }
1593*e4b17023SJohn Marino }
1594