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
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
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. */
25 #include "coretypes.h"
29 #include "basic-block.h"
30 #include "tree-pretty-print.h"
31 #include "tree-flow.h"
34 #include "tree-inline.h"
35 #include "tree-affine.h"
37 /* FIXME: We compute address costs using RTL. */
38 #include "insn-config.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
70 /* A "template" for memory address, used to determine whether the address is
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
77 rtx
* GTY ((skip
)) off_p
; /* The point in template where the offset should
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) \
90 | ((SYMBOL != 0) << 4) \
91 | ((BASE != 0) << 3) \
92 | ((INDEX != 0) << 2) \
93 | ((STEP != 0) << 1) \
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. */
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
)
118 act_elem
= gen_rtx_MULT (address_mode
, act_elem
, step
);
121 *step_p
= &XEXP (act_elem
, 1);
127 if (base
&& base
!= const0_rtx
)
130 *addr
= simplify_gen_binary (PLUS
, address_mode
, base
, *addr
);
140 act_elem
= gen_rtx_PLUS (address_mode
, act_elem
, offset
);
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
);
152 *addr
= gen_rtx_PLUS (address_mode
, *addr
, act_elem
);
160 *addr
= gen_rtx_PLUS (address_mode
, *addr
, offset
);
162 *offset_p
= &XEXP (*addr
, 1);
176 /* Returns address for TARGET_MEM_REF with parameters given by ADDR
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
,
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
);
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
))),
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
];
216 sym
= (addr
->symbol
?
217 gen_rtx_SYMBOL_REF (pointer_mode
, ggc_strdup ("test_symbol"))
220 gen_raw_REG (pointer_mode
, LAST_VIRTUAL_REGISTER
+ 1)
223 gen_raw_REG (pointer_mode
, LAST_VIRTUAL_REGISTER
+ 2)
226 gen_addr_rtx (pointer_mode
, sym
, bse
, idx
,
227 st
? const0_rtx
: NULL_RTX
,
228 off
? const0_rtx
: NULL_RTX
,
242 /* Otherwise really expand the expressions. */
244 ? expand_expr (addr
->symbol
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
247 ? expand_expr (addr
->base
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
250 ? expand_expr (addr
->index
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
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
);
259 /* Returns address of MEM_REF in TYPE. */
262 tree_mem_ref_addr (tree type
, tree mem_ref
)
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
);
275 act_elem
= fold_build2 (MULT_EXPR
, TREE_TYPE (act_elem
),
280 act_elem
= TMR_INDEX2 (mem_ref
);
284 addr_off
= fold_build2 (PLUS_EXPR
, TREE_TYPE (addr_off
),
290 if (offset
&& !integer_zerop (offset
))
293 addr_off
= fold_build2 (PLUS_EXPR
, TREE_TYPE (addr_off
), addr_off
,
294 fold_convert (TREE_TYPE (addr_off
), offset
));
300 addr
= fold_build_pointer_plus (addr_base
, addr_off
);
307 /* Returns true if a memory reference in MODE and with parameters given by
308 ADDR is valid on the current target. */
311 valid_mem_ref_p (enum machine_mode mode
, addr_space_t as
,
312 struct mem_address
*addr
)
316 address
= addr_for_mem_ref (addr
, as
, 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. */
328 create_mem_ref_raw (tree type
, tree alias_ptr_type
, struct mem_address
*addr
,
334 && !valid_mem_ref_p (TYPE_MODE (type
), TYPE_ADDR_SPACE (type
), addr
))
337 if (addr
->step
&& integer_onep (addr
->step
))
338 addr
->step
= NULL_TREE
;
341 addr
->offset
= fold_convert (alias_ptr_type
, addr
->offset
);
343 addr
->offset
= build_int_cst (alias_ptr_type
, 0);
351 && POINTER_TYPE_P (TREE_TYPE (addr
->base
)))
358 base
= build_int_cst (ptr_type_node
, 0);
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
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. */
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. */
390 move_fixed_address_to_symbol (struct mem_address
*parts
, aff_tree
*addr
)
393 tree val
= NULL_TREE
;
395 for (i
= 0; i
< addr
->n
; i
++)
397 if (!addr
->elts
[i
].coef
.is_one ())
400 val
= addr
->elts
[i
].val
;
401 if (TREE_CODE (val
) == ADDR_EXPR
402 && fixed_address_object_p (TREE_OPERAND (val
, 0)))
410 aff_combination_remove_elt (addr
, i
);
413 /* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */
416 move_hint_to_base (tree type
, struct mem_address
*parts
, tree base_hint
,
420 tree val
= NULL_TREE
;
423 for (i
= 0; i
< addr
->n
; i
++)
425 if (!addr
->elts
[i
].coef
.is_one ())
428 val
= addr
->elts
[i
].val
;
429 if (operand_equal_p (val
, base_hint
, 0))
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
450 move_pointer_to_base (struct mem_address
*parts
, aff_tree
*addr
)
453 tree val
= NULL_TREE
;
455 for (i
= 0; i
< addr
->n
; i
++)
457 if (!addr
->elts
[i
].coef
.is_one ())
460 val
= addr
->elts
[i
].val
;
461 if (POINTER_TYPE_P (TREE_TYPE (val
)))
469 aff_combination_remove_elt (addr
, i
);
472 /* Moves the loop variant part V in linear address ADDR to be the index
476 move_variant_to_index (struct mem_address
*parts
, aff_tree
*addr
, tree v
)
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))
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. */
500 add_to_parts (struct mem_address
*parts
, tree elt
)
506 parts
->index
= fold_convert (sizetype
, elt
);
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
);
521 parts
->base
= fold_build2 (PLUS_EXPR
, type
,
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. */
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
);
536 double_int best_mult
, amult
, amult_neg
;
537 unsigned best_mult_cost
= 0, acost
;
538 tree mult_elt
= NULL_TREE
, elt
;
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 ())
548 coef
= addr
->elts
[i
].coef
.to_shwi ();
550 || !multiplier_allowed_in_address_p (coef
, TYPE_MODE (type
), as
))
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
;
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
)
573 else if (amult_neg
== best_mult
)
574 op_code
= MINUS_EXPR
;
577 addr
->elts
[j
] = addr
->elts
[i
];
582 elt
= fold_convert (sizetype
, addr
->elts
[i
].val
);
584 mult_elt
= fold_build2 (op_code
, sizetype
, mult_elt
, elt
);
585 else if (op_code
== PLUS_EXPR
)
588 mult_elt
= fold_build1 (NEGATE_EXPR
, sizetype
, elt
);
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. */
609 addr_to_parts (tree type
, aff_tree
*addr
, tree iv_cand
,
610 tree base_hint
, struct mem_address
*parts
,
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
);
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
633 if (!base_hint
&& (addr
->n
> 2))
634 move_variant_to_index (parts
, addr
, iv_cand
);
636 /* First move the most expensive feasible multiplication
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
);
659 add_to_parts (parts
, fold_convert (sizetype
, addr
->rest
));
662 /* Force the PARTS to register. */
665 gimplify_mem_ref_parts (gimple_stmt_iterator
*gsi
, struct mem_address
*parts
)
668 parts
->base
= force_gimple_operand_gsi_1 (gsi
, parts
->base
,
669 is_gimple_mem_ref_addr
, NULL_TREE
,
670 true, GSI_SAME_STMT
);
672 parts
->index
= force_gimple_operand_gsi (gsi
, parts
->index
,
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
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
)
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);
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);
716 gcc_assert (is_gimple_val (tmp
));
718 /* Add the symbol to base, eventually forcing it to register. */
721 gcc_assert (useless_type_conversion_p
722 (sizetype
, TREE_TYPE (parts
.base
)));
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
);
732 parts
.index
= parts
.base
;
738 parts
.symbol
= NULL_TREE
;
740 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
747 /* Add index to 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
);
755 parts
.base
= parts
.index
;
756 parts
.index
= NULL_TREE
;
758 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
763 if (parts
.offset
&& !integer_zerop (parts
.offset
))
765 /* Try adding offset to 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
);
773 parts
.base
= parts
.offset
;
775 parts
.offset
= NULL_TREE
;
777 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
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
));
792 /* Copies components of the address from OP to ADDR. */
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
);
804 addr
->symbol
= NULL_TREE
;
807 gcc_assert (integer_zerop (TMR_BASE (op
)));
808 addr
->base
= TMR_INDEX2 (op
);
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. */
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. */
837 && TREE_CODE (new_ptr_base
) == SSA_NAME
838 && !SSA_NAME_PTR_INFO (new_ptr_base
))
840 tree base
= get_base_address (old_ref
);
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
))
863 unsigned int inc
= (mem_ref_offset (old_ref
)
864 - mem_ref_offset (new_ref
)).low
;
865 adjust_ptr_info_misalignment (new_pi
, inc
);
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. */
884 maybe_fold_tmr (tree ref
)
886 struct mem_address addr
;
887 bool changed
= false;
890 get_address_description (ref
, &addr
);
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
;
904 && TREE_CODE (TREE_OPERAND (addr
.symbol
, 0)) == MEM_REF
)
906 addr
.offset
= fold_binary_to_constant
907 (PLUS_EXPR
, TREE_TYPE (addr
.offset
),
909 TREE_OPERAND (TREE_OPERAND (addr
.symbol
, 0), 1));
910 addr
.symbol
= TREE_OPERAND (TREE_OPERAND (addr
.symbol
, 0), 0);
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
));
925 if (addr
.index
&& TREE_CODE (addr
.index
) == INTEGER_CST
)
930 off
= fold_binary_to_constant (MULT_EXPR
, sizetype
,
932 addr
.step
= NULL_TREE
;
935 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
,
936 TREE_TYPE (addr
.offset
),
938 addr
.index
= 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
);
956 /* Dump PARTS to FILE. */
958 extern void dump_mem_address (FILE *, struct mem_address
*);
960 dump_mem_address (FILE *file
, struct mem_address
*parts
)
964 fprintf (file
, "symbol: ");
965 print_generic_expr (file
, TREE_OPERAND (parts
->symbol
, 0), TDF_SLIM
);
966 fprintf (file
, "\n");
970 fprintf (file
, "base: ");
971 print_generic_expr (file
, parts
->base
, TDF_SLIM
);
972 fprintf (file
, "\n");
976 fprintf (file
, "index: ");
977 print_generic_expr (file
, parts
->index
, TDF_SLIM
);
978 fprintf (file
, "\n");
982 fprintf (file
, "step: ");
983 print_generic_expr (file
, parts
->step
, TDF_SLIM
);
984 fprintf (file
, "\n");
988 fprintf (file
, "offset: ");
989 print_generic_expr (file
, parts
->offset
, TDF_SLIM
);
990 fprintf (file
, "\n");
994 #include "gt-tree-ssa-address.h"