1 /* Memory address lowering and addressing mode selection.
2 Copyright (C) 2004-2019 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"
32 #include "stringpool.h"
34 #include "tree-ssanames.h"
36 #include "insn-config.h"
39 #include "tree-pretty-print.h"
40 #include "fold-const.h"
41 #include "stor-layout.h"
42 #include "gimple-iterator.h"
43 #include "gimplify-me.h"
44 #include "tree-ssa-loop-ivopts.h"
48 #include "tree-affine.h"
51 /* FIXME: We compute address costs using RTL. */
52 #include "tree-ssa-address.h"
54 /* TODO -- handling of symbols (according to Richard Hendersons
55 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
57 There are at least 5 different kinds of symbols that we can run up against:
59 (1) binds_local_p, small data area.
60 (2) binds_local_p, eg local statics
61 (3) !binds_local_p, eg global variables
62 (4) thread local, local_exec
63 (5) thread local, !local_exec
65 Now, (1) won't appear often in an array context, but it certainly can.
66 All you have to do is set -GN high enough, or explicitly mark any
67 random object __attribute__((section (".sdata"))).
69 All of these affect whether or not a symbol is in fact a valid address.
70 The only one tested here is (3). And that result may very well
71 be incorrect for (4) or (5).
73 An incorrect result here does not cause incorrect results out the
74 back end, because the expander in expr.c validizes the address. However
75 it would be nice to improve the handling here in order to produce more
78 /* A "template" for memory address, used to determine whether the address is
81 struct GTY (()) mem_addr_template
{
82 rtx ref
; /* The template. */
83 rtx
* GTY ((skip
)) step_p
; /* The point in template where the step should be
85 rtx
* GTY ((skip
)) off_p
; /* The point in template where the offset should
90 /* The templates. Each of the low five bits of the index corresponds to one
91 component of TARGET_MEM_REF being present, while the high bits identify
92 the address space. See TEMPL_IDX. */
94 static GTY(()) vec
<mem_addr_template
, va_gc
> *mem_addr_template_list
;
96 #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
98 | ((SYMBOL != 0) << 4) \
99 | ((BASE != 0) << 3) \
100 | ((INDEX != 0) << 2) \
101 | ((STEP != 0) << 1) \
104 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
105 STEP and OFFSET to *ADDR using address mode ADDRESS_MODE. Stores pointers
106 to where step is placed to *STEP_P and offset to *OFFSET_P. */
109 gen_addr_rtx (machine_mode address_mode
,
110 rtx symbol
, rtx base
, rtx index
, rtx step
, rtx offset
,
111 rtx
*addr
, rtx
**step_p
, rtx
**offset_p
)
121 if (index
&& index
!= const0_rtx
)
126 act_elem
= gen_rtx_MULT (address_mode
, act_elem
, step
);
129 *step_p
= &XEXP (act_elem
, 1);
135 if (base
&& base
!= const0_rtx
)
138 *addr
= simplify_gen_binary (PLUS
, address_mode
, base
, *addr
);
148 act_elem
= gen_rtx_PLUS (address_mode
, act_elem
, offset
);
151 *offset_p
= &XEXP (act_elem
, 1);
153 if (GET_CODE (symbol
) == SYMBOL_REF
154 || GET_CODE (symbol
) == LABEL_REF
155 || GET_CODE (symbol
) == CONST
)
156 act_elem
= gen_rtx_CONST (address_mode
, act_elem
);
160 *addr
= gen_rtx_PLUS (address_mode
, *addr
, act_elem
);
168 *addr
= gen_rtx_PLUS (address_mode
, *addr
, offset
);
170 *offset_p
= &XEXP (*addr
, 1);
184 /* Returns address for TARGET_MEM_REF with parameters given by ADDR
186 If REALLY_EXPAND is false, just make fake registers instead
187 of really expanding the operands, and perform the expansion in-place
188 by using one of the "templates". */
191 addr_for_mem_ref (struct mem_address
*addr
, addr_space_t as
,
194 scalar_int_mode address_mode
= targetm
.addr_space
.address_mode (as
);
195 scalar_int_mode pointer_mode
= targetm
.addr_space
.pointer_mode (as
);
196 rtx address
, sym
, bse
, idx
, st
, off
;
197 struct mem_addr_template
*templ
;
199 if (addr
->step
&& !integer_onep (addr
->step
))
200 st
= immed_wide_int_const (wi::to_wide (addr
->step
), pointer_mode
);
204 if (addr
->offset
&& !integer_zerop (addr
->offset
))
207 = poly_offset_int::from (wi::to_poly_wide (addr
->offset
), SIGNED
);
208 off
= immed_wide_int_const (dc
, pointer_mode
);
215 unsigned int templ_index
216 = TEMPL_IDX (as
, addr
->symbol
, addr
->base
, addr
->index
, st
, off
);
218 if (templ_index
>= vec_safe_length (mem_addr_template_list
))
219 vec_safe_grow_cleared (mem_addr_template_list
, templ_index
+ 1);
221 /* Reuse the templates for addresses, so that we do not waste memory. */
222 templ
= &(*mem_addr_template_list
)[templ_index
];
225 sym
= (addr
->symbol
?
226 gen_rtx_SYMBOL_REF (pointer_mode
, ggc_strdup ("test_symbol"))
229 gen_raw_REG (pointer_mode
, LAST_VIRTUAL_REGISTER
+ 1)
232 gen_raw_REG (pointer_mode
, LAST_VIRTUAL_REGISTER
+ 2)
235 gen_addr_rtx (pointer_mode
, sym
, bse
, idx
,
236 st
? const0_rtx
: NULL_RTX
,
237 off
? const0_rtx
: NULL_RTX
,
251 /* Otherwise really expand the expressions. */
253 ? expand_expr (addr
->symbol
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
256 ? expand_expr (addr
->base
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
259 ? expand_expr (addr
->index
, NULL_RTX
, pointer_mode
, EXPAND_NORMAL
)
262 gen_addr_rtx (pointer_mode
, sym
, bse
, idx
, st
, off
, &address
, NULL
, NULL
);
263 if (pointer_mode
!= address_mode
)
264 address
= convert_memory_address (address_mode
, address
);
268 /* implement addr_for_mem_ref() directly from a tree, which avoids exporting
269 the mem_address structure. */
272 addr_for_mem_ref (tree exp
, addr_space_t as
, bool really_expand
)
274 struct mem_address addr
;
275 get_address_description (exp
, &addr
);
276 return addr_for_mem_ref (&addr
, as
, really_expand
);
279 /* Returns address of MEM_REF in TYPE. */
282 tree_mem_ref_addr (tree type
, tree mem_ref
)
286 tree step
= TMR_STEP (mem_ref
), offset
= TMR_OFFSET (mem_ref
);
287 tree addr_base
= NULL_TREE
, addr_off
= NULL_TREE
;
289 addr_base
= fold_convert (type
, TMR_BASE (mem_ref
));
291 act_elem
= TMR_INDEX (mem_ref
);
295 act_elem
= fold_build2 (MULT_EXPR
, TREE_TYPE (act_elem
),
300 act_elem
= TMR_INDEX2 (mem_ref
);
304 addr_off
= fold_build2 (PLUS_EXPR
, TREE_TYPE (addr_off
),
310 if (offset
&& !integer_zerop (offset
))
313 addr_off
= fold_build2 (PLUS_EXPR
, TREE_TYPE (addr_off
), addr_off
,
314 fold_convert (TREE_TYPE (addr_off
), offset
));
320 addr
= fold_build_pointer_plus (addr_base
, addr_off
);
327 /* Returns true if a memory reference in MODE and with parameters given by
328 ADDR is valid on the current target. */
331 valid_mem_ref_p (machine_mode mode
, addr_space_t as
,
332 struct mem_address
*addr
)
336 address
= addr_for_mem_ref (addr
, as
, false);
340 return memory_address_addr_space_p (mode
, address
, as
);
343 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
344 is valid on the current target and if so, creates and returns the
345 TARGET_MEM_REF. If VERIFY is false omit the verification step. */
348 create_mem_ref_raw (tree type
, tree alias_ptr_type
, struct mem_address
*addr
,
354 && !valid_mem_ref_p (TYPE_MODE (type
), TYPE_ADDR_SPACE (type
), addr
))
357 if (addr
->step
&& integer_onep (addr
->step
))
358 addr
->step
= NULL_TREE
;
361 addr
->offset
= fold_convert (alias_ptr_type
, addr
->offset
);
363 addr
->offset
= build_int_cst (alias_ptr_type
, 0);
371 && POINTER_TYPE_P (TREE_TYPE (addr
->base
)))
378 base
= build_int_cst (build_pointer_type (type
), 0);
382 /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF.
383 ??? As IVOPTs does not follow restrictions to where the base
384 pointer may point to create a MEM_REF only if we know that
386 if ((TREE_CODE (base
) == ADDR_EXPR
|| TREE_CODE (base
) == INTEGER_CST
)
387 && (!index2
|| integer_zerop (index2
))
388 && (!addr
->index
|| integer_zerop (addr
->index
)))
389 return fold_build2 (MEM_REF
, type
, base
, addr
->offset
);
391 return build5 (TARGET_MEM_REF
, type
,
392 base
, addr
->offset
, addr
->index
, addr
->step
, index2
);
395 /* Returns true if OBJ is an object whose address is a link time constant. */
398 fixed_address_object_p (tree obj
)
401 && (TREE_STATIC (obj
) || DECL_EXTERNAL (obj
))
402 && ! DECL_DLLIMPORT_P (obj
));
405 /* If ADDR contains an address of object that is a link time constant,
406 move it to PARTS->symbol. */
409 move_fixed_address_to_symbol (struct mem_address
*parts
, aff_tree
*addr
)
412 tree val
= NULL_TREE
;
414 for (i
= 0; i
< addr
->n
; i
++)
416 if (addr
->elts
[i
].coef
!= 1)
419 val
= addr
->elts
[i
].val
;
420 if (TREE_CODE (val
) == ADDR_EXPR
421 && fixed_address_object_p (TREE_OPERAND (val
, 0)))
429 aff_combination_remove_elt (addr
, i
);
432 /* Return true if ADDR contains an instance of BASE_HINT and it's moved to
436 move_hint_to_base (tree type
, struct mem_address
*parts
, tree base_hint
,
440 tree val
= NULL_TREE
;
443 for (i
= 0; i
< addr
->n
; i
++)
445 if (addr
->elts
[i
].coef
!= 1)
448 val
= addr
->elts
[i
].val
;
449 if (operand_equal_p (val
, base_hint
, 0))
456 /* Cast value to appropriate pointer type. We cannot use a pointer
457 to TYPE directly, as the back-end will assume registers of pointer
458 type are aligned, and just the base itself may not actually be.
459 We use void pointer to the type's address space instead. */
460 qual
= ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type
));
461 type
= build_qualified_type (void_type_node
, qual
);
462 parts
->base
= fold_convert (build_pointer_type (type
), val
);
463 aff_combination_remove_elt (addr
, i
);
467 /* If ADDR contains an address of a dereferenced pointer, move it to
471 move_pointer_to_base (struct mem_address
*parts
, aff_tree
*addr
)
474 tree val
= NULL_TREE
;
476 for (i
= 0; i
< addr
->n
; i
++)
478 if (addr
->elts
[i
].coef
!= 1)
481 val
= addr
->elts
[i
].val
;
482 if (POINTER_TYPE_P (TREE_TYPE (val
)))
490 aff_combination_remove_elt (addr
, i
);
493 /* Moves the loop variant part V in linear address ADDR to be the index
497 move_variant_to_index (struct mem_address
*parts
, aff_tree
*addr
, tree v
)
500 tree val
= NULL_TREE
;
502 gcc_assert (!parts
->index
);
503 for (i
= 0; i
< addr
->n
; i
++)
505 val
= addr
->elts
[i
].val
;
506 if (operand_equal_p (val
, v
, 0))
513 parts
->index
= fold_convert (sizetype
, val
);
514 parts
->step
= wide_int_to_tree (sizetype
, addr
->elts
[i
].coef
);
515 aff_combination_remove_elt (addr
, i
);
518 /* Adds ELT to PARTS. */
521 add_to_parts (struct mem_address
*parts
, tree elt
)
527 parts
->index
= fold_convert (sizetype
, elt
);
537 /* Add ELT to base. */
538 type
= TREE_TYPE (parts
->base
);
539 if (POINTER_TYPE_P (type
))
540 parts
->base
= fold_build_pointer_plus (parts
->base
, elt
);
542 parts
->base
= fold_build2 (PLUS_EXPR
, type
, parts
->base
, elt
);
545 /* Returns true if multiplying by RATIO is allowed in an address. Test the
546 validity for a memory reference accessing memory of mode MODE in address
550 multiplier_allowed_in_address_p (HOST_WIDE_INT ratio
, machine_mode mode
,
553 #define MAX_RATIO 128
554 unsigned int data_index
= (int) as
* MAX_MACHINE_MODE
+ (int) mode
;
555 static vec
<sbitmap
> valid_mult_list
;
558 if (data_index
>= valid_mult_list
.length ())
559 valid_mult_list
.safe_grow_cleared (data_index
+ 1);
561 valid_mult
= valid_mult_list
[data_index
];
564 machine_mode address_mode
= targetm
.addr_space
.address_mode (as
);
565 rtx reg1
= gen_raw_REG (address_mode
, LAST_VIRTUAL_REGISTER
+ 1);
566 rtx reg2
= gen_raw_REG (address_mode
, LAST_VIRTUAL_REGISTER
+ 2);
570 valid_mult
= sbitmap_alloc (2 * MAX_RATIO
+ 1);
571 bitmap_clear (valid_mult
);
572 scaled
= gen_rtx_fmt_ee (MULT
, address_mode
, reg1
, NULL_RTX
);
573 addr
= gen_rtx_fmt_ee (PLUS
, address_mode
, scaled
, reg2
);
574 for (i
= -MAX_RATIO
; i
<= MAX_RATIO
; i
++)
576 XEXP (scaled
, 1) = gen_int_mode (i
, address_mode
);
577 if (memory_address_addr_space_p (mode
, addr
, as
)
578 || memory_address_addr_space_p (mode
, scaled
, as
))
579 bitmap_set_bit (valid_mult
, i
+ MAX_RATIO
);
582 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
584 fprintf (dump_file
, " allowed multipliers:");
585 for (i
= -MAX_RATIO
; i
<= MAX_RATIO
; i
++)
586 if (bitmap_bit_p (valid_mult
, i
+ MAX_RATIO
))
587 fprintf (dump_file
, " %d", (int) i
);
588 fprintf (dump_file
, "\n");
589 fprintf (dump_file
, "\n");
592 valid_mult_list
[data_index
] = valid_mult
;
595 if (ratio
> MAX_RATIO
|| ratio
< -MAX_RATIO
)
598 return bitmap_bit_p (valid_mult
, ratio
+ MAX_RATIO
);
601 /* Finds the most expensive multiplication in ADDR that can be
602 expressed in an addressing mode and move the corresponding
603 element(s) to PARTS. */
606 most_expensive_mult_to_index (tree type
, struct mem_address
*parts
,
607 aff_tree
*addr
, bool speed
)
609 addr_space_t as
= TYPE_ADDR_SPACE (type
);
610 machine_mode address_mode
= targetm
.addr_space
.address_mode (as
);
612 unsigned best_mult_cost
= 0, acost
;
613 tree mult_elt
= NULL_TREE
, elt
;
615 enum tree_code op_code
;
617 offset_int best_mult
= 0;
618 for (i
= 0; i
< addr
->n
; i
++)
620 if (!wi::fits_shwi_p (addr
->elts
[i
].coef
))
623 coef
= addr
->elts
[i
].coef
.to_shwi ();
625 || !multiplier_allowed_in_address_p (coef
, TYPE_MODE (type
), as
))
628 acost
= mult_by_coeff_cost (coef
, address_mode
, speed
);
630 if (acost
> best_mult_cost
)
632 best_mult_cost
= acost
;
633 best_mult
= offset_int::from (addr
->elts
[i
].coef
, SIGNED
);
640 /* Collect elements multiplied by best_mult. */
641 for (i
= j
= 0; i
< addr
->n
; i
++)
643 offset_int amult
= offset_int::from (addr
->elts
[i
].coef
, SIGNED
);
644 offset_int amult_neg
= -wi::sext (amult
, TYPE_PRECISION (addr
->type
));
646 if (amult
== best_mult
)
648 else if (amult_neg
== best_mult
)
649 op_code
= MINUS_EXPR
;
652 addr
->elts
[j
] = addr
->elts
[i
];
657 elt
= fold_convert (sizetype
, addr
->elts
[i
].val
);
659 mult_elt
= fold_build2 (op_code
, sizetype
, mult_elt
, elt
);
660 else if (op_code
== PLUS_EXPR
)
663 mult_elt
= fold_build1 (NEGATE_EXPR
, sizetype
, elt
);
667 parts
->index
= mult_elt
;
668 parts
->step
= wide_int_to_tree (sizetype
, best_mult
);
671 /* Splits address ADDR for a memory access of type TYPE into PARTS.
672 If BASE_HINT is non-NULL, it specifies an SSA name to be used
673 preferentially as base of the reference, and IV_CAND is the selected
674 iv candidate used in ADDR. Store true to VAR_IN_BASE if variant
675 part of address is split to PARTS.base.
677 TODO -- be more clever about the distribution of the elements of ADDR
678 to PARTS. Some architectures do not support anything but single
679 register in address, possibly with a small integer offset; while
680 create_mem_ref will simplify the address to an acceptable shape
681 later, it would be more efficient to know that asking for complicated
682 addressing modes is useless. */
685 addr_to_parts (tree type
, aff_tree
*addr
, tree iv_cand
, tree base_hint
,
686 struct mem_address
*parts
, bool *var_in_base
, bool speed
)
691 parts
->symbol
= NULL_TREE
;
692 parts
->base
= NULL_TREE
;
693 parts
->index
= NULL_TREE
;
694 parts
->step
= NULL_TREE
;
696 if (maybe_ne (addr
->offset
, 0))
697 parts
->offset
= wide_int_to_tree (sizetype
, addr
->offset
);
699 parts
->offset
= NULL_TREE
;
701 /* Try to find a symbol. */
702 move_fixed_address_to_symbol (parts
, addr
);
704 /* Since at the moment there is no reliable way to know how to
705 distinguish between pointer and its offset, we decide if var
706 part is the pointer based on guess. */
707 *var_in_base
= (base_hint
!= NULL
&& parts
->symbol
== NULL
);
709 *var_in_base
= move_hint_to_base (type
, parts
, base_hint
, addr
);
711 move_variant_to_index (parts
, addr
, iv_cand
);
713 /* First move the most expensive feasible multiplication to index. */
715 most_expensive_mult_to_index (type
, parts
, addr
, speed
);
717 /* Move pointer into base. */
718 if (!parts
->symbol
&& !parts
->base
)
719 move_pointer_to_base (parts
, addr
);
721 /* Then try to process the remaining elements. */
722 for (i
= 0; i
< addr
->n
; i
++)
724 part
= fold_convert (sizetype
, addr
->elts
[i
].val
);
725 if (addr
->elts
[i
].coef
!= 1)
726 part
= fold_build2 (MULT_EXPR
, sizetype
, part
,
727 wide_int_to_tree (sizetype
, addr
->elts
[i
].coef
));
728 add_to_parts (parts
, part
);
731 add_to_parts (parts
, fold_convert (sizetype
, addr
->rest
));
734 /* Force the PARTS to register. */
737 gimplify_mem_ref_parts (gimple_stmt_iterator
*gsi
, struct mem_address
*parts
)
740 parts
->base
= force_gimple_operand_gsi_1 (gsi
, parts
->base
,
741 is_gimple_mem_ref_addr
, NULL_TREE
,
742 true, GSI_SAME_STMT
);
744 parts
->index
= force_gimple_operand_gsi (gsi
, parts
->index
,
746 true, GSI_SAME_STMT
);
749 /* Return true if the OFFSET in PARTS is the only thing that is making
750 it an invalid address for type TYPE. */
753 mem_ref_valid_without_offset_p (tree type
, mem_address parts
)
756 parts
.base
= parts
.offset
;
757 parts
.offset
= NULL_TREE
;
758 return valid_mem_ref_p (TYPE_MODE (type
), TYPE_ADDR_SPACE (type
), &parts
);
761 /* Fold PARTS->offset into PARTS->base, so that there is no longer
762 a separate offset. Emit any new instructions before GSI. */
765 add_offset_to_base (gimple_stmt_iterator
*gsi
, mem_address
*parts
)
767 tree tmp
= parts
->offset
;
770 tmp
= fold_build_pointer_plus (parts
->base
, tmp
);
771 tmp
= force_gimple_operand_gsi_1 (gsi
, tmp
, is_gimple_mem_ref_addr
,
772 NULL_TREE
, true, GSI_SAME_STMT
);
775 parts
->offset
= NULL_TREE
;
778 /* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
779 computations are emitted in front of GSI. TYPE is the mode
780 of created memory reference. IV_CAND is the selected iv candidate in ADDR,
781 and BASE_HINT is non NULL if IV_CAND comes from a base address
785 create_mem_ref (gimple_stmt_iterator
*gsi
, tree type
, aff_tree
*addr
,
786 tree alias_ptr_type
, tree iv_cand
, tree base_hint
, bool speed
)
790 struct mem_address parts
;
792 addr_to_parts (type
, addr
, iv_cand
, base_hint
, &parts
, &var_in_base
, speed
);
793 gimplify_mem_ref_parts (gsi
, &parts
);
794 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
798 /* The expression is too complicated. Try making it simpler. */
800 /* Merge symbol into other parts. */
804 parts
.symbol
= NULL_TREE
;
805 gcc_assert (is_gimple_val (tmp
));
809 gcc_assert (useless_type_conversion_p (sizetype
,
810 TREE_TYPE (parts
.base
)));
814 /* Add the symbol to base, eventually forcing it to register. */
815 tmp
= fold_build_pointer_plus (tmp
, parts
.base
);
816 tmp
= force_gimple_operand_gsi_1 (gsi
, tmp
,
817 is_gimple_mem_ref_addr
,
823 /* Move base to index, then move the symbol to base. */
824 parts
.index
= parts
.base
;
831 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
836 /* Move multiplication to index by transforming address expression:
837 [... + index << step + ...]
839 index' = index << step;
840 [... + index' + ,,,]. */
841 if (parts
.step
&& !integer_onep (parts
.step
))
843 gcc_assert (parts
.index
);
844 if (parts
.offset
&& mem_ref_valid_without_offset_p (type
, parts
))
846 add_offset_to_base (gsi
, &parts
);
847 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
848 gcc_assert (mem_ref
);
852 parts
.index
= force_gimple_operand_gsi (gsi
,
853 fold_build2 (MULT_EXPR
, sizetype
,
854 parts
.index
, parts
.step
),
855 true, NULL_TREE
, true, GSI_SAME_STMT
);
856 parts
.step
= NULL_TREE
;
858 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
863 /* Add offset to invariant part by transforming address expression:
864 [base + index + offset]
866 base' = base + offset;
869 index' = index + offset;
871 depending on which one is invariant. */
872 if (parts
.offset
&& !integer_zerop (parts
.offset
))
874 tree old_base
= unshare_expr (parts
.base
);
875 tree old_index
= unshare_expr (parts
.index
);
876 tree old_offset
= unshare_expr (parts
.offset
);
879 parts
.offset
= NULL_TREE
;
880 /* Add offset to invariant part. */
885 tmp
= fold_build_pointer_plus (parts
.base
, tmp
);
886 tmp
= force_gimple_operand_gsi_1 (gsi
, tmp
,
887 is_gimple_mem_ref_addr
,
897 tmp
= fold_build_pointer_plus (parts
.index
, tmp
);
898 tmp
= force_gimple_operand_gsi_1 (gsi
, tmp
,
899 is_gimple_mem_ref_addr
,
906 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
910 /* Restore parts.base, index and offset so that we can check if
911 [base + offset] addressing mode is supported in next step.
912 This is necessary for targets only support [base + offset],
913 but not [base + index] addressing mode. */
914 parts
.base
= old_base
;
915 parts
.index
= old_index
;
916 parts
.offset
= old_offset
;
919 /* Transform [base + index + ...] into:
920 base' = base + index;
925 parts
.index
= NULL_TREE
;
926 /* Add index to base. */
929 tmp
= fold_build_pointer_plus (parts
.base
, tmp
);
930 tmp
= force_gimple_operand_gsi_1 (gsi
, tmp
,
931 is_gimple_mem_ref_addr
,
932 NULL_TREE
, true, GSI_SAME_STMT
);
936 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
941 /* Transform [base + offset] into:
942 base' = base + offset;
944 if (parts
.offset
&& !integer_zerop (parts
.offset
))
946 add_offset_to_base (gsi
, &parts
);
947 mem_ref
= create_mem_ref_raw (type
, alias_ptr_type
, &parts
, true);
952 /* Verify that the address is in the simplest possible shape
953 (only a register). If we cannot create such a memory reference,
954 something is really wrong. */
955 gcc_assert (parts
.symbol
== NULL_TREE
);
956 gcc_assert (parts
.index
== NULL_TREE
);
957 gcc_assert (!parts
.step
|| integer_onep (parts
.step
));
958 gcc_assert (!parts
.offset
|| integer_zerop (parts
.offset
));
962 /* Copies components of the address from OP to ADDR. */
965 get_address_description (tree op
, struct mem_address
*addr
)
967 if (TREE_CODE (TMR_BASE (op
)) == ADDR_EXPR
)
969 addr
->symbol
= TMR_BASE (op
);
970 addr
->base
= TMR_INDEX2 (op
);
974 addr
->symbol
= NULL_TREE
;
977 gcc_assert (integer_zerop (TMR_BASE (op
)));
978 addr
->base
= TMR_INDEX2 (op
);
981 addr
->base
= TMR_BASE (op
);
983 addr
->index
= TMR_INDEX (op
);
984 addr
->step
= TMR_STEP (op
);
985 addr
->offset
= TMR_OFFSET (op
);
988 /* Copies the reference information from OLD_REF to NEW_REF, where
989 NEW_REF should be either a MEM_REF or a TARGET_MEM_REF. */
992 copy_ref_info (tree new_ref
, tree old_ref
)
994 tree new_ptr_base
= NULL_TREE
;
996 gcc_assert (TREE_CODE (new_ref
) == MEM_REF
997 || TREE_CODE (new_ref
) == TARGET_MEM_REF
);
999 TREE_SIDE_EFFECTS (new_ref
) = TREE_SIDE_EFFECTS (old_ref
);
1000 TREE_THIS_VOLATILE (new_ref
) = TREE_THIS_VOLATILE (old_ref
);
1002 new_ptr_base
= TREE_OPERAND (new_ref
, 0);
1004 /* We can transfer points-to information from an old pointer
1005 or decl base to the new one. */
1007 && TREE_CODE (new_ptr_base
) == SSA_NAME
1008 && !SSA_NAME_PTR_INFO (new_ptr_base
))
1010 tree base
= get_base_address (old_ref
);
1013 else if ((TREE_CODE (base
) == MEM_REF
1014 || TREE_CODE (base
) == TARGET_MEM_REF
)
1015 && TREE_CODE (TREE_OPERAND (base
, 0)) == SSA_NAME
1016 && SSA_NAME_PTR_INFO (TREE_OPERAND (base
, 0)))
1018 struct ptr_info_def
*new_pi
;
1019 unsigned int align
, misalign
;
1021 duplicate_ssa_name_ptr_info
1022 (new_ptr_base
, SSA_NAME_PTR_INFO (TREE_OPERAND (base
, 0)));
1023 new_pi
= SSA_NAME_PTR_INFO (new_ptr_base
);
1024 /* We have to be careful about transferring alignment information. */
1025 if (get_ptr_info_alignment (new_pi
, &align
, &misalign
)
1026 && TREE_CODE (old_ref
) == MEM_REF
1027 && !(TREE_CODE (new_ref
) == TARGET_MEM_REF
1028 && (TMR_INDEX2 (new_ref
)
1029 /* TODO: Below conditions can be relaxed if TMR_INDEX
1030 is an indcution variable and its initial value and
1031 step are aligned. */
1032 || (TMR_INDEX (new_ref
) && !TMR_STEP (new_ref
))
1033 || (TMR_STEP (new_ref
)
1034 && (TREE_INT_CST_LOW (TMR_STEP (new_ref
))
1037 poly_uint64 inc
= (mem_ref_offset (old_ref
)
1038 - mem_ref_offset (new_ref
)).force_uhwi ();
1039 adjust_ptr_info_misalignment (new_pi
, inc
);
1042 mark_ptr_info_alignment_unknown (new_pi
);
1044 else if (VAR_P (base
)
1045 || TREE_CODE (base
) == PARM_DECL
1046 || TREE_CODE (base
) == RESULT_DECL
)
1048 struct ptr_info_def
*pi
= get_ptr_info (new_ptr_base
);
1049 pt_solution_set_var (&pi
->pt
, base
);
1054 /* Move constants in target_mem_ref REF to offset. Returns the new target
1055 mem ref if anything changes, NULL_TREE otherwise. */
1058 maybe_fold_tmr (tree ref
)
1060 struct mem_address addr
;
1061 bool changed
= false;
1064 get_address_description (ref
, &addr
);
1067 && TREE_CODE (addr
.base
) == INTEGER_CST
1068 && !integer_zerop (addr
.base
))
1070 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
,
1071 TREE_TYPE (addr
.offset
),
1072 addr
.offset
, addr
.base
);
1073 addr
.base
= NULL_TREE
;
1078 && TREE_CODE (TREE_OPERAND (addr
.symbol
, 0)) == MEM_REF
)
1080 addr
.offset
= fold_binary_to_constant
1081 (PLUS_EXPR
, TREE_TYPE (addr
.offset
),
1083 TREE_OPERAND (TREE_OPERAND (addr
.symbol
, 0), 1));
1084 addr
.symbol
= TREE_OPERAND (TREE_OPERAND (addr
.symbol
, 0), 0);
1087 else if (addr
.symbol
1088 && handled_component_p (TREE_OPERAND (addr
.symbol
, 0)))
1091 addr
.symbol
= build_fold_addr_expr
1092 (get_addr_base_and_unit_offset
1093 (TREE_OPERAND (addr
.symbol
, 0), &offset
));
1094 addr
.offset
= int_const_binop (PLUS_EXPR
,
1095 addr
.offset
, size_int (offset
));
1099 if (addr
.index
&& TREE_CODE (addr
.index
) == INTEGER_CST
)
1104 off
= fold_binary_to_constant (MULT_EXPR
, sizetype
,
1106 addr
.step
= NULL_TREE
;
1109 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
,
1110 TREE_TYPE (addr
.offset
),
1112 addr
.index
= NULL_TREE
;
1119 /* If we have propagated something into this TARGET_MEM_REF and thus
1120 ended up folding it, always create a new TARGET_MEM_REF regardless
1121 if it is valid in this for on the target - the propagation result
1122 wouldn't be anyway. */
1123 new_ref
= create_mem_ref_raw (TREE_TYPE (ref
),
1124 TREE_TYPE (addr
.offset
), &addr
, false);
1125 TREE_SIDE_EFFECTS (new_ref
) = TREE_SIDE_EFFECTS (ref
);
1126 TREE_THIS_VOLATILE (new_ref
) = TREE_THIS_VOLATILE (ref
);
1130 /* Dump PARTS to FILE. */
1132 extern void dump_mem_address (FILE *, struct mem_address
*);
1134 dump_mem_address (FILE *file
, struct mem_address
*parts
)
1138 fprintf (file
, "symbol: ");
1139 print_generic_expr (file
, TREE_OPERAND (parts
->symbol
, 0), TDF_SLIM
);
1140 fprintf (file
, "\n");
1144 fprintf (file
, "base: ");
1145 print_generic_expr (file
, parts
->base
, TDF_SLIM
);
1146 fprintf (file
, "\n");
1150 fprintf (file
, "index: ");
1151 print_generic_expr (file
, parts
->index
, TDF_SLIM
);
1152 fprintf (file
, "\n");
1156 fprintf (file
, "step: ");
1157 print_generic_expr (file
, parts
->step
, TDF_SLIM
);
1158 fprintf (file
, "\n");
1162 fprintf (file
, "offset: ");
1163 print_generic_expr (file
, parts
->offset
, TDF_SLIM
);
1164 fprintf (file
, "\n");
1168 #include "gt-tree-ssa-address.h"