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 /gcc/tree-vrp.c | |
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
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 150 |
1 files changed, 133 insertions, 17 deletions
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 |