Commit 1e8552eb by Sebastian Pop Committed by Sebastian Pop

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
parent 89a590b3
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> 2005-06-07 Eric Christopher <echristo@redhat.com>
* config/mips/predicates.md (sleu_operand): Use * config/mips/predicates.md (sleu_operand): Use
......
...@@ -1873,7 +1873,7 @@ tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \ ...@@ -1873,7 +1873,7 @@ tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
$(TM_H) coretypes.h $(TM_H) coretypes.h
tree-chrec.o: tree-chrec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_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) \ $(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) \ tree-scalar-evolution.o: tree-scalar-evolution.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) \ coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(RTL_H) \
$(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \ $(BASIC_BLOCK_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) \
......
...@@ -39,7 +39,7 @@ int main (void) ...@@ -39,7 +39,7 @@ int main (void)
return 0; return 0;
} }
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 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 { lp64 || 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 { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -40,7 +40,7 @@ int main (void) ...@@ -40,7 +40,7 @@ int main (void)
return 0; return 0;
} }
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 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 { lp64 || 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 { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -32,6 +32,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -32,6 +32,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree.h" #include "tree.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "varray.h" #include "varray.h"
#include "cfgloop.h"
#include "tree-flow.h"
#include "tree-chrec.h" #include "tree-chrec.h"
#include "tree-pass.h" #include "tree-pass.h"
#include "params.h" #include "params.h"
...@@ -909,6 +911,57 @@ tree_contains_chrecs (tree expr, int *size) ...@@ -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 /* Determine whether the given tree is an affine multivariate
evolution. */ evolution. */
...@@ -1019,11 +1072,17 @@ nb_vars_in_chrec (tree chrec) ...@@ -1019,11 +1072,17 @@ nb_vars_in_chrec (tree chrec)
/* Convert CHREC to TYPE. The following is rule is always true: /* Convert CHREC to TYPE. When the analyzer knows the context in
TREE_TYPE (chrec) == TREE_TYPE (CHREC_LEFT (chrec)) == TREE_TYPE which the CHREC is built, it sets AT_STMT to the statement that
(CHREC_RIGHT (chrec)). An example of what could happen when adding contains the definition of the analyzed variable, otherwise the
two chrecs and the type of the CHREC_RIGHT is different than conversion is less accurate: the information is used for
CHREC_LEFT is: 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) 10} +
{(uint) 0, +, (uchar) 250} {(uint) 0, +, (uchar) 250}
...@@ -1038,11 +1097,10 @@ nb_vars_in_chrec (tree chrec) ...@@ -1038,11 +1097,10 @@ nb_vars_in_chrec (tree chrec)
*/ */
tree tree
chrec_convert (tree type, chrec_convert (tree type, tree chrec, tree at_stmt)
tree chrec)
{ {
tree ct; tree ct, res;
if (automatically_generated_chrec_p (chrec)) if (automatically_generated_chrec_p (chrec))
return chrec; return chrec;
...@@ -1050,43 +1108,44 @@ chrec_convert (tree type, ...@@ -1050,43 +1108,44 @@ chrec_convert (tree type,
if (ct == type) if (ct == type)
return chrec; return chrec;
if (TYPE_PRECISION (ct) < TYPE_PRECISION (type)) if (evolution_function_is_affine_p (chrec))
return count_ev_in_wider_type (type, chrec);
switch (TREE_CODE (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), return build_polynomial_chrec (CHREC_VARIABLE (chrec),
chrec_convert (type, chrec_convert (type, CHREC_LEFT (chrec),
CHREC_LEFT (chrec)), at_stmt),
chrec_convert (type, step);
CHREC_RIGHT (chrec))); }
default: if (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
{ return chrec_dont_know;
tree res = fold_convert (type, chrec);
/* Don't propagate overflows. */ res = fold_convert (type, chrec);
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. /* Don't propagate overflows. */
This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the if (CONSTANT_CLASS_P (res))
natural values associated with TYPE_PRECISION and TYPE_UNSIGNED, {
and can cause problems later when computing niters of loops. Note TREE_CONSTANT_OVERFLOW (res) = 0;
that we don't do the check before converting because we don't want TREE_OVERFLOW (res) = 0;
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;
}
} }
/* 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. */ /* Returns the type of the chrec. */
......
...@@ -67,8 +67,7 @@ tree_is_chrec (tree expr) ...@@ -67,8 +67,7 @@ tree_is_chrec (tree expr)
extern tree chrec_fold_plus (tree, tree, tree); extern tree chrec_fold_plus (tree, tree, tree);
extern tree chrec_fold_minus (tree, tree, tree); extern tree chrec_fold_minus (tree, tree, tree);
extern tree chrec_fold_multiply (tree, tree, tree); extern tree chrec_fold_multiply (tree, tree, tree);
extern tree chrec_convert (tree, tree); extern tree chrec_convert (tree, tree, tree);
extern tree count_ev_in_wider_type (tree, tree);
extern tree chrec_type (tree); extern tree chrec_type (tree);
/* Operations. */ /* Operations. */
...@@ -146,6 +145,7 @@ evolution_function_is_constant_p (tree chrec) ...@@ -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. */ /* Determine whether the given tree is an affine evolution function or not. */
static inline bool static inline bool
...@@ -157,8 +157,10 @@ evolution_function_is_affine_p (tree chrec) ...@@ -157,8 +157,10 @@ evolution_function_is_affine_p (tree chrec)
switch (TREE_CODE (chrec)) switch (TREE_CODE (chrec))
{ {
case POLYNOMIAL_CHREC: case POLYNOMIAL_CHREC:
if (evolution_function_is_constant_p (CHREC_LEFT (chrec)) if (evolution_function_is_invariant_p (CHREC_LEFT (chrec),
&& evolution_function_is_constant_p (CHREC_RIGHT (chrec))) CHREC_VARIABLE (chrec))
&& evolution_function_is_invariant_p (CHREC_RIGHT (chrec),
CHREC_VARIABLE (chrec)))
return true; return true;
else else
return false; return false;
......
...@@ -658,7 +658,8 @@ tree find_loop_niter (struct loop *, edge *); ...@@ -658,7 +658,8 @@ tree find_loop_niter (struct loop *, edge *);
tree loop_niter_by_eval (struct loop *, edge); tree loop_niter_by_eval (struct loop *, edge);
tree find_loop_niter_by_eval (struct loop *, edge *); tree find_loop_niter_by_eval (struct loop *, edge *);
void estimate_numbers_of_iterations (struct loops *); 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 free_numbers_of_iterations_estimates (struct loops *);
void rewrite_into_loop_closed_ssa (bitmap, unsigned); void rewrite_into_loop_closed_ssa (bitmap, unsigned);
void verify_loop_closed_ssa (void); void verify_loop_closed_ssa (void);
......
...@@ -349,33 +349,6 @@ find_var_scev_info (tree var) ...@@ -349,33 +349,6 @@ find_var_scev_info (tree var)
return &res->chrec; 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 /* Return true when CHREC contains symbolic names defined in
LOOP_NB. */ LOOP_NB. */
...@@ -1052,6 +1025,7 @@ static bool follow_ssa_edge (struct loop *loop, tree, tree, tree *); ...@@ -1052,6 +1025,7 @@ static bool follow_ssa_edge (struct loop *loop, tree, tree, tree *);
static bool static bool
follow_ssa_edge_in_rhs (struct loop *loop, follow_ssa_edge_in_rhs (struct loop *loop,
tree at_stmt,
tree rhs, tree rhs,
tree halting_phi, tree halting_phi,
tree *evolution_of_loop) tree *evolution_of_loop)
...@@ -1071,9 +1045,10 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1071,9 +1045,10 @@ follow_ssa_edge_in_rhs (struct loop *loop,
{ {
case NOP_EXPR: case NOP_EXPR:
/* This assignment is under the form "a_1 = (cast) rhs. */ /* This assignment is under the form "a_1 = (cast) rhs. */
res = follow_ssa_edge_in_rhs (loop, TREE_OPERAND (rhs, 0), halting_phi, res = follow_ssa_edge_in_rhs (loop, at_stmt, TREE_OPERAND (rhs, 0),
evolution_of_loop); halting_phi, evolution_of_loop);
*evolution_of_loop = chrec_convert (TREE_TYPE (rhs), *evolution_of_loop); *evolution_of_loop = chrec_convert (TREE_TYPE (rhs),
*evolution_of_loop, at_stmt);
break; break;
case INTEGER_CST: case INTEGER_CST:
...@@ -1107,7 +1082,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1107,7 +1082,7 @@ follow_ssa_edge_in_rhs (struct loop *loop,
if (res) if (res)
*evolution_of_loop = add_to_evolution *evolution_of_loop = add_to_evolution
(loop->num, (loop->num,
chrec_convert (type_rhs, *evolution_of_loop), chrec_convert (type_rhs, *evolution_of_loop, at_stmt),
PLUS_EXPR, rhs1); PLUS_EXPR, rhs1);
else else
...@@ -1119,7 +1094,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1119,7 +1094,7 @@ follow_ssa_edge_in_rhs (struct loop *loop,
if (res) if (res)
*evolution_of_loop = add_to_evolution *evolution_of_loop = add_to_evolution
(loop->num, (loop->num,
chrec_convert (type_rhs, *evolution_of_loop), chrec_convert (type_rhs, *evolution_of_loop, at_stmt),
PLUS_EXPR, rhs0); PLUS_EXPR, rhs0);
} }
} }
...@@ -1133,7 +1108,8 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1133,7 +1108,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop); evolution_of_loop);
if (res) if (res)
*evolution_of_loop = add_to_evolution *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); PLUS_EXPR, rhs1);
} }
} }
...@@ -1147,7 +1123,8 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1147,7 +1123,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop); evolution_of_loop);
if (res) if (res)
*evolution_of_loop = add_to_evolution *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); PLUS_EXPR, rhs0);
} }
...@@ -1174,7 +1151,8 @@ follow_ssa_edge_in_rhs (struct loop *loop, ...@@ -1174,7 +1151,8 @@ follow_ssa_edge_in_rhs (struct loop *loop,
evolution_of_loop); evolution_of_loop);
if (res) if (res)
*evolution_of_loop = add_to_evolution *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); MINUS_EXPR, rhs1);
} }
else else
...@@ -1391,7 +1369,8 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop, ...@@ -1391,7 +1369,8 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop,
/* Follow the edges that exit the inner loop. */ /* Follow the edges that exit the inner loop. */
bb = PHI_ARG_EDGE (loop_phi_node, i)->src; bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
if (!flow_bb_inside_loop_p (loop, bb)) 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); evolution_of_loop);
} }
...@@ -1404,7 +1383,7 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop, ...@@ -1404,7 +1383,7 @@ follow_ssa_edge_inner_loop_phi (struct loop *outer_loop,
/* Otherwise, compute the overall effect of the inner loop. */ /* Otherwise, compute the overall effect of the inner loop. */
ev = compute_overall_effect_of_inner_loop (loop, ev); 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); evolution_of_loop);
} }
...@@ -1456,7 +1435,7 @@ follow_ssa_edge (struct loop *loop, ...@@ -1456,7 +1435,7 @@ follow_ssa_edge (struct loop *loop,
return false; return false;
case MODIFY_EXPR: case MODIFY_EXPR:
return follow_ssa_edge_in_rhs (loop, return follow_ssa_edge_in_rhs (loop, def,
TREE_OPERAND (def, 1), TREE_OPERAND (def, 1),
halting_phi, halting_phi,
evolution_of_loop); evolution_of_loop);
...@@ -1665,14 +1644,14 @@ interpret_condition_phi (struct loop *loop, tree condition_phi) ...@@ -1665,14 +1644,14 @@ interpret_condition_phi (struct loop *loop, tree condition_phi)
analyze the effect of an inner loop: see interpret_loop_phi. */ analyze the effect of an inner loop: see interpret_loop_phi. */
static tree static tree
interpret_rhs_modify_expr (struct loop *loop, interpret_rhs_modify_expr (struct loop *loop, tree at_stmt,
tree opnd1, tree type) tree opnd1, tree type)
{ {
tree res, opnd10, opnd11, chrec10, chrec11; tree res, opnd10, opnd11, chrec10, chrec11;
if (is_gimple_min_invariant (opnd1)) if (is_gimple_min_invariant (opnd1))
return chrec_convert (type, opnd1); return chrec_convert (type, opnd1, at_stmt);
switch (TREE_CODE (opnd1)) switch (TREE_CODE (opnd1))
{ {
case PLUS_EXPR: case PLUS_EXPR:
...@@ -1680,8 +1659,8 @@ interpret_rhs_modify_expr (struct loop *loop, ...@@ -1680,8 +1659,8 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1); opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10); chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11); chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10); chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11); chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_plus (type, chrec10, chrec11); res = chrec_fold_plus (type, chrec10, chrec11);
break; break;
...@@ -1690,15 +1669,15 @@ interpret_rhs_modify_expr (struct loop *loop, ...@@ -1690,15 +1669,15 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1); opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10); chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11); chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10); chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11); chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_minus (type, chrec10, chrec11); res = chrec_fold_minus (type, chrec10, chrec11);
break; break;
case NEGATE_EXPR: case NEGATE_EXPR:
opnd10 = TREE_OPERAND (opnd1, 0); opnd10 = TREE_OPERAND (opnd1, 0);
chrec10 = analyze_scalar_evolution (loop, opnd10); 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); res = chrec_fold_minus (type, build_int_cst (type, 0), chrec10);
break; break;
...@@ -1707,25 +1686,27 @@ interpret_rhs_modify_expr (struct loop *loop, ...@@ -1707,25 +1686,27 @@ interpret_rhs_modify_expr (struct loop *loop,
opnd11 = TREE_OPERAND (opnd1, 1); opnd11 = TREE_OPERAND (opnd1, 1);
chrec10 = analyze_scalar_evolution (loop, opnd10); chrec10 = analyze_scalar_evolution (loop, opnd10);
chrec11 = analyze_scalar_evolution (loop, opnd11); chrec11 = analyze_scalar_evolution (loop, opnd11);
chrec10 = chrec_convert (type, chrec10); chrec10 = chrec_convert (type, chrec10, at_stmt);
chrec11 = chrec_convert (type, chrec11); chrec11 = chrec_convert (type, chrec11, at_stmt);
res = chrec_fold_multiply (type, chrec10, chrec11); res = chrec_fold_multiply (type, chrec10, chrec11);
break; break;
case SSA_NAME: case SSA_NAME:
res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1)); res = chrec_convert (type, analyze_scalar_evolution (loop, opnd1),
at_stmt);
break; break;
case ASSERT_EXPR: case ASSERT_EXPR:
opnd10 = ASSERT_EXPR_VAR (opnd1); 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; break;
case NOP_EXPR: case NOP_EXPR:
case CONVERT_EXPR: case CONVERT_EXPR:
opnd10 = TREE_OPERAND (opnd1, 0); opnd10 = TREE_OPERAND (opnd1, 0);
chrec10 = analyze_scalar_evolution (loop, opnd10); chrec10 = analyze_scalar_evolution (loop, opnd10);
res = chrec_convert (type, chrec10); res = chrec_convert (type, chrec10, at_stmt);
break; break;
default: default:
...@@ -1775,7 +1756,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res) ...@@ -1775,7 +1756,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
return chrec_dont_know; return chrec_dont_know;
if (TREE_CODE (var) != SSA_NAME) 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); def = SSA_NAME_DEF_STMT (var);
bb = bb_for_stmt (def); bb = bb_for_stmt (def);
...@@ -1809,7 +1790,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res) ...@@ -1809,7 +1790,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
switch (TREE_CODE (def)) switch (TREE_CODE (def))
{ {
case MODIFY_EXPR: 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; break;
case PHI_NODE: case PHI_NODE:
...@@ -2093,7 +2074,7 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, ...@@ -2093,7 +2074,7 @@ instantiate_parameters_1 (struct loop *loop, tree chrec,
if (op0 == TREE_OPERAND (chrec, 0)) if (op0 == TREE_OPERAND (chrec, 0))
return chrec; return chrec;
return chrec_convert (TREE_TYPE (chrec), op0); return chrec_convert (TREE_TYPE (chrec), op0, NULL_TREE);
case SCEV_NOT_KNOWN: case SCEV_NOT_KNOWN:
return chrec_dont_know; return chrec_dont_know;
......
...@@ -1442,11 +1442,8 @@ idx_find_step (tree base, tree *idx, void *data) ...@@ -1442,11 +1442,8 @@ idx_find_step (tree base, tree *idx, void *data)
/* The step for pointer arithmetics already is 1 byte. */ /* The step for pointer arithmetics already is 1 byte. */
step = build_int_cst (sizetype, 1); step = build_int_cst (sizetype, 1);
if (TYPE_PRECISION (TREE_TYPE (iv->base)) < TYPE_PRECISION (sizetype)) iv_step = convert_step (dta->ivopts_data->current_loop,
iv_step = can_count_iv_in_wider_type (dta->ivopts_data->current_loop, sizetype, iv->base, iv->step, dta->stmt);
sizetype, iv->base, iv->step, dta->stmt);
else
iv_step = fold_convert (sizetype, iv->step);
if (!iv_step) if (!iv_step)
{ {
......
...@@ -1427,13 +1427,13 @@ extract_range_from_expr (value_range_t *vr, tree expr) ...@@ -1427,13 +1427,13 @@ extract_range_from_expr (value_range_t *vr, tree expr)
set_value_range_to_varying (vr); set_value_range_to_varying (vr);
} }
/* Given a range VR, a LOOP and a variable VAR, determine whether it
/* Given a range VR, a loop L and a variable VAR, determine whether it
would be profitable to adjust VR using scalar evolution information would be profitable to adjust VR using scalar evolution information
for VAR. If so, update VR with the new limits. */ for VAR. If so, update VR with the new limits. */
static void 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; tree init, step, chrec;
bool init_is_max; bool init_is_max;
...@@ -1443,7 +1443,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var) ...@@ -1443,7 +1443,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
if (vr->type == VR_ANTI_RANGE) if (vr->type == VR_ANTI_RANGE)
return; return;
chrec = analyze_scalar_evolution (l, var); chrec = analyze_scalar_evolution (loop, var);
if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
return; return;
...@@ -1455,22 +1455,12 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var) ...@@ -1455,22 +1455,12 @@ adjust_range_with_scev (value_range_t *vr, struct loop *l, tree var)
if (!is_gimple_min_invariant (step)) if (!is_gimple_min_invariant (step))
return; return;
/* FIXME. When dealing with unsigned types, /* Do not adjust ranges when chrec may wrap. */
analyze_scalar_evolution sets STEP to very large unsigned values if (scev_probably_wraps_p (chrec_type (chrec), init, step, stmt,
when the evolution goes backwards. This confuses this analysis cfg_loops->parray[CHREC_VARIABLE (chrec)],
because we think that INIT is the smallest value that the range &init_is_max))
can take, instead of the largest. Ignore these chrecs for now. */
if (INTEGRAL_TYPE_P (TREE_TYPE (step)) && TYPE_UNSIGNED (TREE_TYPE (step)))
return;
/* Do not adjust ranges when using wrapping arithmetic. */
if (flag_wrapv)
return; 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)) if (!POINTER_TYPE_P (TREE_TYPE (init))
&& (vr->type == VR_VARYING || vr->type == VR_UNDEFINED)) && (vr->type == VR_VARYING || vr->type == VR_UNDEFINED))
{ {
...@@ -2772,7 +2762,7 @@ vrp_visit_assignment (tree stmt, tree *output_p) ...@@ -2772,7 +2762,7 @@ vrp_visit_assignment (tree stmt, tree *output_p)
else about the range of LHS by examining scalar evolution else about the range of LHS by examining scalar evolution
information. */ information. */
if (cfg_loops && (l = loop_containing_stmt (stmt))) 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)) if (update_value_range (lhs, &new_vr))
{ {
...@@ -3519,7 +3509,10 @@ execute_vrp (void) ...@@ -3519,7 +3509,10 @@ execute_vrp (void)
cfg_loops = loop_optimizer_init (NULL); cfg_loops = loop_optimizer_init (NULL);
if (cfg_loops) if (cfg_loops)
scev_initialize (cfg_loops); {
scev_initialize (cfg_loops);
estimate_numbers_of_iterations (cfg_loops);
}
vrp_initialize (); vrp_initialize ();
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node); ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment