00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #include "config.h"
00066 #include "system.h"
00067 #include "coretypes.h"
00068 #include "tm.h"
00069 #include "tree.h"
00070 #include "rtl.h"
00071 #include "tm_p.h"
00072 #include "hard-reg-set.h"
00073 #include "basic-block.h"
00074 #include "output.h"
00075 #include "diagnostic.h"
00076 #include "tree-flow.h"
00077 #include "tree-dump.h"
00078 #include "timevar.h"
00079 #include "cfgloop.h"
00080 #include "varray.h"
00081 #include "expr.h"
00082 #include "tree-pass.h"
00083 #include "ggc.h"
00084 #include "insn-config.h"
00085 #include "recog.h"
00086 #include "hashtab.h"
00087 #include "tree-chrec.h"
00088 #include "tree-scalar-evolution.h"
00089 #include "cfgloop.h"
00090 #include "params.h"
00091 #include "langhooks.h"
00092
00093
00094 #define INFTY 10000000
00095
00096
00097
00098 #define AVG_LOOP_NITER(LOOP) 5
00099
00100
00101
00102 struct iv
00103 {
00104 tree base;
00105 tree base_object;
00106 tree step;
00107 tree ssa_name;
00108 bool biv_p;
00109 bool have_use_for;
00110 unsigned use_id;
00111 };
00112
00113
00114 struct version_info
00115 {
00116 tree name;
00117 struct iv *iv;
00118 bool has_nonlin_use;
00119
00120 unsigned inv_id;
00121 bool preserve_biv;
00122 };
00123
00124
00125 struct loop_data
00126 {
00127 unsigned regs_used;
00128 };
00129
00130
00131 enum use_type
00132 {
00133 USE_NONLINEAR_EXPR,
00134 USE_OUTER,
00135 USE_ADDRESS,
00136 USE_COMPARE
00137 };
00138
00139
00140 struct cost_pair
00141 {
00142 struct iv_cand *cand;
00143 unsigned cost;
00144 bitmap depends_on;
00145
00146 };
00147
00148
00149 struct iv_use
00150 {
00151 unsigned id;
00152 enum use_type type;
00153 struct iv *iv;
00154 tree stmt;
00155 tree *op_p;
00156 bitmap related_cands;
00157
00158
00159 unsigned n_map_members;
00160 struct cost_pair *cost_map;
00161
00162
00163 struct iv_cand *selected;
00164
00165 };
00166
00167
00168 enum iv_position
00169 {
00170 IP_NORMAL,
00171 IP_END,
00172 IP_ORIGINAL
00173 };
00174
00175
00176 struct iv_cand
00177 {
00178 unsigned id;
00179 bool important;
00180
00181 enum iv_position pos;
00182 tree incremented_at;
00183
00184 tree var_before;
00185 tree var_after;
00186 struct iv *iv;
00187
00188
00189
00190 unsigned cost;
00191 };
00192
00193
00194
00195 struct ivopts_data
00196 {
00197
00198 struct loop *current_loop;
00199
00200
00201 htab_t niters;
00202
00203
00204 unsigned version_info_size;
00205
00206
00207 struct version_info *version_info;
00208
00209
00210 bitmap relevant;
00211
00212
00213 unsigned max_inv_id;
00214
00215
00216 varray_type iv_uses;
00217
00218
00219 varray_type iv_candidates;
00220
00221
00222 bitmap important_candidates;
00223
00224
00225
00226 bool consider_all_candidates;
00227 };
00228
00229
00230
00231 struct iv_ca
00232 {
00233
00234 unsigned upto;
00235
00236
00237 unsigned bad_uses;
00238
00239
00240 struct cost_pair **cand_for_use;
00241
00242
00243 unsigned *n_cand_uses;
00244
00245
00246 bitmap cands;
00247
00248
00249 unsigned n_cands;
00250
00251
00252 unsigned n_regs;
00253
00254
00255 unsigned cand_use_cost;
00256
00257
00258 unsigned cand_cost;
00259
00260
00261 unsigned *n_invariant_uses;
00262
00263
00264 unsigned cost;
00265 };
00266
00267
00268
00269 struct iv_ca_delta
00270 {
00271
00272 struct iv_use *use;
00273
00274
00275 struct cost_pair *old_cp;
00276
00277
00278 struct cost_pair *new_cp;
00279
00280
00281 struct iv_ca_delta *next_change;
00282 };
00283
00284
00285
00286 #define CONSIDER_ALL_CANDIDATES_BOUND \
00287 ((unsigned) PARAM_VALUE (PARAM_IV_CONSIDER_ALL_CANDIDATES_BOUND))
00288
00289
00290
00291
00292 #define MAX_CONSIDERED_USES \
00293 ((unsigned) PARAM_VALUE (PARAM_IV_MAX_CONSIDERED_USES))
00294
00295
00296
00297
00298 #define ALWAYS_PRUNE_CAND_SET_BOUND \
00299 ((unsigned) PARAM_VALUE (PARAM_IV_ALWAYS_PRUNE_CAND_SET_BOUND))
00300
00301
00302
00303
00304 static varray_type decl_rtl_to_reset;
00305
00306
00307
00308 static inline unsigned
00309 n_iv_uses (struct ivopts_data *data)
00310 {
00311 return VARRAY_ACTIVE_SIZE (data->iv_uses);
00312 }
00313
00314
00315
00316 static inline struct iv_use *
00317 iv_use (struct ivopts_data *data, unsigned i)
00318 {
00319 return VARRAY_GENERIC_PTR_NOGC (data->iv_uses, i);
00320 }
00321
00322
00323
00324 static inline unsigned
00325 n_iv_cands (struct ivopts_data *data)
00326 {
00327 return VARRAY_ACTIVE_SIZE (data->iv_candidates);
00328 }
00329
00330
00331
00332 static inline struct iv_cand *
00333 iv_cand (struct ivopts_data *data, unsigned i)
00334 {
00335 return VARRAY_GENERIC_PTR_NOGC (data->iv_candidates, i);
00336 }
00337
00338
00339
00340 static inline struct loop_data *
00341 loop_data (struct loop *loop)
00342 {
00343 return loop->aux;
00344 }
00345
00346
00347
00348 static edge
00349 single_dom_exit (struct loop *loop)
00350 {
00351 edge exit = loop->single_exit;
00352
00353 if (!exit)
00354 return NULL;
00355
00356 if (!just_once_each_iteration_p (loop, exit->src))
00357 return NULL;
00358
00359 return exit;
00360 }
00361
00362
00363
00364 extern void dump_iv (FILE *, struct iv *);
00365 void
00366 dump_iv (FILE *file, struct iv *iv)
00367 {
00368 if (iv->ssa_name)
00369 {
00370 fprintf (file, "ssa name ");
00371 print_generic_expr (file, iv->ssa_name, TDF_SLIM);
00372 fprintf (file, "\n");
00373 }
00374
00375 fprintf (file, " type ");
00376 print_generic_expr (file, TREE_TYPE (iv->base), TDF_SLIM);
00377 fprintf (file, "\n");
00378
00379 if (iv->step)
00380 {
00381 fprintf (file, " base ");
00382 print_generic_expr (file, iv->base, TDF_SLIM);
00383 fprintf (file, "\n");
00384
00385 fprintf (file, " step ");
00386 print_generic_expr (file, iv->step, TDF_SLIM);
00387 fprintf (file, "\n");
00388 }
00389 else
00390 {
00391 fprintf (file, " invariant ");
00392 print_generic_expr (file, iv->base, TDF_SLIM);
00393 fprintf (file, "\n");
00394 }
00395
00396 if (iv->base_object)
00397 {
00398 fprintf (file, " base object ");
00399 print_generic_expr (file, iv->base_object, TDF_SLIM);
00400 fprintf (file, "\n");
00401 }
00402
00403 if (iv->biv_p)
00404 fprintf (file, " is a biv\n");
00405 }
00406
00407
00408
00409 extern void dump_use (FILE *, struct iv_use *);
00410 void
00411 dump_use (FILE *file, struct iv_use *use)
00412 {
00413 fprintf (file, "use %d\n", use->id);
00414
00415 switch (use->type)
00416 {
00417 case USE_NONLINEAR_EXPR:
00418 fprintf (file, " generic\n");
00419 break;
00420
00421 case USE_OUTER:
00422 fprintf (file, " outside\n");
00423 break;
00424
00425 case USE_ADDRESS:
00426 fprintf (file, " address\n");
00427 break;
00428
00429 case USE_COMPARE:
00430 fprintf (file, " compare\n");
00431 break;
00432
00433 default:
00434 gcc_unreachable ();
00435 }
00436
00437 fprintf (file, " in statement ");
00438 print_generic_expr (file, use->stmt, TDF_SLIM);
00439 fprintf (file, "\n");
00440
00441 fprintf (file, " at position ");
00442 if (use->op_p)
00443 print_generic_expr (file, *use->op_p, TDF_SLIM);
00444 fprintf (file, "\n");
00445
00446 dump_iv (file, use->iv);
00447
00448 if (use->related_cands)
00449 {
00450 fprintf (file, " related candidates ");
00451 dump_bitmap (file, use->related_cands);
00452 }
00453 }
00454
00455
00456
00457 extern void dump_uses (FILE *, struct ivopts_data *);
00458 void
00459 dump_uses (FILE *file, struct ivopts_data *data)
00460 {
00461 unsigned i;
00462 struct iv_use *use;
00463
00464 for (i = 0; i < n_iv_uses (data); i++)
00465 {
00466 use = iv_use (data, i);
00467
00468 dump_use (file, use);
00469 fprintf (file, "\n");
00470 }
00471 }
00472
00473
00474
00475 extern void dump_cand (FILE *, struct iv_cand *);
00476 void
00477 dump_cand (FILE *file, struct iv_cand *cand)
00478 {
00479 struct iv *iv = cand->iv;
00480
00481 fprintf (file, "candidate %d%s\n",
00482 cand->id, cand->important ? " (important)" : "");
00483
00484 if (!iv)
00485 {
00486 fprintf (file, " final value replacement\n");
00487 return;
00488 }
00489
00490 switch (cand->pos)
00491 {
00492 case IP_NORMAL:
00493 fprintf (file, " incremented before exit test\n");
00494 break;
00495
00496 case IP_END:
00497 fprintf (file, " incremented at end\n");
00498 break;
00499
00500 case IP_ORIGINAL:
00501 fprintf (file, " original biv\n");
00502 break;
00503 }
00504
00505 dump_iv (file, iv);
00506 }
00507
00508
00509
00510 static inline struct version_info *
00511 ver_info (struct ivopts_data *data, unsigned ver)
00512 {
00513 return data->version_info + ver;
00514 }
00515
00516
00517
00518 static inline struct version_info *
00519 name_info (struct ivopts_data *data, tree name)
00520 {
00521 return ver_info (data, SSA_NAME_VERSION (name));
00522 }
00523
00524
00525
00526
00527 static bool
00528 divide (unsigned bits, unsigned HOST_WIDE_INT a, unsigned HOST_WIDE_INT b,
00529 HOST_WIDE_INT *x)
00530 {
00531 unsigned HOST_WIDE_INT mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
00532 unsigned HOST_WIDE_INT inv, ex, val;
00533 unsigned i;
00534
00535 a &= mask;
00536 b &= mask;
00537
00538
00539 while (!(a & 1) && !(b & 1))
00540 {
00541 a >>= 1;
00542 b >>= 1;
00543 bits--;
00544 mask >>= 1;
00545 }
00546
00547 if (!(b & 1))
00548 {
00549
00550 return false;
00551 }
00552
00553
00554
00555 inv = 1;
00556 ex = b;
00557 for (i = 0; i < bits - 1; i++)
00558 {
00559 inv = (inv * ex) & mask;
00560 ex = (ex * ex) & mask;
00561 }
00562
00563 val = (a * inv) & mask;
00564
00565 gcc_assert (((val * b) & mask) == a);
00566
00567 if ((val >> (bits - 1)) & 1)
00568 val |= ~mask;
00569
00570 *x = val;
00571
00572 return true;
00573 }
00574
00575
00576
00577
00578 static bool
00579 stmt_after_ip_normal_pos (struct loop *loop, tree stmt)
00580 {
00581 basic_block bb = ip_normal_pos (loop), sbb = bb_for_stmt (stmt);
00582
00583 gcc_assert (bb);
00584
00585 if (sbb == loop->latch)
00586 return true;
00587
00588 if (sbb != bb)
00589 return false;
00590
00591 return stmt == last_stmt (bb);
00592 }
00593
00594
00595
00596
00597 static bool
00598 stmt_after_ip_original_pos (struct iv_cand *cand, tree stmt)
00599 {
00600 basic_block cand_bb = bb_for_stmt (cand->incremented_at);
00601 basic_block stmt_bb = bb_for_stmt (stmt);
00602 block_stmt_iterator bsi;
00603
00604 if (!dominated_by_p (CDI_DOMINATORS, stmt_bb, cand_bb))
00605 return false;
00606
00607 if (stmt_bb != cand_bb)
00608 return true;
00609
00610
00611
00612 for (bsi = bsi_last (stmt_bb); ; bsi_prev (&bsi))
00613 {
00614 if (bsi_stmt (bsi) == cand->incremented_at)
00615 return false;
00616 if (bsi_stmt (bsi) == stmt)
00617 return true;
00618 }
00619 }
00620
00621
00622
00623
00624 static bool
00625 stmt_after_increment (struct loop *loop, struct iv_cand *cand, tree stmt)
00626 {
00627 switch (cand->pos)
00628 {
00629 case IP_END:
00630 return false;
00631
00632 case IP_NORMAL:
00633 return stmt_after_ip_normal_pos (loop, stmt);
00634
00635 case IP_ORIGINAL:
00636 return stmt_after_ip_original_pos (cand, stmt);
00637
00638 default:
00639 gcc_unreachable ();
00640 }
00641 }
00642
00643
00644
00645
00646 struct nfe_cache_elt
00647 {
00648
00649 edge exit;
00650
00651
00652 bool valid_p;
00653
00654
00655 struct tree_niter_desc niter;
00656 };
00657
00658
00659
00660 static hashval_t
00661 nfe_hash (const void *e)
00662 {
00663 const struct nfe_cache_elt *elt = e;
00664
00665 return htab_hash_pointer (elt->exit);
00666 }
00667
00668
00669
00670 static int
00671 nfe_eq (const void *e1, const void *e2)
00672 {
00673 const struct nfe_cache_elt *elt1 = e1;
00674
00675 return elt1->exit == e2;
00676 }
00677
00678
00679
00680
00681 static struct tree_niter_desc *
00682 niter_for_exit (struct ivopts_data *data, edge exit)
00683 {
00684 struct nfe_cache_elt *nfe_desc;
00685 PTR *slot;
00686
00687 slot = htab_find_slot_with_hash (data->niters, exit,
00688 htab_hash_pointer (exit),
00689 INSERT);
00690
00691 if (!*slot)
00692 {
00693 nfe_desc = xmalloc (sizeof (struct nfe_cache_elt));
00694 nfe_desc->exit = exit;
00695 nfe_desc->valid_p = number_of_iterations_exit (data->current_loop,
00696 exit, &nfe_desc->niter);
00697 *slot = nfe_desc;
00698 }
00699 else
00700 nfe_desc = *slot;
00701
00702 if (!nfe_desc->valid_p)
00703 return NULL;
00704
00705 return &nfe_desc->niter;
00706 }
00707
00708
00709
00710
00711
00712 static struct tree_niter_desc *
00713 niter_for_single_dom_exit (struct ivopts_data *data)
00714 {
00715 edge exit = single_dom_exit (data->current_loop);
00716
00717 if (!exit)
00718 return NULL;
00719
00720 return niter_for_exit (data, exit);
00721 }
00722
00723
00724
00725
00726 static void
00727 tree_ssa_iv_optimize_init (struct loops *loops, struct ivopts_data *data)
00728 {
00729 unsigned i;
00730
00731 data->version_info_size = 2 * num_ssa_names;
00732 data->version_info = xcalloc (data->version_info_size,
00733 sizeof (struct version_info));
00734 data->relevant = BITMAP_ALLOC (NULL);
00735 data->important_candidates = BITMAP_ALLOC (NULL);
00736 data->max_inv_id = 0;
00737 data->niters = htab_create (10, nfe_hash, nfe_eq, free);
00738
00739 for (i = 1; i < loops->num; i++)
00740 if (loops->parray[i])
00741 loops->parray[i]->aux = xcalloc (1, sizeof (struct loop_data));
00742
00743 VARRAY_GENERIC_PTR_NOGC_INIT (data->iv_uses, 20, "iv_uses");
00744 VARRAY_GENERIC_PTR_NOGC_INIT (data->iv_candidates, 20, "iv_candidates");
00745 VARRAY_GENERIC_PTR_NOGC_INIT (decl_rtl_to_reset, 20, "decl_rtl_to_reset");
00746 }
00747
00748
00749
00750
00751 static tree
00752 determine_base_object (tree expr)
00753 {
00754 enum tree_code code = TREE_CODE (expr);
00755 tree base, obj, op0, op1;
00756
00757 if (!POINTER_TYPE_P (TREE_TYPE (expr)))
00758 return NULL_TREE;
00759
00760 switch (code)
00761 {
00762 case INTEGER_CST:
00763 return NULL_TREE;
00764
00765 case ADDR_EXPR:
00766 obj = TREE_OPERAND (expr, 0);
00767 base = get_base_address (obj);
00768
00769 if (!base)
00770 return expr;
00771
00772 if (TREE_CODE (base) == INDIRECT_REF)
00773 return determine_base_object (TREE_OPERAND (base, 0));
00774
00775 return fold (build1 (ADDR_EXPR, ptr_type_node, base));
00776
00777 case PLUS_EXPR:
00778 case MINUS_EXPR:
00779 op0 = determine_base_object (TREE_OPERAND (expr, 0));
00780 op1 = determine_base_object (TREE_OPERAND (expr, 1));
00781
00782 if (!op1)
00783 return op0;
00784
00785 if (!op0)
00786 return (code == PLUS_EXPR
00787 ? op1
00788 : fold (build1 (NEGATE_EXPR, ptr_type_node, op1)));
00789
00790 return fold (build (code, ptr_type_node, op0, op1));
00791
00792 case NOP_EXPR:
00793 case CONVERT_EXPR:
00794 return determine_base_object (TREE_OPERAND (expr, 0));
00795
00796 default:
00797 return fold_convert (ptr_type_node, expr);
00798 }
00799 }
00800
00801
00802
00803
00804 static struct iv *
00805 alloc_iv (tree base, tree step)
00806 {
00807 struct iv *iv = xcalloc (1, sizeof (struct iv));
00808
00809 if (step && integer_zerop (step))
00810 step = NULL_TREE;
00811
00812 iv->base = base;
00813 iv->base_object = determine_base_object (base);
00814 iv->step = step;
00815 iv->biv_p = false;
00816 iv->have_use_for = false;
00817 iv->use_id = 0;
00818 iv->ssa_name = NULL_TREE;
00819
00820 return iv;
00821 }
00822
00823
00824
00825 static void
00826 set_iv (struct ivopts_data *data, tree iv, tree base, tree step)
00827 {
00828 struct version_info *info = name_info (data, iv);
00829
00830 gcc_assert (!info->iv);
00831
00832 bitmap_set_bit (data->relevant, SSA_NAME_VERSION (iv));
00833 info->iv = alloc_iv (base, step);
00834 info->iv->ssa_name = iv;
00835 }
00836
00837
00838
00839 static struct iv *
00840 get_iv (struct ivopts_data *data, tree var)
00841 {
00842 basic_block bb;
00843
00844 if (!name_info (data, var)->iv)
00845 {
00846 bb = bb_for_stmt (SSA_NAME_DEF_STMT (var));
00847
00848 if (!bb
00849 || !flow_bb_inside_loop_p (data->current_loop, bb))
00850 set_iv (data, var, var, NULL_TREE);
00851 }
00852
00853 return name_info (data, var)->iv;
00854 }
00855
00856
00857
00858 static tree
00859 determine_biv_step (tree phi)
00860 {
00861 struct loop *loop = bb_for_stmt (phi)->loop_father;
00862 tree name = PHI_RESULT (phi), base, step;
00863 tree type = TREE_TYPE (name);
00864
00865 if (!is_gimple_reg (name))
00866 return NULL_TREE;
00867
00868 if (!simple_iv (loop, phi, name, &base, &step))
00869 return NULL_TREE;
00870
00871 if (!step)
00872 return build_int_cst (type, 0);
00873
00874 return step;
00875 }
00876
00877
00878
00879 static bool
00880 abnormal_ssa_name_p (tree exp)
00881 {
00882 if (!exp)
00883 return false;
00884
00885 if (TREE_CODE (exp) != SSA_NAME)
00886 return false;
00887
00888 return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
00889 }
00890
00891
00892
00893
00894 static bool
00895 idx_contains_abnormal_ssa_name_p (tree base, tree *index,
00896 void *data ATTRIBUTE_UNUSED)
00897 {
00898 if (TREE_CODE (base) == ARRAY_REF)
00899 {
00900 if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
00901 return false;
00902 if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
00903 return false;
00904 }
00905
00906 return !abnormal_ssa_name_p (*index);
00907 }
00908
00909
00910
00911
00912 static bool
00913 contains_abnormal_ssa_name_p (tree expr)
00914 {
00915 enum tree_code code = TREE_CODE (expr);
00916 enum tree_code_class class = TREE_CODE_CLASS (code);
00917
00918 if (code == SSA_NAME)
00919 return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
00920
00921 if (code == INTEGER_CST
00922 || is_gimple_min_invariant (expr))
00923 return false;
00924
00925 if (code == ADDR_EXPR)
00926 return !for_each_index (&TREE_OPERAND (expr, 0),
00927 idx_contains_abnormal_ssa_name_p,
00928 NULL);
00929
00930 switch (class)
00931 {
00932 case tcc_binary:
00933 case tcc_comparison:
00934 if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
00935 return true;
00936
00937
00938 case tcc_unary:
00939 if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
00940 return true;
00941
00942 break;
00943
00944 default:
00945 gcc_unreachable ();
00946 }
00947
00948 return false;
00949 }
00950
00951
00952
00953 static bool
00954 find_bivs (struct ivopts_data *data)
00955 {
00956 tree phi, step, type, base;
00957 bool found = false;
00958 struct loop *loop = data->current_loop;
00959
00960 for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
00961 {
00962 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)))
00963 continue;
00964
00965 step = determine_biv_step (phi);
00966
00967 if (!step)
00968 continue;
00969 if (cst_and_fits_in_hwi (step)
00970 && int_cst_value (step) == 0)
00971 continue;
00972
00973 base = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
00974 if (contains_abnormal_ssa_name_p (base))
00975 continue;
00976
00977 type = TREE_TYPE (PHI_RESULT (phi));
00978 base = fold_convert (type, base);
00979 step = fold_convert (type, step);
00980
00981
00982
00983 if (!cst_and_fits_in_hwi (step))
00984 continue;
00985
00986 set_iv (data, PHI_RESULT (phi), base, step);
00987 found = true;
00988 }
00989
00990 return found;
00991 }
00992
00993
00994
00995 static void
00996 mark_bivs (struct ivopts_data *data)
00997 {
00998 tree phi, var;
00999 struct iv *iv, *incr_iv;
01000 struct loop *loop = data->current_loop;
01001 basic_block incr_bb;
01002
01003 for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
01004 {
01005 iv = get_iv (data, PHI_RESULT (phi));
01006 if (!iv)
01007 continue;
01008
01009 var = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
01010 incr_iv = get_iv (data, var);
01011 if (!incr_iv)
01012 continue;
01013
01014
01015 incr_bb = bb_for_stmt (SSA_NAME_DEF_STMT (var));
01016 if (incr_bb->loop_father != data->current_loop
01017 || (incr_bb->flags & BB_IRREDUCIBLE_LOOP))
01018 continue;
01019
01020 iv->biv_p = true;
01021 incr_iv->biv_p = true;
01022 }
01023 }
01024
01025
01026
01027
01028 static bool
01029 find_givs_in_stmt_scev (struct ivopts_data *data, tree stmt,
01030 tree *base, tree *step)
01031 {
01032 tree lhs;
01033 struct loop *loop = data->current_loop;
01034
01035 *base = NULL_TREE;
01036 *step = NULL_TREE;
01037
01038 if (TREE_CODE (stmt) != MODIFY_EXPR)
01039 return false;
01040
01041 lhs = TREE_OPERAND (stmt, 0);
01042 if (TREE_CODE (lhs) != SSA_NAME)
01043 return false;
01044
01045 if (!simple_iv (loop, stmt, TREE_OPERAND (stmt, 1), base, step))
01046 return false;
01047
01048
01049
01050 if (!zero_p (*step)
01051 && !cst_and_fits_in_hwi (*step))
01052 return false;
01053
01054 if (contains_abnormal_ssa_name_p (*base))
01055 return false;
01056
01057 return true;
01058 }
01059
01060
01061
01062 static void
01063 find_givs_in_stmt (struct ivopts_data *data, tree stmt)
01064 {
01065 tree base, step;
01066
01067 if (!find_givs_in_stmt_scev (data, stmt, &base, &step))
01068 return;
01069
01070 set_iv (data, TREE_OPERAND (stmt, 0), base, step);
01071 }
01072
01073
01074
01075 static void
01076 find_givs_in_bb (struct ivopts_data *data, basic_block bb)
01077 {
01078 block_stmt_iterator bsi;
01079
01080 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01081 find_givs_in_stmt (data, bsi_stmt (bsi));
01082 }
01083
01084
01085
01086 static void
01087 find_givs (struct ivopts_data *data)
01088 {
01089 struct loop *loop = data->current_loop;
01090 basic_block *body = get_loop_body_in_dom_order (loop);
01091 unsigned i;
01092
01093 for (i = 0; i < loop->num_nodes; i++)
01094 find_givs_in_bb (data, body[i]);
01095 free (body);
01096 }
01097
01098
01099
01100
01101 static bool
01102 find_induction_variables (struct ivopts_data *data)
01103 {
01104 unsigned i;
01105 bitmap_iterator bi;
01106
01107 if (!find_bivs (data))
01108 return false;
01109
01110 find_givs (data);
01111 mark_bivs (data);
01112
01113 if (dump_file && (dump_flags & TDF_DETAILS))
01114 {
01115 struct tree_niter_desc *niter;
01116
01117 niter = niter_for_single_dom_exit (data);
01118
01119 if (niter)
01120 {
01121 fprintf (dump_file, " number of iterations ");
01122 print_generic_expr (dump_file, niter->niter, TDF_SLIM);
01123 fprintf (dump_file, "\n");
01124
01125 fprintf (dump_file, " may be zero if ");
01126 print_generic_expr (dump_file, niter->may_be_zero, TDF_SLIM);
01127 fprintf (dump_file, "\n");
01128 fprintf (dump_file, "\n");
01129 };
01130
01131 fprintf (dump_file, "Induction variables:\n\n");
01132
01133 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
01134 {
01135 if (ver_info (data, i)->iv)
01136 dump_iv (dump_file, ver_info (data, i)->iv);
01137 }
01138 }
01139
01140 return true;
01141 }
01142
01143
01144
01145 static struct iv_use *
01146 record_use (struct ivopts_data *data, tree *use_p, struct iv *iv,
01147 tree stmt, enum use_type use_type)
01148 {
01149 struct iv_use *use = xcalloc (1, sizeof (struct iv_use));
01150
01151 use->id = n_iv_uses (data);
01152 use->type = use_type;
01153 use->iv = iv;
01154 use->stmt = stmt;
01155 use->op_p = use_p;
01156 use->related_cands = BITMAP_ALLOC (NULL);
01157
01158
01159
01160 iv->ssa_name = NULL_TREE;
01161
01162 if (dump_file && (dump_flags & TDF_DETAILS))
01163 dump_use (dump_file, use);
01164
01165 VARRAY_PUSH_GENERIC_PTR_NOGC (data->iv_uses, use);
01166
01167 return use;
01168 }
01169
01170
01171
01172
01173
01174 static void
01175 record_invariant (struct ivopts_data *data, tree op, bool nonlinear_use)
01176 {
01177 basic_block bb;
01178 struct version_info *info;
01179
01180 if (TREE_CODE (op) != SSA_NAME
01181 || !is_gimple_reg (op))
01182 return;
01183
01184 bb = bb_for_stmt (SSA_NAME_DEF_STMT (op));
01185 if (bb
01186 && flow_bb_inside_loop_p (data->current_loop, bb))
01187 return;
01188
01189 info = name_info (data, op);
01190 info->name = op;
01191 info->has_nonlin_use |= nonlinear_use;
01192 if (!info->inv_id)
01193 info->inv_id = ++data->max_inv_id;
01194 bitmap_set_bit (data->relevant, SSA_NAME_VERSION (op));
01195 }
01196
01197
01198
01199
01200 static struct iv_use *
01201 find_interesting_uses_outer_or_nonlin (struct ivopts_data *data, tree op,
01202 enum use_type type)
01203 {
01204 struct iv *iv;
01205 struct iv *civ;
01206 tree stmt;
01207 struct iv_use *use;
01208
01209 if (TREE_CODE (op) != SSA_NAME)
01210 return NULL;
01211
01212 iv = get_iv (data, op);
01213 if (!iv)
01214 return NULL;
01215
01216 if (iv->have_use_for)
01217 {
01218 use = iv_use (data, iv->use_id);
01219
01220 gcc_assert (use->type == USE_NONLINEAR_EXPR
01221 || use->type == USE_OUTER);
01222
01223 if (type == USE_NONLINEAR_EXPR)
01224 use->type = USE_NONLINEAR_EXPR;
01225 return use;
01226 }
01227
01228 if (zero_p (iv->step))
01229 {
01230 record_invariant (data, op, true);
01231 return NULL;
01232 }
01233 iv->have_use_for = true;
01234
01235 civ = xmalloc (sizeof (struct iv));
01236 *civ = *iv;
01237
01238 stmt = SSA_NAME_DEF_STMT (op);
01239 gcc_assert (TREE_CODE (stmt) == PHI_NODE
01240 || TREE_CODE (stmt) == MODIFY_EXPR);
01241
01242 use = record_use (data, NULL, civ, stmt, type);
01243 iv->use_id = use->id;
01244
01245 return use;
01246 }
01247
01248
01249
01250 static struct iv_use *
01251 find_interesting_uses_op (struct ivopts_data *data, tree op)
01252 {
01253 return find_interesting_uses_outer_or_nonlin (data, op, USE_NONLINEAR_EXPR);
01254 }
01255
01256
01257
01258
01259 static struct iv_use *
01260 find_interesting_uses_outer (struct ivopts_data *data, tree op)
01261 {
01262 return find_interesting_uses_outer_or_nonlin (data, op, USE_OUTER);
01263 }
01264
01265
01266
01267
01268 static void
01269 find_interesting_uses_cond (struct ivopts_data *data, tree stmt, tree *cond_p)
01270 {
01271 tree *op0_p;
01272 tree *op1_p;
01273 struct iv *iv0 = NULL, *iv1 = NULL, *civ;
01274 struct iv const_iv;
01275 tree zero = integer_zero_node;
01276
01277 const_iv.step = NULL_TREE;
01278
01279 if (integer_zerop (*cond_p)
01280 || integer_nonzerop (*cond_p))
01281 return;
01282
01283 if (TREE_CODE (*cond_p) == SSA_NAME)
01284 {
01285 op0_p = cond_p;
01286 op1_p = &zero;
01287 }
01288 else
01289 {
01290 op0_p = &TREE_OPERAND (*cond_p, 0);
01291 op1_p = &TREE_OPERAND (*cond_p, 1);
01292 }
01293
01294 if (TREE_CODE (*op0_p) == SSA_NAME)
01295 iv0 = get_iv (data, *op0_p);
01296 else
01297 iv0 = &const_iv;
01298
01299 if (TREE_CODE (*op1_p) == SSA_NAME)
01300 iv1 = get_iv (data, *op1_p);
01301 else
01302 iv1 = &const_iv;
01303
01304 if (
01305
01306 (!iv0 || !iv1)
01307
01308
01309 || (!zero_p (iv0->step) && !zero_p (iv1->step)))
01310 {
01311 find_interesting_uses_op (data, *op0_p);
01312 find_interesting_uses_op (data, *op1_p);
01313 return;
01314 }
01315
01316 if (zero_p (iv0->step) && zero_p (iv1->step))
01317 {
01318
01319 return;
01320 }
01321
01322 civ = xmalloc (sizeof (struct iv));
01323 *civ = zero_p (iv0->step) ? *iv1: *iv0;
01324 record_use (data, cond_p, civ, stmt, USE_COMPARE);
01325 }
01326
01327
01328
01329
01330 bool
01331 expr_invariant_in_loop_p (struct loop *loop, tree expr)
01332 {
01333 basic_block def_bb;
01334 unsigned i, len;
01335
01336 if (is_gimple_min_invariant (expr))
01337 return true;
01338
01339 if (TREE_CODE (expr) == SSA_NAME)
01340 {
01341 def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (expr));
01342 if (def_bb
01343 && flow_bb_inside_loop_p (loop, def_bb))
01344 return false;
01345
01346 return true;
01347 }
01348
01349 if (!EXPR_P (expr))
01350 return false;
01351
01352 len = TREE_CODE_LENGTH (TREE_CODE (expr));
01353 for (i = 0; i < len; i++)
01354 if (!expr_invariant_in_loop_p (loop, TREE_OPERAND (expr, i)))
01355 return false;
01356
01357 return true;
01358 }
01359
01360
01361
01362
01363
01364 struct ifs_ivopts_data
01365 {
01366 struct ivopts_data *ivopts_data;
01367 tree stmt;
01368 tree *step_p;
01369 };
01370
01371 static bool
01372 idx_find_step (tree base, tree *idx, void *data)
01373 {
01374 struct ifs_ivopts_data *dta = data;
01375 struct iv *iv;
01376 tree step, type, iv_type, iv_step, lbound, off;
01377 struct loop *loop = dta->ivopts_data->current_loop;
01378
01379 if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF
01380 || TREE_CODE (base) == ALIGN_INDIRECT_REF)
01381 return false;
01382
01383
01384
01385 if (TREE_CODE (base) == COMPONENT_REF)
01386 {
01387 off = component_ref_field_offset (base);
01388 return expr_invariant_in_loop_p (loop, off);
01389 }
01390
01391
01392
01393
01394
01395 if (TREE_CODE (base) == ARRAY_REF)
01396 {
01397 step = array_ref_element_size (base);
01398 lbound = array_ref_low_bound (base);
01399
01400 if (!expr_invariant_in_loop_p (loop, step)
01401 || !expr_invariant_in_loop_p (loop, lbound))
01402 return false;
01403 }
01404
01405 if (TREE_CODE (*idx) != SSA_NAME)
01406 return true;
01407
01408 iv = get_iv (dta->ivopts_data, *idx);
01409 if (!iv)
01410 return false;
01411
01412 *idx = iv->base;
01413
01414 if (!iv->step)
01415 return true;
01416
01417 iv_type = TREE_TYPE (iv->base);
01418 type = build_pointer_type (TREE_TYPE (base));
01419 if (TREE_CODE (base) == ARRAY_REF)
01420 {
01421 step = array_ref_element_size (base);
01422
01423
01424 if (TREE_CODE (step) != INTEGER_CST)
01425 return false;
01426 }
01427 else
01428
01429 step = build_int_cst (type, 1);
01430
01431 if (TYPE_PRECISION (iv_type) < TYPE_PRECISION (type))
01432 iv_step = can_count_iv_in_wider_type (dta->ivopts_data->current_loop,
01433 type, iv->base, iv->step, dta->stmt);
01434 else
01435 iv_step = fold_convert (iv_type, iv->step);
01436
01437 if (!iv_step)
01438 {
01439
01440 return false;
01441 }
01442
01443 step = fold_binary_to_constant (MULT_EXPR, type, step, iv_step);
01444
01445 if (!*dta->step_p)
01446 *dta->step_p = step;
01447 else
01448 *dta->step_p = fold_binary_to_constant (PLUS_EXPR, type,
01449 *dta->step_p, step);
01450
01451 return true;
01452 }
01453
01454
01455
01456
01457 static bool
01458 idx_record_use (tree base, tree *idx,
01459 void *data)
01460 {
01461 find_interesting_uses_op (data, *idx);
01462 if (TREE_CODE (base) == ARRAY_REF)
01463 {
01464 find_interesting_uses_op (data, array_ref_element_size (base));
01465 find_interesting_uses_op (data, array_ref_low_bound (base));
01466 }
01467 return true;
01468 }
01469
01470
01471
01472 static bool
01473 may_be_unaligned_p (tree ref)
01474 {
01475 tree base;
01476 tree base_type;
01477 HOST_WIDE_INT bitsize;
01478 HOST_WIDE_INT bitpos;
01479 tree toffset;
01480 enum machine_mode mode;
01481 int unsignedp, volatilep;
01482 unsigned base_align;
01483
01484
01485
01486
01487 base = get_inner_reference (ref, &bitsize, &bitpos, &toffset, &mode,
01488 &unsignedp, &volatilep, true);
01489 base_type = TREE_TYPE (base);
01490 base_align = TYPE_ALIGN (base_type);
01491
01492 if (mode != BLKmode
01493 && (base_align < GET_MODE_ALIGNMENT (mode)
01494 || bitpos % GET_MODE_ALIGNMENT (mode) != 0
01495 || bitpos % BITS_PER_UNIT != 0))
01496 return true;
01497
01498 return false;
01499 }
01500
01501
01502
01503 static void
01504 find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p)
01505 {
01506 tree base = unshare_expr (*op_p), step = NULL;
01507 struct iv *civ;
01508 struct ifs_ivopts_data ifs_ivopts_data;
01509
01510
01511
01512 if (stmt_ann (stmt)->has_volatile_ops)
01513 goto fail;
01514
01515
01516
01517 if (TREE_CODE (base) == COMPONENT_REF
01518 && DECL_NONADDRESSABLE_P (TREE_OPERAND (base, 1)))
01519 goto fail;
01520
01521 if (STRICT_ALIGNMENT
01522 && may_be_unaligned_p (base))
01523 goto fail;
01524
01525 ifs_ivopts_data.ivopts_data = data;
01526 ifs_ivopts_data.stmt = stmt;
01527 ifs_ivopts_data.step_p = &step;
01528 if (!for_each_index (&base, idx_find_step, &ifs_ivopts_data)
01529 || zero_p (step))
01530 goto fail;
01531
01532 gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
01533 gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
01534
01535 if (TREE_CODE (base) == INDIRECT_REF)
01536 base = TREE_OPERAND (base, 0);
01537 else
01538 base = build_addr (base);
01539
01540 civ = alloc_iv (base, step);
01541 record_use (data, op_p, civ, stmt, USE_ADDRESS);
01542 return;
01543
01544 fail:
01545 for_each_index (op_p, idx_record_use, data);
01546 }
01547
01548
01549
01550 static void
01551 find_invariants_stmt (struct ivopts_data *data, tree stmt)
01552 {
01553 use_optype uses = NULL;
01554 unsigned i, n;
01555 tree op;
01556
01557 if (TREE_CODE (stmt) == PHI_NODE)
01558 n = PHI_NUM_ARGS (stmt);
01559 else
01560 {
01561 get_stmt_operands (stmt);
01562 uses = STMT_USE_OPS (stmt);
01563 n = NUM_USES (uses);
01564 }
01565
01566 for (i = 0; i < n; i++)
01567 {
01568 if (TREE_CODE (stmt) == PHI_NODE)
01569 op = PHI_ARG_DEF (stmt, i);
01570 else
01571 op = USE_OP (uses, i);
01572
01573 record_invariant (data, op, false);
01574 }
01575 }
01576
01577
01578
01579 static void
01580 find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
01581 {
01582 struct iv *iv;
01583 tree op, lhs, rhs;
01584 use_optype uses = NULL;
01585 unsigned i, n;
01586
01587 find_invariants_stmt (data, stmt);
01588
01589 if (TREE_CODE (stmt) == COND_EXPR)
01590 {
01591 find_interesting_uses_cond (data, stmt, &COND_EXPR_COND (stmt));
01592 return;
01593 }
01594
01595 if (TREE_CODE (stmt) == MODIFY_EXPR)
01596 {
01597 lhs = TREE_OPERAND (stmt, 0);
01598 rhs = TREE_OPERAND (stmt, 1);
01599
01600 if (TREE_CODE (lhs) == SSA_NAME)
01601 {
01602
01603
01604
01605 iv = get_iv (data, lhs);
01606
01607 if (iv && !zero_p (iv->step))
01608 return;
01609 }
01610
01611 switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
01612 {
01613 case tcc_comparison:
01614 find_interesting_uses_cond (data, stmt, &TREE_OPERAND (stmt, 1));
01615 return;
01616
01617 case tcc_reference:
01618 find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 1));
01619 if (REFERENCE_CLASS_P (lhs))
01620 find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 0));
01621 return;
01622
01623 default: ;
01624 }
01625
01626 if (REFERENCE_CLASS_P (lhs)
01627 && is_gimple_val (rhs))
01628 {
01629 find_interesting_uses_address (data, stmt, &TREE_OPERAND (stmt, 0));
01630 find_interesting_uses_op (data, rhs);
01631 return;
01632 }
01633
01634
01635
01636
01637
01638
01639
01640
01641 }
01642
01643 if (TREE_CODE (stmt) == PHI_NODE
01644 && bb_for_stmt (stmt) == data->current_loop->header)
01645 {
01646 lhs = PHI_RESULT (stmt);
01647 iv = get_iv (data, lhs);
01648
01649 if (iv && !zero_p (iv->step))
01650 return;
01651 }
01652
01653 if (TREE_CODE (stmt) == PHI_NODE)
01654 n = PHI_NUM_ARGS (stmt);
01655 else
01656 {
01657 uses = STMT_USE_OPS (stmt);
01658 n = NUM_USES (uses);
01659 }
01660
01661 for (i = 0; i < n; i++)
01662 {
01663 if (TREE_CODE (stmt) == PHI_NODE)
01664 op = PHI_ARG_DEF (stmt, i);
01665 else
01666 op = USE_OP (uses, i);
01667
01668 if (TREE_CODE (op) != SSA_NAME)
01669 continue;
01670
01671 iv = get_iv (data, op);
01672 if (!iv)
01673 continue;
01674
01675 find_interesting_uses_op (data, op);
01676 }
01677 }
01678
01679
01680
01681
01682 static void
01683 find_interesting_uses_outside (struct ivopts_data *data, edge exit)
01684 {
01685 tree phi, def;
01686
01687 for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
01688 {
01689 def = PHI_ARG_DEF_FROM_EDGE (phi, exit);
01690 find_interesting_uses_outer (data, def);
01691 }
01692 }
01693
01694
01695
01696 static void
01697 find_interesting_uses (struct ivopts_data *data)
01698 {
01699 basic_block bb;
01700 block_stmt_iterator bsi;
01701 tree phi;
01702 basic_block *body = get_loop_body (data->current_loop);
01703 unsigned i;
01704 struct version_info *info;
01705 edge e;
01706
01707 if (dump_file && (dump_flags & TDF_DETAILS))
01708 fprintf (dump_file, "Uses:\n\n");
01709
01710 for (i = 0; i < data->current_loop->num_nodes; i++)
01711 {
01712 edge_iterator ei;
01713 bb = body[i];
01714
01715 FOR_EACH_EDGE (e, ei, bb->succs)
01716 if (e->dest != EXIT_BLOCK_PTR
01717 && !flow_bb_inside_loop_p (data->current_loop, e->dest))
01718 find_interesting_uses_outside (data, e);
01719
01720 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
01721 find_interesting_uses_stmt (data, phi);
01722 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01723 find_interesting_uses_stmt (data, bsi_stmt (bsi));
01724 }
01725
01726 if (dump_file && (dump_flags & TDF_DETAILS))
01727 {
01728 bitmap_iterator bi;
01729
01730 fprintf (dump_file, "\n");
01731
01732 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
01733 {
01734 info = ver_info (data, i);
01735 if (info->inv_id)
01736 {
01737 fprintf (dump_file, " ");
01738 print_generic_expr (dump_file, info->name, TDF_SLIM);
01739 fprintf (dump_file, " is invariant (%d)%s\n",
01740 info->inv_id, info->has_nonlin_use ? "" : ", eliminable");
01741 }
01742 }
01743
01744 fprintf (dump_file, "\n");
01745 }
01746
01747 free (body);
01748 }
01749
01750
01751
01752
01753 static tree
01754 strip_offset (tree expr, bool inside_addr, unsigned HOST_WIDE_INT *offset)
01755 {
01756 tree op0 = NULL_TREE, op1 = NULL_TREE, step;
01757 enum tree_code code;
01758 tree type, orig_type = TREE_TYPE (expr);
01759 unsigned HOST_WIDE_INT off0, off1, st;
01760 tree orig_expr = expr;
01761
01762 STRIP_NOPS (expr);
01763 type = TREE_TYPE (expr);
01764 code = TREE_CODE (expr);
01765 *offset = 0;
01766
01767 switch (code)
01768 {
01769 case INTEGER_CST:
01770 if (!cst_and_fits_in_hwi (expr)
01771 || zero_p (expr))
01772 return orig_expr;
01773
01774 *offset = int_cst_value (expr);
01775 return build_int_cst_type (orig_type, 0);
01776
01777 case PLUS_EXPR:
01778 case MINUS_EXPR:
01779 op0 = TREE_OPERAND (expr, 0);
01780 op1 = TREE_OPERAND (expr, 1);
01781
01782 op0 = strip_offset (op0, false, &off0);
01783 op1 = strip_offset (op1, false, &off1);
01784
01785 *offset = (code == PLUS_EXPR ? off0 + off1 : off0 - off1);
01786 if (op0 == TREE_OPERAND (expr, 0)
01787 && op1 == TREE_OPERAND (expr, 1))
01788 return orig_expr;
01789
01790 if (zero_p (op1))
01791 expr = op0;
01792 else if (zero_p (op0))
01793 {
01794 if (code == PLUS_EXPR)
01795 expr = op1;
01796 else
01797 expr = build1 (NEGATE_EXPR, type, op1);
01798 }
01799 else
01800 expr = build2 (code, type, op0, op1);
01801
01802 return fold_convert (orig_type, expr);
01803
01804 case ARRAY_REF:
01805 if (!inside_addr)
01806 return orig_expr;
01807
01808 step = array_ref_element_size (expr);
01809 if (!cst_and_fits_in_hwi (step))
01810 break;
01811
01812 st = int_cst_value (step);
01813 op1 = TREE_OPERAND (expr, 1);
01814 op1 = strip_offset (op1, false, &off1);
01815 *offset = off1 * st;
01816 break;
01817
01818 case COMPONENT_REF:
01819 if (!inside_addr)
01820 return orig_expr;
01821 break;
01822
01823 case ADDR_EXPR:
01824 inside_addr = true;
01825 break;
01826
01827 default:
01828 return orig_expr;
01829 }
01830
01831
01832
01833 op0 = TREE_OPERAND (expr, 0);
01834 op0 = strip_offset (op0, inside_addr, &off0);
01835 *offset += off0;
01836
01837 if (op0 == TREE_OPERAND (expr, 0)
01838 && (!op1 || op1 == TREE_OPERAND (expr, 1)))
01839 return orig_expr;
01840
01841 expr = copy_node (expr);
01842 TREE_OPERAND (expr, 0) = op0;
01843 if (op1)
01844 TREE_OPERAND (expr, 1) = op1;
01845
01846 return fold_convert (orig_type, expr);
01847 }
01848
01849
01850
01851
01852
01853 static tree
01854 generic_type_for (tree type)
01855 {
01856 if (POINTER_TYPE_P (type))
01857 return ptr_type_node;
01858
01859 if (TYPE_UNSIGNED (type))
01860 return type;
01861
01862 return unsigned_type_for (type);
01863 }
01864
01865
01866
01867
01868
01869
01870 static struct iv_cand *
01871 add_candidate_1 (struct ivopts_data *data,
01872 tree base, tree step, bool important, enum iv_position pos,
01873 struct iv_use *use, tree incremented_at)
01874 {
01875 unsigned i;
01876 struct iv_cand *cand = NULL;
01877 tree type, orig_type;
01878
01879 if (base)
01880 {
01881 orig_type = TREE_TYPE (base);
01882 type = generic_type_for (orig_type);
01883 if (type != orig_type)
01884 {
01885 base = fold_convert (type, base);
01886 if (step)
01887 step = fold_convert (type, step);
01888 }
01889 }
01890
01891 for (i = 0; i < n_iv_cands (data); i++)
01892 {
01893 cand = iv_cand (data, i);
01894
01895 if (cand->pos != pos)
01896 continue;
01897
01898 if (cand->incremented_at != incremented_at)
01899 continue;
01900
01901 if (!cand->iv)
01902 {
01903 if (!base && !step)
01904 break;
01905
01906 continue;
01907 }
01908
01909 if (!base && !step)
01910 continue;
01911
01912 if (!operand_equal_p (base, cand->iv->base, 0))
01913 continue;
01914
01915 if (zero_p (cand->iv->step))
01916 {
01917 if (zero_p (step))
01918 break;
01919 }
01920 else
01921 {
01922 if (step && operand_equal_p (step, cand->iv->step, 0))
01923 break;
01924 }
01925 }
01926
01927 if (i == n_iv_cands (data))
01928 {
01929 cand = xcalloc (1, sizeof (struct iv_cand));
01930 cand->id = i;
01931
01932 if (!base && !step)
01933 cand->iv = NULL;
01934 else
01935 cand->iv = alloc_iv (base, step);
01936
01937 cand->pos = pos;
01938 if (pos != IP_ORIGINAL && cand->iv)
01939 {
01940 cand->var_before = create_tmp_var_raw (TREE_TYPE (base), "ivtmp");
01941 cand->var_after = cand->var_before;
01942 }
01943 cand->important = important;
01944 cand->incremented_at = incremented_at;
01945 VARRAY_PUSH_GENERIC_PTR_NOGC (data->iv_candidates, cand);
01946
01947 if (dump_file && (dump_flags & TDF_DETAILS))
01948 dump_cand (dump_file, cand);
01949 }
01950
01951 if (important && !cand->important)
01952 {
01953 cand->important = true;
01954 if (dump_file && (dump_flags & TDF_DETAILS))
01955 fprintf (dump_file, "Candidate %d is important\n", cand->id);
01956 }
01957
01958 if (use)
01959 {
01960 bitmap_set_bit (use->related_cands, i);
01961 if (dump_file && (dump_flags & TDF_DETAILS))
01962 fprintf (dump_file, "Candidate %d is related to use %d\n",
01963 cand->id, use->id);
01964 }
01965
01966 return cand;
01967 }
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978 static bool
01979 allow_ip_end_pos_p (struct loop *loop)
01980 {
01981 if (!ip_normal_pos (loop))
01982 return true;
01983
01984 if (!empty_block_p (ip_end_pos (loop)))
01985 return true;
01986
01987 return false;
01988 }
01989
01990
01991
01992
01993
01994 static void
01995 add_candidate (struct ivopts_data *data,
01996 tree base, tree step, bool important, struct iv_use *use)
01997 {
01998 if (ip_normal_pos (data->current_loop))
01999 add_candidate_1 (data, base, step, important, IP_NORMAL, use, NULL_TREE);
02000 if (ip_end_pos (data->current_loop)
02001 && allow_ip_end_pos_p (data->current_loop))
02002 add_candidate_1 (data, base, step, important, IP_END, use, NULL_TREE);
02003 }
02004
02005
02006
02007
02008 static void
02009 add_standard_iv_candidates_for_size (struct ivopts_data *data,
02010 unsigned int size)
02011 {
02012 tree type = lang_hooks.types.type_for_size (size, true);
02013 add_candidate (data, build_int_cst (type, 0), build_int_cst (type, 1),
02014 true, NULL);
02015 }
02016
02017
02018
02019 static void
02020 add_standard_iv_candidates (struct ivopts_data *data)
02021 {
02022 add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE);
02023
02024
02025 if (BITS_PER_WORD >= INT_TYPE_SIZE * 2)
02026 add_standard_iv_candidates_for_size (data, INT_TYPE_SIZE * 2);
02027 }
02028
02029
02030
02031
02032 static void
02033 add_old_iv_candidates (struct ivopts_data *data, struct iv *iv)
02034 {
02035 tree phi, def;
02036 struct iv_cand *cand;
02037
02038 add_candidate (data, iv->base, iv->step, true, NULL);
02039
02040
02041 add_candidate (data,
02042 build_int_cst (TREE_TYPE (iv->base), 0),
02043 iv->step, true, NULL);
02044
02045 phi = SSA_NAME_DEF_STMT (iv->ssa_name);
02046 if (TREE_CODE (phi) == PHI_NODE)
02047 {
02048
02049
02050 def = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (data->current_loop));
02051 cand = add_candidate_1 (data,
02052 iv->base, iv->step, true, IP_ORIGINAL, NULL,
02053 SSA_NAME_DEF_STMT (def));
02054 cand->var_before = iv->ssa_name;
02055 cand->var_after = def;
02056 }
02057 }
02058
02059
02060
02061 static void
02062 add_old_ivs_candidates (struct ivopts_data *data)
02063 {
02064 unsigned i;
02065 struct iv *iv;
02066 bitmap_iterator bi;
02067
02068 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
02069 {
02070 iv = ver_info (data, i)->iv;
02071 if (iv && iv->biv_p && !zero_p (iv->step))
02072 add_old_iv_candidates (data, iv);
02073 }
02074 }
02075
02076
02077
02078 static void
02079 add_iv_value_candidates (struct ivopts_data *data,
02080 struct iv *iv, struct iv_use *use)
02081 {
02082 add_candidate (data, iv->base, iv->step, false, use);
02083
02084
02085 add_candidate (data, build_int_cst (TREE_TYPE (iv->base), 0),
02086 iv->step, false, use);
02087 }
02088
02089
02090
02091 static void
02092 add_address_candidates (struct ivopts_data *data,
02093 struct iv *iv, struct iv_use *use)
02094 {
02095 tree base, abase;
02096 unsigned HOST_WIDE_INT offset;
02097
02098
02099 add_iv_value_candidates (data, iv, use);
02100
02101
02102 if (TREE_CODE (iv->base) == ADDR_EXPR)
02103 {
02104 base = TREE_OPERAND (iv->base, 0);
02105 while (TREE_CODE (base) == COMPONENT_REF
02106 || (TREE_CODE (base) == ARRAY_REF
02107 && TREE_CODE (TREE_OPERAND (base, 1)) == INTEGER_CST))
02108 base = TREE_OPERAND (base, 0);
02109
02110 if (base != TREE_OPERAND (iv->base, 0))
02111 {
02112 gcc_assert (TREE_CODE (base) != ALIGN_INDIRECT_REF);
02113 gcc_assert (TREE_CODE (base) != MISALIGNED_INDIRECT_REF);
02114
02115 if (TREE_CODE (base) == INDIRECT_REF)
02116 base = TREE_OPERAND (base, 0);
02117 else
02118 base = build_addr (base);
02119 add_candidate (data, base, iv->step, false, use);
02120 }
02121 }
02122
02123
02124 abase = iv->base;
02125 base = strip_offset (abase, false, &offset);
02126 if (offset)
02127 add_candidate (data, base, iv->step, false, use);
02128 }
02129
02130
02131
02132
02133 static void
02134 add_iv_outer_candidates (struct ivopts_data *data, struct iv_use *use)
02135 {
02136 struct tree_niter_desc *niter;
02137
02138
02139 niter = niter_for_single_dom_exit (data);
02140 if (!niter
02141 || !zero_p (niter->may_be_zero))
02142 return;
02143
02144 add_candidate_1 (data, NULL, NULL, false, IP_NORMAL, use, NULL_TREE);
02145 }
02146
02147
02148
02149 static void
02150 add_derived_ivs_candidates (struct ivopts_data *data)
02151 {
02152 unsigned i;
02153
02154 for (i = 0; i < n_iv_uses (data); i++)
02155 {
02156 struct iv_use *use = iv_use (data, i);
02157
02158 if (!use)
02159 continue;
02160
02161 switch (use->type)
02162 {
02163 case USE_NONLINEAR_EXPR:
02164 case USE_COMPARE:
02165
02166 add_iv_value_candidates (data, use->iv, use);
02167 break;
02168
02169 case USE_OUTER:
02170 add_iv_value_candidates (data, use->iv, use);
02171
02172
02173
02174 add_iv_outer_candidates (data, use);
02175 break;
02176
02177 case USE_ADDRESS:
02178 add_address_candidates (data, use->iv, use);
02179 break;
02180
02181 default:
02182 gcc_unreachable ();
02183 }
02184 }
02185 }
02186
02187
02188
02189
02190 static void
02191 record_important_candidates (struct ivopts_data *data)
02192 {
02193 unsigned i;
02194 struct iv_use *use;
02195
02196 for (i = 0; i < n_iv_cands (data); i++)
02197 {
02198 struct iv_cand *cand = iv_cand (data, i);
02199
02200 if (cand->important)
02201 bitmap_set_bit (data->important_candidates, i);
02202 }
02203
02204 data->consider_all_candidates = (n_iv_cands (data)
02205 <= CONSIDER_ALL_CANDIDATES_BOUND);
02206
02207 if (data->consider_all_candidates)
02208 {
02209
02210
02211 for (i = 0; i < n_iv_uses (data); i++)
02212 {
02213 use = iv_use (data, i);
02214 BITMAP_FREE (use->related_cands);
02215 }
02216 }
02217 else
02218 {
02219
02220 for (i = 0; i < n_iv_uses (data); i++)
02221 bitmap_ior_into (iv_use (data, i)->related_cands,
02222 data->important_candidates);
02223 }
02224 }
02225
02226
02227
02228 static void
02229 find_iv_candidates (struct ivopts_data *data)
02230 {
02231
02232 add_standard_iv_candidates (data);
02233
02234
02235 add_old_ivs_candidates (data);
02236
02237
02238 add_derived_ivs_candidates (data);
02239
02240
02241 record_important_candidates (data);
02242 }
02243
02244
02245
02246
02247
02248 static void
02249 alloc_use_cost_map (struct ivopts_data *data)
02250 {
02251 unsigned i, size, s, j;
02252
02253 for (i = 0; i < n_iv_uses (data); i++)
02254 {
02255 struct iv_use *use = iv_use (data, i);
02256 bitmap_iterator bi;
02257
02258 if (data->consider_all_candidates)
02259 size = n_iv_cands (data);
02260 else
02261 {
02262 s = 0;
02263 EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
02264 {
02265 s++;
02266 }
02267
02268
02269 for (size = 1; size < s; size <<= 1)
02270 continue;
02271 }
02272
02273 use->n_map_members = size;
02274 use->cost_map = xcalloc (size, sizeof (struct cost_pair));
02275 }
02276 }
02277
02278
02279
02280
02281 static void
02282 set_use_iv_cost (struct ivopts_data *data,
02283 struct iv_use *use, struct iv_cand *cand, unsigned cost,
02284 bitmap depends_on)
02285 {
02286 unsigned i, s;
02287
02288 if (cost == INFTY)
02289 {
02290 BITMAP_FREE (depends_on);
02291 return;
02292 }
02293
02294 if (data->consider_all_candidates)
02295 {
02296 use->cost_map[cand->id].cand = cand;
02297 use->cost_map[cand->id].cost = cost;
02298 use->cost_map[cand->id].depends_on = depends_on;
02299 return;
02300 }
02301
02302
02303 s = cand->id & (use->n_map_members - 1);
02304 for (i = s; i < use->n_map_members; i++)
02305 if (!use->cost_map[i].cand)
02306 goto found;
02307 for (i = 0; i < s; i++)
02308 if (!use->cost_map[i].cand)
02309 goto found;
02310
02311 gcc_unreachable ();
02312
02313 found:
02314 use->cost_map[i].cand = cand;
02315 use->cost_map[i].cost = cost;
02316 use->cost_map[i].depends_on = depends_on;
02317 }
02318
02319
02320
02321 static struct cost_pair *
02322 get_use_iv_cost (struct ivopts_data *data, struct iv_use *use,
02323 struct iv_cand *cand)
02324 {
02325 unsigned i, s;
02326 struct cost_pair *ret;
02327
02328 if (!cand)
02329 return NULL;
02330
02331 if (data->consider_all_candidates)
02332 {
02333 ret = use->cost_map + cand->id;
02334 if (!ret->cand)
02335 return NULL;
02336
02337 return ret;
02338 }
02339
02340
02341 s = cand->id & (use->n_map_members - 1);
02342 for (i = s; i < use->n_map_members; i++)
02343 if (use->cost_map[i].cand == cand)
02344 return use->cost_map + i;
02345
02346 for (i = 0; i < s; i++)
02347 if (use->cost_map[i].cand == cand)
02348 return use->cost_map + i;
02349
02350 return NULL;
02351 }
02352
02353
02354
02355 static unsigned
02356 seq_cost (rtx seq)
02357 {
02358 unsigned cost = 0;
02359 rtx set;
02360
02361 for (; seq; seq = NEXT_INSN (seq))
02362 {
02363 set = single_set (seq);
02364 if (set)
02365 cost += rtx_cost (set, SET);
02366 else
02367 cost++;
02368 }
02369
02370 return cost;
02371 }
02372
02373
02374 static rtx
02375 produce_memory_decl_rtl (tree obj, int *regno)
02376 {
02377 rtx x;
02378 if (!obj)
02379 abort ();
02380 if (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
02381 {
02382 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
02383 x = gen_rtx_SYMBOL_REF (Pmode, name);
02384 }
02385 else
02386 x = gen_raw_REG (Pmode, (*regno)++);
02387
02388 return gen_rtx_MEM (DECL_MODE (obj), x);
02389 }
02390
02391
02392
02393
02394 static tree
02395 prepare_decl_rtl (tree *expr_p, int *ws, void *data)
02396 {
02397 tree obj = NULL_TREE;
02398 rtx x = NULL_RTX;
02399 int *regno = data;
02400
02401 switch (TREE_CODE (*expr_p))
02402 {
02403 case ADDR_EXPR:
02404 for (expr_p = &TREE_OPERAND (*expr_p, 0);
02405 handled_component_p (*expr_p);
02406 expr_p = &TREE_OPERAND (*expr_p, 0))
02407 continue;
02408 obj = *expr_p;
02409 if (DECL_P (obj))
02410 x = produce_memory_decl_rtl (obj, regno);
02411 break;
02412
02413 case SSA_NAME:
02414 *ws = 0;
02415 obj = SSA_NAME_VAR (*expr_p);
02416 if (!DECL_RTL_SET_P (obj))
02417 x = gen_raw_REG (DECL_MODE (obj), (*regno)++);
02418 break;
02419
02420 case VAR_DECL:
02421 case PARM_DECL:
02422 case RESULT_DECL:
02423 *ws = 0;
02424 obj = *expr_p;
02425
02426 if (DECL_RTL_SET_P (obj))
02427 break;
02428
02429 if (DECL_MODE (obj) == BLKmode)
02430 x = produce_memory_decl_rtl (obj, regno);
02431 else
02432 x = gen_raw_REG (DECL_MODE (obj), (*regno)++);
02433
02434 break;
02435
02436 default:
02437 break;
02438 }
02439
02440 if (x)
02441 {
02442 VARRAY_PUSH_GENERIC_PTR_NOGC (decl_rtl_to_reset, obj);
02443 SET_DECL_RTL (obj, x);
02444 }
02445
02446 return NULL_TREE;
02447 }
02448
02449
02450
02451 static unsigned
02452 computation_cost (tree expr)
02453 {
02454 rtx seq, rslt;
02455 tree type = TREE_TYPE (expr);
02456 unsigned cost;
02457
02458 int regno = LAST_VIRTUAL_REGISTER + 1;
02459
02460 walk_tree (&expr, prepare_decl_rtl, ®no, NULL);
02461 start_sequence ();
02462 rslt = expand_expr (expr, NULL_RTX, TYPE_MODE (type), EXPAND_NORMAL);
02463 seq = get_insns ();
02464 end_sequence ();
02465
02466 cost = seq_cost (seq);
02467 if (GET_CODE (rslt) == MEM)
02468 cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type));
02469
02470 return cost;
02471 }
02472
02473
02474
02475 static tree
02476 var_at_stmt (struct loop *loop, struct iv_cand *cand, tree stmt)
02477 {
02478 if (stmt_after_increment (loop, cand, stmt))
02479 return cand->var_after;
02480 else
02481 return cand->var_before;
02482 }
02483
02484
02485
02486
02487 static tree
02488 get_computation_at (struct loop *loop,
02489 struct iv_use *use, struct iv_cand *cand, tree at)
02490 {
02491 tree ubase = use->iv->base;
02492 tree ustep = use->iv->step;
02493 tree cbase = cand->iv->base;
02494 tree cstep = cand->iv->step;
02495 tree utype = TREE_TYPE (ubase), ctype = TREE_TYPE (cbase);
02496 tree uutype;
02497 tree expr, delta;
02498 tree ratio;
02499 unsigned HOST_WIDE_INT ustepi, cstepi;
02500 HOST_WIDE_INT ratioi;
02501
02502 if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
02503 {
02504
02505 return NULL_TREE;
02506 }
02507
02508 expr = var_at_stmt (loop, cand, at);
02509
02510 if (TREE_TYPE (expr) != ctype)
02511 {
02512
02513 expr = fold_convert (ctype, expr);
02514 }
02515
02516 if (TYPE_UNSIGNED (utype))
02517 uutype = utype;
02518 else
02519 {
02520 uutype = unsigned_type_for (utype);
02521 ubase = fold_convert (uutype, ubase);
02522 ustep = fold_convert (uutype, ustep);
02523 }
02524
02525 if (uutype != ctype)
02526 {
02527 expr = fold_convert (uutype, expr);
02528 cbase = fold_convert (uutype, cbase);
02529 cstep = fold_convert (uutype, cstep);
02530 }
02531
02532 if (!cst_and_fits_in_hwi (cstep)
02533 || !cst_and_fits_in_hwi (ustep))
02534 return NULL_TREE;
02535
02536 ustepi = int_cst_value (ustep);
02537 cstepi = int_cst_value (cstep);
02538
02539 if (!divide (TYPE_PRECISION (uutype), ustepi, cstepi, &ratioi))
02540 {
02541
02542
02543
02544 return NULL_TREE;
02545 }
02546
02547
02548 if (stmt_after_increment (loop, cand, at))
02549 cbase = fold (build2 (PLUS_EXPR, uutype, cbase, cstep));
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559 if (ratioi == 1)
02560 {
02561 delta = fold (build2 (MINUS_EXPR, uutype, ubase, cbase));
02562 expr = fold (build2 (PLUS_EXPR, uutype, expr, delta));
02563 }
02564 else if (ratioi == -1)
02565 {
02566 delta = fold (build2 (PLUS_EXPR, uutype, ubase, cbase));
02567 expr = fold (build2 (MINUS_EXPR, uutype, delta, expr));
02568 }
02569 else
02570 {
02571 ratio = build_int_cst_type (uutype, ratioi);
02572 delta = fold (build2 (MULT_EXPR, uutype, ratio, cbase));
02573 delta = fold (build2 (MINUS_EXPR, uutype, ubase, delta));
02574 expr = fold (build2 (MULT_EXPR, uutype, ratio, expr));
02575 expr = fold (build2 (PLUS_EXPR, uutype, delta, expr));
02576 }
02577
02578 return fold_convert (utype, expr);
02579 }
02580
02581
02582
02583
02584 static tree
02585 get_computation (struct loop *loop, struct iv_use *use, struct iv_cand *cand)
02586 {
02587 return get_computation_at (loop, use, cand, use->stmt);
02588 }
02589
02590
02591
02592 static unsigned
02593 add_cost (enum machine_mode mode)
02594 {
02595 static unsigned costs[NUM_MACHINE_MODES];
02596 rtx seq;
02597 unsigned cost;
02598
02599 if (costs[mode])
02600 return costs[mode];
02601
02602 start_sequence ();
02603 force_operand (gen_rtx_fmt_ee (PLUS, mode,
02604 gen_raw_REG (mode, FIRST_PSEUDO_REGISTER),
02605 gen_raw_REG (mode, FIRST_PSEUDO_REGISTER + 1)),
02606 NULL_RTX);
02607 seq = get_insns ();
02608 end_sequence ();
02609
02610 cost = seq_cost (seq);
02611 if (!cost)
02612 cost = 1;
02613
02614 costs[mode] = cost;
02615
02616 if (dump_file && (dump_flags & TDF_DETAILS))
02617 fprintf (dump_file, "Addition in %s costs %d\n",
02618 GET_MODE_NAME (mode), cost);
02619 return cost;
02620 }
02621
02622
02623 struct mbc_entry
02624 {
02625 HOST_WIDE_INT cst;
02626 enum machine_mode mode;
02627 unsigned cost;
02628 };
02629
02630
02631
02632 static hashval_t
02633 mbc_entry_hash (const void *entry)
02634 {
02635 const struct mbc_entry *e = entry;
02636
02637 return 57 * (hashval_t) e->mode + (hashval_t) (e->cst % 877);
02638 }
02639
02640
02641
02642 static int
02643 mbc_entry_eq (const void *entry1, const void *entry2)
02644 {
02645 const struct mbc_entry *e1 = entry1;
02646 const struct mbc_entry *e2 = entry2;
02647
02648 return (e1->mode == e2->mode
02649 && e1->cst == e2->cst);
02650 }
02651
02652
02653
02654 static unsigned
02655 multiply_by_cost (HOST_WIDE_INT cst, enum machine_mode mode)
02656 {
02657 static htab_t costs;
02658 struct mbc_entry **cached, act;
02659 rtx seq;
02660 unsigned cost;
02661
02662 if (!costs)
02663 costs = htab_create (100, mbc_entry_hash, mbc_entry_eq, free);
02664
02665 act.mode = mode;
02666 act.cst = cst;
02667 cached = (struct mbc_entry **) htab_find_slot (costs, &act, INSERT);
02668 if (*cached)
02669 return (*cached)->cost;
02670
02671 *cached = xmalloc (sizeof (struct mbc_entry));
02672 (*cached)->mode = mode;
02673 (*cached)->cst = cst;
02674
02675 start_sequence ();
02676 expand_mult (mode, gen_raw_REG (mode, FIRST_PSEUDO_REGISTER), GEN_INT (cst),
02677 NULL_RTX, 0);
02678 seq = get_insns ();
02679 end_sequence ();
02680
02681 cost = seq_cost (seq);
02682
02683 if (dump_file && (dump_flags & TDF_DETAILS))
02684 fprintf (dump_file, "Multiplication by %d in %s costs %d\n",
02685 (int) cst, GET_MODE_NAME (mode), cost);
02686
02687 (*cached)->cost = cost;
02688
02689 return cost;
02690 }
02691
02692
02693
02694
02695
02696
02697
02698 static unsigned
02699 get_address_cost (bool symbol_present, bool var_present,
02700 unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio)
02701 {
02702 #define MAX_RATIO 128
02703 static sbitmap valid_mult;
02704 static HOST_WIDE_INT rat, off;
02705 static HOST_WIDE_INT min_offset, max_offset;
02706 static unsigned costs[2][2][2][2];
02707 unsigned cost, acost;
02708 rtx seq, addr, base;
02709 bool offset_p, ratio_p;
02710 rtx reg1;
02711 HOST_WIDE_INT s_offset;
02712 unsigned HOST_WIDE_INT mask;
02713 unsigned bits;
02714
02715 if (!valid_mult)
02716 {
02717 HOST_WIDE_INT i;
02718
02719 reg1 = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER);
02720
02721 addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, NULL_RTX);
02722 for (i = 1; i <= 1 << 20; i <<= 1)
02723 {
02724 XEXP (addr, 1) = GEN_INT (i);
02725 if (!memory_address_p (Pmode, addr))
02726 break;
02727 }
02728 max_offset = i >> 1;
02729 off = max_offset;
02730
02731 for (i = 1; i <= 1 << 20; i <<= 1)
02732 {
02733 XEXP (addr, 1) = GEN_INT (-i);
02734 if (!memory_address_p (Pmode, addr))
02735 break;
02736 }
02737 min_offset = -(i >> 1);
02738
02739 if (dump_file && (dump_flags & TDF_DETAILS))
02740 {
02741 fprintf (dump_file, "get_address_cost:\n");
02742 fprintf (dump_file, " min offset %d\n", (int) min_offset);
02743 fprintf (dump_file, " max offset %d\n", (int) max_offset);
02744 }
02745
02746 valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
02747 sbitmap_zero (valid_mult);
02748 rat = 1;
02749 addr = gen_rtx_fmt_ee (MULT, Pmode, reg1, NULL_RTX);
02750 for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
02751 {
02752 XEXP (addr, 1) = GEN_INT (i);
02753 if (memory_address_p (Pmode, addr))
02754 {
02755 SET_BIT (valid_mult, i + MAX_RATIO);
02756 rat = i;
02757 }
02758 }
02759
02760 if (dump_file && (dump_flags & TDF_DETAILS))
02761 {
02762 fprintf (dump_file, " allowed multipliers:");
02763 for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
02764 if (TEST_BIT (valid_mult, i + MAX_RATIO))
02765 fprintf (dump_file, " %d", (int) i);
02766 fprintf (dump_file, "\n");
02767 fprintf (dump_file, "\n");
02768 }
02769 }
02770
02771 bits = GET_MODE_BITSIZE (Pmode);
02772 mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
02773 offset &= mask;
02774 if ((offset >> (bits - 1) & 1))
02775 offset |= ~mask;
02776 s_offset = offset;
02777
02778 cost = 0;
02779 offset_p = (s_offset != 0
02780 && min_offset <= s_offset && s_offset <= max_offset);
02781 ratio_p = (ratio != 1
02782 && -MAX_RATIO <= ratio && ratio <= MAX_RATIO
02783 && TEST_BIT (valid_mult, ratio + MAX_RATIO));
02784
02785 if (ratio != 1 && !ratio_p)
02786 cost += multiply_by_cost (ratio, Pmode);
02787
02788 if (s_offset && !offset_p && !symbol_present)
02789 {
02790 cost += add_cost (Pmode);
02791 var_present = true;
02792 }
02793
02794 acost = costs[symbol_present][var_present][offset_p][ratio_p];
02795 if (!acost)
02796 {
02797 acost = 0;
02798
02799 addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER);
02800 reg1 = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 1);
02801 if (ratio_p)
02802 addr = gen_rtx_fmt_ee (MULT, Pmode, addr, GEN_INT (rat));
02803
02804 if (var_present)
02805 addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
02806
02807 if (symbol_present)
02808 {
02809 base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (""));
02810 if (offset_p)
02811 base = gen_rtx_fmt_e (CONST, Pmode,
02812 gen_rtx_fmt_ee (PLUS, Pmode,
02813 base,
02814 GEN_INT (off)));
02815 }
02816 else if (offset_p)
02817 base = GEN_INT (off);
02818 else
02819 base = NULL_RTX;
02820
02821 if (base)
02822 addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
02823
02824 start_sequence ();
02825 addr = memory_address (Pmode, addr);
02826 seq = get_insns ();
02827 end_sequence ();
02828
02829 acost = seq_cost (seq);
02830 acost += address_cost (addr, Pmode);
02831
02832 if (!acost)
02833 acost = 1;
02834 costs[symbol_present][var_present][offset_p][ratio_p] = acost;
02835 }
02836
02837 return cost + acost;
02838 }
02839
02840
02841
02842
02843 static struct ivopts_data *fd_ivopts_data;
02844 static tree
02845 find_depends (tree *expr_p, int *ws ATTRIBUTE_UNUSED, void *data)
02846 {
02847 bitmap *depends_on = data;
02848 struct version_info *info;
02849
02850 if (TREE_CODE (*expr_p) != SSA_NAME)
02851 return NULL_TREE;
02852 info = name_info (fd_ivopts_data, *expr_p);
02853
02854 if (!info->inv_id || info->has_nonlin_use)
02855 return NULL_TREE;
02856
02857 if (!*depends_on)
02858 *depends_on = BITMAP_ALLOC (NULL);
02859 bitmap_set_bit (*depends_on, info->inv_id);
02860
02861 return NULL_TREE;
02862 }
02863
02864
02865
02866
02867 static unsigned
02868 force_var_cost (struct ivopts_data *data,
02869 tree expr, bitmap *depends_on)
02870 {
02871 static bool costs_initialized = false;
02872 static unsigned integer_cost;
02873 static unsigned symbol_cost;
02874 static unsigned address_cost;
02875 tree op0, op1;
02876 unsigned cost0, cost1, cost;
02877 enum machine_mode mode;
02878
02879 if (!costs_initialized)
02880 {
02881 tree var = create_tmp_var_raw (integer_type_node, "test_var");
02882 rtx x = gen_rtx_MEM (DECL_MODE (var),
02883 gen_rtx_SYMBOL_REF (Pmode, "test_var"));
02884 tree addr;
02885 tree type = build_pointer_type (integer_type_node);
02886
02887 integer_cost = computation_cost (build_int_cst_type (integer_type_node,
02888 2000));
02889
02890 SET_DECL_RTL (var, x);
02891 TREE_STATIC (var) = 1;
02892 addr = build1 (ADDR_EXPR, type, var);
02893 symbol_cost = computation_cost (addr) + 1;
02894
02895 address_cost
02896 = computation_cost (build2 (PLUS_EXPR, type,
02897 addr,
02898 build_int_cst_type (type, 2000))) + 1;
02899 if (dump_file && (dump_flags & TDF_DETAILS))
02900 {
02901 fprintf (dump_file, "force_var_cost:\n");
02902 fprintf (dump_file, " integer %d\n", (int) integer_cost);
02903 fprintf (dump_file, " symbol %d\n", (int) symbol_cost);
02904 fprintf (dump_file, " address %d\n", (int) address_cost);
02905 fprintf (dump_file, " other %d\n", (int) target_spill_cost);
02906 fprintf (dump_file, "\n");
02907 }
02908
02909 costs_initialized = true;
02910 }
02911
02912 STRIP_NOPS (expr);
02913
02914 if (depends_on)
02915 {
02916 fd_ivopts_data = data;
02917 walk_tree (&expr, find_depends, depends_on, NULL);
02918 }
02919
02920 if (SSA_VAR_P (expr))
02921 return 0;
02922
02923 if (TREE_INVARIANT (expr))
02924 {
02925 if (TREE_CODE (expr) == INTEGER_CST)
02926 return integer_cost;
02927
02928 if (TREE_CODE (expr) == ADDR_EXPR)
02929 {
02930 tree obj = TREE_OPERAND (expr, 0);
02931
02932 if (TREE_CODE (obj) == VAR_DECL
02933 || TREE_CODE (obj) == PARM_DECL
02934 || TREE_CODE (obj) == RESULT_DECL)
02935 return symbol_cost;
02936 }
02937
02938 return address_cost;
02939 }
02940
02941 switch (TREE_CODE (expr))
02942 {
02943 case PLUS_EXPR:
02944 case MINUS_EXPR:
02945 case MULT_EXPR:
02946 op0 = TREE_OPERAND (expr, 0);
02947 op1 = TREE_OPERAND (expr, 1);
02948 STRIP_NOPS (op0);
02949 STRIP_NOPS (op1);
02950
02951 if (is_gimple_val (op0))
02952 cost0 = 0;
02953 else
02954 cost0 = force_var_cost (data, op0, NULL);
02955
02956 if (is_gimple_val (op1))
02957 cost1 = 0;
02958 else
02959 cost1 = force_var_cost (data, op1, NULL);
02960
02961 break;
02962
02963 default:
02964
02965 return target_spill_cost;
02966 }
02967
02968 mode = TYPE_MODE (TREE_TYPE (expr));
02969 switch (TREE_CODE (expr))
02970 {
02971 case PLUS_EXPR:
02972 case MINUS_EXPR:
02973 cost = add_cost (mode);
02974 break;
02975
02976 case MULT_EXPR:
02977 if (cst_and_fits_in_hwi (op0))
02978 cost = multiply_by_cost (int_cst_value (op0), mode);
02979 else if (cst_and_fits_in_hwi (op1))
02980 cost = multiply_by_cost (int_cst_value (op1), mode);
02981 else
02982 return target_spill_cost;
02983 break;
02984
02985 default:
02986 gcc_unreachable ();
02987 }
02988
02989 cost += cost0;
02990 cost += cost1;
02991
02992
02993
02994
02995
02996 return cost < target_spill_cost ? cost : target_spill_cost;
02997 }
02998
02999
03000
03001
03002
03003
03004 static unsigned
03005 split_address_cost (struct ivopts_data *data,
03006 tree addr, bool *symbol_present, bool *var_present,
03007 unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
03008 {
03009 tree core;
03010 HOST_WIDE_INT bitsize;
03011 HOST_WIDE_INT bitpos;
03012 tree toffset;
03013 enum machine_mode mode;
03014 int unsignedp, volatilep;
03015
03016 core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode,
03017 &unsignedp, &volatilep, false);
03018
03019 if (toffset != 0
03020 || bitpos % BITS_PER_UNIT != 0
03021 || TREE_CODE (core) != VAR_DECL)
03022 {
03023 *symbol_present = false;
03024 *var_present = true;
03025 fd_ivopts_data = data;
03026 walk_tree (&addr, find_depends, depends_on, NULL);
03027 return target_spill_cost;
03028 }
03029
03030 *offset += bitpos / BITS_PER_UNIT;
03031 if (TREE_STATIC (core)
03032 || DECL_EXTERNAL (core))
03033 {
03034 *symbol_present = true;
03035 *var_present = false;
03036 return 0;
03037 }
03038
03039 *symbol_present = false;
03040 *var_present = true;
03041 return 0;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050 static unsigned
03051 ptr_difference_cost (struct ivopts_data *data,
03052 tree e1, tree e2, bool *symbol_present, bool *var_present,
03053 unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
03054 {
03055 HOST_WIDE_INT diff = 0;
03056 unsigned cost;
03057
03058 gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
03059
03060 if (ptr_difference_const (e1, e2, &diff))
03061 {
03062 *offset += diff;
03063 *symbol_present = false;
03064 *var_present = false;
03065 return 0;
03066 }
03067
03068 if (e2 == integer_zero_node)
03069 return split_address_cost (data, TREE_OPERAND (e1, 0),
03070 symbol_present, var_present, offset, depends_on);
03071
03072 *symbol_present = false;
03073 *var_present = true;
03074
03075 cost = force_var_cost (data, e1, depends_on);
03076 cost += force_var_cost (data, e2, depends_on);
03077 cost += add_cost (Pmode);
03078
03079 return cost;
03080 }
03081
03082
03083
03084
03085
03086
03087
03088 static unsigned
03089 difference_cost (struct ivopts_data *data,
03090 tree e1, tree e2, bool *symbol_present, bool *var_present,
03091 unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
03092 {
03093 unsigned cost;
03094 enum machine_mode mode = TYPE_MODE (TREE_TYPE (e1));
03095 unsigned HOST_WIDE_INT off1, off2;
03096
03097 e1 = strip_offset (e1, false, &off1);
03098 e2 = strip_offset (e2, false, &off2);
03099 *offset += off1 - off2;
03100
03101 STRIP_NOPS (e1);
03102 STRIP_NOPS (e2);
03103
03104 if (TREE_CODE (e1) == ADDR_EXPR)
03105 return ptr_difference_cost (data, e1, e2, symbol_present, var_present, offset,
03106 depends_on);
03107 *symbol_present = false;
03108
03109 if (operand_equal_p (e1, e2, 0))
03110 {
03111 *var_present = false;
03112 return 0;
03113 }
03114 *var_present = true;
03115 if (zero_p (e2))
03116 return force_var_cost (data, e1, depends_on);
03117
03118 if (zero_p (e1))
03119 {
03120 cost = force_var_cost (data, e2, depends_on);
03121 cost += multiply_by_cost (-1, mode);
03122
03123 return cost;
03124 }
03125
03126 cost = force_var_cost (data, e1, depends_on);
03127 cost += force_var_cost (data, e2, depends_on);
03128 cost += add_cost (mode);
03129
03130 return cost;
03131 }
03132
03133
03134
03135
03136
03137
03138
03139 static unsigned
03140 get_computation_cost_at (struct ivopts_data *data,
03141 struct iv_use *use, struct iv_cand *cand,
03142 bool address_p, bitmap *depends_on, tree at)
03143 {
03144 tree ubase = use->iv->base, ustep = use->iv->step;
03145 tree cbase, cstep;
03146 tree utype = TREE_TYPE (ubase), ctype;
03147 unsigned HOST_WIDE_INT ustepi, cstepi, offset = 0;
03148 HOST_WIDE_INT ratio, aratio;
03149 bool var_present, symbol_present;
03150 unsigned cost = 0, n_sums;
03151
03152 *depends_on = NULL;
03153
03154
03155 if (!cand->iv)
03156 return INFTY;
03157
03158 cbase = cand->iv->base;
03159 cstep = cand->iv->step;
03160 ctype = TREE_TYPE (cbase);
03161
03162 if (TYPE_PRECISION (utype) > TYPE_PRECISION (ctype))
03163 {
03164
03165 return INFTY;
03166 }
03167
03168 if (address_p)
03169 {
03170
03171
03172
03173
03174
03175 if (use->iv->base_object
03176 && cand->iv->base_object
03177 && !operand_equal_p (use->iv->base_object, cand->iv->base_object, 0))
03178 return INFTY;
03179 }
03180
03181 if (!cst_and_fits_in_hwi (ustep)
03182 || !cst_and_fits_in_hwi (cstep))
03183 return INFTY;
03184
03185 if (TREE_CODE (ubase) == INTEGER_CST
03186 && !cst_and_fits_in_hwi (ubase))
03187 goto fallback;
03188
03189 if (TREE_CODE (cbase) == INTEGER_CST
03190 && !cst_and_fits_in_hwi (cbase))
03191 goto fallback;
03192
03193 ustepi = int_cst_value (ustep);
03194 cstepi = int_cst_value (cstep);
03195
03196 if (TYPE_PRECISION (utype) != TYPE_PRECISION (ctype))
03197 {
03198
03199 goto fallback;
03200 }
03201
03202 if (!divide (TYPE_PRECISION (utype), ustepi, cstepi, &ratio))
03203 return INFTY;
03204
03205
03206
03207
03208
03209
03210
03211
03212 if (TREE_CODE (cbase) == INTEGER_CST)
03213 {
03214 offset = - ratio * int_cst_value (cbase);
03215 cost += difference_cost (data,
03216 ubase, integer_zero_node,
03217 &symbol_present, &var_present, &offset,
03218 depends_on);
03219 }
03220 else if (ratio == 1)
03221 {
03222 cost += difference_cost (data,
03223 ubase, cbase,
03224 &symbol_present, &var_present, &offset,
03225 depends_on);
03226 }
03227 else
03228 {
03229 cost += force_var_cost (data, cbase, depends_on);
03230 cost += add_cost (TYPE_MODE (ctype));
03231 cost += difference_cost (data,
03232 ubase, integer_zero_node,
03233 &symbol_present, &var_present, &offset,
03234 depends_on);
03235 }
03236
03237
03238
03239 if (stmt_after_increment (data->current_loop, cand, at))
03240 offset -= ratio * cstepi;
03241
03242
03243
03244
03245 if (address_p)
03246 return cost + get_address_cost (symbol_present, var_present, offset, ratio);
03247
03248
03249 aratio = ratio > 0 ? ratio : -ratio;
03250 if (!symbol_present && !var_present && !offset)
03251 {
03252 if (ratio != 1)
03253 cost += multiply_by_cost (ratio, TYPE_MODE (ctype));
03254
03255 return cost;
03256 }
03257
03258 if (aratio != 1)
03259 cost += multiply_by_cost (aratio, TYPE_MODE (ctype));
03260
03261 n_sums = 1;
03262 if (var_present
03263
03264 && (symbol_present || offset))
03265 n_sums++;
03266
03267 return cost + n_sums * add_cost (TYPE_MODE (ctype));
03268
03269 fallback:
03270 {
03271
03272 tree comp = get_computation_at (data->current_loop, use, cand, at);
03273
03274 if (!comp)
03275 return INFTY;
03276
03277 if (address_p)
03278 comp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (comp)), comp);
03279
03280 return computation_cost (comp);
03281 }
03282 }
03283
03284
03285
03286
03287
03288
03289
03290 static unsigned
03291 get_computation_cost (struct ivopts_data *data,
03292 struct iv_use *use, struct iv_cand *cand,
03293 bool address_p, bitmap *depends_on)
03294 {
03295 return get_computation_cost_at (data,
03296 use, cand, address_p, depends_on, use->stmt);
03297 }
03298
03299
03300
03301
03302 static bool
03303 determine_use_iv_cost_generic (struct ivopts_data *data,
03304 struct iv_use *use, struct iv_cand *cand)
03305 {
03306 bitmap depends_on;
03307 unsigned cost;
03308
03309
03310
03311
03312
03313 if (cand->pos == IP_ORIGINAL
03314 && cand->incremented_at == use->stmt)
03315 {
03316 set_use_iv_cost (data, use, cand, 0, NULL);
03317 return true;
03318 }
03319
03320 cost = get_computation_cost (data, use, cand, false, &depends_on);
03321 set_use_iv_cost (data, use, cand, cost, depends_on);
03322
03323 return cost != INFTY;
03324 }
03325
03326
03327
03328 static bool
03329 determine_use_iv_cost_address (struct ivopts_data *data,
03330 struct iv_use *use, struct iv_cand *cand)
03331 {
03332 bitmap depends_on;
03333 unsigned cost = get_computation_cost (data, use, cand, true, &depends_on);
03334
03335 set_use_iv_cost (data, use, cand, cost, depends_on);
03336
03337 return cost != INFTY;
03338 }
03339
03340
03341
03342 static tree
03343 iv_value (struct iv *iv, tree niter)
03344 {
03345 tree val;
03346 tree type = TREE_TYPE (iv->base);
03347
03348 niter = fold_convert (type, niter);
03349 val = fold (build2 (MULT_EXPR, type, iv->step, niter));
03350
03351 return fold (build2 (PLUS_EXPR, type, iv->base, val));
03352 }
03353
03354
03355
03356 static tree
03357 cand_value_at (struct loop *loop, struct iv_cand *cand, tree at, tree niter)
03358 {
03359 tree val = iv_value (cand->iv, niter);
03360 tree type = TREE_TYPE (cand->iv->base);
03361
03362 if (stmt_after_increment (loop, cand, at))
03363 val = fold (build2 (PLUS_EXPR, type, val, cand->iv->step));
03364
03365 return val;
03366 }
03367
03368
03369
03370 static tree
03371 iv_period (struct iv *iv)
03372 {
03373 tree step = iv->step, period, type;
03374 tree pow2div;
03375
03376 gcc_assert (step && TREE_CODE (step) == INTEGER_CST);
03377
03378
03379
03380
03381 pow2div = num_ending_zeros (step);
03382 type = unsigned_type_for (TREE_TYPE (step));
03383
03384 period = build_low_bits_mask (type,
03385 (TYPE_PRECISION (type)
03386 - tree_low_cst (pow2div, 1)));
03387
03388 return period;
03389 }
03390
03391
03392
03393
03394
03395 static bool
03396 may_eliminate_iv (struct ivopts_data *data,
03397 struct iv_use *use, struct iv_cand *cand,
03398 enum tree_code *compare, tree *bound)
03399 {
03400 basic_block ex_bb;
03401 edge exit;
03402 struct tree_niter_desc *niter;
03403 tree nit, nit_type;
03404 tree wider_type, period, per_type;
03405 struct loop *loop = data->current_loop;
03406
03407
03408
03409 ex_bb = bb_for_stmt (use->stmt);
03410 if (use->stmt != last_stmt (ex_bb)
03411 || TREE_CODE (use->stmt) != COND_EXPR)
03412 return false;
03413 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, ex_bb))
03414 return false;
03415
03416 exit = EDGE_SUCC (ex_bb, 0);
03417 if (flow_bb_inside_loop_p (loop, exit->dest))
03418 exit = EDGE_SUCC (ex_bb, 1);
03419 if (flow_bb_inside_loop_p (loop, exit->dest))
03420 return false;
03421
03422 niter = niter_for_exit (data, exit);
03423 if (!niter
03424 || !zero_p (niter->may_be_zero))
03425 return false;
03426
03427 nit = niter->niter;
03428 nit_type = TREE_TYPE (nit);
03429
03430
03431
03432
03433 period = iv_period (cand->iv);
03434 if (!period)
03435 return false;
03436 per_type = TREE_TYPE (period);
03437
03438 wider_type = TREE_TYPE (period);
03439 if (TYPE_PRECISION (nit_type) < TYPE_PRECISION (per_type))
03440 wider_type = per_type;
03441 else
03442 wider_type = nit_type;
03443
03444 if (!integer_nonzerop (fold (build2 (GE_EXPR, boolean_type_node,
03445 fold_convert (wider_type, period),
03446 fold_convert (wider_type, nit)))))
03447 return false;
03448
03449 if (exit->flags & EDGE_TRUE_VALUE)
03450 *compare = EQ_EXPR;
03451 else
03452 *compare = NE_EXPR;
03453
03454 *bound = cand_value_at (loop, cand, use->stmt, nit);
03455 return true;
03456 }
03457
03458
03459
03460 static bool
03461 determine_use_iv_cost_condition (struct ivopts_data *data,
03462 struct iv_use *use, struct iv_cand *cand)
03463 {
03464 tree bound;
03465 enum tree_code compare;
03466
03467
03468 if (!cand->iv)
03469 {
03470 set_use_iv_cost (data, use, cand, INFTY, NULL);
03471 return false;
03472 }
03473
03474 if (may_eliminate_iv (data, use, cand, &compare, &bound))
03475 {
03476 bitmap depends_on = NULL;
03477 unsigned cost = force_var_cost (data, bound, &depends_on);
03478
03479 set_use_iv_cost (data, use, cand, cost, depends_on);
03480 return cost != INFTY;
03481 }
03482
03483
03484
03485
03486 if (TREE_CODE (*use->op_p) == SSA_NAME)
03487 record_invariant (data, *use->op_p, true);
03488 else
03489 {
03490 record_invariant (data, TREE_OPERAND (*use->op_p, 0), true);
03491 record_invariant (data, TREE_OPERAND (*use->op_p, 1), true);
03492 }
03493
03494 return determine_use_iv_cost_generic (data, use, cand);
03495 }
03496
03497
03498
03499
03500 static bool
03501 may_replace_final_value (struct ivopts_data *data, struct iv_use *use,
03502 tree *value)
03503 {
03504 struct loop *loop = data->current_loop;
03505 edge exit;
03506 struct tree_niter_desc *niter;
03507
03508 exit = single_dom_exit (loop);
03509 if (!exit)
03510 return false;
03511
03512 gcc_assert (dominated_by_p (CDI_DOMINATORS, exit->src,
03513 bb_for_stmt (use->stmt)));
03514
03515 niter = niter_for_single_dom_exit (data);
03516 if (!niter
03517 || !zero_p (niter->may_be_zero))
03518 return false;
03519
03520 *value = iv_value (use->iv, niter->niter);
03521
03522 return true;
03523 }
03524
03525
03526
03527 static bool
03528 determine_use_iv_cost_outer (struct ivopts_data *data,
03529 struct iv_use *use, struct iv_cand *cand)
03530 {
03531 bitmap depends_on;
03532 unsigned cost;
03533 edge exit;
03534 tree value;
03535 struct loop *loop = data->current_loop;
03536
03537
03538
03539
03540
03541 if (cand->pos == IP_ORIGINAL
03542 && cand->incremented_at == use->stmt)
03543 {
03544 set_use_iv_cost (data, use, cand, 0, NULL);
03545 return true;
03546 }
03547
03548 if (!cand->iv)
03549 {
03550 if (!may_replace_final_value (data, use, &value))
03551 {
03552 set_use_iv_cost (data, use, cand, INFTY, NULL);
03553 return false;
03554 }
03555
03556 depends_on = NULL;
03557 cost = force_var_cost (data, value, &depends_on);
03558
03559 cost /= AVG_LOOP_NITER (loop);
03560
03561 set_use_iv_cost (data, use, cand, cost, depends_on);
03562 return cost != INFTY;
03563 }
03564
03565 exit = single_dom_exit (loop);
03566 if (exit)
03567 {
03568
03569
03570 cost = get_computation_cost_at (data, use, cand, false, &depends_on,
03571 last_stmt (exit->src));
03572 if (cost != INFTY)
03573 cost /= AVG_LOOP_NITER (loop);
03574 }
03575 else
03576 {
03577
03578 cost = get_computation_cost (data, use, cand, false, &depends_on);
03579 }
03580
03581 set_use_iv_cost (data, use, cand, cost, depends_on);
03582
03583 return cost != INFTY;
03584 }
03585
03586
03587
03588
03589 static bool
03590 determine_use_iv_cost (struct ivopts_data *data,
03591 struct iv_use *use, struct iv_cand *cand)
03592 {
03593 switch (use->type)
03594 {
03595 case USE_NONLINEAR_EXPR:
03596 return determine_use_iv_cost_generic (data, use, cand);
03597
03598 case USE_OUTER:
03599 return determine_use_iv_cost_outer (data, use, cand);
03600
03601 case USE_ADDRESS:
03602 return determine_use_iv_cost_address (data, use, cand);
03603
03604 case USE_COMPARE:
03605 return determine_use_iv_cost_condition (data, use, cand);
03606
03607 default:
03608 gcc_unreachable ();
03609 }
03610 }
03611
03612
03613
03614 static void
03615 determine_use_iv_costs (struct ivopts_data *data)
03616 {
03617 unsigned i, j;
03618 struct iv_use *use;
03619 struct iv_cand *cand;
03620 bitmap to_clear = BITMAP_ALLOC (NULL);
03621
03622 alloc_use_cost_map (data);
03623
03624 for (i = 0; i < n_iv_uses (data); i++)
03625 {
03626 use = iv_use (data, i);
03627
03628 if (data->consider_all_candidates)
03629 {
03630 for (j = 0; j < n_iv_cands (data); j++)
03631 {
03632 cand = iv_cand (data, j);
03633 determine_use_iv_cost (data, use, cand);
03634 }
03635 }
03636 else
03637 {
03638 bitmap_iterator bi;
03639
03640 EXECUTE_IF_SET_IN_BITMAP (use->related_cands, 0, j, bi)
03641 {
03642 cand = iv_cand (data, j);
03643 if (!determine_use_iv_cost (data, use, cand))
03644 bitmap_set_bit (to_clear, j);
03645 }
03646
03647
03648
03649 bitmap_and_compl_into (use->related_cands, to_clear);
03650 bitmap_clear (to_clear);
03651 }
03652 }
03653
03654 BITMAP_FREE (to_clear);
03655
03656 if (dump_file && (dump_flags & TDF_DETAILS))
03657 {
03658 fprintf (dump_file, "Use-candidate costs:\n");
03659
03660 for (i = 0; i < n_iv_uses (data); i++)
03661 {
03662 use = iv_use (data, i);
03663
03664 fprintf (dump_file, "Use %d:\n", i);
03665 fprintf (dump_file, " cand\tcost\tdepends on\n");
03666 for (j = 0; j < use->n_map_members; j++)
03667 {
03668 if (!use->cost_map[j].cand
03669 || use->cost_map[j].cost == INFTY)
03670 continue;
03671
03672 fprintf (dump_file, " %d\t%d\t",
03673 use->cost_map[j].cand->id,
03674 use->cost_map[j].cost);
03675 if (use->cost_map[j].depends_on)
03676 bitmap_print (dump_file,
03677 use->cost_map[j].depends_on, "","");
03678 fprintf (dump_file, "\n");
03679 }
03680
03681 fprintf (dump_file, "\n");
03682 }
03683 fprintf (dump_file, "\n");
03684 }
03685 }
03686
03687
03688
03689 static void
03690 determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand)
03691 {
03692 unsigned cost_base, cost_step;
03693 tree base;
03694
03695 if (!cand->iv)
03696 {
03697 cand->cost = 0;
03698 return;
03699 }
03700
03701
03702
03703
03704
03705 base = cand->iv->base;
03706 cost_base = force_var_cost (data, base, NULL);
03707 cost_step = add_cost (TYPE_MODE (TREE_TYPE (base)));
03708
03709 cand->cost = cost_step + cost_base / AVG_LOOP_NITER (current_loop);
03710
03711
03712 if (cand->pos == IP_ORIGINAL)
03713 cand->cost--;
03714
03715
03716
03717 if (cand->pos == IP_END
03718 && empty_block_p (ip_end_pos (data->current_loop)))
03719 cand->cost++;
03720 }
03721
03722
03723
03724 static void
03725 determine_iv_costs (struct ivopts_data *data)
03726 {
03727 unsigned i;
03728
03729 if (dump_file && (dump_flags & TDF_DETAILS))
03730 {
03731 fprintf (dump_file, "Candidate costs:\n");
03732 fprintf (dump_file, " cand\tcost\n");
03733 }
03734
03735 for (i = 0; i < n_iv_cands (data); i++)
03736 {
03737 struct iv_cand *cand = iv_cand (data, i);
03738
03739 determine_iv_cost (data, cand);
03740
03741 if (dump_file && (dump_flags & TDF_DETAILS))
03742 fprintf (dump_file, " %d\t%d\n", i, cand->cost);
03743 }
03744
03745 if (dump_file && (dump_flags & TDF_DETAILS))
03746 fprintf (dump_file, "\n");
03747 }
03748
03749
03750
03751 static unsigned
03752 ivopts_global_cost_for_size (struct ivopts_data *data, unsigned size)
03753 {
03754 return global_cost_for_size (size,
03755 loop_data (data->current_loop)->regs_used,
03756 n_iv_uses (data));
03757 }
03758
03759
03760
03761 static void
03762 determine_set_costs (struct ivopts_data *data)
03763 {
03764 unsigned j, n;
03765 tree phi, op;
03766 struct loop *loop = data->current_loop;
03767 bitmap_iterator bi;
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03780
03781
03782
03783
03784
03785
03786
03787
03788
03789 if (dump_file && (dump_flags & TDF_DETAILS))
03790 {
03791 fprintf (dump_file, "Global costs:\n");
03792 fprintf (dump_file, " target_avail_regs %d\n", target_avail_regs);
03793 fprintf (dump_file, " target_small_cost %d\n", target_small_cost);
03794 fprintf (dump_file, " target_pres_cost %d\n", target_pres_cost);
03795 fprintf (dump_file, " target_spill_cost %d\n", target_spill_cost);
03796 }
03797
03798 n = 0;
03799 for (phi = phi_nodes (loop->header); phi; phi = PHI_CHAIN (phi))
03800 {
03801 op = PHI_RESULT (phi);
03802
03803 if (!is_gimple_reg (op))
03804 continue;
03805
03806 if (get_iv (data, op))
03807 continue;
03808
03809 n++;
03810 }
03811
03812 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi)
03813 {
03814 struct version_info *info = ver_info (data, j);
03815
03816 if (info->inv_id && info->has_nonlin_use)
03817 n++;
03818 }
03819
03820 loop_data (loop)->regs_used = n;
03821 if (dump_file && (dump_flags & TDF_DETAILS))
03822 fprintf (dump_file, " regs_used %d\n", n);
03823
03824 if (dump_file && (dump_flags & TDF_DETAILS))
03825 {
03826 fprintf (dump_file, " cost for size:\n");
03827 fprintf (dump_file, " ivs\tcost\n");
03828 for (j = 0; j <= 2 * target_avail_regs; j++)
03829 fprintf (dump_file, " %d\t%d\n", j,
03830 ivopts_global_cost_for_size (data, j));
03831 fprintf (dump_file, "\n");
03832 }
03833 }
03834
03835
03836
03837 static bool
03838 cheaper_cost_pair (struct cost_pair *a, struct cost_pair *b)
03839 {
03840 if (!a)
03841 return false;
03842
03843 if (!b)
03844 return true;
03845
03846 if (a->cost < b->cost)
03847 return true;
03848
03849 if (a->cost > b->cost)
03850 return false;
03851
03852
03853 if (a->cand->cost < b->cand->cost)
03854 return true;
03855
03856 return false;
03857 }
03858
03859
03860
03861 static void
03862 iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
03863 {
03864 unsigned cost = 0;
03865
03866 cost += ivs->cand_use_cost;
03867 cost += ivs->cand_cost;
03868 cost += ivopts_global_cost_for_size (data, ivs->n_regs);
03869
03870 ivs->cost = cost;
03871 }
03872
03873
03874
03875 static void
03876 iv_ca_set_no_cp (struct ivopts_data *data, struct iv_ca *ivs,
03877 struct iv_use *use)
03878 {
03879 unsigned uid = use->id, cid, iid;
03880 bitmap deps;
03881 struct cost_pair *cp;
03882 bitmap_iterator bi;
03883
03884 cp = ivs->cand_for_use[uid];
03885 if (!cp)
03886 return;
03887 cid = cp->cand->id;
03888
03889 ivs->bad_uses++;
03890 ivs->cand_for_use[uid] = NULL;
03891 ivs->n_cand_uses[cid]--;
03892
03893 if (ivs->n_cand_uses[cid] == 0)
03894 {
03895 bitmap_clear_bit (ivs->cands, cid);
03896
03897 if (cp->cand->iv)
03898 ivs->n_regs--;
03899 ivs->n_cands--;
03900 ivs->cand_cost -= cp->cand->cost;
03901 }
03902
03903 ivs->cand_use_cost -= cp->cost;
03904
03905 deps = cp->depends_on;
03906
03907 if (deps)
03908 {
03909 EXECUTE_IF_SET_IN_BITMAP (deps, 0, iid, bi)
03910 {
03911 ivs->n_invariant_uses[iid]--;
03912 if (ivs->n_invariant_uses[iid] == 0)
03913 ivs->n_regs--;
03914 }
03915 }
03916
03917 iv_ca_recount_cost (data, ivs);
03918 }
03919
03920
03921
03922 static void
03923 iv_ca_set_cp (struct ivopts_data *data, struct iv_ca *ivs,
03924 struct iv_use *use, struct cost_pair *cp)
03925 {
03926 unsigned uid = use->id, cid, iid;
03927 bitmap deps;
03928 bitmap_iterator bi;
03929
03930 if (ivs->cand_for_use[uid] == cp)
03931 return;
03932
03933 if (ivs->cand_for_use[uid])
03934 iv_ca_set_no_cp (data, ivs, use);
03935
03936 if (cp)
03937 {
03938 cid = cp->cand->id;
03939
03940 ivs->bad_uses--;
03941 ivs->cand_for_use[uid] = cp;
03942 ivs->n_cand_uses[cid]++;
03943 if (ivs->n_cand_uses[cid] == 1)
03944 {
03945 bitmap_set_bit (ivs->cands, cid);
03946
03947 if (cp->cand->iv)
03948 ivs->n_regs++;
03949 ivs->n_cands++;
03950 ivs->cand_cost += cp->cand->cost;
03951 }
03952
03953 ivs->cand_use_cost += cp->cost;
03954
03955 deps = cp->depends_on;
03956
03957 if (deps)
03958 {
03959 EXECUTE_IF_SET_IN_BITMAP (deps, 0, iid, bi)
03960 {
03961 ivs->n_invariant_uses[iid]++;
03962 if (ivs->n_invariant_uses[iid] == 1)
03963 ivs->n_regs++;
03964 }
03965 }
03966
03967 iv_ca_recount_cost (data, ivs);
03968 }
03969 }
03970
03971
03972
03973
03974 static void
03975 iv_ca_add_use (struct ivopts_data *data, struct iv_ca *ivs,
03976 struct iv_use *use)
03977 {
03978 struct cost_pair *best_cp = NULL, *cp;
03979 bitmap_iterator bi;
03980 unsigned i;
03981
03982 gcc_assert (ivs->upto >= use->id);
03983
03984 if (ivs->upto == use->id)
03985 {
03986 ivs->upto++;
03987 ivs->bad_uses++;
03988 }
03989
03990 EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, i, bi)
03991 {
03992 cp = get_use_iv_cost (data, use, iv_cand (data, i));
03993
03994 if (cheaper_cost_pair (cp, best_cp))
03995 best_cp = cp;
03996 }
03997
03998 iv_ca_set_cp (data, ivs, use, best_cp);
03999 }
04000
04001
04002
04003 static unsigned
04004 iv_ca_cost (struct iv_ca *ivs)
04005 {
04006 return (ivs->bad_uses ? INFTY : ivs->cost);
04007 }
04008
04009
04010
04011 static bool
04012 iv_ca_has_deps (struct iv_ca *ivs, struct cost_pair *cp)
04013 {
04014 unsigned i;
04015 bitmap_iterator bi;
04016
04017 if (!cp->depends_on)
04018 return true;
04019
04020 EXECUTE_IF_SET_IN_BITMAP (cp->depends_on, 0, i, bi)
04021 {
04022 if (ivs->n_invariant_uses[i] == 0)
04023 return false;
04024 }
04025
04026 return true;
04027 }
04028
04029
04030
04031
04032 static struct iv_ca_delta *
04033 iv_ca_delta_add (struct iv_use *use, struct cost_pair *old_cp,
04034 struct cost_pair *new_cp, struct iv_ca_delta *next_change)
04035 {
04036 struct iv_ca_delta *change = xmalloc (sizeof (struct iv_ca_delta));
04037
04038 change->use = use;
04039 change->old_cp = old_cp;
04040 change->new_cp = new_cp;
04041 change->next_change = next_change;
04042
04043 return change;
04044 }
04045
04046
04047
04048
04049 static struct iv_ca_delta *
04050 iv_ca_delta_join (struct iv_ca_delta *l1, struct iv_ca_delta *l2)
04051 {
04052 struct iv_ca_delta *last;
04053
04054 if (!l2)
04055 return l1;
04056
04057 if (!l1)
04058 return l2;
04059
04060 for (last = l1; last->next_change; last = last->next_change)
04061 continue;
04062 last->next_change = l2;
04063
04064 return l1;
04065 }
04066
04067
04068
04069 static struct cost_pair *
04070 iv_ca_cand_for_use (struct iv_ca *ivs, struct iv_use *use)
04071 {
04072 return ivs->cand_for_use[use->id];
04073 }
04074
04075
04076
04077 static struct iv_ca_delta *
04078 iv_ca_delta_reverse (struct iv_ca_delta *delta)
04079 {
04080 struct iv_ca_delta *act, *next, *prev = NULL;
04081 struct cost_pair *tmp;
04082
04083 for (act = delta; act; act = next)
04084 {
04085 next = act->next_change;
04086 act->next_change = prev;
04087 prev = act;
04088
04089 tmp = act->old_cp;
04090 act->old_cp = act->new_cp;
04091 act->new_cp = tmp;
04092 }
04093
04094 return prev;
04095 }
04096
04097
04098
04099
04100 static void
04101 iv_ca_delta_commit (struct ivopts_data *data, struct iv_ca *ivs,
04102 struct iv_ca_delta *delta, bool forward)
04103 {
04104 struct cost_pair *from, *to;
04105 struct iv_ca_delta *act;
04106
04107 if (!forward)
04108 delta = iv_ca_delta_reverse (delta);
04109
04110 for (act = delta; act; act = act->next_change)
04111 {
04112 from = act->old_cp;
04113 to = act->new_cp;
04114 gcc_assert (iv_ca_cand_for_use (ivs, act->use) == from);
04115 iv_ca_set_cp (data, ivs, act->use, to);
04116 }
04117
04118 if (!forward)
04119 iv_ca_delta_reverse (delta);
04120 }
04121
04122
04123
04124 static bool
04125 iv_ca_cand_used_p (struct iv_ca *ivs, struct iv_cand *cand)
04126 {
04127 return ivs->n_cand_uses[cand->id] > 0;
04128 }
04129
04130
04131
04132 static unsigned
04133 iv_ca_n_cands (struct iv_ca *ivs)
04134 {
04135 return ivs->n_cands;
04136 }
04137
04138
04139
04140 static void
04141 iv_ca_delta_free (struct iv_ca_delta **delta)
04142 {
04143 struct iv_ca_delta *act, *next;
04144
04145 for (act = *delta; act; act = next)
04146 {
04147 next = act->next_change;
04148 free (act);
04149 }
04150
04151 *delta = NULL;
04152 }
04153
04154
04155
04156 static struct iv_ca *
04157 iv_ca_new (struct ivopts_data *data)
04158 {
04159 struct iv_ca *nw = xmalloc (sizeof (struct iv_ca));
04160
04161 nw->upto = 0;
04162 nw->bad_uses = 0;
04163 nw->cand_for_use = xcalloc (n_iv_uses (data), sizeof (struct cost_pair *));
04164 nw->n_cand_uses = xcalloc (n_iv_cands (data), sizeof (unsigned));
04165 nw->cands = BITMAP_ALLOC (NULL);
04166 nw->n_cands = 0;
04167 nw->n_regs = 0;
04168 nw->cand_use_cost = 0;
04169 nw->cand_cost = 0;
04170 nw->n_invariant_uses = xcalloc (data->max_inv_id + 1, sizeof (unsigned));
04171 nw->cost = 0;
04172
04173 return nw;
04174 }
04175
04176
04177
04178 static void
04179 iv_ca_free (struct iv_ca **ivs)
04180 {
04181 free ((*ivs)->cand_for_use);
04182 free ((*ivs)->n_cand_uses);
04183 BITMAP_FREE ((*ivs)->cands);
04184 free ((*ivs)->n_invariant_uses);
04185 free (*ivs);
04186 *ivs = NULL;
04187 }
04188
04189
04190
04191 static void
04192 iv_ca_dump (struct ivopts_data *data, FILE *file, struct iv_ca *ivs)
04193 {
04194 const char *pref = " invariants ";
04195 unsigned i;
04196
04197 fprintf (file, " cost %d\n", iv_ca_cost (ivs));
04198 bitmap_print (file, ivs->cands, " candidates ","\n");
04199
04200 for (i = 1; i <= data->max_inv_id; i++)
04201 if (ivs->n_invariant_uses[i])
04202 {
04203 fprintf (file, "%s%d", pref, i);
04204 pref = ", ";
04205 }
04206 fprintf (file, "\n");
04207 }
04208
04209
04210
04211
04212
04213 static unsigned
04214 iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs,
04215 struct iv_cand *cand, struct iv_ca_delta **delta,
04216 unsigned *n_ivs)
04217 {
04218 unsigned i, cost;
04219 struct iv_use *use;
04220 struct cost_pair *old_cp, *new_cp;
04221
04222 *delta = NULL;
04223 for (i = 0; i < ivs->upto; i++)
04224 {
04225 use = iv_use (data, i);
04226 old_cp = iv_ca_cand_for_use (ivs, use);
04227
04228 if (old_cp
04229 && old_cp->cand == cand)
04230 continue;
04231
04232 new_cp = get_use_iv_cost (data, use, cand);
04233 if (!new_cp)
04234 continue;
04235
04236 if (!iv_ca_has_deps (ivs, new_cp))
04237 continue;
04238
04239 if (!cheaper_cost_pair (new_cp, old_cp))
04240 continue;
04241
04242 *delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
04243 }
04244
04245 iv_ca_delta_commit (data, ivs, *delta, true);
04246 cost = iv_ca_cost (ivs);
04247 if (n_ivs)
04248 *n_ivs = iv_ca_n_cands (ivs);
04249 iv_ca_delta_commit (data, ivs, *delta, false);
04250
04251 return cost;
04252 }
04253
04254
04255
04256
04257 static unsigned
04258 iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs,
04259 struct iv_cand *cand, struct iv_ca_delta **delta)
04260 {
04261 unsigned i, ci;
04262 struct iv_use *use;
04263 struct cost_pair *old_cp, *new_cp, *cp;
04264 bitmap_iterator bi;
04265 struct iv_cand *cnd;
04266 unsigned cost;
04267
04268 *delta = NULL;
04269 for (i = 0; i < n_iv_uses (data); i++)
04270 {
04271 use = iv_use (data, i);
04272
04273 old_cp = iv_ca_cand_for_use (ivs, use);
04274 if (old_cp->cand != cand)
04275 continue;
04276
04277 new_cp = NULL;
04278
04279 if (data->consider_all_candidates)
04280 {
04281 EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, ci, bi)
04282 {
04283 if (ci == cand->id)
04284 continue;
04285
04286 cnd = iv_cand (data, ci);
04287
04288 cp = get_use_iv_cost (data, use, cnd);
04289 if (!cp)
04290 continue;
04291 if (!iv_ca_has_deps (ivs, cp))
04292 continue;
04293
04294 if (!cheaper_cost_pair (cp, new_cp))
04295 continue;
04296
04297 new_cp = cp;
04298 }
04299 }
04300 else
04301 {
04302 EXECUTE_IF_AND_IN_BITMAP (use->related_cands, ivs->cands, 0, ci, bi)
04303 {
04304 if (ci == cand->id)
04305 continue;
04306
04307 cnd = iv_cand (data, ci);
04308
04309 cp = get_use_iv_cost (data, use, cnd);
04310 if (!cp)
04311 continue;
04312 if (!iv_ca_has_deps (ivs, cp))
04313 continue;
04314
04315 if (!cheaper_cost_pair (cp, new_cp))
04316 continue;
04317
04318 new_cp = cp;
04319 }
04320 }
04321
04322 if (!new_cp)
04323 {
04324 iv_ca_delta_free (delta);
04325 return INFTY;
04326 }
04327
04328 *delta = iv_ca_delta_add (use, old_cp, new_cp, *delta);
04329 }
04330
04331 iv_ca_delta_commit (data, ivs, *delta, true);
04332 cost = iv_ca_cost (ivs);
04333 iv_ca_delta_commit (data, ivs, *delta, false);
04334
04335 return cost;
04336 }
04337
04338
04339
04340
04341
04342 static unsigned
04343 iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs,
04344 struct iv_cand *except_cand, struct iv_ca_delta **delta)
04345 {
04346 bitmap_iterator bi;
04347 struct iv_ca_delta *act_delta, *best_delta;
04348 unsigned i, best_cost, acost;
04349 struct iv_cand *cand;
04350
04351 best_delta = NULL;
04352 best_cost = iv_ca_cost (ivs);
04353
04354 EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, i, bi)
04355 {
04356 cand = iv_cand (data, i);
04357
04358 if (cand == except_cand)
04359 continue;
04360
04361 acost = iv_ca_narrow (data, ivs, cand, &act_delta);
04362
04363 if (acost < best_cost)
04364 {
04365 best_cost = acost;
04366 iv_ca_delta_free (&best_delta);
04367 best_delta = act_delta;
04368 }
04369 else
04370 iv_ca_delta_free (&act_delta);
04371 }
04372
04373 if (!best_delta)
04374 {
04375 *delta = NULL;
04376 return best_cost;
04377 }
04378
04379
04380 iv_ca_delta_commit (data, ivs, best_delta, true);
04381 best_cost = iv_ca_prune (data, ivs, except_cand, delta);
04382 iv_ca_delta_commit (data, ivs, best_delta, false);
04383 *delta = iv_ca_delta_join (best_delta, *delta);
04384 return best_cost;
04385 }
04386
04387
04388
04389
04390 static bool
04391 try_add_cand_for (struct ivopts_data *data, struct iv_ca *ivs,
04392 struct iv_use *use)
04393 {
04394 unsigned best_cost, act_cost;
04395 unsigned i;
04396 bitmap_iterator bi;
04397 struct iv_cand *cand;
04398 struct iv_ca_delta *best_delta = NULL, *act_delta;
04399 struct cost_pair *cp;
04400
04401 iv_ca_add_use (data, ivs, use);
04402 best_cost = iv_ca_cost (ivs);
04403
04404 cp = iv_ca_cand_for_use (ivs, use);
04405 if (cp)
04406 {
04407 best_delta = iv_ca_delta_add (use, NULL, cp, NULL);
04408 iv_ca_set_no_cp (data, ivs, use);
04409 }
04410
04411
04412
04413
04414
04415
04416
04417
04418
04419 EXECUTE_IF_SET_IN_BITMAP (data->important_candidates, 0, i, bi)
04420 {
04421 cand = iv_cand (data, i);
04422
04423 if (iv_ca_cand_used_p (ivs, cand))
04424 continue;
04425
04426 cp = get_use_iv_cost (data, use, cand);
04427 if (!cp)
04428 continue;
04429
04430 iv_ca_set_cp (data, ivs, use, cp);
04431 act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL);
04432 iv_ca_set_no_cp (data, ivs, use);
04433 act_delta = iv_ca_delta_add (use, NULL, cp, act_delta);
04434
04435 if (act_cost < best_cost)
04436 {
04437 best_cost = act_cost;
04438
04439 iv_ca_delta_free (&best_delta);
04440 best_delta = act_delta;
04441 }
04442 else
04443 iv_ca_delta_free (&act_delta);
04444 }
04445
04446 if (best_cost == INFTY)
04447 {
04448 for (i = 0; i < use->n_map_members; i++)
04449 {
04450 cp = use->cost_map + i;
04451 cand = cp->cand;
04452 if (!cand)
04453 continue;
04454
04455
04456 if (cand->important)
04457 continue;
04458
04459 if (iv_ca_cand_used_p (ivs, cand))
04460 continue;
04461
04462 act_delta = NULL;
04463 iv_ca_set_cp (data, ivs, use, cp);
04464 act_cost = iv_ca_extend (data, ivs, cand, &act_delta, NULL);
04465 iv_ca_set_no_cp (data, ivs, use);
04466 act_delta = iv_ca_delta_add (use, iv_ca_cand_for_use (ivs, use),
04467 cp, act_delta);
04468
04469 if (act_cost < best_cost)
04470 {
04471 best_cost = act_cost;
04472
04473 if (best_delta)
04474 iv_ca_delta_free (&best_delta);
04475 best_delta = act_delta;
04476 }
04477 else
04478 iv_ca_delta_free (&act_delta);
04479 }
04480 }
04481
04482 iv_ca_delta_commit (data, ivs, best_delta, true);
04483 iv_ca_delta_free (&best_delta);
04484
04485 return (best_cost != INFTY);
04486 }
04487
04488
04489
04490 static struct iv_ca *
04491 get_initial_solution (struct ivopts_data *data)
04492 {
04493 struct iv_ca *ivs = iv_ca_new (data);
04494 unsigned i;
04495
04496 for (i = 0; i < n_iv_uses (data); i++)
04497 if (!try_add_cand_for (data, ivs, iv_use (data, i)))
04498 {
04499 iv_ca_free (&ivs);
04500 return NULL;
04501 }
04502
04503 return ivs;
04504 }
04505
04506
04507
04508 static bool
04509 try_improve_iv_set (struct ivopts_data *data, struct iv_ca *ivs)
04510 {
04511 unsigned i, acost, best_cost = iv_ca_cost (ivs), n_ivs;
04512 struct iv_ca_delta *best_delta = NULL, *act_delta, *tmp_delta;
04513 struct iv_cand *cand;
04514
04515
04516 for (i = 0; i < n_iv_cands (data); i++)
04517 {
04518 cand = iv_cand (data, i);
04519
04520 if (iv_ca_cand_used_p (ivs, cand))
04521 continue;
04522
04523 acost = iv_ca_extend (data, ivs, cand, &act_delta, &n_ivs);
04524 if (!act_delta)
04525 continue;
04526
04527
04528
04529 if (n_ivs <= ALWAYS_PRUNE_CAND_SET_BOUND)
04530 {
04531 iv_ca_delta_commit (data, ivs, act_delta, true);
04532 acost = iv_ca_prune (data, ivs, cand, &tmp_delta);
04533 iv_ca_delta_commit (data, ivs, act_delta, false);
04534 act_delta = iv_ca_delta_join (act_delta, tmp_delta);
04535 }
04536
04537 if (acost < best_cost)
04538 {
04539 best_cost = acost;
04540 iv_ca_delta_free (&best_delta);
04541 best_delta = act_delta;
04542 }
04543 else
04544 iv_ca_delta_free (&act_delta);
04545 }
04546
04547 if (!best_delta)
04548 {
04549
04550 best_cost = iv_ca_prune (data, ivs, NULL, &best_delta);
04551
04552
04553 if (!best_delta)
04554 return false;
04555 }
04556
04557 iv_ca_delta_commit (data, ivs, best_delta, true);
04558 gcc_assert (best_cost == iv_ca_cost (ivs));
04559 iv_ca_delta_free (&best_delta);
04560 return true;
04561 }
04562
04563
04564
04565
04566
04567 static struct iv_ca *
04568 find_optimal_iv_set (struct ivopts_data *data)
04569 {
04570 unsigned i;
04571 struct iv_ca *set;
04572 struct iv_use *use;
04573
04574
04575 set = get_initial_solution (data);
04576 if (!set)
04577 {
04578 if (dump_file && (dump_flags & TDF_DETAILS))
04579 fprintf (dump_file, "Unable to substitute for ivs, failed.\n");
04580 return NULL;
04581 }
04582
04583 if (dump_file && (dump_flags & TDF_DETAILS))
04584 {
04585 fprintf (dump_file, "Initial set of candidates:\n");
04586 iv_ca_dump (data, dump_file, set);
04587 }
04588
04589 while (try_improve_iv_set (data, set))
04590 {
04591 if (dump_file && (dump_flags & TDF_DETAILS))
04592 {
04593 fprintf (dump_file, "Improved to:\n");
04594 iv_ca_dump (data, dump_file, set);
04595 }
04596 }
04597
04598 if (dump_file && (dump_flags & TDF_DETAILS))
04599 fprintf (dump_file, "Final cost %d\n\n", iv_ca_cost (set));
04600
04601 for (i = 0; i < n_iv_uses (data); i++)
04602 {
04603 use = iv_use (data, i);
04604 use->selected = iv_ca_cand_for_use (set, use)->cand;
04605 }
04606
04607 return set;
04608 }
04609
04610
04611
04612 static void
04613 create_new_iv (struct ivopts_data *data, struct iv_cand *cand)
04614 {
04615 block_stmt_iterator incr_pos;
04616 tree base;
04617 bool after = false;
04618
04619 if (!cand->iv)
04620 return;
04621
04622 switch (cand->pos)
04623 {
04624 case IP_NORMAL:
04625 incr_pos = bsi_last (ip_normal_pos (data->current_loop));
04626 break;
04627
04628 case IP_END:
04629 incr_pos = bsi_last (ip_end_pos (data->current_loop));
04630 after = true;
04631 break;
04632
04633 case IP_ORIGINAL:
04634
04635 name_info (data, cand->var_before)->preserve_biv = true;
04636 name_info (data, cand->var_after)->preserve_biv = true;
04637
04638
04639 find_interesting_uses_op (data, cand->var_after)->selected = cand;
04640
04641 return;
04642 }
04643
04644 gimple_add_tmp_var (cand->var_before);
04645 add_referenced_tmp_var (cand->var_before);
04646
04647 base = unshare_expr (cand->iv->base);
04648
04649 create_iv (base, cand->iv->step, cand->var_before, data->current_loop,
04650 &incr_pos, after, &cand->var_before, &cand->var_after);
04651 }
04652
04653
04654
04655 static void
04656 create_new_ivs (struct ivopts_data *data, struct iv_ca *set)
04657 {
04658 unsigned i;
04659 struct iv_cand *cand;
04660 bitmap_iterator bi;
04661
04662 EXECUTE_IF_SET_IN_BITMAP (set->cands, 0, i, bi)
04663 {
04664 cand = iv_cand (data, i);
04665 create_new_iv (data, cand);
04666 }
04667 }
04668
04669
04670
04671
04672 static void
04673 remove_statement (tree stmt, bool including_defined_name)
04674 {
04675 if (TREE_CODE (stmt) == PHI_NODE)
04676 {
04677 if (!including_defined_name)
04678 {
04679
04680 SET_PHI_RESULT (stmt, NULL);
04681 }
04682 remove_phi_node (stmt, NULL_TREE, bb_for_stmt (stmt));
04683 }
04684 else
04685 {
04686 block_stmt_iterator bsi = bsi_for_stmt (stmt);
04687
04688 bsi_remove (&bsi);
04689 }
04690 }
04691
04692
04693
04694
04695 static void
04696 rewrite_use_nonlinear_expr (struct ivopts_data *data,
04697 struct iv_use *use, struct iv_cand *cand)
04698 {
04699 tree comp;
04700 tree op, stmts, tgt, ass;
04701 block_stmt_iterator bsi, pbsi;
04702
04703
04704
04705
04706
04707 if (cand->pos == IP_ORIGINAL
04708 && TREE_CODE (use->stmt) == MODIFY_EXPR
04709 && TREE_OPERAND (use->stmt, 0) == cand->var_after)
04710 {
04711 op = TREE_OPERAND (use->stmt, 1);
04712
04713
04714
04715
04716 if ((TREE_CODE (op) == PLUS_EXPR
04717 || TREE_CODE (op) == MINUS_EXPR)
04718 && TREE_OPERAND (op, 0) == cand->var_before
04719 && TREE_CODE (TREE_OPERAND (op, 1)) == INTEGER_CST)
04720 return;
04721 }
04722
04723 comp = unshare_expr (get_computation (data->current_loop,
04724 use, cand));
04725 switch (TREE_CODE (use->stmt))
04726 {
04727 case PHI_NODE:
04728 tgt = PHI_RESULT (use->stmt);
04729
04730
04731 if (name_info (data, tgt)->preserve_biv)
04732 return;
04733
04734 pbsi = bsi = bsi_start (bb_for_stmt (use->stmt));
04735 while (!bsi_end_p (pbsi)
04736 && TREE_CODE (bsi_stmt (pbsi)) == LABEL_EXPR)
04737 {
04738 bsi = pbsi;
04739 bsi_next (&pbsi);
04740 }
04741 break;
04742
04743 case MODIFY_EXPR:
04744 tgt = TREE_OPERAND (use->stmt, 0);
04745 bsi = bsi_for_stmt (use->stmt);
04746 break;
04747
04748 default:
04749 gcc_unreachable ();
04750 }
04751
04752 op = force_gimple_operand (comp, &stmts, false, SSA_NAME_VAR (tgt));
04753
04754 if (TREE_CODE (use->stmt) == PHI_NODE)
04755 {
04756 if (stmts)
04757 bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
04758 ass = build2 (MODIFY_EXPR, TREE_TYPE (tgt), tgt, op);
04759 bsi_insert_after (&bsi, ass, BSI_NEW_STMT);
04760 remove_statement (use->stmt, false);
04761 SSA_NAME_DEF_STMT (tgt) = ass;
04762 }
04763 else
04764 {
04765 if (stmts)
04766 bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
04767 TREE_OPERAND (use->stmt, 1) = op;
04768 }
04769 }
04770
04771
04772
04773
04774 static bool
04775 idx_remove_ssa_names (tree base, tree *idx,
04776 void *data ATTRIBUTE_UNUSED)
04777 {
04778 tree *op;
04779
04780 if (TREE_CODE (*idx) == SSA_NAME)
04781 *idx = SSA_NAME_VAR (*idx);
04782
04783 if (TREE_CODE (base) == ARRAY_REF)
04784 {
04785 op = &TREE_OPERAND (base, 2);
04786 if (*op
04787 && TREE_CODE (*op) == SSA_NAME)
04788 *op = SSA_NAME_VAR (*op);
04789 op = &TREE_OPERAND (base, 3);
04790 if (*op
04791 && TREE_CODE (*op) == SSA_NAME)
04792 *op = SSA_NAME_VAR (*op);
04793 }
04794
04795 return true;
04796 }
04797
04798
04799
04800 static tree
04801 unshare_and_remove_ssa_names (tree ref)
04802 {
04803 ref = unshare_expr (ref);
04804 for_each_index (&ref, idx_remove_ssa_names, NULL);
04805
04806 return ref;
04807 }
04808
04809
04810
04811
04812 static void
04813 rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
04814 {
04815 tree bvar, var, new_var, new_name, copy, name;
04816 tree orig;
04817
04818 var = bvar = get_base_address (*op);
04819
04820 if (!var || TREE_CODE (with) != SSA_NAME)
04821 goto do_rewrite;
04822
04823 gcc_assert (TREE_CODE (var) != ALIGN_INDIRECT_REF);
04824 gcc_assert (TREE_CODE (var) != MISALIGNED_INDIRECT_REF);
04825 if (TREE_CODE (var) == INDIRECT_REF)
04826 var = TREE_OPERAND (var, 0);
04827 if (TREE_CODE (var) == SSA_NAME)
04828 {
04829 name = var;
04830 var = SSA_NAME_VAR (var);
04831 }
04832 else if (DECL_P (var))
04833 name = NULL_TREE;
04834 else
04835 goto do_rewrite;
04836
04837 if (var_ann (var)->type_mem_tag)
04838 var = var_ann (var)->type_mem_tag;
04839
04840
04841
04842
04843
04844
04845 copy = build2 (MODIFY_EXPR, void_type_node, NULL_TREE, with);
04846 if (name)
04847 new_name = duplicate_ssa_name (name, copy);
04848 else
04849 {
04850 new_var = create_tmp_var (TREE_TYPE (with), "ruatmp");
04851 add_referenced_tmp_var (new_var);
04852 var_ann (new_var)->type_mem_tag = var;
04853 new_name = make_ssa_name (new_var, copy);
04854 }
04855 TREE_OPERAND (copy, 0) = new_name;
04856 bsi_insert_before (bsi, copy, BSI_SAME_STMT);
04857 with = new_name;
04858
04859 do_rewrite:
04860
04861 orig = NULL_TREE;
04862 gcc_assert (TREE_CODE (*op) != ALIGN_INDIRECT_REF);
04863 gcc_assert (TREE_CODE (*op) != MISALIGNED_INDIRECT_REF);
04864
04865 if (TREE_CODE (*op) == INDIRECT_REF)
04866 orig = REF_ORIGINAL (*op);
04867 if (!orig)
04868 orig = unshare_and_remove_ssa_names (*op);
04869
04870 *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
04871
04872
04873 REF_ORIGINAL (*op) = orig;
04874 }
04875
04876
04877
04878 static void
04879 rewrite_use_address (struct ivopts_data *data,
04880 struct iv_use *use, struct iv_cand *cand)
04881 {
04882 tree comp = unshare_expr (get_computation (data->current_loop,
04883 use, cand));
04884 block_stmt_iterator bsi = bsi_for_stmt (use->stmt);
04885 tree stmts;
04886 tree op = force_gimple_operand (comp, &stmts, true, NULL_TREE);
04887
04888 if (stmts)
04889 bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
04890
04891 rewrite_address_base (&bsi, use->op_p, op);
04892 }
04893
04894
04895
04896
04897 static void
04898 rewrite_use_compare (struct ivopts_data *data,
04899 struct iv_use *use, struct iv_cand *cand)
04900 {
04901 tree comp;
04902 tree *op_p, cond, op, stmts, bound;
04903 block_stmt_iterator bsi = bsi_for_stmt (use->stmt);
04904 enum tree_code compare;
04905
04906 if (may_eliminate_iv (data, use, cand, &compare, &bound))
04907 {
04908 tree var = var_at_stmt (data->current_loop, cand, use->stmt);
04909 tree var_type = TREE_TYPE (var);
04910
04911 bound = fold_convert (var_type, bound);
04912 op = force_gimple_operand (unshare_expr (bound), &stmts,
04913 true, NULL_TREE);
04914
04915 if (stmts)
04916 bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
04917
04918 *use->op_p = build2 (compare, boolean_type_node, var, op);
04919 modify_stmt (use->stmt);
04920 return;
04921 }
04922
04923
04924
04925 comp = unshare_expr (get_computation (data->current_loop, use, cand));
04926
04927 cond = *use->op_p;
04928 op_p = &TREE_OPERAND (cond, 0);
04929 if (TREE_CODE (*op_p) != SSA_NAME
04930 || zero_p (get_iv (data, *op_p)->step))
04931 op_p = &TREE_OPERAND (cond, 1);
04932
04933 op = force_gimple_operand (comp, &stmts, true, SSA_NAME_VAR (*op_p));
04934 if (stmts)
04935 bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
04936
04937 *op_p = op;
04938 }
04939
04940
04941
04942
04943 static void
04944 protect_loop_closed_ssa_form_use (edge exit, use_operand_p op_p)
04945 {
04946 basic_block def_bb;
04947 struct loop *def_loop;
04948 tree phi, use;
04949
04950 use = USE_FROM_PTR (op_p);
04951 if (TREE_CODE (use) != SSA_NAME)
04952 return;
04953
04954 def_bb = bb_for_stmt (SSA_NAME_DEF_STMT (use));
04955 if (!def_bb)
04956 return;
04957
04958 def_loop = def_bb->loop_father;
04959 if (flow_bb_inside_loop_p (def_loop, exit->dest))
04960 return;
04961
04962
04963 for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
04964 if (PHI_ARG_DEF_FROM_EDGE (phi, exit) == use)
04965 break;
04966
04967 if (!phi)
04968 {
04969
04970 tree new_name = duplicate_ssa_name (use, NULL);
04971
04972 phi = create_phi_node (new_name, exit->dest);
04973 SSA_NAME_DEF_STMT (new_name) = phi;
04974 add_phi_arg (phi, use, exit);
04975 }
04976
04977 SET_USE (op_p, PHI_RESULT (phi));
04978 }
04979
04980
04981
04982
04983 static void
04984 protect_loop_closed_ssa_form (edge exit, tree stmt)
04985 {
04986 use_optype uses;
04987 vuse_optype vuses;
04988 v_may_def_optype v_may_defs;
04989 unsigned i;
04990
04991 get_stmt_operands (stmt);
04992
04993 uses = STMT_USE_OPS (stmt);
04994 for (i = 0; i < NUM_USES (uses); i++)
04995 protect_loop_closed_ssa_form_use (exit, USE_OP_PTR (uses, i));
04996
04997 vuses = STMT_VUSE_OPS (stmt);
04998 for (i = 0; i < NUM_VUSES (vuses); i++)
04999 protect_loop_closed_ssa_form_use (exit, VUSE_OP_PTR (vuses, i));
05000
05001 v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
05002 for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
05003 protect_loop_closed_ssa_form_use (exit, V_MAY_DEF_OP_PTR (v_may_defs, i));
05004 }
05005
05006
05007
05008
05009
05010 static void
05011 compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
05012 {
05013 tree_stmt_iterator tsi;
05014 block_stmt_iterator bsi;
05015 tree phi, stmt, def, next;
05016
05017 if (EDGE_COUNT (exit->dest->preds) > 1)
05018 split_loop_exit_edge (exit);
05019
05020 if (TREE_CODE (stmts) == STATEMENT_LIST)
05021 {
05022 for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
05023 protect_loop_closed_ssa_form (exit, tsi_stmt (tsi));
05024 }
05025 else
05026 protect_loop_closed_ssa_form (exit, stmts);
05027
05028
05029
05030 tree_block_label (exit->dest);
05031 bsi = bsi_after_labels (exit->dest);
05032 bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
05033
05034 if (!op)
05035 return;
05036
05037 for (phi = phi_nodes (exit->dest); phi; phi = next)
05038 {
05039 next = PHI_CHAIN (phi);
05040
05041 if (PHI_ARG_DEF_FROM_EDGE (phi, exit) == op)
05042 {
05043 def = PHI_RESULT (phi);
05044 remove_statement (phi, false);
05045 stmt = build2 (MODIFY_EXPR, TREE_TYPE (op),
05046 def, op);
05047 SSA_NAME_DEF_STMT (def) = stmt;
05048 bsi_insert_after (&bsi, stmt, BSI_CONTINUE_LINKING);
05049 }
05050 }
05051 }
05052
05053
05054
05055
05056 static void
05057 rewrite_use_outer (struct ivopts_data *data,
05058 struct iv_use *use, struct iv_cand *cand)
05059 {
05060 edge exit;
05061 tree value, op, stmts, tgt;
05062 tree phi;
05063
05064 switch (TREE_CODE (use->stmt))
05065 {
05066 case PHI_NODE:
05067 tgt = PHI_RESULT (use->stmt);
05068 break;
05069 case MODIFY_EXPR:
05070 tgt = TREE_OPERAND (use->stmt, 0);
05071 break;
05072 default:
05073 gcc_unreachable ();
05074 }
05075
05076 exit = single_dom_exit (data->current_loop);
05077
05078 if (exit)
05079 {
05080 if (!cand->iv)
05081 {
05082 bool ok = may_replace_final_value (data, use, &value);
05083 gcc_assert (ok);
05084 }
05085 else
05086 value = get_computation_at (data->current_loop,
05087 use, cand, last_stmt (exit->src));
05088
05089 value = unshare_expr (value);
05090 op = force_gimple_operand (value, &stmts, true, SSA_NAME_VAR (tgt));
05091
05092
05093
05094 if (stmts && name_info (data, tgt)->preserve_biv)
05095 return;
05096
05097 for (phi = phi_nodes (exit->dest); phi; phi = PHI_CHAIN (phi))
05098 {
05099 use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, exit);
05100
05101 if (USE_FROM_PTR (use_p) == tgt)
05102 SET_USE (use_p, op);
05103 }
05104
05105 if (stmts)
05106 compute_phi_arg_on_exit (exit, stmts, op);
05107
05108
05109
05110
05111 name_info (data, tgt)->iv->have_use_for = false;
05112 return;
05113 }
05114
05115
05116
05117 if (name_info (data, tgt)->preserve_biv)
05118 return;
05119
05120
05121 rewrite_use_nonlinear_expr (data, use, cand);
05122 }
05123
05124
05125
05126 static void
05127 rewrite_use (struct ivopts_data *data,
05128 struct iv_use *use, struct iv_cand *cand)
05129 {
05130 switch (use->type)
05131 {
05132 case USE_NONLINEAR_EXPR:
05133 rewrite_use_nonlinear_expr (data, use, cand);
05134 break;
05135
05136 case USE_OUTER:
05137 rewrite_use_outer (data, use, cand);
05138 break;
05139
05140 case USE_ADDRESS:
05141 rewrite_use_address (data, use, cand);
05142 break;
05143
05144 case USE_COMPARE:
05145 rewrite_use_compare (data, use, cand);
05146 break;
05147
05148 default:
05149 gcc_unreachable ();
05150 }
05151 modify_stmt (use->stmt);
05152 }
05153
05154
05155
05156 static void
05157 rewrite_uses (struct ivopts_data *data)
05158 {
05159 unsigned i;
05160 struct iv_cand *cand;
05161 struct iv_use *use;
05162
05163 for (i = 0; i < n_iv_uses (data); i++)
05164 {
05165 use = iv_use (data, i);
05166 cand = use->selected;
05167 gcc_assert (cand);
05168
05169 rewrite_use (data, use, cand);
05170 }
05171 }
05172
05173
05174
05175 static void
05176 remove_unused_ivs (struct ivopts_data *data)
05177 {
05178 unsigned j;
05179 bitmap_iterator bi;
05180
05181 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, j, bi)
05182 {
05183 struct version_info *info;
05184
05185 info = ver_info (data, j);
05186 if (info->iv
05187 && !zero_p (info->iv->step)
05188 && !info->inv_id
05189 && !info->iv->have_use_for
05190 && !info->preserve_biv)
05191 remove_statement (SSA_NAME_DEF_STMT (info->iv->ssa_name), true);
05192 }
05193 }
05194
05195
05196
05197 static void
05198 free_loop_data (struct ivopts_data *data)
05199 {
05200 unsigned i, j;
05201 bitmap_iterator bi;
05202
05203 htab_empty (data->niters);
05204
05205 EXECUTE_IF_SET_IN_BITMAP (data->relevant, 0, i, bi)
05206 {
05207 struct version_info *info;
05208
05209 info = ver_info (data, i);
05210 if (info->iv)
05211 free (info->iv);
05212 info->iv = NULL;
05213 info->has_nonlin_use = false;
05214 info->preserve_biv = false;
05215 info->inv_id = 0;
05216 }
05217 bitmap_clear (data->relevant);
05218 bitmap_clear (data->important_candidates);
05219
05220 for (i = 0; i < n_iv_uses (data); i++)
05221 {
05222 struct iv_use *use = iv_use (data, i);
05223
05224 free (use->iv);
05225 BITMAP_FREE (use->related_cands);
05226 for (j = 0; j < use->n_map_members; j++)
05227 if (use->cost_map[j].depends_on)
05228 BITMAP_FREE (use->cost_map[j].depends_on);
05229 free (use->cost_map);
05230 free (use);
05231 }
05232 VARRAY_POP_ALL (data->iv_uses);
05233
05234 for (i = 0; i < n_iv_cands (data); i++)
05235 {
05236 struct iv_cand *cand = iv_cand (data, i);
05237
05238 if (cand->iv)
05239 free (cand->iv);
05240 free (cand);
05241 }
05242 VARRAY_POP_ALL (data->iv_candidates);
05243
05244 if (data->version_info_size < num_ssa_names)
05245 {
05246 data->version_info_size = 2 * num_ssa_names;
05247 free (data->version_info);
05248 data->version_info = xcalloc (data->version_info_size,
05249 sizeof (struct version_info));
05250 }
05251
05252 data->max_inv_id = 0;
05253
05254 for (i = 0; i < VARRAY_ACTIVE_SIZE (decl_rtl_to_reset); i++)
05255 {
05256 tree obj = VARRAY_GENERIC_PTR_NOGC (decl_rtl_to_reset, i);
05257
05258 SET_DECL_RTL (obj, NULL_RTX);
05259 }
05260 VARRAY_POP_ALL (decl_rtl_to_reset);
05261 }
05262
05263
05264
05265
05266 static void
05267 tree_ssa_iv_optimize_finalize (struct loops *loops, struct ivopts_data *data)
05268 {
05269 unsigned i;
05270
05271 for (i = 1; i < loops->num; i++)
05272 if (loops->parray[i])
05273 {
05274 free (loops->parray[i]->aux);
05275 loops->parray[i]->aux = NULL;
05276 }
05277
05278 free_loop_data (data);
05279 free (data->version_info);
05280 BITMAP_FREE (data->relevant);
05281 BITMAP_FREE (data->important_candidates);
05282 htab_delete (data->niters);
05283
05284 VARRAY_FREE (decl_rtl_to_reset);
05285 VARRAY_FREE (data->iv_uses);
05286 VARRAY_FREE (data->iv_candidates);
05287 }
05288
05289
05290
05291 static bool
05292 tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop)
05293 {
05294 bool changed = false;
05295 struct iv_ca *iv_ca;
05296 edge exit;
05297
05298 data->current_loop = loop;
05299
05300 if (dump_file && (dump_flags & TDF_DETAILS))
05301 {
05302 fprintf (dump_file, "Processing loop %d\n", loop->num);
05303
05304 exit = single_dom_exit (loop);
05305 if (exit)
05306 {
05307 fprintf (dump_file, " single exit %d -> %d, exit condition ",
05308 exit->src->index, exit->dest->index);
05309 print_generic_expr (dump_file, last_stmt (exit->src), TDF_SLIM);
05310 fprintf (dump_file, "\n");
05311 }
05312
05313 fprintf (dump_file, "\n");
05314 }
05315
05316
05317
05318 if (!find_induction_variables (data))
05319 goto finish;
05320
05321
05322 find_interesting_uses (data);
05323 if (n_iv_uses (data) > MAX_CONSIDERED_USES)
05324 goto finish;
05325
05326
05327 find_iv_candidates (data);
05328
05329
05330 determine_use_iv_costs (data);
05331 determine_iv_costs (data);
05332 determine_set_costs (data);
05333
05334
05335 iv_ca = find_optimal_iv_set (data);
05336 if (!iv_ca)
05337 goto finish;
05338 changed = true;
05339
05340
05341 create_new_ivs (data, iv_ca);
05342 iv_ca_free (&iv_ca);
05343
05344
05345 rewrite_uses (data);
05346
05347
05348 remove_unused_ivs (data);
05349
05350
05351
05352
05353 scev_reset ();
05354
05355 finish:
05356 free_loop_data (data);
05357
05358 return changed;
05359 }
05360
05361
05362
05363 void
05364 tree_ssa_iv_optimize (struct loops *loops)
05365 {
05366 struct loop *loop;
05367 struct ivopts_data data;
05368
05369 tree_ssa_iv_optimize_init (loops, &data);
05370
05371
05372 loop = loops->tree_root;
05373 while (loop->inner)
05374 loop = loop->inner;
05375
05376 #ifdef ENABLE_CHECKING
05377 verify_loop_closed_ssa ();
05378 verify_stmts ();
05379 #endif
05380
05381
05382 while (loop != loops->tree_root)
05383 {
05384 if (dump_file && (dump_flags & TDF_DETAILS))
05385 flow_loop_dump (loop, dump_file, NULL, 1);
05386
05387 tree_ssa_iv_optimize_loop (&data, loop);
05388
05389 if (loop->next)
05390 {
05391 loop = loop->next;
05392 while (loop->inner)
05393 loop = loop->inner;
05394 }
05395 else
05396 loop = loop->outer;
05397 }
05398
05399 #ifdef ENABLE_CHECKING
05400 verify_loop_closed_ssa ();
05401 verify_stmts ();
05402 #endif
05403
05404 tree_ssa_iv_optimize_finalize (loops, &data);
05405 }