tree-vrp.c: Include "intl.h".

./:	* tree-vrp.c: Include "intl.h".
	(usable_range_p): New static function.
	(compare_values_warnv): Don't test TYPE_OVERFLOW_UNDEFINED for
	overflowed values, juts set *strict_overflow_p.
	(compare_values): Only return -2 if one of the operands is not a
	constant.
	(compare_ranges): Call usable_range_p.
	(compare_range_with_value): Likewise.
	(vrp_evaluate_conditional_warnv): Rename from
	vrp_evaluate_conditional.  Make static.  Change all callers.
	(vrp_evaluate_conditional): New function.
	(simplify_div_or_mod_using_ranges): Issue warning about reliance
	on signed overflow.
	(simplify_abs_using_ranges): Likewise.
	(simplify_stmt_for_jump_threading): Add within_stmt parameter.
	* tree-ssa-dom.c (simplify_stmt_for_jump_threading): Add
	within_stmt parameter.
	* tree-ssa-propagate.c (fold_predicate_in): Update call to
	vrp_evaluate_conditional.
	* tree-ssa-threadedge.c
	(record_temporary_equivalences_from_stmts_at_dest): Change
	simplify parameter to take a second tree parameter.
	(simplify_control_stmt_condition): Likewise.
	(thread_across_edge): Likewise.
	* tree-flow.h (vrp_evaluate_conditional): Update declaration.
	(thread_across_edge): Likewise.
	* gcc/Makefile.in (tree-vrp.o): Depend upon intl.h.
testsuite/:
	* gcc.dg/no-strict-overflow-5.c: New test.
	* gcc.dg/no-strict-overflow-6.c: New test.
	* gcc.dg/Wstrict-overflow-11.c: New test.
	* gcc.dg/Wstrict-overflow-12.c: New test.
	* gcc.dg/Wstrict-overflow-13.c: New test.
	* gcc.dg/Wstrict-overflow-14.c: New test.
	* gcc.dg/Wstrict-overflow-15.c: New test.

From-SVN: r122706
This commit is contained in:
Ian Lance Taylor 2007-03-08 17:36:05 +00:00 committed by Ian Lance Taylor
parent 3c2d980c94
commit 0c948c2746
15 changed files with 308 additions and 31 deletions

View File

@ -1,3 +1,33 @@
2007-03-08 Ian Lance Taylor <iant@google.com>
* tree-vrp.c: Include "intl.h".
(usable_range_p): New static function.
(compare_values_warnv): Don't test TYPE_OVERFLOW_UNDEFINED for
overflowed values, juts set *strict_overflow_p.
(compare_values): Only return -2 if one of the operands is not a
constant.
(compare_ranges): Call usable_range_p.
(compare_range_with_value): Likewise.
(vrp_evaluate_conditional_warnv): Rename from
vrp_evaluate_conditional. Make static. Change all callers.
(vrp_evaluate_conditional): New function.
(simplify_div_or_mod_using_ranges): Issue warning about reliance
on signed overflow.
(simplify_abs_using_ranges): Likewise.
(simplify_stmt_for_jump_threading): Add within_stmt parameter.
* tree-ssa-dom.c (simplify_stmt_for_jump_threading): Add
within_stmt parameter.
* tree-ssa-propagate.c (fold_predicate_in): Update call to
vrp_evaluate_conditional.
* tree-ssa-threadedge.c
(record_temporary_equivalences_from_stmts_at_dest): Change
simplify parameter to take a second tree parameter.
(simplify_control_stmt_condition): Likewise.
(thread_across_edge): Likewise.
* tree-flow.h (vrp_evaluate_conditional): Update declaration.
(thread_across_edge): Likewise.
* gcc/Makefile.in (tree-vrp.o): Depend upon intl.h.
2007-03-08 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (TARGET_SAHF): New define.

View File

@ -2044,7 +2044,7 @@ tree-vn.o : tree-vn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) \
tree-vrp.o : tree-vrp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H) $(DIAGNOSTIC_H) $(GGC_H) \
$(BASIC_BLOCK_H) tree-ssa-propagate.h $(FLAGS_H) $(TREE_DUMP_H) \
$(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) toplev.h
$(CFGLOOP_H) $(SCEV_H) tree-chrec.h $(TIMEVAR_H) toplev.h intl.h
tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) $(FLAGS_H) output.h \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \

View File

@ -1,3 +1,13 @@
2007-03-08 Ian Lance Taylor <iant@google.com>
* gcc.dg/no-strict-overflow-5.c: New test.
* gcc.dg/no-strict-overflow-6.c: New test.
* gcc.dg/Wstrict-overflow-11.c: New test.
* gcc.dg/Wstrict-overflow-12.c: New test.
* gcc.dg/Wstrict-overflow-13.c: New test.
* gcc.dg/Wstrict-overflow-14.c: New test.
* gcc.dg/Wstrict-overflow-15.c: New test.
2007-03-08 Richard Sandiford <richard@codesourcery.com>
* gcc.c-torture/execute/strcmp-1.x: New file. XFAIL execution

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=1" } */
/* Based on strict-overflow-5.c. */
/* We can only unroll when using strict overflow semantics. */
int foo (int i)
{
int index;
int r=0;
for (index = i; index <= i+4; index+=2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
r++;
return r;
}

View File

@ -0,0 +1,16 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
/* Source: Ian Lance Taylor. Dual of no-strict-overflow-6.c. */
/* VRP test. This turns into an infinite loop when using strict
overflow semantics. */
int
foo ()
{
int i, bits;
for (i = 1, bits = 1; i > 0; i += i) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
++bits;
return bits;
}

View File

@ -0,0 +1,18 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=2" } */
/* Source: Ian Lance Taylor. Dual of no-strict-overflow-6.c. */
/* VRP test. This turns into an infinite loop (depending on what
bigtime_test does), but at least we warn about it. */
extern int bigtime_test (int);
int
foo ()
{
int j;
for (j = 1; 0 < j; j *= 2) /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
if (! bigtime_test (j))
return 1;
return 0;
}

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=4" } */
/* Source: Ian Lance Taylor. */
int
foo (int j)
{
int i;
int sum = 0;
for (i = 1; i < j; i += i)
sum += i / 16; /* { dg-warning "assuming signed overflow does not occur" "" } */
return sum;
}

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow=4" } */
/* Source: Ian Lance Taylor. */
int
foo (int j)
{
int i;
int sum = 0;
for (i = 1; i < j; i += i)
sum += __builtin_abs (i); /* { dg-warning "assuming signed overflow does not occur" "" } */
return sum;
}

View File

@ -0,0 +1,20 @@
/* { dg-do compile } */
/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
/* Dual of strict-overflow-5.c. */
/* We can only unroll when using strict overflow semantics. */
int foo (int i)
{
int index;
int r=0;
for (index = i; index <= i+4; index+=2)
r++;
return r;
}
/* { dg-final { scan-tree-dump-times "r = 3" 0 "final_cleanup" } } */
/* { dg-final { cleanup-tree-dump "final_cleanup" } } */

View File

@ -0,0 +1,21 @@
/* { dg-do compile } */
/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
/* Source: Ian Lance Taylor. */
/* VRP test. We can not simplify the conditional when not using
strict overflow semantics. We don't test this with
-fstrict-overflow because it turns into an infinite loop. That is
OK but it would also be OK to not do that. */
int
foo ()
{
int i, bits;
for (i = 1, bits = 1; i > 0; i += i)
++bits;
return bits;
}
/* { dg-final { scan-tree-dump "return bits" "final_cleanup" } } */
/* { dg-final { cleanup-tree-dump "final_cleanup" } } */

View File

@ -776,7 +776,7 @@ bool fold_stmt_inplace (tree);
tree widen_bitfield (tree, tree, tree);
/* In tree-vrp.c */
tree vrp_evaluate_conditional (tree, bool, bool *);
tree vrp_evaluate_conditional (tree, tree);
void simplify_stmt_using_ranges (tree);
/* In tree-ssa-dom.c */
@ -910,7 +910,7 @@ bool contains_abnormal_ssa_name_p (tree);
/* In tree-ssa-threadedge.c */
extern bool potentially_threadable_block (basic_block);
extern void thread_across_edge (tree, edge, bool,
VEC(tree, heap) **, tree (*) (tree));
VEC(tree, heap) **, tree (*) (tree, tree));
/* In tree-ssa-loop-im.c */
/* The possibilities of statement movement. */

View File

@ -554,7 +554,7 @@ restore_vars_to_original_value (void)
/* A trivial wrapper so that we can present the generic jump
threading code with a simple API for simplifying statements. */
static tree
simplify_stmt_for_jump_threading (tree stmt)
simplify_stmt_for_jump_threading (tree stmt, tree within_stmt ATTRIBUTE_UNUSED)
{
return lookup_avail_expr (stmt, false);
}

View File

@ -1100,7 +1100,6 @@ fold_predicate_in (tree stmt)
tree *pred_p = NULL;
bool modify_stmt_p = false;
tree val;
bool sop;
if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
&& COMPARISON_CLASS_P (GIMPLE_STMT_OPERAND (stmt, 1)))
@ -1113,8 +1112,7 @@ fold_predicate_in (tree stmt)
else
return false;
sop = false;
val = vrp_evaluate_conditional (*pred_p, true, &sop);
val = vrp_evaluate_conditional (*pred_p, stmt);
if (val)
{
if (modify_stmt_p)

View File

@ -211,7 +211,8 @@ record_temporary_equivalences_from_phis (edge e, VEC(tree, heap) **stack)
static tree
record_temporary_equivalences_from_stmts_at_dest (edge e,
VEC(tree, heap) **stack,
tree (*simplify) (tree))
tree (*simplify) (tree,
tree))
{
block_stmt_iterator bsi;
tree stmt = NULL;
@ -315,7 +316,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
cached_lhs = fold (pre_fold_expr);
if (TREE_CODE (cached_lhs) != SSA_NAME
&& !is_gimple_min_invariant (cached_lhs))
cached_lhs = (*simplify) (stmt);
cached_lhs = (*simplify) (stmt, stmt);
}
/* Restore the statement's original uses/defs. */
@ -353,7 +354,7 @@ static tree
simplify_control_stmt_condition (edge e,
tree stmt,
tree dummy_cond,
tree (*simplify) (tree),
tree (*simplify) (tree, tree),
bool handle_dominating_asserts)
{
tree cond, cached_lhs;
@ -439,7 +440,7 @@ simplify_control_stmt_condition (edge e,
/* If we have not simplified the condition down to an invariant,
then use the pass specific callback to simplify the condition. */
if (! is_gimple_min_invariant (cached_lhs))
cached_lhs = (*simplify) (dummy_cond);
cached_lhs = (*simplify) (dummy_cond, stmt);
}
/* We can have conditionals which just test the state of a variable
@ -466,7 +467,7 @@ simplify_control_stmt_condition (edge e,
/* If we haven't simplified to an invariant yet, then use the
pass specific callback to try and simplify it further. */
if (cached_lhs && ! is_gimple_min_invariant (cached_lhs))
cached_lhs = (*simplify) (stmt);
cached_lhs = (*simplify) (stmt, stmt);
}
else
cached_lhs = NULL;
@ -494,7 +495,7 @@ thread_across_edge (tree dummy_cond,
edge e,
bool handle_dominating_asserts,
VEC(tree, heap) **stack,
tree (*simplify) (tree))
tree (*simplify) (tree, tree))
{
tree stmt;

View File

@ -33,6 +33,7 @@ Boston, MA 02110-1301, USA. */
#include "timevar.h"
#include "diagnostic.h"
#include "toplev.h"
#include "intl.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "tree-ssa-propagate.h"
@ -46,6 +47,7 @@ static sbitmap found_in_subgraph;
static int compare_values (tree val1, tree val2);
static int compare_values_warnv (tree val1, tree val2, bool *);
static void vrp_meet (value_range_t *, value_range_t *);
static tree vrp_evaluate_conditional_warnv (tree, bool, bool *);
/* Location information for ASSERT_EXPRs. Each instance of this
structure describes an ASSERT_EXPR for an SSA name. Since a single
@ -543,6 +545,32 @@ overflow_infinity_range_p (value_range_t *vr)
|| is_overflow_infinity (vr->max)));
}
/* Return false if we can not make a valid comparison based on VR;
this will be the case if it uses an overflow infinity and overflow
is not undefined (i.e., -fno-strict-overflow is in effect).
Otherwise return true, and set *STRICT_OVERFLOW_P to true if VR
uses an overflow infinity. */
static bool
usable_range_p (value_range_t *vr, bool *strict_overflow_p)
{
gcc_assert (vr->type == VR_RANGE);
if (is_overflow_infinity (vr->min))
{
*strict_overflow_p = true;
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->min)))
return false;
}
if (is_overflow_infinity (vr->max))
{
*strict_overflow_p = true;
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (vr->max)))
return false;
}
return true;
}
/* Like tree_expr_nonnegative_warnv_p, but this function uses value
ranges obtained so far. */
@ -783,9 +811,8 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
infinities. */
if (TREE_OVERFLOW (val1) || TREE_OVERFLOW (val2))
{
if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1)))
return -2;
if (strict_overflow_p != NULL)
*strict_overflow_p = true;
if (is_negative_overflow_infinity (val1))
return is_negative_overflow_infinity (val2) ? 0 : -1;
else if (is_negative_overflow_infinity (val2))
@ -831,8 +858,8 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
}
}
/* Compare values like compare_values_warnv, but treat comparisons
which rely on undefined overflow as incomparable. */
/* Compare values like compare_values_warnv, but treat comparisons of
nonconstants which rely on undefined overflow as incomparable. */
static int
compare_values (tree val1, tree val2)
@ -842,7 +869,8 @@ compare_values (tree val1, tree val2)
sop = false;
ret = compare_values_warnv (val1, val2, &sop);
if (sop)
if (sop
&& (!is_gimple_min_invariant (val1) || !is_gimple_min_invariant (val2)))
ret = -2;
return ret;
}
@ -2359,7 +2387,7 @@ static void
extract_range_from_comparison (value_range_t *vr, tree expr)
{
bool sop = false;
tree val = vrp_evaluate_conditional (expr, false, &sop);
tree val = vrp_evaluate_conditional_warnv (expr, false, &sop);
/* A disadvantage of using a special infinity as an overflow
representation is that we lose the ability to record overflow
@ -2604,6 +2632,10 @@ compare_ranges (enum tree_code comp, value_range_t *vr0, value_range_t *vr1,
return NULL_TREE;
}
if (!usable_range_p (vr0, strict_overflow_p)
|| !usable_range_p (vr1, strict_overflow_p))
return NULL_TREE;
/* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the
operands around and change the comparison code. */
if (comp == GT_EXPR || comp == GE_EXPR)
@ -2737,6 +2769,9 @@ compare_range_with_value (enum tree_code comp, value_range_t *vr, tree val,
return NULL_TREE;
}
if (!usable_range_p (vr, strict_overflow_p))
return NULL_TREE;
if (comp == EQ_EXPR)
{
/* EQ_EXPR may only be computed if VR represents exactly
@ -4531,8 +4566,9 @@ compare_names (enum tree_code comp, tree n1, tree n2,
Set *STRICT_OVERFLOW_P to indicate whether we relied on an overflow
infinity to produce the result. */
tree
vrp_evaluate_conditional (tree cond, bool use_equiv_p, bool *strict_overflow_p)
static tree
vrp_evaluate_conditional_warnv (tree cond, bool use_equiv_p,
bool *strict_overflow_p)
{
gcc_assert (TREE_CODE (cond) == SSA_NAME
|| TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison);
@ -4609,6 +4645,55 @@ vrp_evaluate_conditional (tree cond, bool use_equiv_p, bool *strict_overflow_p)
return NULL_TREE;
}
/* Given COND within STMT, try to simplify it based on value range
information. Return NULL if the conditional can not be evaluated.
The ranges of all the names equivalent with the operands in COND
will be used when trying to compute the value. If the result is
based on undefined signed overflow, issue a warning if
appropriate. */
tree
vrp_evaluate_conditional (tree cond, tree stmt)
{
bool sop;
tree ret;
sop = false;
ret = vrp_evaluate_conditional_warnv (cond, true, &sop);
if (ret && sop)
{
enum warn_strict_overflow_code wc;
const char* warnmsg;
if (is_gimple_min_invariant (ret))
{
wc = WARN_STRICT_OVERFLOW_CONDITIONAL;
warnmsg = G_("assuming signed overflow does not occur when "
"simplifying conditional to constant");
}
else
{
wc = WARN_STRICT_OVERFLOW_COMPARISON;
warnmsg = G_("assuming signed overflow does not occur when "
"simplifying conditional");
}
if (issue_strict_overflow_warning (wc))
{
location_t locus;
if (!EXPR_HAS_LOCATION (stmt))
locus = input_location;
else
locus = EXPR_LOCATION (stmt);
warning (OPT_Wstrict_overflow, "%H%s", &locus, warnmsg);
}
}
return ret;
}
/* Visit conditional statement STMT. If we can determine which edge
will be taken out of STMT's basic block, record it in
@ -4693,7 +4778,7 @@ vrp_visit_cond_stmt (tree stmt, edge *taken_edge_p)
MICO, TRAMP3D and SPEC2000) showed that doing this results in
4 more predicates folded in SPEC. */
sop = false;
val = vrp_evaluate_conditional (cond, false, &sop);
val = vrp_evaluate_conditional_warnv (cond, false, &sop);
if (val)
{
if (!sop)
@ -5071,6 +5156,23 @@ simplify_div_or_mod_using_ranges (tree stmt, tree rhs, enum tree_code rhs_code)
bool sop = false;
val = compare_range_with_value (GT_EXPR, vr, integer_zero_node, &sop);
if (val
&& sop
&& integer_onep (val)
&& issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
{
location_t locus;
if (!EXPR_HAS_LOCATION (stmt))
locus = input_location;
else
locus = EXPR_LOCATION (stmt);
warning (OPT_Wstrict_overflow,
("%Hassuming signed overflow does not occur when "
"simplifying / or %% to >> or &"),
&locus);
}
}
if (val && integer_onep (val))
@ -5138,6 +5240,20 @@ simplify_abs_using_ranges (tree stmt, tree rhs)
{
tree t;
if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
{
location_t locus;
if (!EXPR_HAS_LOCATION (stmt))
locus = input_location;
else
locus = EXPR_LOCATION (stmt);
warning (OPT_Wstrict_overflow,
("%Hassuming signed overflow does not occur when "
"simplifying abs (X) to X or -X"),
&locus);
}
if (integer_onep (val))
t = build1 (NEGATE_EXPR, TREE_TYPE (op), op);
else
@ -5330,21 +5446,21 @@ simplify_stmt_using_ranges (tree stmt)
restored. */
static VEC(tree,heap) *stack;
/* A trivial wrapper so that we can present the generic jump
threading code with a simple API for simplifying statements. */
static tree
simplify_stmt_for_jump_threading (tree stmt)
{
bool sop;
/* A trivial wrapper so that we can present the generic jump threading
code with a simple API for simplifying statements. STMT is the
statement we want to simplify, WITHIN_STMT provides the location
for any overflow warnings. */
static tree
simplify_stmt_for_jump_threading (tree stmt, tree within_stmt)
{
/* We only use VRP information to simplify conditionals. This is
overly conservative, but it's unclear if doing more would be
worth the compile time cost. */
if (TREE_CODE (stmt) != COND_EXPR)
return NULL;
sop = false;
return vrp_evaluate_conditional (COND_EXPR_COND (stmt), true, &sop);
return vrp_evaluate_conditional (COND_EXPR_COND (stmt), within_stmt);
}
/* Blocks which have more than one predecessor and more than