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