OSDN Git Service

PR c++/43856
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-address.c
1 /* Memory address lowering and addressing mode selection.
2    Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010
3    Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option) any
10 later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20
21 /* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
22    that directly map to addressing modes of the target.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "rtl.h"
30 #include "tm_p.h"
31 #include "hard-reg-set.h"
32 #include "basic-block.h"
33 #include "output.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
36 #include "tree-dump.h"
37 #include "tree-pass.h"
38 #include "timevar.h"
39 #include "flags.h"
40 #include "tree-inline.h"
41 #include "insn-config.h"
42 #include "recog.h"
43 #include "expr.h"
44 #include "ggc.h"
45 #include "tree-affine.h"
46 #include "target.h"
47
48 /* TODO -- handling of symbols (according to Richard Hendersons
49    comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
50
51    There are at least 5 different kinds of symbols that we can run up against:
52
53      (1) binds_local_p, small data area.
54      (2) binds_local_p, eg local statics
55      (3) !binds_local_p, eg global variables
56      (4) thread local, local_exec
57      (5) thread local, !local_exec
58
59    Now, (1) won't appear often in an array context, but it certainly can.
60    All you have to do is set -GN high enough, or explicitly mark any
61    random object __attribute__((section (".sdata"))).
62
63    All of these affect whether or not a symbol is in fact a valid address.
64    The only one tested here is (3).  And that result may very well
65    be incorrect for (4) or (5).
66
67    An incorrect result here does not cause incorrect results out the
68    back end, because the expander in expr.c validizes the address.  However
69    it would be nice to improve the handling here in order to produce more
70    precise results.  */
71
72 /* A "template" for memory address, used to determine whether the address is
73    valid for mode.  */
74
75 typedef struct GTY (()) mem_addr_template {
76   rtx ref;                      /* The template.  */
77   rtx * GTY ((skip)) step_p;    /* The point in template where the step should be
78                                    filled in.  */
79   rtx * GTY ((skip)) off_p;     /* The point in template where the offset should
80                                    be filled in.  */
81 } mem_addr_template;
82
83 DEF_VEC_O (mem_addr_template);
84 DEF_VEC_ALLOC_O (mem_addr_template, gc);
85
86 /* The templates.  Each of the low five bits of the index corresponds to one
87    component of TARGET_MEM_REF being present, while the high bits identify
88    the address space.  See TEMPL_IDX.  */
89
90 static GTY(()) VEC (mem_addr_template, gc) *mem_addr_template_list;
91
92 #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
93   (((int) (AS) << 5) \
94    | ((SYMBOL != 0) << 4) \
95    | ((BASE != 0) << 3) \
96    | ((INDEX != 0) << 2) \
97    | ((STEP != 0) << 1) \
98    | (OFFSET != 0))
99
100 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
101    STEP and OFFSET to *ADDR using address mode ADDRESS_MODE.  Stores pointers
102    to where step is placed to *STEP_P and offset to *OFFSET_P.  */
103
104 static void
105 gen_addr_rtx (enum machine_mode address_mode,
106               rtx symbol, rtx base, rtx index, rtx step, rtx offset,
107               rtx *addr, rtx **step_p, rtx **offset_p)
108 {
109   rtx act_elem;
110
111   *addr = NULL_RTX;
112   if (step_p)
113     *step_p = NULL;
114   if (offset_p)
115     *offset_p = NULL;
116
117   if (index)
118     {
119       act_elem = index;
120       if (step)
121         {
122           act_elem = gen_rtx_MULT (address_mode, act_elem, step);
123
124           if (step_p)
125             *step_p = &XEXP (act_elem, 1);
126         }
127
128       *addr = act_elem;
129     }
130
131   if (base)
132     {
133       if (*addr)
134         *addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
135       else
136         *addr = base;
137     }
138
139   if (symbol)
140     {
141       act_elem = symbol;
142       if (offset)
143         {
144           act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
145
146           if (offset_p)
147             *offset_p = &XEXP (act_elem, 1);
148
149           if (GET_CODE (symbol) == SYMBOL_REF
150               || GET_CODE (symbol) == LABEL_REF
151               || GET_CODE (symbol) == CONST)
152             act_elem = gen_rtx_CONST (address_mode, act_elem);
153         }
154
155       if (*addr)
156         *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
157       else
158         *addr = act_elem;
159     }
160   else if (offset)
161     {
162       if (*addr)
163         {
164           *addr = gen_rtx_PLUS (address_mode, *addr, offset);
165           if (offset_p)
166             *offset_p = &XEXP (*addr, 1);
167         }
168       else
169         {
170           *addr = offset;
171           if (offset_p)
172             *offset_p = addr;
173         }
174     }
175
176   if (!*addr)
177     *addr = const0_rtx;
178 }
179
180 /* Returns address for TARGET_MEM_REF with parameters given by ADDR
181    in address space AS.
182    If REALLY_EXPAND is false, just make fake registers instead
183    of really expanding the operands, and perform the expansion in-place
184    by using one of the "templates".  */
185
186 rtx
187 addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
188                   bool really_expand)
189 {
190   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
191   rtx address, sym, bse, idx, st, off;
192   struct mem_addr_template *templ;
193
194   if (addr->step && !integer_onep (addr->step))
195     st = immed_double_int_const (tree_to_double_int (addr->step), address_mode);
196   else
197     st = NULL_RTX;
198
199   if (addr->offset && !integer_zerop (addr->offset))
200     off = immed_double_int_const (tree_to_double_int (addr->offset), address_mode);
201   else
202     off = NULL_RTX;
203
204   if (!really_expand)
205     {
206       unsigned int templ_index
207         = TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
208
209       if (templ_index
210           >= VEC_length (mem_addr_template, mem_addr_template_list))
211         VEC_safe_grow_cleared (mem_addr_template, gc, mem_addr_template_list,
212                                templ_index + 1);
213
214       /* Reuse the templates for addresses, so that we do not waste memory.  */
215       templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
216       if (!templ->ref)
217         {
218           sym = (addr->symbol ?
219                  gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol"))
220                  : NULL_RTX);
221           bse = (addr->base ?
222                  gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1)
223                  : NULL_RTX);
224           idx = (addr->index ?
225                  gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2)
226                  : NULL_RTX);
227
228           gen_addr_rtx (address_mode, sym, bse, idx,
229                         st? const0_rtx : NULL_RTX,
230                         off? const0_rtx : NULL_RTX,
231                         &templ->ref,
232                         &templ->step_p,
233                         &templ->off_p);
234         }
235
236       if (st)
237         *templ->step_p = st;
238       if (off)
239         *templ->off_p = off;
240
241       return templ->ref;
242     }
243
244   /* Otherwise really expand the expressions.  */
245   sym = (addr->symbol
246          ? expand_expr (build_addr (addr->symbol, current_function_decl),
247                         NULL_RTX, address_mode, EXPAND_NORMAL)
248          : NULL_RTX);
249   bse = (addr->base
250          ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL)
251          : NULL_RTX);
252   idx = (addr->index
253          ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL)
254          : NULL_RTX);
255
256   gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL);
257   return address;
258 }
259
260 /* Returns address of MEM_REF in TYPE.  */
261
262 tree
263 tree_mem_ref_addr (tree type, tree mem_ref)
264 {
265   tree addr;
266   tree act_elem;
267   tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
268   tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref);
269   tree addr_base = NULL_TREE, addr_off = NULL_TREE;
270
271   if (sym)
272     addr_base = fold_convert (type, build_addr (sym, current_function_decl));
273   else if (base && POINTER_TYPE_P (TREE_TYPE (base)))
274     {
275       addr_base = fold_convert (type, base);
276       base = NULL_TREE;
277     }
278
279   act_elem = TMR_INDEX (mem_ref);
280   if (act_elem)
281     {
282       if (step)
283         act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
284       addr_off = act_elem;
285     }
286
287   act_elem = base;
288   if (act_elem)
289     {
290       if (addr_off)
291         addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
292       else
293         addr_off = act_elem;
294     }
295
296   if (offset && !integer_zerop (offset))
297     {
298       if (addr_off)
299         addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
300       else
301         addr_off = offset;
302     }
303
304   if (addr_off)
305     {
306       if (addr_base)
307         addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
308       else
309         addr = fold_convert (type, addr_off);
310     }
311   else if (addr_base)
312     addr = addr_base;
313   else
314     addr = build_int_cst (type, 0);
315
316   return addr;
317 }
318
319 /* Returns true if a memory reference in MODE and with parameters given by
320    ADDR is valid on the current target.  */
321
322 static bool
323 valid_mem_ref_p (enum machine_mode mode, addr_space_t as,
324                  struct mem_address *addr)
325 {
326   rtx address;
327
328   address = addr_for_mem_ref (addr, as, false);
329   if (!address)
330     return false;
331
332   return memory_address_addr_space_p (mode, address, as);
333 }
334
335 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
336    is valid on the current target and if so, creates and returns the
337    TARGET_MEM_REF.  */
338
339 static tree
340 create_mem_ref_raw (tree type, struct mem_address *addr)
341 {
342   if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
343     return NULL_TREE;
344
345   if (addr->step && integer_onep (addr->step))
346     addr->step = NULL_TREE;
347
348   if (addr->offset && integer_zerop (addr->offset))
349     addr->offset = NULL_TREE;
350
351   return build6 (TARGET_MEM_REF, type,
352                  addr->symbol, addr->base, addr->index,
353                  addr->step, addr->offset, NULL);
354 }
355
356 /* Returns true if OBJ is an object whose address is a link time constant.  */
357
358 static bool
359 fixed_address_object_p (tree obj)
360 {
361   return (TREE_CODE (obj) == VAR_DECL
362           && (TREE_STATIC (obj)
363               || DECL_EXTERNAL (obj))
364           && ! DECL_DLLIMPORT_P (obj));
365 }
366
367 /* If ADDR contains an address of object that is a link time constant,
368    move it to PARTS->symbol.  */
369
370 static void
371 move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
372 {
373   unsigned i;
374   tree val = NULL_TREE;
375
376   for (i = 0; i < addr->n; i++)
377     {
378       if (!double_int_one_p (addr->elts[i].coef))
379         continue;
380
381       val = addr->elts[i].val;
382       if (TREE_CODE (val) == ADDR_EXPR
383           && fixed_address_object_p (TREE_OPERAND (val, 0)))
384         break;
385     }
386
387   if (i == addr->n)
388     return;
389
390   parts->symbol = TREE_OPERAND (val, 0);
391   aff_combination_remove_elt (addr, i);
392 }
393
394 /* If ADDR contains an instance of BASE_HINT, move it to PARTS->base.  */
395
396 static void
397 move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
398                    aff_tree *addr)
399 {
400   unsigned i;
401   tree val = NULL_TREE;
402   int qual;
403
404   for (i = 0; i < addr->n; i++)
405     {
406       if (!double_int_one_p (addr->elts[i].coef))
407         continue;
408
409       val = addr->elts[i].val;
410       if (operand_equal_p (val, base_hint, 0))
411         break;
412     }
413
414   if (i == addr->n)
415     return;
416
417   /* Cast value to appropriate pointer type.  We cannot use a pointer
418      to TYPE directly, as the back-end will assume registers of pointer
419      type are aligned, and just the base itself may not actually be.
420      We use void pointer to the type's address space instead.  */
421   qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type));
422   type = build_qualified_type (void_type_node, qual);
423   parts->base = fold_convert (build_pointer_type (type), val);
424   aff_combination_remove_elt (addr, i);
425 }
426
427 /* If ADDR contains an address of a dereferenced pointer, move it to
428    PARTS->base.  */
429
430 static void
431 move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
432 {
433   unsigned i;
434   tree val = NULL_TREE;
435
436   for (i = 0; i < addr->n; i++)
437     {
438       if (!double_int_one_p (addr->elts[i].coef))
439         continue;
440
441       val = addr->elts[i].val;
442       if (POINTER_TYPE_P (TREE_TYPE (val)))
443         break;
444     }
445
446   if (i == addr->n)
447     return;
448
449   parts->base = val;
450   aff_combination_remove_elt (addr, i);
451 }
452
453 /* Adds ELT to PARTS.  */
454
455 static void
456 add_to_parts (struct mem_address *parts, tree elt)
457 {
458   tree type;
459
460   if (!parts->index)
461     {
462       parts->index = fold_convert (sizetype, elt);
463       return;
464     }
465
466   if (!parts->base)
467     {
468       parts->base = elt;
469       return;
470     }
471
472   /* Add ELT to base.  */
473   type = TREE_TYPE (parts->base);
474   if (POINTER_TYPE_P (type))
475     parts->base = fold_build2 (POINTER_PLUS_EXPR, type,
476                                parts->base,
477                                fold_convert (sizetype, elt));
478   else
479     parts->base = fold_build2 (PLUS_EXPR, type,
480                                parts->base, elt);
481 }
482
483 /* Finds the most expensive multiplication in ADDR that can be
484    expressed in an addressing mode and move the corresponding
485    element(s) to PARTS.  */
486
487 static void
488 most_expensive_mult_to_index (tree type, struct mem_address *parts,
489                               aff_tree *addr, bool speed)
490 {
491   addr_space_t as = TYPE_ADDR_SPACE (type);
492   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
493   HOST_WIDE_INT coef;
494   double_int best_mult, amult, amult_neg;
495   unsigned best_mult_cost = 0, acost;
496   tree mult_elt = NULL_TREE, elt;
497   unsigned i, j;
498   enum tree_code op_code;
499
500   best_mult = double_int_zero;
501   for (i = 0; i < addr->n; i++)
502     {
503       if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
504         continue;
505
506       coef = double_int_to_shwi (addr->elts[i].coef);
507       if (coef == 1
508           || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
509         continue;
510
511       acost = multiply_by_cost (coef, address_mode, speed);
512
513       if (acost > best_mult_cost)
514         {
515           best_mult_cost = acost;
516           best_mult = addr->elts[i].coef;
517         }
518     }
519
520   if (!best_mult_cost)
521     return;
522
523   /* Collect elements multiplied by best_mult.  */
524   for (i = j = 0; i < addr->n; i++)
525     {
526       amult = addr->elts[i].coef;
527       amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
528
529       if (double_int_equal_p (amult, best_mult))
530         op_code = PLUS_EXPR;
531       else if (double_int_equal_p (amult_neg, best_mult))
532         op_code = MINUS_EXPR;
533       else
534         {
535           addr->elts[j] = addr->elts[i];
536           j++;
537           continue;
538         }
539
540       elt = fold_convert (sizetype, addr->elts[i].val);
541       if (mult_elt)
542         mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
543       else if (op_code == PLUS_EXPR)
544         mult_elt = elt;
545       else
546         mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
547     }
548   addr->n = j;
549
550   parts->index = mult_elt;
551   parts->step = double_int_to_tree (sizetype, best_mult);
552 }
553
554 /* Splits address ADDR for a memory access of type TYPE into PARTS.
555    If BASE_HINT is non-NULL, it specifies an SSA name to be used
556    preferentially as base of the reference.
557
558    TODO -- be more clever about the distribution of the elements of ADDR
559    to PARTS.  Some architectures do not support anything but single
560    register in address, possibly with a small integer offset; while
561    create_mem_ref will simplify the address to an acceptable shape
562    later, it would be more efficient to know that asking for complicated
563    addressing modes is useless.  */
564
565 static void
566 addr_to_parts (tree type, aff_tree *addr, tree base_hint,
567                struct mem_address *parts, bool speed)
568 {
569   tree part;
570   unsigned i;
571
572   parts->symbol = NULL_TREE;
573   parts->base = NULL_TREE;
574   parts->index = NULL_TREE;
575   parts->step = NULL_TREE;
576
577   if (!double_int_zero_p (addr->offset))
578     parts->offset = double_int_to_tree (sizetype, addr->offset);
579   else
580     parts->offset = NULL_TREE;
581
582   /* Try to find a symbol.  */
583   move_fixed_address_to_symbol (parts, addr);
584
585   /* First move the most expensive feasible multiplication
586      to index.  */
587   most_expensive_mult_to_index (type, parts, addr, speed);
588
589   /* Try to find a base of the reference.  Since at the moment
590      there is no reliable way how to distinguish between pointer and its
591      offset, this is just a guess.  */
592   if (!parts->symbol && base_hint)
593     move_hint_to_base (type, parts, base_hint, addr);
594   if (!parts->symbol && !parts->base)
595     move_pointer_to_base (parts, addr);
596
597   /* Then try to process the remaining elements.  */
598   for (i = 0; i < addr->n; i++)
599     {
600       part = fold_convert (sizetype, addr->elts[i].val);
601       if (!double_int_one_p (addr->elts[i].coef))
602         part = fold_build2 (MULT_EXPR, sizetype, part,
603                             double_int_to_tree (sizetype, addr->elts[i].coef));
604       add_to_parts (parts, part);
605     }
606   if (addr->rest)
607     add_to_parts (parts, fold_convert (sizetype, addr->rest));
608 }
609
610 /* Force the PARTS to register.  */
611
612 static void
613 gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
614 {
615   if (parts->base)
616     parts->base = force_gimple_operand_gsi (gsi, parts->base,
617                                             true, NULL_TREE,
618                                             true, GSI_SAME_STMT);
619   if (parts->index)
620     parts->index = force_gimple_operand_gsi (gsi, parts->index,
621                                              true, NULL_TREE,
622                                              true, GSI_SAME_STMT);
623 }
624
625 /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
626    computations are emitted in front of GSI.  TYPE is the mode
627    of created memory reference.  */
628
629 tree
630 create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
631                 tree base_hint, bool speed)
632 {
633   tree mem_ref, tmp;
634   tree atype;
635   struct mem_address parts;
636
637   addr_to_parts (type, addr, base_hint, &parts, speed);
638   gimplify_mem_ref_parts (gsi, &parts);
639   mem_ref = create_mem_ref_raw (type, &parts);
640   if (mem_ref)
641     return mem_ref;
642
643   /* The expression is too complicated.  Try making it simpler.  */
644
645   if (parts.step && !integer_onep (parts.step))
646     {
647       /* Move the multiplication to index.  */
648       gcc_assert (parts.index);
649       parts.index = force_gimple_operand_gsi (gsi,
650                                 fold_build2 (MULT_EXPR, sizetype,
651                                              parts.index, parts.step),
652                                 true, NULL_TREE, true, GSI_SAME_STMT);
653       parts.step = NULL_TREE;
654
655       mem_ref = create_mem_ref_raw (type, &parts);
656       if (mem_ref)
657         return mem_ref;
658     }
659
660   if (parts.symbol)
661     {
662       tmp = build_addr (parts.symbol, current_function_decl);
663       gcc_assert (is_gimple_val (tmp));
664
665       /* Add the symbol to base, eventually forcing it to register.  */
666       if (parts.base)
667         {
668           gcc_assert (useless_type_conversion_p
669                                 (sizetype, TREE_TYPE (parts.base)));
670
671           if (parts.index)
672             {
673               atype = TREE_TYPE (tmp);
674               parts.base = force_gimple_operand_gsi (gsi,
675                         fold_build2 (POINTER_PLUS_EXPR, atype,
676                                      tmp,
677                                      fold_convert (sizetype, parts.base)),
678                         true, NULL_TREE, true, GSI_SAME_STMT);
679             }
680           else
681             {
682               parts.index = parts.base;
683               parts.base = tmp;
684             }
685         }
686       else
687         parts.base = tmp;
688       parts.symbol = NULL_TREE;
689
690       mem_ref = create_mem_ref_raw (type, &parts);
691       if (mem_ref)
692         return mem_ref;
693     }
694
695   if (parts.index)
696     {
697       /* Add index to base.  */
698       if (parts.base)
699         {
700           atype = TREE_TYPE (parts.base);
701           parts.base = force_gimple_operand_gsi (gsi,
702                         fold_build2 (POINTER_PLUS_EXPR, atype,
703                                      parts.base,
704                                      parts.index),
705                         true, NULL_TREE, true, GSI_SAME_STMT);
706         }
707       else
708         parts.base = parts.index;
709       parts.index = NULL_TREE;
710
711       mem_ref = create_mem_ref_raw (type, &parts);
712       if (mem_ref)
713         return mem_ref;
714     }
715
716   if (parts.offset && !integer_zerop (parts.offset))
717     {
718       /* Try adding offset to base.  */
719       if (parts.base)
720         {
721           atype = TREE_TYPE (parts.base);
722           parts.base = force_gimple_operand_gsi (gsi,
723                         fold_build2 (POINTER_PLUS_EXPR, atype,
724                                      parts.base,
725                                      fold_convert (sizetype, parts.offset)),
726                         true, NULL_TREE, true, GSI_SAME_STMT);
727         }
728       else
729         parts.base = parts.offset;
730
731       parts.offset = NULL_TREE;
732
733       mem_ref = create_mem_ref_raw (type, &parts);
734       if (mem_ref)
735         return mem_ref;
736     }
737
738   /* Verify that the address is in the simplest possible shape
739      (only a register).  If we cannot create such a memory reference,
740      something is really wrong.  */
741   gcc_assert (parts.symbol == NULL_TREE);
742   gcc_assert (parts.index == NULL_TREE);
743   gcc_assert (!parts.step || integer_onep (parts.step));
744   gcc_assert (!parts.offset || integer_zerop (parts.offset));
745   gcc_unreachable ();
746 }
747
748 /* Copies components of the address from OP to ADDR.  */
749
750 void
751 get_address_description (tree op, struct mem_address *addr)
752 {
753   addr->symbol = TMR_SYMBOL (op);
754   addr->base = TMR_BASE (op);
755   addr->index = TMR_INDEX (op);
756   addr->step = TMR_STEP (op);
757   addr->offset = TMR_OFFSET (op);
758 }
759
760 /* Copies the additional information attached to target_mem_ref FROM to TO.  */
761
762 void
763 copy_mem_ref_info (tree to, tree from)
764 {
765   /* And the info about the original reference.  */
766   TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
767   TREE_SIDE_EFFECTS (to) = TREE_SIDE_EFFECTS (from);
768   TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from);
769 }
770
771 /* Move constants in target_mem_ref REF to offset.  Returns the new target
772    mem ref if anything changes, NULL_TREE otherwise.  */
773
774 tree
775 maybe_fold_tmr (tree ref)
776 {
777   struct mem_address addr;
778   bool changed = false;
779   tree ret, off;
780
781   get_address_description (ref, &addr);
782
783   if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
784     {
785       if (addr.offset)
786         addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
787                         addr.offset,
788                         fold_convert (sizetype, addr.base));
789       else
790         addr.offset = addr.base;
791
792       addr.base = NULL_TREE;
793       changed = true;
794     }
795
796   if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
797     {
798       off = addr.index;
799       if (addr.step)
800         {
801           off = fold_binary_to_constant (MULT_EXPR, sizetype,
802                                          off, addr.step);
803           addr.step = NULL_TREE;
804         }
805
806       if (addr.offset)
807         {
808           addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
809                                                  addr.offset, off);
810         }
811       else
812         addr.offset = off;
813
814       addr.index = NULL_TREE;
815       changed = true;
816     }
817
818   if (!changed)
819     return NULL_TREE;
820
821   ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
822   if (!ret)
823     return NULL_TREE;
824
825   copy_mem_ref_info (ret, ref);
826   return ret;
827 }
828
829 /* Dump PARTS to FILE.  */
830
831 extern void dump_mem_address (FILE *, struct mem_address *);
832 void
833 dump_mem_address (FILE *file, struct mem_address *parts)
834 {
835   if (parts->symbol)
836     {
837       fprintf (file, "symbol: ");
838       print_generic_expr (file, parts->symbol, TDF_SLIM);
839       fprintf (file, "\n");
840     }
841   if (parts->base)
842     {
843       fprintf (file, "base: ");
844       print_generic_expr (file, parts->base, TDF_SLIM);
845       fprintf (file, "\n");
846     }
847   if (parts->index)
848     {
849       fprintf (file, "index: ");
850       print_generic_expr (file, parts->index, TDF_SLIM);
851       fprintf (file, "\n");
852     }
853   if (parts->step)
854     {
855       fprintf (file, "step: ");
856       print_generic_expr (file, parts->step, TDF_SLIM);
857       fprintf (file, "\n");
858     }
859   if (parts->offset)
860     {
861       fprintf (file, "offset: ");
862       print_generic_expr (file, parts->offset, TDF_SLIM);
863       fprintf (file, "\n");
864     }
865 }
866
867 #include "gt-tree-ssa-address.h"