xref: /dflybsd-src/contrib/gcc-8.0/gcc/tree-chrec.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Chains of recurrences.
2*38fd1498Szrj    Copyright (C) 2003-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
4*38fd1498Szrj 
5*38fd1498Szrj This file is part of GCC.
6*38fd1498Szrj 
7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
8*38fd1498Szrj the terms of the GNU General Public License as published by the Free
9*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
10*38fd1498Szrj version.
11*38fd1498Szrj 
12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*38fd1498Szrj for more details.
16*38fd1498Szrj 
17*38fd1498Szrj You should have received a copy of the GNU General Public License
18*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
19*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
20*38fd1498Szrj 
21*38fd1498Szrj #ifndef GCC_TREE_CHREC_H
22*38fd1498Szrj #define GCC_TREE_CHREC_H
23*38fd1498Szrj 
24*38fd1498Szrj /* The following trees are unique elements.  Thus the comparison of another
25*38fd1498Szrj    element to these elements should be done on the pointer to these trees,
26*38fd1498Szrj    and not on their value.  */
27*38fd1498Szrj 
28*38fd1498Szrj extern tree chrec_not_analyzed_yet;
29*38fd1498Szrj extern GTY(()) tree chrec_dont_know;
30*38fd1498Szrj extern GTY(()) tree chrec_known;
31*38fd1498Szrj 
32*38fd1498Szrj /* After having added an automatically generated element, please
33*38fd1498Szrj    include it in the following function.  */
34*38fd1498Szrj 
35*38fd1498Szrj static inline bool
automatically_generated_chrec_p(const_tree chrec)36*38fd1498Szrj automatically_generated_chrec_p (const_tree chrec)
37*38fd1498Szrj {
38*38fd1498Szrj   return (chrec == chrec_dont_know
39*38fd1498Szrj 	  || chrec == chrec_known);
40*38fd1498Szrj }
41*38fd1498Szrj 
42*38fd1498Szrj /* The tree nodes aka. CHRECs.  */
43*38fd1498Szrj 
44*38fd1498Szrj static inline bool
tree_is_chrec(const_tree expr)45*38fd1498Szrj tree_is_chrec (const_tree expr)
46*38fd1498Szrj {
47*38fd1498Szrj   if (TREE_CODE (expr) == POLYNOMIAL_CHREC
48*38fd1498Szrj       || automatically_generated_chrec_p (expr))
49*38fd1498Szrj     return true;
50*38fd1498Szrj   else
51*38fd1498Szrj     return false;
52*38fd1498Szrj }
53*38fd1498Szrj 
54*38fd1498Szrj 
55*38fd1498Szrj enum ev_direction {EV_DIR_GROWS, EV_DIR_DECREASES, EV_DIR_UNKNOWN};
56*38fd1498Szrj enum ev_direction scev_direction (const_tree);
57*38fd1498Szrj 
58*38fd1498Szrj /* Chrec folding functions.  */
59*38fd1498Szrj extern tree chrec_fold_plus (tree, tree, tree);
60*38fd1498Szrj extern tree chrec_fold_minus (tree, tree, tree);
61*38fd1498Szrj extern tree chrec_fold_multiply (tree, tree, tree);
62*38fd1498Szrj extern tree chrec_convert (tree, tree, gimple *, bool = true, tree = NULL);
63*38fd1498Szrj extern tree chrec_convert_rhs (tree, tree, gimple *);
64*38fd1498Szrj extern tree chrec_convert_aggressive (tree, tree, bool *);
65*38fd1498Szrj 
66*38fd1498Szrj /* Operations.  */
67*38fd1498Szrj extern tree chrec_apply (unsigned, tree, tree);
68*38fd1498Szrj extern tree chrec_apply_map (tree, vec<tree> );
69*38fd1498Szrj extern tree chrec_replace_initial_condition (tree, tree);
70*38fd1498Szrj extern tree initial_condition (tree);
71*38fd1498Szrj extern tree initial_condition_in_loop_num (tree, unsigned);
72*38fd1498Szrj extern tree evolution_part_in_loop_num (tree, unsigned);
73*38fd1498Szrj extern tree hide_evolution_in_other_loops_than_loop (tree, unsigned);
74*38fd1498Szrj extern tree reset_evolution_in_loop (unsigned, tree, tree);
75*38fd1498Szrj extern tree chrec_merge (tree, tree);
76*38fd1498Szrj extern void for_each_scev_op (tree *, bool (*) (tree *, void *), void *);
77*38fd1498Szrj extern bool convert_affine_scev (struct loop *, tree, tree *, tree *, gimple *,
78*38fd1498Szrj 				 bool, tree = NULL);
79*38fd1498Szrj 
80*38fd1498Szrj /* Observers.  */
81*38fd1498Szrj extern bool eq_evolutions_p (const_tree, const_tree);
82*38fd1498Szrj extern bool is_multivariate_chrec (const_tree);
83*38fd1498Szrj extern bool chrec_contains_symbols (const_tree);
84*38fd1498Szrj extern bool chrec_contains_symbols_defined_in_loop (const_tree, unsigned);
85*38fd1498Szrj extern bool chrec_contains_undetermined (const_tree);
86*38fd1498Szrj extern bool tree_contains_chrecs (const_tree, int *);
87*38fd1498Szrj extern bool evolution_function_is_affine_multivariate_p (const_tree, int);
88*38fd1498Szrj extern bool evolution_function_is_univariate_p (const_tree);
89*38fd1498Szrj extern unsigned nb_vars_in_chrec (tree);
90*38fd1498Szrj extern bool evolution_function_is_invariant_p (tree, int);
91*38fd1498Szrj extern bool scev_is_linear_expression (tree);
92*38fd1498Szrj extern bool evolution_function_right_is_integer_cst (const_tree);
93*38fd1498Szrj 
94*38fd1498Szrj /* Determines whether CHREC is equal to zero.  */
95*38fd1498Szrj 
96*38fd1498Szrj static inline bool
chrec_zerop(const_tree chrec)97*38fd1498Szrj chrec_zerop (const_tree chrec)
98*38fd1498Szrj {
99*38fd1498Szrj   if (chrec == NULL_TREE)
100*38fd1498Szrj     return false;
101*38fd1498Szrj 
102*38fd1498Szrj   if (TREE_CODE (chrec) == INTEGER_CST)
103*38fd1498Szrj     return integer_zerop (chrec);
104*38fd1498Szrj 
105*38fd1498Szrj   return false;
106*38fd1498Szrj }
107*38fd1498Szrj 
108*38fd1498Szrj /* Determines whether CHREC is a loop invariant with respect to LOOP_NUM.
109*38fd1498Szrj    Set the result in RES and return true when the property can be computed.  */
110*38fd1498Szrj 
111*38fd1498Szrj static inline bool
no_evolution_in_loop_p(tree chrec,unsigned loop_num,bool * res)112*38fd1498Szrj no_evolution_in_loop_p (tree chrec, unsigned loop_num, bool *res)
113*38fd1498Szrj {
114*38fd1498Szrj   tree scev;
115*38fd1498Szrj 
116*38fd1498Szrj   if (chrec == chrec_not_analyzed_yet
117*38fd1498Szrj       || chrec == chrec_dont_know
118*38fd1498Szrj       || chrec_contains_symbols_defined_in_loop (chrec, loop_num))
119*38fd1498Szrj     return false;
120*38fd1498Szrj 
121*38fd1498Szrj   STRIP_NOPS (chrec);
122*38fd1498Szrj   scev = hide_evolution_in_other_loops_than_loop (chrec, loop_num);
123*38fd1498Szrj   *res = !tree_contains_chrecs (scev, NULL);
124*38fd1498Szrj   return true;
125*38fd1498Szrj }
126*38fd1498Szrj 
127*38fd1498Szrj /* Build a polynomial chain of recurrence.  */
128*38fd1498Szrj 
129*38fd1498Szrj static inline tree
build_polynomial_chrec(unsigned loop_num,tree left,tree right)130*38fd1498Szrj build_polynomial_chrec (unsigned loop_num,
131*38fd1498Szrj 			tree left,
132*38fd1498Szrj 			tree right)
133*38fd1498Szrj {
134*38fd1498Szrj   bool val;
135*38fd1498Szrj 
136*38fd1498Szrj   if (left == chrec_dont_know
137*38fd1498Szrj       || right == chrec_dont_know)
138*38fd1498Szrj     return chrec_dont_know;
139*38fd1498Szrj 
140*38fd1498Szrj   if (!no_evolution_in_loop_p (left, loop_num, &val)
141*38fd1498Szrj       || !val)
142*38fd1498Szrj     return chrec_dont_know;
143*38fd1498Szrj 
144*38fd1498Szrj   /* Types of left and right sides of a chrec should be compatible, but
145*38fd1498Szrj      pointer CHRECs are special in that the evolution is of ptroff type.  */
146*38fd1498Szrj   if (POINTER_TYPE_P (TREE_TYPE (left)))
147*38fd1498Szrj     gcc_checking_assert (ptrofftype_p (TREE_TYPE (right)));
148*38fd1498Szrj   else
149*38fd1498Szrj     {
150*38fd1498Szrj       /* Pointer types should occur only on the left hand side, i.e. in
151*38fd1498Szrj 	 the base of the chrec, and not in the step.  */
152*38fd1498Szrj       gcc_checking_assert (!POINTER_TYPE_P (TREE_TYPE (right))
153*38fd1498Szrj 			   && types_compatible_p (TREE_TYPE (left),
154*38fd1498Szrj 						  TREE_TYPE (right)));
155*38fd1498Szrj     }
156*38fd1498Szrj 
157*38fd1498Szrj   if (chrec_zerop (right))
158*38fd1498Szrj     return left;
159*38fd1498Szrj 
160*38fd1498Szrj   tree chrec = build2 (POLYNOMIAL_CHREC, TREE_TYPE (left), left, right);
161*38fd1498Szrj   CHREC_VARIABLE (chrec) = loop_num;
162*38fd1498Szrj   return chrec;
163*38fd1498Szrj }
164*38fd1498Szrj 
165*38fd1498Szrj /* Determines whether the expression CHREC is a constant.  */
166*38fd1498Szrj 
167*38fd1498Szrj static inline bool
evolution_function_is_constant_p(const_tree chrec)168*38fd1498Szrj evolution_function_is_constant_p (const_tree chrec)
169*38fd1498Szrj {
170*38fd1498Szrj   if (chrec == NULL_TREE)
171*38fd1498Szrj     return false;
172*38fd1498Szrj 
173*38fd1498Szrj   if (CONSTANT_CLASS_P (chrec))
174*38fd1498Szrj     return true;
175*38fd1498Szrj   return is_gimple_min_invariant (chrec);
176*38fd1498Szrj }
177*38fd1498Szrj 
178*38fd1498Szrj /* Determine whether CHREC is an affine evolution function in LOOPNUM.  */
179*38fd1498Szrj 
180*38fd1498Szrj static inline bool
evolution_function_is_affine_in_loop(const_tree chrec,int loopnum)181*38fd1498Szrj evolution_function_is_affine_in_loop (const_tree chrec, int loopnum)
182*38fd1498Szrj {
183*38fd1498Szrj   if (chrec == NULL_TREE)
184*38fd1498Szrj     return false;
185*38fd1498Szrj 
186*38fd1498Szrj   switch (TREE_CODE (chrec))
187*38fd1498Szrj     {
188*38fd1498Szrj     case POLYNOMIAL_CHREC:
189*38fd1498Szrj       if (evolution_function_is_invariant_p (CHREC_LEFT (chrec), loopnum)
190*38fd1498Szrj 	  && evolution_function_is_invariant_p (CHREC_RIGHT (chrec), loopnum))
191*38fd1498Szrj 	return true;
192*38fd1498Szrj       else
193*38fd1498Szrj 	return false;
194*38fd1498Szrj 
195*38fd1498Szrj     default:
196*38fd1498Szrj       return false;
197*38fd1498Szrj     }
198*38fd1498Szrj }
199*38fd1498Szrj 
200*38fd1498Szrj /* Determine whether CHREC is an affine evolution function or not.  */
201*38fd1498Szrj 
202*38fd1498Szrj static inline bool
evolution_function_is_affine_p(const_tree chrec)203*38fd1498Szrj evolution_function_is_affine_p (const_tree chrec)
204*38fd1498Szrj {
205*38fd1498Szrj   return chrec
206*38fd1498Szrj     && TREE_CODE (chrec) == POLYNOMIAL_CHREC
207*38fd1498Szrj     && evolution_function_is_invariant_p (CHREC_RIGHT (chrec),
208*38fd1498Szrj 					  CHREC_VARIABLE (chrec))
209*38fd1498Szrj     && (TREE_CODE (CHREC_RIGHT (chrec)) != POLYNOMIAL_CHREC
210*38fd1498Szrj 	|| evolution_function_is_affine_p (CHREC_RIGHT (chrec)));
211*38fd1498Szrj }
212*38fd1498Szrj 
213*38fd1498Szrj /* Determines whether EXPR does not contains chrec expressions.  */
214*38fd1498Szrj 
215*38fd1498Szrj static inline bool
tree_does_not_contain_chrecs(const_tree expr)216*38fd1498Szrj tree_does_not_contain_chrecs (const_tree expr)
217*38fd1498Szrj {
218*38fd1498Szrj   return !tree_contains_chrecs (expr, NULL);
219*38fd1498Szrj }
220*38fd1498Szrj 
221*38fd1498Szrj /* Returns the type of the chrec.  */
222*38fd1498Szrj 
223*38fd1498Szrj static inline tree
chrec_type(const_tree chrec)224*38fd1498Szrj chrec_type (const_tree chrec)
225*38fd1498Szrj {
226*38fd1498Szrj   if (automatically_generated_chrec_p (chrec))
227*38fd1498Szrj     return NULL_TREE;
228*38fd1498Szrj 
229*38fd1498Szrj   return TREE_TYPE (chrec);
230*38fd1498Szrj }
231*38fd1498Szrj 
232*38fd1498Szrj static inline tree
chrec_fold_op(enum tree_code code,tree type,tree op0,tree op1)233*38fd1498Szrj chrec_fold_op (enum tree_code code, tree type, tree op0, tree op1)
234*38fd1498Szrj {
235*38fd1498Szrj   switch (code)
236*38fd1498Szrj     {
237*38fd1498Szrj     case PLUS_EXPR:
238*38fd1498Szrj       return chrec_fold_plus (type, op0, op1);
239*38fd1498Szrj 
240*38fd1498Szrj     case MINUS_EXPR:
241*38fd1498Szrj       return chrec_fold_minus (type, op0, op1);
242*38fd1498Szrj 
243*38fd1498Szrj     case MULT_EXPR:
244*38fd1498Szrj       return chrec_fold_multiply (type, op0, op1);
245*38fd1498Szrj 
246*38fd1498Szrj     default:
247*38fd1498Szrj       gcc_unreachable ();
248*38fd1498Szrj     }
249*38fd1498Szrj 
250*38fd1498Szrj }
251*38fd1498Szrj 
252*38fd1498Szrj #endif  /* GCC_TREE_CHREC_H  */
253