2013-05-30 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / gcc / tree-ssa-address.c
blobcfd42ad21d5a61457804ec0f6118ffb05ae94c7b
1 /* Memory address lowering and addressing mode selection.
2 Copyright (C) 2004-2013 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
20 /* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
21 that directly map to addressing modes of the target. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "tm_p.h"
29 #include "basic-block.h"
30 #include "tree-pretty-print.h"
31 #include "tree-flow.h"
32 #include "dumpfile.h"
33 #include "flags.h"
34 #include "tree-inline.h"
35 #include "tree-affine.h"
37 /* FIXME: We compute address costs using RTL. */
38 #include "insn-config.h"
39 #include "rtl.h"
40 #include "recog.h"
41 #include "expr.h"
42 #include "ggc.h"
43 #include "target.h"
44 #include "expmed.h"
46 /* TODO -- handling of symbols (according to Richard Hendersons
47 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
49 There are at least 5 different kinds of symbols that we can run up against:
51 (1) binds_local_p, small data area.
52 (2) binds_local_p, eg local statics
53 (3) !binds_local_p, eg global variables
54 (4) thread local, local_exec
55 (5) thread local, !local_exec
57 Now, (1) won't appear often in an array context, but it certainly can.
58 All you have to do is set -GN high enough, or explicitly mark any
59 random object __attribute__((section (".sdata"))).
61 All of these affect whether or not a symbol is in fact a valid address.
62 The only one tested here is (3). And that result may very well
63 be incorrect for (4) or (5).
65 An incorrect result here does not cause incorrect results out the
66 back end, because the expander in expr.c validizes the address. However
67 it would be nice to improve the handling here in order to produce more
68 precise results. */
70 /* A "template" for memory address, used to determine whether the address is
71 valid for mode. */
73 typedef struct GTY (()) mem_addr_template {
74 rtx ref; /* The template. */
75 rtx * GTY ((skip)) step_p; /* The point in template where the step should be
76 filled in. */
77 rtx * GTY ((skip)) off_p; /* The point in template where the offset should
78 be filled in. */
79 } mem_addr_template;
82 /* The templates. Each of the low five bits of the index corresponds to one
83 component of TARGET_MEM_REF being present, while the high bits identify
84 the address space. See TEMPL_IDX. */
86 static GTY(()) vec<mem_addr_template, va_gc> *mem_addr_template_list;
88 #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
89 (((int) (AS) << 5) \
90 | ((SYMBOL != 0) << 4) \
91 | ((BASE != 0) << 3) \
92 | ((INDEX != 0) << 2) \
93 | ((STEP != 0) << 1) \
94 | (OFFSET != 0))
96 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
97 STEP and OFFSET to *ADDR using address mode ADDRESS_MODE. Stores pointers
98 to where step is placed to *STEP_P and offset to *OFFSET_P. */
100 static void
101 gen_addr_rtx (enum machine_mode address_mode,
102 rtx symbol, rtx base, rtx index, rtx step, rtx offset,
103 rtx *addr, rtx **step_p, rtx **offset_p)
105 rtx act_elem;
107 *addr = NULL_RTX;
108 if (step_p)
109 *step_p = NULL;
110 if (offset_p)
111 *offset_p = NULL;
113 if (index)
115 act_elem = index;
116 if (step)
118 act_elem = gen_rtx_MULT (address_mode, act_elem, step);
120 if (step_p)
121 *step_p = &XEXP (act_elem, 1);
124 *addr = act_elem;
127 if (base && base != const0_rtx)
129 if (*addr)
130 *addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
131 else
132 *addr = base;
135 if (symbol)
137 act_elem = symbol;
138 if (offset)
140 act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
142 if (offset_p)
143 *offset_p = &XEXP (act_elem, 1);
145 if (GET_CODE (symbol) == SYMBOL_REF
146 || GET_CODE (symbol) == LABEL_REF
147 || GET_CODE (symbol) == CONST)
148 act_elem = gen_rtx_CONST (address_mode, act_elem);
151 if (*addr)
152 *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
153 else
154 *addr = act_elem;
156 else if (offset)
158 if (*addr)
160 *addr = gen_rtx_PLUS (address_mode, *addr, offset);
161 if (offset_p)
162 *offset_p = &XEXP (*addr, 1);
164 else
166 *addr = offset;
167 if (offset_p)
168 *offset_p = addr;
172 if (!*addr)
173 *addr = const0_rtx;
176 /* Returns address for TARGET_MEM_REF with parameters given by ADDR
177 in address space AS.
178 If REALLY_EXPAND is false, just make fake registers instead
179 of really expanding the operands, and perform the expansion in-place
180 by using one of the "templates". */
183 addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
184 bool really_expand)
186 enum machine_mode address_mode = targetm.addr_space.address_mode (as);
187 enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
188 rtx address, sym, bse, idx, st, off;
189 struct mem_addr_template *templ;
191 if (addr->step && !integer_onep (addr->step))
192 st = immed_double_int_const (tree_to_double_int (addr->step), pointer_mode);
193 else
194 st = NULL_RTX;
196 if (addr->offset && !integer_zerop (addr->offset))
197 off = immed_double_int_const
198 (tree_to_double_int (addr->offset)
199 .sext (TYPE_PRECISION (TREE_TYPE (addr->offset))),
200 pointer_mode);
201 else
202 off = NULL_RTX;
204 if (!really_expand)
206 unsigned int templ_index
207 = TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
209 if (templ_index >= vec_safe_length (mem_addr_template_list))
210 vec_safe_grow_cleared (mem_addr_template_list, templ_index + 1);
212 /* Reuse the templates for addresses, so that we do not waste memory. */
213 templ = &(*mem_addr_template_list)[templ_index];
214 if (!templ->ref)
216 sym = (addr->symbol ?
217 gen_rtx_SYMBOL_REF (pointer_mode, ggc_strdup ("test_symbol"))
218 : NULL_RTX);
219 bse = (addr->base ?
220 gen_raw_REG (pointer_mode, LAST_VIRTUAL_REGISTER + 1)
221 : NULL_RTX);
222 idx = (addr->index ?
223 gen_raw_REG (pointer_mode, LAST_VIRTUAL_REGISTER + 2)
224 : NULL_RTX);
226 gen_addr_rtx (pointer_mode, sym, bse, idx,
227 st? const0_rtx : NULL_RTX,
228 off? const0_rtx : NULL_RTX,
229 &templ->ref,
230 &templ->step_p,
231 &templ->off_p);
234 if (st)
235 *templ->step_p = st;
236 if (off)
237 *templ->off_p = off;
239 return templ->ref;
242 /* Otherwise really expand the expressions. */
243 sym = (addr->symbol
244 ? expand_expr (addr->symbol, NULL_RTX, pointer_mode, EXPAND_NORMAL)
245 : NULL_RTX);
246 bse = (addr->base
247 ? expand_expr (addr->base, NULL_RTX, pointer_mode, EXPAND_NORMAL)
248 : NULL_RTX);
249 idx = (addr->index
250 ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL)
251 : NULL_RTX);
253 gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL);
254 if (pointer_mode != address_mode)
255 address = convert_memory_address (address_mode, address);
256 return address;
259 /* Returns address of MEM_REF in TYPE. */
261 tree
262 tree_mem_ref_addr (tree type, tree mem_ref)
264 tree addr;
265 tree act_elem;
266 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
267 tree addr_base = NULL_TREE, addr_off = NULL_TREE;
269 addr_base = fold_convert (type, TMR_BASE (mem_ref));
271 act_elem = TMR_INDEX (mem_ref);
272 if (act_elem)
274 if (step)
275 act_elem = fold_build2 (MULT_EXPR, TREE_TYPE (act_elem),
276 act_elem, step);
277 addr_off = act_elem;
280 act_elem = TMR_INDEX2 (mem_ref);
281 if (act_elem)
283 if (addr_off)
284 addr_off = fold_build2 (PLUS_EXPR, TREE_TYPE (addr_off),
285 addr_off, act_elem);
286 else
287 addr_off = act_elem;
290 if (offset && !integer_zerop (offset))
292 if (addr_off)
293 addr_off = fold_build2 (PLUS_EXPR, TREE_TYPE (addr_off), addr_off,
294 fold_convert (TREE_TYPE (addr_off), offset));
295 else
296 addr_off = offset;
299 if (addr_off)
300 addr = fold_build_pointer_plus (addr_base, addr_off);
301 else
302 addr = addr_base;
304 return addr;
307 /* Returns true if a memory reference in MODE and with parameters given by
308 ADDR is valid on the current target. */
310 static bool
311 valid_mem_ref_p (enum machine_mode mode, addr_space_t as,
312 struct mem_address *addr)
314 rtx address;
316 address = addr_for_mem_ref (addr, as, false);
317 if (!address)
318 return false;
320 return memory_address_addr_space_p (mode, address, as);
323 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
324 is valid on the current target and if so, creates and returns the
325 TARGET_MEM_REF. If VERIFY is false omit the verification step. */
327 static tree
328 create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr,
329 bool verify)
331 tree base, index2;
333 if (verify
334 && !valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
335 return NULL_TREE;
337 if (addr->step && integer_onep (addr->step))
338 addr->step = NULL_TREE;
340 if (addr->offset)
341 addr->offset = fold_convert (alias_ptr_type, addr->offset);
342 else
343 addr->offset = build_int_cst (alias_ptr_type, 0);
345 if (addr->symbol)
347 base = addr->symbol;
348 index2 = addr->base;
350 else if (addr->base
351 && POINTER_TYPE_P (TREE_TYPE (addr->base)))
353 base = addr->base;
354 index2 = NULL_TREE;
356 else
358 base = build_int_cst (ptr_type_node, 0);
359 index2 = addr->base;
362 /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF.
363 ??? As IVOPTs does not follow restrictions to where the base
364 pointer may point to create a MEM_REF only if we know that
365 base is valid. */
366 if ((TREE_CODE (base) == ADDR_EXPR || TREE_CODE (base) == INTEGER_CST)
367 && (!index2 || integer_zerop (index2))
368 && (!addr->index || integer_zerop (addr->index)))
369 return fold_build2 (MEM_REF, type, base, addr->offset);
371 return build5 (TARGET_MEM_REF, type,
372 base, addr->offset, addr->index, addr->step, index2);
375 /* Returns true if OBJ is an object whose address is a link time constant. */
377 static bool
378 fixed_address_object_p (tree obj)
380 return (TREE_CODE (obj) == VAR_DECL
381 && (TREE_STATIC (obj)
382 || DECL_EXTERNAL (obj))
383 && ! DECL_DLLIMPORT_P (obj));
386 /* If ADDR contains an address of object that is a link time constant,
387 move it to PARTS->symbol. */
389 static void
390 move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
392 unsigned i;
393 tree val = NULL_TREE;
395 for (i = 0; i < addr->n; i++)
397 if (!addr->elts[i].coef.is_one ())
398 continue;
400 val = addr->elts[i].val;
401 if (TREE_CODE (val) == ADDR_EXPR
402 && fixed_address_object_p (TREE_OPERAND (val, 0)))
403 break;
406 if (i == addr->n)
407 return;
409 parts->symbol = val;
410 aff_combination_remove_elt (addr, i);
413 /* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */
415 static void
416 move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
417 aff_tree *addr)
419 unsigned i;
420 tree val = NULL_TREE;
421 int qual;
423 for (i = 0; i < addr->n; i++)
425 if (!addr->elts[i].coef.is_one ())
426 continue;
428 val = addr->elts[i].val;
429 if (operand_equal_p (val, base_hint, 0))
430 break;
433 if (i == addr->n)
434 return;
436 /* Cast value to appropriate pointer type. We cannot use a pointer
437 to TYPE directly, as the back-end will assume registers of pointer
438 type are aligned, and just the base itself may not actually be.
439 We use void pointer to the type's address space instead. */
440 qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type));
441 type = build_qualified_type (void_type_node, qual);
442 parts->base = fold_convert (build_pointer_type (type), val);
443 aff_combination_remove_elt (addr, i);
446 /* If ADDR contains an address of a dereferenced pointer, move it to
447 PARTS->base. */
449 static void
450 move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
452 unsigned i;
453 tree val = NULL_TREE;
455 for (i = 0; i < addr->n; i++)
457 if (!addr->elts[i].coef.is_one ())
458 continue;
460 val = addr->elts[i].val;
461 if (POINTER_TYPE_P (TREE_TYPE (val)))
462 break;
465 if (i == addr->n)
466 return;
468 parts->base = val;
469 aff_combination_remove_elt (addr, i);
472 /* Moves the loop variant part V in linear address ADDR to be the index
473 of PARTS. */
475 static void
476 move_variant_to_index (struct mem_address *parts, aff_tree *addr, tree v)
478 unsigned i;
479 tree val = NULL_TREE;
481 gcc_assert (!parts->index);
482 for (i = 0; i < addr->n; i++)
484 val = addr->elts[i].val;
485 if (operand_equal_p (val, v, 0))
486 break;
489 if (i == addr->n)
490 return;
492 parts->index = fold_convert (sizetype, val);
493 parts->step = double_int_to_tree (sizetype, addr->elts[i].coef);
494 aff_combination_remove_elt (addr, i);
497 /* Adds ELT to PARTS. */
499 static void
500 add_to_parts (struct mem_address *parts, tree elt)
502 tree type;
504 if (!parts->index)
506 parts->index = fold_convert (sizetype, elt);
507 return;
510 if (!parts->base)
512 parts->base = elt;
513 return;
516 /* Add ELT to base. */
517 type = TREE_TYPE (parts->base);
518 if (POINTER_TYPE_P (type))
519 parts->base = fold_build_pointer_plus (parts->base, elt);
520 else
521 parts->base = fold_build2 (PLUS_EXPR, type,
522 parts->base, elt);
525 /* Finds the most expensive multiplication in ADDR that can be
526 expressed in an addressing mode and move the corresponding
527 element(s) to PARTS. */
529 static void
530 most_expensive_mult_to_index (tree type, struct mem_address *parts,
531 aff_tree *addr, bool speed)
533 addr_space_t as = TYPE_ADDR_SPACE (type);
534 enum machine_mode address_mode = targetm.addr_space.address_mode (as);
535 HOST_WIDE_INT coef;
536 double_int best_mult, amult, amult_neg;
537 unsigned best_mult_cost = 0, acost;
538 tree mult_elt = NULL_TREE, elt;
539 unsigned i, j;
540 enum tree_code op_code;
542 best_mult = double_int_zero;
543 for (i = 0; i < addr->n; i++)
545 if (!addr->elts[i].coef.fits_shwi ())
546 continue;
548 coef = addr->elts[i].coef.to_shwi ();
549 if (coef == 1
550 || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
551 continue;
553 acost = mult_by_coeff_cost (coef, address_mode, speed);
555 if (acost > best_mult_cost)
557 best_mult_cost = acost;
558 best_mult = addr->elts[i].coef;
562 if (!best_mult_cost)
563 return;
565 /* Collect elements multiplied by best_mult. */
566 for (i = j = 0; i < addr->n; i++)
568 amult = addr->elts[i].coef;
569 amult_neg = double_int_ext_for_comb (-amult, addr);
571 if (amult == best_mult)
572 op_code = PLUS_EXPR;
573 else if (amult_neg == best_mult)
574 op_code = MINUS_EXPR;
575 else
577 addr->elts[j] = addr->elts[i];
578 j++;
579 continue;
582 elt = fold_convert (sizetype, addr->elts[i].val);
583 if (mult_elt)
584 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
585 else if (op_code == PLUS_EXPR)
586 mult_elt = elt;
587 else
588 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
590 addr->n = j;
592 parts->index = mult_elt;
593 parts->step = double_int_to_tree (sizetype, best_mult);
596 /* Splits address ADDR for a memory access of type TYPE into PARTS.
597 If BASE_HINT is non-NULL, it specifies an SSA name to be used
598 preferentially as base of the reference, and IV_CAND is the selected
599 iv candidate used in ADDR.
601 TODO -- be more clever about the distribution of the elements of ADDR
602 to PARTS. Some architectures do not support anything but single
603 register in address, possibly with a small integer offset; while
604 create_mem_ref will simplify the address to an acceptable shape
605 later, it would be more efficient to know that asking for complicated
606 addressing modes is useless. */
608 static void
609 addr_to_parts (tree type, aff_tree *addr, tree iv_cand,
610 tree base_hint, struct mem_address *parts,
611 bool speed)
613 tree part;
614 unsigned i;
616 parts->symbol = NULL_TREE;
617 parts->base = NULL_TREE;
618 parts->index = NULL_TREE;
619 parts->step = NULL_TREE;
621 if (!addr->offset.is_zero ())
622 parts->offset = double_int_to_tree (sizetype, addr->offset);
623 else
624 parts->offset = NULL_TREE;
626 /* Try to find a symbol. */
627 move_fixed_address_to_symbol (parts, addr);
629 /* No need to do address parts reassociation if the number of parts
630 is <= 2 -- in that case, no loop invariant code motion can be
631 exposed. */
633 if (!base_hint && (addr->n > 2))
634 move_variant_to_index (parts, addr, iv_cand);
636 /* First move the most expensive feasible multiplication
637 to index. */
638 if (!parts->index)
639 most_expensive_mult_to_index (type, parts, addr, speed);
641 /* Try to find a base of the reference. Since at the moment
642 there is no reliable way how to distinguish between pointer and its
643 offset, this is just a guess. */
644 if (!parts->symbol && base_hint)
645 move_hint_to_base (type, parts, base_hint, addr);
646 if (!parts->symbol && !parts->base)
647 move_pointer_to_base (parts, addr);
649 /* Then try to process the remaining elements. */
650 for (i = 0; i < addr->n; i++)
652 part = fold_convert (sizetype, addr->elts[i].val);
653 if (!addr->elts[i].coef.is_one ())
654 part = fold_build2 (MULT_EXPR, sizetype, part,
655 double_int_to_tree (sizetype, addr->elts[i].coef));
656 add_to_parts (parts, part);
658 if (addr->rest)
659 add_to_parts (parts, fold_convert (sizetype, addr->rest));
662 /* Force the PARTS to register. */
664 static void
665 gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
667 if (parts->base)
668 parts->base = force_gimple_operand_gsi_1 (gsi, parts->base,
669 is_gimple_mem_ref_addr, NULL_TREE,
670 true, GSI_SAME_STMT);
671 if (parts->index)
672 parts->index = force_gimple_operand_gsi (gsi, parts->index,
673 true, NULL_TREE,
674 true, GSI_SAME_STMT);
677 /* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
678 computations are emitted in front of GSI. TYPE is the mode
679 of created memory reference. IV_CAND is the selected iv candidate in ADDR,
680 and BASE_HINT is non NULL if IV_CAND comes from a base address
681 object. */
683 tree
684 create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
685 tree alias_ptr_type, tree iv_cand, tree base_hint, bool speed)
687 tree mem_ref, tmp;
688 struct mem_address parts;
690 addr_to_parts (type, addr, iv_cand, base_hint, &parts, speed);
691 gimplify_mem_ref_parts (gsi, &parts);
692 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
693 if (mem_ref)
694 return mem_ref;
696 /* The expression is too complicated. Try making it simpler. */
698 if (parts.step && !integer_onep (parts.step))
700 /* Move the multiplication to index. */
701 gcc_assert (parts.index);
702 parts.index = force_gimple_operand_gsi (gsi,
703 fold_build2 (MULT_EXPR, sizetype,
704 parts.index, parts.step),
705 true, NULL_TREE, true, GSI_SAME_STMT);
706 parts.step = NULL_TREE;
708 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
709 if (mem_ref)
710 return mem_ref;
713 if (parts.symbol)
715 tmp = parts.symbol;
716 gcc_assert (is_gimple_val (tmp));
718 /* Add the symbol to base, eventually forcing it to register. */
719 if (parts.base)
721 gcc_assert (useless_type_conversion_p
722 (sizetype, TREE_TYPE (parts.base)));
724 if (parts.index)
726 parts.base = force_gimple_operand_gsi_1 (gsi,
727 fold_build_pointer_plus (tmp, parts.base),
728 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
730 else
732 parts.index = parts.base;
733 parts.base = tmp;
736 else
737 parts.base = tmp;
738 parts.symbol = NULL_TREE;
740 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
741 if (mem_ref)
742 return mem_ref;
745 if (parts.index)
747 /* Add index to base. */
748 if (parts.base)
750 parts.base = force_gimple_operand_gsi_1 (gsi,
751 fold_build_pointer_plus (parts.base, parts.index),
752 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
754 else
755 parts.base = parts.index;
756 parts.index = NULL_TREE;
758 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
759 if (mem_ref)
760 return mem_ref;
763 if (parts.offset && !integer_zerop (parts.offset))
765 /* Try adding offset to base. */
766 if (parts.base)
768 parts.base = force_gimple_operand_gsi_1 (gsi,
769 fold_build_pointer_plus (parts.base, parts.offset),
770 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
772 else
773 parts.base = parts.offset;
775 parts.offset = NULL_TREE;
777 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts, true);
778 if (mem_ref)
779 return mem_ref;
782 /* Verify that the address is in the simplest possible shape
783 (only a register). If we cannot create such a memory reference,
784 something is really wrong. */
785 gcc_assert (parts.symbol == NULL_TREE);
786 gcc_assert (parts.index == NULL_TREE);
787 gcc_assert (!parts.step || integer_onep (parts.step));
788 gcc_assert (!parts.offset || integer_zerop (parts.offset));
789 gcc_unreachable ();
792 /* Copies components of the address from OP to ADDR. */
794 void
795 get_address_description (tree op, struct mem_address *addr)
797 if (TREE_CODE (TMR_BASE (op)) == ADDR_EXPR)
799 addr->symbol = TMR_BASE (op);
800 addr->base = TMR_INDEX2 (op);
802 else
804 addr->symbol = NULL_TREE;
805 if (TMR_INDEX2 (op))
807 gcc_assert (integer_zerop (TMR_BASE (op)));
808 addr->base = TMR_INDEX2 (op);
810 else
811 addr->base = TMR_BASE (op);
813 addr->index = TMR_INDEX (op);
814 addr->step = TMR_STEP (op);
815 addr->offset = TMR_OFFSET (op);
818 /* Copies the reference information from OLD_REF to NEW_REF, where
819 NEW_REF should be either a MEM_REF or a TARGET_MEM_REF. */
821 void
822 copy_ref_info (tree new_ref, tree old_ref)
824 tree new_ptr_base = NULL_TREE;
826 gcc_assert (TREE_CODE (new_ref) == MEM_REF
827 || TREE_CODE (new_ref) == TARGET_MEM_REF);
829 TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
830 TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
832 new_ptr_base = TREE_OPERAND (new_ref, 0);
834 /* We can transfer points-to information from an old pointer
835 or decl base to the new one. */
836 if (new_ptr_base
837 && TREE_CODE (new_ptr_base) == SSA_NAME
838 && !SSA_NAME_PTR_INFO (new_ptr_base))
840 tree base = get_base_address (old_ref);
841 if (!base)
843 else if ((TREE_CODE (base) == MEM_REF
844 || TREE_CODE (base) == TARGET_MEM_REF)
845 && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
846 && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
848 struct ptr_info_def *new_pi;
849 unsigned int align, misalign;
851 duplicate_ssa_name_ptr_info
852 (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
853 new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
854 /* We have to be careful about transferring alignment information. */
855 if (get_ptr_info_alignment (new_pi, &align, &misalign)
856 && TREE_CODE (old_ref) == MEM_REF
857 && !(TREE_CODE (new_ref) == TARGET_MEM_REF
858 && (TMR_INDEX2 (new_ref)
859 || (TMR_STEP (new_ref)
860 && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
861 < align)))))
863 unsigned int inc = (mem_ref_offset (old_ref)
864 - mem_ref_offset (new_ref)).low;
865 adjust_ptr_info_misalignment (new_pi, inc);
867 else
868 mark_ptr_info_alignment_unknown (new_pi);
870 else if (TREE_CODE (base) == VAR_DECL
871 || TREE_CODE (base) == PARM_DECL
872 || TREE_CODE (base) == RESULT_DECL)
874 struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
875 pt_solution_set_var (&pi->pt, base);
880 /* Move constants in target_mem_ref REF to offset. Returns the new target
881 mem ref if anything changes, NULL_TREE otherwise. */
883 tree
884 maybe_fold_tmr (tree ref)
886 struct mem_address addr;
887 bool changed = false;
888 tree new_ref, off;
890 get_address_description (ref, &addr);
892 if (addr.base
893 && TREE_CODE (addr.base) == INTEGER_CST
894 && !integer_zerop (addr.base))
896 addr.offset = fold_binary_to_constant (PLUS_EXPR,
897 TREE_TYPE (addr.offset),
898 addr.offset, addr.base);
899 addr.base = NULL_TREE;
900 changed = true;
903 if (addr.symbol
904 && TREE_CODE (TREE_OPERAND (addr.symbol, 0)) == MEM_REF)
906 addr.offset = fold_binary_to_constant
907 (PLUS_EXPR, TREE_TYPE (addr.offset),
908 addr.offset,
909 TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 1));
910 addr.symbol = TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 0);
911 changed = true;
913 else if (addr.symbol
914 && handled_component_p (TREE_OPERAND (addr.symbol, 0)))
916 HOST_WIDE_INT offset;
917 addr.symbol = build_fold_addr_expr
918 (get_addr_base_and_unit_offset
919 (TREE_OPERAND (addr.symbol, 0), &offset));
920 addr.offset = int_const_binop (PLUS_EXPR,
921 addr.offset, size_int (offset));
922 changed = true;
925 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
927 off = addr.index;
928 if (addr.step)
930 off = fold_binary_to_constant (MULT_EXPR, sizetype,
931 off, addr.step);
932 addr.step = NULL_TREE;
935 addr.offset = fold_binary_to_constant (PLUS_EXPR,
936 TREE_TYPE (addr.offset),
937 addr.offset, off);
938 addr.index = NULL_TREE;
939 changed = true;
942 if (!changed)
943 return NULL_TREE;
945 /* If we have propagated something into this TARGET_MEM_REF and thus
946 ended up folding it, always create a new TARGET_MEM_REF regardless
947 if it is valid in this for on the target - the propagation result
948 wouldn't be anyway. */
949 new_ref = create_mem_ref_raw (TREE_TYPE (ref),
950 TREE_TYPE (addr.offset), &addr, false);
951 TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (ref);
952 TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (ref);
953 return new_ref;
956 /* Dump PARTS to FILE. */
958 extern void dump_mem_address (FILE *, struct mem_address *);
959 void
960 dump_mem_address (FILE *file, struct mem_address *parts)
962 if (parts->symbol)
964 fprintf (file, "symbol: ");
965 print_generic_expr (file, TREE_OPERAND (parts->symbol, 0), TDF_SLIM);
966 fprintf (file, "\n");
968 if (parts->base)
970 fprintf (file, "base: ");
971 print_generic_expr (file, parts->base, TDF_SLIM);
972 fprintf (file, "\n");
974 if (parts->index)
976 fprintf (file, "index: ");
977 print_generic_expr (file, parts->index, TDF_SLIM);
978 fprintf (file, "\n");
980 if (parts->step)
982 fprintf (file, "step: ");
983 print_generic_expr (file, parts->step, TDF_SLIM);
984 fprintf (file, "\n");
986 if (parts->offset)
988 fprintf (file, "offset: ");
989 print_generic_expr (file, parts->offset, TDF_SLIM);
990 fprintf (file, "\n");
994 #include "gt-tree-ssa-address.h"