From 4ba5ea117ac17ad00bb26b2cb64588ae345a6491 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 11 Apr 2013 11:21:18 +0000 Subject: [PATCH] re PR tree-optimization/56878 (Issue with candidate choice in vect_gen_niters_for_prolog_loop.) 2013-04-11 Richard Biener PR tree-optimization/56878 * tree-flow.h (outermost_invariant_loop_for_expr): Declare. * tree-ssa-loop-ivopts.c (outermost_invariant_loop_for_expr): New function. * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Prefer to align the DR with the most invariant base address. From-SVN: r197769 --- gcc/ChangeLog | 9 +++++++++ gcc/tree-flow.h | 1 + gcc/tree-ssa-loop-ivopts.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++ gcc/tree-vect-data-refs.c | 31 +++++++++++++++++++++--------- 4 files changed, 80 insertions(+), 9 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9ef2302c99..de5bee5d92e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-04-11 Richard Biener + + PR tree-optimization/56878 + * tree-flow.h (outermost_invariant_loop_for_expr): Declare. + * tree-ssa-loop-ivopts.c (outermost_invariant_loop_for_expr): + New function. + * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): + Prefer to align the DR with the most invariant base address. + 2013-04-11 Senthil Kumar Selvaraj * opts.c (common_handle_option): Fix formatting and add FALLTHRU diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 389246d406f..227fe56d00e 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -749,6 +749,7 @@ extern void tree_check_data_deps (void); /* In tree-ssa-loop-ivopts.c */ bool expr_invariant_in_loop_p (struct loop *, tree); bool stmt_invariant_in_loop_p (struct loop *, gimple); +struct loop *outermost_invariant_loop_for_expr (struct loop *, tree); bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode, addr_space_t); bool may_be_nonaddressable_p (tree expr); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 2940bf10044..0099275d49f 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1367,6 +1367,54 @@ find_interesting_uses_cond (struct ivopts_data *data, gimple stmt) record_use (data, NULL, civ, stmt, USE_COMPARE); } +/* Returns the outermost loop EXPR is obviously invariant in + relative to the loop LOOP, i.e. if all its operands are defined + outside of the returned loop. Returns NULL if EXPR is not + even obviously invariant in LOOP. */ + +struct loop * +outermost_invariant_loop_for_expr (struct loop *loop, tree expr) +{ + basic_block def_bb; + unsigned i, len; + + if (is_gimple_min_invariant (expr)) + return current_loops->tree_root; + + if (TREE_CODE (expr) == SSA_NAME) + { + def_bb = gimple_bb (SSA_NAME_DEF_STMT (expr)); + if (def_bb) + { + if (flow_bb_inside_loop_p (loop, def_bb)) + return NULL; + return superloop_at_depth (loop, + loop_depth (def_bb->loop_father) + 1); + } + + return current_loops->tree_root; + } + + if (!EXPR_P (expr)) + return NULL; + + unsigned maxdepth = 0; + len = TREE_OPERAND_LENGTH (expr); + for (i = 0; i < len; i++) + { + struct loop *ivloop; + if (!TREE_OPERAND (expr, i)) + continue; + + ivloop = outermost_invariant_loop_for_expr (loop, TREE_OPERAND (expr, i)); + if (!ivloop) + return NULL; + maxdepth = MAX (maxdepth, loop_depth (ivloop)); + } + + return superloop_at_depth (loop, maxdepth); +} + /* Returns true if expression EXPR is obviously invariant in LOOP, i.e. if all its operands are defined outside of the LOOP. LOOP should not be the function body. */ diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index e20ab1f6d17..64f2a8b6d9e 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -1456,20 +1456,35 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) } else { - /* If we don't know all the misalignment values, we prefer - peeling for data-ref that has maximum number of data-refs + /* If we don't know any misalignment values, we prefer + peeling for data-ref that has the maximum number of data-refs with the same alignment, unless the target prefers to align stores over load. */ if (all_misalignments_unknown) { - if (same_align_drs_max - < STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length () - || !dr0) + unsigned same_align_drs + = STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length (); + if (!dr0 + || same_align_drs_max < same_align_drs) { - same_align_drs_max - = STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length (); + same_align_drs_max = same_align_drs; dr0 = dr; } + /* For data-refs with the same number of related + accesses prefer the one where the misalign + computation will be invariant in the outermost loop. */ + else if (same_align_drs_max == same_align_drs) + { + struct loop *ivloop0, *ivloop; + ivloop0 = outermost_invariant_loop_for_expr + (loop, DR_BASE_ADDRESS (dr0)); + ivloop = outermost_invariant_loop_for_expr + (loop, DR_BASE_ADDRESS (dr)); + if ((ivloop && !ivloop0) + || (ivloop && ivloop0 + && flow_loop_nested_p (ivloop, ivloop0))) + dr0 = dr; + } if (!first_store && DR_IS_WRITE (dr)) first_store = dr; @@ -1478,8 +1493,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* If there are both known and unknown misaligned accesses in the loop, we choose peeling amount according to the known accesses. */ - - if (!supportable_dr_alignment) { dr0 = dr; -- 2.11.4.GIT