OSDN Git Service

2007-01-08 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-affine.c
1 /* Operations with affine combinations of trees.
2    Copyright (C) 2005 Free Software Foundation, Inc.
3    
4 This file is part of GCC.
5    
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10    
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15    
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "rtl.h"
27 #include "tm_p.h"
28 #include "hard-reg-set.h"
29 #include "output.h"
30 #include "diagnostic.h"
31 #include "tree-dump.h"
32 #include "tree-affine.h"
33
34 /* Extends CST as appropriate for the affine combinations COMB.  */
35
36 double_int
37 double_int_ext_for_comb (double_int cst, aff_tree *comb)
38 {
39   return double_int_sext (cst, TYPE_PRECISION (comb->type));
40 }
41
42 /* Initializes affine combination COMB so that its value is zero in TYPE.  */
43
44 static void
45 aff_combination_zero (aff_tree *comb, tree type)
46 {
47   comb->type = type;
48   comb->offset = double_int_zero;
49   comb->n = 0;
50   comb->rest = NULL_TREE;
51 }
52
53 /* Sets COMB to CST.  */
54
55 void
56 aff_combination_const (aff_tree *comb, tree type, double_int cst)
57 {
58   aff_combination_zero (comb, type);
59   comb->offset = double_int_ext_for_comb (cst, comb);
60 }
61
62 /* Sets COMB to single element ELT.  */
63
64 void
65 aff_combination_elt (aff_tree *comb, tree type, tree elt)
66 {
67   aff_combination_zero (comb, type);
68
69   comb->n = 1;
70   comb->elts[0].val = elt;
71   comb->elts[0].coef = double_int_one;
72 }
73
74 /* Scales COMB by SCALE.  */
75
76 void
77 aff_combination_scale (aff_tree *comb, double_int scale)
78 {
79   unsigned i, j;
80
81   scale = double_int_ext_for_comb (scale, comb);
82   if (double_int_one_p (scale))
83     return;
84
85   if (double_int_zero_p (scale))
86     {
87       aff_combination_zero (comb, comb->type);
88       return;
89     }
90
91   comb->offset
92     = double_int_ext_for_comb (double_int_mul (scale, comb->offset), comb);
93   for (i = 0, j = 0; i < comb->n; i++)
94     {
95       double_int new_coef;
96
97       new_coef
98         = double_int_ext_for_comb (double_int_mul (scale, comb->elts[i].coef),
99                                    comb);
100       /* A coefficient may become zero due to overflow.  Remove the zero
101          elements.  */
102       if (double_int_zero_p (new_coef))
103         continue;
104       comb->elts[j].coef = new_coef;
105       comb->elts[j].val = comb->elts[i].val;
106       j++;
107     }
108   comb->n = j;
109
110   if (comb->rest)
111     {
112       if (comb->n < MAX_AFF_ELTS)
113         {
114           comb->elts[comb->n].coef = scale;
115           comb->elts[comb->n].val = comb->rest;
116           comb->rest = NULL_TREE;
117           comb->n++;
118         }
119       else
120         comb->rest = fold_build2 (MULT_EXPR, comb->type, comb->rest, 
121                                   double_int_to_tree (comb->type, scale));
122     }
123 }
124
125 /* Adds ELT * SCALE to COMB.  */
126
127 void
128 aff_combination_add_elt (aff_tree *comb, tree elt, double_int scale)
129 {
130   unsigned i;
131
132   scale = double_int_ext_for_comb (scale, comb);
133   if (double_int_zero_p (scale))
134     return;
135
136   for (i = 0; i < comb->n; i++)
137     if (operand_equal_p (comb->elts[i].val, elt, 0))
138       {
139         double_int new_coef;
140
141         new_coef = double_int_add (comb->elts[i].coef, scale);
142         new_coef = double_int_ext_for_comb (new_coef, comb);
143         if (!double_int_zero_p (new_coef))
144           {
145             comb->elts[i].coef = new_coef;
146             return;
147           }
148
149         comb->n--;
150         comb->elts[i] = comb->elts[comb->n];
151
152         if (comb->rest)
153           {
154             gcc_assert (comb->n == MAX_AFF_ELTS - 1);
155             comb->elts[comb->n].coef = double_int_one;
156             comb->elts[comb->n].val = comb->rest;
157             comb->rest = NULL_TREE;
158             comb->n++;
159           }
160         return;
161       }
162   if (comb->n < MAX_AFF_ELTS)
163     {
164       comb->elts[comb->n].coef = scale;
165       comb->elts[comb->n].val = elt;
166       comb->n++;
167       return;
168     }
169
170   if (double_int_one_p (scale))
171     elt = fold_convert (comb->type, elt);
172   else
173     elt = fold_build2 (MULT_EXPR, comb->type,
174                        fold_convert (comb->type, elt),
175                        double_int_to_tree (comb->type, scale)); 
176
177   if (comb->rest)
178     comb->rest = fold_build2 (PLUS_EXPR, comb->type, comb->rest, elt);
179   else
180     comb->rest = elt;
181 }
182
183 /* Adds COMB2 to COMB1.  */
184
185 void
186 aff_combination_add (aff_tree *comb1, aff_tree *comb2)
187 {
188   unsigned i;
189
190   comb1->offset
191     = double_int_ext_for_comb (double_int_add (comb1->offset, comb2->offset),
192                                comb1);
193   for (i = 0; i < comb2->n; i++)
194     aff_combination_add_elt (comb1, comb2->elts[i].val, comb2->elts[i].coef);
195   if (comb2->rest)
196     aff_combination_add_elt (comb1, comb2->rest, double_int_one);
197 }
198
199 /* Converts affine combination COMB to TYPE.  */
200
201 void
202 aff_combination_convert (aff_tree *comb, tree type)
203 {
204   unsigned i, j;
205   tree comb_type = comb->type;
206
207   gcc_assert (TYPE_PRECISION (type) <= TYPE_PRECISION (comb_type));
208   comb->type = type;
209   if (comb->rest)
210     comb->rest = fold_convert (type, comb->rest);
211
212   if (TYPE_PRECISION (type) == TYPE_PRECISION (comb_type))
213     return;
214
215   comb->offset = double_int_ext_for_comb (comb->offset, comb);
216   for (i = j = 0; i < comb->n; i++)
217     {
218       double_int new_coef = double_int_ext_for_comb (comb->elts[i].coef, comb);
219       if (double_int_zero_p (new_coef))
220         continue;
221       comb->elts[j].coef = new_coef;
222       comb->elts[j].val = fold_convert (type, comb->elts[i].val);
223       j++;
224     }
225
226   comb->n = j;
227   if (comb->n < MAX_AFF_ELTS && comb->rest)
228     {
229       comb->elts[comb->n].coef = double_int_one;
230       comb->elts[comb->n].val = comb->rest;
231       comb->rest = NULL_TREE;
232       comb->n++;
233     }
234 }
235
236 /* Splits EXPR into an affine combination of parts.  */
237
238 void
239 tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
240 {
241   aff_tree tmp;
242   enum tree_code code;
243   tree cst, core, toffset;
244   HOST_WIDE_INT bitpos, bitsize;
245   enum machine_mode mode;
246   int unsignedp, volatilep;
247
248   STRIP_NOPS (expr);
249
250   code = TREE_CODE (expr);
251   switch (code)
252     {
253     case INTEGER_CST:
254       aff_combination_const (comb, type, tree_to_double_int (expr));
255       return;
256
257     case PLUS_EXPR:
258     case MINUS_EXPR:
259       tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
260       tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
261       if (code == MINUS_EXPR)
262         aff_combination_scale (&tmp, double_int_minus_one);
263       aff_combination_add (comb, &tmp);
264       return;
265
266     case MULT_EXPR:
267       cst = TREE_OPERAND (expr, 1);
268       if (TREE_CODE (cst) != INTEGER_CST)
269         break;
270       tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
271       aff_combination_scale (comb, tree_to_double_int (cst));
272       return;
273
274     case NEGATE_EXPR:
275       tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
276       aff_combination_scale (comb, double_int_minus_one);
277       return;
278
279     case ADDR_EXPR:
280       core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
281                                   &toffset, &mode, &unsignedp, &volatilep,
282                                   false);
283       if (bitpos % BITS_PER_UNIT != 0)
284         break;
285       aff_combination_const (comb, type,
286                              uhwi_to_double_int (bitpos / BITS_PER_UNIT));
287       core = build_fold_addr_expr (core);
288       if (TREE_CODE (core) == ADDR_EXPR)
289         aff_combination_add_elt (comb, core, double_int_one);
290       else
291         {
292           tree_to_aff_combination (core, type, &tmp);
293           aff_combination_add (comb, &tmp);
294         }
295       if (toffset)
296         {
297           tree_to_aff_combination (toffset, type, &tmp);
298           aff_combination_add (comb, &tmp);
299         }
300       return;
301
302     default:
303       break;
304     }
305
306   aff_combination_elt (comb, type, expr);
307 }
308
309 /* Creates EXPR + ELT * SCALE in TYPE.  EXPR is taken from affine
310    combination COMB.  */
311
312 static tree
313 add_elt_to_tree (tree expr, tree type, tree elt, double_int scale,
314                  aff_tree *comb)
315 {
316   enum tree_code code;
317
318   scale = double_int_ext_for_comb (scale, comb);
319   elt = fold_convert (type, elt);
320
321   if (double_int_one_p (scale))
322     {
323       if (!expr)
324         return elt;
325
326       return fold_build2 (PLUS_EXPR, type, expr, elt);
327     }
328
329   if (double_int_minus_one_p (scale))
330     {
331       if (!expr)
332         return fold_build1 (NEGATE_EXPR, type, elt);
333
334       return fold_build2 (MINUS_EXPR, type, expr, elt);
335     }
336
337   if (!expr)
338     return fold_build2 (MULT_EXPR, type, elt,
339                         double_int_to_tree (type, scale));
340
341   if (double_int_negative_p (scale))
342     {
343       code = MINUS_EXPR;
344       scale = double_int_neg (scale);
345     }
346   else
347     code = PLUS_EXPR;
348
349   elt = fold_build2 (MULT_EXPR, type, elt,
350                      double_int_to_tree (type, scale));
351   return fold_build2 (code, type, expr, elt);
352 }
353
354 /* Makes tree from the affine combination COMB.  */
355
356 tree
357 aff_combination_to_tree (aff_tree *comb)
358 {
359   tree type = comb->type;
360   tree expr = comb->rest;
361   unsigned i;
362   double_int off, sgn;
363
364   gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
365
366   for (i = 0; i < comb->n; i++)
367     expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef,
368                             comb);
369
370   /* Ensure that we get x - 1, not x + (-1) or x + 0xff..f if x is
371      unsigned.  */
372   if (double_int_negative_p (comb->offset))
373     {
374       off = double_int_neg (comb->offset);
375       sgn = double_int_minus_one;
376     }
377   else
378     {
379       off = comb->offset;
380       sgn = double_int_one;
381     }
382   return add_elt_to_tree (expr, type, double_int_to_tree (type, off), sgn,
383                           comb);
384 }
385
386 /* Copies the tree elements of COMB to ensure that they are not shared.  */
387
388 void
389 unshare_aff_combination (aff_tree *comb)
390 {
391   unsigned i;
392
393   for (i = 0; i < comb->n; i++)
394     comb->elts[i].val = unshare_expr (comb->elts[i].val);
395   if (comb->rest)
396     comb->rest = unshare_expr (comb->rest);
397 }
398
399 /* Remove M-th element from COMB.  */
400
401 void
402 aff_combination_remove_elt (aff_tree *comb, unsigned m)
403 {
404   comb->n--;
405   if (m <= comb->n)
406     comb->elts[m] = comb->elts[comb->n];
407   if (comb->rest)
408     {
409       comb->elts[comb->n].coef = double_int_one;
410       comb->elts[comb->n].val = comb->rest;
411       comb->rest = NULL_TREE;
412       comb->n++;
413     }
414 }