OSDN Git Service

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