00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "tree.h"
00026 #include "rtl.h"
00027 #include "tm_p.h"
00028 #include "hard-reg-set.h"
00029 #include "basic-block.h"
00030 #include "output.h"
00031 #include "diagnostic.h"
00032 #include "tree-flow.h"
00033 #include "tree-dump.h"
00034 #include "timevar.h"
00035 #include "cfgloop.h"
00036 #include "domwalk.h"
00037 #include "params.h"
00038 #include "tree-pass.h"
00039 #include "flags.h"
00040 #include "real.h"
00041 #include "hashtab.h"
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 struct depend
00069 {
00070 tree stmt;
00071 struct depend *next;
00072 };
00073
00074
00075
00076 struct lim_aux_data
00077 {
00078 struct loop *max_loop;
00079
00080
00081 struct loop *tgt_loop;
00082
00083
00084 struct loop *always_executed_in;
00085
00086
00087
00088
00089 bool sm_done;
00090
00091
00092
00093 unsigned cost;
00094
00095
00096 struct depend *depends;
00097
00098
00099
00100
00101 };
00102
00103 #define LIM_DATA(STMT) (TREE_CODE (STMT) == PHI_NODE \
00104 ? NULL \
00105 : (struct lim_aux_data *) (stmt_ann (STMT)->common.aux))
00106
00107
00108
00109 struct mem_ref_loc
00110 {
00111 tree *ref;
00112 tree stmt;
00113 struct mem_ref_loc *next;
00114 };
00115
00116
00117
00118 struct mem_ref
00119 {
00120 tree mem;
00121 hashval_t hash;
00122 bool is_stored;
00123
00124 struct mem_ref_loc *locs;
00125 bitmap vops;
00126
00127 struct mem_ref *next;
00128
00129
00130
00131
00132
00133
00134 };
00135
00136
00137 #define LIM_EXPENSIVE ((unsigned) PARAM_VALUE (PARAM_LIM_EXPENSIVE))
00138
00139
00140
00141 #define ALWAYS_EXECUTED_IN(BB) ((struct loop *) (BB)->aux)
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 bool
00158 for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
00159 {
00160 tree *nxt, *idx;
00161
00162 for (; ; addr_p = nxt)
00163 {
00164 switch (TREE_CODE (*addr_p))
00165 {
00166 case SSA_NAME:
00167 return cbck (*addr_p, addr_p, data);
00168
00169 case MISALIGNED_INDIRECT_REF:
00170 case ALIGN_INDIRECT_REF:
00171 case INDIRECT_REF:
00172 nxt = &TREE_OPERAND (*addr_p, 0);
00173 return cbck (*addr_p, nxt, data);
00174
00175 case BIT_FIELD_REF:
00176 case VIEW_CONVERT_EXPR:
00177 case REALPART_EXPR:
00178 case IMAGPART_EXPR:
00179 nxt = &TREE_OPERAND (*addr_p, 0);
00180 break;
00181
00182 case COMPONENT_REF:
00183
00184
00185 idx = &TREE_OPERAND (*addr_p, 2);
00186 if (*idx
00187 && !cbck (*addr_p, idx, data))
00188 return false;
00189
00190 nxt = &TREE_OPERAND (*addr_p, 0);
00191 break;
00192
00193 case ARRAY_REF:
00194 case ARRAY_RANGE_REF:
00195 nxt = &TREE_OPERAND (*addr_p, 0);
00196 if (!cbck (*addr_p, &TREE_OPERAND (*addr_p, 1), data))
00197 return false;
00198 break;
00199
00200 case VAR_DECL:
00201 case PARM_DECL:
00202 case STRING_CST:
00203 case RESULT_DECL:
00204 case VECTOR_CST:
00205 case COMPLEX_CST:
00206 case INTEGER_CST:
00207 case REAL_CST:
00208 return true;
00209
00210 case TARGET_MEM_REF:
00211 idx = &TMR_BASE (*addr_p);
00212 if (*idx
00213 && !cbck (*addr_p, idx, data))
00214 return false;
00215 idx = &TMR_INDEX (*addr_p);
00216 if (*idx
00217 && !cbck (*addr_p, idx, data))
00218 return false;
00219 return true;
00220
00221 default:
00222 gcc_unreachable ();
00223 }
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 enum move_pos
00235 movement_possibility (tree stmt)
00236 {
00237 tree lhs, rhs;
00238
00239 if (flag_unswitch_loops
00240 && TREE_CODE (stmt) == COND_EXPR)
00241 {
00242
00243
00244 return MOVE_POSSIBLE;
00245 }
00246
00247 if (TREE_CODE (stmt) != MODIFY_EXPR)
00248 return MOVE_IMPOSSIBLE;
00249
00250 if (stmt_ends_bb_p (stmt))
00251 return MOVE_IMPOSSIBLE;
00252
00253 if (stmt_ann (stmt)->has_volatile_ops)
00254 return MOVE_IMPOSSIBLE;
00255
00256 lhs = TREE_OPERAND (stmt, 0);
00257 if (TREE_CODE (lhs) == SSA_NAME
00258 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
00259 return MOVE_IMPOSSIBLE;
00260
00261 rhs = TREE_OPERAND (stmt, 1);
00262
00263 if (TREE_SIDE_EFFECTS (rhs))
00264 return MOVE_IMPOSSIBLE;
00265
00266 if (TREE_CODE (lhs) != SSA_NAME
00267 || tree_could_trap_p (rhs))
00268 return MOVE_PRESERVE_EXECUTION;
00269
00270 if (get_call_expr_in (stmt))
00271 {
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 return MOVE_PRESERVE_EXECUTION;
00291 }
00292 return MOVE_POSSIBLE;
00293 }
00294
00295
00296
00297
00298
00299
00300 static struct loop *
00301 outermost_invariant_loop (tree def, struct loop *loop)
00302 {
00303 tree def_stmt;
00304 basic_block def_bb;
00305 struct loop *max_loop;
00306
00307 if (TREE_CODE (def) != SSA_NAME)
00308 return superloop_at_depth (loop, 1);
00309
00310 def_stmt = SSA_NAME_DEF_STMT (def);
00311 def_bb = bb_for_stmt (def_stmt);
00312 if (!def_bb)
00313 return superloop_at_depth (loop, 1);
00314
00315 max_loop = find_common_loop (loop, def_bb->loop_father);
00316
00317 if (LIM_DATA (def_stmt) && LIM_DATA (def_stmt)->max_loop)
00318 max_loop = find_common_loop (max_loop,
00319 LIM_DATA (def_stmt)->max_loop->outer);
00320 if (max_loop == loop)
00321 return NULL;
00322 max_loop = superloop_at_depth (loop, max_loop->depth + 1);
00323
00324 return max_loop;
00325 }
00326
00327
00328
00329
00330 static struct loop *
00331 outermost_invariant_loop_expr (tree expr, struct loop *loop)
00332 {
00333 enum tree_code_class class = TREE_CODE_CLASS (TREE_CODE (expr));
00334 unsigned i, nops;
00335 struct loop *max_loop = superloop_at_depth (loop, 1), *aloop;
00336
00337 if (TREE_CODE (expr) == SSA_NAME
00338 || TREE_CODE (expr) == INTEGER_CST
00339 || is_gimple_min_invariant (expr))
00340 return outermost_invariant_loop (expr, loop);
00341
00342 if (class != tcc_unary
00343 && class != tcc_binary
00344 && class != tcc_expression
00345 && class != tcc_comparison)
00346 return NULL;
00347
00348 nops = TREE_CODE_LENGTH (TREE_CODE (expr));
00349 for (i = 0; i < nops; i++)
00350 {
00351 aloop = outermost_invariant_loop_expr (TREE_OPERAND (expr, i), loop);
00352 if (!aloop)
00353 return NULL;
00354
00355 if (flow_loop_nested_p (max_loop, aloop))
00356 max_loop = aloop;
00357 }
00358
00359 return max_loop;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 static bool
00375 add_dependency (tree def, struct lim_aux_data *data, struct loop *loop,
00376 bool add_cost)
00377 {
00378 tree def_stmt = SSA_NAME_DEF_STMT (def);
00379 basic_block def_bb = bb_for_stmt (def_stmt);
00380 struct loop *max_loop;
00381 struct depend *dep;
00382
00383 if (!def_bb)
00384 return true;
00385
00386 max_loop = outermost_invariant_loop (def, loop);
00387 if (!max_loop)
00388 return false;
00389
00390 if (flow_loop_nested_p (data->max_loop, max_loop))
00391 data->max_loop = max_loop;
00392
00393 if (!LIM_DATA (def_stmt))
00394 return true;
00395
00396 if (add_cost
00397
00398
00399
00400
00401 && def_bb->loop_father == loop)
00402 data->cost += LIM_DATA (def_stmt)->cost;
00403
00404 dep = XNEW (struct depend);
00405 dep->stmt = def_stmt;
00406 dep->next = data->depends;
00407 data->depends = dep;
00408
00409 return true;
00410 }
00411
00412
00413
00414
00415
00416 static unsigned
00417 stmt_cost (tree stmt)
00418 {
00419 tree rhs;
00420 unsigned cost = 1;
00421
00422
00423 if (TREE_CODE (stmt) == COND_EXPR)
00424 return LIM_EXPENSIVE;
00425
00426 rhs = TREE_OPERAND (stmt, 1);
00427
00428
00429 if (stmt_references_memory_p (stmt))
00430 cost += 20;
00431
00432 switch (TREE_CODE (rhs))
00433 {
00434 case CALL_EXPR:
00435
00436
00437
00438
00439 rhs = get_callee_fndecl (rhs);
00440 if (DECL_BUILT_IN_CLASS (rhs) == BUILT_IN_NORMAL
00441 && DECL_FUNCTION_CODE (rhs) == BUILT_IN_CONSTANT_P)
00442 return 0;
00443
00444 cost += 20;
00445 break;
00446
00447 case MULT_EXPR:
00448 case TRUNC_DIV_EXPR:
00449 case CEIL_DIV_EXPR:
00450 case FLOOR_DIV_EXPR:
00451 case ROUND_DIV_EXPR:
00452 case EXACT_DIV_EXPR:
00453 case CEIL_MOD_EXPR:
00454 case FLOOR_MOD_EXPR:
00455 case ROUND_MOD_EXPR:
00456 case TRUNC_MOD_EXPR:
00457 case RDIV_EXPR:
00458
00459 cost += 20;
00460 break;
00461
00462 default:
00463 break;
00464 }
00465
00466 return cost;
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 static bool
00480 determine_max_movement (tree stmt, bool must_preserve_exec)
00481 {
00482 basic_block bb = bb_for_stmt (stmt);
00483 struct loop *loop = bb->loop_father;
00484 struct loop *level;
00485 struct lim_aux_data *lim_data = LIM_DATA (stmt);
00486 tree val;
00487 ssa_op_iter iter;
00488
00489 if (must_preserve_exec)
00490 level = ALWAYS_EXECUTED_IN (bb);
00491 else
00492 level = superloop_at_depth (loop, 1);
00493 lim_data->max_loop = level;
00494
00495 FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_USE)
00496 if (!add_dependency (val, lim_data, loop, true))
00497 return false;
00498
00499 FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
00500 if (!add_dependency (val, lim_data, loop, false))
00501 return false;
00502
00503 lim_data->cost += stmt_cost (stmt);
00504
00505 return true;
00506 }
00507
00508
00509
00510
00511
00512
00513 static void
00514 set_level (tree stmt, struct loop *orig_loop, struct loop *level)
00515 {
00516 struct loop *stmt_loop = bb_for_stmt (stmt)->loop_father;
00517 struct depend *dep;
00518
00519 stmt_loop = find_common_loop (orig_loop, stmt_loop);
00520 if (LIM_DATA (stmt) && LIM_DATA (stmt)->tgt_loop)
00521 stmt_loop = find_common_loop (stmt_loop,
00522 LIM_DATA (stmt)->tgt_loop->outer);
00523 if (flow_loop_nested_p (stmt_loop, level))
00524 return;
00525
00526 gcc_assert (LIM_DATA (stmt));
00527 gcc_assert (level == LIM_DATA (stmt)->max_loop
00528 || flow_loop_nested_p (LIM_DATA (stmt)->max_loop, level));
00529
00530 LIM_DATA (stmt)->tgt_loop = level;
00531 for (dep = LIM_DATA (stmt)->depends; dep; dep = dep->next)
00532 set_level (dep->stmt, orig_loop, level);
00533 }
00534
00535
00536
00537
00538
00539 static void
00540 set_profitable_level (tree stmt)
00541 {
00542 set_level (stmt, bb_for_stmt (stmt)->loop_father, LIM_DATA (stmt)->max_loop);
00543 }
00544
00545
00546
00547 static bool
00548 nonpure_call_p (tree stmt)
00549 {
00550 tree call = get_call_expr_in (stmt);
00551
00552 if (!call)
00553 return false;
00554
00555 return TREE_SIDE_EFFECTS (call) != 0;
00556 }
00557
00558
00559
00560 static void
00561 free_lim_aux_data (struct lim_aux_data *data)
00562 {
00563 struct depend *dep, *next;
00564
00565 for (dep = data->depends; dep; dep = next)
00566 {
00567 next = dep->next;
00568 free (dep);
00569 }
00570 free (data);
00571 }
00572
00573
00574
00575
00576
00577 static void
00578 determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
00579 basic_block bb)
00580 {
00581 enum move_pos pos;
00582 block_stmt_iterator bsi;
00583 tree stmt, rhs;
00584 bool maybe_never = ALWAYS_EXECUTED_IN (bb) == NULL;
00585 struct loop *outermost = ALWAYS_EXECUTED_IN (bb);
00586
00587 if (!bb->loop_father->outer)
00588 return;
00589
00590 if (dump_file && (dump_flags & TDF_DETAILS))
00591 fprintf (dump_file, "Basic block %d (loop %d -- depth %d):\n\n",
00592 bb->index, bb->loop_father->num, bb->loop_father->depth);
00593
00594 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00595 {
00596 stmt = bsi_stmt (bsi);
00597
00598 pos = movement_possibility (stmt);
00599 if (pos == MOVE_IMPOSSIBLE)
00600 {
00601 if (nonpure_call_p (stmt))
00602 {
00603 maybe_never = true;
00604 outermost = NULL;
00605 }
00606 continue;
00607 }
00608
00609
00610
00611 if (pos == MOVE_POSSIBLE
00612 && (rhs = TREE_OPERAND (stmt, 1)) != NULL
00613 && TREE_CODE (rhs) == RDIV_EXPR
00614 && flag_unsafe_math_optimizations
00615 && !flag_trapping_math
00616 && outermost_invariant_loop_expr (TREE_OPERAND (rhs, 1),
00617 loop_containing_stmt (stmt)) != NULL
00618 && outermost_invariant_loop_expr (rhs,
00619 loop_containing_stmt (stmt)) == NULL)
00620 {
00621 tree lhs, stmt1, stmt2, var, name;
00622
00623 lhs = TREE_OPERAND (stmt, 0);
00624
00625
00626 var = create_tmp_var (TREE_TYPE (rhs), "reciptmp");
00627 add_referenced_var (var);
00628
00629 stmt1 = build2 (MODIFY_EXPR, void_type_node, var,
00630 build2 (RDIV_EXPR, TREE_TYPE (rhs),
00631 build_real (TREE_TYPE (rhs), dconst1),
00632 TREE_OPERAND (rhs, 1)));
00633 name = make_ssa_name (var, stmt1);
00634 TREE_OPERAND (stmt1, 0) = name;
00635 stmt2 = build2 (MODIFY_EXPR, void_type_node, lhs,
00636 build2 (MULT_EXPR, TREE_TYPE (rhs),
00637 name, TREE_OPERAND (rhs, 0)));
00638
00639
00640
00641
00642 bsi_replace (&bsi, stmt1, true);
00643 bsi_insert_after (&bsi, stmt2, BSI_NEW_STMT);
00644 SSA_NAME_DEF_STMT (lhs) = stmt2;
00645
00646
00647 stmt = stmt1;
00648 }
00649
00650 stmt_ann (stmt)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
00651 LIM_DATA (stmt)->always_executed_in = outermost;
00652
00653 if (maybe_never && pos == MOVE_PRESERVE_EXECUTION)
00654 continue;
00655
00656 if (!determine_max_movement (stmt, pos == MOVE_PRESERVE_EXECUTION))
00657 {
00658 LIM_DATA (stmt)->max_loop = NULL;
00659 continue;
00660 }
00661
00662 if (dump_file && (dump_flags & TDF_DETAILS))
00663 {
00664 print_generic_stmt_indented (dump_file, stmt, 0, 2);
00665 fprintf (dump_file, " invariant up to level %d, cost %d.\n\n",
00666 LIM_DATA (stmt)->max_loop->depth,
00667 LIM_DATA (stmt)->cost);
00668 }
00669
00670 if (LIM_DATA (stmt)->cost >= LIM_EXPENSIVE)
00671 set_profitable_level (stmt);
00672 }
00673 }
00674
00675
00676
00677
00678
00679
00680 static void
00681 determine_invariantness (void)
00682 {
00683 struct dom_walk_data walk_data;
00684
00685 memset (&walk_data, 0, sizeof (struct dom_walk_data));
00686 walk_data.before_dom_children_before_stmts = determine_invariantness_stmt;
00687
00688 init_walk_dominator_tree (&walk_data);
00689 walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
00690 fini_walk_dominator_tree (&walk_data);
00691 }
00692
00693
00694
00695 void
00696 loop_commit_inserts (void)
00697 {
00698 unsigned old_last_basic_block, i;
00699 basic_block bb;
00700
00701 old_last_basic_block = last_basic_block;
00702 bsi_commit_edge_inserts ();
00703 for (i = old_last_basic_block; i < (unsigned) last_basic_block; i++)
00704 {
00705 bb = BASIC_BLOCK (i);
00706 add_bb_to_loop (bb,
00707 find_common_loop (single_pred (bb)->loop_father,
00708 single_succ (bb)->loop_father));
00709 }
00710 }
00711
00712
00713
00714
00715
00716 static void
00717 move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
00718 basic_block bb)
00719 {
00720 struct loop *level;
00721 block_stmt_iterator bsi;
00722 tree stmt;
00723 unsigned cost = 0;
00724
00725 if (!bb->loop_father->outer)
00726 return;
00727
00728 for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
00729 {
00730 stmt = bsi_stmt (bsi);
00731
00732 if (!LIM_DATA (stmt))
00733 {
00734 bsi_next (&bsi);
00735 continue;
00736 }
00737
00738 cost = LIM_DATA (stmt)->cost;
00739 level = LIM_DATA (stmt)->tgt_loop;
00740 free_lim_aux_data (LIM_DATA (stmt));
00741 stmt_ann (stmt)->common.aux = NULL;
00742
00743 if (!level)
00744 {
00745 bsi_next (&bsi);
00746 continue;
00747 }
00748
00749
00750
00751 if (TREE_CODE (stmt) == COND_EXPR)
00752 continue;
00753
00754 if (dump_file && (dump_flags & TDF_DETAILS))
00755 {
00756 fprintf (dump_file, "Moving statement\n");
00757 print_generic_stmt (dump_file, stmt, 0);
00758 fprintf (dump_file, "(cost %u) out of loop %d.\n\n",
00759 cost, level->num);
00760 }
00761 bsi_insert_on_edge (loop_preheader_edge (level), stmt);
00762 bsi_remove (&bsi, false);
00763 }
00764 }
00765
00766
00767
00768
00769 static void
00770 move_computations (void)
00771 {
00772 struct dom_walk_data walk_data;
00773
00774 memset (&walk_data, 0, sizeof (struct dom_walk_data));
00775 walk_data.before_dom_children_before_stmts = move_computations_stmt;
00776
00777 init_walk_dominator_tree (&walk_data);
00778 walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
00779 fini_walk_dominator_tree (&walk_data);
00780
00781 loop_commit_inserts ();
00782 if (need_ssa_update_p ())
00783 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
00784 }
00785
00786
00787
00788
00789 static bool
00790 may_move_till (tree ref, tree *index, void *data)
00791 {
00792 struct loop *loop = data, *max_loop;
00793
00794
00795
00796 if (TREE_CODE (ref) == ARRAY_REF)
00797 {
00798 tree step = array_ref_element_size (ref);
00799 tree lbound = array_ref_low_bound (ref);
00800
00801 max_loop = outermost_invariant_loop_expr (step, loop);
00802 if (!max_loop)
00803 return false;
00804
00805 max_loop = outermost_invariant_loop_expr (lbound, loop);
00806 if (!max_loop)
00807 return false;
00808 }
00809
00810 max_loop = outermost_invariant_loop (*index, loop);
00811 if (!max_loop)
00812 return false;
00813
00814 return true;
00815 }
00816
00817
00818
00819
00820 static void
00821 force_move_till_expr (tree expr, struct loop *orig_loop, struct loop *loop)
00822 {
00823 enum tree_code_class class = TREE_CODE_CLASS (TREE_CODE (expr));
00824 unsigned i, nops;
00825
00826 if (TREE_CODE (expr) == SSA_NAME)
00827 {
00828 tree stmt = SSA_NAME_DEF_STMT (expr);
00829 if (IS_EMPTY_STMT (stmt))
00830 return;
00831
00832 set_level (stmt, orig_loop, loop);
00833 return;
00834 }
00835
00836 if (class != tcc_unary
00837 && class != tcc_binary
00838 && class != tcc_expression
00839 && class != tcc_comparison)
00840 return;
00841
00842 nops = TREE_CODE_LENGTH (TREE_CODE (expr));
00843 for (i = 0; i < nops; i++)
00844 force_move_till_expr (TREE_OPERAND (expr, i), orig_loop, loop);
00845 }
00846
00847
00848
00849
00850
00851 struct fmt_data
00852 {
00853 struct loop *loop;
00854 struct loop *orig_loop;
00855 };
00856
00857 static bool
00858 force_move_till (tree ref, tree *index, void *data)
00859 {
00860 tree stmt;
00861 struct fmt_data *fmt_data = data;
00862
00863 if (TREE_CODE (ref) == ARRAY_REF)
00864 {
00865 tree step = array_ref_element_size (ref);
00866 tree lbound = array_ref_low_bound (ref);
00867
00868 force_move_till_expr (step, fmt_data->orig_loop, fmt_data->loop);
00869 force_move_till_expr (lbound, fmt_data->orig_loop, fmt_data->loop);
00870 }
00871
00872 if (TREE_CODE (*index) != SSA_NAME)
00873 return true;
00874
00875 stmt = SSA_NAME_DEF_STMT (*index);
00876 if (IS_EMPTY_STMT (stmt))
00877 return true;
00878
00879 set_level (stmt, fmt_data->orig_loop, fmt_data->loop);
00880
00881 return true;
00882 }
00883
00884
00885
00886
00887 static void
00888 record_mem_ref_loc (struct mem_ref_loc **mem_refs, tree stmt, tree *ref)
00889 {
00890 struct mem_ref_loc *aref = XNEW (struct mem_ref_loc);
00891
00892 aref->stmt = stmt;
00893 aref->ref = ref;
00894
00895 aref->next = *mem_refs;
00896 *mem_refs = aref;
00897 }
00898
00899
00900
00901 static void
00902 free_mem_ref_locs (struct mem_ref_loc *mem_refs)
00903 {
00904 struct mem_ref_loc *act;
00905
00906 while (mem_refs)
00907 {
00908 act = mem_refs;
00909 mem_refs = mem_refs->next;
00910 free (act);
00911 }
00912 }
00913
00914
00915
00916 static void
00917 rewrite_mem_refs (tree tmp_var, struct mem_ref_loc *mem_refs)
00918 {
00919 tree var;
00920 ssa_op_iter iter;
00921
00922 for (; mem_refs; mem_refs = mem_refs->next)
00923 {
00924 FOR_EACH_SSA_TREE_OPERAND (var, mem_refs->stmt, iter, SSA_OP_ALL_VIRTUALS)
00925 mark_sym_for_renaming (SSA_NAME_VAR (var));
00926
00927 *mem_refs->ref = tmp_var;
00928 update_stmt (mem_refs->stmt);
00929 }
00930 }
00931
00932
00933
00934 #define MAX_LSM_NAME_LENGTH 40
00935 static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
00936 static int lsm_tmp_name_length;
00937
00938
00939
00940 static void
00941 lsm_tmp_name_add (const char *s)
00942 {
00943 int l = strlen (s) + lsm_tmp_name_length;
00944 if (l > MAX_LSM_NAME_LENGTH)
00945 return;
00946
00947 strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
00948 lsm_tmp_name_length = l;
00949 }
00950
00951
00952
00953
00954 static void
00955 gen_lsm_tmp_name (tree ref)
00956 {
00957 const char *name;
00958
00959 switch (TREE_CODE (ref))
00960 {
00961 case MISALIGNED_INDIRECT_REF:
00962 case ALIGN_INDIRECT_REF:
00963 case INDIRECT_REF:
00964 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00965 lsm_tmp_name_add ("_");
00966 break;
00967
00968 case BIT_FIELD_REF:
00969 case VIEW_CONVERT_EXPR:
00970 case ARRAY_RANGE_REF:
00971 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00972 break;
00973
00974 case REALPART_EXPR:
00975 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00976 lsm_tmp_name_add ("_RE");
00977 break;
00978
00979 case IMAGPART_EXPR:
00980 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00981 lsm_tmp_name_add ("_IM");
00982 break;
00983
00984 case COMPONENT_REF:
00985 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00986 lsm_tmp_name_add ("_");
00987 name = get_name (TREE_OPERAND (ref, 1));
00988 if (!name)
00989 name = "F";
00990 lsm_tmp_name_add ("_");
00991 lsm_tmp_name_add (name);
00992
00993 case ARRAY_REF:
00994 gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
00995 lsm_tmp_name_add ("_I");
00996 break;
00997
00998 case SSA_NAME:
00999 ref = SSA_NAME_VAR (ref);
01000
01001
01002 case VAR_DECL:
01003 case PARM_DECL:
01004 name = get_name (ref);
01005 if (!name)
01006 name = "D";
01007 lsm_tmp_name_add (name);
01008 break;
01009
01010 case STRING_CST:
01011 lsm_tmp_name_add ("S");
01012 break;
01013
01014 case RESULT_DECL:
01015 lsm_tmp_name_add ("R");
01016 break;
01017
01018 default:
01019 gcc_unreachable ();
01020 }
01021 }
01022
01023
01024
01025
01026 static char *
01027 get_lsm_tmp_name (tree ref)
01028 {
01029 lsm_tmp_name_length = 0;
01030 gen_lsm_tmp_name (ref);
01031 lsm_tmp_name_add ("_lsm");
01032 return lsm_tmp_name;
01033 }
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 static void
01044 schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
01045 struct mem_ref_loc *mem_refs)
01046 {
01047 struct mem_ref_loc *aref;
01048 tree tmp_var;
01049 unsigned i;
01050 tree load, store;
01051 struct fmt_data fmt_data;
01052
01053 if (dump_file && (dump_flags & TDF_DETAILS))
01054 {
01055 fprintf (dump_file, "Executing store motion of ");
01056 print_generic_expr (dump_file, ref, 0);
01057 fprintf (dump_file, " from loop %d\n", loop->num);
01058 }
01059
01060 tmp_var = make_rename_temp (TREE_TYPE (ref),
01061 get_lsm_tmp_name (ref));
01062
01063 fmt_data.loop = loop;
01064 fmt_data.orig_loop = loop;
01065 for_each_index (&ref, force_move_till, &fmt_data);
01066
01067 rewrite_mem_refs (tmp_var, mem_refs);
01068 for (aref = mem_refs; aref; aref = aref->next)
01069 if (LIM_DATA (aref->stmt))
01070 LIM_DATA (aref->stmt)->sm_done = true;
01071
01072
01073 load = build2 (MODIFY_EXPR, void_type_node, tmp_var, ref);
01074 get_stmt_ann (load)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
01075 LIM_DATA (load)->max_loop = loop;
01076 LIM_DATA (load)->tgt_loop = loop;
01077
01078
01079
01080 bsi_insert_on_edge (loop_latch_edge (loop), load);
01081
01082 for (i = 0; i < n_exits; i++)
01083 {
01084 store = build2 (MODIFY_EXPR, void_type_node,
01085 unshare_expr (ref), tmp_var);
01086 bsi_insert_on_edge (exits[i], store);
01087 }
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 static void
01099 determine_lsm_ref (struct loop *loop, edge *exits, unsigned n_exits,
01100 bitmap clobbered_vops, struct mem_ref *ref)
01101 {
01102 struct mem_ref_loc *aref;
01103 struct loop *must_exec;
01104
01105
01106 if (!ref->is_stored)
01107 return;
01108
01109
01110
01111 if (bitmap_intersect_p (ref->vops, clobbered_vops))
01112 return;
01113
01114 if (tree_could_trap_p (ref->mem))
01115 {
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 for (aref = ref->locs; aref; aref = aref->next)
01128 {
01129 if (!LIM_DATA (aref->stmt))
01130 continue;
01131
01132 must_exec = LIM_DATA (aref->stmt)->always_executed_in;
01133 if (!must_exec)
01134 continue;
01135
01136 if (must_exec == loop
01137 || flow_loop_nested_p (must_exec, loop))
01138 break;
01139 }
01140
01141 if (!aref)
01142 return;
01143 }
01144
01145 schedule_sm (loop, exits, n_exits, ref->mem, ref->locs);
01146 }
01147
01148
01149
01150
01151
01152 static void
01153 hoist_memory_references (struct loop *loop, struct mem_ref *mem_refs,
01154 bitmap clobbered_vops, edge *exits, unsigned n_exits)
01155 {
01156 struct mem_ref *ref;
01157
01158 for (ref = mem_refs; ref; ref = ref->next)
01159 determine_lsm_ref (loop, exits, n_exits, clobbered_vops, ref);
01160 }
01161
01162
01163
01164
01165
01166 static bool
01167 loop_suitable_for_sm (struct loop *loop ATTRIBUTE_UNUSED, edge *exits,
01168 unsigned n_exits)
01169 {
01170 unsigned i;
01171
01172 for (i = 0; i < n_exits; i++)
01173 if (exits[i]->flags & EDGE_ABNORMAL)
01174 return false;
01175
01176 return true;
01177 }
01178
01179
01180
01181 static hashval_t
01182 memref_hash (const void *obj)
01183 {
01184 const struct mem_ref *mem = obj;
01185
01186 return mem->hash;
01187 }
01188
01189
01190
01191
01192 static int
01193 memref_eq (const void *obj1, const void *obj2)
01194 {
01195 const struct mem_ref *mem1 = obj1;
01196
01197 return operand_equal_p (mem1->mem, (tree) obj2, 0);
01198 }
01199
01200
01201
01202
01203
01204
01205 static void
01206 gather_mem_refs_stmt (struct loop *loop, htab_t mem_refs,
01207 bitmap clobbered_vops, tree stmt,
01208 struct mem_ref **mem_ref_list)
01209 {
01210 tree *lhs, *rhs, *mem = NULL;
01211 hashval_t hash;
01212 PTR *slot;
01213 struct mem_ref *ref = NULL;
01214 ssa_op_iter oi;
01215 tree vname;
01216 bool is_stored;
01217
01218 if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
01219 return;
01220
01221
01222 if (TREE_CODE (stmt) != MODIFY_EXPR)
01223 goto fail;
01224
01225 lhs = &TREE_OPERAND (stmt, 0);
01226 rhs = &TREE_OPERAND (stmt, 1);
01227
01228 if (TREE_CODE (*lhs) == SSA_NAME)
01229 {
01230 if (!is_gimple_addressable (*rhs))
01231 goto fail;
01232
01233 mem = rhs;
01234 is_stored = false;
01235 }
01236 else if (TREE_CODE (*rhs) == SSA_NAME
01237 || is_gimple_min_invariant (*rhs))
01238 {
01239 mem = lhs;
01240 is_stored = true;
01241 }
01242 else
01243 goto fail;
01244
01245
01246 if (!is_gimple_reg_type (TREE_TYPE (*mem))
01247 || TREE_THIS_VOLATILE (*mem))
01248 goto fail;
01249
01250
01251 if (!for_each_index (mem, may_move_till, loop))
01252 goto fail;
01253
01254 hash = iterative_hash_expr (*mem, 0);
01255 slot = htab_find_slot_with_hash (mem_refs, *mem, hash, INSERT);
01256
01257 if (*slot)
01258 ref = *slot;
01259 else
01260 {
01261 ref = XNEW (struct mem_ref);
01262 ref->mem = *mem;
01263 ref->hash = hash;
01264 ref->locs = NULL;
01265 ref->is_stored = false;
01266 ref->vops = BITMAP_ALLOC (NULL);
01267 ref->next = *mem_ref_list;
01268 *mem_ref_list = ref;
01269 *slot = ref;
01270 }
01271 ref->is_stored |= is_stored;
01272
01273 FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi,
01274 SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
01275 bitmap_set_bit (ref->vops, DECL_UID (SSA_NAME_VAR (vname)));
01276 record_mem_ref_loc (&ref->locs, stmt, mem);
01277 return;
01278
01279 fail:
01280 FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi,
01281 SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
01282 bitmap_set_bit (clobbered_vops, DECL_UID (SSA_NAME_VAR (vname)));
01283 }
01284
01285
01286
01287
01288
01289 static struct mem_ref *
01290 gather_mem_refs (struct loop *loop, bitmap clobbered_vops)
01291 {
01292 basic_block *body = get_loop_body (loop);
01293 block_stmt_iterator bsi;
01294 unsigned i;
01295 struct mem_ref *mem_ref_list = NULL;
01296 htab_t mem_refs = htab_create (100, memref_hash, memref_eq, NULL);
01297
01298 for (i = 0; i < loop->num_nodes; i++)
01299 {
01300 for (bsi = bsi_start (body[i]); !bsi_end_p (bsi); bsi_next (&bsi))
01301 gather_mem_refs_stmt (loop, mem_refs, clobbered_vops, bsi_stmt (bsi),
01302 &mem_ref_list);
01303 }
01304
01305 free (body);
01306
01307 htab_delete (mem_refs);
01308 return mem_ref_list;
01309 }
01310
01311
01312
01313
01314 static void
01315 find_more_ref_vops (struct mem_ref *mem_refs, bitmap clobbered_vops)
01316 {
01317 bitmap_head tmp, all_vops;
01318 struct mem_ref *ref;
01319
01320 bitmap_initialize (&tmp, &bitmap_default_obstack);
01321 bitmap_initialize (&all_vops, &bitmap_default_obstack);
01322
01323 for (ref = mem_refs; ref; ref = ref->next)
01324 {
01325
01326
01327 bitmap_and (&tmp, &all_vops, ref->vops);
01328 bitmap_ior_into (clobbered_vops, &tmp);
01329 bitmap_clear (&tmp);
01330
01331 bitmap_ior_into (&all_vops, ref->vops);
01332 }
01333
01334 bitmap_clear (&all_vops);
01335 }
01336
01337
01338
01339 static void
01340 free_mem_ref (struct mem_ref *ref)
01341 {
01342 free_mem_ref_locs (ref->locs);
01343 BITMAP_FREE (ref->vops);
01344 free (ref);
01345 }
01346
01347
01348
01349 static void
01350 free_mem_refs (struct mem_ref *refs)
01351 {
01352 struct mem_ref *ref, *next;
01353
01354 for (ref = refs; ref; ref = next)
01355 {
01356 next = ref->next;
01357 free_mem_ref (ref);
01358 }
01359 }
01360
01361
01362
01363
01364 static void
01365 determine_lsm_loop (struct loop *loop)
01366 {
01367 unsigned n_exits;
01368 edge *exits = get_loop_exit_edges (loop, &n_exits);
01369 bitmap clobbered_vops;
01370 struct mem_ref *mem_refs;
01371
01372 if (!loop_suitable_for_sm (loop, exits, n_exits))
01373 {
01374 free (exits);
01375 return;
01376 }
01377
01378
01379 clobbered_vops = BITMAP_ALLOC (NULL);
01380 mem_refs = gather_mem_refs (loop, clobbered_vops);
01381
01382
01383 find_more_ref_vops (mem_refs, clobbered_vops);
01384
01385
01386 hoist_memory_references (loop, mem_refs, clobbered_vops, exits, n_exits);
01387
01388 free_mem_refs (mem_refs);
01389 free (exits);
01390 BITMAP_FREE (clobbered_vops);
01391 }
01392
01393
01394
01395
01396 static void
01397 determine_lsm (struct loops *loops)
01398 {
01399 struct loop *loop;
01400
01401 if (!loops->tree_root->inner)
01402 return;
01403
01404
01405
01406
01407 loop = loops->tree_root->inner;
01408 while (1)
01409 {
01410 determine_lsm_loop (loop);
01411
01412 if (loop->inner)
01413 {
01414 loop = loop->inner;
01415 continue;
01416 }
01417 while (!loop->next)
01418 {
01419 loop = loop->outer;
01420 if (loop == loops->tree_root)
01421 {
01422 loop_commit_inserts ();
01423 return;
01424 }
01425 }
01426 loop = loop->next;
01427 }
01428 }
01429
01430
01431
01432
01433
01434
01435 static void
01436 fill_always_executed_in (struct loop *loop, sbitmap contains_call)
01437 {
01438 basic_block bb = NULL, *bbs, last = NULL;
01439 unsigned i;
01440 edge e;
01441 struct loop *inn_loop = loop;
01442
01443 if (!loop->header->aux)
01444 {
01445 bbs = get_loop_body_in_dom_order (loop);
01446
01447 for (i = 0; i < loop->num_nodes; i++)
01448 {
01449 edge_iterator ei;
01450 bb = bbs[i];
01451
01452 if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
01453 last = bb;
01454
01455 if (TEST_BIT (contains_call, bb->index))
01456 break;
01457
01458 FOR_EACH_EDGE (e, ei, bb->succs)
01459 if (!flow_bb_inside_loop_p (loop, e->dest))
01460 break;
01461 if (e)
01462 break;
01463
01464
01465
01466 if (bb->flags & BB_IRREDUCIBLE_LOOP)
01467 break;
01468
01469 if (!flow_bb_inside_loop_p (inn_loop, bb))
01470 break;
01471
01472 if (bb->loop_father->header == bb)
01473 {
01474 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
01475 break;
01476
01477
01478
01479 inn_loop = bb->loop_father;
01480 }
01481 }
01482
01483 while (1)
01484 {
01485 last->aux = loop;
01486 if (last == loop->header)
01487 break;
01488 last = get_immediate_dominator (CDI_DOMINATORS, last);
01489 }
01490
01491 free (bbs);
01492 }
01493
01494 for (loop = loop->inner; loop; loop = loop->next)
01495 fill_always_executed_in (loop, contains_call);
01496 }
01497
01498
01499
01500
01501 static void
01502 tree_ssa_lim_initialize (struct loops *loops)
01503 {
01504 sbitmap contains_call = sbitmap_alloc (last_basic_block);
01505 block_stmt_iterator bsi;
01506 struct loop *loop;
01507 basic_block bb;
01508
01509 sbitmap_zero (contains_call);
01510 FOR_EACH_BB (bb)
01511 {
01512 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01513 {
01514 if (nonpure_call_p (bsi_stmt (bsi)))
01515 break;
01516 }
01517
01518 if (!bsi_end_p (bsi))
01519 SET_BIT (contains_call, bb->index);
01520 }
01521
01522 for (loop = loops->tree_root->inner; loop; loop = loop->next)
01523 fill_always_executed_in (loop, contains_call);
01524
01525 sbitmap_free (contains_call);
01526 }
01527
01528
01529
01530 static void
01531 tree_ssa_lim_finalize (void)
01532 {
01533 basic_block bb;
01534
01535 FOR_EACH_BB (bb)
01536 {
01537 bb->aux = NULL;
01538 }
01539 }
01540
01541
01542
01543
01544 void
01545 tree_ssa_lim (struct loops *loops)
01546 {
01547 tree_ssa_lim_initialize (loops);
01548
01549
01550
01551 determine_invariantness ();
01552
01553
01554
01555
01556 determine_lsm (loops);
01557
01558
01559 move_computations ();
01560
01561 tree_ssa_lim_finalize ();
01562 }