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