--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
+
+int A[1024 * 2];
+
+int foo (unsigned offset, unsigned N)
+{
+ int sum = 0;
+
+ for (unsigned i = 0; i < N; i++)
+ sum += A[i + offset];
+
+ return sum;
+}
+
+/* Loop can be vectorized by referring "i + offset" is nonwrapping from array. */
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target { ! { avr-*-* msp430-*-* pru-*-* } } } } } */
DECL_NONALIASED in
VAR_DECL
+ CHREC_NOWRAP in
+ POLYNOMIAL_CHREC
+
deprecated_flag:
TREE_DEPRECATED in
dump_generic_node (pp, CHREC_LEFT (node), spc, flags, false);
pp_string (pp, ", +, ");
dump_generic_node (pp, CHREC_RIGHT (node), spc, flags, false);
- pp_string (pp, "}_");
+ pp_string (pp, !CHREC_NOWRAP (node) ? "}_" : "}<nw>_");
pp_scalar (pp, "%u", CHREC_VARIABLE (node));
is_stmt = false;
break;
return res;
}
+/* If CHREC doesn't overflow, set the nonwrapping flag. */
+
+void record_nonwrapping_chrec (tree chrec)
+{
+ CHREC_NOWRAP(chrec) = 1;
+
+ if (dump_file && (dump_flags & TDF_SCEV))
+ {
+ fprintf (dump_file, "(record_nonwrapping_chrec: ");
+ print_generic_expr (dump_file, chrec);
+ fprintf (dump_file, ")\n");
+ }
+}
+
+/* Return true if CHREC's nonwrapping flag is set. */
+
+bool nonwrapping_chrec_p (tree chrec)
+{
+ if (!chrec || TREE_CODE(chrec) != POLYNOMIAL_CHREC)
+ return false;
+
+ return CHREC_NOWRAP(chrec);
+}
+
/* Analyzes and returns the scalar evolution of VAR address in LOOP. */
static tree
bool);
extern bool iv_can_overflow_p (class loop *, tree, tree, tree);
extern tree compute_overall_effect_of_inner_loop (class loop *, tree);
+extern void record_nonwrapping_chrec (tree);
+extern bool nonwrapping_chrec_p (tree);
/* Returns the basic block preceding LOOP, or the CFG entry block when
the loop is function's body. */
/* If access is not executed on every iteration, we must ensure that overlow
may not make the access valid later. */
- if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt))
- && scev_probably_wraps_p (NULL_TREE,
- initial_condition_in_loop_num (ev, loop->num),
- step, data->stmt, loop, true))
- upper = false;
+ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, gimple_bb (data->stmt)))
+ {
+ if (scev_probably_wraps_p (NULL_TREE,
+ initial_condition_in_loop_num (ev, loop->num),
+ step, data->stmt, loop, true))
+ upper = false;
+ }
+ else
+ record_nonwrapping_chrec (ev);
record_nonwrapping_iv (loop, init, step, data->stmt, low, high, false, upper);
return true;
if (flag_delete_null_pointer_checks && int_cst_value (low) == 0)
low = build_int_cstu (TREE_TYPE (low), TYPE_ALIGN_UNIT (TREE_TYPE (type)));
+ record_nonwrapping_chrec (scev);
record_nonwrapping_iv (loop, base, step, stmt, low, high, false, true);
}
high = wide_int_to_tree (type, r.upper_bound ());
}
+ record_nonwrapping_chrec (scev);
record_nonwrapping_iv (loop, base, step, stmt, low, high, false, true);
}
if (loop_exits_before_overflow (base, step, at_stmt, loop))
return false;
+ /* Check the nonwrapping flag, which may be set by niter analysis (e.g., the
+ above loop exits before overflow). */
+ if (var && nonwrapping_chrec_p (analyze_scalar_evolution (loop, var)))
+ return false;
+
/* At this point we still don't have a proof that the iv does not
overflow: give up. */
return true;
analysis are done under the assumptions. */
loop_constraint_set (loop, LOOP_C_FINITE);
}
+ else
+ /* Clear the existing niter information to make sure the nonwrapping flag
+ will be calculated and set propriately. */
+ free_numbers_of_iterations_estimates (loop);
auto_vector_modes vector_modes;
/* Autodetect first vector size we try. */
#define COND_EXPR_ELSE(NODE) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 2))
/* Accessors for the chains of recurrences. */
-#define CHREC_LEFT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 0)
-#define CHREC_RIGHT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 1)
-#define CHREC_VARIABLE(NODE) POLYNOMIAL_CHREC_CHECK (NODE)->base.u.chrec_var
+#define CHREC_LEFT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 0)
+#define CHREC_RIGHT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 1)
+#define CHREC_VARIABLE(NODE) POLYNOMIAL_CHREC_CHECK (NODE)->base.u.chrec_var
+/* Nonzero if this chrec doesn't overflow (i.e., nonwrapping). */
+#define CHREC_NOWRAP(NODE) POLYNOMIAL_CHREC_CHECK (NODE)->base.nothrow_flag
/* LABEL_EXPR accessor. This gives access to the label associated with
the given label expression. */