1 /* Memory address lowering and addressing mode selection.
2 Copyright (C) 2004, 2007 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"
30 #include "hard-reg-set.h"
31 #include "basic-block.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
35 #include "tree-dump.h"
36 #include "tree-pass.h"
39 #include "tree-inline.h"
40 #include "insn-config.h"
45 /* TODO -- handling of symbols (according to Richard Hendersons
46 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
48 There are at least 5 different kinds of symbols that we can run up against:
50 (1) binds_local_p, small data area.
51 (2) binds_local_p, eg local statics
52 (3) !binds_local_p, eg global variables
53 (4) thread local, local_exec
54 (5) thread local, !local_exec
56 Now, (1) won't appear often in an array context, but it certainly can.
57 All you have to do is set -GN high enough, or explicitly mark any
58 random object __attribute__((section (".sdata"))).
60 All of these affect whether or not a symbol is in fact a valid address.
61 The only one tested here is (3). And that result may very well
62 be incorrect for (4) or (5).
64 An incorrect result here does not cause incorrect results out the
65 back end, because the expander in expr.c validizes the address. However
66 it would be nice to improve the handling here in order to produce more
69 /* A "template" for memory address, used to determine whether the address is
72 struct mem_addr_template
GTY (())
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
81 /* The templates. Each of the five bits of the index corresponds to one
82 component of TARGET_MEM_REF being present, see TEMPL_IDX. */
84 static GTY (()) struct mem_addr_template templates
[32];
86 #define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
87 (((SYMBOL != 0) << 4) \
88 | ((BASE != 0) << 3) \
89 | ((INDEX != 0) << 2) \
90 | ((STEP != 0) << 1) \
93 /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
94 STEP and OFFSET to *ADDR. Stores pointers to where step is placed to
95 *STEP_P and offset to *OFFSET_P. */
98 gen_addr_rtx (rtx symbol
, rtx base
, rtx index
, rtx step
, rtx offset
,
99 rtx
*addr
, rtx
**step_p
, rtx
**offset_p
)
114 act_elem
= gen_rtx_MULT (Pmode
, act_elem
, step
);
117 *step_p
= &XEXP (act_elem
, 1);
126 *addr
= gen_rtx_PLUS (Pmode
, *addr
, base
);
136 act_elem
= gen_rtx_CONST (Pmode
,
137 gen_rtx_PLUS (Pmode
, act_elem
, offset
));
139 *offset_p
= &XEXP (XEXP (act_elem
, 0), 1);
143 *addr
= gen_rtx_PLUS (Pmode
, *addr
, act_elem
);
151 *addr
= gen_rtx_PLUS (Pmode
, *addr
, offset
);
153 *offset_p
= &XEXP (*addr
, 1);
167 /* Returns address for TARGET_MEM_REF with parameters given by ADDR.
168 If REALLY_EXPAND is false, just make fake registers instead
169 of really expanding the operands, and perform the expansion in-place
170 by using one of the "templates". */
173 addr_for_mem_ref (struct mem_address
*addr
, bool really_expand
)
175 rtx address
, sym
, bse
, idx
, st
, off
;
176 static bool templates_initialized
= false;
177 struct mem_addr_template
*templ
;
179 if (addr
->step
&& !integer_onep (addr
->step
))
180 st
= immed_double_const (TREE_INT_CST_LOW (addr
->step
),
181 TREE_INT_CST_HIGH (addr
->step
), Pmode
);
185 if (addr
->offset
&& !integer_zerop (addr
->offset
))
186 off
= immed_double_const (TREE_INT_CST_LOW (addr
->offset
),
187 TREE_INT_CST_HIGH (addr
->offset
), Pmode
);
193 /* Reuse the templates for addresses, so that we do not waste memory. */
194 if (!templates_initialized
)
198 templates_initialized
= true;
199 sym
= gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup ("test_symbol"));
200 bse
= gen_raw_REG (Pmode
, LAST_VIRTUAL_REGISTER
+ 1);
201 idx
= gen_raw_REG (Pmode
, LAST_VIRTUAL_REGISTER
+ 2);
203 for (i
= 0; i
< 32; i
++)
204 gen_addr_rtx ((i
& 16 ? sym
: NULL_RTX
),
205 (i
& 8 ? bse
: NULL_RTX
),
206 (i
& 4 ? idx
: NULL_RTX
),
207 (i
& 2 ? const0_rtx
: NULL_RTX
),
208 (i
& 1 ? const0_rtx
: NULL_RTX
),
210 &templates
[i
].step_p
,
211 &templates
[i
].off_p
);
214 templ
= templates
+ TEMPL_IDX (addr
->symbol
, addr
->base
, addr
->index
,
224 /* Otherwise really expand the expressions. */
226 ? expand_expr (build_addr (addr
->symbol
, current_function_decl
),
227 NULL_RTX
, Pmode
, EXPAND_NORMAL
)
230 ? expand_expr (addr
->base
, NULL_RTX
, Pmode
, EXPAND_NORMAL
)
233 ? expand_expr (addr
->index
, NULL_RTX
, Pmode
, EXPAND_NORMAL
)
236 gen_addr_rtx (sym
, bse
, idx
, st
, off
, &address
, NULL
, NULL
);
240 /* Returns address of MEM_REF in TYPE. */
243 tree_mem_ref_addr (tree type
, tree mem_ref
)
247 tree step
= TMR_STEP (mem_ref
), offset
= TMR_OFFSET (mem_ref
);
248 tree sym
= TMR_SYMBOL (mem_ref
), base
= TMR_BASE (mem_ref
);
249 tree addr_base
= NULL_TREE
, addr_off
= NULL_TREE
;
252 addr_base
= fold_convert (type
, build_addr (sym
, current_function_decl
));
253 else if (base
&& POINTER_TYPE_P (TREE_TYPE (base
)))
255 addr_base
= fold_convert (type
, base
);
259 act_elem
= TMR_INDEX (mem_ref
);
263 act_elem
= fold_build2 (MULT_EXPR
, sizetype
, act_elem
, step
);
271 addr_off
= fold_build2 (PLUS_EXPR
, sizetype
, addr_off
, act_elem
);
276 if (!zero_p (offset
))
279 addr_off
= fold_build2 (PLUS_EXPR
, sizetype
, addr_off
, offset
);
286 addr
= fold_convert (type
, addr_off
);
288 addr
= fold_build2 (PLUS_EXPR
, type
, addr_base
, addr
);
293 addr
= build_int_cst (type
, 0);
298 /* Returns true if a memory reference in MODE and with parameters given by
299 ADDR is valid on the current target. */
302 valid_mem_ref_p (enum machine_mode mode
, struct mem_address
*addr
)
306 address
= addr_for_mem_ref (addr
, false);
310 return memory_address_p (mode
, address
);
313 /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
314 is valid on the current target and if so, creates and returns the
318 create_mem_ref_raw (tree type
, struct mem_address
*addr
)
320 if (!valid_mem_ref_p (TYPE_MODE (type
), addr
))
323 if (addr
->step
&& integer_onep (addr
->step
))
324 addr
->step
= NULL_TREE
;
326 if (addr
->offset
&& zero_p (addr
->offset
))
327 addr
->offset
= NULL_TREE
;
329 return build7 (TARGET_MEM_REF
, type
,
330 addr
->symbol
, addr
->base
, addr
->index
,
331 addr
->step
, addr
->offset
, NULL
, NULL
);
334 /* Returns true if OBJ is an object whose address is a link time constant. */
337 fixed_address_object_p (tree obj
)
339 return (TREE_CODE (obj
) == VAR_DECL
340 && (TREE_STATIC (obj
)
341 || DECL_EXTERNAL (obj
)));
344 /* Remove M-th element from COMB. */
347 aff_combination_remove_elt (struct affine_tree_combination
*comb
, unsigned m
)
352 comb
->coefs
[m
] = comb
->coefs
[comb
->n
];
353 comb
->elts
[m
] = comb
->elts
[comb
->n
];
357 comb
->coefs
[comb
->n
] = 1;
358 comb
->elts
[comb
->n
] = comb
->rest
;
359 comb
->rest
= NULL_TREE
;
364 /* If ADDR contains an address of object that is a link time constant,
365 move it to PARTS->symbol. */
368 move_fixed_address_to_symbol (struct mem_address
*parts
,
369 struct affine_tree_combination
*addr
)
372 tree val
= NULL_TREE
;
374 for (i
= 0; i
< addr
->n
; i
++)
376 if (addr
->coefs
[i
] != 1)
380 if (TREE_CODE (val
) == ADDR_EXPR
381 && fixed_address_object_p (TREE_OPERAND (val
, 0)))
388 parts
->symbol
= TREE_OPERAND (val
, 0);
389 aff_combination_remove_elt (addr
, i
);
392 /* If ADDR contains an address of a dereferenced pointer, move it to
396 move_pointer_to_base (struct mem_address
*parts
,
397 struct affine_tree_combination
*addr
)
400 tree val
= NULL_TREE
;
402 for (i
= 0; i
< addr
->n
; i
++)
404 if (addr
->coefs
[i
] != 1)
408 if (POINTER_TYPE_P (TREE_TYPE (val
)))
416 aff_combination_remove_elt (addr
, i
);
419 /* Adds ELT to PARTS. */
422 add_to_parts (struct mem_address
*parts
, tree elt
)
438 /* Add ELT to base. */
439 type
= TREE_TYPE (parts
->base
);
440 parts
->base
= fold_build2 (PLUS_EXPR
, type
,
442 fold_convert (type
, elt
));
445 /* Finds the most expensive multiplication in ADDR that can be
446 expressed in an addressing mode and move the corresponding
447 element(s) to PARTS. */
450 most_expensive_mult_to_index (struct mem_address
*parts
,
451 struct affine_tree_combination
*addr
)
453 unsigned HOST_WIDE_INT best_mult
= 0;
454 unsigned best_mult_cost
= 0, acost
;
455 tree mult_elt
= NULL_TREE
, elt
;
458 for (i
= 0; i
< addr
->n
; i
++)
460 if (addr
->coefs
[i
] == 1
461 || !multiplier_allowed_in_address_p (addr
->coefs
[i
]))
464 acost
= multiply_by_cost (addr
->coefs
[i
], Pmode
);
466 if (acost
> best_mult_cost
)
468 best_mult_cost
= acost
;
469 best_mult
= addr
->coefs
[i
];
476 for (i
= j
= 0; i
< addr
->n
; i
++)
478 if (addr
->coefs
[i
] != best_mult
)
480 addr
->coefs
[j
] = addr
->coefs
[i
];
481 addr
->elts
[j
] = addr
->elts
[i
];
486 elt
= fold_convert (sizetype
, addr
->elts
[i
]);
490 mult_elt
= fold_build2 (PLUS_EXPR
, sizetype
, mult_elt
, elt
);
494 parts
->index
= mult_elt
;
495 parts
->step
= build_int_cst_type (sizetype
, best_mult
);
498 /* Splits address ADDR into PARTS.
500 TODO -- be more clever about the distribution of the elements of ADDR
501 to PARTS. Some architectures do not support anything but single
502 register in address, possibly with a small integer offset; while
503 create_mem_ref will simplify the address to an acceptable shape
504 later, it would be a small bit more efficient to know that asking
505 for complicated addressing modes is useless. */
508 addr_to_parts (struct affine_tree_combination
*addr
, struct mem_address
*parts
)
513 parts
->symbol
= NULL_TREE
;
514 parts
->base
= NULL_TREE
;
515 parts
->index
= NULL_TREE
;
516 parts
->step
= NULL_TREE
;
519 parts
->offset
= build_int_cst_type (sizetype
, addr
->offset
);
521 parts
->offset
= NULL_TREE
;
523 /* Try to find a symbol. */
524 move_fixed_address_to_symbol (parts
, addr
);
526 /* First move the most expensive feasible multiplication
528 most_expensive_mult_to_index (parts
, addr
);
530 /* Try to find a base of the reference. Since at the moment
531 there is no reliable way how to distinguish between pointer and its
532 offset, this is just a guess. */
534 move_pointer_to_base (parts
, addr
);
536 /* Then try to process the remaining elements. */
537 for (i
= 0; i
< addr
->n
; i
++)
539 part
= fold_convert (sizetype
, addr
->elts
[i
]);
540 if (addr
->coefs
[i
] != 1)
541 part
= fold_build2 (MULT_EXPR
, sizetype
, part
,
542 build_int_cst_type (sizetype
, addr
->coefs
[i
]));
543 add_to_parts (parts
, part
);
546 add_to_parts (parts
, fold_convert (sizetype
, addr
->rest
));
549 /* Force the PARTS to register. */
552 gimplify_mem_ref_parts (block_stmt_iterator
*bsi
, struct mem_address
*parts
)
555 parts
->base
= force_gimple_operand_bsi (bsi
, parts
->base
,
558 parts
->index
= force_gimple_operand_bsi (bsi
, parts
->index
,
562 /* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
563 computations are emitted in front of BSI. TYPE is the mode
564 of created memory reference. */
567 create_mem_ref (block_stmt_iterator
*bsi
, tree type
,
568 struct affine_tree_combination
*addr
)
571 tree addr_type
= build_pointer_type (type
), atype
;
572 struct mem_address parts
;
574 addr_to_parts (addr
, &parts
);
575 gimplify_mem_ref_parts (bsi
, &parts
);
576 mem_ref
= create_mem_ref_raw (type
, &parts
);
580 /* The expression is too complicated. Try making it simpler. */
582 if (parts
.step
&& !integer_onep (parts
.step
))
584 /* Move the multiplication to index. */
585 gcc_assert (parts
.index
);
586 parts
.index
= force_gimple_operand_bsi (bsi
,
587 fold_build2 (MULT_EXPR
, sizetype
,
588 parts
.index
, parts
.step
),
590 parts
.step
= NULL_TREE
;
592 mem_ref
= create_mem_ref_raw (type
, &parts
);
599 tmp
= fold_convert (addr_type
,
600 build_addr (parts
.symbol
, current_function_decl
));
602 /* Add the symbol to base, eventually forcing it to register. */
606 parts
.base
= force_gimple_operand_bsi (bsi
,
607 fold_build2 (PLUS_EXPR
, addr_type
,
608 fold_convert (addr_type
, parts
.base
),
613 parts
.index
= parts
.base
;
619 parts
.symbol
= NULL_TREE
;
621 mem_ref
= create_mem_ref_raw (type
, &parts
);
628 /* Add index to base. */
631 atype
= TREE_TYPE (parts
.base
);
632 parts
.base
= force_gimple_operand_bsi (bsi
,
633 fold_build2 (PLUS_EXPR
, atype
,
635 fold_convert (atype
, parts
.index
)),
639 parts
.base
= parts
.index
;
640 parts
.index
= NULL_TREE
;
642 mem_ref
= create_mem_ref_raw (type
, &parts
);
647 if (parts
.offset
&& !integer_zerop (parts
.offset
))
649 /* Try adding offset to base. */
652 atype
= TREE_TYPE (parts
.base
);
653 parts
.base
= force_gimple_operand_bsi (bsi
,
654 fold_build2 (PLUS_EXPR
, atype
,
656 fold_convert (atype
, parts
.offset
)),
660 parts
.base
= parts
.offset
;
662 parts
.offset
= NULL_TREE
;
664 mem_ref
= create_mem_ref_raw (type
, &parts
);
669 /* Verify that the address is in the simplest possible shape
670 (only a register). If we cannot create such a memory reference,
671 something is really wrong. */
672 gcc_assert (parts
.symbol
== NULL_TREE
);
673 gcc_assert (parts
.index
== NULL_TREE
);
674 gcc_assert (!parts
.step
|| integer_onep (parts
.step
));
675 gcc_assert (!parts
.offset
|| integer_zerop (parts
.offset
));
679 /* Copies components of the address from OP to ADDR. */
682 get_address_description (tree op
, struct mem_address
*addr
)
684 addr
->symbol
= TMR_SYMBOL (op
);
685 addr
->base
= TMR_BASE (op
);
686 addr
->index
= TMR_INDEX (op
);
687 addr
->step
= TMR_STEP (op
);
688 addr
->offset
= TMR_OFFSET (op
);
691 /* Copies the additional information attached to target_mem_ref FROM to TO. */
694 copy_mem_ref_info (tree to
, tree from
)
696 /* Copy the annotation, to preserve the aliasing information. */
697 TMR_TAG (to
) = TMR_TAG (from
);
699 /* And the info about the original reference. */
700 TMR_ORIGINAL (to
) = TMR_ORIGINAL (from
);
703 /* Move constants in target_mem_ref REF to offset. Returns the new target
704 mem ref if anything changes, NULL_TREE otherwise. */
707 maybe_fold_tmr (tree ref
)
709 struct mem_address addr
;
710 bool changed
= false;
713 get_address_description (ref
, &addr
);
715 if (addr
.base
&& TREE_CODE (addr
.base
) == INTEGER_CST
)
718 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
, sizetype
,
720 fold_convert (sizetype
, addr
.base
));
722 addr
.offset
= addr
.base
;
724 addr
.base
= NULL_TREE
;
728 if (addr
.index
&& TREE_CODE (addr
.index
) == INTEGER_CST
)
733 off
= fold_binary_to_constant (MULT_EXPR
, sizetype
,
735 addr
.step
= NULL_TREE
;
740 addr
.offset
= fold_binary_to_constant (PLUS_EXPR
, sizetype
,
746 addr
.index
= NULL_TREE
;
753 ret
= create_mem_ref_raw (TREE_TYPE (ref
), &addr
);
757 copy_mem_ref_info (ret
, ref
);
761 /* Dump PARTS to FILE. */
763 extern void dump_mem_address (FILE *, struct mem_address
*);
765 dump_mem_address (FILE *file
, struct mem_address
*parts
)
769 fprintf (file
, "symbol: ");
770 print_generic_expr (file
, parts
->symbol
, TDF_SLIM
);
771 fprintf (file
, "\n");
775 fprintf (file
, "base: ");
776 print_generic_expr (file
, parts
->base
, TDF_SLIM
);
777 fprintf (file
, "\n");
781 fprintf (file
, "index: ");
782 print_generic_expr (file
, parts
->index
, TDF_SLIM
);
783 fprintf (file
, "\n");
787 fprintf (file
, "step: ");
788 print_generic_expr (file
, parts
->step
, TDF_SLIM
);
789 fprintf (file
, "\n");
793 fprintf (file
, "offset: ");
794 print_generic_expr (file
, parts
->offset
, TDF_SLIM
);
795 fprintf (file
, "\n");
799 #include "gt-tree-ssa-address.h"