xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-chrec.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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 #ifndef GCC_TREE_CHREC_H
23*e4b17023SJohn Marino #define GCC_TREE_CHREC_H
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /* The following trees are unique elements.  Thus the comparison of another
26*e4b17023SJohn Marino    element to these elements should be done on the pointer to these trees,
27*e4b17023SJohn Marino    and not on their value.  */
28*e4b17023SJohn Marino 
29*e4b17023SJohn Marino extern tree chrec_not_analyzed_yet;
30*e4b17023SJohn Marino extern GTY(()) tree chrec_dont_know;
31*e4b17023SJohn Marino extern GTY(()) tree chrec_known;
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino /* After having added an automatically generated element, please
34*e4b17023SJohn Marino    include it in the following function.  */
35*e4b17023SJohn Marino 
36*e4b17023SJohn Marino static inline bool
automatically_generated_chrec_p(const_tree chrec)37*e4b17023SJohn Marino automatically_generated_chrec_p (const_tree chrec)
38*e4b17023SJohn Marino {
39*e4b17023SJohn Marino   return (chrec == chrec_dont_know
40*e4b17023SJohn Marino 	  || chrec == chrec_known);
41*e4b17023SJohn Marino }
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino /* The tree nodes aka. CHRECs.  */
44*e4b17023SJohn Marino 
45*e4b17023SJohn Marino static inline bool
tree_is_chrec(const_tree expr)46*e4b17023SJohn Marino tree_is_chrec (const_tree expr)
47*e4b17023SJohn Marino {
48*e4b17023SJohn Marino   if (TREE_CODE (expr) == POLYNOMIAL_CHREC
49*e4b17023SJohn Marino       || automatically_generated_chrec_p (expr))
50*e4b17023SJohn Marino     return true;
51*e4b17023SJohn Marino   else
52*e4b17023SJohn Marino     return false;
53*e4b17023SJohn Marino }
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino 
57*e4b17023SJohn Marino /* Chrec folding functions.  */
58*e4b17023SJohn Marino extern tree chrec_fold_plus (tree, tree, tree);
59*e4b17023SJohn Marino extern tree chrec_fold_minus (tree, tree, tree);
60*e4b17023SJohn Marino extern tree chrec_fold_multiply (tree, tree, tree);
61*e4b17023SJohn Marino extern tree chrec_convert (tree, tree, gimple);
62*e4b17023SJohn Marino extern tree chrec_convert_rhs (tree, tree, gimple);
63*e4b17023SJohn Marino extern tree chrec_convert_aggressive (tree, tree);
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino /* Operations.  */
66*e4b17023SJohn Marino extern tree chrec_apply (unsigned, tree, tree);
67*e4b17023SJohn Marino extern tree chrec_apply_map (tree, VEC (tree, heap) *);
68*e4b17023SJohn Marino extern tree chrec_replace_initial_condition (tree, tree);
69*e4b17023SJohn Marino extern tree initial_condition (tree);
70*e4b17023SJohn Marino extern tree initial_condition_in_loop_num (tree, unsigned);
71*e4b17023SJohn Marino extern tree evolution_part_in_loop_num (tree, unsigned);
72*e4b17023SJohn Marino extern tree hide_evolution_in_other_loops_than_loop (tree, unsigned);
73*e4b17023SJohn Marino extern tree reset_evolution_in_loop (unsigned, tree, tree);
74*e4b17023SJohn Marino extern tree chrec_merge (tree, tree);
75*e4b17023SJohn Marino extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *);
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino /* Observers.  */
78*e4b17023SJohn Marino extern bool eq_evolutions_p (const_tree, const_tree);
79*e4b17023SJohn Marino extern bool is_multivariate_chrec (const_tree);
80*e4b17023SJohn Marino extern bool chrec_contains_symbols (const_tree);
81*e4b17023SJohn Marino extern bool chrec_contains_symbols_defined_in_loop (const_tree, unsigned);
82*e4b17023SJohn Marino extern bool chrec_contains_undetermined (const_tree);
83*e4b17023SJohn Marino extern bool tree_contains_chrecs (const_tree, int *);
84*e4b17023SJohn Marino extern bool evolution_function_is_affine_multivariate_p (const_tree, int);
85*e4b17023SJohn Marino extern bool evolution_function_is_univariate_p (const_tree);
86*e4b17023SJohn Marino extern unsigned nb_vars_in_chrec (tree);
87*e4b17023SJohn Marino extern bool evolution_function_is_invariant_p (tree, int);
88*e4b17023SJohn Marino extern bool scev_is_linear_expression (tree);
89*e4b17023SJohn Marino extern bool evolution_function_right_is_integer_cst (const_tree);
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino /* Determines whether CHREC is equal to zero.  */
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino static inline bool
chrec_zerop(const_tree chrec)94*e4b17023SJohn Marino chrec_zerop (const_tree chrec)
95*e4b17023SJohn Marino {
96*e4b17023SJohn Marino   if (chrec == NULL_TREE)
97*e4b17023SJohn Marino     return false;
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino   if (TREE_CODE (chrec) == INTEGER_CST)
100*e4b17023SJohn Marino     return integer_zerop (chrec);
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino   return false;
103*e4b17023SJohn Marino }
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino /* Determines whether CHREC is a loop invariant with respect to LOOP_NUM.
106*e4b17023SJohn Marino    Set the result in RES and return true when the property can be computed.  */
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino static inline bool
no_evolution_in_loop_p(tree chrec,unsigned loop_num,bool * res)109*e4b17023SJohn Marino no_evolution_in_loop_p (tree chrec, unsigned loop_num, bool *res)
110*e4b17023SJohn Marino {
111*e4b17023SJohn Marino   tree scev;
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino   if (chrec == chrec_not_analyzed_yet
114*e4b17023SJohn Marino       || chrec == chrec_dont_know
115*e4b17023SJohn Marino       || chrec_contains_symbols_defined_in_loop (chrec, loop_num))
116*e4b17023SJohn Marino     return false;
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino   STRIP_NOPS (chrec);
119*e4b17023SJohn Marino   scev = hide_evolution_in_other_loops_than_loop (chrec, loop_num);
120*e4b17023SJohn Marino   *res = !tree_is_chrec (scev);
121*e4b17023SJohn Marino   return true;
122*e4b17023SJohn Marino }
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino /* Build a polynomial chain of recurrence.  */
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino static inline tree
build_polynomial_chrec(unsigned loop_num,tree left,tree right)127*e4b17023SJohn Marino build_polynomial_chrec (unsigned loop_num,
128*e4b17023SJohn Marino 			tree left,
129*e4b17023SJohn Marino 			tree right)
130*e4b17023SJohn Marino {
131*e4b17023SJohn Marino   bool val;
132*e4b17023SJohn Marino 
133*e4b17023SJohn Marino   if (left == chrec_dont_know
134*e4b17023SJohn Marino       || right == chrec_dont_know)
135*e4b17023SJohn Marino     return chrec_dont_know;
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino   if (!no_evolution_in_loop_p (left, loop_num, &val)
138*e4b17023SJohn Marino       || !val)
139*e4b17023SJohn Marino     return chrec_dont_know;
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino   /* Pointer types should occur only on the left hand side, i.e. in
142*e4b17023SJohn Marino      the base of the chrec, and not in the step.  */
143*e4b17023SJohn Marino   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (right)));
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino   /* Types of left and right sides of a chrec should be compatible.  */
146*e4b17023SJohn Marino   if (POINTER_TYPE_P (TREE_TYPE (left)))
147*e4b17023SJohn Marino     gcc_assert (ptrofftype_p (TREE_TYPE (right)));
148*e4b17023SJohn Marino   else
149*e4b17023SJohn Marino     gcc_assert (TREE_TYPE (left) == TREE_TYPE (right));
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino   if (chrec_zerop (right))
152*e4b17023SJohn Marino     return left;
153*e4b17023SJohn Marino 
154*e4b17023SJohn Marino   return build3 (POLYNOMIAL_CHREC, TREE_TYPE (left),
155*e4b17023SJohn Marino 		 build_int_cst (NULL_TREE, loop_num), left, right);
156*e4b17023SJohn Marino }
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino /* Determines whether the expression CHREC is a constant.  */
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino static inline bool
evolution_function_is_constant_p(const_tree chrec)161*e4b17023SJohn Marino evolution_function_is_constant_p (const_tree chrec)
162*e4b17023SJohn Marino {
163*e4b17023SJohn Marino   if (chrec == NULL_TREE)
164*e4b17023SJohn Marino     return false;
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
167*e4b17023SJohn Marino     {
168*e4b17023SJohn Marino     case INTEGER_CST:
169*e4b17023SJohn Marino     case REAL_CST:
170*e4b17023SJohn Marino       return true;
171*e4b17023SJohn Marino 
172*e4b17023SJohn Marino     default:
173*e4b17023SJohn Marino       return false;
174*e4b17023SJohn Marino     }
175*e4b17023SJohn Marino }
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino /* Determine whether CHREC is an affine evolution function in LOOPNUM.  */
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino static inline bool
evolution_function_is_affine_in_loop(const_tree chrec,int loopnum)180*e4b17023SJohn Marino evolution_function_is_affine_in_loop (const_tree chrec, int loopnum)
181*e4b17023SJohn Marino {
182*e4b17023SJohn Marino   if (chrec == NULL_TREE)
183*e4b17023SJohn Marino     return false;
184*e4b17023SJohn Marino 
185*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
186*e4b17023SJohn Marino     {
187*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
188*e4b17023SJohn Marino       if (evolution_function_is_invariant_p (CHREC_LEFT (chrec), loopnum)
189*e4b17023SJohn Marino 	  && evolution_function_is_invariant_p (CHREC_RIGHT (chrec), loopnum))
190*e4b17023SJohn Marino 	return true;
191*e4b17023SJohn Marino       else
192*e4b17023SJohn Marino 	return false;
193*e4b17023SJohn Marino 
194*e4b17023SJohn Marino     default:
195*e4b17023SJohn Marino       return false;
196*e4b17023SJohn Marino     }
197*e4b17023SJohn Marino }
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino /* Determine whether CHREC is an affine evolution function or not.  */
200*e4b17023SJohn Marino 
201*e4b17023SJohn Marino static inline bool
evolution_function_is_affine_p(const_tree chrec)202*e4b17023SJohn Marino evolution_function_is_affine_p (const_tree chrec)
203*e4b17023SJohn Marino {
204*e4b17023SJohn Marino   return chrec
205*e4b17023SJohn Marino     && TREE_CODE (chrec) == POLYNOMIAL_CHREC
206*e4b17023SJohn Marino     && evolution_function_is_invariant_p (CHREC_RIGHT (chrec),
207*e4b17023SJohn Marino 					  CHREC_VARIABLE (chrec))
208*e4b17023SJohn Marino     && (TREE_CODE (CHREC_RIGHT (chrec)) != POLYNOMIAL_CHREC
209*e4b17023SJohn Marino 	|| evolution_function_is_affine_p (CHREC_RIGHT (chrec)));
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino 
212*e4b17023SJohn Marino /* Determines whether EXPR does not contains chrec expressions.  */
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino static inline bool
tree_does_not_contain_chrecs(const_tree expr)215*e4b17023SJohn Marino tree_does_not_contain_chrecs (const_tree expr)
216*e4b17023SJohn Marino {
217*e4b17023SJohn Marino   return !tree_contains_chrecs (expr, NULL);
218*e4b17023SJohn Marino }
219*e4b17023SJohn Marino 
220*e4b17023SJohn Marino /* Returns the type of the chrec.  */
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino static inline tree
chrec_type(const_tree chrec)223*e4b17023SJohn Marino chrec_type (const_tree chrec)
224*e4b17023SJohn Marino {
225*e4b17023SJohn Marino   if (automatically_generated_chrec_p (chrec))
226*e4b17023SJohn Marino     return NULL_TREE;
227*e4b17023SJohn Marino 
228*e4b17023SJohn Marino   return TREE_TYPE (chrec);
229*e4b17023SJohn Marino }
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino static inline tree
chrec_fold_op(enum tree_code code,tree type,tree op0,tree op1)232*e4b17023SJohn Marino chrec_fold_op (enum tree_code code, tree type, tree op0, tree op1)
233*e4b17023SJohn Marino {
234*e4b17023SJohn Marino   switch (code)
235*e4b17023SJohn Marino     {
236*e4b17023SJohn Marino     case PLUS_EXPR:
237*e4b17023SJohn Marino       return chrec_fold_plus (type, op0, op1);
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino     case MINUS_EXPR:
240*e4b17023SJohn Marino       return chrec_fold_minus (type, op0, op1);
241*e4b17023SJohn Marino 
242*e4b17023SJohn Marino     case MULT_EXPR:
243*e4b17023SJohn Marino       return chrec_fold_multiply (type, op0, op1);
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino     default:
246*e4b17023SJohn Marino       gcc_unreachable ();
247*e4b17023SJohn Marino     }
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino #endif  /* GCC_TREE_CHREC_H  */
252