diff options
author | Ian Lance Taylor <iant@google.com> | 2007-03-08 17:36:05 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2007-03-08 17:36:05 +0000 |
commit | 0c948c27462a668b4e01f7841c0cca812fbbdd8c (patch) | |
tree | fa8cc8f84a345de54e6ab532ecec5b191cd7a5ca | |
parent | 3c2d980c94357e2a020597a47cee0ee1c2458be7 (diff) | |
download | gcc-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/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstrict-overflow-11.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstrict-overflow-12.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstrict-overflow-13.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstrict-overflow-14.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wstrict-overflow-15.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/no-strict-overflow-5.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/no-strict-overflow-6.c | 21 | ||||
-rw-r--r-- | gcc/tree-flow.h | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 2 | ||||
-rw-r--r-- | gcc/tree-ssa-propagate.c | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-threadedge.c | 13 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 150 |
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 |