* cfgloop.h (struct loop): New field constraints.
(LOOP_C_INFINITE, LOOP_C_FINITE): New macros.
(loop_constraint_set, loop_constraint_clr, loop_constraint_set_p): New
functions.
* cfgloop.c (alloc_loop): Initialize new field.
* cfgloopmanip.c (copy_loop_info): Copy constraints.
* tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions):
Adjust niter analysis wrto loop constraints.
* doc/loop.texi (@node Number of iterations): Add description for loop
constraints.
From-SVN: r238876
+2016-07-29 Bin Cheng <bin.cheng@arm.com>
+
+ * cfgloop.h (struct loop): New field constraints.
+ (LOOP_C_INFINITE, LOOP_C_FINITE): New macros.
+ (loop_constraint_set, loop_constraint_clr, loop_constraint_set_p): New
+ functions.
+ * cfgloop.c (alloc_loop): Initialize new field.
+ * cfgloopmanip.c (copy_loop_info): Copy constraints.
+ * tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions):
+ Adjust niter analysis wrto loop constraints.
+ * doc/loop.texi (@node Number of iterations): Add description for loop
+ constraints.
+
2016-07-29 Marek Polacek <polacek@redhat.com>
PR c/7652
loop->exits = ggc_cleared_alloc<loop_exit> ();
loop->exits->next = loop->exits->prev = loop->exits;
loop->can_be_parallel = false;
+ loop->constraints = 0;
loop->nb_iterations_upper_bound = 0;
loop->nb_iterations_likely_upper_bound = 0;
loop->nb_iterations_estimate = 0;
of the loop can be safely evaluated concurrently. */
int safelen;
+ /* Constraints are generally set by consumers and affect certain
+ semantics of niter analyzer APIs. Currently the APIs affected are
+ number_of_iterations_exit* functions and their callers. One typical
+ use case of constraints is to vectorize possibly infinite loop:
+
+ 1) Compute niter->assumptions by calling niter analyzer API and
+ record it as possible condition for loop versioning.
+ 2) Clear buffered result of niter/scev analyzer.
+ 3) Set constraint LOOP_C_FINITE assuming the loop is finite.
+ 4) Analyze data references. Since data reference analysis depends
+ on niter/scev analyzer, the point is that niter/scev analysis
+ is done under circumstance of LOOP_C_FINITE constraint.
+ 5) Version the loop with niter->assumptions computed in step 1).
+ 6) Vectorize the versioned loop in which niter->assumptions is
+ checked to be true.
+ 7) Update constraints in versioned loops so that niter analyzer
+ in following passes can use it.
+
+ Note consumers are usually the loop optimizers and it is consumers'
+ responsibility to set/clear constraints correctly. Failing to do
+ that might result in hard to track down bugs in niter/scev consumers. */
+ unsigned constraints;
+
/* True if this loop should never be vectorized. */
bool dont_vectorize;
basic_block former_header;
};
+/* Set if the loop is known to be infinite. */
+#define LOOP_C_INFINITE (1 << 0)
+/* Set if the loop is known to be finite without any assumptions. */
+#define LOOP_C_FINITE (1 << 1)
+
+/* Set C to the LOOP constraint. */
+static inline void
+loop_constraint_set (struct loop *loop, unsigned c)
+{
+ loop->constraints |= c;
+}
+
+/* Clear C from the LOOP constraint. */
+static inline void
+loop_constraint_clear (struct loop *loop, unsigned c)
+{
+ loop->constraints &= ~c;
+}
+
+/* Check if C is set in the LOOP constraint. */
+static inline bool
+loop_constraint_set_p (struct loop *loop, unsigned c)
+{
+ return (loop->constraints & c) == c;
+}
+
/* Flags for state of loop structure. */
enum
{
target->any_estimate = loop->any_estimate;
target->nb_iterations_estimate = loop->nb_iterations_estimate;
target->estimate_state = loop->estimate_state;
+ target->constraints = loop->constraints;
target->warned_aggressive_loop_optimizations
|= loop->warned_aggressive_loop_optimizations;
target->in_oacc_kernels_region = loop->in_oacc_kernels_region;
determine number of executions of the exit condition of a single-exit
loop (i.e., the @code{number_of_latch_executions} increased by one).
+On GIMPLE, below constraint flags affect semantics of some APIs of number
+of iterations analyzer:
+
+@itemize
+@item @code{LOOP_C_INFINITE}: If this constraint flag is set, the loop
+is known to be infinite. APIs like @code{number_of_iterations_exit} can
+return false directly without doing any analysis.
+@item @code{LOOP_C_FINITE}: If this constraint flag is set, the loop is
+known to be finite, in other words, loop's number of iterations can be
+computed with @code{assumptions} be true.
+@end itemize
+
+Generally, the constraint flags are set/cleared by consumers which are
+loop optimizers. It's also the consumers' responsibility to set/clear
+constraints correctly. Failing to do that might result in hard to track
+down bugs in scev/niter consumers. One typical use case is vectorizer:
+it drives number of iterations analyzer by setting @code{LOOP_C_FINITE}
+and vectorizes possibly infinite loop by versioning loop with analysis
+result. In return, constraints set by consumers can also help number of
+iterations analyzer in following optimizers. For example, @code{niter}
+of a loop versioned under @code{assumptions} is valid unconditionally.
+
+Other constraints may be added in the future, for example, a constraint
+indicating that loops' latch must roll thus @code{may_be_zero} would be
+false unconditionally.
+
@node Dependency analysis
@section Data Dependency Analysis
@cindex Data Dependency Analysis
affine_iv iv0, iv1;
bool safe;
+ /* Nothing to analyze if the loop is known to be infinite. */
+ if (loop_constraint_set_p (loop, LOOP_C_INFINITE))
+ return false;
+
safe = dominated_by_p (CDI_DOMINATORS, loop->latch, exit->src);
if (every_iteration && !safe)
niter->max = wi::to_widest (iv_niters);
}
+ /* There is no assumptions if the loop is known to be finite. */
+ if (!integer_zerop (niter->assumptions)
+ && loop_constraint_set_p (loop, LOOP_C_FINITE))
+ niter->assumptions = boolean_true_node;
+
if (optimize >= 3)
{
niter->assumptions = simplify_using_outer_evolutions (loop,