xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-address.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
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_const (TREE_INT_CST_LOW (addr->step),
196 			     TREE_INT_CST_HIGH (addr->step), address_mode);
197   else
198     st = NULL_RTX;
199 
200   if (addr->offset && !integer_zerop (addr->offset))
201     off = immed_double_const (TREE_INT_CST_LOW (addr->offset),
202 			      TREE_INT_CST_HIGH (addr->offset), address_mode);
203   else
204     off = NULL_RTX;
205 
206   if (!really_expand)
207     {
208       unsigned int templ_index
209 	= TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
210 
211       if (templ_index
212 	  >= VEC_length (mem_addr_template, mem_addr_template_list))
213 	VEC_safe_grow_cleared (mem_addr_template, gc, mem_addr_template_list,
214 			       templ_index + 1);
215 
216       /* Reuse the templates for addresses, so that we do not waste memory.  */
217       templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
218       if (!templ->ref)
219 	{
220 	  sym = (addr->symbol ?
221 		 gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol"))
222 		 : NULL_RTX);
223 	  bse = (addr->base ?
224 		 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1)
225 		 : NULL_RTX);
226 	  idx = (addr->index ?
227 		 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2)
228 		 : NULL_RTX);
229 
230 	  gen_addr_rtx (address_mode, sym, bse, idx,
231 			st? const0_rtx : NULL_RTX,
232 			off? const0_rtx : NULL_RTX,
233 			&templ->ref,
234 			&templ->step_p,
235 			&templ->off_p);
236 	}
237 
238       if (st)
239 	*templ->step_p = st;
240       if (off)
241 	*templ->off_p = off;
242 
243       return templ->ref;
244     }
245 
246   /* Otherwise really expand the expressions.  */
247   sym = (addr->symbol
248 	 ? expand_expr (build_addr (addr->symbol, current_function_decl),
249 			NULL_RTX, address_mode, EXPAND_NORMAL)
250 	 : NULL_RTX);
251   bse = (addr->base
252 	 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL)
253 	 : NULL_RTX);
254   idx = (addr->index
255 	 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL)
256 	 : NULL_RTX);
257 
258   gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL);
259   return address;
260 }
261 
262 /* Returns address of MEM_REF in TYPE.  */
263 
264 tree
265 tree_mem_ref_addr (tree type, tree mem_ref)
266 {
267   tree addr;
268   tree act_elem;
269   tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
270   tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref);
271   tree addr_base = NULL_TREE, addr_off = NULL_TREE;
272 
273   if (sym)
274     addr_base = fold_convert (type, build_addr (sym, current_function_decl));
275   else if (base && POINTER_TYPE_P (TREE_TYPE (base)))
276     {
277       addr_base = fold_convert (type, base);
278       base = NULL_TREE;
279     }
280 
281   act_elem = TMR_INDEX (mem_ref);
282   if (act_elem)
283     {
284       if (step)
285 	act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
286       addr_off = act_elem;
287     }
288 
289   act_elem = base;
290   if (act_elem)
291     {
292       if (addr_off)
293 	addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
294       else
295 	addr_off = act_elem;
296     }
297 
298   if (offset && !integer_zerop (offset))
299     {
300       if (addr_off)
301 	addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
302       else
303 	addr_off = offset;
304     }
305 
306   if (addr_off)
307     {
308       if (addr_base)
309 	addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
310       else
311 	addr = fold_convert (type, addr_off);
312     }
313   else if (addr_base)
314     addr = addr_base;
315   else
316     addr = build_int_cst (type, 0);
317 
318   return addr;
319 }
320 
321 /* Returns true if a memory reference in MODE and with parameters given by
322    ADDR is valid on the current target.  */
323 
324 static bool
325 valid_mem_ref_p (enum machine_mode mode, addr_space_t as,
326 		 struct mem_address *addr)
327 {
328   rtx address;
329 
330   address = addr_for_mem_ref (addr, as, false);
331   if (!address)
332     return false;
333 
334   return memory_address_addr_space_p (mode, address, as);
335 }
336 
337 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
338    is valid on the current target and if so, creates and returns the
339    TARGET_MEM_REF.  */
340 
341 static tree
342 create_mem_ref_raw (tree type, struct mem_address *addr)
343 {
344   if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
345     return NULL_TREE;
346 
347   if (addr->step && integer_onep (addr->step))
348     addr->step = NULL_TREE;
349 
350   if (addr->offset && integer_zerop (addr->offset))
351     addr->offset = NULL_TREE;
352 
353   return build6 (TARGET_MEM_REF, type,
354 		 addr->symbol, addr->base, addr->index,
355 		 addr->step, addr->offset, NULL);
356 }
357 
358 /* Returns true if OBJ is an object whose address is a link time constant.  */
359 
360 static bool
361 fixed_address_object_p (tree obj)
362 {
363   return (TREE_CODE (obj) == VAR_DECL
364 	  && (TREE_STATIC (obj)
365 	      || DECL_EXTERNAL (obj))
366 	  && ! DECL_DLLIMPORT_P (obj));
367 }
368 
369 /* If ADDR contains an address of object that is a link time constant,
370    move it to PARTS->symbol.  */
371 
372 static void
373 move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
374 {
375   unsigned i;
376   tree val = NULL_TREE;
377 
378   for (i = 0; i < addr->n; i++)
379     {
380       if (!double_int_one_p (addr->elts[i].coef))
381 	continue;
382 
383       val = addr->elts[i].val;
384       if (TREE_CODE (val) == ADDR_EXPR
385 	  && fixed_address_object_p (TREE_OPERAND (val, 0)))
386 	break;
387     }
388 
389   if (i == addr->n)
390     return;
391 
392   parts->symbol = TREE_OPERAND (val, 0);
393   aff_combination_remove_elt (addr, i);
394 }
395 
396 /* If ADDR contains an instance of BASE_HINT, move it to PARTS->base.  */
397 
398 static void
399 move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
400 		   aff_tree *addr)
401 {
402   unsigned i;
403   tree val = NULL_TREE;
404   int qual;
405 
406   for (i = 0; i < addr->n; i++)
407     {
408       if (!double_int_one_p (addr->elts[i].coef))
409 	continue;
410 
411       val = addr->elts[i].val;
412       if (operand_equal_p (val, base_hint, 0))
413 	break;
414     }
415 
416   if (i == addr->n)
417     return;
418 
419   /* Cast value to appropriate pointer type.  We cannot use a pointer
420      to TYPE directly, as the back-end will assume registers of pointer
421      type are aligned, and just the base itself may not actually be.
422      We use void pointer to the type's address space instead.  */
423   qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type));
424   type = build_qualified_type (void_type_node, qual);
425   parts->base = fold_convert (build_pointer_type (type), val);
426   aff_combination_remove_elt (addr, i);
427 }
428 
429 /* If ADDR contains an address of a dereferenced pointer, move it to
430    PARTS->base.  */
431 
432 static void
433 move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
434 {
435   unsigned i;
436   tree val = NULL_TREE;
437 
438   for (i = 0; i < addr->n; i++)
439     {
440       if (!double_int_one_p (addr->elts[i].coef))
441 	continue;
442 
443       val = addr->elts[i].val;
444       if (POINTER_TYPE_P (TREE_TYPE (val)))
445 	break;
446     }
447 
448   if (i == addr->n)
449     return;
450 
451   parts->base = val;
452   aff_combination_remove_elt (addr, i);
453 }
454 
455 /* Adds ELT to PARTS.  */
456 
457 static void
458 add_to_parts (struct mem_address *parts, tree elt)
459 {
460   tree type;
461 
462   if (!parts->index)
463     {
464       parts->index = fold_convert (sizetype, elt);
465       return;
466     }
467 
468   if (!parts->base)
469     {
470       parts->base = elt;
471       return;
472     }
473 
474   /* Add ELT to base.  */
475   type = TREE_TYPE (parts->base);
476   if (POINTER_TYPE_P (type))
477     parts->base = fold_build2 (POINTER_PLUS_EXPR, type,
478 			       parts->base,
479 			       fold_convert (sizetype, elt));
480   else
481     parts->base = fold_build2 (PLUS_EXPR, type,
482 			       parts->base, elt);
483 }
484 
485 /* Finds the most expensive multiplication in ADDR that can be
486    expressed in an addressing mode and move the corresponding
487    element(s) to PARTS.  */
488 
489 static void
490 most_expensive_mult_to_index (tree type, struct mem_address *parts,
491 			      aff_tree *addr, bool speed)
492 {
493   addr_space_t as = TYPE_ADDR_SPACE (type);
494   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
495   HOST_WIDE_INT coef;
496   double_int best_mult, amult, amult_neg;
497   unsigned best_mult_cost = 0, acost;
498   tree mult_elt = NULL_TREE, elt;
499   unsigned i, j;
500   enum tree_code op_code;
501 
502   best_mult = double_int_zero;
503   for (i = 0; i < addr->n; i++)
504     {
505       if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
506 	continue;
507 
508       coef = double_int_to_shwi (addr->elts[i].coef);
509       if (coef == 1
510 	  || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
511 	continue;
512 
513       acost = multiply_by_cost (coef, address_mode, speed);
514 
515       if (acost > best_mult_cost)
516 	{
517 	  best_mult_cost = acost;
518 	  best_mult = addr->elts[i].coef;
519 	}
520     }
521 
522   if (!best_mult_cost)
523     return;
524 
525   /* Collect elements multiplied by best_mult.  */
526   for (i = j = 0; i < addr->n; i++)
527     {
528       amult = addr->elts[i].coef;
529       amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
530 
531       if (double_int_equal_p (amult, best_mult))
532 	op_code = PLUS_EXPR;
533       else if (double_int_equal_p (amult_neg, best_mult))
534 	op_code = MINUS_EXPR;
535       else
536 	{
537 	  addr->elts[j] = addr->elts[i];
538 	  j++;
539 	  continue;
540 	}
541 
542       elt = fold_convert (sizetype, addr->elts[i].val);
543       if (mult_elt)
544 	mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
545       else if (op_code == PLUS_EXPR)
546 	mult_elt = elt;
547       else
548 	mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
549     }
550   addr->n = j;
551 
552   parts->index = mult_elt;
553   parts->step = double_int_to_tree (sizetype, best_mult);
554 }
555 
556 /* Splits address ADDR for a memory access of type TYPE into PARTS.
557    If BASE_HINT is non-NULL, it specifies an SSA name to be used
558    preferentially as base of the reference.
559 
560    TODO -- be more clever about the distribution of the elements of ADDR
561    to PARTS.  Some architectures do not support anything but single
562    register in address, possibly with a small integer offset; while
563    create_mem_ref will simplify the address to an acceptable shape
564    later, it would be more efficient to know that asking for complicated
565    addressing modes is useless.  */
566 
567 static void
568 addr_to_parts (tree type, aff_tree *addr, tree base_hint,
569 	       struct mem_address *parts, bool speed)
570 {
571   tree part;
572   unsigned i;
573 
574   parts->symbol = NULL_TREE;
575   parts->base = NULL_TREE;
576   parts->index = NULL_TREE;
577   parts->step = NULL_TREE;
578 
579   if (!double_int_zero_p (addr->offset))
580     parts->offset = double_int_to_tree (sizetype, addr->offset);
581   else
582     parts->offset = NULL_TREE;
583 
584   /* Try to find a symbol.  */
585   move_fixed_address_to_symbol (parts, addr);
586 
587   /* First move the most expensive feasible multiplication
588      to index.  */
589   most_expensive_mult_to_index (type, parts, addr, speed);
590 
591   /* Try to find a base of the reference.  Since at the moment
592      there is no reliable way how to distinguish between pointer and its
593      offset, this is just a guess.  */
594   if (!parts->symbol && base_hint)
595     move_hint_to_base (type, parts, base_hint, addr);
596   if (!parts->symbol && !parts->base)
597     move_pointer_to_base (parts, addr);
598 
599   /* Then try to process the remaining elements.  */
600   for (i = 0; i < addr->n; i++)
601     {
602       part = fold_convert (sizetype, addr->elts[i].val);
603       if (!double_int_one_p (addr->elts[i].coef))
604 	part = fold_build2 (MULT_EXPR, sizetype, part,
605 			    double_int_to_tree (sizetype, addr->elts[i].coef));
606       add_to_parts (parts, part);
607     }
608   if (addr->rest)
609     add_to_parts (parts, fold_convert (sizetype, addr->rest));
610 }
611 
612 /* Force the PARTS to register.  */
613 
614 static void
615 gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
616 {
617   if (parts->base)
618     parts->base = force_gimple_operand_gsi (gsi, parts->base,
619 					    true, NULL_TREE,
620 					    true, GSI_SAME_STMT);
621   if (parts->index)
622     parts->index = force_gimple_operand_gsi (gsi, parts->index,
623 					     true, NULL_TREE,
624 					     true, GSI_SAME_STMT);
625 }
626 
627 /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
628    computations are emitted in front of GSI.  TYPE is the mode
629    of created memory reference.  */
630 
631 tree
632 create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
633 		tree base_hint, bool speed)
634 {
635   tree mem_ref, tmp;
636   tree atype;
637   struct mem_address parts;
638 
639   addr_to_parts (type, addr, base_hint, &parts, speed);
640   gimplify_mem_ref_parts (gsi, &parts);
641   mem_ref = create_mem_ref_raw (type, &parts);
642   if (mem_ref)
643     return mem_ref;
644 
645   /* The expression is too complicated.  Try making it simpler.  */
646 
647   if (parts.step && !integer_onep (parts.step))
648     {
649       /* Move the multiplication to index.  */
650       gcc_assert (parts.index);
651       parts.index = force_gimple_operand_gsi (gsi,
652 				fold_build2 (MULT_EXPR, sizetype,
653 					     parts.index, parts.step),
654 				true, NULL_TREE, true, GSI_SAME_STMT);
655       parts.step = NULL_TREE;
656 
657       mem_ref = create_mem_ref_raw (type, &parts);
658       if (mem_ref)
659 	return mem_ref;
660     }
661 
662   if (parts.symbol)
663     {
664       tmp = build_addr (parts.symbol, current_function_decl);
665       gcc_assert (is_gimple_val (tmp));
666 
667       /* Add the symbol to base, eventually forcing it to register.  */
668       if (parts.base)
669 	{
670 	  gcc_assert (useless_type_conversion_p
671 				(sizetype, TREE_TYPE (parts.base)));
672 
673 	  if (parts.index)
674 	    {
675 	      atype = TREE_TYPE (tmp);
676 	      parts.base = force_gimple_operand_gsi (gsi,
677 			fold_build2 (POINTER_PLUS_EXPR, atype,
678 				     tmp,
679 				     fold_convert (sizetype, parts.base)),
680 			true, NULL_TREE, true, GSI_SAME_STMT);
681 	    }
682 	  else
683 	    {
684 	      parts.index = parts.base;
685 	      parts.base = tmp;
686 	    }
687 	}
688       else
689 	parts.base = tmp;
690       parts.symbol = NULL_TREE;
691 
692       mem_ref = create_mem_ref_raw (type, &parts);
693       if (mem_ref)
694 	return mem_ref;
695     }
696 
697   if (parts.index)
698     {
699       /* Add index to base.  */
700       if (parts.base)
701 	{
702 	  atype = TREE_TYPE (parts.base);
703 	  parts.base = force_gimple_operand_gsi (gsi,
704 			fold_build2 (POINTER_PLUS_EXPR, atype,
705 				     parts.base,
706 			    	     parts.index),
707 			true, NULL_TREE, true, GSI_SAME_STMT);
708 	}
709       else
710 	parts.base = parts.index;
711       parts.index = NULL_TREE;
712 
713       mem_ref = create_mem_ref_raw (type, &parts);
714       if (mem_ref)
715 	return mem_ref;
716     }
717 
718   if (parts.offset && !integer_zerop (parts.offset))
719     {
720       /* Try adding offset to base.  */
721       if (parts.base)
722 	{
723 	  atype = TREE_TYPE (parts.base);
724 	  parts.base = force_gimple_operand_gsi (gsi,
725 			fold_build2 (POINTER_PLUS_EXPR, atype,
726 				     parts.base,
727 				     fold_convert (sizetype, parts.offset)),
728 			true, NULL_TREE, true, GSI_SAME_STMT);
729 	}
730       else
731 	parts.base = parts.offset;
732 
733       parts.offset = NULL_TREE;
734 
735       mem_ref = create_mem_ref_raw (type, &parts);
736       if (mem_ref)
737 	return mem_ref;
738     }
739 
740   /* Verify that the address is in the simplest possible shape
741      (only a register).  If we cannot create such a memory reference,
742      something is really wrong.  */
743   gcc_assert (parts.symbol == NULL_TREE);
744   gcc_assert (parts.index == NULL_TREE);
745   gcc_assert (!parts.step || integer_onep (parts.step));
746   gcc_assert (!parts.offset || integer_zerop (parts.offset));
747   gcc_unreachable ();
748 }
749 
750 /* Copies components of the address from OP to ADDR.  */
751 
752 void
753 get_address_description (tree op, struct mem_address *addr)
754 {
755   addr->symbol = TMR_SYMBOL (op);
756   addr->base = TMR_BASE (op);
757   addr->index = TMR_INDEX (op);
758   addr->step = TMR_STEP (op);
759   addr->offset = TMR_OFFSET (op);
760 }
761 
762 /* Copies the additional information attached to target_mem_ref FROM to TO.  */
763 
764 void
765 copy_mem_ref_info (tree to, tree from)
766 {
767   /* And the info about the original reference.  */
768   TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
769   TREE_SIDE_EFFECTS (to) = TREE_SIDE_EFFECTS (from);
770   TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from);
771 }
772 
773 /* Move constants in target_mem_ref REF to offset.  Returns the new target
774    mem ref if anything changes, NULL_TREE otherwise.  */
775 
776 tree
777 maybe_fold_tmr (tree ref)
778 {
779   struct mem_address addr;
780   bool changed = false;
781   tree ret, off;
782 
783   get_address_description (ref, &addr);
784 
785   if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
786     {
787       if (addr.offset)
788 	addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
789 			addr.offset,
790 			fold_convert (sizetype, addr.base));
791       else
792 	addr.offset = addr.base;
793 
794       addr.base = NULL_TREE;
795       changed = true;
796     }
797 
798   if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
799     {
800       off = addr.index;
801       if (addr.step)
802 	{
803 	  off = fold_binary_to_constant (MULT_EXPR, sizetype,
804 					 off, addr.step);
805 	  addr.step = NULL_TREE;
806 	}
807 
808       if (addr.offset)
809 	{
810 	  addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
811 						 addr.offset, off);
812 	}
813       else
814 	addr.offset = off;
815 
816       addr.index = NULL_TREE;
817       changed = true;
818     }
819 
820   if (!changed)
821     return NULL_TREE;
822 
823   ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
824   if (!ret)
825     return NULL_TREE;
826 
827   copy_mem_ref_info (ret, ref);
828   return ret;
829 }
830 
831 /* Dump PARTS to FILE.  */
832 
833 extern void dump_mem_address (FILE *, struct mem_address *);
834 void
835 dump_mem_address (FILE *file, struct mem_address *parts)
836 {
837   if (parts->symbol)
838     {
839       fprintf (file, "symbol: ");
840       print_generic_expr (file, parts->symbol, TDF_SLIM);
841       fprintf (file, "\n");
842     }
843   if (parts->base)
844     {
845       fprintf (file, "base: ");
846       print_generic_expr (file, parts->base, TDF_SLIM);
847       fprintf (file, "\n");
848     }
849   if (parts->index)
850     {
851       fprintf (file, "index: ");
852       print_generic_expr (file, parts->index, TDF_SLIM);
853       fprintf (file, "\n");
854     }
855   if (parts->step)
856     {
857       fprintf (file, "step: ");
858       print_generic_expr (file, parts->step, TDF_SLIM);
859       fprintf (file, "\n");
860     }
861   if (parts->offset)
862     {
863       fprintf (file, "offset: ");
864       print_generic_expr (file, parts->offset, TDF_SLIM);
865       fprintf (file, "\n");
866     }
867 }
868 
869 #include "gt-tree-ssa-address.h"
870