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