Mercurial > hg > CbC > CbC_gcc
diff gcc/tree-if-conv.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/tree-if-conv.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/tree-if-conv.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* If-conversion for vectorizer. - Copyright (C) 2004-2018 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. Contributed by Devang Patel <dpatel@apple.com> This file is part of GCC. @@ -114,15 +114,17 @@ #include "tree-hash-traits.h" #include "varasm.h" #include "builtins.h" -#include "params.h" #include "cfganal.h" #include "internal-fn.h" #include "fold-const.h" +#include "tree-ssa-sccvn.h" +#include "tree-cfgcleanup.h" +#include "tree-ssa-dse.h" /* Only handle PHIs with no more arguments unless we are asked to by simd pragma. */ #define MAX_PHI_ARG_NUM \ - ((unsigned) PARAM_VALUE (PARAM_MAX_TREE_IF_CONVERSION_PHI_ARGS)) + ((unsigned) param_max_tree_if_conversion_phi_args) /* True if we've converted a statement that was only executed when some condition C was true, and if for correctness we need to predicate the @@ -434,7 +436,7 @@ if (code1 != ERROR_MARK && code2 != ERROR_MARK) { - tree t = maybe_fold_or_comparisons (code1, op1a, op1b, + tree t = maybe_fold_or_comparisons (boolean_type_node, code1, op1a, op1b, code2, op2a, op2b); if (t) return t; @@ -500,7 +502,7 @@ cd-equivalent if they are executed under the same condition. */ static inline void -add_to_predicate_list (struct loop *loop, basic_block bb, tree nc) +add_to_predicate_list (class loop *loop, basic_block bb, tree nc) { tree bc, *tp; basic_block dom_bb; @@ -565,7 +567,7 @@ the loop to be if-converted. */ static void -add_to_dst_predicate_list (struct loop *loop, edge e, +add_to_dst_predicate_list (class loop *loop, edge e, tree prev_cond, tree cond) { if (!flow_bb_inside_loop_p (loop, e->dest)) @@ -582,7 +584,7 @@ /* Return true if one of the successor edges of BB exits LOOP. */ static bool -bb_with_exit_edge_p (struct loop *loop, basic_block bb) +bb_with_exit_edge_p (class loop *loop, basic_block bb) { edge e; edge_iterator ei; @@ -659,7 +661,7 @@ ANY_COMPLICATED_PHI if PHI is complicated. */ static bool -if_convertible_phi_p (struct loop *loop, basic_block bb, gphi *phi) +if_convertible_phi_p (class loop *loop, basic_block bb, gphi *phi) { if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -754,7 +756,7 @@ widest_int niter, valid_niter, delta, wi_step; tree ev, init, step; tree low, high; - struct loop *loop = (struct loop*) dta; + class loop *loop = (class loop*) dta; /* Only support within-bound access for array references. */ if (TREE_CODE (ref) != ARRAY_REF) @@ -820,7 +822,7 @@ static bool ref_within_array_bound (gimple *stmt, tree ref) { - struct loop *loop = loop_containing_stmt (stmt); + class loop *loop = loop_containing_stmt (stmt); gcc_assert (loop != NULL); return for_each_index (&ref, idx_within_array_bound, loop); @@ -911,10 +913,10 @@ to unconditionally. */ if (base_master_dr && DR_BASE_W_UNCONDITIONALLY (*base_master_dr)) - return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES); + return flag_store_data_races; /* or the base is known to be not readonly. */ else if (base_object_writable (DR_REF (a))) - return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES); + return flag_store_data_races; } return false; @@ -1126,7 +1128,7 @@ inside LOOP. */ static bool -if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) +if_convertible_bb_p (class loop *loop, basic_block bb, basic_block exit_bb) { edge e; edge_iterator ei; @@ -1195,7 +1197,7 @@ predecessors are already selected. */ static basic_block * -get_loop_body_in_if_conv_order (const struct loop *loop) +get_loop_body_in_if_conv_order (const class loop *loop) { basic_block *blocks, *blocks_in_bfs_order; basic_block bb; @@ -1342,7 +1344,7 @@ /* Build region by adding loop pre-header and post-header blocks. */ static vec<basic_block> -build_region (struct loop *loop) +build_region (class loop *loop) { vec<basic_block> region = vNULL; basic_block exit_bb = NULL; @@ -1376,7 +1378,7 @@ in if_convertible_loop_p. */ static bool -if_convertible_loop_p_1 (struct loop *loop, vec<data_reference_p> *refs) +if_convertible_loop_p_1 (class loop *loop, vec<data_reference_p> *refs) { unsigned int i; basic_block exit_bb = NULL; @@ -1516,7 +1518,7 @@ - if its basic blocks and phi nodes are if convertible. */ static bool -if_convertible_loop_p (struct loop *loop) +if_convertible_loop_p (class loop *loop) { edge e; edge_iterator ei; @@ -1595,7 +1597,7 @@ gimple *header_phi = NULL; enum tree_code reduction_op; basic_block bb = gimple_bb (phi); - struct loop *loop = bb->loop_father; + class loop *loop = bb->loop_father; edge latch_e = loop_latch_edge (loop); imm_use_iterator imm_iter; use_operand_p use_p; @@ -2002,7 +2004,7 @@ LOOP->header block with conditional modify expressions. */ static void -predicate_all_scalar_phis (struct loop *loop) +predicate_all_scalar_phis (class loop *loop) { basic_block bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2139,9 +2141,7 @@ new_stmt = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr, mask, rhs); - gimple_set_vuse (new_stmt, gimple_vuse (stmt)); - gimple_set_vdef (new_stmt, gimple_vdef (stmt)); - SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; + gimple_move_vops (new_stmt, stmt); } gimple_call_set_nothrow (new_stmt, true); return new_stmt; @@ -2524,7 +2524,7 @@ blocks. Replace PHI nodes with conditional modify expressions. */ static void -combine_blocks (struct loop *loop) +combine_blocks (class loop *loop) { basic_block bb, exit_bb, merge_target_bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2624,6 +2624,11 @@ vphi = get_virtual_phi (bb); if (vphi) { + /* When there's just loads inside the loop a stray virtual + PHI merging the uses can appear, update last_vdef from + it. */ + if (!last_vdef) + last_vdef = gimple_phi_arg_def (vphi, 0); imm_use_iterator iter; use_operand_p use_p; gimple *use_stmt; @@ -2632,6 +2637,8 @@ FOR_EACH_IMM_USE_ON_STMT (use_p, iter) SET_USE (use_p, last_vdef); } + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))) + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef) = 1; gsi = gsi_for_stmt (vphi); remove_phi_node (&gsi, true); } @@ -2653,6 +2660,10 @@ if (gimple_vdef (stmt)) last_vdef = gimple_vdef (stmt); } + else + /* If this is the first load we arrive at update last_vdef + so we handle stray PHIs correctly. */ + last_vdef = gimple_vuse (stmt); if (predicated[i]) { ssa_op_iter i; @@ -2690,6 +2701,8 @@ FOR_EACH_IMM_USE_ON_STMT (use_p, iter) SET_USE (use_p, last_vdef); } + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))) + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef) = 1; gimple_stmt_iterator gsi = gsi_for_stmt (vphi); remove_phi_node (&gsi, true); } @@ -2713,12 +2726,12 @@ out of LOOP_VECTORIZED must have 100% probability so the profile remains consistent after the condition is folded in the vectorizer. */ -static struct loop * -version_loop_for_if_conversion (struct loop *loop) +static class loop * +version_loop_for_if_conversion (class loop *loop, vec<gimple *> *preds) { basic_block cond_bb; tree cond = make_ssa_name (boolean_type_node); - struct loop *new_loop; + class loop *new_loop; gimple *g; gimple_stmt_iterator gsi; unsigned int save_length; @@ -2754,6 +2767,8 @@ new_loop->force_vectorize = false; gsi = gsi_last_bb (cond_bb); gimple_call_set_arg (g, 1, build_int_cst (integer_type_node, new_loop->num)); + if (preds) + preds->safe_push (g); gsi_insert_before (&gsi, g, GSI_SAME_STMT); update_ssa (TODO_update_ssa); return new_loop; @@ -2773,7 +2788,7 @@ inner loop's exit block. */ static bool -versionable_outer_loop_p (struct loop *loop) +versionable_outer_loop_p (class loop *loop) { if (!loop_outer (loop) || loop->dont_vectorize @@ -2807,7 +2822,7 @@ Last restriction is valid only if AGGRESSIVE_IF_CONV is false. */ static bool -ifcvt_split_critical_edges (struct loop *loop, bool aggressive_if_conv) +ifcvt_split_critical_edges (class loop *loop, bool aggressive_if_conv) { basic_block *body; basic_block bb; @@ -2867,7 +2882,7 @@ loop vectorization. */ static void -ifcvt_local_dce (basic_block bb) +ifcvt_local_dce (class loop *loop) { gimple *stmt; gimple *stmt1; @@ -2884,6 +2899,10 @@ replace_uses_by (name_pair->first, name_pair->second); redundant_ssa_names.release (); + /* The loop has a single BB only. */ + basic_block bb = loop->header; + tree latch_vdef = NULL_TREE; + worklist.create (64); /* Consider all phi as live statements. */ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -2891,6 +2910,8 @@ phi = gsi_stmt (gsi); gimple_set_plf (phi, GF_PLF_2, true); worklist.safe_push (phi); + if (virtual_operand_p (gimple_phi_result (phi))) + latch_vdef = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); } /* Consider load/store statements, CALL and COND as live. */ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -2954,6 +2975,20 @@ while (!gsi_end_p (gsi)) { stmt = gsi_stmt (gsi); + if (gimple_store_p (stmt)) + { + tree lhs = gimple_get_lhs (stmt); + ao_ref write; + ao_ref_init (&write, lhs); + + if (dse_classify_store (&write, stmt, false, NULL, NULL, latch_vdef) + == DSE_STORE_DEAD) + delete_dead_or_redundant_assignment (&gsi, "dead"); + else + gsi_next (&gsi); + continue; + } + if (gimple_plf (stmt, GF_PLF_2)) { gsi_next (&gsi); @@ -2974,11 +3009,12 @@ changed. */ unsigned int -tree_if_conversion (struct loop *loop) +tree_if_conversion (class loop *loop, vec<gimple *> *preds) { unsigned int todo = 0; bool aggressive_if_conv; - struct loop *rloop; + class loop *rloop; + bitmap exit_bbs; again: rloop = NULL; @@ -2992,7 +3028,7 @@ aggressive_if_conv = loop->force_vectorize; if (!aggressive_if_conv) { - struct loop *outer_loop = loop_outer (loop); + class loop *outer_loop = loop_outer (loop); if (outer_loop && outer_loop->force_vectorize) aggressive_if_conv = true; } @@ -3018,10 +3054,10 @@ || any_complicated_phi || flag_tree_loop_if_convert != 1) { - struct loop *vloop + class loop *vloop = (versionable_outer_loop_p (loop_outer (loop)) ? loop_outer (loop) : loop); - struct loop *nloop = version_loop_for_if_conversion (vloop); + class loop *nloop = version_loop_for_if_conversion (vloop, preds); if (nloop == NULL) goto cleanup; if (vloop != loop) @@ -3053,8 +3089,18 @@ on-the-fly. */ combine_blocks (loop); + /* Perform local CSE, this esp. helps the vectorizer analysis if loads + and stores are involved. CSE only the loop body, not the entry + PHIs, those are to be kept in sync with the non-if-converted copy. + ??? We'll still keep dead stores though. */ + exit_bbs = BITMAP_ALLOC (NULL); + bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index); + bitmap_set_bit (exit_bbs, loop->latch->index); + todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs); + /* Delete dead predicate computations. */ - ifcvt_local_dce (loop->header); + ifcvt_local_dce (loop); + BITMAP_FREE (exit_bbs); todo |= TODO_cleanup_cfg; @@ -3119,17 +3165,18 @@ unsigned int pass_if_conversion::execute (function *fun) { - struct loop *loop; + class loop *loop; unsigned todo = 0; if (number_of_loops (fun) <= 1) return 0; + auto_vec<gimple *> preds; FOR_EACH_LOOP (loop, 0) if (flag_tree_loop_if_convert == 1 || ((flag_tree_loop_vectorize || loop->force_vectorize) && !loop->dont_vectorize)) - todo |= tree_if_conversion (loop); + todo |= tree_if_conversion (loop, &preds); if (todo) { @@ -3144,7 +3191,32 @@ gcc_assert (!bb->aux); } - return todo; + /* Perform IL update now, it might elide some loops. */ + if (todo & TODO_cleanup_cfg) + { + cleanup_tree_cfg (); + if (need_ssa_update_p (fun)) + todo |= TODO_update_ssa; + } + if (todo & TODO_update_ssa_any) + update_ssa (todo & TODO_update_ssa_any); + + /* If if-conversion elided the loop fall back to the original one. */ + for (unsigned i = 0; i < preds.length (); ++i) + { + gimple *g = preds[i]; + if (!gimple_bb (g)) + continue; + unsigned ifcvt_loop = tree_to_uhwi (gimple_call_arg (g, 0)); + if (!get_loop (fun, ifcvt_loop)) + { + if (dump_file) + fprintf (dump_file, "If-converted loop vanished\n"); + fold_loop_internal_call (g, boolean_false_node); + } + } + + return 0; } } // anon namespace