+2013-04-11 Richard Biener <rguenther@suse.de>
+
+ 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 <senthil_kumar.selvaraj@atmel.com>
* opts.c (common_handle_option): Fix formatting and add FALLTHRU
/* 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);
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. */
}
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;
/* 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;