aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-03-08 17:36:05 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2007-03-08 17:36:05 +0000
commit0c948c27462a668b4e01f7841c0cca812fbbdd8c (patch)
treefa8cc8f84a345de54e6ab532ecec5b191cd7a5ca
parent3c2d980c94357e2a020597a47cee0ee1c2458be7 (diff)
downloadgcc-0c948c27462a668b4e01f7841c0cca812fbbdd8c.zip
gcc-0c948c27462a668b4e01f7841c0cca812fbbdd8c.tar.gz
gcc-0c948c27462a668b4e01f7841c0cca812fbbdd8c.tar.bz2
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
-rw-r--r--gcc/ChangeLog30
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-11.c17
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-12.c16
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-13.c18
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-14.c15
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-15.c15
-rw-r--r--gcc/testsuite/gcc.dg/no-strict-overflow-5.c20
-rw-r--r--gcc/testsuite/gcc.dg/no-strict-overflow-6.c21
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-dom.c2
-rw-r--r--gcc/tree-ssa-propagate.c4
-rw-r--r--gcc/tree-ssa-threadedge.c13
-rw-r--r--gcc/tree-vrp.c150
15 files changed, 307 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 98906d7..5b19aa3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 4feaa9f..82821cb 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -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 \
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4de1a12..a2780b4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-11.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-11.c
new file mode 100644
index 0000000..c98610e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-11.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-12.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-12.c
new file mode 100644
index 0000000..177904d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-12.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-13.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-13.c
new file mode 100644
index 0000000..170d137
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-13.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
new file mode 100644
index 0000000..6f3c5a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-14.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
new file mode 100644
index 0000000..d1627d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-15.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-5.c b/gcc/testsuite/gcc.dg/no-strict-overflow-5.c
new file mode 100644
index 0000000..7f82014
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-strict-overflow-5.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.dg/no-strict-overflow-6.c b/gcc/testsuite/gcc.dg/no-strict-overflow-6.c
new file mode 100644
index 0000000..664aa25
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/no-strict-overflow-6.c
@@ -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" } } */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 87b655b..bb08732 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -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. */
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 888c5ee..22e0121 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -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);
}
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 3cc3239..1981fa1 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -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)
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 72018c0..777685a 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -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;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index fd5ba64..0e0e327 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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. */
+/* 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)
+simplify_stmt_for_jump_threading (tree stmt, tree within_stmt)
{
- bool sop;
-
/* 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