]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-address.c
tree-flow.h (tree_ssa_useless_type_conversion_1): Rename to ...
[thirdparty/gcc.git] / gcc / tree-ssa-address.c
CommitLineData
ac182688 1/* Memory address lowering and addressing mode selection.
8893239d 2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
ac182688
ZD
3
4This file is part of GCC.
5
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
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
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.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING. If not, write to the Free
366ccddb
KC
18Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
1902110-1301, USA. */
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"
29#include "rtl.h"
30#include "tm_p.h"
31#include "hard-reg-set.h"
32#include "basic-block.h"
33#include "output.h"
34#include "diagnostic.h"
35#include "tree-flow.h"
36#include "tree-dump.h"
37#include "tree-pass.h"
38#include "timevar.h"
39#include "flags.h"
40#include "tree-inline.h"
41#include "insn-config.h"
42#include "recog.h"
43#include "expr.h"
44#include "ggc.h"
73f30c63 45#include "tree-affine.h"
ac182688
ZD
46
47/* TODO -- handling of symbols (according to Richard Hendersons
48 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
49
50 There are at least 5 different kinds of symbols that we can run up against:
51
52 (1) binds_local_p, small data area.
53 (2) binds_local_p, eg local statics
54 (3) !binds_local_p, eg global variables
55 (4) thread local, local_exec
56 (5) thread local, !local_exec
57
58 Now, (1) won't appear often in an array context, but it certainly can.
59 All you have to do is set -GN high enough, or explicitly mark any
60 random object __attribute__((section (".sdata"))).
61
62 All of these affect whether or not a symbol is in fact a valid address.
63 The only one tested here is (3). And that result may very well
64 be incorrect for (4) or (5).
65
66 An incorrect result here does not cause incorrect results out the
67 back end, because the expander in expr.c validizes the address. However
68 it would be nice to improve the handling here in order to produce more
69 precise results. */
70
71/* A "template" for memory address, used to determine whether the address is
72 valid for mode. */
73
74struct mem_addr_template GTY (())
75{
76 rtx ref; /* The template. */
77 rtx * GTY ((skip)) step_p; /* The point in template where the step should be
78 filled in. */
79 rtx * GTY ((skip)) off_p; /* The point in template where the offset should
80 be filled in. */
81};
82
83/* The templates. Each of the five bits of the index corresponds to one
84 component of TARGET_MEM_REF being present, see TEMPL_IDX. */
85
86static GTY (()) struct mem_addr_template templates[32];
87
88#define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
89 (((SYMBOL != 0) << 4) \
90 | ((BASE != 0) << 3) \
91 | ((INDEX != 0) << 2) \
92 | ((STEP != 0) << 1) \
93 | (OFFSET != 0))
94
95/* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
96 STEP and OFFSET to *ADDR. Stores pointers to where step is placed to
97 *STEP_P and offset to *OFFSET_P. */
98
99static void
100gen_addr_rtx (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
101 rtx *addr, rtx **step_p, rtx **offset_p)
102{
103 rtx act_elem;
104
105 *addr = NULL_RTX;
106 if (step_p)
107 *step_p = NULL;
108 if (offset_p)
109 *offset_p = NULL;
110
111 if (index)
112 {
113 act_elem = index;
114 if (step)
115 {
116 act_elem = gen_rtx_MULT (Pmode, act_elem, step);
117
118 if (step_p)
119 *step_p = &XEXP (act_elem, 1);
120 }
121
122 *addr = act_elem;
123 }
124
125 if (base)
126 {
127 if (*addr)
128 *addr = gen_rtx_PLUS (Pmode, *addr, base);
129 else
130 *addr = base;
131 }
132
133 if (symbol)
134 {
135 act_elem = symbol;
136 if (offset)
137 {
8893239d
RH
138 act_elem = gen_rtx_PLUS (Pmode, act_elem, offset);
139
ac182688 140 if (offset_p)
8893239d
RH
141 *offset_p = &XEXP (act_elem, 1);
142
143 if (GET_CODE (symbol) == SYMBOL_REF
144 || GET_CODE (symbol) == LABEL_REF
145 || GET_CODE (symbol) == CONST)
146 act_elem = gen_rtx_CONST (Pmode, act_elem);
ac182688
ZD
147 }
148
149 if (*addr)
150 *addr = gen_rtx_PLUS (Pmode, *addr, act_elem);
151 else
152 *addr = act_elem;
153 }
154 else if (offset)
155 {
156 if (*addr)
157 {
158 *addr = gen_rtx_PLUS (Pmode, *addr, offset);
159 if (offset_p)
160 *offset_p = &XEXP (*addr, 1);
161 }
162 else
163 {
164 *addr = offset;
165 if (offset_p)
166 *offset_p = addr;
167 }
168 }
169
170 if (!*addr)
171 *addr = const0_rtx;
172}
173
174/* Returns address for TARGET_MEM_REF with parameters given by ADDR.
175 If REALLY_EXPAND is false, just make fake registers instead
176 of really expanding the operands, and perform the expansion in-place
177 by using one of the "templates". */
178
179rtx
180addr_for_mem_ref (struct mem_address *addr, bool really_expand)
181{
182 rtx address, sym, bse, idx, st, off;
183 static bool templates_initialized = false;
184 struct mem_addr_template *templ;
185
186 if (addr->step && !integer_onep (addr->step))
187 st = immed_double_const (TREE_INT_CST_LOW (addr->step),
188 TREE_INT_CST_HIGH (addr->step), Pmode);
189 else
190 st = NULL_RTX;
191
192 if (addr->offset && !integer_zerop (addr->offset))
193 off = immed_double_const (TREE_INT_CST_LOW (addr->offset),
194 TREE_INT_CST_HIGH (addr->offset), Pmode);
195 else
196 off = NULL_RTX;
197
198 if (!really_expand)
199 {
200 /* Reuse the templates for addresses, so that we do not waste memory. */
201 if (!templates_initialized)
202 {
203 unsigned i;
204
205 templates_initialized = true;
206 sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup ("test_symbol"));
03daa27a
ZD
207 bse = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
208 idx = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
ac182688
ZD
209
210 for (i = 0; i < 32; i++)
211 gen_addr_rtx ((i & 16 ? sym : NULL_RTX),
212 (i & 8 ? bse : NULL_RTX),
213 (i & 4 ? idx : NULL_RTX),
214 (i & 2 ? const0_rtx : NULL_RTX),
215 (i & 1 ? const0_rtx : NULL_RTX),
216 &templates[i].ref,
217 &templates[i].step_p,
218 &templates[i].off_p);
219 }
220
221 templ = templates + TEMPL_IDX (addr->symbol, addr->base, addr->index,
222 st, off);
223 if (st)
224 *templ->step_p = st;
225 if (off)
226 *templ->off_p = off;
227
228 return templ->ref;
229 }
230
231 /* Otherwise really expand the expressions. */
232 sym = (addr->symbol
233 ? expand_expr (build_addr (addr->symbol, current_function_decl),
234 NULL_RTX, Pmode, EXPAND_NORMAL)
235 : NULL_RTX);
236 bse = (addr->base
237 ? expand_expr (addr->base, NULL_RTX, Pmode, EXPAND_NORMAL)
238 : NULL_RTX);
239 idx = (addr->index
240 ? expand_expr (addr->index, NULL_RTX, Pmode, EXPAND_NORMAL)
241 : NULL_RTX);
242
243 gen_addr_rtx (sym, bse, idx, st, off, &address, NULL, NULL);
244 return address;
245}
246
247/* Returns address of MEM_REF in TYPE. */
248
249tree
250tree_mem_ref_addr (tree type, tree mem_ref)
251{
820410e0 252 tree addr;
ac182688
ZD
253 tree act_elem;
254 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
820410e0
ZD
255 tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref);
256 tree addr_base = NULL_TREE, addr_off = NULL_TREE;
ac182688 257
820410e0
ZD
258 if (sym)
259 addr_base = fold_convert (type, build_addr (sym, current_function_decl));
260 else if (base && POINTER_TYPE_P (TREE_TYPE (base)))
ac182688 261 {
820410e0
ZD
262 addr_base = fold_convert (type, base);
263 base = NULL_TREE;
ac182688
ZD
264 }
265
820410e0 266 act_elem = TMR_INDEX (mem_ref);
ac182688
ZD
267 if (act_elem)
268 {
820410e0
ZD
269 if (step)
270 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
271 addr_off = act_elem;
ac182688
ZD
272 }
273
820410e0 274 act_elem = base;
ac182688
ZD
275 if (act_elem)
276 {
820410e0
ZD
277 if (addr_off)
278 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
ac182688 279 else
820410e0 280 addr_off = act_elem;
ac182688
ZD
281 }
282
6e682d7e 283 if (offset && !integer_zerop (offset))
ac182688 284 {
820410e0
ZD
285 if (addr_off)
286 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
ac182688 287 else
820410e0 288 addr_off = offset;
ac182688
ZD
289 }
290
820410e0
ZD
291 if (addr_off)
292 {
820410e0 293 if (addr_base)
5be014d5
AP
294 addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off);
295 else
296 addr = fold_convert (type, addr_off);
820410e0
ZD
297 }
298 else if (addr_base)
299 addr = addr_base;
300 else
ac182688
ZD
301 addr = build_int_cst (type, 0);
302
303 return addr;
304}
305
306/* Returns true if a memory reference in MODE and with parameters given by
307 ADDR is valid on the current target. */
308
309static bool
310valid_mem_ref_p (enum machine_mode mode, struct mem_address *addr)
311{
312 rtx address;
313
314 address = addr_for_mem_ref (addr, false);
315 if (!address)
316 return false;
317
318 return memory_address_p (mode, address);
319}
320
321/* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
322 is valid on the current target and if so, creates and returns the
323 TARGET_MEM_REF. */
324
325static tree
326create_mem_ref_raw (tree type, struct mem_address *addr)
327{
328 if (!valid_mem_ref_p (TYPE_MODE (type), addr))
329 return NULL_TREE;
330
331 if (addr->step && integer_onep (addr->step))
332 addr->step = NULL_TREE;
333
6e682d7e 334 if (addr->offset && integer_zerop (addr->offset))
ac182688
ZD
335 addr->offset = NULL_TREE;
336
337 return build7 (TARGET_MEM_REF, type,
338 addr->symbol, addr->base, addr->index,
339 addr->step, addr->offset, NULL, NULL);
340}
341
342/* Returns true if OBJ is an object whose address is a link time constant. */
343
344static bool
345fixed_address_object_p (tree obj)
346{
347 return (TREE_CODE (obj) == VAR_DECL
348 && (TREE_STATIC (obj)
349 || DECL_EXTERNAL (obj)));
350}
351
820410e0
ZD
352/* If ADDR contains an address of object that is a link time constant,
353 move it to PARTS->symbol. */
ac182688
ZD
354
355static void
820410e0 356move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
ac182688 357{
820410e0
ZD
358 unsigned i;
359 tree val = NULL_TREE;
73f30c63 360
820410e0 361 for (i = 0; i < addr->n; i++)
ac182688 362 {
820410e0
ZD
363 if (!double_int_one_p (addr->elts[i].coef))
364 continue;
365
366 val = addr->elts[i].val;
367 if (TREE_CODE (val) == ADDR_EXPR
368 && fixed_address_object_p (TREE_OPERAND (val, 0)))
369 break;
ac182688
ZD
370 }
371
820410e0
ZD
372 if (i == addr->n)
373 return;
374
375 parts->symbol = TREE_OPERAND (val, 0);
376 aff_combination_remove_elt (addr, i);
377}
378
379/* If ADDR contains an address of a dereferenced pointer, move it to
380 PARTS->base. */
381
382static void
383move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
384{
385 unsigned i;
386 tree val = NULL_TREE;
387
388 for (i = 0; i < addr->n; i++)
ac182688 389 {
820410e0
ZD
390 if (!double_int_one_p (addr->elts[i].coef))
391 continue;
392
393 val = addr->elts[i].val;
394 if (POINTER_TYPE_P (TREE_TYPE (val)))
395 break;
ac182688
ZD
396 }
397
820410e0
ZD
398 if (i == addr->n)
399 return;
400
401 parts->base = val;
402 aff_combination_remove_elt (addr, i);
403}
404
405/* Adds ELT to PARTS. */
406
407static void
408add_to_parts (struct mem_address *parts, tree elt)
409{
410 tree type;
411
ac182688
ZD
412 if (!parts->index)
413 {
5be014d5 414 parts->index = fold_convert (sizetype, elt);
ac182688
ZD
415 return;
416 }
417
820410e0
ZD
418 if (!parts->base)
419 {
420 parts->base = elt;
421 return;
422 }
423
ac182688 424 /* Add ELT to base. */
820410e0
ZD
425 type = TREE_TYPE (parts->base);
426 parts->base = fold_build2 (PLUS_EXPR, type,
427 parts->base,
428 fold_convert (type, elt));
ac182688
ZD
429}
430
431/* Finds the most expensive multiplication in ADDR that can be
432 expressed in an addressing mode and move the corresponding
820410e0 433 element(s) to PARTS. */
ac182688
ZD
434
435static void
820410e0 436most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr)
ac182688 437{
73f30c63
ZD
438 HOST_WIDE_INT coef;
439 double_int best_mult, amult, amult_neg;
ac182688
ZD
440 unsigned best_mult_cost = 0, acost;
441 tree mult_elt = NULL_TREE, elt;
442 unsigned i, j;
73f30c63 443 enum tree_code op_code;
ac182688 444
73f30c63 445 best_mult = double_int_zero;
ac182688
ZD
446 for (i = 0; i < addr->n; i++)
447 {
73f30c63
ZD
448 if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
449 continue;
450
dd5f63f8 451 /* FIXME: Should use the correct memory mode rather than Pmode. */
73f30c63
ZD
452
453 coef = double_int_to_shwi (addr->elts[i].coef);
454 if (coef == 1
455 || !multiplier_allowed_in_address_p (coef, Pmode))
ac182688 456 continue;
73f30c63
ZD
457
458 acost = multiply_by_cost (coef, Pmode);
ac182688
ZD
459
460 if (acost > best_mult_cost)
461 {
462 best_mult_cost = acost;
73f30c63 463 best_mult = addr->elts[i].coef;
ac182688
ZD
464 }
465 }
466
73f30c63 467 if (!best_mult_cost)
ac182688
ZD
468 return;
469
73f30c63 470 /* Collect elements multiplied by best_mult. */
ac182688
ZD
471 for (i = j = 0; i < addr->n; i++)
472 {
73f30c63
ZD
473 amult = addr->elts[i].coef;
474 amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
475
476 if (double_int_equal_p (amult, best_mult))
477 op_code = PLUS_EXPR;
478 else if (double_int_equal_p (amult_neg, best_mult))
479 op_code = MINUS_EXPR;
480 else
ac182688 481 {
ac182688
ZD
482 addr->elts[j] = addr->elts[i];
483 j++;
484 continue;
485 }
5be014d5 486
820410e0 487 elt = fold_convert (sizetype, addr->elts[i].val);
73f30c63 488 if (mult_elt)
820410e0 489 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
73f30c63 490 else if (op_code == PLUS_EXPR)
ac182688
ZD
491 mult_elt = elt;
492 else
820410e0 493 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
ac182688
ZD
494 }
495 addr->n = j;
73f30c63 496
ac182688 497 parts->index = mult_elt;
820410e0 498 parts->step = double_int_to_tree (sizetype, best_mult);
ac182688
ZD
499}
500
501/* Splits address ADDR into PARTS.
502
503 TODO -- be more clever about the distribution of the elements of ADDR
504 to PARTS. Some architectures do not support anything but single
505 register in address, possibly with a small integer offset; while
506 create_mem_ref will simplify the address to an acceptable shape
73f30c63
ZD
507 later, it would be more efficient to know that asking for complicated
508 addressing modes is useless. */
ac182688
ZD
509
510static void
820410e0 511addr_to_parts (aff_tree *addr, struct mem_address *parts)
ac182688 512{
73f30c63 513 tree part;
ac182688
ZD
514 unsigned i;
515
516 parts->symbol = NULL_TREE;
517 parts->base = NULL_TREE;
518 parts->index = NULL_TREE;
519 parts->step = NULL_TREE;
520
73f30c63 521 if (!double_int_zero_p (addr->offset))
820410e0 522 parts->offset = double_int_to_tree (sizetype, addr->offset);
ac182688
ZD
523 else
524 parts->offset = NULL_TREE;
525
820410e0
ZD
526 /* Try to find a symbol. */
527 move_fixed_address_to_symbol (parts, addr);
528
ac182688
ZD
529 /* First move the most expensive feasible multiplication
530 to index. */
820410e0
ZD
531 most_expensive_mult_to_index (parts, addr);
532
533 /* Try to find a base of the reference. Since at the moment
534 there is no reliable way how to distinguish between pointer and its
535 offset, this is just a guess. */
536 if (!parts->symbol)
537 move_pointer_to_base (parts, addr);
ac182688
ZD
538
539 /* Then try to process the remaining elements. */
540 for (i = 0; i < addr->n; i++)
73f30c63 541 {
820410e0 542 part = fold_convert (sizetype, addr->elts[i].val);
73f30c63 543 if (!double_int_one_p (addr->elts[i].coef))
820410e0
ZD
544 part = fold_build2 (MULT_EXPR, sizetype, part,
545 double_int_to_tree (sizetype, addr->elts[i].coef));
546 add_to_parts (parts, part);
73f30c63 547 }
ac182688 548 if (addr->rest)
820410e0 549 add_to_parts (parts, fold_convert (sizetype, addr->rest));
ac182688
ZD
550}
551
552/* Force the PARTS to register. */
553
554static void
555gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
556{
557 if (parts->base)
558 parts->base = force_gimple_operand_bsi (bsi, parts->base,
559 true, NULL_TREE);
560 if (parts->index)
561 parts->index = force_gimple_operand_bsi (bsi, parts->index,
562 true, NULL_TREE);
563}
564
565/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
566 computations are emitted in front of BSI. TYPE is the mode
567 of created memory reference. */
568
569tree
73f30c63 570create_mem_ref (block_stmt_iterator *bsi, tree type, aff_tree *addr)
ac182688
ZD
571{
572 tree mem_ref, tmp;
69bd3423 573 tree atype;
ac182688
ZD
574 struct mem_address parts;
575
820410e0 576 addr_to_parts (addr, &parts);
ac182688
ZD
577 gimplify_mem_ref_parts (bsi, &parts);
578 mem_ref = create_mem_ref_raw (type, &parts);
579 if (mem_ref)
580 return mem_ref;
581
582 /* The expression is too complicated. Try making it simpler. */
583
584 if (parts.step && !integer_onep (parts.step))
585 {
586 /* Move the multiplication to index. */
587 gcc_assert (parts.index);
588 parts.index = force_gimple_operand_bsi (bsi,
820410e0
ZD
589 fold_build2 (MULT_EXPR, sizetype,
590 parts.index, parts.step),
591 true, NULL_TREE);
ac182688
ZD
592 parts.step = NULL_TREE;
593
594 mem_ref = create_mem_ref_raw (type, &parts);
595 if (mem_ref)
596 return mem_ref;
597 }
598
599 if (parts.symbol)
600 {
69bd3423
ZD
601 tmp = build_addr (parts.symbol, current_function_decl);
602 gcc_assert (is_gimple_val (tmp));
ac182688
ZD
603
604 /* Add the symbol to base, eventually forcing it to register. */
605 if (parts.base)
39278c14 606 {
36618b93 607 gcc_assert (useless_type_conversion_p
5f787cbc 608 (sizetype, TREE_TYPE (parts.base)));
69bd3423 609
39278c14 610 if (parts.index)
69bd3423
ZD
611 {
612 atype = TREE_TYPE (tmp);
613 parts.base = force_gimple_operand_bsi (bsi,
614 fold_build2 (PLUS_EXPR, atype,
615 fold_convert (atype, parts.base),
820410e0
ZD
616 tmp),
617 true, NULL_TREE);
69bd3423 618 }
39278c14
AK
619 else
620 {
621 parts.index = parts.base;
622 parts.base = tmp;
623 }
624 }
ac182688
ZD
625 else
626 parts.base = tmp;
627 parts.symbol = NULL_TREE;
628
629 mem_ref = create_mem_ref_raw (type, &parts);
630 if (mem_ref)
631 return mem_ref;
632 }
633
820410e0 634 if (parts.index)
ac182688 635 {
820410e0
ZD
636 /* Add index to base. */
637 if (parts.base)
638 {
639 atype = TREE_TYPE (parts.base);
640 parts.base = force_gimple_operand_bsi (bsi,
641 fold_build2 (PLUS_EXPR, atype,
642 parts.base,
643 fold_convert (atype, parts.index)),
644 true, NULL_TREE);
645 }
ac182688 646 else
820410e0
ZD
647 parts.base = parts.index;
648 parts.index = NULL_TREE;
ac182688
ZD
649
650 mem_ref = create_mem_ref_raw (type, &parts);
651 if (mem_ref)
652 return mem_ref;
653 }
654
655 if (parts.offset && !integer_zerop (parts.offset))
656 {
820410e0
ZD
657 /* Try adding offset to base. */
658 if (parts.base)
659 {
660 atype = TREE_TYPE (parts.base);
661 parts.base = force_gimple_operand_bsi (bsi,
5be014d5 662 fold_build2 (POINTER_PLUS_EXPR, atype,
820410e0 663 parts.base,
5be014d5 664 fold_convert (sizetype, parts.offset)),
820410e0
ZD
665 true, NULL_TREE);
666 }
ac182688 667 else
cdd76d88 668 parts.base = parts.offset;
ac182688
ZD
669
670 parts.offset = NULL_TREE;
671
672 mem_ref = create_mem_ref_raw (type, &parts);
673 if (mem_ref)
674 return mem_ref;
675 }
676
677 /* Verify that the address is in the simplest possible shape
678 (only a register). If we cannot create such a memory reference,
679 something is really wrong. */
680 gcc_assert (parts.symbol == NULL_TREE);
820410e0 681 gcc_assert (parts.index == NULL_TREE);
ac182688
ZD
682 gcc_assert (!parts.step || integer_onep (parts.step));
683 gcc_assert (!parts.offset || integer_zerop (parts.offset));
684 gcc_unreachable ();
685}
686
687/* Copies components of the address from OP to ADDR. */
688
689void
690get_address_description (tree op, struct mem_address *addr)
691{
692 addr->symbol = TMR_SYMBOL (op);
693 addr->base = TMR_BASE (op);
694 addr->index = TMR_INDEX (op);
695 addr->step = TMR_STEP (op);
696 addr->offset = TMR_OFFSET (op);
697}
698
699/* Copies the additional information attached to target_mem_ref FROM to TO. */
700
701void
702copy_mem_ref_info (tree to, tree from)
703{
704 /* Copy the annotation, to preserve the aliasing information. */
705 TMR_TAG (to) = TMR_TAG (from);
706
707 /* And the info about the original reference. */
708 TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
709}
710
711/* Move constants in target_mem_ref REF to offset. Returns the new target
712 mem ref if anything changes, NULL_TREE otherwise. */
713
714tree
715maybe_fold_tmr (tree ref)
716{
717 struct mem_address addr;
718 bool changed = false;
719 tree ret, off;
720
721 get_address_description (ref, &addr);
722
723 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
724 {
725 if (addr.offset)
820410e0
ZD
726 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
727 addr.offset,
728 fold_convert (sizetype, addr.base));
ac182688
ZD
729 else
730 addr.offset = addr.base;
731
732 addr.base = NULL_TREE;
733 changed = true;
734 }
735
736 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
737 {
738 off = addr.index;
739 if (addr.step)
740 {
820410e0 741 off = fold_binary_to_constant (MULT_EXPR, sizetype,
ac182688
ZD
742 off, addr.step);
743 addr.step = NULL_TREE;
744 }
745
746 if (addr.offset)
747 {
820410e0 748 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
ac182688
ZD
749 addr.offset, off);
750 }
751 else
752 addr.offset = off;
753
754 addr.index = NULL_TREE;
755 changed = true;
756 }
757
758 if (!changed)
759 return NULL_TREE;
760
761 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
762 if (!ret)
763 return NULL_TREE;
764
765 copy_mem_ref_info (ret, ref);
766 return ret;
767}
768
769/* Dump PARTS to FILE. */
770
771extern void dump_mem_address (FILE *, struct mem_address *);
772void
773dump_mem_address (FILE *file, struct mem_address *parts)
774{
775 if (parts->symbol)
776 {
777 fprintf (file, "symbol: ");
778 print_generic_expr (file, parts->symbol, TDF_SLIM);
779 fprintf (file, "\n");
780 }
781 if (parts->base)
782 {
783 fprintf (file, "base: ");
784 print_generic_expr (file, parts->base, TDF_SLIM);
785 fprintf (file, "\n");
786 }
787 if (parts->index)
788 {
789 fprintf (file, "index: ");
790 print_generic_expr (file, parts->index, TDF_SLIM);
791 fprintf (file, "\n");
792 }
793 if (parts->step)
794 {
795 fprintf (file, "step: ");
796 print_generic_expr (file, parts->step, TDF_SLIM);
797 fprintf (file, "\n");
798 }
799 if (parts->offset)
800 {
801 fprintf (file, "offset: ");
802 print_generic_expr (file, parts->offset, TDF_SLIM);
803 fprintf (file, "\n");
804 }
805}
806
807#include "gt-tree-ssa-address.h"