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