]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-address.c
config.gcc (i?86-*-darwin*): Add t-crtfm and t-crtpc.
[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 {
293 addr = fold_convert (type, addr_off);
294 if (addr_base)
295 addr = fold_build2 (PLUS_EXPR, type, addr_base, addr);
296 }
297 else if (addr_base)
298 addr = addr_base;
299 else
ac182688
ZD
300 addr = build_int_cst (type, 0);
301
302 return addr;
303}
304
305/* Returns true if a memory reference in MODE and with parameters given by
306 ADDR is valid on the current target. */
307
308static bool
309valid_mem_ref_p (enum machine_mode mode, struct mem_address *addr)
310{
311 rtx address;
312
313 address = addr_for_mem_ref (addr, false);
314 if (!address)
315 return false;
316
317 return memory_address_p (mode, address);
318}
319
320/* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
321 is valid on the current target and if so, creates and returns the
322 TARGET_MEM_REF. */
323
324static tree
325create_mem_ref_raw (tree type, struct mem_address *addr)
326{
327 if (!valid_mem_ref_p (TYPE_MODE (type), addr))
328 return NULL_TREE;
329
330 if (addr->step && integer_onep (addr->step))
331 addr->step = NULL_TREE;
332
6e682d7e 333 if (addr->offset && integer_zerop (addr->offset))
ac182688
ZD
334 addr->offset = NULL_TREE;
335
336 return build7 (TARGET_MEM_REF, type,
337 addr->symbol, addr->base, addr->index,
338 addr->step, addr->offset, NULL, NULL);
339}
340
341/* Returns true if OBJ is an object whose address is a link time constant. */
342
343static bool
344fixed_address_object_p (tree obj)
345{
346 return (TREE_CODE (obj) == VAR_DECL
347 && (TREE_STATIC (obj)
348 || DECL_EXTERNAL (obj)));
349}
350
820410e0
ZD
351/* If ADDR contains an address of object that is a link time constant,
352 move it to PARTS->symbol. */
ac182688
ZD
353
354static void
820410e0 355move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr)
ac182688 356{
820410e0
ZD
357 unsigned i;
358 tree val = NULL_TREE;
73f30c63 359
820410e0 360 for (i = 0; i < addr->n; i++)
ac182688 361 {
820410e0
ZD
362 if (!double_int_one_p (addr->elts[i].coef))
363 continue;
364
365 val = addr->elts[i].val;
366 if (TREE_CODE (val) == ADDR_EXPR
367 && fixed_address_object_p (TREE_OPERAND (val, 0)))
368 break;
ac182688
ZD
369 }
370
820410e0
ZD
371 if (i == addr->n)
372 return;
373
374 parts->symbol = TREE_OPERAND (val, 0);
375 aff_combination_remove_elt (addr, i);
376}
377
378/* If ADDR contains an address of a dereferenced pointer, move it to
379 PARTS->base. */
380
381static void
382move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
383{
384 unsigned i;
385 tree val = NULL_TREE;
386
387 for (i = 0; i < addr->n; i++)
ac182688 388 {
820410e0
ZD
389 if (!double_int_one_p (addr->elts[i].coef))
390 continue;
391
392 val = addr->elts[i].val;
393 if (POINTER_TYPE_P (TREE_TYPE (val)))
394 break;
ac182688
ZD
395 }
396
820410e0
ZD
397 if (i == addr->n)
398 return;
399
400 parts->base = val;
401 aff_combination_remove_elt (addr, i);
402}
403
404/* Adds ELT to PARTS. */
405
406static void
407add_to_parts (struct mem_address *parts, tree elt)
408{
409 tree type;
410
ac182688
ZD
411 if (!parts->index)
412 {
413 parts->index = elt;
414 return;
415 }
416
820410e0
ZD
417 if (!parts->base)
418 {
419 parts->base = elt;
420 return;
421 }
422
ac182688 423 /* Add ELT to base. */
820410e0
ZD
424 type = TREE_TYPE (parts->base);
425 parts->base = fold_build2 (PLUS_EXPR, type,
426 parts->base,
427 fold_convert (type, elt));
ac182688
ZD
428}
429
430/* Finds the most expensive multiplication in ADDR that can be
431 expressed in an addressing mode and move the corresponding
820410e0 432 element(s) to PARTS. */
ac182688
ZD
433
434static void
820410e0 435most_expensive_mult_to_index (struct mem_address *parts, aff_tree *addr)
ac182688 436{
73f30c63
ZD
437 HOST_WIDE_INT coef;
438 double_int best_mult, amult, amult_neg;
ac182688
ZD
439 unsigned best_mult_cost = 0, acost;
440 tree mult_elt = NULL_TREE, elt;
441 unsigned i, j;
73f30c63 442 enum tree_code op_code;
ac182688 443
73f30c63 444 best_mult = double_int_zero;
ac182688
ZD
445 for (i = 0; i < addr->n; i++)
446 {
73f30c63
ZD
447 if (!double_int_fits_in_shwi_p (addr->elts[i].coef))
448 continue;
449
dd5f63f8 450 /* FIXME: Should use the correct memory mode rather than Pmode. */
73f30c63
ZD
451
452 coef = double_int_to_shwi (addr->elts[i].coef);
453 if (coef == 1
454 || !multiplier_allowed_in_address_p (coef, Pmode))
ac182688 455 continue;
73f30c63
ZD
456
457 acost = multiply_by_cost (coef, Pmode);
ac182688
ZD
458
459 if (acost > best_mult_cost)
460 {
461 best_mult_cost = acost;
73f30c63 462 best_mult = addr->elts[i].coef;
ac182688
ZD
463 }
464 }
465
73f30c63 466 if (!best_mult_cost)
ac182688
ZD
467 return;
468
73f30c63 469 /* Collect elements multiplied by best_mult. */
ac182688
ZD
470 for (i = j = 0; i < addr->n; i++)
471 {
73f30c63
ZD
472 amult = addr->elts[i].coef;
473 amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr);
474
475 if (double_int_equal_p (amult, best_mult))
476 op_code = PLUS_EXPR;
477 else if (double_int_equal_p (amult_neg, best_mult))
478 op_code = MINUS_EXPR;
479 else
ac182688 480 {
ac182688
ZD
481 addr->elts[j] = addr->elts[i];
482 j++;
483 continue;
484 }
73f30c63 485
820410e0 486 elt = fold_convert (sizetype, addr->elts[i].val);
73f30c63 487 if (mult_elt)
820410e0 488 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt);
73f30c63 489 else if (op_code == PLUS_EXPR)
ac182688
ZD
490 mult_elt = elt;
491 else
820410e0 492 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt);
ac182688
ZD
493 }
494 addr->n = j;
73f30c63 495
ac182688 496 parts->index = mult_elt;
820410e0 497 parts->step = double_int_to_tree (sizetype, best_mult);
ac182688
ZD
498}
499
500/* Splits address ADDR into PARTS.
501
502 TODO -- be more clever about the distribution of the elements of ADDR
503 to PARTS. Some architectures do not support anything but single
504 register in address, possibly with a small integer offset; while
505 create_mem_ref will simplify the address to an acceptable shape
73f30c63
ZD
506 later, it would be more efficient to know that asking for complicated
507 addressing modes is useless. */
ac182688
ZD
508
509static void
820410e0 510addr_to_parts (aff_tree *addr, struct mem_address *parts)
ac182688 511{
73f30c63 512 tree part;
ac182688
ZD
513 unsigned i;
514
515 parts->symbol = NULL_TREE;
516 parts->base = NULL_TREE;
517 parts->index = NULL_TREE;
518 parts->step = NULL_TREE;
519
73f30c63 520 if (!double_int_zero_p (addr->offset))
820410e0 521 parts->offset = double_int_to_tree (sizetype, addr->offset);
ac182688
ZD
522 else
523 parts->offset = NULL_TREE;
524
820410e0
ZD
525 /* Try to find a symbol. */
526 move_fixed_address_to_symbol (parts, addr);
527
ac182688
ZD
528 /* First move the most expensive feasible multiplication
529 to index. */
820410e0
ZD
530 most_expensive_mult_to_index (parts, addr);
531
532 /* Try to find a base of the reference. Since at the moment
533 there is no reliable way how to distinguish between pointer and its
534 offset, this is just a guess. */
535 if (!parts->symbol)
536 move_pointer_to_base (parts, addr);
ac182688
ZD
537
538 /* Then try to process the remaining elements. */
539 for (i = 0; i < addr->n; i++)
73f30c63 540 {
820410e0 541 part = fold_convert (sizetype, addr->elts[i].val);
73f30c63 542 if (!double_int_one_p (addr->elts[i].coef))
820410e0
ZD
543 part = fold_build2 (MULT_EXPR, sizetype, part,
544 double_int_to_tree (sizetype, addr->elts[i].coef));
545 add_to_parts (parts, part);
73f30c63 546 }
ac182688 547 if (addr->rest)
820410e0 548 add_to_parts (parts, fold_convert (sizetype, addr->rest));
ac182688
ZD
549}
550
551/* Force the PARTS to register. */
552
553static void
554gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
555{
556 if (parts->base)
557 parts->base = force_gimple_operand_bsi (bsi, parts->base,
558 true, NULL_TREE);
559 if (parts->index)
560 parts->index = force_gimple_operand_bsi (bsi, parts->index,
561 true, NULL_TREE);
562}
563
564/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
565 computations are emitted in front of BSI. TYPE is the mode
566 of created memory reference. */
567
568tree
73f30c63 569create_mem_ref (block_stmt_iterator *bsi, tree type, aff_tree *addr)
ac182688
ZD
570{
571 tree mem_ref, tmp;
69bd3423 572 tree atype;
ac182688
ZD
573 struct mem_address parts;
574
820410e0 575 addr_to_parts (addr, &parts);
ac182688
ZD
576 gimplify_mem_ref_parts (bsi, &parts);
577 mem_ref = create_mem_ref_raw (type, &parts);
578 if (mem_ref)
579 return mem_ref;
580
581 /* The expression is too complicated. Try making it simpler. */
582
583 if (parts.step && !integer_onep (parts.step))
584 {
585 /* Move the multiplication to index. */
586 gcc_assert (parts.index);
587 parts.index = force_gimple_operand_bsi (bsi,
820410e0
ZD
588 fold_build2 (MULT_EXPR, sizetype,
589 parts.index, parts.step),
590 true, NULL_TREE);
ac182688
ZD
591 parts.step = NULL_TREE;
592
593 mem_ref = create_mem_ref_raw (type, &parts);
594 if (mem_ref)
595 return mem_ref;
596 }
597
598 if (parts.symbol)
599 {
69bd3423
ZD
600 tmp = build_addr (parts.symbol, current_function_decl);
601 gcc_assert (is_gimple_val (tmp));
ac182688
ZD
602
603 /* Add the symbol to base, eventually forcing it to register. */
604 if (parts.base)
39278c14 605 {
5f787cbc
ZD
606 gcc_assert (tree_ssa_useless_type_conversion_1
607 (sizetype, TREE_TYPE (parts.base)));
69bd3423 608
39278c14 609 if (parts.index)
69bd3423
ZD
610 {
611 atype = TREE_TYPE (tmp);
612 parts.base = force_gimple_operand_bsi (bsi,
613 fold_build2 (PLUS_EXPR, atype,
614 fold_convert (atype, parts.base),
820410e0
ZD
615 tmp),
616 true, NULL_TREE);
69bd3423 617 }
39278c14
AK
618 else
619 {
620 parts.index = parts.base;
621 parts.base = tmp;
622 }
623 }
ac182688
ZD
624 else
625 parts.base = tmp;
626 parts.symbol = NULL_TREE;
627
628 mem_ref = create_mem_ref_raw (type, &parts);
629 if (mem_ref)
630 return mem_ref;
631 }
632
820410e0 633 if (parts.index)
ac182688 634 {
820410e0
ZD
635 /* Add index to base. */
636 if (parts.base)
637 {
638 atype = TREE_TYPE (parts.base);
639 parts.base = force_gimple_operand_bsi (bsi,
640 fold_build2 (PLUS_EXPR, atype,
641 parts.base,
642 fold_convert (atype, parts.index)),
643 true, NULL_TREE);
644 }
ac182688 645 else
820410e0
ZD
646 parts.base = parts.index;
647 parts.index = NULL_TREE;
ac182688
ZD
648
649 mem_ref = create_mem_ref_raw (type, &parts);
650 if (mem_ref)
651 return mem_ref;
652 }
653
654 if (parts.offset && !integer_zerop (parts.offset))
655 {
820410e0
ZD
656 /* Try adding offset to base. */
657 if (parts.base)
658 {
659 atype = TREE_TYPE (parts.base);
660 parts.base = force_gimple_operand_bsi (bsi,
661 fold_build2 (PLUS_EXPR, atype,
662 parts.base,
663 fold_convert (atype, parts.offset)),
664 true, NULL_TREE);
665 }
ac182688 666 else
cdd76d88 667 parts.base = parts.offset;
ac182688
ZD
668
669 parts.offset = NULL_TREE;
670
671 mem_ref = create_mem_ref_raw (type, &parts);
672 if (mem_ref)
673 return mem_ref;
674 }
675
676 /* Verify that the address is in the simplest possible shape
677 (only a register). If we cannot create such a memory reference,
678 something is really wrong. */
679 gcc_assert (parts.symbol == NULL_TREE);
820410e0 680 gcc_assert (parts.index == NULL_TREE);
ac182688
ZD
681 gcc_assert (!parts.step || integer_onep (parts.step));
682 gcc_assert (!parts.offset || integer_zerop (parts.offset));
683 gcc_unreachable ();
684}
685
686/* Copies components of the address from OP to ADDR. */
687
688void
689get_address_description (tree op, struct mem_address *addr)
690{
691 addr->symbol = TMR_SYMBOL (op);
692 addr->base = TMR_BASE (op);
693 addr->index = TMR_INDEX (op);
694 addr->step = TMR_STEP (op);
695 addr->offset = TMR_OFFSET (op);
696}
697
698/* Copies the additional information attached to target_mem_ref FROM to TO. */
699
700void
701copy_mem_ref_info (tree to, tree from)
702{
703 /* Copy the annotation, to preserve the aliasing information. */
704 TMR_TAG (to) = TMR_TAG (from);
705
706 /* And the info about the original reference. */
707 TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
708}
709
710/* Move constants in target_mem_ref REF to offset. Returns the new target
711 mem ref if anything changes, NULL_TREE otherwise. */
712
713tree
714maybe_fold_tmr (tree ref)
715{
716 struct mem_address addr;
717 bool changed = false;
718 tree ret, off;
719
720 get_address_description (ref, &addr);
721
722 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
723 {
724 if (addr.offset)
820410e0
ZD
725 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
726 addr.offset,
727 fold_convert (sizetype, addr.base));
ac182688
ZD
728 else
729 addr.offset = addr.base;
730
731 addr.base = NULL_TREE;
732 changed = true;
733 }
734
735 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
736 {
737 off = addr.index;
738 if (addr.step)
739 {
820410e0 740 off = fold_binary_to_constant (MULT_EXPR, sizetype,
ac182688
ZD
741 off, addr.step);
742 addr.step = NULL_TREE;
743 }
744
745 if (addr.offset)
746 {
820410e0 747 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
ac182688
ZD
748 addr.offset, off);
749 }
750 else
751 addr.offset = off;
752
753 addr.index = NULL_TREE;
754 changed = true;
755 }
756
757 if (!changed)
758 return NULL_TREE;
759
760 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
761 if (!ret)
762 return NULL_TREE;
763
764 copy_mem_ref_info (ret, ref);
765 return ret;
766}
767
768/* Dump PARTS to FILE. */
769
770extern void dump_mem_address (FILE *, struct mem_address *);
771void
772dump_mem_address (FILE *file, struct mem_address *parts)
773{
774 if (parts->symbol)
775 {
776 fprintf (file, "symbol: ");
777 print_generic_expr (file, parts->symbol, TDF_SLIM);
778 fprintf (file, "\n");
779 }
780 if (parts->base)
781 {
782 fprintf (file, "base: ");
783 print_generic_expr (file, parts->base, TDF_SLIM);
784 fprintf (file, "\n");
785 }
786 if (parts->index)
787 {
788 fprintf (file, "index: ");
789 print_generic_expr (file, parts->index, TDF_SLIM);
790 fprintf (file, "\n");
791 }
792 if (parts->step)
793 {
794 fprintf (file, "step: ");
795 print_generic_expr (file, parts->step, TDF_SLIM);
796 fprintf (file, "\n");
797 }
798 if (parts->offset)
799 {
800 fprintf (file, "offset: ");
801 print_generic_expr (file, parts->offset, TDF_SLIM);
802 fprintf (file, "\n");
803 }
804}
805
806#include "gt-tree-ssa-address.h"