]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-address.c
dfp.m4: Quote argument of AC_MSG_WARN.
[thirdparty/gcc.git] / gcc / tree-ssa-address.c
CommitLineData
ac182688 1/* Memory address lowering and addressing mode selection.
c75c517d
SB
2 Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
b8698a0f 4
ac182688 5This file is part of GCC.
b8698a0f 6
ac182688
ZD
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9dcd6f09 9Free Software Foundation; either version 3, or (at your option) any
ac182688 10later version.
b8698a0f 11
ac182688
ZD
12GCC is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
b8698a0f 16
ac182688 17You should have received a copy of the GNU General Public License
9dcd6f09
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
ac182688
ZD
20
21/* Utility functions for manipulation with TARGET_MEM_REFs -- tree expressions
22 that directly map to addressing modes of the target. */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "tree.h"
ac182688 29#include "tm_p.h"
ac182688
ZD
30#include "basic-block.h"
31#include "output.h"
cf835838 32#include "tree-pretty-print.h"
ac182688
ZD
33#include "tree-flow.h"
34#include "tree-dump.h"
35#include "tree-pass.h"
36#include "timevar.h"
37#include "flags.h"
38#include "tree-inline.h"
40013784
SB
39#include "tree-affine.h"
40
41/* FIXME: We compute address costs using RTL. */
ac182688 42#include "insn-config.h"
40013784 43#include "rtl.h"
ac182688
ZD
44#include "recog.h"
45#include "expr.h"
46#include "ggc.h"
d4ebfa65 47#include "target.h"
ac182688
ZD
48
49/* TODO -- handling of symbols (according to Richard Hendersons
50 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
b8698a0f 51
ac182688
ZD
52 There are at least 5 different kinds of symbols that we can run up against:
53
54 (1) binds_local_p, small data area.
55 (2) binds_local_p, eg local statics
56 (3) !binds_local_p, eg global variables
57 (4) thread local, local_exec
58 (5) thread local, !local_exec
59
60 Now, (1) won't appear often in an array context, but it certainly can.
61 All you have to do is set -GN high enough, or explicitly mark any
62 random object __attribute__((section (".sdata"))).
63
64 All of these affect whether or not a symbol is in fact a valid address.
65 The only one tested here is (3). And that result may very well
66 be incorrect for (4) or (5).
67
68 An incorrect result here does not cause incorrect results out the
69 back end, because the expander in expr.c validizes the address. However
70 it would be nice to improve the handling here in order to produce more
71 precise results. */
72
73/* A "template" for memory address, used to determine whether the address is
74 valid for mode. */
75
d4ebfa65 76typedef struct GTY (()) mem_addr_template {
ac182688
ZD
77 rtx ref; /* The template. */
78 rtx * GTY ((skip)) step_p; /* The point in template where the step should be
79 filled in. */
80 rtx * GTY ((skip)) off_p; /* The point in template where the offset should
81 be filled in. */
d4ebfa65 82} mem_addr_template;
ac182688 83
d4ebfa65
BE
84DEF_VEC_O (mem_addr_template);
85DEF_VEC_ALLOC_O (mem_addr_template, gc);
ac182688 86
d4ebfa65
BE
87/* The templates. Each of the low five bits of the index corresponds to one
88 component of TARGET_MEM_REF being present, while the high bits identify
89 the address space. See TEMPL_IDX. */
ac182688 90
d4ebfa65
BE
91static GTY(()) VEC (mem_addr_template, gc) *mem_addr_template_list;
92
93#define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
94 (((int) (AS) << 5) \
95 | ((SYMBOL != 0) << 4) \
ac182688
ZD
96 | ((BASE != 0) << 3) \
97 | ((INDEX != 0) << 2) \
98 | ((STEP != 0) << 1) \
99 | (OFFSET != 0))
100
101/* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
d4ebfa65
BE
102 STEP and OFFSET to *ADDR using address mode ADDRESS_MODE. Stores pointers
103 to where step is placed to *STEP_P and offset to *OFFSET_P. */
ac182688
ZD
104
105static void
d4ebfa65
BE
106gen_addr_rtx (enum machine_mode address_mode,
107 rtx symbol, rtx base, rtx index, rtx step, rtx offset,
ac182688
ZD
108 rtx *addr, rtx **step_p, rtx **offset_p)
109{
110 rtx act_elem;
111
112 *addr = NULL_RTX;
113 if (step_p)
114 *step_p = NULL;
115 if (offset_p)
116 *offset_p = NULL;
117
118 if (index)
119 {
120 act_elem = index;
121 if (step)
122 {
d4ebfa65 123 act_elem = gen_rtx_MULT (address_mode, act_elem, step);
ac182688
ZD
124
125 if (step_p)
126 *step_p = &XEXP (act_elem, 1);
127 }
128
129 *addr = act_elem;
130 }
131
132 if (base)
133 {
134 if (*addr)
d4ebfa65 135 *addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
ac182688
ZD
136 else
137 *addr = base;
138 }
139
140 if (symbol)
141 {
142 act_elem = symbol;
143 if (offset)
144 {
d4ebfa65 145 act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
8893239d 146
ac182688 147 if (offset_p)
8893239d
RH
148 *offset_p = &XEXP (act_elem, 1);
149
150 if (GET_CODE (symbol) == SYMBOL_REF
151 || GET_CODE (symbol) == LABEL_REF
152 || GET_CODE (symbol) == CONST)
d4ebfa65 153 act_elem = gen_rtx_CONST (address_mode, act_elem);
ac182688
ZD
154 }
155
156 if (*addr)
d4ebfa65 157 *addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
ac182688
ZD
158 else
159 *addr = act_elem;
160 }
161 else if (offset)
162 {
163 if (*addr)
164 {
d4ebfa65 165 *addr = gen_rtx_PLUS (address_mode, *addr, offset);
ac182688
ZD
166 if (offset_p)
167 *offset_p = &XEXP (*addr, 1);
168 }
169 else
170 {
171 *addr = offset;
172 if (offset_p)
173 *offset_p = addr;
174 }
175 }
176
177 if (!*addr)
178 *addr = const0_rtx;
179}
180
d4ebfa65
BE
181/* Returns address for TARGET_MEM_REF with parameters given by ADDR
182 in address space AS.
b8698a0f 183 If REALLY_EXPAND is false, just make fake registers instead
ac182688
ZD
184 of really expanding the operands, and perform the expansion in-place
185 by using one of the "templates". */
186
187rtx
d4ebfa65
BE
188addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
189 bool really_expand)
ac182688 190{
d4ebfa65 191 enum machine_mode address_mode = targetm.addr_space.address_mode (as);
ac182688 192 rtx address, sym, bse, idx, st, off;
ac182688
ZD
193 struct mem_addr_template *templ;
194
195 if (addr->step && !integer_onep (addr->step))
54fb1ae0 196 st = immed_double_int_const (tree_to_double_int (addr->step), address_mode);
ac182688
ZD
197 else
198 st = NULL_RTX;
199
200 if (addr->offset && !integer_zerop (addr->offset))
4b228e61
RG
201 off = immed_double_int_const
202 (double_int_sext (tree_to_double_int (addr->offset),
203 TYPE_PRECISION (TREE_TYPE (addr->offset))),
204 address_mode);
ac182688
ZD
205 else
206 off = NULL_RTX;
207
208 if (!really_expand)
209 {
d4ebfa65
BE
210 unsigned int templ_index
211 = TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
212
213 if (templ_index
214 >= VEC_length (mem_addr_template, mem_addr_template_list))
215 VEC_safe_grow_cleared (mem_addr_template, gc, mem_addr_template_list,
216 templ_index + 1);
217
ac182688 218 /* Reuse the templates for addresses, so that we do not waste memory. */
d4ebfa65
BE
219 templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
220 if (!templ->ref)
ac182688 221 {
d4ebfa65
BE
222 sym = (addr->symbol ?
223 gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol"))
224 : NULL_RTX);
225 bse = (addr->base ?
226 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1)
227 : NULL_RTX);
228 idx = (addr->index ?
229 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2)
230 : NULL_RTX);
231
232 gen_addr_rtx (address_mode, sym, bse, idx,
233 st? const0_rtx : NULL_RTX,
234 off? const0_rtx : NULL_RTX,
235 &templ->ref,
236 &templ->step_p,
237 &templ->off_p);
ac182688
ZD
238 }
239
ac182688
ZD
240 if (st)
241 *templ->step_p = st;
242 if (off)
243 *templ->off_p = off;
244
245 return templ->ref;
246 }
247
248 /* Otherwise really expand the expressions. */
249 sym = (addr->symbol
23a534a1 250 ? expand_expr (addr->symbol, NULL_RTX, address_mode, EXPAND_NORMAL)
ac182688
ZD
251 : NULL_RTX);
252 bse = (addr->base
d4ebfa65 253 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL)
ac182688
ZD
254 : NULL_RTX);
255 idx = (addr->index
d4ebfa65 256 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL)
ac182688
ZD
257 : NULL_RTX);
258
d4ebfa65 259 gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL);
ac182688
ZD
260 return address;
261}
262
263/* Returns address of MEM_REF in TYPE. */
264
265tree
266tree_mem_ref_addr (tree type, tree mem_ref)
267{
820410e0 268 tree addr;
ac182688
ZD
269 tree act_elem;
270 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
820410e0 271 tree addr_base = NULL_TREE, addr_off = NULL_TREE;
ac182688 272
4d948885 273 addr_base = fold_convert (type, TMR_BASE (mem_ref));
ac182688 274
820410e0 275 act_elem = TMR_INDEX (mem_ref);
ac182688
ZD
276 if (act_elem)
277 {
820410e0
ZD
278 if (step)
279 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
280 addr_off = act_elem;
ac182688
ZD
281 }
282
4d948885 283 act_elem = TMR_INDEX2 (mem_ref);
ac182688
ZD
284 if (act_elem)
285 {
820410e0
ZD
286 if (addr_off)
287 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
ac182688 288 else
820410e0 289 addr_off = act_elem;
ac182688
ZD
290 }
291
6e682d7e 292 if (offset && !integer_zerop (offset))
ac182688 293 {
521fdcda 294 offset = fold_convert (sizetype, offset);
820410e0
ZD
295 if (addr_off)
296 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
ac182688 297 else
820410e0 298 addr_off = offset;
ac182688
ZD
299 }
300
820410e0 301 if (addr_off)
4d948885 302 addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
820410e0 303 else
4d948885 304 addr = addr_base;
ac182688
ZD
305
306 return addr;
307}
308
309/* Returns true if a memory reference in MODE and with parameters given by
310 ADDR is valid on the current target. */
311
312static bool
09e881c9
BE
313valid_mem_ref_p (enum machine_mode mode, addr_space_t as,
314 struct mem_address *addr)
ac182688
ZD
315{
316 rtx address;
317
d4ebfa65 318 address = addr_for_mem_ref (addr, as, false);
ac182688
ZD
319 if (!address)
320 return false;
321
09e881c9 322 return memory_address_addr_space_p (mode, address, as);
ac182688
ZD
323}
324
325/* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
326 is valid on the current target and if so, creates and returns the
327 TARGET_MEM_REF. */
328
329static tree
a41e5e86 330create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr)
ac182688 331{
4d948885
RG
332 tree base, index2;
333
09e881c9 334 if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
ac182688
ZD
335 return NULL_TREE;
336
337 if (addr->step && integer_onep (addr->step))
338 addr->step = NULL_TREE;
339
4b228e61
RG
340 if (addr->offset)
341 addr->offset = fold_convert (alias_ptr_type, addr->offset);
342 else
343 addr->offset = build_int_cst (alias_ptr_type, 0);
ac182688 344
4d948885 345 if (addr->symbol)
a41e5e86 346 {
4d948885
RG
347 base = addr->symbol;
348 index2 = addr->base;
349 }
350 else if (addr->base
351 && POINTER_TYPE_P (TREE_TYPE (addr->base)))
352 {
353 base = addr->base;
354 index2 = NULL_TREE;
a41e5e86 355 }
4d948885
RG
356 else
357 {
358 base = build_int_cst (ptr_type_node, 0);
359 index2 = addr->base;
360 }
361
362 /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF. */
363 if (alias_ptr_type
364 && (!index2 || integer_zerop (index2))
365 && (!addr->index || integer_zerop (addr->index)))
366 return fold_build2 (MEM_REF, type, base, addr->offset);
a41e5e86 367
4b228e61 368 return build5 (TARGET_MEM_REF, type,
4d948885 369 base, addr->offset, addr->index, addr->step, index2);
ac182688
ZD
370}
371
372/* Returns true if OBJ is an object whose address is a link time constant. */
373
374static bool
375fixed_address_object_p (tree obj)
376{
377 return (TREE_CODE (obj) == VAR_DECL
378 && (TREE_STATIC (obj)
8c51effa
RG
379 || DECL_EXTERNAL (obj))
380 && ! DECL_DLLIMPORT_P (obj));
ac182688
ZD
381}
382
820410e0
ZD
383/* If ADDR contains an address of object that is a link time constant,
384 move it to PARTS->symbol. */
ac182688
ZD
385
386static void
820410e0 387move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
ac182688 388{
820410e0
ZD
389 unsigned i;
390 tree val = NULL_TREE;
73f30c63 391
820410e0 392 for (i = 0; i < addr->n; i++)
ac182688 393 {
820410e0
ZD
394 if (!double_int_one_p (addr->elts[i].coef))
395 continue;
396
397 val = addr->elts[i].val;
398 if (TREE_CODE (val) == ADDR_EXPR
399 && fixed_address_object_p (TREE_OPERAND (val, 0)))
400 break;
ac182688
ZD
401 }
402
820410e0
ZD
403 if (i == addr->n)
404 return;
405
23a534a1 406 parts->symbol = val;
820410e0
ZD
407 aff_combination_remove_elt (addr, i);
408}
409
d7c0c068
UW
410/* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */
411
412static void
413move_hint_to_base (tree type, struct mem_address *parts, tree base_hint,
414 aff_tree *addr)
415{
416 unsigned i;
417 tree val = NULL_TREE;
5456cefc 418 int qual;
d7c0c068
UW
419
420 for (i = 0; i < addr->n; i++)
421 {
422 if (!double_int_one_p (addr->elts[i].coef))
423 continue;
424
425 val = addr->elts[i].val;
426 if (operand_equal_p (val, base_hint, 0))
427 break;
428 }
429
430 if (i == addr->n)
431 return;
432
5456cefc
UW
433 /* Cast value to appropriate pointer type. We cannot use a pointer
434 to TYPE directly, as the back-end will assume registers of pointer
435 type are aligned, and just the base itself may not actually be.
436 We use void pointer to the type's address space instead. */
437 qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type));
438 type = build_qualified_type (void_type_node, qual);
d7c0c068
UW
439 parts->base = fold_convert (build_pointer_type (type), val);
440 aff_combination_remove_elt (addr, i);
441}
442
820410e0
ZD
443/* If ADDR contains an address of a dereferenced pointer, move it to
444 PARTS->base. */
445
446static void
447move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
448{
449 unsigned i;
450 tree val = NULL_TREE;
451
452 for (i = 0; i < addr->n; i++)
ac182688 453 {
820410e0
ZD
454 if (!double_int_one_p (addr->elts[i].coef))
455 continue;
456
457 val = addr->elts[i].val;
458 if (POINTER_TYPE_P (TREE_TYPE (val)))
459 break;
ac182688
ZD
460 }
461
820410e0
ZD
462 if (i == addr->n)
463 return;
464
465 parts->base = val;
466 aff_combination_remove_elt (addr, i);
467}
468
880a1451
XDL
469/* Moves the loop variant part V in linear address ADDR to be the index
470 of PARTS. */
471
472static void
473move_variant_to_index (struct mem_address *parts, aff_tree *addr, tree v)
474{
475 unsigned i;
476 tree val = NULL_TREE;
477
478 gcc_assert (!parts->index);
479 for (i = 0; i < addr->n; i++)
480 {
481 val = addr->elts[i].val;
482 if (operand_equal_p (val, v, 0))
483 break;
484 }
485
486 if (i == addr->n)
487 return;
488
489 parts->index = fold_convert (sizetype, val);
490 parts->step = double_int_to_tree (sizetype, addr->elts[i].coef);
491 aff_combination_remove_elt (addr, i);
492}
493
820410e0
ZD
494/* Adds ELT to PARTS. */
495
496static void
497add_to_parts (struct mem_address *parts, tree elt)
498{
499 tree type;
500
ac182688
ZD
501 if (!parts->index)
502 {
5be014d5 503 parts->index = fold_convert (sizetype, elt);
ac182688
ZD
504 return;
505 }
506
820410e0
ZD
507 if (!parts->base)
508 {
509 parts->base = elt;
510 return;
511 }
512
ac182688 513 /* Add ELT to base. */
820410e0 514 type = TREE_TYPE (parts->base);
6fe2f65a
RG
515 if (POINTER_TYPE_P (type))
516 parts->base = fold_build2 (POINTER_PLUS_EXPR, type,
517 parts->base,
518 fold_convert (sizetype, elt));
519 else
520 parts->base = fold_build2 (PLUS_EXPR, type,
521 parts->base, elt);
ac182688
ZD
522}
523
524/* Finds the most expensive multiplication in ADDR that can be
525 expressed in an addressing mode and move the corresponding
820410e0 526 element(s) to PARTS. */
ac182688
ZD
527
528static void
d7c0c068
UW
529most_expensive_mult_to_index (tree type, struct mem_address *parts,
530 aff_tree *addr, bool speed)
ac182688 531{
d7c0c068
UW
532 addr_space_t as = TYPE_ADDR_SPACE (type);
533 enum machine_mode address_mode = targetm.addr_space.address_mode (as);
73f30c63
ZD
534 HOST_WIDE_INT coef;
535 double_int best_mult, amult, amult_neg;
ac182688
ZD
536 unsigned best_mult_cost = 0, acost;
537 tree mult_elt = NULL_TREE, elt;
538 unsigned i, j;
73f30c63 539 enum tree_code op_code;
ac182688 540
73f30c63 541 best_mult = double_int_zero;
ac182688
ZD
542 for (i = 0; i < addr->n; i++)
543 {
73f30c63
ZD
544 if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
545 continue;
546
73f30c63
ZD
547 coef = double_int_to_shwi (addr->elts[i].coef);
548 if (coef == 1
d7c0c068 549 || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as))
ac182688 550 continue;
73f30c63 551
d7c0c068 552 acost = multiply_by_cost (coef, address_mode, speed);
ac182688
ZD
553
554 if (acost > best_mult_cost)
555 {
556 best_mult_cost = acost;
73f30c63 557 best_mult = addr->elts[i].coef;
ac182688
ZD
558 }
559 }
560
73f30c63 561 if (!best_mult_cost)
ac182688
ZD
562 return;
563
73f30c63 564 /* Collect elements multiplied by best_mult. */
ac182688
ZD
565 for (i = j = 0; i < addr->n; i++)
566 {
73f30c63
ZD
567 amult = addr->elts[i].coef;
568 amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
b8698a0f 569
73f30c63
ZD
570 if (double_int_equal_p (amult, best_mult))
571 op_code = PLUS_EXPR;
572 else if (double_int_equal_p (amult_neg, best_mult))
573 op_code = MINUS_EXPR;
574 else
ac182688 575 {
ac182688
ZD
576 addr->elts[j] = addr->elts[i];
577 j++;
578 continue;
579 }
5be014d5 580
820410e0 581 elt = fold_convert (sizetype, addr->elts[i].val);
73f30c63 582 if (mult_elt)
820410e0 583 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
73f30c63 584 else if (op_code == PLUS_EXPR)
ac182688
ZD
585 mult_elt = elt;
586 else
820410e0 587 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
ac182688
ZD
588 }
589 addr->n = j;
b8698a0f 590
ac182688 591 parts->index = mult_elt;
820410e0 592 parts->step = double_int_to_tree (sizetype, best_mult);
ac182688
ZD
593}
594
d7c0c068
UW
595/* Splits address ADDR for a memory access of type TYPE into PARTS.
596 If BASE_HINT is non-NULL, it specifies an SSA name to be used
880a1451
XDL
597 preferentially as base of the reference, and IV_CAND is the selected
598 iv candidate used in ADDR.
d7c0c068 599
ac182688
ZD
600 TODO -- be more clever about the distribution of the elements of ADDR
601 to PARTS. Some architectures do not support anything but single
602 register in address, possibly with a small integer offset; while
603 create_mem_ref will simplify the address to an acceptable shape
73f30c63
ZD
604 later, it would be more efficient to know that asking for complicated
605 addressing modes is useless. */
ac182688
ZD
606
607static void
880a1451
XDL
608addr_to_parts (tree type, aff_tree *addr, tree iv_cand,
609 tree base_hint, struct mem_address *parts,
610 bool speed)
ac182688 611{
73f30c63 612 tree part;
ac182688
ZD
613 unsigned i;
614
615 parts->symbol = NULL_TREE;
616 parts->base = NULL_TREE;
617 parts->index = NULL_TREE;
618 parts->step = NULL_TREE;
619
73f30c63 620 if (!double_int_zero_p (addr->offset))
820410e0 621 parts->offset = double_int_to_tree (sizetype, addr->offset);
ac182688
ZD
622 else
623 parts->offset = NULL_TREE;
624
820410e0
ZD
625 /* Try to find a symbol. */
626 move_fixed_address_to_symbol (parts, addr);
627
880a1451
XDL
628 /* No need to do address parts reassociation if the number of parts
629 is <= 2 -- in that case, no loop invariant code motion can be
630 exposed. */
631
632 if (!base_hint && (addr->n > 2))
633 move_variant_to_index (parts, addr, iv_cand);
634
ac182688
ZD
635 /* First move the most expensive feasible multiplication
636 to index. */
880a1451
XDL
637 if (!parts->index)
638 most_expensive_mult_to_index (type, parts, addr, speed);
820410e0
ZD
639
640 /* Try to find a base of the reference. Since at the moment
641 there is no reliable way how to distinguish between pointer and its
642 offset, this is just a guess. */
d7c0c068
UW
643 if (!parts->symbol && base_hint)
644 move_hint_to_base (type, parts, base_hint, addr);
645 if (!parts->symbol && !parts->base)
820410e0 646 move_pointer_to_base (parts, addr);
ac182688
ZD
647
648 /* Then try to process the remaining elements. */
649 for (i = 0; i < addr->n; i++)
73f30c63 650 {
820410e0 651 part = fold_convert (sizetype, addr->elts[i].val);
73f30c63 652 if (!double_int_one_p (addr->elts[i].coef))
820410e0
ZD
653 part = fold_build2 (MULT_EXPR, sizetype, part,
654 double_int_to_tree (sizetype, addr->elts[i].coef));
655 add_to_parts (parts, part);
73f30c63 656 }
ac182688 657 if (addr->rest)
820410e0 658 add_to_parts (parts, fold_convert (sizetype, addr->rest));
ac182688
ZD
659}
660
661/* Force the PARTS to register. */
662
663static void
726a989a 664gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
ac182688
ZD
665{
666 if (parts->base)
bcf71673
RG
667 parts->base = force_gimple_operand_gsi_1 (gsi, parts->base,
668 is_gimple_mem_ref_addr, NULL_TREE,
726a989a 669 true, GSI_SAME_STMT);
ac182688 670 if (parts->index)
726a989a 671 parts->index = force_gimple_operand_gsi (gsi, parts->index,
c6540bde 672 true, NULL_TREE,
726a989a 673 true, GSI_SAME_STMT);
ac182688
ZD
674}
675
676/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
726a989a 677 computations are emitted in front of GSI. TYPE is the mode
880a1451
XDL
678 of created memory reference. IV_CAND is the selected iv candidate in ADDR,
679 and BASE_HINT is non NULL if IV_CAND comes from a base address
680 object. */
ac182688
ZD
681
682tree
880a1451
XDL
683create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
684 tree alias_ptr_type, tree iv_cand, tree base_hint, bool speed)
ac182688
ZD
685{
686 tree mem_ref, tmp;
69bd3423 687 tree atype;
ac182688
ZD
688 struct mem_address parts;
689
880a1451 690 addr_to_parts (type, addr, iv_cand, base_hint, &parts, speed);
726a989a 691 gimplify_mem_ref_parts (gsi, &parts);
a41e5e86 692 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
ac182688
ZD
693 if (mem_ref)
694 return mem_ref;
695
696 /* The expression is too complicated. Try making it simpler. */
697
698 if (parts.step && !integer_onep (parts.step))
699 {
700 /* Move the multiplication to index. */
701 gcc_assert (parts.index);
726a989a 702 parts.index = force_gimple_operand_gsi (gsi,
820410e0
ZD
703 fold_build2 (MULT_EXPR, sizetype,
704 parts.index, parts.step),
726a989a 705 true, NULL_TREE, true, GSI_SAME_STMT);
ac182688 706 parts.step = NULL_TREE;
b8698a0f 707
a41e5e86 708 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
ac182688
ZD
709 if (mem_ref)
710 return mem_ref;
711 }
712
713 if (parts.symbol)
714 {
23a534a1 715 tmp = parts.symbol;
69bd3423 716 gcc_assert (is_gimple_val (tmp));
b8698a0f 717
ac182688
ZD
718 /* Add the symbol to base, eventually forcing it to register. */
719 if (parts.base)
39278c14 720 {
36618b93 721 gcc_assert (useless_type_conversion_p
5f787cbc 722 (sizetype, TREE_TYPE (parts.base)));
69bd3423 723
39278c14 724 if (parts.index)
69bd3423
ZD
725 {
726 atype = TREE_TYPE (tmp);
bcf71673 727 parts.base = force_gimple_operand_gsi_1 (gsi,
786ce82d
RG
728 fold_build2 (POINTER_PLUS_EXPR, atype,
729 tmp,
730 fold_convert (sizetype, parts.base)),
bcf71673 731 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
69bd3423 732 }
39278c14
AK
733 else
734 {
735 parts.index = parts.base;
736 parts.base = tmp;
737 }
738 }
ac182688
ZD
739 else
740 parts.base = tmp;
741 parts.symbol = NULL_TREE;
742
a41e5e86 743 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
ac182688
ZD
744 if (mem_ref)
745 return mem_ref;
746 }
747
820410e0 748 if (parts.index)
ac182688 749 {
820410e0
ZD
750 /* Add index to base. */
751 if (parts.base)
752 {
753 atype = TREE_TYPE (parts.base);
bcf71673 754 parts.base = force_gimple_operand_gsi_1 (gsi,
903b3003 755 fold_build2 (POINTER_PLUS_EXPR, atype,
820410e0 756 parts.base,
903b3003 757 parts.index),
bcf71673 758 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
820410e0 759 }
ac182688 760 else
820410e0
ZD
761 parts.base = parts.index;
762 parts.index = NULL_TREE;
ac182688 763
a41e5e86 764 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
ac182688
ZD
765 if (mem_ref)
766 return mem_ref;
767 }
768
769 if (parts.offset && !integer_zerop (parts.offset))
770 {
820410e0
ZD
771 /* Try adding offset to base. */
772 if (parts.base)
773 {
774 atype = TREE_TYPE (parts.base);
bcf71673 775 parts.base = force_gimple_operand_gsi_1 (gsi,
5be014d5 776 fold_build2 (POINTER_PLUS_EXPR, atype,
820410e0 777 parts.base,
5be014d5 778 fold_convert (sizetype, parts.offset)),
bcf71673 779 is_gimple_mem_ref_addr, NULL_TREE, true, GSI_SAME_STMT);
820410e0 780 }
ac182688 781 else
cdd76d88 782 parts.base = parts.offset;
ac182688
ZD
783
784 parts.offset = NULL_TREE;
785
a41e5e86 786 mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
ac182688
ZD
787 if (mem_ref)
788 return mem_ref;
789 }
790
791 /* Verify that the address is in the simplest possible shape
792 (only a register). If we cannot create such a memory reference,
793 something is really wrong. */
794 gcc_assert (parts.symbol == NULL_TREE);
820410e0 795 gcc_assert (parts.index == NULL_TREE);
ac182688
ZD
796 gcc_assert (!parts.step || integer_onep (parts.step));
797 gcc_assert (!parts.offset || integer_zerop (parts.offset));
798 gcc_unreachable ();
799}
800
801/* Copies components of the address from OP to ADDR. */
802
803void
804get_address_description (tree op, struct mem_address *addr)
805{
4d948885
RG
806 if (TREE_CODE (TMR_BASE (op)) == ADDR_EXPR)
807 {
808 addr->symbol = TMR_BASE (op);
809 addr->base = TMR_INDEX2 (op);
810 }
811 else
812 {
813 addr->symbol = NULL_TREE;
814 if (TMR_INDEX2 (op))
815 {
816 gcc_assert (integer_zerop (TMR_BASE (op)));
817 addr->base = TMR_INDEX2 (op);
818 }
819 else
820 addr->base = TMR_BASE (op);
821 }
ac182688
ZD
822 addr->index = TMR_INDEX (op);
823 addr->step = TMR_STEP (op);
824 addr->offset = TMR_OFFSET (op);
825}
826
827/* Copies the additional information attached to target_mem_ref FROM to TO. */
828
829void
830copy_mem_ref_info (tree to, tree from)
831{
ac182688 832 /* And the info about the original reference. */
5e9fb3db
RG
833 TREE_SIDE_EFFECTS (to) = TREE_SIDE_EFFECTS (from);
834 TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from);
ac182688
ZD
835}
836
837/* Move constants in target_mem_ref REF to offset. Returns the new target
838 mem ref if anything changes, NULL_TREE otherwise. */
839
840tree
841maybe_fold_tmr (tree ref)
842{
843 struct mem_address addr;
844 bool changed = false;
845 tree ret, off;
846
847 get_address_description (ref, &addr);
848
4d948885
RG
849 if (addr.base
850 && TREE_CODE (addr.base) == INTEGER_CST
851 && !integer_zerop (addr.base))
ac182688 852 {
4b228e61
RG
853 addr.offset = fold_binary_to_constant (PLUS_EXPR,
854 TREE_TYPE (addr.offset),
855 addr.offset, addr.base);
ac182688
ZD
856 addr.base = NULL_TREE;
857 changed = true;
858 }
859
4d948885
RG
860 if (addr.symbol
861 && TREE_CODE (TREE_OPERAND (addr.symbol, 0)) == MEM_REF)
862 {
863 addr.offset = fold_binary_to_constant
864 (PLUS_EXPR, TREE_TYPE (addr.offset),
865 addr.offset,
866 TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 1));
867 addr.symbol = TREE_OPERAND (TREE_OPERAND (addr.symbol, 0), 0);
868 changed = true;
869 }
870 else if (addr.symbol
871 && handled_component_p (TREE_OPERAND (addr.symbol, 0)))
872 {
873 HOST_WIDE_INT offset;
874 addr.symbol = build_fold_addr_expr
875 (get_addr_base_and_unit_offset
876 (TREE_OPERAND (addr.symbol, 0), &offset));
877 addr.offset = int_const_binop (PLUS_EXPR,
878 addr.offset, size_int (offset), 0);
879 changed = true;
880 }
881
ac182688
ZD
882 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
883 {
884 off = addr.index;
885 if (addr.step)
886 {
820410e0 887 off = fold_binary_to_constant (MULT_EXPR, sizetype,
ac182688
ZD
888 off, addr.step);
889 addr.step = NULL_TREE;
890 }
891
4b228e61
RG
892 addr.offset = fold_binary_to_constant (PLUS_EXPR,
893 TREE_TYPE (addr.offset),
894 addr.offset, off);
ac182688
ZD
895 addr.index = NULL_TREE;
896 changed = true;
897 }
898
899 if (!changed)
900 return NULL_TREE;
b8698a0f 901
4b228e61 902 ret = create_mem_ref_raw (TREE_TYPE (ref), TREE_TYPE (addr.offset), &addr);
ac182688
ZD
903 if (!ret)
904 return NULL_TREE;
905
906 copy_mem_ref_info (ret, ref);
907 return ret;
908}
909
910/* Dump PARTS to FILE. */
911
912extern void dump_mem_address (FILE *, struct mem_address *);
913void
914dump_mem_address (FILE *file, struct mem_address *parts)
915{
916 if (parts->symbol)
917 {
918 fprintf (file, "symbol: ");
23a534a1 919 print_generic_expr (file, TREE_OPERAND (parts->symbol, 0), TDF_SLIM);
ac182688
ZD
920 fprintf (file, "\n");
921 }
922 if (parts->base)
923 {
924 fprintf (file, "base: ");
925 print_generic_expr (file, parts->base, TDF_SLIM);
926 fprintf (file, "\n");
927 }
928 if (parts->index)
929 {
930 fprintf (file, "index: ");
931 print_generic_expr (file, parts->index, TDF_SLIM);
932 fprintf (file, "\n");
933 }
934 if (parts->step)
935 {
936 fprintf (file, "step: ");
937 print_generic_expr (file, parts->step, TDF_SLIM);
938 fprintf (file, "\n");
939 }
940 if (parts->offset)
941 {
942 fprintf (file, "offset: ");
943 print_generic_expr (file, parts->offset, TDF_SLIM);
944 fprintf (file, "\n");
945 }
946}
947
948#include "gt-tree-ssa-address.h"