OSDN Git Service

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