1 /* Memory address lowering and addressing mode selection.
2 Copyright (C) 2004 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 2, 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 COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 /* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
22 that directly map to addressing modes of the target. */
26 #include "coretypes.h"
31 #include "hard-reg-set.h"
32 #include "basic-block.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
36 #include "tree-dump.h"
37 #include "tree-pass.h"
40 #include "tree-inline.h"
41 #include "insn-config.h"
45 #include "tree-affine.h"
47 /* TODO -- handling of symbols (according to Richard Hendersons
48 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
50 There are at least 5 different kinds of symbols that we can run up against:
52 (1) binds_local_p, small data area.
53 (2) binds_local_p, eg local statics
54 (3) !binds_local_p, eg global variables
55 (4) thread local, local_exec
56 (5) thread local, !local_exec
58 Now, (1) won't appear often in an array context, but it certainly can.
59 All you have to do is set -GN high enough, or explicitly mark any
60 random object __attribute__((section (".sdata"))).
62 All of these affect whether or not a symbol is in fact a valid address.
63 The only one tested here is (3). And that result may very well
64 be incorrect for (4) or (5).
66 An incorrect result here does not cause incorrect results out the
67 back end, because the expander in expr.c validizes the address. However
68 it would be nice to improve the handling here in order to produce more
71 /* A "template" for memory address, used to determine whether the address is
74 struct mem_addr_template
GTY (())
76 rtx ref
; /* The template. */
77 rtx
* GTY ((skip
)) step_p
; /* The point in template where the step should be
79 rtx
* GTY ((skip
)) off_p
; /* The point in template where the offset should
83 /* The templates. Each of the five bits of the index corresponds to one
84 component of TARGET_MEM_REF being present, see TEMPL_IDX. */
86 static GTY (()) struct mem_addr_template templates
[32];
88 #define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
89 (((SYMBOL != 0) << 4) \
90 | ((BASE != 0) << 3) \
91 | ((INDEX != 0) << 2) \
92 | ((STEP != 0) << 1) \
95 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
96 STEP and OFFSET to *ADDR. Stores pointers to where step is placed to
97 *STEP_P and offset to *OFFSET_P. */
100 gen_addr_rtx (rtx symbol
, rtx base
, rtx index
, rtx step
, rtx offset
,
101 rtx
*addr
, rtx
**step_p
, rtx
**offset_p
)
116 act_elem
= gen_rtx_MULT (Pmode
, act_elem
, step
);
119 *step_p
= &XEXP (act_elem
, 1);
128 *addr
= gen_rtx_PLUS (Pmode
, *addr
, base
);
138 act_elem
= gen_rtx_CONST (Pmode
,
139 gen_rtx_PLUS (Pmode
, act_elem
, offset
));
141 *offset_p
= &XEXP (XEXP (act_elem
, 0), 1);
145 *addr
= gen_rtx_PLUS (Pmode
, *addr
, act_elem
);
153 *addr
= gen_rtx_PLUS (Pmode
, *addr
, offset
);
155 *offset_p
= &XEXP (*addr
, 1);
169 /* Returns address for TARGET_MEM_REF with parameters given by ADDR.
170 If REALLY_EXPAND is false, just make fake registers instead
171 of really expanding the operands, and perform the expansion in-place
172 by using one of the "templates". */
175 addr_for_mem_ref (struct mem_address
*addr
, bool really_expand
)
177 rtx address
, sym
, bse
, idx
, st
, off
;
178 static bool templates_initialized
= false;
179 struct mem_addr_template
*templ
;
181 if (addr
->step
&& !integer_onep (addr
->step
))
182 st
= immed_double_const (TREE_INT_CST_LOW (addr
->step
),
183 TREE_INT_CST_HIGH (addr
->step
), Pmode
);
187 if (addr
->offset
&& !integer_zerop (addr
->offset
))
188 off
= immed_double_const (TREE_INT_CST_LOW (addr
->offset
),
189 TREE_INT_CST_HIGH (addr
->offset
), Pmode
);
195 /* Reuse the templates for addresses, so that we do not waste memory. */
196 if (!templates_initialized
)
200 templates_initialized
= true;
201 sym
= gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup ("test_symbol"));
202 bse
= gen_raw_REG (Pmode
, LAST_VIRTUAL_REGISTER
+ 1);
203 idx
= gen_raw_REG (Pmode
, LAST_VIRTUAL_REGISTER
+ 2);
205 for (i
= 0; i
< 32; i
++)
206 gen_addr_rtx ((i
& 16 ? sym
: NULL_RTX
),
207 (i
& 8 ? bse
: NULL_RTX
),
208 (i
& 4 ? idx
: NULL_RTX
),
209 (i
& 2 ? const0_rtx
: NULL_RTX
),
210 (i
& 1 ? const0_rtx
: NULL_RTX
),
212 &templates
[i
].step_p
,
213 &templates
[i
].off_p
);
216 templ
= templates
+ TEMPL_IDX (addr
->symbol
, addr
->base
, addr
->index
,
226 /* Otherwise really expand the expressions. */
228 ? expand_expr (build_addr (addr
->symbol
, current_function_decl
),
229 NULL_RTX
, Pmode
, EXPAND_NORMAL
)
232 ? expand_expr (addr
->base
, NULL_RTX
, Pmode
, EXPAND_NORMAL
)
235 ? expand_expr (addr
->index
, NULL_RTX
, Pmode
, EXPAND_NORMAL
)
238 gen_addr_rtx (sym
, bse
, idx
, st
, off
, &address
, NULL
, NULL
);
242 /* Returns address of MEM_REF in TYPE. */
245 tree_mem_ref_addr (tree type
, tree mem_ref
)
249 tree step
= TMR_STEP (mem_ref
), offset
= TMR_OFFSET (mem_ref
);
250 tree sym
= TMR_SYMBOL (mem_ref
), base
= TMR_BASE (mem_ref
);
251 tree addr_base
= NULL_TREE
, addr_off
= NULL_TREE
;
254 addr_base
= fold_convert (type
, build_addr (sym
, current_function_decl
));
255 else if (base
&& POINTER_TYPE_P (TREE_TYPE (base
)))
257 addr_base
= fold_convert (type
, base
);
261 act_elem
= TMR_INDEX (mem_ref
);
265 act_elem
= fold_build2 (MULT_EXPR
, sizetype
, act_elem
, step
);
273 addr_off
= fold_build2 (PLUS_EXPR
, sizetype
, addr_off
, act_elem
);
278 if (offset
&& !integer_zerop (offset
))
281 addr_off
= fold_build2 (PLUS_EXPR
, sizetype
, addr_off
, offset
);
288 addr
= fold_convert (type
, addr_off
);
290 addr
= fold_build2 (PLUS_EXPR
, type
, addr_base
, addr
);
295 addr
= build_int_cst (type
, 0);
300 /* Returns true if a memory reference in MODE and with parameters given by
301 ADDR is valid on the current target. */
304 valid_mem_ref_p (enum machine_mode mode
, struct mem_address
*addr
)
308 address
= addr_for_mem_ref (addr
, false);
312 return memory_address_p (mode
, address
);
315 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
316 is valid on the current target and if so, creates and returns the
320 create_mem_ref_raw (tree type
, struct mem_address
*addr
)
322 if (!valid_mem_ref_p (TYPE_MODE (type
), addr
))
325 if (addr
->step
&& integer_onep (addr
->step
))
326 addr
->step
= NULL_TREE
;
328 if (addr
->offset
&& integer_zerop (addr
->offset
))
329 addr
->offset
= NULL_TREE
;
331 return build7 (TARGET_MEM_REF
, type
,
332 addr
->symbol
, addr
->base
, addr
->index
,
333 addr
->step
, addr
->offset
, NULL
, NULL
);
336 /* Returns true if OBJ is an object whose address is a link time constant. */
339 fixed_address_object_p (tree obj
)
341 return (TREE_CODE (obj
) == VAR_DECL
342 && (TREE_STATIC (obj
)
343 || DECL_EXTERNAL (obj
)));
346 /* If ADDR contains an address of object that is a link time constant,
347 move it to PARTS->symbol. */
350 move_fixed_address_to_symbol (struct mem_address
*parts
, aff_tree
*addr
)
353 tree val
= NULL_TREE
;
355 for (i
= 0; i
< addr
->n
; i
++)
357 if (!double_int_one_p (addr
->elts
[i
].coef
))
360 val
= addr
->elts
[i
].val
;
361 if (TREE_CODE (val
) == ADDR_EXPR
362 && fixed_address_object_p (TREE_OPERAND (val
, 0)))
369 parts
->symbol
= TREE_OPERAND (val
, 0);
370 aff_combination_remove_elt (addr
, i
);
373 /* If ADDR contains an address of a dereferenced pointer, move it to
377 move_pointer_to_base (struct mem_address
*parts
, aff_tree
*addr
)
380 tree val
= NULL_TREE
;
382 for (i
= 0; i
< addr
->n
; i
++)
384 if (!double_int_one_p (addr
->elts
[i
].coef
))
387 val
= addr
->elts
[i
].val
;
388 if (POINTER_TYPE_P (TREE_TYPE (val
)))
396 aff_combination_remove_elt (addr
, i
);
399 /* Adds ELT to PARTS. */
402 add_to_parts (struct mem_address
*parts
, tree elt
)
418 /* Add ELT to base. */
419 type
= TREE_TYPE (parts
->base
);
420 parts
->base
= fold_build2 (PLUS_EXPR
, type
,
422 fold_convert (type
, elt
));
425 /* Finds the most expensive multiplication in ADDR that can be
426 expressed in an addressing mode and move the corresponding
427 element(s) to PARTS. */
430 most_expensive_mult_to_index (struct mem_address
*parts
, aff_tree
*addr
)
433 double_int best_mult
, amult
, amult_neg
;
434 unsigned best_mult_cost
= 0, acost
;
435 tree mult_elt
= NULL_TREE
, elt
;
437 enum tree_code op_code
;
439 best_mult
= double_int_zero
;
440 for (i
= 0; i
< addr
->n
; i
++)
442 if (!double_int_fits_in_shwi_p (addr
->elts
[i
].coef
))
445 /* FIXME: Should use the correct memory mode rather than Pmode. */
447 coef
= double_int_to_shwi (addr
->elts
[i
].coef
);
449 || !multiplier_allowed_in_address_p (coef
, Pmode
))
452 acost
= multiply_by_cost (coef
, Pmode
);
454 if (acost
> best_mult_cost
)
456 best_mult_cost
= acost
;
457 best_mult
= addr
->elts
[i
].coef
;
464 /* Collect elements multiplied by best_mult. */
465 for (i
= j
= 0; i
< addr
->n
; i
++)
467 amult
= addr
->elts
[i
].coef
;
468 amult_neg
= double_int_ext_for_comb (double_int_neg (amult
), addr
);
470 if (double_int_equal_p (amult
, best_mult
))
472 else if (double_int_equal_p (amult_neg
, best_mult
))
473 op_code
= MINUS_EXPR
;
476 addr
->elts
[j
] = addr
->elts
[i
];
481 elt
= fold_convert (sizetype
, addr
->elts
[i
].val
);
483 mult_elt
= fold_build2 (op_code
, sizetype
, mult_elt
, elt
);
484 else if (op_code
== PLUS_EXPR
)
487 mult_elt
= fold_build1 (NEGATE_EXPR
, sizetype
, elt
);
491 parts
->index
= mult_elt
;
492 parts
->step
= double_int_to_tree (sizetype
, best_mult
);
495 /* Splits address ADDR into PARTS.
497 TODO -- be more clever about the distribution of the elements of ADDR
498 to PARTS. Some architectures do not support anything but single
499 register in address, possibly with a small integer offset; while
500 create_mem_ref will simplify the address to an acceptable shape
501 later, it would be more efficient to know that asking for complicated
502 addressing modes is useless. */
505 addr_to_parts (aff_tree
*addr
, struct mem_address
*parts
)
510 parts
->symbol
= NULL_TREE
;
511 parts
->base
= NULL_TREE
;
512 parts
->index
= NULL_TREE
;
513 parts
->step
= NULL_TREE
;
515 if (!double_int_zero_p (addr
->offset
))
516 parts
->offset
= double_int_to_tree (sizetype
, addr
->offset
);
518 parts
->offset
= NULL_TREE
;
520 /* Try to find a symbol. */
521 move_fixed_address_to_symbol (parts
, addr
);
523 /* First move the most expensive feasible multiplication
525 most_expensive_mult_to_index (parts
, addr
);
527 /* Try to find a base of the reference. Since at the moment
528 there is no reliable way how to distinguish between pointer and its
529 offset, this is just a guess. */
531 move_pointer_to_base (parts
, addr
);
533 /* Then try to process the remaining elements. */
534 for (i
= 0; i
< addr
->n
; i
++)
536 part
= fold_convert (sizetype
, addr
->elts
[i
].val
);
537 if (!double_int_one_p (addr
->elts
[i
].coef
))
538 part
= fold_build2 (MULT_EXPR
, sizetype
, part
,
539 double_int_to_tree (sizetype
, addr
->elts
[i
].coef
));
540 add_to_parts (parts
, part
);
543 add_to_parts (parts
, fold_convert (sizetype
, addr
->rest
));
546 /* Force the PARTS to register. */
549 gimplify_mem_ref_parts (block_stmt_iterator
*bsi
, struct mem_address
*parts
)
552 parts
->base
= force_gimple_operand_bsi (bsi
, parts
->base
,
555 parts
->index
= force_gimple_operand_bsi (bsi
, parts
->index
,
559 /* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
560 computations are emitted in front of BSI. TYPE is the mode
561 of created memory reference. */
564 create_mem_ref (block_stmt_iterator
*bsi
, tree type
, aff_tree
*addr
)
567 tree addr_type
= build_pointer_type (type
), atype
;
568 struct mem_address parts
;
570 addr_to_parts (addr
, &parts
);
571 gimplify_mem_ref_parts (bsi
, &parts
);
572 mem_ref
= create_mem_ref_raw (type
, &parts
);
576 /* The expression is too complicated. Try making it simpler. */
578 if (parts
.step
&& !integer_onep (parts
.step
))
580 /* Move the multiplication to index. */
581 gcc_assert (parts
.index
);
582 parts
.index
= force_gimple_operand_bsi (bsi
,
583 fold_build2 (MULT_EXPR
, sizetype
,
584 parts
.index
, parts
.step
),
586 parts
.step
= NULL_TREE
;
588 mem_ref
= create_mem_ref_raw (type
, &parts
);
595 tmp
= fold_convert (addr_type
,
596 build_addr (parts
.symbol
, current_function_decl
));
598 /* Add the symbol to base, eventually forcing it to register. */
602 parts
.base
= force_gimple_operand_bsi (bsi
,
603 fold_build2 (PLUS_EXPR
, addr_type
,
604 fold_convert (addr_type
, parts
.base
),
609 parts
.index
= parts
.base
;
615 parts
.symbol
= NULL_TREE
;
617 mem_ref
= create_mem_ref_raw (type
, &parts
);
624 /* Add index to base. */
627 atype
= TREE_TYPE (parts
.base
);
628 parts
.base
= force_gimple_operand_bsi (bsi
,
629 fold_build2 (PLUS_EXPR
, atype
,
631 fold_convert (atype
, parts
.index
)),
635 parts
.base
= parts
.index
;
636 parts
.index
= NULL_TREE
;
638 mem_ref
= create_mem_ref_raw (type
, &parts
);
643 if (parts
.offset
&& !integer_zerop (parts
.offset
))
645 /* Try adding offset to base. */
648 atype
= TREE_TYPE (parts
.base
);
649 parts
.base
= force_gimple_operand_bsi (bsi
,
650 fold_build2 (PLUS_EXPR
, atype
,
652 fold_convert (atype
, parts
.offset
)),
656 parts
.base
= parts
.offset
;
658 parts
.offset
= NULL_TREE
;
660 mem_ref
= create_mem_ref_raw (type
, &parts
);
665 /* Verify that the address is in the simplest possible shape
666 (only a register). If we cannot create such a memory reference,
667 something is really wrong. */
668 gcc_assert (parts
.symbol
== NULL_TREE
);
669 gcc_assert (parts
.index
== NULL_TREE
);
670 gcc_assert (!parts
.step
|| integer_onep (parts
.step
));
671 gcc_assert (!parts
.offset
|| integer_zerop (parts
.offset
));
675 /* Copies components of the address from OP to ADDR. */
678 get_address_description (tree op
, struct mem_address
*addr
)
680 addr
->symbol
= TMR_SYMBOL (op
);
681 addr
->base
= TMR_BASE (op
);
682 addr
->index
= TMR_INDEX (op
);
683 addr
->step
= TMR_STEP (op
);
684 addr
->offset
= TMR_OFFSET (op
);
687 /* Copies the additional information attached to target_mem_ref FROM to TO. */
690 copy_mem_ref_info (tree to
, tree from
)
692 /* Copy the annotation, to preserve the aliasing information. */
693 TMR_TAG (to
) = TMR_TAG (from
);
695 /* And the info about the original reference. */
696 TMR_ORIGINAL (to
) = TMR_ORIGINAL (from
);
699 /* Move constants in target_mem_ref REF to offset. Returns the new target
700 mem ref if anything changes, NULL_TREE otherwise. */
703 maybe_fold_tmr (tree ref
)
705 struct mem_address addr
;
706 bool changed
= false;
709 get_address_description (ref
, &addr
);
711 if (addr
.base
&& TREE_CODE (addr
.base
) == INTEGER_CST
)
714 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
, sizetype
,
716 fold_convert (sizetype
, addr
.base
));
718 addr
.offset
= addr
.base
;
720 addr
.base
= NULL_TREE
;
724 if (addr
.index
&& TREE_CODE (addr
.index
) == INTEGER_CST
)
729 off
= fold_binary_to_constant (MULT_EXPR
, sizetype
,
731 addr
.step
= NULL_TREE
;
736 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
, sizetype
,
742 addr
.index
= NULL_TREE
;
749 ret
= create_mem_ref_raw (TREE_TYPE (ref
), &addr
);
753 copy_mem_ref_info (ret
, ref
);
757 /* Dump PARTS to FILE. */
759 extern void dump_mem_address (FILE *, struct mem_address
*);
761 dump_mem_address (FILE *file
, struct mem_address
*parts
)
765 fprintf (file
, "symbol: ");
766 print_generic_expr (file
, parts
->symbol
, TDF_SLIM
);
767 fprintf (file
, "\n");
771 fprintf (file
, "base: ");
772 print_generic_expr (file
, parts
->base
, TDF_SLIM
);
773 fprintf (file
, "\n");
777 fprintf (file
, "index: ");
778 print_generic_expr (file
, parts
->index
, TDF_SLIM
);
779 fprintf (file
, "\n");
783 fprintf (file
, "step: ");
784 print_generic_expr (file
, parts
->step
, TDF_SLIM
);
785 fprintf (file
, "\n");
789 fprintf (file
, "offset: ");
790 print_generic_expr (file
, parts
->offset
, TDF_SLIM
);
791 fprintf (file
, "\n");
795 #include "gt-tree-ssa-address.h"