Fixes PR 18403 and meta PR 21861.

* Makefile.in (tree-chrec.o): Depend on CFGLOOP_H and TREE_FLOW_H.
	* tree-chrec.c: Include cfgloop.h and tree-flow.h.
	(evolution_function_is_invariant_rec_p,
	evolution_function_is_invariant_p): New.
	(chrec_convert): Use an extra parameter AT_STMT for refining the
	information that is passed down to convert_step.  Integrate the
	code that was in count_ev_in_wider_type.
	* tree-chrec.h (count_ev_in_wider_type): Removed.
	(chrec_convert): Modify its declaration.
	(evolution_function_is_invariant_p): Declared.
	(evolution_function_is_affine_p): Use evolution_function_is_invariant_p.
	* tree-flow.h (can_count_iv_in_wider_type): Renamed convert_step.
	(scev_probably_wraps_p): Declared.
	* tree-scalar-evolution.c (count_ev_in_wider_type): Removed.
	(follow_ssa_edge_in_rhs, interpret_rhs_modify_expr):
	Use an extra parameter AT_STMT for refining the information that is
	passed down to convert_step.
	(follow_ssa_edge_inner_loop_phi, follow_ssa_edge,
	analyze_scalar_evolution_1): Initialize AT_STMT with the current
	analyzed statement.
	(instantiate_parameters_1): Don't know yet how to initialize AT_STMT.
	* tree-ssa-loop-ivopts.c (idx_find_step): Update the use of
	can_count_iv_in_wider_type to use convert_step.
	* tree-ssa-loop-niter.c (can_count_iv_in_wider_type_bound): Move
	code that is independent of the loop over the known iteration
	bounds to convert_step_widening, the rest is moved to
	proved_non_wrapping_p.
	(scev_probably_wraps_p): New.
	(can_count_iv_in_wider_type): Renamed convert_step.
	* tree-vrp.c (adjust_range_with_scev): Take an extra AT_STMT parameter.
	Use scev_probably_wraps_p for computing init_is_max.
	(vrp_visit_assignment): Pass the current analyzed statement to
	adjust_range_with_scev.
	(execute_vrp): Call estimate_numbers_of_iterations for refining the
	information provided by scev analyzer.

testsuite:

	* testsuite/gcc.dg/vect/vect-77.c: Remove xfail from lp64.
	* testsuite/gcc.dg/vect/vect-78.c: Same.

From-SVN: r100718
This commit is contained in:
Sebastian Pop 2005-06-07 21:51:25 +02:00 committed by Sebastian Pop
parent 89a590b340
commit 1e8552ebb2
11 changed files with 390 additions and 210 deletions

View File

@ -1,3 +1,42 @@
2005-06-07 Sebastian Pop <pop@cri.ensmp.fr>
PR 18403 and meta PR 21861.
* Makefile.in (tree-chrec.o): Depend on CFGLOOP_H and TREE_FLOW_H.
* tree-chrec.c: Include cfgloop.h and tree-flow.h.
(evolution_function_is_invariant_rec_p,
evolution_function_is_invariant_p): New.
(chrec_convert): Use an extra parameter AT_STMT for refining the
information that is passed down to convert_step. Integrate the
code that was in count_ev_in_wider_type.
* tree-chrec.h (count_ev_in_wider_type): Removed.
(chrec_convert): Modify its declaration.
(evolution_function_is_invariant_p): Declared.
(evolution_function_is_affine_p): Use evolution_function_is_invariant_p.
* tree-flow.h (can_count_iv_in_wider_type): Renamed convert_step.
(scev_probably_wraps_p): Declared.
* tree-scalar-evolution.c (count_ev_in_wider_type): Removed.
(follow_ssa_edge_in_rhs, interpret_rhs_modify_expr):
Use an extra parameter AT_STMT for refining the information that is
passed down to convert_step.
(follow_ssa_edge_inner_loop_phi, follow_ssa_edge,
analyze_scalar_evolution_1): Initialize AT_STMT with the current
analyzed statement.
(instantiate_parameters_1): Don't know yet how to initialize AT_STMT.
* tree-ssa-loop-ivopts.c (idx_find_step): Update the use of
can_count_iv_in_wider_type to use convert_step.
* tree-ssa-loop-niter.c (can_count_iv_in_wider_type_bound): Move
code that is independent of the loop over the known iteration
bounds to convert_step_widening, the rest is moved to
proved_non_wrapping_p.
(scev_probably_wraps_p): New.
(can_count_iv_in_wider_type): Renamed convert_step.
* tree-vrp.c (adjust_range_with_scev): Take an extra AT_STMT parameter.
Use scev_probably_wraps_p for computing init_is_max.
(vrp_visit_assignment): Pass the current analyzed statement to
adjust_range_with_scev.
(execute_vrp): Call estimate_numbers_of_iterations for refining the
information provided by scev analyzer.
2005-06-07 Eric Christopher <echristo@redhat.com>
* config/mips/predicates.md (sleu_operand): Use

View File

@ -1873,7 +1873,7 @@ tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
$(TM_H) coretypes.h
tree-chrec.o: tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(GGC_H) $(TREE_H) tree-chrec.h tree-pass.h $(PARAMS_H) \
$(DIAGNOSTIC_H) $(VARRAY_H)
$(DIAGNOSTIC_H) $(VARRAY_H) $(CFGLOOP_H) $(TREE_FLOW_H)
tree-scalar-evolution.o: tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) \
$(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \

View File

@ -39,7 +39,7 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -40,7 +40,7 @@ int main (void)
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { lp64 || vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail { vect_no_align } } } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -32,6 +32,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree.h"
#include "diagnostic.h"
#include "varray.h"
#include "cfgloop.h"
#include "tree-flow.h"
#include "tree-chrec.h"
#include "tree-pass.h"
#include "params.h"
@ -909,6 +911,57 @@ tree_contains_chrecs (tree expr, int *size)
}
}
/* Recursive helper function. */
static bool
evolution_function_is_invariant_rec_p (tree chrec, int loopnum)
{
if (evolution_function_is_constant_p (chrec))
return true;
if (TREE_CODE (chrec) == SSA_NAME
&& expr_invariant_in_loop_p (current_loops->parray[loopnum],
chrec))
return true;
if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
&& CHREC_VARIABLE (chrec) == (unsigned) loopnum)
return false;
switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
{
case 2:
if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 1),
loopnum))
return false;
case 1:
if (!evolution_function_is_invariant_rec_p (TREE_OPERAND (chrec, 0),
loopnum))
return false;
return true;
default:
return false;
}
return false;
}
/* Return true if CHREC is invariant in loop LOOPNUM, false otherwise. */
bool
evolution_function_is_invariant_p (tree chrec, int loopnum)
{
if (evolution_function_is_constant_p (chrec))
return true;
if (current_loops != NULL)
return evolution_function_is_invariant_rec_p (chrec, loopnum);
return false;
}
/* Determine whether the given tree is an affine multivariate
evolution. */
@ -1019,11 +1072,17 @@ nb_vars_in_chrec (tree chrec)
/* Convert CHREC to TYPE. The following is rule is always true:
TREE_TYPE (chrec) == TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE
(CHREC_RIGHT (chrec)). An example of what could happen when adding
two chrecs and the type of the CHREC_RIGHT is different than
CHREC_LEFT is:
/* Convert CHREC to TYPE. When the analyzer knows the context in
which the CHREC is built, it sets AT_STMT to the statement that
contains the definition of the analyzed variable, otherwise the
conversion is less accurate: the information is used for
determining a more accurate estimation of the number of iterations.
By default AT_STMT could be safely set to NULL_TREE.
The following rule is always true: TREE_TYPE (chrec) ==
TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE (CHREC_RIGHT (chrec)).
An example of what could happen when adding two chrecs and the type
of the CHREC_RIGHT is different than CHREC_LEFT is:
{(uint) 0, +, (uchar) 10} +
{(uint) 0, +, (uchar) 250}
@ -1038,11 +1097,10 @@ nb_vars_in_chrec (tree chrec)
*/
tree
chrec_convert (tree type,
tree chrec)
chrec_convert (tree type, tree chrec, tree at_stmt)
{
tree ct;
tree ct, res;
if (automatically_generated_chrec_p (chrec))
return chrec;
@ -1050,43 +1108,44 @@ chrec_convert (tree type,
if (ct == type)
return chrec;
if (TYPE_PRECISION (ct) < TYPE_PRECISION (type))
return count_ev_in_wider_type (type, chrec);
switch (TREE_CODE (chrec))
if (evolution_function_is_affine_p (chrec))
{
case POLYNOMIAL_CHREC:
tree step = convert_step (current_loops->parray[CHREC_VARIABLE (chrec)],
type, CHREC_LEFT (chrec), CHREC_RIGHT (chrec),
at_stmt);
if (!step)
return fold_convert (type, chrec);
return build_polynomial_chrec (CHREC_VARIABLE (chrec),
chrec_convert (type,
CHREC_LEFT (chrec)),
chrec_convert (type,
CHREC_RIGHT (chrec)));
default:
{
tree res = fold_convert (type, chrec);
/* Don't propagate overflows. */
if (CONSTANT_CLASS_P (res))
{
TREE_CONSTANT_OVERFLOW (res) = 0;
TREE_OVERFLOW (res) = 0;
}
/* But reject constants that don't fit in their type after conversion.
This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
and can cause problems later when computing niters of loops. Note
that we don't do the check before converting because we don't want
to reject conversions of negative chrecs to unsigned types. */
if (TREE_CODE (res) == INTEGER_CST
&& TREE_CODE (type) == INTEGER_TYPE
&& !int_fits_type_p (res, type))
res = chrec_dont_know;
return res;
}
chrec_convert (type, CHREC_LEFT (chrec),
at_stmt),
step);
}
if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
return chrec_dont_know;
res = fold_convert (type, chrec);
/* Don't propagate overflows. */
if (CONSTANT_CLASS_P (res))
{
TREE_CONSTANT_OVERFLOW (res) = 0;
TREE_OVERFLOW (res) = 0;
}
/* But reject constants that don't fit in their type after conversion.
This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
and can cause problems later when computing niters of loops. Note
that we don't do the check before converting because we don't want
to reject conversions of negative chrecs to unsigned types. */
if (TREE_CODE (res) == INTEGER_CST
&& TREE_CODE (type) == INTEGER_TYPE
&& !int_fits_type_p (res, type))
res = chrec_dont_know;
return res;
}
/* Returns the type of the chrec. */

View File

@ -67,8 +67,7 @@ tree_is_chrec (tree expr)
extern tree chrec_fold_plus (tree, tree, tree);
extern tree chrec_fold_minus (tree, tree, tree);
extern tree chrec_fold_multiply (tree, tree, tree);
extern tree chrec_convert (tree, tree);
extern tree count_ev_in_wider_type (tree, tree);
extern tree chrec_convert (tree, tree, tree);
extern tree chrec_type (tree);
/* Operations. */
@ -146,6 +145,7 @@ evolution_function_is_constant_p (tree chrec)
}
}
extern bool evolution_function_is_invariant_p (tree, int);
/* Determine whether the given tree is an affine evolution function or not. */
static inline bool
@ -157,8 +157,10 @@ evolution_function_is_affine_p (tree chrec)
switch (TREE_CODE (chrec))
{
case POLYNOMIAL_CHREC:
if (evolution_function_is_constant_p (CHREC_LEFT (chrec))
&& evolution_function_is_constant_p (CHREC_RIGHT (chrec)))
if (evolution_function_is_invariant_p (CHREC_LEFT (chrec),
CHREC_VARIABLE (chrec))
&& evolution_function_is_invariant_p (CHREC_RIGHT (chrec),
CHREC_VARIABLE (chrec)))
return true;
else
return false;

View File

@ -658,7 +658,8 @@ tree find_loop_niter (struct loop *, edge *);
tree loop_niter_by_eval (struct loop *, edge);
tree find_loop_niter_by_eval (struct loop *, edge *);
void estimate_numbers_of_iterations (struct loops *);
tree can_count_iv_in_wider_type (struct loop *, tree, tree, tree, tree);
bool scev_probably_wraps_p (tree, tree, tree, tree, struct loop *, bool *);
tree convert_step (struct loop *, tree, tree, tree, tree);
void free_numbers_of_iterations_estimates (struct loops *);
void rewrite_into_loop_closed_ssa (bitmap, unsigned);
void verify_loop_closed_ssa (void);

View File

@ -349,33 +349,6 @@ find_var_scev_info (tree var)
return &res->chrec;
}
/* Tries to express CHREC in wider type TYPE. */
tree
count_ev_in_wider_type (tree type, tree chrec)
{
tree base, step;
struct loop *loop;
if (!evolution_function_is_affine_p (chrec))
return fold_convert (type, chrec);
base = CHREC_LEFT (chrec);
step = CHREC_RIGHT (chrec);
loop = current_loops->parray[CHREC_VARIABLE (chrec)];
/* TODO -- if we knew the statement at that the conversion occurs,
we could pass it to can_count_iv_in_wider_type and get a better
result. */
step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
if (!step)
return fold_convert (type, chrec);
base = chrec_convert (type, base);
return build_polynomial_chrec (CHREC_VARIABLE (chrec),
base, step);
}
/* Return true when CHREC contains symbolic names defined in
LOOP_NB. */
@ -1052,6 +1025,7 @@ static bool follow_ssa_edge (struct loop *loop, tree, tree, tree *);
static bool
follow_ssa_edge_in_rhs (struct loop *loop,
tree at_stmt,
tree rhs,
tree halting_phi,
tree *evolution_of_loop)
@ -1071,9 +1045,10 @@ follow_ssa_edge_in_rhs (struct loop *loop,
{
case NOP_EXPR:
/* This assignment is under the form "a_1 = (cast) rhs. */
res = follow_ssa_edge_in_rhs (loop, TREE_OPERAND (rhs, 0), halting_phi,
evolution_of_loop);
*evolution_of_loop = chrec_convert (TREE_TYPE (rhs), *evolution_of_loop);
res = follow_ssa_edge_in_rhs (loop, at_stmt, TREE_OPERAND (rhs, 0),
halting_phi, evolution_of_loop);
*evolution_of_loop = chrec_convert (TREE_TYPE (rhs),
*evolution_of_loop, at_stmt);
break;
case INTEGER_CST:
@ -1107,7 +1082,7 @@ follow_ssa_edge_in_rhs (struct loop *loop,
if (res)
*evolution_of_loop = add_to_evolution
(loop->num,
chrec_convert (type_rhs, *evolution_of_loop),
chrec_convert (type_rhs, *evolution_of_loop, at_stmt),
PLUS_EXPR, rhs1);
else
@ -1119,7 +1094,7 @@ follow_ssa_edge_in_rhs (struct loop *loop,
if (res)
*evolution_of_loop = add_to_evolution
(loop->num,
chrec_convert (type_rhs, *evolution_of_loop),
chrec_convert (type_rhs, *evolution_of_loop, at_stmt),
PLUS_EXPR, rhs0);
}
}
@ -1133,7 +1108,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop);
if (res)
*evolution_of_loop = add_to_evolution
(loop->num, chrec_convert (type_rhs, *evolution_of_loop),
(loop->num, chrec_convert (type_rhs, *evolution_of_loop,
at_stmt),
PLUS_EXPR, rhs1);
}
}
@ -1147,7 +1123,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop);
if (res)
*evolution_of_loop = add_to_evolution
(loop->num, chrec_convert (type_rhs, *evolution_of_loop),
(loop->num, chrec_convert (type_rhs, *evolution_of_loop,
at_stmt),
PLUS_EXPR, rhs0);
}
@ -1174,7 +1151,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop);
if (res)
*evolution_of_loop = add_to_evolution
(loop->num, chrec_convert (type_rhs, *evolution_of_loop),
(loop->num, chrec_convert (type_rhs, *evolution_of_loop,
at_stmt),
MINUS_EXPR, rhs1);
}
else
@ -1391,7 +1369,8 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop,
/* Follow the edges that exit the inner loop. */
bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
if (!flow_bb_inside_loop_p (loop, bb))
res = res || follow_ssa_edge_in_rhs (outer_loop, arg, halting_phi,
res = res || follow_ssa_edge_in_rhs (outer_loop, loop_phi_node,
arg, halting_phi,
evolution_of_loop);
}
@ -1404,7 +1383,7 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop,
/* Otherwise, compute the overall effect of the inner loop. */
ev = compute_overall_effect_of_inner_loop (loop, ev);
return follow_ssa_edge_in_rhs (outer_loop, ev, halting_phi,
return follow_ssa_edge_in_rhs (outer_loop, loop_phi_node, ev, halting_phi,
evolution_of_loop);
}
@ -1456,7 +1435,7 @@ follow_ssa_edge (struct loop *loop,
return false;
case MODIFY_EXPR:
return follow_ssa_edge_in_rhs (loop,
return follow_ssa_edge_in_rhs (loop, def,
TREE_OPERAND (def, 1),
halting_phi,
evolution_of_loop);
@ -1665,14 +1644,14 @@ interpret_condition_phi (struct loop *loop, tree condition_phi)
analyze the effect of an inner loop: see interpret_loop_phi. */
static tree
interpret_rhs_modify_expr (struct loop *loop,
interpret_rhs_modify_expr (struct loop *loop, tree at_stmt,
tree opnd1, tree type)
{
tree res, opnd10, opnd11, chrec10, chrec11;
if (is_gimple_min_invariant (opnd1))
return chrec_convert (type, opnd1);
return chrec_convert (type, opnd1, at_stmt);
switch (TREE_CODE (opnd1))
{
case PLUS_EXPR:
@ -1680,8 +1659,8 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10);
chrec11 = chrec_convert (type, chrec11);
chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_plus (type, chrec10, chrec11);
break;
@ -1690,15 +1669,15 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10);
chrec11 = chrec_convert (type, chrec11);
chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_minus (type, chrec10, chrec11);
break;
case NEGATE_EXPR:
opnd10 = TREE_OPERAND (opnd1, 0);
chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec10 = chrec_convert (type, chrec10);
chrec10 = chrec_convert (type, chrec10, at_stmt);
res = chrec_fold_minus (type, build_int_cst (type, 0), chrec10);
break;
@ -1707,25 +1686,27 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10);
chrec11 = chrec_convert (type, chrec11);
chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_multiply (type, chrec10, chrec11);
break;
case SSA_NAME:
res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1));
res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1),
at_stmt);
break;
case ASSERT_EXPR:
opnd10 = ASSERT_EXPR_VAR (opnd1);
res = chrec_convert (type, analyze_scalar_evolution (loop, opnd10));
res = chrec_convert (type, analyze_scalar_evolution (loop, opnd10),
at_stmt);
break;
case NOP_EXPR:
case CONVERT_EXPR:
opnd10 = TREE_OPERAND (opnd1, 0);
chrec10 = analyze_scalar_evolution (loop, opnd10);
res = chrec_convert (type, chrec10);
res = chrec_convert (type, chrec10, at_stmt);
break;
default:
@ -1775,7 +1756,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
return chrec_dont_know;
if (TREE_CODE (var) != SSA_NAME)
return interpret_rhs_modify_expr (loop, var, type);
return interpret_rhs_modify_expr (loop, NULL_TREE, var, type);
def = SSA_NAME_DEF_STMT (var);
bb = bb_for_stmt (def);
@ -1809,7 +1790,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
switch (TREE_CODE (def))
{
case MODIFY_EXPR:
res = interpret_rhs_modify_expr (loop, TREE_OPERAND (def, 1), type);
res = interpret_rhs_modify_expr (loop, def, TREE_OPERAND (def, 1), type);
break;
case PHI_NODE:
@ -2093,7 +2074,7 @@ instantiate_parameters_1 (struct loop *loop, tree chrec,
if (op0 == TREE_OPERAND (chrec, 0))
return chrec;
return chrec_convert (TREE_TYPE (chrec), op0);
return chrec_convert (TREE_TYPE (chrec), op0, NULL_TREE);
case SCEV_NOT_KNOWN:
return chrec_dont_know;

View File

@ -1442,11 +1442,8 @@ idx_find_step (tree base, tree *idx, void *data)
/* The step for pointer arithmetics already is 1 byte. */
step = build_int_cst (sizetype, 1);
if (TYPE_PRECISION (TREE_TYPE (iv->base)) < TYPE_PRECISION (sizetype))
iv_step = can_count_iv_in_wider_type (dta->ivopts_data->current_loop,
sizetype, iv->base, iv->step, dta->stmt);
else
iv_step = fold_convert (sizetype, iv->step);
iv_step = convert_step (dta->ivopts_data->current_loop,
sizetype, iv->base, iv->step, dta->stmt);
if (!iv_step)
{

View File

@ -1445,13 +1445,18 @@ stmt_dominates_stmt_p (tree s1, tree s2)
return dominated_by_p (CDI_DOMINATORS, bb2, bb1);
}
/* Checks whether it is correct to count the induction variable BASE + STEP * I
at AT_STMT in wider TYPE, using the fact that statement OF is executed at
most BOUND times in the loop. If it is possible, return the value of step
of the induction variable in the TYPE, otherwise return NULL_TREE.
/* Return true when it is possible to prove that the induction
variable does not wrap: vary outside the type specified bounds.
Checks whether BOUND < VALID_NITER that means in the context of iv
conversion that all the iterations in the loop are safe: not
producing wraps.
The statement NITER_BOUND->AT_STMT is executed at most
NITER_BOUND->BOUND times in the loop.
ADDITIONAL is the additional condition recorded for operands of the bound.
This is useful in the following case, created by loop header copying:
NITER_BOUND->ADDITIONAL is the additional condition recorded for
operands of the bound. This is useful in the following case,
created by loop header copying:
i = 0;
if (n > 0)
@ -1465,108 +1470,211 @@ stmt_dominates_stmt_p (tree s1, tree s2)
assumption "n > 0" says us that the value of the number of iterations is at
most MAX_TYPE - 1 (without this assumption, it might overflow). */
static tree
can_count_iv_in_wider_type_bound (tree type, tree base, tree step,
tree at_stmt,
tree bound,
tree additional,
tree of)
static bool
proved_non_wrapping_p (tree at_stmt,
struct nb_iter_bound *niter_bound,
tree new_type,
tree valid_niter)
{
tree inner_type = TREE_TYPE (base), b, bplusstep, new_step, new_step_abs;
tree valid_niter, extreme, unsigned_type, delta, bound_type;
tree cond;
tree bound = niter_bound->bound;
b = fold_convert (type, base);
bplusstep = fold_convert (type,
fold_build2 (PLUS_EXPR, inner_type, base, step));
new_step = fold_build2 (MINUS_EXPR, type, bplusstep, b);
if (TREE_CODE (new_step) != INTEGER_CST)
if (TYPE_PRECISION (new_type) > TYPE_PRECISION (TREE_TYPE (bound)))
bound = fold_convert (unsigned_type_for (new_type), bound);
else
valid_niter = fold_convert (TREE_TYPE (bound), valid_niter);
/* After the statement niter_bound->at_stmt we know that anything is
executed at most BOUND times. */
if (at_stmt && stmt_dominates_stmt_p (niter_bound->at_stmt, at_stmt))
cond = fold_build2 (GE_EXPR, boolean_type_node, valid_niter, bound);
/* Before the statement niter_bound->at_stmt we know that anything
is executed at most BOUND + 1 times. */
else
cond = fold_build2 (GT_EXPR, boolean_type_node, valid_niter, bound);
if (nonzero_p (cond))
return true;
/* Try taking additional conditions into account. */
cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
invert_truthvalue (niter_bound->additional),
cond);
if (nonzero_p (cond))
return true;
return false;
}
/* Checks whether it is correct to count the induction variable BASE +
STEP * I at AT_STMT in a wider type NEW_TYPE, using the bounds on
numbers of iterations of a LOOP. If it is possible, return the
value of step of the induction variable in the NEW_TYPE, otherwise
return NULL_TREE. */
static tree
convert_step_widening (struct loop *loop, tree new_type, tree base, tree step,
tree at_stmt)
{
struct nb_iter_bound *bound;
tree base_in_new_type, base_plus_step_in_new_type, step_in_new_type;
tree delta, step_abs;
tree unsigned_type, valid_niter;
/* Compute the new step. For example, {(uchar) 100, +, (uchar) 240}
is converted to {(uint) 100, +, (uint) 0xfffffff0} in order to
keep the values of the induction variable unchanged: 100, 84, 68,
...
Another example is: (uint) {(uchar)100, +, (uchar)3} is converted
to {(uint)100, +, (uint)3}.
Before returning the new step, verify that the number of
iterations is less than DELTA / STEP_ABS (i.e. in the previous
example (256 - 100) / 3) such that the iv does not wrap (in which
case the operations are too difficult to be represented and
handled: the values of the iv should be taken modulo 256 in the
wider type; this is not implemented). */
base_in_new_type = fold_convert (new_type, base);
base_plus_step_in_new_type =
fold_convert (new_type,
fold_build2 (PLUS_EXPR, TREE_TYPE (base), base, step));
step_in_new_type = fold_build2 (MINUS_EXPR, new_type,
base_plus_step_in_new_type,
base_in_new_type);
if (TREE_CODE (step_in_new_type) != INTEGER_CST)
return NULL_TREE;
switch (compare_trees (bplusstep, b))
switch (compare_trees (base_plus_step_in_new_type, base_in_new_type))
{
case -1:
extreme = upper_bound_in_type (type, inner_type);
delta = fold_build2 (MINUS_EXPR, type, extreme, b);
new_step_abs = new_step;
break;
{
tree extreme = upper_bound_in_type (new_type, TREE_TYPE (base));
delta = fold_build2 (MINUS_EXPR, new_type, extreme,
base_in_new_type);
step_abs = step_in_new_type;
break;
}
case 1:
extreme = lower_bound_in_type (type, inner_type);
new_step_abs = fold_build1 (NEGATE_EXPR, type, new_step);
delta = fold_build2 (MINUS_EXPR, type, b, extreme);
break;
{
tree extreme = lower_bound_in_type (new_type, TREE_TYPE (base));
delta = fold_build2 (MINUS_EXPR, new_type, base_in_new_type,
extreme);
step_abs = fold_build1 (NEGATE_EXPR, new_type, step_in_new_type);
break;
}
case 0:
return new_step;
return step_in_new_type;
default:
return NULL_TREE;
}
unsigned_type = unsigned_type_for (type);
unsigned_type = unsigned_type_for (new_type);
delta = fold_convert (unsigned_type, delta);
new_step_abs = fold_convert (unsigned_type, new_step_abs);
step_abs = fold_convert (unsigned_type, step_abs);
valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type,
delta, new_step_abs);
delta, step_abs);
bound_type = TREE_TYPE (bound);
if (TYPE_PRECISION (type) > TYPE_PRECISION (bound_type))
bound = fold_convert (unsigned_type, bound);
else
valid_niter = fold_convert (bound_type, valid_niter);
if (at_stmt && stmt_dominates_stmt_p (of, at_stmt))
{
/* After the statement OF we know that anything is executed at most
BOUND times. */
cond = fold_build2 (GE_EXPR, boolean_type_node, valid_niter, bound);
}
else
{
/* Before the statement OF we know that anything is executed at most
BOUND + 1 times. */
cond = fold_build2 (GT_EXPR, boolean_type_node, valid_niter, bound);
}
if (nonzero_p (cond))
return new_step;
/* Try taking additional conditions into account. */
cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
invert_truthvalue (additional),
cond);
if (nonzero_p (cond))
return new_step;
for (bound = loop->bounds; bound; bound = bound->next)
if (proved_non_wrapping_p (at_stmt, bound, new_type, valid_niter))
return step_in_new_type;
/* Fail when the loop has no bound estimations, or when no bound can
be used for verifying the conversion. */
return NULL_TREE;
}
/* Checks whether it is correct to count the induction variable BASE + STEP * I
at AT_STMT in wider TYPE, using the bounds on numbers of iterations of a
LOOP. If it is possible, return the value of step of the induction variable
in the TYPE, otherwise return NULL_TREE. */
/* Return false only when the induction variable BASE + STEP * I is
known to not overflow: i.e. when the number of iterations is small
enough with respect to the step and initial condition in order to
keep the evolution confined in TYPEs bounds. Return true when the
iv is known to overflow or when the property is not computable.
tree
can_count_iv_in_wider_type (struct loop *loop, tree type, tree base, tree step,
tree at_stmt)
Initialize INIT_IS_MAX to true when the evolution goes from
INIT_IS_MAX to LOWER_BOUND_IN_TYPE, false in the contrary case, not
defined when the function returns true. */
bool
scev_probably_wraps_p (tree type, tree base, tree step,
tree at_stmt, struct loop *loop,
bool *init_is_max)
{
struct nb_iter_bound *bound;
tree new_step;
tree delta, step_abs;
tree unsigned_type, valid_niter;
tree base_plus_step = fold_build2 (PLUS_EXPR, type, base, step);
for (bound = loop->bounds; bound; bound = bound->next)
switch (compare_trees (base_plus_step, base))
{
new_step = can_count_iv_in_wider_type_bound (type, base, step,
at_stmt,
bound->bound,
bound->additional,
bound->at_stmt);
case -1:
{
tree extreme = upper_bound_in_type (type, TREE_TYPE (base));
delta = fold_build2 (MINUS_EXPR, type, extreme, base);
step_abs = step;
*init_is_max = false;
break;
}
if (new_step)
return new_step;
case 1:
{
tree extreme = lower_bound_in_type (type, TREE_TYPE (base));
delta = fold_build2 (MINUS_EXPR, type, base, extreme);
step_abs = fold_build1 (NEGATE_EXPR, type, step);
*init_is_max = true;
break;
}
case 0:
/* This means step is equal to 0. This should not happen. It
could happen in convert step, but not here. Safely answer
don't know as in the default case. */
default:
return true;
}
return NULL_TREE;
/* After having set INIT_IS_MAX, we can return false: when not using
wrapping arithmetic, signed types don't wrap. */
if (!flag_wrapv && !TYPE_UNSIGNED (type))
return false;
unsigned_type = unsigned_type_for (type);
delta = fold_convert (unsigned_type, delta);
step_abs = fold_convert (unsigned_type, step_abs);
valid_niter = fold_build2 (FLOOR_DIV_EXPR, unsigned_type, delta, step_abs);
for (bound = loop->bounds; bound; bound = bound->next)
if (proved_non_wrapping_p (at_stmt, bound, type, valid_niter))
return false;
/* At this point we still don't have a proof that the iv does not
overflow: give up. */
return true;
}
/* Return the conversion to NEW_TYPE of the STEP of an induction
variable BASE + STEP * I at AT_STMT. */
tree
convert_step (struct loop *loop, tree new_type, tree base, tree step,
tree at_stmt)
{
tree base_type = TREE_TYPE (base);
/* When not using wrapping arithmetic, signed types don't wrap. */
if (!flag_wrapv && !TYPE_UNSIGNED (base_type))
return fold_convert (new_type, step);
if (TYPE_PRECISION (new_type) > TYPE_PRECISION (base_type))
return convert_step_widening (loop, new_type, base, step, at_stmt);
return fold_convert (new_type, step);
}
/* Frees the information on upper bounds on numbers of iterations of LOOP. */

View File

@ -1427,13 +1427,13 @@ extract_range_from_expr (value_range_t *vr, tree expr)
set_value_range_to_varying (vr);
}
/* Given a range VR, a loop L and a variable VAR, determine whether it
/* Given a range VR, a LOOP and a variable VAR, determine whether it
would be profitable to adjust VR using scalar evolution information
for VAR. If so, update VR with the new limits. */
static void
adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
adjust_range_with_scev (value_range_t *vr, struct loop *loop, tree stmt,
tree var)
{
tree init, step, chrec;
bool init_is_max;
@ -1443,7 +1443,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
if (vr->type == VR_ANTI_RANGE)
return;
chrec = analyze_scalar_evolution (l, var);
chrec = analyze_scalar_evolution (loop, var);
if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
return;
@ -1455,22 +1455,12 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
if (!is_gimple_min_invariant (step))
return;
/* FIXME. When dealing with unsigned types,
analyze_scalar_evolution sets STEP to very large unsigned values
when the evolution goes backwards. This confuses this analysis
because we think that INIT is the smallest value that the range
can take, instead of the largest. Ignore these chrecs for now. */
if (INTEGRAL_TYPE_P (TREE_TYPE (step)) && TYPE_UNSIGNED (TREE_TYPE (step)))
/* Do not adjust ranges when chrec may wrap. */
if (scev_probably_wraps_p (chrec_type (chrec), init, step, stmt,
cfg_loops->parray[CHREC_VARIABLE (chrec)],
&init_is_max))
return;
/* Do not adjust ranges when using wrapping arithmetic. */
if (flag_wrapv)
return;
/* If STEP is negative, then INIT is the maximum value the range
will take. Otherwise, INIT is the minimum value. */
init_is_max = (tree_int_cst_sgn (step) < 0);
if (!POINTER_TYPE_P (TREE_TYPE (init))
&& (vr->type == VR_VARYING || vr->type == VR_UNDEFINED))
{
@ -2772,7 +2762,7 @@ vrp_visit_assignment (tree stmt, tree *output_p)
else about the range of LHS by examining scalar evolution
information. */
if (cfg_loops && (l = loop_containing_stmt (stmt)))
adjust_range_with_scev (&new_vr, l, lhs);
adjust_range_with_scev (&new_vr, l, stmt, lhs);
if (update_value_range (lhs, &new_vr))
{
@ -3519,7 +3509,10 @@ execute_vrp (void)
cfg_loops = loop_optimizer_init (NULL);
if (cfg_loops)
scev_initialize (cfg_loops);
{
scev_initialize (cfg_loops);
estimate_numbers_of_iterations (cfg_loops);
}
vrp_initialize ();
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);