Mark as release
[official-gcc.git] / gcc / tree-ssa-address.c
blob1d851f29accd63dc6308b3e373b289a4f555bfb3
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
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 "rtl.h"
29 #include "tm_p.h"
30 #include "hard-reg-set.h"
31 #include "basic-block.h"
32 #include "output.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
35 #include "tree-dump.h"
36 #include "tree-pass.h"
37 #include "timevar.h"
38 #include "flags.h"
39 #include "tree-inline.h"
40 #include "insn-config.h"
41 #include "recog.h"
42 #include "expr.h"
43 #include "ggc.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
67 precise results. */
69 /* A "template" for memory address, used to determine whether the address is
70 valid for mode. */
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
76 filled in. */
77 rtx * GTY ((skip)) off_p; /* The point in template where the offset should
78 be filled in. */
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) \
91 | (OFFSET != 0))
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. */
97 static void
98 gen_addr_rtx (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
99 rtx *addr, rtx **step_p, rtx **offset_p)
101 rtx act_elem;
103 *addr = NULL_RTX;
104 if (step_p)
105 *step_p = NULL;
106 if (offset_p)
107 *offset_p = NULL;
109 if (index)
111 act_elem = index;
112 if (step)
114 act_elem = gen_rtx_MULT (Pmode, act_elem, step);
116 if (step_p)
117 *step_p = &XEXP (act_elem, 1);
120 *addr = act_elem;
123 if (base)
125 if (*addr)
126 *addr = gen_rtx_PLUS (Pmode, *addr, base);
127 else
128 *addr = base;
131 if (symbol)
133 act_elem = symbol;
134 if (offset)
136 act_elem = gen_rtx_CONST (Pmode,
137 gen_rtx_PLUS (Pmode, act_elem, offset));
138 if (offset_p)
139 *offset_p = &XEXP (XEXP (act_elem, 0), 1);
142 if (*addr)
143 *addr = gen_rtx_PLUS (Pmode, *addr, act_elem);
144 else
145 *addr = act_elem;
147 else if (offset)
149 if (*addr)
151 *addr = gen_rtx_PLUS (Pmode, *addr, offset);
152 if (offset_p)
153 *offset_p = &XEXP (*addr, 1);
155 else
157 *addr = offset;
158 if (offset_p)
159 *offset_p = addr;
163 if (!*addr)
164 *addr = const0_rtx;
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);
182 else
183 st = NULL_RTX;
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);
188 else
189 off = NULL_RTX;
191 if (!really_expand)
193 /* Reuse the templates for addresses, so that we do not waste memory. */
194 if (!templates_initialized)
196 unsigned i;
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),
209 &templates[i].ref,
210 &templates[i].step_p,
211 &templates[i].off_p);
214 templ = templates + TEMPL_IDX (addr->symbol, addr->base, addr->index,
215 st, off);
216 if (st)
217 *templ->step_p = st;
218 if (off)
219 *templ->off_p = off;
221 return templ->ref;
224 /* Otherwise really expand the expressions. */
225 sym = (addr->symbol
226 ? expand_expr (build_addr (addr->symbol, current_function_decl),
227 NULL_RTX, Pmode, EXPAND_NORMAL)
228 : NULL_RTX);
229 bse = (addr->base
230 ? expand_expr (addr->base, NULL_RTX, Pmode, EXPAND_NORMAL)
231 : NULL_RTX);
232 idx = (addr->index
233 ? expand_expr (addr->index, NULL_RTX, Pmode, EXPAND_NORMAL)
234 : NULL_RTX);
236 gen_addr_rtx (sym, bse, idx, st, off, &address, NULL, NULL);
237 return address;
240 /* Returns address of MEM_REF in TYPE. */
242 tree
243 tree_mem_ref_addr (tree type, tree mem_ref)
245 tree addr;
246 tree act_elem;
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;
251 if (sym)
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);
256 base = NULL_TREE;
259 act_elem = TMR_INDEX (mem_ref);
260 if (act_elem)
262 if (step)
263 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
264 addr_off = act_elem;
267 act_elem = base;
268 if (act_elem)
270 if (addr_off)
271 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
272 else
273 addr_off = act_elem;
276 if (!zero_p (offset))
278 if (addr_off)
279 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
280 else
281 addr_off = offset;
284 if (addr_off)
286 addr = fold_convert (type, addr_off);
287 if (addr_base)
288 addr = fold_build2 (PLUS_EXPR, type, addr_base, addr);
290 else if (addr_base)
291 addr = addr_base;
292 else
293 addr = build_int_cst (type, 0);
295 return addr;
298 /* Returns true if a memory reference in MODE and with parameters given by
299 ADDR is valid on the current target. */
301 static bool
302 valid_mem_ref_p (enum machine_mode mode, struct mem_address *addr)
304 rtx address;
306 address = addr_for_mem_ref (addr, false);
307 if (!address)
308 return 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
315 TARGET_MEM_REF. */
317 static tree
318 create_mem_ref_raw (tree type, struct mem_address *addr)
320 if (!valid_mem_ref_p (TYPE_MODE (type), addr))
321 return NULL_TREE;
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. */
336 static bool
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. */
346 static void
347 aff_combination_remove_elt (struct affine_tree_combination *comb, unsigned m)
349 comb->n--;
350 if (m <= comb->n)
352 comb->coefs[m] = comb->coefs[comb->n];
353 comb->elts[m] = comb->elts[comb->n];
355 if (comb->rest)
357 comb->coefs[comb->n] = 1;
358 comb->elts[comb->n] = comb->rest;
359 comb->rest = NULL_TREE;
360 comb->n++;
364 /* If ADDR contains an address of object that is a link time constant,
365 move it to PARTS->symbol. */
367 static void
368 move_fixed_address_to_symbol (struct mem_address *parts,
369 struct affine_tree_combination *addr)
371 unsigned i;
372 tree val = NULL_TREE;
374 for (i = 0; i < addr->n; i++)
376 if (addr->coefs[i] != 1)
377 continue;
379 val = addr->elts[i];
380 if (TREE_CODE (val) == ADDR_EXPR
381 && fixed_address_object_p (TREE_OPERAND (val, 0)))
382 break;
385 if (i == addr->n)
386 return;
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
393 PARTS->base. */
395 static void
396 move_pointer_to_base (struct mem_address *parts,
397 struct affine_tree_combination *addr)
399 unsigned i;
400 tree val = NULL_TREE;
402 for (i = 0; i < addr->n; i++)
404 if (addr->coefs[i] != 1)
405 continue;
407 val = addr->elts[i];
408 if (POINTER_TYPE_P (TREE_TYPE (val)))
409 break;
412 if (i == addr->n)
413 return;
415 parts->base = val;
416 aff_combination_remove_elt (addr, i);
419 /* Adds ELT to PARTS. */
421 static void
422 add_to_parts (struct mem_address *parts, tree elt)
424 tree type;
426 if (!parts->index)
428 parts->index = elt;
429 return;
432 if (!parts->base)
434 parts->base = elt;
435 return;
438 /* Add ELT to base. */
439 type = TREE_TYPE (parts->base);
440 parts->base = fold_build2 (PLUS_EXPR, type,
441 parts->base,
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. */
449 static void
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;
456 unsigned i, j;
458 for (i = 0; i < addr->n; i++)
460 if (addr->coefs[i] == 1
461 || !multiplier_allowed_in_address_p (addr->coefs[i]))
462 continue;
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];
473 if (!best_mult)
474 return;
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];
482 j++;
483 continue;
486 elt = fold_convert (sizetype, addr->elts[i]);
487 if (!mult_elt)
488 mult_elt = elt;
489 else
490 mult_elt = fold_build2 (PLUS_EXPR, sizetype, mult_elt, elt);
492 addr->n = j;
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. */
507 static void
508 addr_to_parts (struct affine_tree_combination *addr, struct mem_address *parts)
510 unsigned i;
511 tree part;
513 parts->symbol = NULL_TREE;
514 parts->base = NULL_TREE;
515 parts->index = NULL_TREE;
516 parts->step = NULL_TREE;
518 if (addr->offset)
519 parts->offset = build_int_cst_type (sizetype, addr->offset);
520 else
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
527 to index. */
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. */
533 if (!parts->symbol)
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);
545 if (addr->rest)
546 add_to_parts (parts, fold_convert (sizetype, addr->rest));
549 /* Force the PARTS to register. */
551 static void
552 gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
554 if (parts->base)
555 parts->base = force_gimple_operand_bsi (bsi, parts->base,
556 true, NULL_TREE);
557 if (parts->index)
558 parts->index = force_gimple_operand_bsi (bsi, parts->index,
559 true, NULL_TREE);
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. */
566 tree
567 create_mem_ref (block_stmt_iterator *bsi, tree type,
568 struct affine_tree_combination *addr)
570 tree mem_ref, tmp;
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);
577 if (mem_ref)
578 return mem_ref;
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),
589 true, NULL_TREE);
590 parts.step = NULL_TREE;
592 mem_ref = create_mem_ref_raw (type, &parts);
593 if (mem_ref)
594 return mem_ref;
597 if (parts.symbol)
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. */
603 if (parts.base)
605 if (parts.index)
606 parts.base = force_gimple_operand_bsi (bsi,
607 fold_build2 (PLUS_EXPR, addr_type,
608 fold_convert (addr_type, parts.base),
609 tmp),
610 true, NULL_TREE);
611 else
613 parts.index = parts.base;
614 parts.base = tmp;
617 else
618 parts.base = tmp;
619 parts.symbol = NULL_TREE;
621 mem_ref = create_mem_ref_raw (type, &parts);
622 if (mem_ref)
623 return mem_ref;
626 if (parts.index)
628 /* Add index to base. */
629 if (parts.base)
631 atype = TREE_TYPE (parts.base);
632 parts.base = force_gimple_operand_bsi (bsi,
633 fold_build2 (PLUS_EXPR, atype,
634 parts.base,
635 fold_convert (atype, parts.index)),
636 true, NULL_TREE);
638 else
639 parts.base = parts.index;
640 parts.index = NULL_TREE;
642 mem_ref = create_mem_ref_raw (type, &parts);
643 if (mem_ref)
644 return mem_ref;
647 if (parts.offset && !integer_zerop (parts.offset))
649 /* Try adding offset to base. */
650 if (parts.base)
652 atype = TREE_TYPE (parts.base);
653 parts.base = force_gimple_operand_bsi (bsi,
654 fold_build2 (PLUS_EXPR, atype,
655 parts.base,
656 fold_convert (atype, parts.offset)),
657 true, NULL_TREE);
659 else
660 parts.base = parts.offset;
662 parts.offset = NULL_TREE;
664 mem_ref = create_mem_ref_raw (type, &parts);
665 if (mem_ref)
666 return mem_ref;
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));
676 gcc_unreachable ();
679 /* Copies components of the address from OP to ADDR. */
681 void
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. */
693 void
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. */
706 tree
707 maybe_fold_tmr (tree ref)
709 struct mem_address addr;
710 bool changed = false;
711 tree ret, off;
713 get_address_description (ref, &addr);
715 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
717 if (addr.offset)
718 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
719 addr.offset,
720 fold_convert (sizetype, addr.base));
721 else
722 addr.offset = addr.base;
724 addr.base = NULL_TREE;
725 changed = true;
728 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
730 off = addr.index;
731 if (addr.step)
733 off = fold_binary_to_constant (MULT_EXPR, sizetype,
734 off, addr.step);
735 addr.step = NULL_TREE;
738 if (addr.offset)
740 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
741 addr.offset, off);
743 else
744 addr.offset = off;
746 addr.index = NULL_TREE;
747 changed = true;
750 if (!changed)
751 return NULL_TREE;
753 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
754 if (!ret)
755 return NULL_TREE;
757 copy_mem_ref_info (ret, ref);
758 return ret;
761 /* Dump PARTS to FILE. */
763 extern void dump_mem_address (FILE *, struct mem_address *);
764 void
765 dump_mem_address (FILE *file, struct mem_address *parts)
767 if (parts->symbol)
769 fprintf (file, "symbol: ");
770 print_generic_expr (file, parts->symbol, TDF_SLIM);
771 fprintf (file, "\n");
773 if (parts->base)
775 fprintf (file, "base: ");
776 print_generic_expr (file, parts->base, TDF_SLIM);
777 fprintf (file, "\n");
779 if (parts->index)
781 fprintf (file, "index: ");
782 print_generic_expr (file, parts->index, TDF_SLIM);
783 fprintf (file, "\n");
785 if (parts->step)
787 fprintf (file, "step: ");
788 print_generic_expr (file, parts->step, TDF_SLIM);
789 fprintf (file, "\n");
791 if (parts->offset)
793 fprintf (file, "offset: ");
794 print_generic_expr (file, parts->offset, TDF_SLIM);
795 fprintf (file, "\n");
799 #include "gt-tree-ssa-address.h"