1*e4b17023SJohn Marino /* Operations with affine combinations of trees.
2*e4b17023SJohn Marino Copyright (C) 2005, 2007, 2008, 2010 Free Software Foundation, Inc.
3*e4b17023SJohn Marino
4*e4b17023SJohn Marino This file is part of GCC.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
7*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any
9*e4b17023SJohn Marino later version.
10*e4b17023SJohn Marino
11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
12*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*e4b17023SJohn Marino for more details.
15*e4b17023SJohn Marino
16*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
17*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
18*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
19*e4b17023SJohn Marino
20*e4b17023SJohn Marino #include "config.h"
21*e4b17023SJohn Marino #include "system.h"
22*e4b17023SJohn Marino #include "coretypes.h"
23*e4b17023SJohn Marino #include "tree.h"
24*e4b17023SJohn Marino #include "output.h"
25*e4b17023SJohn Marino #include "tree-pretty-print.h"
26*e4b17023SJohn Marino #include "tree-dump.h"
27*e4b17023SJohn Marino #include "pointer-set.h"
28*e4b17023SJohn Marino #include "tree-affine.h"
29*e4b17023SJohn Marino #include "gimple.h"
30*e4b17023SJohn Marino #include "flags.h"
31*e4b17023SJohn Marino
32*e4b17023SJohn Marino /* Extends CST as appropriate for the affine combinations COMB. */
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino double_int
double_int_ext_for_comb(double_int cst,aff_tree * comb)35*e4b17023SJohn Marino double_int_ext_for_comb (double_int cst, aff_tree *comb)
36*e4b17023SJohn Marino {
37*e4b17023SJohn Marino return double_int_sext (cst, TYPE_PRECISION (comb->type));
38*e4b17023SJohn Marino }
39*e4b17023SJohn Marino
40*e4b17023SJohn Marino /* Initializes affine combination COMB so that its value is zero in TYPE. */
41*e4b17023SJohn Marino
42*e4b17023SJohn Marino static void
aff_combination_zero(aff_tree * comb,tree type)43*e4b17023SJohn Marino aff_combination_zero (aff_tree *comb, tree type)
44*e4b17023SJohn Marino {
45*e4b17023SJohn Marino comb->type = type;
46*e4b17023SJohn Marino comb->offset = double_int_zero;
47*e4b17023SJohn Marino comb->n = 0;
48*e4b17023SJohn Marino comb->rest = NULL_TREE;
49*e4b17023SJohn Marino }
50*e4b17023SJohn Marino
51*e4b17023SJohn Marino /* Sets COMB to CST. */
52*e4b17023SJohn Marino
53*e4b17023SJohn Marino void
aff_combination_const(aff_tree * comb,tree type,double_int cst)54*e4b17023SJohn Marino aff_combination_const (aff_tree *comb, tree type, double_int cst)
55*e4b17023SJohn Marino {
56*e4b17023SJohn Marino aff_combination_zero (comb, type);
57*e4b17023SJohn Marino comb->offset = double_int_ext_for_comb (cst, comb);
58*e4b17023SJohn Marino }
59*e4b17023SJohn Marino
60*e4b17023SJohn Marino /* Sets COMB to single element ELT. */
61*e4b17023SJohn Marino
62*e4b17023SJohn Marino void
aff_combination_elt(aff_tree * comb,tree type,tree elt)63*e4b17023SJohn Marino aff_combination_elt (aff_tree *comb, tree type, tree elt)
64*e4b17023SJohn Marino {
65*e4b17023SJohn Marino aff_combination_zero (comb, type);
66*e4b17023SJohn Marino
67*e4b17023SJohn Marino comb->n = 1;
68*e4b17023SJohn Marino comb->elts[0].val = elt;
69*e4b17023SJohn Marino comb->elts[0].coef = double_int_one;
70*e4b17023SJohn Marino }
71*e4b17023SJohn Marino
72*e4b17023SJohn Marino /* Scales COMB by SCALE. */
73*e4b17023SJohn Marino
74*e4b17023SJohn Marino void
aff_combination_scale(aff_tree * comb,double_int scale)75*e4b17023SJohn Marino aff_combination_scale (aff_tree *comb, double_int scale)
76*e4b17023SJohn Marino {
77*e4b17023SJohn Marino unsigned i, j;
78*e4b17023SJohn Marino
79*e4b17023SJohn Marino scale = double_int_ext_for_comb (scale, comb);
80*e4b17023SJohn Marino if (double_int_one_p (scale))
81*e4b17023SJohn Marino return;
82*e4b17023SJohn Marino
83*e4b17023SJohn Marino if (double_int_zero_p (scale))
84*e4b17023SJohn Marino {
85*e4b17023SJohn Marino aff_combination_zero (comb, comb->type);
86*e4b17023SJohn Marino return;
87*e4b17023SJohn Marino }
88*e4b17023SJohn Marino
89*e4b17023SJohn Marino comb->offset
90*e4b17023SJohn Marino = double_int_ext_for_comb (double_int_mul (scale, comb->offset), comb);
91*e4b17023SJohn Marino for (i = 0, j = 0; i < comb->n; i++)
92*e4b17023SJohn Marino {
93*e4b17023SJohn Marino double_int new_coef;
94*e4b17023SJohn Marino
95*e4b17023SJohn Marino new_coef
96*e4b17023SJohn Marino = double_int_ext_for_comb (double_int_mul (scale, comb->elts[i].coef),
97*e4b17023SJohn Marino comb);
98*e4b17023SJohn Marino /* A coefficient may become zero due to overflow. Remove the zero
99*e4b17023SJohn Marino elements. */
100*e4b17023SJohn Marino if (double_int_zero_p (new_coef))
101*e4b17023SJohn Marino continue;
102*e4b17023SJohn Marino comb->elts[j].coef = new_coef;
103*e4b17023SJohn Marino comb->elts[j].val = comb->elts[i].val;
104*e4b17023SJohn Marino j++;
105*e4b17023SJohn Marino }
106*e4b17023SJohn Marino comb->n = j;
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino if (comb->rest)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino tree type = comb->type;
111*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
112*e4b17023SJohn Marino type = sizetype;
113*e4b17023SJohn Marino if (comb->n < MAX_AFF_ELTS)
114*e4b17023SJohn Marino {
115*e4b17023SJohn Marino comb->elts[comb->n].coef = scale;
116*e4b17023SJohn Marino comb->elts[comb->n].val = comb->rest;
117*e4b17023SJohn Marino comb->rest = NULL_TREE;
118*e4b17023SJohn Marino comb->n++;
119*e4b17023SJohn Marino }
120*e4b17023SJohn Marino else
121*e4b17023SJohn Marino comb->rest = fold_build2 (MULT_EXPR, type, comb->rest,
122*e4b17023SJohn Marino double_int_to_tree (type, scale));
123*e4b17023SJohn Marino }
124*e4b17023SJohn Marino }
125*e4b17023SJohn Marino
126*e4b17023SJohn Marino /* Adds ELT * SCALE to COMB. */
127*e4b17023SJohn Marino
128*e4b17023SJohn Marino void
aff_combination_add_elt(aff_tree * comb,tree elt,double_int scale)129*e4b17023SJohn Marino aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale)
130*e4b17023SJohn Marino {
131*e4b17023SJohn Marino unsigned i;
132*e4b17023SJohn Marino tree type;
133*e4b17023SJohn Marino
134*e4b17023SJohn Marino scale = double_int_ext_for_comb (scale, comb);
135*e4b17023SJohn Marino if (double_int_zero_p (scale))
136*e4b17023SJohn Marino return;
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino for (i = 0; i < comb->n; i++)
139*e4b17023SJohn Marino if (operand_equal_p (comb->elts[i].val, elt, 0))
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino double_int new_coef;
142*e4b17023SJohn Marino
143*e4b17023SJohn Marino new_coef = double_int_add (comb->elts[i].coef, scale);
144*e4b17023SJohn Marino new_coef = double_int_ext_for_comb (new_coef, comb);
145*e4b17023SJohn Marino if (!double_int_zero_p (new_coef))
146*e4b17023SJohn Marino {
147*e4b17023SJohn Marino comb->elts[i].coef = new_coef;
148*e4b17023SJohn Marino return;
149*e4b17023SJohn Marino }
150*e4b17023SJohn Marino
151*e4b17023SJohn Marino comb->n--;
152*e4b17023SJohn Marino comb->elts[i] = comb->elts[comb->n];
153*e4b17023SJohn Marino
154*e4b17023SJohn Marino if (comb->rest)
155*e4b17023SJohn Marino {
156*e4b17023SJohn Marino gcc_assert (comb->n == MAX_AFF_ELTS - 1);
157*e4b17023SJohn Marino comb->elts[comb->n].coef = double_int_one;
158*e4b17023SJohn Marino comb->elts[comb->n].val = comb->rest;
159*e4b17023SJohn Marino comb->rest = NULL_TREE;
160*e4b17023SJohn Marino comb->n++;
161*e4b17023SJohn Marino }
162*e4b17023SJohn Marino return;
163*e4b17023SJohn Marino }
164*e4b17023SJohn Marino if (comb->n < MAX_AFF_ELTS)
165*e4b17023SJohn Marino {
166*e4b17023SJohn Marino comb->elts[comb->n].coef = scale;
167*e4b17023SJohn Marino comb->elts[comb->n].val = elt;
168*e4b17023SJohn Marino comb->n++;
169*e4b17023SJohn Marino return;
170*e4b17023SJohn Marino }
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino type = comb->type;
173*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
174*e4b17023SJohn Marino type = sizetype;
175*e4b17023SJohn Marino
176*e4b17023SJohn Marino if (double_int_one_p (scale))
177*e4b17023SJohn Marino elt = fold_convert (type, elt);
178*e4b17023SJohn Marino else
179*e4b17023SJohn Marino elt = fold_build2 (MULT_EXPR, type,
180*e4b17023SJohn Marino fold_convert (type, elt),
181*e4b17023SJohn Marino double_int_to_tree (type, scale));
182*e4b17023SJohn Marino
183*e4b17023SJohn Marino if (comb->rest)
184*e4b17023SJohn Marino comb->rest = fold_build2 (PLUS_EXPR, type, comb->rest,
185*e4b17023SJohn Marino elt);
186*e4b17023SJohn Marino else
187*e4b17023SJohn Marino comb->rest = elt;
188*e4b17023SJohn Marino }
189*e4b17023SJohn Marino
190*e4b17023SJohn Marino /* Adds CST to C. */
191*e4b17023SJohn Marino
192*e4b17023SJohn Marino static void
aff_combination_add_cst(aff_tree * c,double_int cst)193*e4b17023SJohn Marino aff_combination_add_cst (aff_tree *c, double_int cst)
194*e4b17023SJohn Marino {
195*e4b17023SJohn Marino c->offset = double_int_ext_for_comb (double_int_add (c->offset, cst), c);
196*e4b17023SJohn Marino }
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino /* Adds COMB2 to COMB1. */
199*e4b17023SJohn Marino
200*e4b17023SJohn Marino void
aff_combination_add(aff_tree * comb1,aff_tree * comb2)201*e4b17023SJohn Marino aff_combination_add (aff_tree *comb1, aff_tree *comb2)
202*e4b17023SJohn Marino {
203*e4b17023SJohn Marino unsigned i;
204*e4b17023SJohn Marino
205*e4b17023SJohn Marino aff_combination_add_cst (comb1, comb2->offset);
206*e4b17023SJohn Marino for (i = 0; i < comb2->n; i++)
207*e4b17023SJohn Marino aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
208*e4b17023SJohn Marino if (comb2->rest)
209*e4b17023SJohn Marino aff_combination_add_elt (comb1, comb2->rest, double_int_one);
210*e4b17023SJohn Marino }
211*e4b17023SJohn Marino
212*e4b17023SJohn Marino /* Converts affine combination COMB to TYPE. */
213*e4b17023SJohn Marino
214*e4b17023SJohn Marino void
aff_combination_convert(aff_tree * comb,tree type)215*e4b17023SJohn Marino aff_combination_convert (aff_tree *comb, tree type)
216*e4b17023SJohn Marino {
217*e4b17023SJohn Marino unsigned i, j;
218*e4b17023SJohn Marino tree comb_type = comb->type;
219*e4b17023SJohn Marino
220*e4b17023SJohn Marino if (TYPE_PRECISION (type) > TYPE_PRECISION (comb_type))
221*e4b17023SJohn Marino {
222*e4b17023SJohn Marino tree val = fold_convert (type, aff_combination_to_tree (comb));
223*e4b17023SJohn Marino tree_to_aff_combination (val, type, comb);
224*e4b17023SJohn Marino return;
225*e4b17023SJohn Marino }
226*e4b17023SJohn Marino
227*e4b17023SJohn Marino comb->type = type;
228*e4b17023SJohn Marino if (comb->rest && !POINTER_TYPE_P (type))
229*e4b17023SJohn Marino comb->rest = fold_convert (type, comb->rest);
230*e4b17023SJohn Marino
231*e4b17023SJohn Marino if (TYPE_PRECISION (type) == TYPE_PRECISION (comb_type))
232*e4b17023SJohn Marino return;
233*e4b17023SJohn Marino
234*e4b17023SJohn Marino comb->offset = double_int_ext_for_comb (comb->offset, comb);
235*e4b17023SJohn Marino for (i = j = 0; i < comb->n; i++)
236*e4b17023SJohn Marino {
237*e4b17023SJohn Marino double_int new_coef = double_int_ext_for_comb (comb->elts[i].coef, comb);
238*e4b17023SJohn Marino if (double_int_zero_p (new_coef))
239*e4b17023SJohn Marino continue;
240*e4b17023SJohn Marino comb->elts[j].coef = new_coef;
241*e4b17023SJohn Marino comb->elts[j].val = fold_convert (type, comb->elts[i].val);
242*e4b17023SJohn Marino j++;
243*e4b17023SJohn Marino }
244*e4b17023SJohn Marino
245*e4b17023SJohn Marino comb->n = j;
246*e4b17023SJohn Marino if (comb->n < MAX_AFF_ELTS && comb->rest)
247*e4b17023SJohn Marino {
248*e4b17023SJohn Marino comb->elts[comb->n].coef = double_int_one;
249*e4b17023SJohn Marino comb->elts[comb->n].val = comb->rest;
250*e4b17023SJohn Marino comb->rest = NULL_TREE;
251*e4b17023SJohn Marino comb->n++;
252*e4b17023SJohn Marino }
253*e4b17023SJohn Marino }
254*e4b17023SJohn Marino
255*e4b17023SJohn Marino /* Splits EXPR into an affine combination of parts. */
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino void
tree_to_aff_combination(tree expr,tree type,aff_tree * comb)258*e4b17023SJohn Marino tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
259*e4b17023SJohn Marino {
260*e4b17023SJohn Marino aff_tree tmp;
261*e4b17023SJohn Marino enum tree_code code;
262*e4b17023SJohn Marino tree cst, core, toffset;
263*e4b17023SJohn Marino HOST_WIDE_INT bitpos, bitsize;
264*e4b17023SJohn Marino enum machine_mode mode;
265*e4b17023SJohn Marino int unsignedp, volatilep;
266*e4b17023SJohn Marino
267*e4b17023SJohn Marino STRIP_NOPS (expr);
268*e4b17023SJohn Marino
269*e4b17023SJohn Marino code = TREE_CODE (expr);
270*e4b17023SJohn Marino switch (code)
271*e4b17023SJohn Marino {
272*e4b17023SJohn Marino case INTEGER_CST:
273*e4b17023SJohn Marino aff_combination_const (comb, type, tree_to_double_int (expr));
274*e4b17023SJohn Marino return;
275*e4b17023SJohn Marino
276*e4b17023SJohn Marino case POINTER_PLUS_EXPR:
277*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
278*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
279*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
280*e4b17023SJohn Marino return;
281*e4b17023SJohn Marino
282*e4b17023SJohn Marino case PLUS_EXPR:
283*e4b17023SJohn Marino case MINUS_EXPR:
284*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
285*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
286*e4b17023SJohn Marino if (code == MINUS_EXPR)
287*e4b17023SJohn Marino aff_combination_scale (&tmp, double_int_minus_one);
288*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
289*e4b17023SJohn Marino return;
290*e4b17023SJohn Marino
291*e4b17023SJohn Marino case MULT_EXPR:
292*e4b17023SJohn Marino cst = TREE_OPERAND (expr, 1);
293*e4b17023SJohn Marino if (TREE_CODE (cst) != INTEGER_CST)
294*e4b17023SJohn Marino break;
295*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
296*e4b17023SJohn Marino aff_combination_scale (comb, tree_to_double_int (cst));
297*e4b17023SJohn Marino return;
298*e4b17023SJohn Marino
299*e4b17023SJohn Marino case NEGATE_EXPR:
300*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
301*e4b17023SJohn Marino aff_combination_scale (comb, double_int_minus_one);
302*e4b17023SJohn Marino return;
303*e4b17023SJohn Marino
304*e4b17023SJohn Marino case BIT_NOT_EXPR:
305*e4b17023SJohn Marino /* ~x = -x - 1 */
306*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
307*e4b17023SJohn Marino aff_combination_scale (comb, double_int_minus_one);
308*e4b17023SJohn Marino aff_combination_add_cst (comb, double_int_minus_one);
309*e4b17023SJohn Marino return;
310*e4b17023SJohn Marino
311*e4b17023SJohn Marino case ADDR_EXPR:
312*e4b17023SJohn Marino /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
313*e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
314*e4b17023SJohn Marino {
315*e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
316*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
317*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
318*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
319*e4b17023SJohn Marino return;
320*e4b17023SJohn Marino }
321*e4b17023SJohn Marino core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
322*e4b17023SJohn Marino &toffset, &mode, &unsignedp, &volatilep,
323*e4b17023SJohn Marino false);
324*e4b17023SJohn Marino if (bitpos % BITS_PER_UNIT != 0)
325*e4b17023SJohn Marino break;
326*e4b17023SJohn Marino aff_combination_const (comb, type,
327*e4b17023SJohn Marino uhwi_to_double_int (bitpos / BITS_PER_UNIT));
328*e4b17023SJohn Marino core = build_fold_addr_expr (core);
329*e4b17023SJohn Marino if (TREE_CODE (core) == ADDR_EXPR)
330*e4b17023SJohn Marino aff_combination_add_elt (comb, core, double_int_one);
331*e4b17023SJohn Marino else
332*e4b17023SJohn Marino {
333*e4b17023SJohn Marino tree_to_aff_combination (core, type, &tmp);
334*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
335*e4b17023SJohn Marino }
336*e4b17023SJohn Marino if (toffset)
337*e4b17023SJohn Marino {
338*e4b17023SJohn Marino tree_to_aff_combination (toffset, type, &tmp);
339*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
340*e4b17023SJohn Marino }
341*e4b17023SJohn Marino return;
342*e4b17023SJohn Marino
343*e4b17023SJohn Marino case MEM_REF:
344*e4b17023SJohn Marino if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
345*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (TREE_OPERAND (expr, 0), 0),
346*e4b17023SJohn Marino type, comb);
347*e4b17023SJohn Marino else if (integer_zerop (TREE_OPERAND (expr, 1)))
348*e4b17023SJohn Marino {
349*e4b17023SJohn Marino aff_combination_elt (comb, type, expr);
350*e4b17023SJohn Marino return;
351*e4b17023SJohn Marino }
352*e4b17023SJohn Marino else
353*e4b17023SJohn Marino aff_combination_elt (comb, type,
354*e4b17023SJohn Marino build2 (MEM_REF, TREE_TYPE (expr),
355*e4b17023SJohn Marino TREE_OPERAND (expr, 0),
356*e4b17023SJohn Marino build_int_cst
357*e4b17023SJohn Marino (TREE_TYPE (TREE_OPERAND (expr, 1)), 0)));
358*e4b17023SJohn Marino tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
359*e4b17023SJohn Marino aff_combination_add (comb, &tmp);
360*e4b17023SJohn Marino return;
361*e4b17023SJohn Marino
362*e4b17023SJohn Marino default:
363*e4b17023SJohn Marino break;
364*e4b17023SJohn Marino }
365*e4b17023SJohn Marino
366*e4b17023SJohn Marino aff_combination_elt (comb, type, expr);
367*e4b17023SJohn Marino }
368*e4b17023SJohn Marino
369*e4b17023SJohn Marino /* Creates EXPR + ELT * SCALE in TYPE. EXPR is taken from affine
370*e4b17023SJohn Marino combination COMB. */
371*e4b17023SJohn Marino
372*e4b17023SJohn Marino static tree
add_elt_to_tree(tree expr,tree type,tree elt,double_int scale,aff_tree * comb)373*e4b17023SJohn Marino add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
374*e4b17023SJohn Marino aff_tree *comb)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino enum tree_code code;
377*e4b17023SJohn Marino tree type1 = type;
378*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
379*e4b17023SJohn Marino type1 = sizetype;
380*e4b17023SJohn Marino
381*e4b17023SJohn Marino scale = double_int_ext_for_comb (scale, comb);
382*e4b17023SJohn Marino elt = fold_convert (type1, elt);
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino if (double_int_one_p (scale))
385*e4b17023SJohn Marino {
386*e4b17023SJohn Marino if (!expr)
387*e4b17023SJohn Marino return fold_convert (type, elt);
388*e4b17023SJohn Marino
389*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
390*e4b17023SJohn Marino return fold_build_pointer_plus (expr, elt);
391*e4b17023SJohn Marino return fold_build2 (PLUS_EXPR, type, expr, elt);
392*e4b17023SJohn Marino }
393*e4b17023SJohn Marino
394*e4b17023SJohn Marino if (double_int_minus_one_p (scale))
395*e4b17023SJohn Marino {
396*e4b17023SJohn Marino if (!expr)
397*e4b17023SJohn Marino return fold_convert (type, fold_build1 (NEGATE_EXPR, type1, elt));
398*e4b17023SJohn Marino
399*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
400*e4b17023SJohn Marino {
401*e4b17023SJohn Marino elt = fold_build1 (NEGATE_EXPR, type1, elt);
402*e4b17023SJohn Marino return fold_build_pointer_plus (expr, elt);
403*e4b17023SJohn Marino }
404*e4b17023SJohn Marino return fold_build2 (MINUS_EXPR, type, expr, elt);
405*e4b17023SJohn Marino }
406*e4b17023SJohn Marino
407*e4b17023SJohn Marino if (!expr)
408*e4b17023SJohn Marino return fold_convert (type,
409*e4b17023SJohn Marino fold_build2 (MULT_EXPR, type1, elt,
410*e4b17023SJohn Marino double_int_to_tree (type1, scale)));
411*e4b17023SJohn Marino
412*e4b17023SJohn Marino if (double_int_negative_p (scale))
413*e4b17023SJohn Marino {
414*e4b17023SJohn Marino code = MINUS_EXPR;
415*e4b17023SJohn Marino scale = double_int_neg (scale);
416*e4b17023SJohn Marino }
417*e4b17023SJohn Marino else
418*e4b17023SJohn Marino code = PLUS_EXPR;
419*e4b17023SJohn Marino
420*e4b17023SJohn Marino elt = fold_build2 (MULT_EXPR, type1, elt,
421*e4b17023SJohn Marino double_int_to_tree (type1, scale));
422*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
423*e4b17023SJohn Marino {
424*e4b17023SJohn Marino if (code == MINUS_EXPR)
425*e4b17023SJohn Marino elt = fold_build1 (NEGATE_EXPR, type1, elt);
426*e4b17023SJohn Marino return fold_build_pointer_plus (expr, elt);
427*e4b17023SJohn Marino }
428*e4b17023SJohn Marino return fold_build2 (code, type, expr, elt);
429*e4b17023SJohn Marino }
430*e4b17023SJohn Marino
431*e4b17023SJohn Marino /* Makes tree from the affine combination COMB. */
432*e4b17023SJohn Marino
433*e4b17023SJohn Marino tree
aff_combination_to_tree(aff_tree * comb)434*e4b17023SJohn Marino aff_combination_to_tree (aff_tree *comb)
435*e4b17023SJohn Marino {
436*e4b17023SJohn Marino tree type = comb->type;
437*e4b17023SJohn Marino tree expr = NULL_TREE;
438*e4b17023SJohn Marino unsigned i;
439*e4b17023SJohn Marino double_int off, sgn;
440*e4b17023SJohn Marino tree type1 = type;
441*e4b17023SJohn Marino if (POINTER_TYPE_P (type))
442*e4b17023SJohn Marino type1 = sizetype;
443*e4b17023SJohn Marino
444*e4b17023SJohn Marino gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
445*e4b17023SJohn Marino
446*e4b17023SJohn Marino for (i = 0; i < comb->n; i++)
447*e4b17023SJohn Marino expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef,
448*e4b17023SJohn Marino comb);
449*e4b17023SJohn Marino
450*e4b17023SJohn Marino if (comb->rest)
451*e4b17023SJohn Marino expr = add_elt_to_tree (expr, type, comb->rest, double_int_one, comb);
452*e4b17023SJohn Marino
453*e4b17023SJohn Marino /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
454*e4b17023SJohn Marino unsigned. */
455*e4b17023SJohn Marino if (double_int_negative_p (comb->offset))
456*e4b17023SJohn Marino {
457*e4b17023SJohn Marino off = double_int_neg (comb->offset);
458*e4b17023SJohn Marino sgn = double_int_minus_one;
459*e4b17023SJohn Marino }
460*e4b17023SJohn Marino else
461*e4b17023SJohn Marino {
462*e4b17023SJohn Marino off = comb->offset;
463*e4b17023SJohn Marino sgn = double_int_one;
464*e4b17023SJohn Marino }
465*e4b17023SJohn Marino return add_elt_to_tree (expr, type, double_int_to_tree (type1, off), sgn,
466*e4b17023SJohn Marino comb);
467*e4b17023SJohn Marino }
468*e4b17023SJohn Marino
469*e4b17023SJohn Marino /* Copies the tree elements of COMB to ensure that they are not shared. */
470*e4b17023SJohn Marino
471*e4b17023SJohn Marino void
unshare_aff_combination(aff_tree * comb)472*e4b17023SJohn Marino unshare_aff_combination (aff_tree *comb)
473*e4b17023SJohn Marino {
474*e4b17023SJohn Marino unsigned i;
475*e4b17023SJohn Marino
476*e4b17023SJohn Marino for (i = 0; i < comb->n; i++)
477*e4b17023SJohn Marino comb->elts[i].val = unshare_expr (comb->elts[i].val);
478*e4b17023SJohn Marino if (comb->rest)
479*e4b17023SJohn Marino comb->rest = unshare_expr (comb->rest);
480*e4b17023SJohn Marino }
481*e4b17023SJohn Marino
482*e4b17023SJohn Marino /* Remove M-th element from COMB. */
483*e4b17023SJohn Marino
484*e4b17023SJohn Marino void
aff_combination_remove_elt(aff_tree * comb,unsigned m)485*e4b17023SJohn Marino aff_combination_remove_elt (aff_tree *comb, unsigned m)
486*e4b17023SJohn Marino {
487*e4b17023SJohn Marino comb->n--;
488*e4b17023SJohn Marino if (m <= comb->n)
489*e4b17023SJohn Marino comb->elts[m] = comb->elts[comb->n];
490*e4b17023SJohn Marino if (comb->rest)
491*e4b17023SJohn Marino {
492*e4b17023SJohn Marino comb->elts[comb->n].coef = double_int_one;
493*e4b17023SJohn Marino comb->elts[comb->n].val = comb->rest;
494*e4b17023SJohn Marino comb->rest = NULL_TREE;
495*e4b17023SJohn Marino comb->n++;
496*e4b17023SJohn Marino }
497*e4b17023SJohn Marino }
498*e4b17023SJohn Marino
499*e4b17023SJohn Marino /* Adds C * COEF * VAL to R. VAL may be NULL, in that case only
500*e4b17023SJohn Marino C * COEF is added to R. */
501*e4b17023SJohn Marino
502*e4b17023SJohn Marino
503*e4b17023SJohn Marino static void
aff_combination_add_product(aff_tree * c,double_int coef,tree val,aff_tree * r)504*e4b17023SJohn Marino aff_combination_add_product (aff_tree *c, double_int coef, tree val,
505*e4b17023SJohn Marino aff_tree *r)
506*e4b17023SJohn Marino {
507*e4b17023SJohn Marino unsigned i;
508*e4b17023SJohn Marino tree aval, type;
509*e4b17023SJohn Marino
510*e4b17023SJohn Marino for (i = 0; i < c->n; i++)
511*e4b17023SJohn Marino {
512*e4b17023SJohn Marino aval = c->elts[i].val;
513*e4b17023SJohn Marino if (val)
514*e4b17023SJohn Marino {
515*e4b17023SJohn Marino type = TREE_TYPE (aval);
516*e4b17023SJohn Marino aval = fold_build2 (MULT_EXPR, type, aval,
517*e4b17023SJohn Marino fold_convert (type, val));
518*e4b17023SJohn Marino }
519*e4b17023SJohn Marino
520*e4b17023SJohn Marino aff_combination_add_elt (r, aval,
521*e4b17023SJohn Marino double_int_mul (coef, c->elts[i].coef));
522*e4b17023SJohn Marino }
523*e4b17023SJohn Marino
524*e4b17023SJohn Marino if (c->rest)
525*e4b17023SJohn Marino {
526*e4b17023SJohn Marino aval = c->rest;
527*e4b17023SJohn Marino if (val)
528*e4b17023SJohn Marino {
529*e4b17023SJohn Marino type = TREE_TYPE (aval);
530*e4b17023SJohn Marino aval = fold_build2 (MULT_EXPR, type, aval,
531*e4b17023SJohn Marino fold_convert (type, val));
532*e4b17023SJohn Marino }
533*e4b17023SJohn Marino
534*e4b17023SJohn Marino aff_combination_add_elt (r, aval, coef);
535*e4b17023SJohn Marino }
536*e4b17023SJohn Marino
537*e4b17023SJohn Marino if (val)
538*e4b17023SJohn Marino aff_combination_add_elt (r, val,
539*e4b17023SJohn Marino double_int_mul (coef, c->offset));
540*e4b17023SJohn Marino else
541*e4b17023SJohn Marino aff_combination_add_cst (r, double_int_mul (coef, c->offset));
542*e4b17023SJohn Marino }
543*e4b17023SJohn Marino
544*e4b17023SJohn Marino /* Multiplies C1 by C2, storing the result to R */
545*e4b17023SJohn Marino
546*e4b17023SJohn Marino void
aff_combination_mult(aff_tree * c1,aff_tree * c2,aff_tree * r)547*e4b17023SJohn Marino aff_combination_mult (aff_tree *c1, aff_tree *c2, aff_tree *r)
548*e4b17023SJohn Marino {
549*e4b17023SJohn Marino unsigned i;
550*e4b17023SJohn Marino gcc_assert (TYPE_PRECISION (c1->type) == TYPE_PRECISION (c2->type));
551*e4b17023SJohn Marino
552*e4b17023SJohn Marino aff_combination_zero (r, c1->type);
553*e4b17023SJohn Marino
554*e4b17023SJohn Marino for (i = 0; i < c2->n; i++)
555*e4b17023SJohn Marino aff_combination_add_product (c1, c2->elts[i].coef, c2->elts[i].val, r);
556*e4b17023SJohn Marino if (c2->rest)
557*e4b17023SJohn Marino aff_combination_add_product (c1, double_int_one, c2->rest, r);
558*e4b17023SJohn Marino aff_combination_add_product (c1, c2->offset, NULL, r);
559*e4b17023SJohn Marino }
560*e4b17023SJohn Marino
561*e4b17023SJohn Marino /* Returns the element of COMB whose value is VAL, or NULL if no such
562*e4b17023SJohn Marino element exists. If IDX is not NULL, it is set to the index of VAL in
563*e4b17023SJohn Marino COMB. */
564*e4b17023SJohn Marino
565*e4b17023SJohn Marino static struct aff_comb_elt *
aff_combination_find_elt(aff_tree * comb,tree val,unsigned * idx)566*e4b17023SJohn Marino aff_combination_find_elt (aff_tree *comb, tree val, unsigned *idx)
567*e4b17023SJohn Marino {
568*e4b17023SJohn Marino unsigned i;
569*e4b17023SJohn Marino
570*e4b17023SJohn Marino for (i = 0; i < comb->n; i++)
571*e4b17023SJohn Marino if (operand_equal_p (comb->elts[i].val, val, 0))
572*e4b17023SJohn Marino {
573*e4b17023SJohn Marino if (idx)
574*e4b17023SJohn Marino *idx = i;
575*e4b17023SJohn Marino
576*e4b17023SJohn Marino return &comb->elts[i];
577*e4b17023SJohn Marino }
578*e4b17023SJohn Marino
579*e4b17023SJohn Marino return NULL;
580*e4b17023SJohn Marino }
581*e4b17023SJohn Marino
582*e4b17023SJohn Marino /* Element of the cache that maps ssa name NAME to its expanded form
583*e4b17023SJohn Marino as an affine expression EXPANSION. */
584*e4b17023SJohn Marino
585*e4b17023SJohn Marino struct name_expansion
586*e4b17023SJohn Marino {
587*e4b17023SJohn Marino aff_tree expansion;
588*e4b17023SJohn Marino
589*e4b17023SJohn Marino /* True if the expansion for the name is just being generated. */
590*e4b17023SJohn Marino unsigned in_progress : 1;
591*e4b17023SJohn Marino };
592*e4b17023SJohn Marino
593*e4b17023SJohn Marino /* Expands SSA names in COMB recursively. CACHE is used to cache the
594*e4b17023SJohn Marino results. */
595*e4b17023SJohn Marino
596*e4b17023SJohn Marino void
aff_combination_expand(aff_tree * comb ATTRIBUTE_UNUSED,struct pointer_map_t ** cache ATTRIBUTE_UNUSED)597*e4b17023SJohn Marino aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
598*e4b17023SJohn Marino struct pointer_map_t **cache ATTRIBUTE_UNUSED)
599*e4b17023SJohn Marino {
600*e4b17023SJohn Marino unsigned i;
601*e4b17023SJohn Marino aff_tree to_add, current, curre;
602*e4b17023SJohn Marino tree e, rhs;
603*e4b17023SJohn Marino gimple def;
604*e4b17023SJohn Marino double_int scale;
605*e4b17023SJohn Marino void **slot;
606*e4b17023SJohn Marino struct name_expansion *exp;
607*e4b17023SJohn Marino
608*e4b17023SJohn Marino aff_combination_zero (&to_add, comb->type);
609*e4b17023SJohn Marino for (i = 0; i < comb->n; i++)
610*e4b17023SJohn Marino {
611*e4b17023SJohn Marino tree type, name;
612*e4b17023SJohn Marino enum tree_code code;
613*e4b17023SJohn Marino
614*e4b17023SJohn Marino e = comb->elts[i].val;
615*e4b17023SJohn Marino type = TREE_TYPE (e);
616*e4b17023SJohn Marino name = e;
617*e4b17023SJohn Marino /* Look through some conversions. */
618*e4b17023SJohn Marino if (TREE_CODE (e) == NOP_EXPR
619*e4b17023SJohn Marino && (TYPE_PRECISION (type)
620*e4b17023SJohn Marino >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (e, 0)))))
621*e4b17023SJohn Marino name = TREE_OPERAND (e, 0);
622*e4b17023SJohn Marino if (TREE_CODE (name) != SSA_NAME)
623*e4b17023SJohn Marino continue;
624*e4b17023SJohn Marino def = SSA_NAME_DEF_STMT (name);
625*e4b17023SJohn Marino if (!is_gimple_assign (def) || gimple_assign_lhs (def) != name)
626*e4b17023SJohn Marino continue;
627*e4b17023SJohn Marino
628*e4b17023SJohn Marino code = gimple_assign_rhs_code (def);
629*e4b17023SJohn Marino if (code != SSA_NAME
630*e4b17023SJohn Marino && !IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
631*e4b17023SJohn Marino && (get_gimple_rhs_class (code) != GIMPLE_SINGLE_RHS
632*e4b17023SJohn Marino || !is_gimple_min_invariant (gimple_assign_rhs1 (def))))
633*e4b17023SJohn Marino continue;
634*e4b17023SJohn Marino
635*e4b17023SJohn Marino /* We do not know whether the reference retains its value at the
636*e4b17023SJohn Marino place where the expansion is used. */
637*e4b17023SJohn Marino if (TREE_CODE_CLASS (code) == tcc_reference)
638*e4b17023SJohn Marino continue;
639*e4b17023SJohn Marino
640*e4b17023SJohn Marino if (!*cache)
641*e4b17023SJohn Marino *cache = pointer_map_create ();
642*e4b17023SJohn Marino slot = pointer_map_insert (*cache, e);
643*e4b17023SJohn Marino exp = (struct name_expansion *) *slot;
644*e4b17023SJohn Marino
645*e4b17023SJohn Marino if (!exp)
646*e4b17023SJohn Marino {
647*e4b17023SJohn Marino exp = XNEW (struct name_expansion);
648*e4b17023SJohn Marino exp->in_progress = 1;
649*e4b17023SJohn Marino *slot = exp;
650*e4b17023SJohn Marino /* In principle this is a generally valid folding, but
651*e4b17023SJohn Marino it is not unconditionally an optimization, so do it
652*e4b17023SJohn Marino here and not in fold_unary. */
653*e4b17023SJohn Marino /* Convert (T1)(X *+- CST) into (T1)X *+- (T1)CST if T1 is wider
654*e4b17023SJohn Marino than the type of X and overflow for the type of X is
655*e4b17023SJohn Marino undefined. */
656*e4b17023SJohn Marino if (e != name
657*e4b17023SJohn Marino && INTEGRAL_TYPE_P (type)
658*e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (name))
659*e4b17023SJohn Marino && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (name))
660*e4b17023SJohn Marino && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (name))
661*e4b17023SJohn Marino && (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR)
662*e4b17023SJohn Marino && TREE_CODE (gimple_assign_rhs2 (def)) == INTEGER_CST)
663*e4b17023SJohn Marino rhs = fold_build2 (code, type,
664*e4b17023SJohn Marino fold_convert (type, gimple_assign_rhs1 (def)),
665*e4b17023SJohn Marino fold_convert (type, gimple_assign_rhs2 (def)));
666*e4b17023SJohn Marino else
667*e4b17023SJohn Marino {
668*e4b17023SJohn Marino rhs = gimple_assign_rhs_to_tree (def);
669*e4b17023SJohn Marino if (e != name)
670*e4b17023SJohn Marino rhs = fold_convert (type, rhs);
671*e4b17023SJohn Marino }
672*e4b17023SJohn Marino tree_to_aff_combination_expand (rhs, comb->type, ¤t, cache);
673*e4b17023SJohn Marino exp->expansion = current;
674*e4b17023SJohn Marino exp->in_progress = 0;
675*e4b17023SJohn Marino }
676*e4b17023SJohn Marino else
677*e4b17023SJohn Marino {
678*e4b17023SJohn Marino /* Since we follow the definitions in the SSA form, we should not
679*e4b17023SJohn Marino enter a cycle unless we pass through a phi node. */
680*e4b17023SJohn Marino gcc_assert (!exp->in_progress);
681*e4b17023SJohn Marino current = exp->expansion;
682*e4b17023SJohn Marino }
683*e4b17023SJohn Marino
684*e4b17023SJohn Marino /* Accumulate the new terms to TO_ADD, so that we do not modify
685*e4b17023SJohn Marino COMB while traversing it; include the term -coef * E, to remove
686*e4b17023SJohn Marino it from COMB. */
687*e4b17023SJohn Marino scale = comb->elts[i].coef;
688*e4b17023SJohn Marino aff_combination_zero (&curre, comb->type);
689*e4b17023SJohn Marino aff_combination_add_elt (&curre, e, double_int_neg (scale));
690*e4b17023SJohn Marino aff_combination_scale (¤t, scale);
691*e4b17023SJohn Marino aff_combination_add (&to_add, ¤t);
692*e4b17023SJohn Marino aff_combination_add (&to_add, &curre);
693*e4b17023SJohn Marino }
694*e4b17023SJohn Marino aff_combination_add (comb, &to_add);
695*e4b17023SJohn Marino }
696*e4b17023SJohn Marino
697*e4b17023SJohn Marino /* Similar to tree_to_aff_combination, but follows SSA name definitions
698*e4b17023SJohn Marino and expands them recursively. CACHE is used to cache the expansions
699*e4b17023SJohn Marino of the ssa names, to avoid exponential time complexity for cases
700*e4b17023SJohn Marino like
701*e4b17023SJohn Marino
702*e4b17023SJohn Marino a1 = a0 + a0;
703*e4b17023SJohn Marino a2 = a1 + a1;
704*e4b17023SJohn Marino a3 = a2 + a2;
705*e4b17023SJohn Marino ... */
706*e4b17023SJohn Marino
707*e4b17023SJohn Marino void
tree_to_aff_combination_expand(tree expr,tree type,aff_tree * comb,struct pointer_map_t ** cache)708*e4b17023SJohn Marino tree_to_aff_combination_expand (tree expr, tree type, aff_tree *comb,
709*e4b17023SJohn Marino struct pointer_map_t **cache)
710*e4b17023SJohn Marino {
711*e4b17023SJohn Marino tree_to_aff_combination (expr, type, comb);
712*e4b17023SJohn Marino aff_combination_expand (comb, cache);
713*e4b17023SJohn Marino }
714*e4b17023SJohn Marino
715*e4b17023SJohn Marino /* Frees memory occupied by struct name_expansion in *VALUE. Callback for
716*e4b17023SJohn Marino pointer_map_traverse. */
717*e4b17023SJohn Marino
718*e4b17023SJohn Marino static bool
free_name_expansion(const void * key ATTRIBUTE_UNUSED,void ** value,void * data ATTRIBUTE_UNUSED)719*e4b17023SJohn Marino free_name_expansion (const void *key ATTRIBUTE_UNUSED, void **value,
720*e4b17023SJohn Marino void *data ATTRIBUTE_UNUSED)
721*e4b17023SJohn Marino {
722*e4b17023SJohn Marino struct name_expansion *const exp = (struct name_expansion *) *value;
723*e4b17023SJohn Marino
724*e4b17023SJohn Marino free (exp);
725*e4b17023SJohn Marino return true;
726*e4b17023SJohn Marino }
727*e4b17023SJohn Marino
728*e4b17023SJohn Marino /* Frees memory allocated for the CACHE used by
729*e4b17023SJohn Marino tree_to_aff_combination_expand. */
730*e4b17023SJohn Marino
731*e4b17023SJohn Marino void
free_affine_expand_cache(struct pointer_map_t ** cache)732*e4b17023SJohn Marino free_affine_expand_cache (struct pointer_map_t **cache)
733*e4b17023SJohn Marino {
734*e4b17023SJohn Marino if (!*cache)
735*e4b17023SJohn Marino return;
736*e4b17023SJohn Marino
737*e4b17023SJohn Marino pointer_map_traverse (*cache, free_name_expansion, NULL);
738*e4b17023SJohn Marino pointer_map_destroy (*cache);
739*e4b17023SJohn Marino *cache = NULL;
740*e4b17023SJohn Marino }
741*e4b17023SJohn Marino
742*e4b17023SJohn Marino /* If VAL != CST * DIV for any constant CST, returns false.
743*e4b17023SJohn Marino Otherwise, if VAL != 0 (and hence CST != 0), and *MULT_SET is true,
744*e4b17023SJohn Marino additionally compares CST and MULT, and if they are different,
745*e4b17023SJohn Marino returns false. Finally, if neither of these two cases occur,
746*e4b17023SJohn Marino true is returned, and if CST != 0, CST is stored to MULT and
747*e4b17023SJohn Marino MULT_SET is set to true. */
748*e4b17023SJohn Marino
749*e4b17023SJohn Marino static bool
double_int_constant_multiple_p(double_int val,double_int div,bool * mult_set,double_int * mult)750*e4b17023SJohn Marino double_int_constant_multiple_p (double_int val, double_int div,
751*e4b17023SJohn Marino bool *mult_set, double_int *mult)
752*e4b17023SJohn Marino {
753*e4b17023SJohn Marino double_int rem, cst;
754*e4b17023SJohn Marino
755*e4b17023SJohn Marino if (double_int_zero_p (val))
756*e4b17023SJohn Marino return true;
757*e4b17023SJohn Marino
758*e4b17023SJohn Marino if (double_int_zero_p (div))
759*e4b17023SJohn Marino return false;
760*e4b17023SJohn Marino
761*e4b17023SJohn Marino cst = double_int_sdivmod (val, div, FLOOR_DIV_EXPR, &rem);
762*e4b17023SJohn Marino if (!double_int_zero_p (rem))
763*e4b17023SJohn Marino return false;
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino if (*mult_set && !double_int_equal_p (*mult, cst))
766*e4b17023SJohn Marino return false;
767*e4b17023SJohn Marino
768*e4b17023SJohn Marino *mult_set = true;
769*e4b17023SJohn Marino *mult = cst;
770*e4b17023SJohn Marino return true;
771*e4b17023SJohn Marino }
772*e4b17023SJohn Marino
773*e4b17023SJohn Marino /* Returns true if VAL = X * DIV for some constant X. If this is the case,
774*e4b17023SJohn Marino X is stored to MULT. */
775*e4b17023SJohn Marino
776*e4b17023SJohn Marino bool
aff_combination_constant_multiple_p(aff_tree * val,aff_tree * div,double_int * mult)777*e4b17023SJohn Marino aff_combination_constant_multiple_p (aff_tree *val, aff_tree *div,
778*e4b17023SJohn Marino double_int *mult)
779*e4b17023SJohn Marino {
780*e4b17023SJohn Marino bool mult_set = false;
781*e4b17023SJohn Marino unsigned i;
782*e4b17023SJohn Marino
783*e4b17023SJohn Marino if (val->n == 0 && double_int_zero_p (val->offset))
784*e4b17023SJohn Marino {
785*e4b17023SJohn Marino *mult = double_int_zero;
786*e4b17023SJohn Marino return true;
787*e4b17023SJohn Marino }
788*e4b17023SJohn Marino if (val->n != div->n)
789*e4b17023SJohn Marino return false;
790*e4b17023SJohn Marino
791*e4b17023SJohn Marino if (val->rest || div->rest)
792*e4b17023SJohn Marino return false;
793*e4b17023SJohn Marino
794*e4b17023SJohn Marino if (!double_int_constant_multiple_p (val->offset, div->offset,
795*e4b17023SJohn Marino &mult_set, mult))
796*e4b17023SJohn Marino return false;
797*e4b17023SJohn Marino
798*e4b17023SJohn Marino for (i = 0; i < div->n; i++)
799*e4b17023SJohn Marino {
800*e4b17023SJohn Marino struct aff_comb_elt *elt
801*e4b17023SJohn Marino = aff_combination_find_elt (val, div->elts[i].val, NULL);
802*e4b17023SJohn Marino if (!elt)
803*e4b17023SJohn Marino return false;
804*e4b17023SJohn Marino if (!double_int_constant_multiple_p (elt->coef, div->elts[i].coef,
805*e4b17023SJohn Marino &mult_set, mult))
806*e4b17023SJohn Marino return false;
807*e4b17023SJohn Marino }
808*e4b17023SJohn Marino
809*e4b17023SJohn Marino gcc_assert (mult_set);
810*e4b17023SJohn Marino return true;
811*e4b17023SJohn Marino }
812*e4b17023SJohn Marino
813*e4b17023SJohn Marino /* Prints the affine VAL to the FILE. */
814*e4b17023SJohn Marino
815*e4b17023SJohn Marino void
print_aff(FILE * file,aff_tree * val)816*e4b17023SJohn Marino print_aff (FILE *file, aff_tree *val)
817*e4b17023SJohn Marino {
818*e4b17023SJohn Marino unsigned i;
819*e4b17023SJohn Marino bool uns = TYPE_UNSIGNED (val->type);
820*e4b17023SJohn Marino if (POINTER_TYPE_P (val->type))
821*e4b17023SJohn Marino uns = false;
822*e4b17023SJohn Marino fprintf (file, "{\n type = ");
823*e4b17023SJohn Marino print_generic_expr (file, val->type, TDF_VOPS|TDF_MEMSYMS);
824*e4b17023SJohn Marino fprintf (file, "\n offset = ");
825*e4b17023SJohn Marino dump_double_int (file, val->offset, uns);
826*e4b17023SJohn Marino if (val->n > 0)
827*e4b17023SJohn Marino {
828*e4b17023SJohn Marino fprintf (file, "\n elements = {\n");
829*e4b17023SJohn Marino for (i = 0; i < val->n; i++)
830*e4b17023SJohn Marino {
831*e4b17023SJohn Marino fprintf (file, " [%d] = ", i);
832*e4b17023SJohn Marino print_generic_expr (file, val->elts[i].val, TDF_VOPS|TDF_MEMSYMS);
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino fprintf (file, " * ");
835*e4b17023SJohn Marino dump_double_int (file, val->elts[i].coef, uns);
836*e4b17023SJohn Marino if (i != val->n - 1)
837*e4b17023SJohn Marino fprintf (file, ", \n");
838*e4b17023SJohn Marino }
839*e4b17023SJohn Marino fprintf (file, "\n }");
840*e4b17023SJohn Marino }
841*e4b17023SJohn Marino if (val->rest)
842*e4b17023SJohn Marino {
843*e4b17023SJohn Marino fprintf (file, "\n rest = ");
844*e4b17023SJohn Marino print_generic_expr (file, val->rest, TDF_VOPS|TDF_MEMSYMS);
845*e4b17023SJohn Marino }
846*e4b17023SJohn Marino fprintf (file, "\n}");
847*e4b17023SJohn Marino }
848*e4b17023SJohn Marino
849*e4b17023SJohn Marino /* Prints the affine VAL to the standard error, used for debugging. */
850*e4b17023SJohn Marino
851*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_aff(aff_tree * val)852*e4b17023SJohn Marino debug_aff (aff_tree *val)
853*e4b17023SJohn Marino {
854*e4b17023SJohn Marino print_aff (stderr, val);
855*e4b17023SJohn Marino fprintf (stderr, "\n");
856*e4b17023SJohn Marino }
857*e4b17023SJohn Marino
858*e4b17023SJohn Marino /* Returns address of the reference REF in ADDR. The size of the accessed
859*e4b17023SJohn Marino location is stored to SIZE. */
860*e4b17023SJohn Marino
861*e4b17023SJohn Marino void
get_inner_reference_aff(tree ref,aff_tree * addr,double_int * size)862*e4b17023SJohn Marino get_inner_reference_aff (tree ref, aff_tree *addr, double_int *size)
863*e4b17023SJohn Marino {
864*e4b17023SJohn Marino HOST_WIDE_INT bitsize, bitpos;
865*e4b17023SJohn Marino tree toff;
866*e4b17023SJohn Marino enum machine_mode mode;
867*e4b17023SJohn Marino int uns, vol;
868*e4b17023SJohn Marino aff_tree tmp;
869*e4b17023SJohn Marino tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode,
870*e4b17023SJohn Marino &uns, &vol, false);
871*e4b17023SJohn Marino tree base_addr = build_fold_addr_expr (base);
872*e4b17023SJohn Marino
873*e4b17023SJohn Marino /* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT. */
874*e4b17023SJohn Marino
875*e4b17023SJohn Marino tree_to_aff_combination (base_addr, sizetype, addr);
876*e4b17023SJohn Marino
877*e4b17023SJohn Marino if (toff)
878*e4b17023SJohn Marino {
879*e4b17023SJohn Marino tree_to_aff_combination (toff, sizetype, &tmp);
880*e4b17023SJohn Marino aff_combination_add (addr, &tmp);
881*e4b17023SJohn Marino }
882*e4b17023SJohn Marino
883*e4b17023SJohn Marino aff_combination_const (&tmp, sizetype,
884*e4b17023SJohn Marino shwi_to_double_int (bitpos / BITS_PER_UNIT));
885*e4b17023SJohn Marino aff_combination_add (addr, &tmp);
886*e4b17023SJohn Marino
887*e4b17023SJohn Marino *size = shwi_to_double_int ((bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
888*e4b17023SJohn Marino }
889*e4b17023SJohn Marino
890*e4b17023SJohn Marino /* Returns true if a region of size SIZE1 at position 0 and a region of
891*e4b17023SJohn Marino size SIZE2 at position DIFF cannot overlap. */
892*e4b17023SJohn Marino
893*e4b17023SJohn Marino bool
aff_comb_cannot_overlap_p(aff_tree * diff,double_int size1,double_int size2)894*e4b17023SJohn Marino aff_comb_cannot_overlap_p (aff_tree *diff, double_int size1, double_int size2)
895*e4b17023SJohn Marino {
896*e4b17023SJohn Marino double_int d, bound;
897*e4b17023SJohn Marino
898*e4b17023SJohn Marino /* Unless the difference is a constant, we fail. */
899*e4b17023SJohn Marino if (diff->n != 0)
900*e4b17023SJohn Marino return false;
901*e4b17023SJohn Marino
902*e4b17023SJohn Marino d = diff->offset;
903*e4b17023SJohn Marino if (double_int_negative_p (d))
904*e4b17023SJohn Marino {
905*e4b17023SJohn Marino /* The second object is before the first one, we succeed if the last
906*e4b17023SJohn Marino element of the second object is before the start of the first one. */
907*e4b17023SJohn Marino bound = double_int_add (d, double_int_add (size2, double_int_minus_one));
908*e4b17023SJohn Marino return double_int_negative_p (bound);
909*e4b17023SJohn Marino }
910*e4b17023SJohn Marino else
911*e4b17023SJohn Marino {
912*e4b17023SJohn Marino /* We succeed if the second object starts after the first one ends. */
913*e4b17023SJohn Marino return double_int_scmp (size1, d) <= 0;
914*e4b17023SJohn Marino }
915*e4b17023SJohn Marino }
916*e4b17023SJohn Marino
917