1/* Memory address lowering and addressing mode selection. 2 Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by the 9Free Software Foundation; either version 3, or (at your option) any 10later version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT 13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along 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 "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" 45#include "tree-affine.h" 46#include "target.h" 47 48/* TODO -- handling of symbols (according to Richard Hendersons 49 comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html): 50 51 There are at least 5 different kinds of symbols that we can run up against: 52 53 (1) binds_local_p, small data area. 54 (2) binds_local_p, eg local statics 55 (3) !binds_local_p, eg global variables 56 (4) thread local, local_exec 57 (5) thread local, !local_exec 58 59 Now, (1) won't appear often in an array context, but it certainly can. 60 All you have to do is set -GN high enough, or explicitly mark any 61 random object __attribute__((section (".sdata"))). 62 63 All of these affect whether or not a symbol is in fact a valid address. 64 The only one tested here is (3). And that result may very well 65 be incorrect for (4) or (5). 66 67 An incorrect result here does not cause incorrect results out the 68 back end, because the expander in expr.c validizes the address. However 69 it would be nice to improve the handling here in order to produce more 70 precise results. */ 71 72/* A "template" for memory address, used to determine whether the address is 73 valid for mode. */ 74 75typedef struct GTY (()) mem_addr_template { 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} mem_addr_template; 82 83DEF_VEC_O (mem_addr_template); 84DEF_VEC_ALLOC_O (mem_addr_template, gc); 85 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. */ 89 90static GTY(()) VEC (mem_addr_template, gc) *mem_addr_template_list; 91 92#define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \ 93 (((int) (AS) << 5) \ 94 | ((SYMBOL != 0) << 4) \ 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, 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. */ 103 104static void 105gen_addr_rtx (enum machine_mode address_mode, 106 rtx symbol, rtx base, rtx index, rtx step, rtx offset, 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 { 122 act_elem = gen_rtx_MULT (address_mode, act_elem, step); 123 124 if (step_p) 125 *step_p = &XEXP (act_elem, 1); 126 } 127 128 *addr = act_elem; 129 } 130 131 if (base) 132 { 133 if (*addr) 134 *addr = simplify_gen_binary (PLUS, address_mode, base, *addr); 135 else 136 *addr = base; 137 } 138 139 if (symbol) 140 { 141 act_elem = symbol; 142 if (offset) 143 { 144 act_elem = gen_rtx_PLUS (address_mode, act_elem, offset); 145 146 if (offset_p) 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) 152 act_elem = gen_rtx_CONST (address_mode, act_elem); 153 } 154 155 if (*addr) 156 *addr = gen_rtx_PLUS (address_mode, *addr, act_elem); 157 else 158 *addr = act_elem; 159 } 160 else if (offset) 161 { 162 if (*addr) 163 { 164 *addr = gen_rtx_PLUS (address_mode, *addr, offset); 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 180/* Returns address for TARGET_MEM_REF with parameters given by ADDR 181 in address space AS. 182 If REALLY_EXPAND is false, just make fake registers instead 183 of really expanding the operands, and perform the expansion in-place 184 by using one of the "templates". */ 185 186rtx 187addr_for_mem_ref (struct mem_address *addr, addr_space_t as, 188 bool really_expand) 189{ 190 enum machine_mode address_mode = targetm.addr_space.address_mode (as); 191 rtx address, sym, bse, idx, st, off; 192 struct mem_addr_template *templ; 193 194 if (addr->step && !integer_onep (addr->step)) 195 st = immed_double_const (TREE_INT_CST_LOW (addr->step), 196 TREE_INT_CST_HIGH (addr->step), address_mode); 197 else 198 st = NULL_RTX; 199 200 if (addr->offset && !integer_zerop (addr->offset)) 201 off = immed_double_const (TREE_INT_CST_LOW (addr->offset), 202 TREE_INT_CST_HIGH (addr->offset), address_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 (address_mode, ggc_strdup ("test_symbol")) 222 : NULL_RTX); 223 bse = (addr->base ? 224 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1) 225 : NULL_RTX); 226 idx = (addr->index ? 227 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2) 228 : NULL_RTX); 229 230 gen_addr_rtx (address_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 (build_addr (addr->symbol, current_function_decl), 249 NULL_RTX, address_mode, EXPAND_NORMAL) 250 : NULL_RTX); 251 bse = (addr->base 252 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL) 253 : NULL_RTX); 254 idx = (addr->index 255 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL) 256 : NULL_RTX); 257 258 gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL); 259 return address; 260} 261 262/* Returns address of MEM_REF in TYPE. */ 263 264tree 265tree_mem_ref_addr (tree type, tree mem_ref) 266{ 267 tree addr; 268 tree act_elem; 269 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref); 270 tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref); 271 tree addr_base = NULL_TREE, addr_off = NULL_TREE; 272 273 if (sym) 274 addr_base = fold_convert (type, build_addr (sym, current_function_decl)); 275 else if (base && POINTER_TYPE_P (TREE_TYPE (base))) 276 { 277 addr_base = fold_convert (type, base); 278 base = NULL_TREE; 279 } 280 281 act_elem = TMR_INDEX (mem_ref); 282 if (act_elem) 283 { 284 if (step) 285 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step); 286 addr_off = act_elem; 287 } 288 289 act_elem = base; 290 if (act_elem) 291 { 292 if (addr_off) 293 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem); 294 else 295 addr_off = act_elem; 296 } 297 298 if (offset && !integer_zerop (offset)) 299 { 300 if (addr_off) 301 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset); 302 else 303 addr_off = offset; 304 } 305 306 if (addr_off) 307 { 308 if (addr_base) 309 addr = fold_build2 (POINTER_PLUS_EXPR, type, addr_base, addr_off); 310 else 311 addr = fold_convert (type, addr_off); 312 } 313 else if (addr_base) 314 addr = addr_base; 315 else 316 addr = build_int_cst (type, 0); 317 318 return addr; 319} 320 321/* Returns true if a memory reference in MODE and with parameters given by 322 ADDR is valid on the current target. */ 323 324static bool 325valid_mem_ref_p (enum machine_mode mode, addr_space_t as, 326 struct mem_address *addr) 327{ 328 rtx address; 329 330 address = addr_for_mem_ref (addr, as, false); 331 if (!address) 332 return false; 333 334 return memory_address_addr_space_p (mode, address, as); 335} 336 337/* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR 338 is valid on the current target and if so, creates and returns the 339 TARGET_MEM_REF. */ 340 341static tree 342create_mem_ref_raw (tree type, struct mem_address *addr) 343{ 344 if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr)) 345 return NULL_TREE; 346 347 if (addr->step && integer_onep (addr->step)) 348 addr->step = NULL_TREE; 349 350 if (addr->offset && integer_zerop (addr->offset)) 351 addr->offset = NULL_TREE; 352 353 return build6 (TARGET_MEM_REF, type, 354 addr->symbol, addr->base, addr->index, 355 addr->step, addr->offset, NULL); 356} 357 358/* Returns true if OBJ is an object whose address is a link time constant. */ 359 360static bool 361fixed_address_object_p (tree obj) 362{ 363 return (TREE_CODE (obj) == VAR_DECL 364 && (TREE_STATIC (obj) 365 || DECL_EXTERNAL (obj)) 366 && ! DECL_DLLIMPORT_P (obj)); 367} 368 369/* If ADDR contains an address of object that is a link time constant, 370 move it to PARTS->symbol. */ 371 372static void 373move_fixed_address_to_symbol (struct mem_address *parts, aff_tree *addr) 374{ 375 unsigned i; 376 tree val = NULL_TREE; 377 378 for (i = 0; i < addr->n; i++) 379 { 380 if (!double_int_one_p (addr->elts[i].coef)) 381 continue; 382 383 val = addr->elts[i].val; 384 if (TREE_CODE (val) == ADDR_EXPR 385 && fixed_address_object_p (TREE_OPERAND (val, 0))) 386 break; 387 } 388 389 if (i == addr->n) 390 return; 391 392 parts->symbol = TREE_OPERAND (val, 0); 393 aff_combination_remove_elt (addr, i); 394} 395 396/* If ADDR contains an instance of BASE_HINT, move it to PARTS->base. */ 397 398static void 399move_hint_to_base (tree type, struct mem_address *parts, tree base_hint, 400 aff_tree *addr) 401{ 402 unsigned i; 403 tree val = NULL_TREE; 404 int qual; 405 406 for (i = 0; i < addr->n; i++) 407 { 408 if (!double_int_one_p (addr->elts[i].coef)) 409 continue; 410 411 val = addr->elts[i].val; 412 if (operand_equal_p (val, base_hint, 0)) 413 break; 414 } 415 416 if (i == addr->n) 417 return; 418 419 /* Cast value to appropriate pointer type. We cannot use a pointer 420 to TYPE directly, as the back-end will assume registers of pointer 421 type are aligned, and just the base itself may not actually be. 422 We use void pointer to the type's address space instead. */ 423 qual = ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (type)); 424 type = build_qualified_type (void_type_node, qual); 425 parts->base = fold_convert (build_pointer_type (type), val); 426 aff_combination_remove_elt (addr, i); 427} 428 429/* If ADDR contains an address of a dereferenced pointer, move it to 430 PARTS->base. */ 431 432static void 433move_pointer_to_base (struct mem_address *parts, aff_tree *addr) 434{ 435 unsigned i; 436 tree val = NULL_TREE; 437 438 for (i = 0; i < addr->n; i++) 439 { 440 if (!double_int_one_p (addr->elts[i].coef)) 441 continue; 442 443 val = addr->elts[i].val; 444 if (POINTER_TYPE_P (TREE_TYPE (val))) 445 break; 446 } 447 448 if (i == addr->n) 449 return; 450 451 parts->base = val; 452 aff_combination_remove_elt (addr, i); 453} 454 455/* Adds ELT to PARTS. */ 456 457static void 458add_to_parts (struct mem_address *parts, tree elt) 459{ 460 tree type; 461 462 if (!parts->index) 463 { 464 parts->index = fold_convert (sizetype, elt); 465 return; 466 } 467 468 if (!parts->base) 469 { 470 parts->base = elt; 471 return; 472 } 473 474 /* Add ELT to base. */ 475 type = TREE_TYPE (parts->base); 476 if (POINTER_TYPE_P (type)) 477 parts->base = fold_build2 (POINTER_PLUS_EXPR, type, 478 parts->base, 479 fold_convert (sizetype, elt)); 480 else 481 parts->base = fold_build2 (PLUS_EXPR, type, 482 parts->base, elt); 483} 484 485/* Finds the most expensive multiplication in ADDR that can be 486 expressed in an addressing mode and move the corresponding 487 element(s) to PARTS. */ 488 489static void 490most_expensive_mult_to_index (tree type, struct mem_address *parts, 491 aff_tree *addr, bool speed) 492{ 493 addr_space_t as = TYPE_ADDR_SPACE (type); 494 enum machine_mode address_mode = targetm.addr_space.address_mode (as); 495 HOST_WIDE_INT coef; 496 double_int best_mult, amult, amult_neg; 497 unsigned best_mult_cost = 0, acost; 498 tree mult_elt = NULL_TREE, elt; 499 unsigned i, j; 500 enum tree_code op_code; 501 502 best_mult = double_int_zero; 503 for (i = 0; i < addr->n; i++) 504 { 505 if (!double_int_fits_in_shwi_p (addr->elts[i].coef)) 506 continue; 507 508 coef = double_int_to_shwi (addr->elts[i].coef); 509 if (coef == 1 510 || !multiplier_allowed_in_address_p (coef, TYPE_MODE (type), as)) 511 continue; 512 513 acost = multiply_by_cost (coef, address_mode, speed); 514 515 if (acost > best_mult_cost) 516 { 517 best_mult_cost = acost; 518 best_mult = addr->elts[i].coef; 519 } 520 } 521 522 if (!best_mult_cost) 523 return; 524 525 /* Collect elements multiplied by best_mult. */ 526 for (i = j = 0; i < addr->n; i++) 527 { 528 amult = addr->elts[i].coef; 529 amult_neg = double_int_ext_for_comb (double_int_neg (amult), addr); 530 531 if (double_int_equal_p (amult, best_mult)) 532 op_code = PLUS_EXPR; 533 else if (double_int_equal_p (amult_neg, best_mult)) 534 op_code = MINUS_EXPR; 535 else 536 { 537 addr->elts[j] = addr->elts[i]; 538 j++; 539 continue; 540 } 541 542 elt = fold_convert (sizetype, addr->elts[i].val); 543 if (mult_elt) 544 mult_elt = fold_build2 (op_code, sizetype, mult_elt, elt); 545 else if (op_code == PLUS_EXPR) 546 mult_elt = elt; 547 else 548 mult_elt = fold_build1 (NEGATE_EXPR, sizetype, elt); 549 } 550 addr->n = j; 551 552 parts->index = mult_elt; 553 parts->step = double_int_to_tree (sizetype, best_mult); 554} 555 556/* Splits address ADDR for a memory access of type TYPE into PARTS. 557 If BASE_HINT is non-NULL, it specifies an SSA name to be used 558 preferentially as base of the reference. 559 560 TODO -- be more clever about the distribution of the elements of ADDR 561 to PARTS. Some architectures do not support anything but single 562 register in address, possibly with a small integer offset; while 563 create_mem_ref will simplify the address to an acceptable shape 564 later, it would be more efficient to know that asking for complicated 565 addressing modes is useless. */ 566 567static void 568addr_to_parts (tree type, aff_tree *addr, tree base_hint, 569 struct mem_address *parts, bool speed) 570{ 571 tree part; 572 unsigned i; 573 574 parts->symbol = NULL_TREE; 575 parts->base = NULL_TREE; 576 parts->index = NULL_TREE; 577 parts->step = NULL_TREE; 578 579 if (!double_int_zero_p (addr->offset)) 580 parts->offset = double_int_to_tree (sizetype, addr->offset); 581 else 582 parts->offset = NULL_TREE; 583 584 /* Try to find a symbol. */ 585 move_fixed_address_to_symbol (parts, addr); 586 587 /* First move the most expensive feasible multiplication 588 to index. */ 589 most_expensive_mult_to_index (type, parts, addr, speed); 590 591 /* Try to find a base of the reference. Since at the moment 592 there is no reliable way how to distinguish between pointer and its 593 offset, this is just a guess. */ 594 if (!parts->symbol && base_hint) 595 move_hint_to_base (type, parts, base_hint, addr); 596 if (!parts->symbol && !parts->base) 597 move_pointer_to_base (parts, addr); 598 599 /* Then try to process the remaining elements. */ 600 for (i = 0; i < addr->n; i++) 601 { 602 part = fold_convert (sizetype, addr->elts[i].val); 603 if (!double_int_one_p (addr->elts[i].coef)) 604 part = fold_build2 (MULT_EXPR, sizetype, part, 605 double_int_to_tree (sizetype, addr->elts[i].coef)); 606 add_to_parts (parts, part); 607 } 608 if (addr->rest) 609 add_to_parts (parts, fold_convert (sizetype, addr->rest)); 610} 611 612/* Force the PARTS to register. */ 613 614static void 615gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts) 616{ 617 if (parts->base) 618 parts->base = force_gimple_operand_gsi (gsi, parts->base, 619 true, NULL_TREE, 620 true, GSI_SAME_STMT); 621 if (parts->index) 622 parts->index = force_gimple_operand_gsi (gsi, parts->index, 623 true, NULL_TREE, 624 true, GSI_SAME_STMT); 625} 626 627/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary 628 computations are emitted in front of GSI. TYPE is the mode 629 of created memory reference. */ 630 631tree 632create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr, 633 tree base_hint, bool speed) 634{ 635 tree mem_ref, tmp; 636 tree atype; 637 struct mem_address parts; 638 639 addr_to_parts (type, addr, base_hint, &parts, speed); 640 gimplify_mem_ref_parts (gsi, &parts); 641 mem_ref = create_mem_ref_raw (type, &parts); 642 if (mem_ref) 643 return mem_ref; 644 645 /* The expression is too complicated. Try making it simpler. */ 646 647 if (parts.step && !integer_onep (parts.step)) 648 { 649 /* Move the multiplication to index. */ 650 gcc_assert (parts.index); 651 parts.index = force_gimple_operand_gsi (gsi, 652 fold_build2 (MULT_EXPR, sizetype, 653 parts.index, parts.step), 654 true, NULL_TREE, true, GSI_SAME_STMT); 655 parts.step = NULL_TREE; 656 657 mem_ref = create_mem_ref_raw (type, &parts); 658 if (mem_ref) 659 return mem_ref; 660 } 661 662 if (parts.symbol) 663 { 664 tmp = build_addr (parts.symbol, current_function_decl); 665 gcc_assert (is_gimple_val (tmp)); 666 667 /* Add the symbol to base, eventually forcing it to register. */ 668 if (parts.base) 669 { 670 gcc_assert (useless_type_conversion_p 671 (sizetype, TREE_TYPE (parts.base))); 672 673 if (parts.index) 674 { 675 atype = TREE_TYPE (tmp); 676 parts.base = force_gimple_operand_gsi (gsi, 677 fold_build2 (POINTER_PLUS_EXPR, atype, 678 tmp, 679 fold_convert (sizetype, parts.base)), 680 true, NULL_TREE, true, GSI_SAME_STMT); 681 } 682 else 683 { 684 parts.index = parts.base; 685 parts.base = tmp; 686 } 687 } 688 else 689 parts.base = tmp; 690 parts.symbol = NULL_TREE; 691 692 mem_ref = create_mem_ref_raw (type, &parts); 693 if (mem_ref) 694 return mem_ref; 695 } 696 697 if (parts.index) 698 { 699 /* Add index to base. */ 700 if (parts.base) 701 { 702 atype = TREE_TYPE (parts.base); 703 parts.base = force_gimple_operand_gsi (gsi, 704 fold_build2 (POINTER_PLUS_EXPR, atype, 705 parts.base, 706 parts.index), 707 true, NULL_TREE, true, GSI_SAME_STMT); 708 } 709 else 710 parts.base = parts.index; 711 parts.index = NULL_TREE; 712 713 mem_ref = create_mem_ref_raw (type, &parts); 714 if (mem_ref) 715 return mem_ref; 716 } 717 718 if (parts.offset && !integer_zerop (parts.offset)) 719 { 720 /* Try adding offset to base. */ 721 if (parts.base) 722 { 723 atype = TREE_TYPE (parts.base); 724 parts.base = force_gimple_operand_gsi (gsi, 725 fold_build2 (POINTER_PLUS_EXPR, atype, 726 parts.base, 727 fold_convert (sizetype, parts.offset)), 728 true, NULL_TREE, true, GSI_SAME_STMT); 729 } 730 else 731 parts.base = parts.offset; 732 733 parts.offset = NULL_TREE; 734 735 mem_ref = create_mem_ref_raw (type, &parts); 736 if (mem_ref) 737 return mem_ref; 738 } 739 740 /* Verify that the address is in the simplest possible shape 741 (only a register). If we cannot create such a memory reference, 742 something is really wrong. */ 743 gcc_assert (parts.symbol == NULL_TREE); 744 gcc_assert (parts.index == NULL_TREE); 745 gcc_assert (!parts.step || integer_onep (parts.step)); 746 gcc_assert (!parts.offset || integer_zerop (parts.offset)); 747 gcc_unreachable (); 748} 749 750/* Copies components of the address from OP to ADDR. */ 751 752void 753get_address_description (tree op, struct mem_address *addr) 754{ 755 addr->symbol = TMR_SYMBOL (op); 756 addr->base = TMR_BASE (op); 757 addr->index = TMR_INDEX (op); 758 addr->step = TMR_STEP (op); 759 addr->offset = TMR_OFFSET (op); 760} 761 762/* Copies the additional information attached to target_mem_ref FROM to TO. */ 763 764void 765copy_mem_ref_info (tree to, tree from) 766{ 767 /* And the info about the original reference. */ 768 TMR_ORIGINAL (to) = TMR_ORIGINAL (from); 769 TREE_SIDE_EFFECTS (to) = TREE_SIDE_EFFECTS (from); 770 TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from); 771} 772 773/* Move constants in target_mem_ref REF to offset. Returns the new target 774 mem ref if anything changes, NULL_TREE otherwise. */ 775 776tree 777maybe_fold_tmr (tree ref) 778{ 779 struct mem_address addr; 780 bool changed = false; 781 tree ret, off; 782 783 get_address_description (ref, &addr); 784 785 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST) 786 { 787 if (addr.offset) 788 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype, 789 addr.offset, 790 fold_convert (sizetype, addr.base)); 791 else 792 addr.offset = addr.base; 793 794 addr.base = NULL_TREE; 795 changed = true; 796 } 797 798 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST) 799 { 800 off = addr.index; 801 if (addr.step) 802 { 803 off = fold_binary_to_constant (MULT_EXPR, sizetype, 804 off, addr.step); 805 addr.step = NULL_TREE; 806 } 807 808 if (addr.offset) 809 { 810 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype, 811 addr.offset, off); 812 } 813 else 814 addr.offset = off; 815 816 addr.index = NULL_TREE; 817 changed = true; 818 } 819 820 if (!changed) 821 return NULL_TREE; 822 823 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr); 824 if (!ret) 825 return NULL_TREE; 826 827 copy_mem_ref_info (ret, ref); 828 return ret; 829} 830 831/* Dump PARTS to FILE. */ 832 833extern void dump_mem_address (FILE *, struct mem_address *); 834void 835dump_mem_address (FILE *file, struct mem_address *parts) 836{ 837 if (parts->symbol) 838 { 839 fprintf (file, "symbol: "); 840 print_generic_expr (file, parts->symbol, TDF_SLIM); 841 fprintf (file, "\n"); 842 } 843 if (parts->base) 844 { 845 fprintf (file, "base: "); 846 print_generic_expr (file, parts->base, TDF_SLIM); 847 fprintf (file, "\n"); 848 } 849 if (parts->index) 850 { 851 fprintf (file, "index: "); 852 print_generic_expr (file, parts->index, TDF_SLIM); 853 fprintf (file, "\n"); 854 } 855 if (parts->step) 856 { 857 fprintf (file, "step: "); 858 print_generic_expr (file, parts->step, TDF_SLIM); 859 fprintf (file, "\n"); 860 } 861 if (parts->offset) 862 { 863 fprintf (file, "offset: "); 864 print_generic_expr (file, parts->offset, TDF_SLIM); 865 fprintf (file, "\n"); 866 } 867} 868 869#include "gt-tree-ssa-address.h" 870