00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "tree.h"
00029 #include "rtl.h"
00030 #include "tm_p.h"
00031 #include "hard-reg-set.h"
00032 #include "basic-block.h"
00033 #include "output.h"
00034 #include "diagnostic.h"
00035 #include "tree-flow.h"
00036 #include "tree-dump.h"
00037 #include "tree-pass.h"
00038 #include "timevar.h"
00039 #include "flags.h"
00040 #include "tree-inline.h"
00041 #include "insn-config.h"
00042 #include "recog.h"
00043 #include "expr.h"
00044 #include "ggc.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 struct mem_addr_template GTY (())
00074 {
00075 rtx ref;
00076 rtx * GTY ((skip)) step_p;
00077
00078 rtx * GTY ((skip)) off_p;
00079
00080 };
00081
00082
00083
00084
00085 static GTY (()) struct mem_addr_template templates[32];
00086
00087 #define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
00088 (((SYMBOL != 0) << 4) \
00089 | ((BASE != 0) << 3) \
00090 | ((INDEX != 0) << 2) \
00091 | ((STEP != 0) << 1) \
00092 | (OFFSET != 0))
00093
00094
00095
00096
00097
00098 static void
00099 gen_addr_rtx (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
00100 rtx *addr, rtx **step_p, rtx **offset_p)
00101 {
00102 rtx act_elem;
00103
00104 *addr = NULL_RTX;
00105 if (step_p)
00106 *step_p = NULL;
00107 if (offset_p)
00108 *offset_p = NULL;
00109
00110 if (index)
00111 {
00112 act_elem = index;
00113 if (step)
00114 {
00115 act_elem = gen_rtx_MULT (Pmode, act_elem, step);
00116
00117 if (step_p)
00118 *step_p = &XEXP (act_elem, 1);
00119 }
00120
00121 *addr = act_elem;
00122 }
00123
00124 if (base)
00125 {
00126 if (*addr)
00127 *addr = gen_rtx_PLUS (Pmode, *addr, base);
00128 else
00129 *addr = base;
00130 }
00131
00132 if (symbol)
00133 {
00134 act_elem = symbol;
00135 if (offset)
00136 {
00137 act_elem = gen_rtx_CONST (Pmode,
00138 gen_rtx_PLUS (Pmode, act_elem, offset));
00139 if (offset_p)
00140 *offset_p = &XEXP (XEXP (act_elem, 0), 1);
00141 }
00142
00143 if (*addr)
00144 *addr = gen_rtx_PLUS (Pmode, *addr, act_elem);
00145 else
00146 *addr = act_elem;
00147 }
00148 else if (offset)
00149 {
00150 if (*addr)
00151 {
00152 *addr = gen_rtx_PLUS (Pmode, *addr, offset);
00153 if (offset_p)
00154 *offset_p = &XEXP (*addr, 1);
00155 }
00156 else
00157 {
00158 *addr = offset;
00159 if (offset_p)
00160 *offset_p = addr;
00161 }
00162 }
00163
00164 if (!*addr)
00165 *addr = const0_rtx;
00166 }
00167
00168
00169
00170
00171
00172
00173 rtx
00174 addr_for_mem_ref (struct mem_address *addr, bool really_expand)
00175 {
00176 rtx address, sym, bse, idx, st, off;
00177 static bool templates_initialized = false;
00178 struct mem_addr_template *templ;
00179
00180 if (addr->step && !integer_onep (addr->step))
00181 st = immed_double_const (TREE_INT_CST_LOW (addr->step),
00182 TREE_INT_CST_HIGH (addr->step), Pmode);
00183 else
00184 st = NULL_RTX;
00185
00186 if (addr->offset && !integer_zerop (addr->offset))
00187 off = immed_double_const (TREE_INT_CST_LOW (addr->offset),
00188 TREE_INT_CST_HIGH (addr->offset), Pmode);
00189 else
00190 off = NULL_RTX;
00191
00192 if (!really_expand)
00193 {
00194
00195 if (!templates_initialized)
00196 {
00197 unsigned i;
00198
00199 templates_initialized = true;
00200 sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup ("test_symbol"));
00201 bse = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
00202 idx = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
00203
00204 for (i = 0; i < 32; i++)
00205 gen_addr_rtx ((i & 16 ? sym : NULL_RTX),
00206 (i & 8 ? bse : NULL_RTX),
00207 (i & 4 ? idx : NULL_RTX),
00208 (i & 2 ? const0_rtx : NULL_RTX),
00209 (i & 1 ? const0_rtx : NULL_RTX),
00210 &templates[i].ref,
00211 &templates[i].step_p,
00212 &templates[i].off_p);
00213 }
00214
00215 templ = templates + TEMPL_IDX (addr->symbol, addr->base, addr->index,
00216 st, off);
00217 if (st)
00218 *templ->step_p = st;
00219 if (off)
00220 *templ->off_p = off;
00221
00222 return templ->ref;
00223 }
00224
00225
00226 sym = (addr->symbol
00227 ? expand_expr (build_addr (addr->symbol, current_function_decl),
00228 NULL_RTX, Pmode, EXPAND_NORMAL)
00229 : NULL_RTX);
00230 bse = (addr->base
00231 ? expand_expr (addr->base, NULL_RTX, Pmode, EXPAND_NORMAL)
00232 : NULL_RTX);
00233 idx = (addr->index
00234 ? expand_expr (addr->index, NULL_RTX, Pmode, EXPAND_NORMAL)
00235 : NULL_RTX);
00236
00237 gen_addr_rtx (sym, bse, idx, st, off, &address, NULL, NULL);
00238 return address;
00239 }
00240
00241
00242
00243 tree
00244 tree_mem_ref_addr (tree type, tree mem_ref)
00245 {
00246 tree addr;
00247 tree act_elem;
00248 tree step = TMR_STEP (mem_ref), offset = TMR_OFFSET (mem_ref);
00249 tree sym = TMR_SYMBOL (mem_ref), base = TMR_BASE (mem_ref);
00250 tree addr_base = NULL_TREE, addr_off = NULL_TREE;
00251
00252 if (sym)
00253 addr_base = fold_convert (type, build_addr (sym, current_function_decl));
00254 else if (base && POINTER_TYPE_P (TREE_TYPE (base)))
00255 {
00256 addr_base = fold_convert (type, base);
00257 base = NULL_TREE;
00258 }
00259
00260 act_elem = TMR_INDEX (mem_ref);
00261 if (act_elem)
00262 {
00263 if (step)
00264 act_elem = fold_build2 (MULT_EXPR, sizetype, act_elem, step);
00265 addr_off = act_elem;
00266 }
00267
00268 act_elem = base;
00269 if (act_elem)
00270 {
00271 if (addr_off)
00272 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, act_elem);
00273 else
00274 addr_off = act_elem;
00275 }
00276
00277 if (!zero_p (offset))
00278 {
00279 if (addr_off)
00280 addr_off = fold_build2 (PLUS_EXPR, sizetype, addr_off, offset);
00281 else
00282 addr_off = offset;
00283 }
00284
00285 if (addr_off)
00286 {
00287 addr = fold_convert (type, addr_off);
00288 if (addr_base)
00289 addr = fold_build2 (PLUS_EXPR, type, addr_base, addr);
00290 }
00291 else if (addr_base)
00292 addr = addr_base;
00293 else
00294 addr = build_int_cst (type, 0);
00295
00296 return addr;
00297 }
00298
00299
00300
00301
00302 static bool
00303 valid_mem_ref_p (enum machine_mode mode, struct mem_address *addr)
00304 {
00305 rtx address;
00306
00307 address = addr_for_mem_ref (addr, false);
00308 if (!address)
00309 return false;
00310
00311 return memory_address_p (mode, address);
00312 }
00313
00314
00315
00316
00317
00318 static tree
00319 create_mem_ref_raw (tree type, struct mem_address *addr)
00320 {
00321 if (!valid_mem_ref_p (TYPE_MODE (type), addr))
00322 return NULL_TREE;
00323
00324 if (addr->step && integer_onep (addr->step))
00325 addr->step = NULL_TREE;
00326
00327 if (addr->offset && zero_p (addr->offset))
00328 addr->offset = NULL_TREE;
00329
00330 return build7 (TARGET_MEM_REF, type,
00331 addr->symbol, addr->base, addr->index,
00332 addr->step, addr->offset, NULL, NULL);
00333 }
00334
00335
00336
00337 static bool
00338 fixed_address_object_p (tree obj)
00339 {
00340 return (TREE_CODE (obj) == VAR_DECL
00341 && (TREE_STATIC (obj)
00342 || DECL_EXTERNAL (obj)));
00343 }
00344
00345
00346
00347 static void
00348 aff_combination_remove_elt (struct affine_tree_combination *comb, unsigned m)
00349 {
00350 comb->n--;
00351 if (m <= comb->n)
00352 {
00353 comb->coefs[m] = comb->coefs[comb->n];
00354 comb->elts[m] = comb->elts[comb->n];
00355 }
00356 if (comb->rest)
00357 {
00358 comb->coefs[comb->n] = 1;
00359 comb->elts[comb->n] = comb->rest;
00360 comb->rest = NULL_TREE;
00361 comb->n++;
00362 }
00363 }
00364
00365
00366
00367
00368 static void
00369 move_fixed_address_to_symbol (struct mem_address *parts,
00370 struct affine_tree_combination *addr)
00371 {
00372 unsigned i;
00373 tree val = NULL_TREE;
00374
00375 for (i = 0; i < addr->n; i++)
00376 {
00377 if (addr->coefs[i] != 1)
00378 continue;
00379
00380 val = addr->elts[i];
00381 if (TREE_CODE (val) == ADDR_EXPR
00382 && fixed_address_object_p (TREE_OPERAND (val, 0)))
00383 break;
00384 }
00385
00386 if (i == addr->n)
00387 return;
00388
00389 parts->symbol = TREE_OPERAND (val, 0);
00390 aff_combination_remove_elt (addr, i);
00391 }
00392
00393
00394
00395
00396 static void
00397 move_pointer_to_base (struct mem_address *parts,
00398 struct affine_tree_combination *addr)
00399 {
00400 unsigned i;
00401 tree val = NULL_TREE;
00402
00403 for (i = 0; i < addr->n; i++)
00404 {
00405 if (addr->coefs[i] != 1)
00406 continue;
00407
00408 val = addr->elts[i];
00409 if (POINTER_TYPE_P (TREE_TYPE (val)))
00410 break;
00411 }
00412
00413 if (i == addr->n)
00414 return;
00415
00416 parts->base = val;
00417 aff_combination_remove_elt (addr, i);
00418 }
00419
00420
00421
00422 static void
00423 add_to_parts (struct mem_address *parts, tree elt)
00424 {
00425 tree type;
00426
00427 if (!parts->index)
00428 {
00429 parts->index = elt;
00430 return;
00431 }
00432
00433 if (!parts->base)
00434 {
00435 parts->base = elt;
00436 return;
00437 }
00438
00439
00440 type = TREE_TYPE (parts->base);
00441 parts->base = fold_build2 (PLUS_EXPR, type,
00442 parts->base,
00443 fold_convert (type, elt));
00444 }
00445
00446
00447
00448
00449
00450 static void
00451 most_expensive_mult_to_index (struct mem_address *parts,
00452 struct affine_tree_combination *addr)
00453 {
00454 unsigned HOST_WIDE_INT best_mult = 0;
00455 unsigned best_mult_cost = 0, acost;
00456 tree mult_elt = NULL_TREE, elt;
00457 unsigned i, j;
00458
00459 for (i = 0; i < addr->n; i++)
00460 {
00461 if (addr->coefs[i] == 1
00462 || !multiplier_allowed_in_address_p (addr->coefs[i]))
00463 continue;
00464
00465 acost = multiply_by_cost (addr->coefs[i], Pmode);
00466
00467 if (acost > best_mult_cost)
00468 {
00469 best_mult_cost = acost;
00470 best_mult = addr->coefs[i];
00471 }
00472 }
00473
00474 if (!best_mult)
00475 return;
00476
00477 for (i = j = 0; i < addr->n; i++)
00478 {
00479 if (addr->coefs[i] != best_mult)
00480 {
00481 addr->coefs[j] = addr->coefs[i];
00482 addr->elts[j] = addr->elts[i];
00483 j++;
00484 continue;
00485 }
00486
00487 elt = fold_convert (sizetype, addr->elts[i]);
00488 if (!mult_elt)
00489 mult_elt = elt;
00490 else
00491 mult_elt = fold_build2 (PLUS_EXPR, sizetype, mult_elt, elt);
00492 }
00493 addr->n = j;
00494
00495 parts->index = mult_elt;
00496 parts->step = build_int_cst_type (sizetype, best_mult);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 static void
00509 addr_to_parts (struct affine_tree_combination *addr, struct mem_address *parts)
00510 {
00511 unsigned i;
00512 tree part;
00513
00514 parts->symbol = NULL_TREE;
00515 parts->base = NULL_TREE;
00516 parts->index = NULL_TREE;
00517 parts->step = NULL_TREE;
00518
00519 if (addr->offset)
00520 parts->offset = build_int_cst_type (sizetype, addr->offset);
00521 else
00522 parts->offset = NULL_TREE;
00523
00524
00525 move_fixed_address_to_symbol (parts, addr);
00526
00527
00528
00529 most_expensive_mult_to_index (parts, addr);
00530
00531
00532
00533
00534 if (!parts->symbol)
00535 move_pointer_to_base (parts, addr);
00536
00537
00538 for (i = 0; i < addr->n; i++)
00539 {
00540 part = fold_convert (sizetype, addr->elts[i]);
00541 if (addr->coefs[i] != 1)
00542 part = fold_build2 (MULT_EXPR, sizetype, part,
00543 build_int_cst_type (sizetype, addr->coefs[i]));
00544 add_to_parts (parts, part);
00545 }
00546 if (addr->rest)
00547 add_to_parts (parts, fold_convert (sizetype, addr->rest));
00548 }
00549
00550
00551
00552 static void
00553 gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
00554 {
00555 if (parts->base)
00556 parts->base = force_gimple_operand_bsi (bsi, parts->base,
00557 true, NULL_TREE);
00558 if (parts->index)
00559 parts->index = force_gimple_operand_bsi (bsi, parts->index,
00560 true, NULL_TREE);
00561 }
00562
00563
00564
00565
00566
00567 tree
00568 create_mem_ref (block_stmt_iterator *bsi, tree type,
00569 struct affine_tree_combination *addr)
00570 {
00571 tree mem_ref, tmp;
00572 tree addr_type = build_pointer_type (type), atype;
00573 struct mem_address parts;
00574
00575 addr_to_parts (addr, &parts);
00576 gimplify_mem_ref_parts (bsi, &parts);
00577 mem_ref = create_mem_ref_raw (type, &parts);
00578 if (mem_ref)
00579 return mem_ref;
00580
00581
00582
00583 if (parts.step && !integer_onep (parts.step))
00584 {
00585
00586 gcc_assert (parts.index);
00587 parts.index = force_gimple_operand_bsi (bsi,
00588 fold_build2 (MULT_EXPR, sizetype,
00589 parts.index, parts.step),
00590 true, NULL_TREE);
00591 parts.step = NULL_TREE;
00592
00593 mem_ref = create_mem_ref_raw (type, &parts);
00594 if (mem_ref)
00595 return mem_ref;
00596 }
00597
00598 if (parts.symbol)
00599 {
00600 tmp = fold_convert (addr_type,
00601 build_addr (parts.symbol, current_function_decl));
00602
00603
00604 if (parts.base)
00605 {
00606 if (parts.index)
00607 parts.base = force_gimple_operand_bsi (bsi,
00608 fold_build2 (PLUS_EXPR, addr_type,
00609 fold_convert (addr_type, parts.base),
00610 tmp),
00611 true, NULL_TREE);
00612 else
00613 {
00614 parts.index = parts.base;
00615 parts.base = tmp;
00616 }
00617 }
00618 else
00619 parts.base = tmp;
00620 parts.symbol = NULL_TREE;
00621
00622 mem_ref = create_mem_ref_raw (type, &parts);
00623 if (mem_ref)
00624 return mem_ref;
00625 }
00626
00627 if (parts.index)
00628 {
00629
00630 if (parts.base)
00631 {
00632 atype = TREE_TYPE (parts.base);
00633 parts.base = force_gimple_operand_bsi (bsi,
00634 fold_build2 (PLUS_EXPR, atype,
00635 parts.base,
00636 fold_convert (atype, parts.index)),
00637 true, NULL_TREE);
00638 }
00639 else
00640 parts.base = parts.index;
00641 parts.index = NULL_TREE;
00642
00643 mem_ref = create_mem_ref_raw (type, &parts);
00644 if (mem_ref)
00645 return mem_ref;
00646 }
00647
00648 if (parts.offset && !integer_zerop (parts.offset))
00649 {
00650
00651 if (parts.base)
00652 {
00653 atype = TREE_TYPE (parts.base);
00654 parts.base = force_gimple_operand_bsi (bsi,
00655 fold_build2 (PLUS_EXPR, atype,
00656 parts.base,
00657 fold_convert (atype, parts.offset)),
00658 true, NULL_TREE);
00659 }
00660 else
00661 parts.base = parts.offset;
00662
00663 parts.offset = NULL_TREE;
00664
00665 mem_ref = create_mem_ref_raw (type, &parts);
00666 if (mem_ref)
00667 return mem_ref;
00668 }
00669
00670
00671
00672
00673 gcc_assert (parts.symbol == NULL_TREE);
00674 gcc_assert (parts.index == NULL_TREE);
00675 gcc_assert (!parts.step || integer_onep (parts.step));
00676 gcc_assert (!parts.offset || integer_zerop (parts.offset));
00677 gcc_unreachable ();
00678 }
00679
00680
00681
00682 void
00683 get_address_description (tree op, struct mem_address *addr)
00684 {
00685 addr->symbol = TMR_SYMBOL (op);
00686 addr->base = TMR_BASE (op);
00687 addr->index = TMR_INDEX (op);
00688 addr->step = TMR_STEP (op);
00689 addr->offset = TMR_OFFSET (op);
00690 }
00691
00692
00693
00694 void
00695 copy_mem_ref_info (tree to, tree from)
00696 {
00697
00698 TMR_TAG (to) = TMR_TAG (from);
00699
00700
00701 TMR_ORIGINAL (to) = TMR_ORIGINAL (from);
00702 }
00703
00704
00705
00706
00707 tree
00708 maybe_fold_tmr (tree ref)
00709 {
00710 struct mem_address addr;
00711 bool changed = false;
00712 tree ret, off;
00713
00714 get_address_description (ref, &addr);
00715
00716 if (addr.base && TREE_CODE (addr.base) == INTEGER_CST)
00717 {
00718 if (addr.offset)
00719 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
00720 addr.offset,
00721 fold_convert (sizetype, addr.base));
00722 else
00723 addr.offset = addr.base;
00724
00725 addr.base = NULL_TREE;
00726 changed = true;
00727 }
00728
00729 if (addr.index && TREE_CODE (addr.index) == INTEGER_CST)
00730 {
00731 off = addr.index;
00732 if (addr.step)
00733 {
00734 off = fold_binary_to_constant (MULT_EXPR, sizetype,
00735 off, addr.step);
00736 addr.step = NULL_TREE;
00737 }
00738
00739 if (addr.offset)
00740 {
00741 addr.offset = fold_binary_to_constant (PLUS_EXPR, sizetype,
00742 addr.offset, off);
00743 }
00744 else
00745 addr.offset = off;
00746
00747 addr.index = NULL_TREE;
00748 changed = true;
00749 }
00750
00751 if (!changed)
00752 return NULL_TREE;
00753
00754 ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
00755 if (!ret)
00756 return NULL_TREE;
00757
00758 copy_mem_ref_info (ret, ref);
00759 return ret;
00760 }
00761
00762
00763
00764 extern void dump_mem_address (FILE *, struct mem_address *);
00765 void
00766 dump_mem_address (FILE *file, struct mem_address *parts)
00767 {
00768 if (parts->symbol)
00769 {
00770 fprintf (file, "symbol: ");
00771 print_generic_expr (file, parts->symbol, TDF_SLIM);
00772 fprintf (file, "\n");
00773 }
00774 if (parts->base)
00775 {
00776 fprintf (file, "base: ");
00777 print_generic_expr (file, parts->base, TDF_SLIM);
00778 fprintf (file, "\n");
00779 }
00780 if (parts->index)
00781 {
00782 fprintf (file, "index: ");
00783 print_generic_expr (file, parts->index, TDF_SLIM);
00784 fprintf (file, "\n");
00785 }
00786 if (parts->step)
00787 {
00788 fprintf (file, "step: ");
00789 print_generic_expr (file, parts->step, TDF_SLIM);
00790 fprintf (file, "\n");
00791 }
00792 if (parts->offset)
00793 {
00794 fprintf (file, "offset: ");
00795 print_generic_expr (file, parts->offset, TDF_SLIM);
00796 fprintf (file, "\n");
00797 }
00798 }
00799
00800 #include "gt-tree-ssa-address.h"