diff options
Diffstat (limited to 'gcc/tree-ssa-phiopt.cc')
-rw-r--r-- | gcc/tree-ssa-phiopt.cc | 147 |
1 files changed, 91 insertions, 56 deletions
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 54ecd93..faecab6 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -838,33 +838,13 @@ move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, auto_bitmap &inserted_exprs) // Mark the name to be renamed if there is one. bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (name)); gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt); - gsi_move_before (&gsi1, gsi); + gsi_move_before (&gsi1, gsi, GSI_NEW_STMT); reset_flow_sensitive_info (name); /* Rewrite some code which might be undefined when unconditionalized. */ - if (gimple_assign_single_p (stmt)) - { - tree rhs = gimple_assign_rhs1 (stmt); - /* VCE from integral types to another integral types but with - different precisions need to be changed into casts - to be well defined when unconditional. */ - if (gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR - && INTEGRAL_TYPE_P (TREE_TYPE (name)) - && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (rhs, 0)))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "rewriting stmt with maybe undefined VCE "); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - } - tree new_rhs = TREE_OPERAND (rhs, 0); - gcc_assert (is_gimple_val (new_rhs)); - gimple_assign_set_rhs_code (stmt, NOP_EXPR); - gimple_assign_set_rhs1 (stmt, new_rhs); - update_stmt (stmt); - } - } + if (gimple_needing_rewrite_undefined (stmt)) + rewrite_to_defined_unconditional (gsi); } /* RAII style class to temporarily remove flow sensitive @@ -1021,16 +1001,9 @@ match_simplify_replacement (basic_block cond_bb, basic_block middle_bb, if (seq) { // Mark the lhs of the new statements maybe for dce - gimple_stmt_iterator gsi1 = gsi_start (seq); - for (; !gsi_end_p (gsi1); gsi_next (&gsi1)) - { - gimple *stmt = gsi_stmt (gsi1); - tree name = gimple_get_lhs (stmt); - if (name && TREE_CODE (name) == SSA_NAME) - bitmap_set_bit (exprs_maybe_dce, SSA_NAME_VERSION (name)); - } - gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING); - } + mark_lhs_in_seq_for_dce (exprs_maybe_dce, seq); + gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING); + } /* If there was a statement to move, move it to right before the original conditional. */ @@ -3546,8 +3519,15 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, /* If LHS is an access to a local variable without address-taken (or when we allow data races) and known not to trap, we could always safely move down the store. */ + tree base; if (ref_can_have_store_data_races (lhs) - || tree_could_trap_p (lhs)) + || tree_could_trap_p (lhs) + /* tree_could_trap_p is a predicate for rvalues, so check + for readonly memory explicitly. */ + || ((base = get_base_address (lhs)) + && ((DECL_P (base) + && TREE_READONLY (base)) + || TREE_CODE (base) == STRING_CST))) return false; } @@ -3625,7 +3605,8 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb, static bool cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, basic_block join_bb, gimple *then_assign, - gimple *else_assign) + gimple *else_assign, + gphi *vphi) { tree lhs_base, lhs, then_rhs, else_rhs, name; location_t then_locus, else_locus; @@ -3692,6 +3673,14 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus); new_stmt = gimple_build_assign (lhs, gimple_phi_result (newphi)); + /* Update the vdef for the new store statement. */ + tree newvphilhs = make_ssa_name (gimple_vop (cfun)); + tree vdef = gimple_phi_result (vphi); + gimple_set_vuse (new_stmt, newvphilhs); + gimple_set_vdef (new_stmt, vdef); + gimple_phi_set_result (vphi, newvphilhs); + SSA_NAME_DEF_STMT (vdef) = new_stmt; + update_stmt (vphi); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf(dump_file, "to use phi:\n"); @@ -3719,10 +3708,11 @@ cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, } /* Return the single store in BB with VDEF or NULL if there are - other stores in the BB or loads following the store. */ + other stores in the BB or loads following the store. VPHI is + where the only use of the vdef should be. */ static gimple * -single_trailing_store_in_bb (basic_block bb, tree vdef) +single_trailing_store_in_bb (basic_block bb, tree vdef, gphi *vphi) { if (SSA_NAME_IS_DEFAULT_DEF (vdef)) return NULL; @@ -3737,17 +3727,62 @@ single_trailing_store_in_bb (basic_block bb, tree vdef) && gimple_code (SSA_NAME_DEF_STMT (gimple_vuse (store))) != GIMPLE_PHI) return NULL; - /* Verify there is no load or store after the store. */ + /* Verify there is no load or store after the store, the vdef of the store + should only be used by the vphi joining the 2 bbs. */ use_operand_p use_p; - imm_use_iterator imm_iter; - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vdef (store)) - if (USE_STMT (use_p) != store - && gimple_bb (USE_STMT (use_p)) == bb) - return NULL; + gimple *use_stmt; + if (!single_imm_use (gimple_vdef (store), &use_p, &use_stmt)) + return NULL; + if (use_stmt != vphi) + return NULL; return store; } +/* Limited Conditional store replacement. We already know + that the recognized pattern looks like so: + + split: + if (cond) goto THEN_BB; else goto ELSE_BB (edge E1) + THEN_BB: + ... + ONLY_STORE = Y; + ... + goto JOIN_BB; + ELSE_BB: + ... + ONLY_STORE = Z; + ... + fallthrough (edge E0) + JOIN_BB: + some more + + Handles only the case with single store in THEN_BB and ELSE_BB. That is + cheap enough due to in phiopt and not worry about heurstics. Moving the store + out might provide an opportunity for a phiopt to happen. */ + +static bool +cond_if_else_store_replacement_limited (basic_block then_bb, basic_block else_bb, + basic_block join_bb) +{ + gphi *vphi = get_virtual_phi (join_bb); + if (!vphi) + return false; + + tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb)); + gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef, vphi); + if (!then_assign) + return false; + + tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb)); + gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef, vphi); + if (!else_assign) + return false; + + return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, + then_assign, else_assign, vphi); +} + /* Conditional store replacement. We already know that the recognized pattern looks like so: @@ -3784,25 +3819,20 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, /* Handle the case with single store in THEN_BB and ELSE_BB. That is cheap enough to always handle as it allows us to elide dependence checking. */ - gphi *vphi = NULL; - for (gphi_iterator si = gsi_start_phis (join_bb); !gsi_end_p (si); - gsi_next (&si)) - if (virtual_operand_p (gimple_phi_result (si.phi ()))) - { - vphi = si.phi (); - break; - } + gphi *vphi = get_virtual_phi (join_bb); if (!vphi) return false; tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb)); - tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb)); - gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef); + gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef, vphi); if (then_assign) { - gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef); + tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb)); + gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef, + vphi); if (else_assign) return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, - then_assign, else_assign); + then_assign, else_assign, + vphi); } /* If either vectorization or if-conversion is disabled then do @@ -3941,7 +3971,7 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, then_store = store_pair.first; else_store = store_pair.second; res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, - then_store, else_store); + then_store, else_store, vphi); ok = ok || res; } @@ -4476,6 +4506,11 @@ pass_phiopt::execute (function *) && !predictable_edge_p (EDGE_SUCC (bb, 0)) && !predictable_edge_p (EDGE_SUCC (bb, 1))) hoist_adjacent_loads (bb, bb1, bb2, bb3); + + /* Try to see if there are only one store in each side of the if + and try to remove that. */ + if (EDGE_COUNT (bb3->preds) == 2) + cond_if_else_store_replacement_limited (bb1, bb2, bb3); } gimple_stmt_iterator gsi; |