00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "tree.h"
00028 #include "flags.h"
00029 #include "rtl.h"
00030 #include "tm_p.h"
00031 #include "ggc.h"
00032 #include "basic-block.h"
00033 #include "cfgloop.h"
00034 #include "output.h"
00035 #include "expr.h"
00036 #include "function.h"
00037 #include "diagnostic.h"
00038 #include "timevar.h"
00039 #include "tree-dump.h"
00040 #include "tree-flow.h"
00041 #include "domwalk.h"
00042 #include "real.h"
00043 #include "tree-pass.h"
00044 #include "tree-ssa-propagate.h"
00045 #include "langhooks.h"
00046 #include "params.h"
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 struct edge_info
00066 {
00067
00068
00069 tree lhs;
00070 tree rhs;
00071
00072
00073
00074
00075
00076 tree *cond_equivalences;
00077 unsigned int max_cond_equivalences;
00078 };
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 static htab_t avail_exprs;
00089
00090
00091
00092
00093
00094
00095 static VEC(tree,heap) *avail_exprs_stack;
00096
00097
00098
00099
00100
00101
00102
00103
00104 static VEC(tree,heap) *stmts_to_rescan;
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 struct expr_hash_elt
00118 {
00119
00120 tree lhs;
00121
00122
00123 tree rhs;
00124
00125
00126 tree stmt;
00127
00128
00129 hashval_t hash;
00130 };
00131
00132
00133
00134
00135
00136 static VEC(tree,heap) *const_and_copies_stack;
00137
00138
00139 static bool cfg_altered;
00140
00141
00142
00143 static bitmap need_eh_cleanup;
00144
00145
00146 struct opt_stats_d
00147 {
00148 long num_stmts;
00149 long num_exprs_considered;
00150 long num_re;
00151 long num_const_prop;
00152 long num_copy_prop;
00153 };
00154
00155 static struct opt_stats_d opt_stats;
00156
00157 struct eq_expr_value
00158 {
00159 tree src;
00160 tree dst;
00161 };
00162
00163
00164 static void optimize_stmt (struct dom_walk_data *,
00165 basic_block bb,
00166 block_stmt_iterator);
00167 static tree lookup_avail_expr (tree, bool);
00168 static hashval_t avail_expr_hash (const void *);
00169 static hashval_t real_avail_expr_hash (const void *);
00170 static int avail_expr_eq (const void *, const void *);
00171 static void htab_statistics (FILE *, htab_t);
00172 static void record_cond (tree, tree);
00173 static void record_const_or_copy (tree, tree);
00174 static void record_equality (tree, tree);
00175 static void record_equivalences_from_phis (basic_block);
00176 static void record_equivalences_from_incoming_edge (basic_block);
00177 static bool eliminate_redundant_computations (tree);
00178 static void record_equivalences_from_stmt (tree, int, stmt_ann_t);
00179 static void dom_thread_across_edge (struct dom_walk_data *, edge);
00180 static void dom_opt_finalize_block (struct dom_walk_data *, basic_block);
00181 static void dom_opt_initialize_block (struct dom_walk_data *, basic_block);
00182 static void propagate_to_outgoing_edges (struct dom_walk_data *, basic_block);
00183 static void remove_local_expressions_from_table (void);
00184 static void restore_vars_to_original_value (void);
00185 static edge single_incoming_edge_ignoring_loop_edges (basic_block);
00186
00187
00188
00189
00190
00191 static struct edge_info *
00192 allocate_edge_info (edge e)
00193 {
00194 struct edge_info *edge_info;
00195
00196 edge_info = XCNEW (struct edge_info);
00197
00198 e->aux = edge_info;
00199 return edge_info;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 static void
00209 free_all_edge_infos (void)
00210 {
00211 basic_block bb;
00212 edge_iterator ei;
00213 edge e;
00214
00215 FOR_EACH_BB (bb)
00216 {
00217 FOR_EACH_EDGE (e, ei, bb->preds)
00218 {
00219 struct edge_info *edge_info = (struct edge_info *) e->aux;
00220
00221 if (edge_info)
00222 {
00223 if (edge_info->cond_equivalences)
00224 free (edge_info->cond_equivalences);
00225 free (edge_info);
00226 e->aux = NULL;
00227 }
00228 }
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 static unsigned int
00239 tree_ssa_dominator_optimize (void)
00240 {
00241 struct dom_walk_data walk_data;
00242 unsigned int i;
00243 struct loops loops_info;
00244
00245 memset (&opt_stats, 0, sizeof (opt_stats));
00246
00247
00248 avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free);
00249 avail_exprs_stack = VEC_alloc (tree, heap, 20);
00250 const_and_copies_stack = VEC_alloc (tree, heap, 20);
00251 stmts_to_rescan = VEC_alloc (tree, heap, 20);
00252 need_eh_cleanup = BITMAP_ALLOC (NULL);
00253
00254
00255 walk_data.walk_stmts_backward = false;
00256 walk_data.dom_direction = CDI_DOMINATORS;
00257 walk_data.initialize_block_local_data = NULL;
00258 walk_data.before_dom_children_before_stmts = dom_opt_initialize_block;
00259 walk_data.before_dom_children_walk_stmts = optimize_stmt;
00260 walk_data.before_dom_children_after_stmts = propagate_to_outgoing_edges;
00261 walk_data.after_dom_children_before_stmts = NULL;
00262 walk_data.after_dom_children_walk_stmts = NULL;
00263 walk_data.after_dom_children_after_stmts = dom_opt_finalize_block;
00264
00265
00266
00267 walk_data.global_data = NULL;
00268 walk_data.block_local_data_size = 0;
00269 walk_data.interesting_blocks = NULL;
00270
00271
00272 init_walk_dominator_tree (&walk_data);
00273
00274 calculate_dominance_info (CDI_DOMINATORS);
00275
00276
00277
00278
00279 flow_loops_find (&loops_info);
00280 mark_loop_exit_edges (&loops_info);
00281 flow_loops_free (&loops_info);
00282
00283
00284
00285 cleanup_tree_cfg ();
00286 calculate_dominance_info (CDI_DOMINATORS);
00287
00288
00289
00290 mark_dfs_back_edges ();
00291
00292
00293 walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
00294
00295 {
00296 block_stmt_iterator bsi;
00297 basic_block bb;
00298 FOR_EACH_BB (bb)
00299 {
00300 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
00301 update_stmt_if_modified (bsi_stmt (bsi));
00302 }
00303 }
00304
00305
00306
00307
00308
00309
00310 update_ssa (TODO_update_ssa);
00311
00312 free_all_edge_infos ();
00313
00314
00315 cfg_altered |= thread_through_all_blocks ();
00316
00317
00318
00319 if (!bitmap_empty_p (need_eh_cleanup))
00320 {
00321 cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
00322 bitmap_zero (need_eh_cleanup);
00323 }
00324
00325 if (cfg_altered)
00326 free_dominance_info (CDI_DOMINATORS);
00327
00328
00329
00330
00331
00332 for (i = 0; i < num_ssa_names; i++)
00333 {
00334 tree name = ssa_name (i);
00335 tree value;
00336
00337 if (!name)
00338 continue;
00339
00340 value = SSA_NAME_VALUE (name);
00341 if (value && !is_gimple_min_invariant (value))
00342 SSA_NAME_VALUE (name) = NULL;
00343 }
00344
00345
00346 if (dump_file && (dump_flags & TDF_STATS))
00347 dump_dominator_optimization_stats (dump_file);
00348
00349
00350 htab_delete (avail_exprs);
00351
00352
00353 fini_walk_dominator_tree (&walk_data);
00354
00355
00356 BITMAP_FREE (need_eh_cleanup);
00357
00358 VEC_free (tree, heap, avail_exprs_stack);
00359 VEC_free (tree, heap, const_and_copies_stack);
00360 VEC_free (tree, heap, stmts_to_rescan);
00361 return 0;
00362 }
00363
00364 static bool
00365 gate_dominator (void)
00366 {
00367 return flag_tree_dom != 0;
00368 }
00369
00370 struct tree_opt_pass pass_dominator =
00371 {
00372 "dom",
00373 gate_dominator,
00374 tree_ssa_dominator_optimize,
00375 NULL,
00376 NULL,
00377 0,
00378 TV_TREE_SSA_DOMINATOR_OPTS,
00379 PROP_cfg | PROP_ssa | PROP_alias,
00380 0,
00381 PROP_smt_usage,
00382 0,
00383 TODO_dump_func
00384 | TODO_update_ssa
00385 | TODO_cleanup_cfg
00386 | TODO_verify_ssa
00387 | TODO_update_smt_usage,
00388 0
00389 };
00390
00391
00392
00393
00394
00395 static void
00396 canonicalize_comparison (tree condstmt)
00397 {
00398 tree cond = COND_EXPR_COND (condstmt);
00399 tree op0;
00400 tree op1;
00401 enum tree_code code = TREE_CODE (cond);
00402
00403 if (!COMPARISON_CLASS_P (cond))
00404 return;
00405
00406 op0 = TREE_OPERAND (cond, 0);
00407 op1 = TREE_OPERAND (cond, 1);
00408
00409
00410
00411
00412
00413
00414
00415 if (tree_swap_operands_p (op0, op1, false))
00416 {
00417
00418
00419 if (code == LT_EXPR
00420 || code == GT_EXPR
00421 || code == LE_EXPR
00422 || code == GE_EXPR)
00423 {
00424 TREE_SET_CODE (cond, swap_tree_comparison (code));
00425 swap_tree_operands (condstmt,
00426 &TREE_OPERAND (cond, 0),
00427 &TREE_OPERAND (cond, 1));
00428
00429
00430
00431
00432 if (TREE_CODE_CLASS (TREE_CODE (op0))
00433 != TREE_CODE_CLASS (TREE_CODE (op1)))
00434 update_stmt (condstmt);
00435 }
00436 }
00437 }
00438
00439
00440
00441
00442
00443 static void
00444 dom_opt_initialize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
00445 basic_block bb)
00446 {
00447 if (dump_file && (dump_flags & TDF_DETAILS))
00448 fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index);
00449
00450
00451
00452 VEC_safe_push (tree, heap, avail_exprs_stack, NULL_TREE);
00453 VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
00454
00455 record_equivalences_from_incoming_edge (bb);
00456
00457
00458 record_equivalences_from_phis (bb);
00459 }
00460
00461
00462
00463
00464 static void
00465 initialize_hash_element (tree expr, tree lhs, struct expr_hash_elt *element)
00466 {
00467
00468
00469
00470
00471
00472 if (COMPARISON_CLASS_P (expr) || TREE_CODE (expr) == TRUTH_NOT_EXPR)
00473 {
00474 element->stmt = NULL;
00475 element->rhs = expr;
00476 }
00477 else if (TREE_CODE (expr) == COND_EXPR)
00478 {
00479 element->stmt = expr;
00480 element->rhs = COND_EXPR_COND (expr);
00481 }
00482 else if (TREE_CODE (expr) == SWITCH_EXPR)
00483 {
00484 element->stmt = expr;
00485 element->rhs = SWITCH_COND (expr);
00486 }
00487 else if (TREE_CODE (expr) == RETURN_EXPR && TREE_OPERAND (expr, 0))
00488 {
00489 element->stmt = expr;
00490 element->rhs = TREE_OPERAND (TREE_OPERAND (expr, 0), 1);
00491 }
00492 else if (TREE_CODE (expr) == GOTO_EXPR)
00493 {
00494 element->stmt = expr;
00495 element->rhs = GOTO_DESTINATION (expr);
00496 }
00497 else
00498 {
00499 element->stmt = expr;
00500 element->rhs = TREE_OPERAND (expr, 1);
00501 }
00502
00503 element->lhs = lhs;
00504 element->hash = avail_expr_hash (element);
00505 }
00506
00507
00508
00509
00510 static void
00511 remove_local_expressions_from_table (void)
00512 {
00513
00514 while (VEC_length (tree, avail_exprs_stack) > 0)
00515 {
00516 struct expr_hash_elt element;
00517 tree expr = VEC_pop (tree, avail_exprs_stack);
00518
00519 if (expr == NULL_TREE)
00520 break;
00521
00522 initialize_hash_element (expr, NULL, &element);
00523 htab_remove_elt_with_hash (avail_exprs, &element, element.hash);
00524 }
00525 }
00526
00527
00528
00529
00530
00531 static void
00532 restore_vars_to_original_value (void)
00533 {
00534 while (VEC_length (tree, const_and_copies_stack) > 0)
00535 {
00536 tree prev_value, dest;
00537
00538 dest = VEC_pop (tree, const_and_copies_stack);
00539
00540 if (dest == NULL)
00541 break;
00542
00543 prev_value = VEC_pop (tree, const_and_copies_stack);
00544 SSA_NAME_VALUE (dest) = prev_value;
00545 }
00546 }
00547
00548
00549
00550 static tree
00551 simplify_stmt_for_jump_threading (tree stmt, tree within_stmt ATTRIBUTE_UNUSED)
00552 {
00553 return lookup_avail_expr (stmt, false);
00554 }
00555
00556
00557
00558
00559
00560 static void
00561 dom_thread_across_edge (struct dom_walk_data *walk_data, edge e)
00562 {
00563
00564 if (! walk_data->global_data)
00565 {
00566 tree dummy_cond = build2 (NE_EXPR, boolean_type_node,
00567 integer_zero_node, integer_zero_node);
00568 dummy_cond = build3 (COND_EXPR, void_type_node, dummy_cond, NULL, NULL);
00569 walk_data->global_data = dummy_cond;
00570 }
00571
00572 thread_across_edge (walk_data->global_data, e, false,
00573 &const_and_copies_stack,
00574 simplify_stmt_for_jump_threading);
00575 }
00576
00577
00578
00579
00580
00581 static void
00582 dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
00583 {
00584 tree last;
00585
00586
00587
00588
00589
00590
00591 if (single_succ_p (bb)
00592 && (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0
00593 && potentially_threadable_block (single_succ (bb)))
00594 {
00595 dom_thread_across_edge (walk_data, single_succ_edge (bb));
00596 }
00597 else if ((last = last_stmt (bb))
00598 && TREE_CODE (last) == COND_EXPR
00599 && (COMPARISON_CLASS_P (COND_EXPR_COND (last))
00600 || TREE_CODE (COND_EXPR_COND (last)) == SSA_NAME)
00601 && EDGE_COUNT (bb->succs) == 2
00602 && (EDGE_SUCC (bb, 0)->flags & EDGE_ABNORMAL) == 0
00603 && (EDGE_SUCC (bb, 1)->flags & EDGE_ABNORMAL) == 0)
00604 {
00605 edge true_edge, false_edge;
00606
00607 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
00608
00609
00610
00611 if (potentially_threadable_block (true_edge->dest))
00612 {
00613 struct edge_info *edge_info;
00614 unsigned int i;
00615
00616
00617
00618
00619 VEC_safe_push (tree, heap, avail_exprs_stack, NULL_TREE);
00620 VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
00621
00622 edge_info = (struct edge_info *) true_edge->aux;
00623
00624
00625
00626 if (edge_info)
00627 {
00628 tree *cond_equivalences = edge_info->cond_equivalences;
00629 tree lhs = edge_info->lhs;
00630 tree rhs = edge_info->rhs;
00631
00632
00633 if (lhs && TREE_CODE (lhs) == SSA_NAME)
00634 record_const_or_copy (lhs, rhs);
00635
00636
00637
00638 if (cond_equivalences)
00639 for (i = 0; i < edge_info->max_cond_equivalences; i += 2)
00640 {
00641 tree expr = cond_equivalences[i];
00642 tree value = cond_equivalences[i + 1];
00643
00644 record_cond (expr, value);
00645 }
00646 }
00647
00648 dom_thread_across_edge (walk_data, true_edge);
00649
00650
00651
00652 remove_local_expressions_from_table ();
00653 }
00654
00655
00656 if (potentially_threadable_block (false_edge->dest))
00657 {
00658 struct edge_info *edge_info;
00659 unsigned int i;
00660
00661 VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE);
00662 edge_info = (struct edge_info *) false_edge->aux;
00663
00664
00665
00666 if (edge_info)
00667 {
00668 tree *cond_equivalences = edge_info->cond_equivalences;
00669 tree lhs = edge_info->lhs;
00670 tree rhs = edge_info->rhs;
00671
00672
00673 if (lhs && TREE_CODE (lhs) == SSA_NAME)
00674 record_const_or_copy (lhs, rhs);
00675
00676
00677
00678 if (cond_equivalences)
00679 for (i = 0; i < edge_info->max_cond_equivalences; i += 2)
00680 {
00681 tree expr = cond_equivalences[i];
00682 tree value = cond_equivalences[i + 1];
00683
00684 record_cond (expr, value);
00685 }
00686 }
00687
00688
00689 dom_thread_across_edge (walk_data, false_edge);
00690
00691
00692
00693
00694 }
00695 }
00696
00697 remove_local_expressions_from_table ();
00698 restore_vars_to_original_value ();
00699
00700
00701
00702 while (VEC_length (tree, stmts_to_rescan) > 0)
00703 {
00704 tree stmt = VEC_last (tree, stmts_to_rescan);
00705 basic_block stmt_bb = bb_for_stmt (stmt);
00706
00707 if (stmt_bb != bb)
00708 break;
00709
00710 VEC_pop (tree, stmts_to_rescan);
00711 mark_new_vars_to_rename (stmt);
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720
00721 static void
00722 record_equivalences_from_phis (basic_block bb)
00723 {
00724 tree phi;
00725
00726 for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00727 {
00728 tree lhs = PHI_RESULT (phi);
00729 tree rhs = NULL;
00730 int i;
00731
00732 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
00733 {
00734 tree t = PHI_ARG_DEF (phi, i);
00735
00736
00737
00738
00739 if (lhs == t)
00740 continue;
00741
00742
00743
00744 if (rhs == NULL)
00745 rhs = t;
00746
00747
00748
00749 else if (! operand_equal_for_phi_arg_p (rhs, t))
00750 break;
00751 }
00752
00753
00754
00755 if (!rhs)
00756 rhs = lhs;
00757
00758
00759
00760
00761
00762
00763
00764 if (i == PHI_NUM_ARGS (phi)
00765 && may_propagate_copy (lhs, rhs))
00766 SSA_NAME_VALUE (lhs) = rhs;
00767 }
00768 }
00769
00770
00771
00772 static edge
00773 single_incoming_edge_ignoring_loop_edges (basic_block bb)
00774 {
00775 edge retval = NULL;
00776 edge e;
00777 edge_iterator ei;
00778
00779 FOR_EACH_EDGE (e, ei, bb->preds)
00780 {
00781
00782
00783 if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
00784 continue;
00785
00786
00787
00788 if (retval)
00789 return NULL;
00790
00791
00792
00793 retval = e;
00794 }
00795
00796 return retval;
00797 }
00798
00799
00800
00801
00802 static void
00803 record_equivalences_from_incoming_edge (basic_block bb)
00804 {
00805 edge e;
00806 basic_block parent;
00807 struct edge_info *edge_info;
00808
00809
00810
00811
00812 parent = get_immediate_dominator (CDI_DOMINATORS, bb);
00813
00814 e = single_incoming_edge_ignoring_loop_edges (bb);
00815
00816
00817
00818 if (e && e->src == parent)
00819 {
00820 unsigned int i;
00821
00822 edge_info = (struct edge_info *) e->aux;
00823
00824 if (edge_info)
00825 {
00826 tree lhs = edge_info->lhs;
00827 tree rhs = edge_info->rhs;
00828 tree *cond_equivalences = edge_info->cond_equivalences;
00829
00830 if (lhs)
00831 record_equality (lhs, rhs);
00832
00833 if (cond_equivalences)
00834 {
00835 for (i = 0; i < edge_info->max_cond_equivalences; i += 2)
00836 {
00837 tree expr = cond_equivalences[i];
00838 tree value = cond_equivalences[i + 1];
00839
00840 record_cond (expr, value);
00841 }
00842 }
00843 }
00844 }
00845 }
00846
00847
00848
00849 void
00850 dump_dominator_optimization_stats (FILE *file)
00851 {
00852 long n_exprs;
00853
00854 fprintf (file, "Total number of statements: %6ld\n\n",
00855 opt_stats.num_stmts);
00856 fprintf (file, "Exprs considered for dominator optimizations: %6ld\n",
00857 opt_stats.num_exprs_considered);
00858
00859 n_exprs = opt_stats.num_exprs_considered;
00860 if (n_exprs == 0)
00861 n_exprs = 1;
00862
00863 fprintf (file, " Redundant expressions eliminated: %6ld (%.0f%%)\n",
00864 opt_stats.num_re, PERCENT (opt_stats.num_re,
00865 n_exprs));
00866 fprintf (file, " Constants propagated: %6ld\n",
00867 opt_stats.num_const_prop);
00868 fprintf (file, " Copies propagated: %6ld\n",
00869 opt_stats.num_copy_prop);
00870
00871 fprintf (file, "\nHash table statistics:\n");
00872
00873 fprintf (file, " avail_exprs: ");
00874 htab_statistics (file, avail_exprs);
00875 }
00876
00877
00878
00879
00880 void
00881 debug_dominator_optimization_stats (void)
00882 {
00883 dump_dominator_optimization_stats (stderr);
00884 }
00885
00886
00887
00888
00889 static void
00890 htab_statistics (FILE *file, htab_t htab)
00891 {
00892 fprintf (file, "size %ld, %ld elements, %f collision/search ratio\n",
00893 (long) htab_size (htab),
00894 (long) htab_elements (htab),
00895 htab_collisions (htab));
00896 }
00897
00898
00899
00900
00901 static void
00902 record_cond (tree cond, tree value)
00903 {
00904 struct expr_hash_elt *element = XCNEW (struct expr_hash_elt);
00905 void **slot;
00906
00907 initialize_hash_element (cond, value, element);
00908
00909 slot = htab_find_slot_with_hash (avail_exprs, (void *)element,
00910 element->hash, INSERT);
00911 if (*slot == NULL)
00912 {
00913 *slot = (void *) element;
00914 VEC_safe_push (tree, heap, avail_exprs_stack, cond);
00915 }
00916 else
00917 free (element);
00918 }
00919
00920
00921
00922
00923
00924 static void
00925 build_and_record_new_cond (enum tree_code new_code, tree op0, tree op1, tree *p)
00926 {
00927 *p = build2 (new_code, boolean_type_node, op0, op1);
00928 p++;
00929 *p = boolean_true_node;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938 static void
00939 record_conditions (struct edge_info *edge_info, tree cond, tree inverted)
00940 {
00941 tree op0, op1;
00942
00943 if (!COMPARISON_CLASS_P (cond))
00944 return;
00945
00946 op0 = TREE_OPERAND (cond, 0);
00947 op1 = TREE_OPERAND (cond, 1);
00948
00949 switch (TREE_CODE (cond))
00950 {
00951 case LT_EXPR:
00952 case GT_EXPR:
00953 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
00954 {
00955 edge_info->max_cond_equivalences = 12;
00956 edge_info->cond_equivalences = XNEWVEC (tree, 12);
00957 build_and_record_new_cond (ORDERED_EXPR, op0, op1,
00958 &edge_info->cond_equivalences[8]);
00959 build_and_record_new_cond (LTGT_EXPR, op0, op1,
00960 &edge_info->cond_equivalences[10]);
00961 }
00962 else
00963 {
00964 edge_info->max_cond_equivalences = 8;
00965 edge_info->cond_equivalences = XNEWVEC (tree, 8);
00966 }
00967
00968 build_and_record_new_cond ((TREE_CODE (cond) == LT_EXPR
00969 ? LE_EXPR : GE_EXPR),
00970 op0, op1, &edge_info->cond_equivalences[4]);
00971 build_and_record_new_cond (NE_EXPR, op0, op1,
00972 &edge_info->cond_equivalences[6]);
00973 break;
00974
00975 case GE_EXPR:
00976 case LE_EXPR:
00977 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
00978 {
00979 edge_info->max_cond_equivalences = 6;
00980 edge_info->cond_equivalences = XNEWVEC (tree, 6);
00981 build_and_record_new_cond (ORDERED_EXPR, op0, op1,
00982 &edge_info->cond_equivalences[4]);
00983 }
00984 else
00985 {
00986 edge_info->max_cond_equivalences = 4;
00987 edge_info->cond_equivalences = XNEWVEC (tree, 4);
00988 }
00989 break;
00990
00991 case EQ_EXPR:
00992 if (FLOAT_TYPE_P (TREE_TYPE (op0)))
00993 {
00994 edge_info->max_cond_equivalences = 10;
00995 edge_info->cond_equivalences = XNEWVEC (tree, 10);
00996 build_and_record_new_cond (ORDERED_EXPR, op0, op1,
00997 &edge_info->cond_equivalences[8]);
00998 }
00999 else
01000 {
01001 edge_info->max_cond_equivalences = 8;
01002 edge_info->cond_equivalences = XNEWVEC (tree, 8);
01003 }
01004 build_and_record_new_cond (LE_EXPR, op0, op1,
01005 &edge_info->cond_equivalences[4]);
01006 build_and_record_new_cond (GE_EXPR, op0, op1,
01007 &edge_info->cond_equivalences[6]);
01008 break;
01009
01010 case UNORDERED_EXPR:
01011 edge_info->max_cond_equivalences = 16;
01012 edge_info->cond_equivalences = XNEWVEC (tree, 16);
01013 build_and_record_new_cond (NE_EXPR, op0, op1,
01014 &edge_info->cond_equivalences[4]);
01015 build_and_record_new_cond (UNLE_EXPR, op0, op1,
01016 &edge_info->cond_equivalences[6]);
01017 build_and_record_new_cond (UNGE_EXPR, op0, op1,
01018 &edge_info->cond_equivalences[8]);
01019 build_and_record_new_cond (UNEQ_EXPR, op0, op1,
01020 &edge_info->cond_equivalences[10]);
01021 build_and_record_new_cond (UNLT_EXPR, op0, op1,
01022 &edge_info->cond_equivalences[12]);
01023 build_and_record_new_cond (UNGT_EXPR, op0, op1,
01024 &edge_info->cond_equivalences[14]);
01025 break;
01026
01027 case UNLT_EXPR:
01028 case UNGT_EXPR:
01029 edge_info->max_cond_equivalences = 8;
01030 edge_info->cond_equivalences = XNEWVEC (tree, 8);
01031 build_and_record_new_cond ((TREE_CODE (cond) == UNLT_EXPR
01032 ? UNLE_EXPR : UNGE_EXPR),
01033 op0, op1, &edge_info->cond_equivalences[4]);
01034 build_and_record_new_cond (NE_EXPR, op0, op1,
01035 &edge_info->cond_equivalences[6]);
01036 break;
01037
01038 case UNEQ_EXPR:
01039 edge_info->max_cond_equivalences = 8;
01040 edge_info->cond_equivalences = XNEWVEC (tree, 8);
01041 build_and_record_new_cond (UNLE_EXPR, op0, op1,
01042 &edge_info->cond_equivalences[4]);
01043 build_and_record_new_cond (UNGE_EXPR, op0, op1,
01044 &edge_info->cond_equivalences[6]);
01045 break;
01046
01047 case LTGT_EXPR:
01048 edge_info->max_cond_equivalences = 8;
01049 edge_info->cond_equivalences = XNEWVEC (tree, 8);
01050 build_and_record_new_cond (NE_EXPR, op0, op1,
01051 &edge_info->cond_equivalences[4]);
01052 build_and_record_new_cond (ORDERED_EXPR, op0, op1,
01053 &edge_info->cond_equivalences[6]);
01054 break;
01055
01056 default:
01057 edge_info->max_cond_equivalences = 4;
01058 edge_info->cond_equivalences = XNEWVEC (tree, 4);
01059 break;
01060 }
01061
01062
01063
01064 edge_info->cond_equivalences[0] = cond;
01065 edge_info->cond_equivalences[1] = boolean_true_node;
01066 edge_info->cond_equivalences[2] = inverted;
01067 edge_info->cond_equivalences[3] = boolean_false_node;
01068 }
01069
01070
01071
01072
01073 static void
01074 record_const_or_copy_1 (tree x, tree y, tree prev_x)
01075 {
01076 SSA_NAME_VALUE (x) = y;
01077
01078 VEC_reserve (tree, heap, const_and_copies_stack, 2);
01079 VEC_quick_push (tree, const_and_copies_stack, prev_x);
01080 VEC_quick_push (tree, const_and_copies_stack, x);
01081 }
01082
01083
01084
01085
01086
01087
01088
01089
01090 int
01091 loop_depth_of_name (tree x)
01092 {
01093 tree defstmt;
01094 basic_block defbb;
01095
01096
01097 if (TREE_CODE (x) != SSA_NAME)
01098 return 0;
01099
01100
01101
01102
01103 defstmt = SSA_NAME_DEF_STMT (x);
01104 defbb = bb_for_stmt (defstmt);
01105 if (!defbb)
01106 return 0;
01107
01108 return defbb->loop_depth;
01109 }
01110
01111
01112
01113
01114
01115 static void
01116 record_const_or_copy (tree x, tree y)
01117 {
01118 tree prev_x = SSA_NAME_VALUE (x);
01119
01120 if (TREE_CODE (y) == SSA_NAME)
01121 {
01122 tree tmp = SSA_NAME_VALUE (y);
01123 if (tmp)
01124 y = tmp;
01125 }
01126
01127 record_const_or_copy_1 (x, y, prev_x);
01128 }
01129
01130
01131
01132
01133 static void
01134 record_equality (tree x, tree y)
01135 {
01136 tree prev_x = NULL, prev_y = NULL;
01137
01138 if (TREE_CODE (x) == SSA_NAME)
01139 prev_x = SSA_NAME_VALUE (x);
01140 if (TREE_CODE (y) == SSA_NAME)
01141 prev_y = SSA_NAME_VALUE (y);
01142
01143
01144
01145
01146
01147 if (TREE_INVARIANT (y))
01148 ;
01149 else if (TREE_INVARIANT (x) || (loop_depth_of_name (x) <= loop_depth_of_name (y)))
01150 prev_x = x, x = y, y = prev_x, prev_x = prev_y;
01151 else if (prev_x && TREE_INVARIANT (prev_x))
01152 x = y, y = prev_x, prev_x = prev_y;
01153 else if (prev_y && TREE_CODE (prev_y) != VALUE_HANDLE)
01154 y = prev_y;
01155
01156
01157 if (TREE_CODE (x) != SSA_NAME)
01158 return;
01159
01160
01161
01162
01163
01164 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (x)))
01165 && (TREE_CODE (y) != REAL_CST
01166 || REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (y))))
01167 return;
01168
01169 record_const_or_copy_1 (x, y, prev_x);
01170 }
01171
01172
01173
01174
01175
01176
01177
01178 static bool
01179 simple_iv_increment_p (tree stmt)
01180 {
01181 tree lhs, rhs, preinc, phi;
01182 unsigned i;
01183
01184 if (TREE_CODE (stmt) != MODIFY_EXPR)
01185 return false;
01186
01187 lhs = TREE_OPERAND (stmt, 0);
01188 if (TREE_CODE (lhs) != SSA_NAME)
01189 return false;
01190
01191 rhs = TREE_OPERAND (stmt, 1);
01192
01193 if (TREE_CODE (rhs) != PLUS_EXPR
01194 && TREE_CODE (rhs) != MINUS_EXPR)
01195 return false;
01196
01197 preinc = TREE_OPERAND (rhs, 0);
01198 if (TREE_CODE (preinc) != SSA_NAME)
01199 return false;
01200
01201 phi = SSA_NAME_DEF_STMT (preinc);
01202 if (TREE_CODE (phi) != PHI_NODE)
01203 return false;
01204
01205 for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++)
01206 if (PHI_ARG_DEF (phi, i) == lhs)
01207 return true;
01208
01209 return false;
01210 }
01211
01212
01213
01214
01215
01216
01217
01218 static void
01219 cprop_into_successor_phis (basic_block bb)
01220 {
01221 edge e;
01222 edge_iterator ei;
01223
01224 FOR_EACH_EDGE (e, ei, bb->succs)
01225 {
01226 tree phi;
01227 int indx;
01228
01229
01230
01231 if (e->flags & EDGE_ABNORMAL)
01232 continue;
01233
01234 phi = phi_nodes (e->dest);
01235 if (! phi)
01236 continue;
01237
01238 indx = e->dest_idx;
01239 for ( ; phi; phi = PHI_CHAIN (phi))
01240 {
01241 tree new;
01242 use_operand_p orig_p;
01243 tree orig;
01244
01245
01246
01247 orig_p = PHI_ARG_DEF_PTR (phi, indx);
01248 orig = USE_FROM_PTR (orig_p);
01249 if (TREE_CODE (orig) != SSA_NAME)
01250 continue;
01251
01252
01253
01254 new = SSA_NAME_VALUE (orig);
01255 if (new
01256 && new != orig
01257 && (TREE_CODE (new) == SSA_NAME
01258 || is_gimple_min_invariant (new))
01259 && may_propagate_copy (orig, new))
01260 propagate_value (orig_p, new);
01261 }
01262 }
01263 }
01264
01265
01266
01267
01268 static void
01269 record_edge_info (basic_block bb)
01270 {
01271 block_stmt_iterator bsi = bsi_last (bb);
01272 struct edge_info *edge_info;
01273
01274 if (! bsi_end_p (bsi))
01275 {
01276 tree stmt = bsi_stmt (bsi);
01277
01278 if (stmt && TREE_CODE (stmt) == SWITCH_EXPR)
01279 {
01280 tree cond = SWITCH_COND (stmt);
01281
01282 if (TREE_CODE (cond) == SSA_NAME)
01283 {
01284 tree labels = SWITCH_LABELS (stmt);
01285 int i, n_labels = TREE_VEC_LENGTH (labels);
01286 tree *info = XCNEWVEC (tree, last_basic_block);
01287 edge e;
01288 edge_iterator ei;
01289
01290 for (i = 0; i < n_labels; i++)
01291 {
01292 tree label = TREE_VEC_ELT (labels, i);
01293 basic_block target_bb = label_to_block (CASE_LABEL (label));
01294
01295 if (CASE_HIGH (label)
01296 || !CASE_LOW (label)
01297 || info[target_bb->index])
01298 info[target_bb->index] = error_mark_node;
01299 else
01300 info[target_bb->index] = label;
01301 }
01302
01303 FOR_EACH_EDGE (e, ei, bb->succs)
01304 {
01305 basic_block target_bb = e->dest;
01306 tree node = info[target_bb->index];
01307
01308 if (node != NULL && node != error_mark_node)
01309 {
01310 tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
01311 edge_info = allocate_edge_info (e);
01312 edge_info->lhs = cond;
01313 edge_info->rhs = x;
01314 }
01315 }
01316 free (info);
01317 }
01318 }
01319
01320
01321 if (stmt && TREE_CODE (stmt) == COND_EXPR)
01322 {
01323 tree cond = COND_EXPR_COND (stmt);
01324 edge true_edge;
01325 edge false_edge;
01326
01327 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
01328
01329
01330
01331 if (SSA_VAR_P (cond))
01332 {
01333 struct edge_info *edge_info;
01334
01335 edge_info = allocate_edge_info (true_edge);
01336 edge_info->lhs = cond;
01337 edge_info->rhs = constant_boolean_node (1, TREE_TYPE (cond));
01338
01339 edge_info = allocate_edge_info (false_edge);
01340 edge_info->lhs = cond;
01341 edge_info->rhs = constant_boolean_node (0, TREE_TYPE (cond));
01342 }
01343
01344 else if (COMPARISON_CLASS_P (cond))
01345 {
01346 tree op0 = TREE_OPERAND (cond, 0);
01347 tree op1 = TREE_OPERAND (cond, 1);
01348
01349
01350
01351
01352 if ((TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
01353 && TREE_CODE (op0) == SSA_NAME
01354 && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
01355 && is_gimple_min_invariant (op1))
01356 {
01357 if (TREE_CODE (cond) == EQ_EXPR)
01358 {
01359 edge_info = allocate_edge_info (true_edge);
01360 edge_info->lhs = op0;
01361 edge_info->rhs = (integer_zerop (op1)
01362 ? boolean_false_node
01363 : boolean_true_node);
01364
01365 edge_info = allocate_edge_info (false_edge);
01366 edge_info->lhs = op0;
01367 edge_info->rhs = (integer_zerop (op1)
01368 ? boolean_true_node
01369 : boolean_false_node);
01370 }
01371 else
01372 {
01373 edge_info = allocate_edge_info (true_edge);
01374 edge_info->lhs = op0;
01375 edge_info->rhs = (integer_zerop (op1)
01376 ? boolean_true_node
01377 : boolean_false_node);
01378
01379 edge_info = allocate_edge_info (false_edge);
01380 edge_info->lhs = op0;
01381 edge_info->rhs = (integer_zerop (op1)
01382 ? boolean_false_node
01383 : boolean_true_node);
01384 }
01385 }
01386
01387 else if (is_gimple_min_invariant (op0)
01388 && (TREE_CODE (op1) == SSA_NAME
01389 || is_gimple_min_invariant (op1)))
01390 {
01391 tree inverted = invert_truthvalue (cond);
01392 struct edge_info *edge_info;
01393
01394 edge_info = allocate_edge_info (true_edge);
01395 record_conditions (edge_info, cond, inverted);
01396
01397 if (TREE_CODE (cond) == EQ_EXPR)
01398 {
01399 edge_info->lhs = op1;
01400 edge_info->rhs = op0;
01401 }
01402
01403 edge_info = allocate_edge_info (false_edge);
01404 record_conditions (edge_info, inverted, cond);
01405
01406 if (TREE_CODE (cond) == NE_EXPR)
01407 {
01408 edge_info->lhs = op1;
01409 edge_info->rhs = op0;
01410 }
01411 }
01412
01413 else if (TREE_CODE (op0) == SSA_NAME
01414 && (is_gimple_min_invariant (op1)
01415 || TREE_CODE (op1) == SSA_NAME))
01416 {
01417 tree inverted = invert_truthvalue (cond);
01418 struct edge_info *edge_info;
01419
01420 edge_info = allocate_edge_info (true_edge);
01421 record_conditions (edge_info, cond, inverted);
01422
01423 if (TREE_CODE (cond) == EQ_EXPR)
01424 {
01425 edge_info->lhs = op0;
01426 edge_info->rhs = op1;
01427 }
01428
01429 edge_info = allocate_edge_info (false_edge);
01430 record_conditions (edge_info, inverted, cond);
01431
01432 if (TREE_CODE (cond) == NE_EXPR)
01433 {
01434 edge_info->lhs = op0;
01435 edge_info->rhs = op1;
01436 }
01437 }
01438 }
01439
01440
01441 }
01442 }
01443 }
01444
01445
01446
01447
01448
01449
01450
01451 static void
01452 propagate_to_outgoing_edges (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
01453 basic_block bb)
01454 {
01455 record_edge_info (bb);
01456 cprop_into_successor_phis (bb);
01457 }
01458
01459
01460
01461
01462
01463
01464
01465 static bool
01466 eliminate_redundant_computations (tree stmt)
01467 {
01468 tree *expr_p, def = NULL_TREE;
01469 bool insert = true;
01470 tree cached_lhs;
01471 bool retval = false;
01472 bool modify_expr_p = false;
01473
01474 if (TREE_CODE (stmt) == MODIFY_EXPR)
01475 def = TREE_OPERAND (stmt, 0);
01476
01477
01478
01479 if (! def
01480 || TREE_CODE (def) != SSA_NAME
01481 || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)
01482 || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF)
01483
01484
01485 || simple_iv_increment_p (stmt))
01486 insert = false;
01487
01488
01489 cached_lhs = lookup_avail_expr (stmt, insert);
01490
01491 opt_stats.num_exprs_considered++;
01492
01493
01494 if (TREE_CODE (stmt) == COND_EXPR)
01495 expr_p = &COND_EXPR_COND (stmt);
01496 else if (TREE_CODE (stmt) == SWITCH_EXPR)
01497 expr_p = &SWITCH_COND (stmt);
01498 else if (TREE_CODE (stmt) == RETURN_EXPR && TREE_OPERAND (stmt, 0))
01499 {
01500 expr_p = &TREE_OPERAND (TREE_OPERAND (stmt, 0), 1);
01501 modify_expr_p = true;
01502 }
01503 else
01504 {
01505 expr_p = &TREE_OPERAND (stmt, 1);
01506 modify_expr_p = true;
01507 }
01508
01509
01510
01511
01512
01513
01514 if (cached_lhs
01515 && ((TREE_CODE (cached_lhs) != SSA_NAME
01516 && (modify_expr_p
01517 || tree_ssa_useless_type_conversion_1 (TREE_TYPE (*expr_p),
01518 TREE_TYPE (cached_lhs))))
01519 || may_propagate_copy (*expr_p, cached_lhs)))
01520 {
01521 if (dump_file && (dump_flags & TDF_DETAILS))
01522 {
01523 fprintf (dump_file, " Replaced redundant expr '");
01524 print_generic_expr (dump_file, *expr_p, dump_flags);
01525 fprintf (dump_file, "' with '");
01526 print_generic_expr (dump_file, cached_lhs, dump_flags);
01527 fprintf (dump_file, "'\n");
01528 }
01529
01530 opt_stats.num_re++;
01531
01532 #if defined ENABLE_CHECKING
01533 gcc_assert (TREE_CODE (cached_lhs) == SSA_NAME
01534 || is_gimple_min_invariant (cached_lhs));
01535 #endif
01536
01537 if (TREE_CODE (cached_lhs) == ADDR_EXPR
01538 || (POINTER_TYPE_P (TREE_TYPE (*expr_p))
01539 && is_gimple_min_invariant (cached_lhs)))
01540 retval = true;
01541
01542 if (modify_expr_p
01543 && !tree_ssa_useless_type_conversion_1 (TREE_TYPE (*expr_p),
01544 TREE_TYPE (cached_lhs)))
01545 cached_lhs = fold_convert (TREE_TYPE (*expr_p), cached_lhs);
01546
01547 propagate_tree_value (expr_p, cached_lhs);
01548 mark_stmt_modified (stmt);
01549 }
01550 return retval;
01551 }
01552
01553
01554
01555
01556
01557 static void
01558 record_equivalences_from_stmt (tree stmt,
01559 int may_optimize_p,
01560 stmt_ann_t ann)
01561 {
01562 tree lhs = TREE_OPERAND (stmt, 0);
01563 enum tree_code lhs_code = TREE_CODE (lhs);
01564
01565 if (lhs_code == SSA_NAME)
01566 {
01567 tree rhs = TREE_OPERAND (stmt, 1);
01568
01569
01570 STRIP_USELESS_TYPE_CONVERSION (rhs);
01571
01572
01573
01574
01575
01576
01577
01578 if (may_optimize_p
01579 && (TREE_CODE (rhs) == SSA_NAME
01580 || is_gimple_min_invariant (rhs)))
01581 SSA_NAME_VALUE (lhs) = rhs;
01582 }
01583
01584
01585
01586
01587
01588 if (!ann->has_volatile_ops
01589 && (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME
01590 || is_gimple_min_invariant (TREE_OPERAND (stmt, 1)))
01591 && !is_gimple_reg (lhs))
01592 {
01593 tree rhs = TREE_OPERAND (stmt, 1);
01594 tree new;
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604 if (lhs_code == COMPONENT_REF
01605 && DECL_BIT_FIELD (TREE_OPERAND (lhs, 1)))
01606 {
01607 if (TREE_CONSTANT (rhs))
01608 rhs = widen_bitfield (rhs, TREE_OPERAND (lhs, 1), lhs);
01609 else
01610 rhs = NULL;
01611
01612
01613 if (rhs && ! is_gimple_min_invariant (rhs))
01614 rhs = NULL;
01615 }
01616
01617 if (rhs)
01618 {
01619
01620 new = build2 (MODIFY_EXPR, TREE_TYPE (stmt), rhs, lhs);
01621
01622 create_ssa_artficial_load_stmt (new, stmt);
01623
01624
01625
01626 lookup_avail_expr (new, true);
01627 }
01628 }
01629 }
01630
01631
01632
01633
01634 static bool
01635 cprop_operand (tree stmt, use_operand_p op_p)
01636 {
01637 bool may_have_exposed_new_symbols = false;
01638 tree val;
01639 tree op = USE_FROM_PTR (op_p);
01640
01641
01642
01643
01644 val = SSA_NAME_VALUE (op);
01645 if (val && val != op && TREE_CODE (val) != VALUE_HANDLE)
01646 {
01647 tree op_type, val_type;
01648
01649
01650
01651
01652
01653
01654 if (!is_gimple_reg (op)
01655 && (TREE_CODE (val) != SSA_NAME
01656 || is_gimple_reg (val)
01657 || get_virtual_var (val) != get_virtual_var (op)))
01658 return false;
01659
01660
01661 if (TREE_CODE (stmt) == ASM_EXPR
01662 && !may_propagate_copy_into_asm (op))
01663 return false;
01664
01665
01666 op_type = TREE_TYPE (op);
01667 val_type = TREE_TYPE (val);
01668
01669
01670
01671 while (POINTER_TYPE_P (op_type) && POINTER_TYPE_P (val_type))
01672 {
01673 op_type = TREE_TYPE (op_type);
01674 val_type = TREE_TYPE (val_type);
01675 }
01676
01677
01678
01679
01680
01681 if (TREE_CODE (val) != SSA_NAME)
01682 {
01683 if (!lang_hooks.types_compatible_p (op_type, val_type))
01684 {
01685 val = fold_convert (TREE_TYPE (op), val);
01686 if (!is_gimple_min_invariant (val))
01687 return false;
01688 }
01689 }
01690
01691
01692
01693
01694 else if (!may_propagate_copy (op, val))
01695 return false;
01696
01697
01698
01699
01700
01701
01702 if (loop_depth_of_name (val) > loop_depth_of_name (op))
01703 return false;
01704
01705
01706 if (dump_file && (dump_flags & TDF_DETAILS))
01707 {
01708 fprintf (dump_file, " Replaced '");
01709 print_generic_expr (dump_file, op, dump_flags);
01710 fprintf (dump_file, "' with %s '",
01711 (TREE_CODE (val) != SSA_NAME ? "constant" : "variable"));
01712 print_generic_expr (dump_file, val, dump_flags);
01713 fprintf (dump_file, "'\n");
01714 }
01715
01716
01717
01718 if (TREE_CODE (val) == ADDR_EXPR
01719 || (POINTER_TYPE_P (TREE_TYPE (op))
01720 && is_gimple_min_invariant (val)))
01721 may_have_exposed_new_symbols = true;
01722
01723 if (TREE_CODE (val) != SSA_NAME)
01724 opt_stats.num_const_prop++;
01725 else
01726 opt_stats.num_copy_prop++;
01727
01728 propagate_value (op_p, val);
01729
01730
01731
01732
01733 mark_stmt_modified (stmt);
01734 }
01735 return may_have_exposed_new_symbols;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744 static bool
01745 cprop_into_stmt (tree stmt)
01746 {
01747 bool may_have_exposed_new_symbols = false;
01748 use_operand_p op_p;
01749 ssa_op_iter iter;
01750
01751 FOR_EACH_SSA_USE_OPERAND (op_p, stmt, iter, SSA_OP_ALL_USES)
01752 {
01753 if (TREE_CODE (USE_FROM_PTR (op_p)) == SSA_NAME)
01754 may_have_exposed_new_symbols |= cprop_operand (stmt, op_p);
01755 }
01756
01757 return may_have_exposed_new_symbols;
01758 }
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776 static void
01777 optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
01778 basic_block bb, block_stmt_iterator si)
01779 {
01780 stmt_ann_t ann;
01781 tree stmt, old_stmt;
01782 bool may_optimize_p;
01783 bool may_have_exposed_new_symbols = false;
01784
01785 old_stmt = stmt = bsi_stmt (si);
01786
01787 if (TREE_CODE (stmt) == COND_EXPR)
01788 canonicalize_comparison (stmt);
01789
01790 update_stmt_if_modified (stmt);
01791 ann = stmt_ann (stmt);
01792 opt_stats.num_stmts++;
01793 may_have_exposed_new_symbols = false;
01794
01795 if (dump_file && (dump_flags & TDF_DETAILS))
01796 {
01797 fprintf (dump_file, "Optimizing statement ");
01798 print_generic_stmt (dump_file, stmt, TDF_SLIM);
01799 }
01800
01801
01802 may_have_exposed_new_symbols = cprop_into_stmt (stmt);
01803
01804
01805
01806 if (ann->modified)
01807 {
01808 tree rhs;
01809
01810
01811
01812 if (fold_stmt (bsi_stmt_ptr (si)))
01813 {
01814 stmt = bsi_stmt (si);
01815 ann = stmt_ann (stmt);
01816
01817 if (dump_file && (dump_flags & TDF_DETAILS))
01818 {
01819 fprintf (dump_file, " Folded to: ");
01820 print_generic_stmt (dump_file, stmt, TDF_SLIM);
01821 }
01822 }
01823
01824 rhs = get_rhs (stmt);
01825 if (rhs && TREE_CODE (rhs) == ADDR_EXPR)
01826 recompute_tree_invariant_for_addr_expr (rhs);
01827
01828
01829
01830
01831
01832
01833 may_have_exposed_new_symbols = true;
01834 }
01835
01836
01837
01838 may_optimize_p = (!ann->has_volatile_ops
01839 && ((TREE_CODE (stmt) == RETURN_EXPR
01840 && TREE_OPERAND (stmt, 0)
01841 && TREE_CODE (TREE_OPERAND (stmt, 0)) == MODIFY_EXPR
01842 && ! (TREE_SIDE_EFFECTS
01843 (TREE_OPERAND (TREE_OPERAND (stmt, 0), 1))))
01844 || (TREE_CODE (stmt) == MODIFY_EXPR
01845 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (stmt, 1)))
01846 || TREE_CODE (stmt) == COND_EXPR
01847 || TREE_CODE (stmt) == SWITCH_EXPR));
01848
01849 if (may_optimize_p)
01850 may_have_exposed_new_symbols |= eliminate_redundant_computations (stmt);
01851
01852
01853 if (TREE_CODE (stmt) == MODIFY_EXPR)
01854 record_equivalences_from_stmt (stmt,
01855 may_optimize_p,
01856 ann);
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 if (ann->modified)
01885 {
01886 tree val = NULL;
01887
01888 if (TREE_CODE (stmt) == COND_EXPR)
01889 val = COND_EXPR_COND (stmt);
01890 else if (TREE_CODE (stmt) == SWITCH_EXPR)
01891 val = SWITCH_COND (stmt);
01892
01893 if (val && TREE_CODE (val) == INTEGER_CST && find_taken_edge (bb, val))
01894 cfg_altered = true;
01895
01896
01897
01898 if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
01899 {
01900 bitmap_set_bit (need_eh_cleanup, bb->index);
01901 if (dump_file && (dump_flags & TDF_DETAILS))
01902 fprintf (dump_file, " Flagged to clear EH edges.\n");
01903 }
01904 }
01905
01906 if (may_have_exposed_new_symbols)
01907 VEC_safe_push (tree, heap, stmts_to_rescan, bsi_stmt (si));
01908 }
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922 static tree
01923 lookup_avail_expr (tree stmt, bool insert)
01924 {
01925 void **slot;
01926 tree lhs;
01927 tree temp;
01928 struct expr_hash_elt *element = XNEW (struct expr_hash_elt);
01929
01930 lhs = TREE_CODE (stmt) == MODIFY_EXPR ? TREE_OPERAND (stmt, 0) : NULL;
01931
01932 initialize_hash_element (stmt, lhs, element);
01933
01934
01935
01936
01937 if (TREE_CODE (element->rhs) == SSA_NAME
01938 || is_gimple_min_invariant (element->rhs))
01939 {
01940 free (element);
01941 return NULL_TREE;
01942 }
01943
01944
01945 slot = htab_find_slot_with_hash (avail_exprs, element, element->hash,
01946 (insert ? INSERT : NO_INSERT));
01947 if (slot == NULL)
01948 {
01949 free (element);
01950 return NULL_TREE;
01951 }
01952
01953 if (*slot == NULL)
01954 {
01955 *slot = (void *) element;
01956 VEC_safe_push (tree, heap, avail_exprs_stack,
01957 stmt ? stmt : element->rhs);
01958 return NULL_TREE;
01959 }
01960
01961
01962
01963 lhs = ((struct expr_hash_elt *)*slot)->lhs;
01964
01965
01966
01967 if (TREE_CODE (lhs) == SSA_NAME)
01968 {
01969 temp = SSA_NAME_VALUE (lhs);
01970 if (temp && TREE_CODE (temp) != VALUE_HANDLE)
01971 lhs = temp;
01972 }
01973
01974 free (element);
01975 return lhs;
01976 }
01977
01978
01979
01980
01981
01982 static hashval_t
01983 avail_expr_hash (const void *p)
01984 {
01985 tree stmt = ((struct expr_hash_elt *)p)->stmt;
01986 tree rhs = ((struct expr_hash_elt *)p)->rhs;
01987 tree vuse;
01988 ssa_op_iter iter;
01989 hashval_t val = 0;
01990
01991
01992
01993
01994 val = iterative_hash_expr (rhs, val);
01995
01996
01997
01998
01999 if (!stmt || !stmt_ann (stmt))
02000 return val;
02001
02002
02003
02004
02005
02006 FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
02007 val = iterative_hash_expr (vuse, val);
02008
02009 return val;
02010 }
02011
02012 static hashval_t
02013 real_avail_expr_hash (const void *p)
02014 {
02015 return ((const struct expr_hash_elt *)p)->hash;
02016 }
02017
02018 static int
02019 avail_expr_eq (const void *p1, const void *p2)
02020 {
02021 tree stmt1 = ((struct expr_hash_elt *)p1)->stmt;
02022 tree rhs1 = ((struct expr_hash_elt *)p1)->rhs;
02023 tree stmt2 = ((struct expr_hash_elt *)p2)->stmt;
02024 tree rhs2 = ((struct expr_hash_elt *)p2)->rhs;
02025
02026
02027 if (rhs1 == rhs2 && stmt1 == stmt2)
02028 return true;
02029
02030
02031 if (TREE_CODE (rhs1) != TREE_CODE (rhs2))
02032 return false;
02033
02034
02035
02036 if ((TREE_TYPE (rhs1) == TREE_TYPE (rhs2)
02037 || lang_hooks.types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2)))
02038 && operand_equal_p (rhs1, rhs2, OEP_PURE_SAME))
02039 {
02040 bool ret = compare_ssa_operands_equal (stmt1, stmt2, SSA_OP_VUSE);
02041 gcc_assert (!ret || ((struct expr_hash_elt *)p1)->hash
02042 == ((struct expr_hash_elt *)p2)->hash);
02043 return ret;
02044 }
02045
02046 return false;
02047 }
02048
02049
02050
02051
02052
02053
02054
02055 static tree
02056 degenerate_phi_result (tree phi)
02057 {
02058 tree lhs = PHI_RESULT (phi);
02059 tree val = NULL;
02060 int i;
02061
02062
02063
02064
02065 for (i = 0; i < PHI_NUM_ARGS (phi); i++)
02066 {
02067 tree arg = PHI_ARG_DEF (phi, i);
02068
02069 if (arg == lhs)
02070 continue;
02071 else if (!val)
02072 val = arg;
02073 else if (!operand_equal_p (arg, val, 0))
02074 break;
02075 }
02076 return (i == PHI_NUM_ARGS (phi) ? val : NULL);
02077 }
02078
02079
02080
02081
02082 static void
02083 remove_stmt_or_phi (tree t)
02084 {
02085 if (TREE_CODE (t) == PHI_NODE)
02086 remove_phi_node (t, NULL);
02087 else
02088 {
02089 block_stmt_iterator bsi = bsi_for_stmt (t);
02090 bsi_remove (&bsi, true);
02091 }
02092 }
02093
02094
02095
02096
02097
02098 static tree
02099 get_rhs_or_phi_arg (tree t)
02100 {
02101 if (TREE_CODE (t) == PHI_NODE)
02102 return degenerate_phi_result (t);
02103 else if (TREE_CODE (t) == MODIFY_EXPR)
02104 return TREE_OPERAND (t, 1);
02105 gcc_unreachable ();
02106 }
02107
02108
02109
02110
02111
02112 static tree
02113 get_lhs_or_phi_result (tree t)
02114 {
02115 if (TREE_CODE (t) == PHI_NODE)
02116 return PHI_RESULT (t);
02117 else if (TREE_CODE (t) == MODIFY_EXPR)
02118 return TREE_OPERAND (t, 0);
02119 gcc_unreachable ();
02120 }
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133 static void
02134 propagate_rhs_into_lhs (tree stmt, tree lhs, tree rhs, bitmap interesting_names)
02135 {
02136
02137
02138 if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
02139 && (TREE_CODE (rhs) != SSA_NAME
02140 || ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs))
02141 && may_propagate_copy (lhs, rhs)
02142 && loop_depth_of_name (lhs) >= loop_depth_of_name (rhs))
02143 {
02144 use_operand_p use_p;
02145 imm_use_iterator iter;
02146 tree use_stmt;
02147 bool all = true;
02148
02149
02150 if (dump_file && (dump_flags & TDF_DETAILS))
02151 {
02152 fprintf (dump_file, " Replacing '");
02153 print_generic_expr (dump_file, lhs, dump_flags);
02154 fprintf (dump_file, "' with %s '",
02155 (TREE_CODE (rhs) != SSA_NAME ? "constant" : "variable"));
02156 print_generic_expr (dump_file, rhs, dump_flags);
02157 fprintf (dump_file, "'\n");
02158 }
02159
02160
02161
02162
02163 FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
02164 {
02165
02166
02167 if (TREE_CODE (use_stmt) == ASM_EXPR
02168 && ! may_propagate_copy_into_asm (lhs))
02169 {
02170 all = false;
02171 continue;
02172 }
02173
02174
02175 if (dump_file && (dump_flags & TDF_DETAILS))
02176 {
02177 fprintf (dump_file, " Original statement:");
02178 print_generic_expr (dump_file, use_stmt, dump_flags);
02179 fprintf (dump_file, "\n");
02180 }
02181
02182
02183 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
02184 propagate_value (use_p, rhs);
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196 if (TREE_CODE (use_stmt) == PHI_NODE
02197 || (! is_gimple_reg (lhs)
02198 && TREE_CODE (rhs) == SSA_NAME
02199 && SSA_NAME_VAR (lhs) == SSA_NAME_VAR (rhs)))
02200 {
02201
02202 if (dump_file && (dump_flags & TDF_DETAILS))
02203 {
02204 fprintf (dump_file, " Updated statement:");
02205 print_generic_expr (dump_file, use_stmt, dump_flags);
02206 fprintf (dump_file, "\n");
02207 }
02208
02209
02210
02211 if (TREE_CODE (use_stmt) == PHI_NODE)
02212 {
02213 tree result = get_lhs_or_phi_result (use_stmt);
02214 bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
02215 }
02216 continue;
02217 }
02218
02219
02220
02221
02222
02223 fold_stmt_inplace (use_stmt);
02224
02225
02226
02227
02228 mark_new_vars_to_rename (use_stmt);
02229
02230
02231 if (dump_file && (dump_flags & TDF_DETAILS))
02232 {
02233 fprintf (dump_file, " Updated statement:");
02234 print_generic_expr (dump_file, use_stmt, dump_flags);
02235 fprintf (dump_file, "\n");
02236 }
02237
02238
02239
02240 if (TREE_CODE (use_stmt) == MODIFY_EXPR
02241 && TREE_CODE (TREE_OPERAND (use_stmt, 1)) == ADDR_EXPR)
02242 recompute_tree_invariant_for_addr_expr (TREE_OPERAND (use_stmt, 1));
02243
02244
02245
02246 if (maybe_clean_or_replace_eh_stmt (use_stmt, use_stmt))
02247 {
02248 bitmap_set_bit (need_eh_cleanup, bb_for_stmt (use_stmt)->index);
02249 if (dump_file && (dump_flags & TDF_DETAILS))
02250 fprintf (dump_file, " Flagged to clear EH edges.\n");
02251 }
02252
02253
02254
02255 if (TREE_CODE (use_stmt) == MODIFY_EXPR
02256 && TREE_CODE (TREE_OPERAND (use_stmt, 0)) == SSA_NAME
02257 && (TREE_CODE (TREE_OPERAND (use_stmt, 1)) == SSA_NAME
02258 || is_gimple_min_invariant (TREE_OPERAND (use_stmt, 1))))
02259 {
02260 tree result = get_lhs_or_phi_result (use_stmt);
02261 bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
02262 }
02263
02264
02265
02266
02267
02268 else if (TREE_CODE (use_stmt) == COND_EXPR
02269 || TREE_CODE (use_stmt) == SWITCH_EXPR
02270 || TREE_CODE (use_stmt) == GOTO_EXPR)
02271 {
02272 tree val;
02273
02274 if (TREE_CODE (use_stmt) == COND_EXPR)
02275 val = COND_EXPR_COND (use_stmt);
02276 else if (TREE_CODE (use_stmt) == SWITCH_EXPR)
02277 val = SWITCH_COND (use_stmt);
02278 else
02279 val = GOTO_DESTINATION (use_stmt);
02280
02281 if (is_gimple_min_invariant (val))
02282 {
02283 basic_block bb = bb_for_stmt (use_stmt);
02284 edge te = find_taken_edge (bb, val);
02285 edge_iterator ei;
02286 edge e;
02287 block_stmt_iterator bsi;
02288
02289
02290 for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei));)
02291 {
02292 if (e != te)
02293 {
02294 tree phi;
02295
02296
02297
02298 for (phi = phi_nodes (e->dest);
02299 phi;
02300 phi = PHI_CHAIN (phi))
02301 {
02302 tree result = PHI_RESULT (phi);
02303 int version = SSA_NAME_VERSION (result);
02304
02305 bitmap_set_bit (interesting_names, version);
02306 }
02307
02308 te->probability += e->probability;
02309
02310 te->count += e->count;
02311 remove_edge (e);
02312 cfg_altered = 1;
02313 }
02314 else
02315 ei_next (&ei);
02316 }
02317
02318 bsi = bsi_last (bb_for_stmt (use_stmt));
02319 bsi_remove (&bsi, true);
02320
02321
02322 te->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
02323 te->flags &= ~EDGE_ABNORMAL;
02324 te->flags |= EDGE_FALLTHRU;
02325 if (te->probability > REG_BR_PROB_BASE)
02326 te->probability = REG_BR_PROB_BASE;
02327 }
02328 }
02329 }
02330
02331
02332 gcc_assert (!all || has_zero_uses (lhs));
02333
02334
02335
02336 if (all)
02337 remove_stmt_or_phi (stmt);
02338 }
02339 }
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351 static void
02352 eliminate_const_or_copy (tree t, bitmap interesting_names)
02353 {
02354 tree lhs = get_lhs_or_phi_result (t);
02355 tree rhs;
02356 int version = SSA_NAME_VERSION (lhs);
02357
02358
02359
02360
02361
02362
02363 if (has_zero_uses (lhs))
02364 {
02365 bitmap_clear_bit (interesting_names, version);
02366 remove_stmt_or_phi (t);
02367 return;
02368 }
02369
02370
02371
02372 rhs = get_rhs_or_phi_arg (t);
02373 if (!rhs)
02374 {
02375 bitmap_clear_bit (interesting_names, version);
02376 return;
02377 }
02378
02379 propagate_rhs_into_lhs (t, lhs, rhs, interesting_names);
02380
02381
02382
02383
02384 bitmap_clear_bit (interesting_names, version);
02385 }
02386
02387
02388
02389
02390
02391
02392 static void
02393 eliminate_degenerate_phis_1 (basic_block bb, bitmap interesting_names)
02394 {
02395 tree phi, next;
02396 basic_block son;
02397
02398 for (phi = phi_nodes (bb); phi; phi = next)
02399 {
02400 next = PHI_CHAIN (phi);
02401 eliminate_const_or_copy (phi, interesting_names);
02402 }
02403
02404
02405 for (son = first_dom_son (CDI_DOMINATORS, bb);
02406 son;
02407 son = next_dom_son (CDI_DOMINATORS, son))
02408 eliminate_degenerate_phis_1 (son, interesting_names);
02409 }
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438 static unsigned int
02439 eliminate_degenerate_phis (void)
02440 {
02441 bitmap interesting_names;
02442 bitmap interesting_names1;
02443
02444
02445
02446 need_eh_cleanup = BITMAP_ALLOC (NULL);
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458 interesting_names = BITMAP_ALLOC (NULL);
02459 interesting_names1 = BITMAP_ALLOC (NULL);
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469 calculate_dominance_info (CDI_DOMINATORS);
02470 eliminate_degenerate_phis_1 (ENTRY_BLOCK_PTR, interesting_names);
02471
02472
02473
02474
02475
02476 while (!bitmap_empty_p (interesting_names))
02477 {
02478 unsigned int i;
02479 bitmap_iterator bi;
02480
02481
02482
02483
02484 bitmap_copy (interesting_names1, interesting_names);
02485
02486 EXECUTE_IF_SET_IN_BITMAP (interesting_names1, 0, i, bi)
02487 {
02488 tree name = ssa_name (i);
02489
02490
02491
02492 if (name)
02493 eliminate_const_or_copy (SSA_NAME_DEF_STMT (ssa_name (i)),
02494 interesting_names);
02495 }
02496 }
02497
02498
02499
02500 if (!bitmap_empty_p (need_eh_cleanup))
02501 {
02502 cfg_altered |= tree_purge_all_dead_eh_edges (need_eh_cleanup);
02503 BITMAP_FREE (need_eh_cleanup);
02504 }
02505
02506 BITMAP_FREE (interesting_names);
02507 BITMAP_FREE (interesting_names1);
02508 if (cfg_altered)
02509 free_dominance_info (CDI_DOMINATORS);
02510 return 0;
02511 }
02512
02513 struct tree_opt_pass pass_phi_only_cprop =
02514 {
02515 "phicprop",
02516 gate_dominator,
02517 eliminate_degenerate_phis,
02518 NULL,
02519 NULL,
02520 0,
02521 TV_TREE_PHI_CPROP,
02522 PROP_cfg | PROP_ssa | PROP_alias,
02523 0,
02524 PROP_smt_usage,
02525 0,
02526 TODO_cleanup_cfg | TODO_dump_func
02527 | TODO_ggc_collect | TODO_verify_ssa
02528 | TODO_verify_stmts | TODO_update_smt_usage
02529 | TODO_update_ssa,
02530 0
02531 };