diff options
author | Patrick Palka <ppalka@gcc.gnu.org> | 2014-11-20 22:25:35 +0000 |
---|---|---|
committer | Patrick Palka <ppalka@gcc.gnu.org> | 2014-11-20 22:25:35 +0000 |
commit | 7ac753f9683133e7b91f2d497ab6b25418a05c5d (patch) | |
tree | 50fdade7d7ba6205c00a1d0613c261fa0f192e1f /gcc/tree-vrp.c | |
parent | 75bda2e8134c013bc3d02b78e5b8b34022961985 (diff) | |
download | gcc-7ac753f9683133e7b91f2d497ab6b25418a05c5d.zip gcc-7ac753f9683133e7b91f2d497ab6b25418a05c5d.tar.gz gcc-7ac753f9683133e7b91f2d497ab6b25418a05c5d.tar.bz2 |
Disable an unsafe VRP transformation when -fno-strict-overflow is set
gcc/
* tree-vrp.c (test_for_singularity): New parameter
strict_overflow_p. Set *strict_overflow_p to true if signed
overflow must be undefined for the return value to satisfy the
conditional.
(simplify_cond_using_ranges): Don't perform the simplification
if it violates overflow rules.
gcc/testsuite/
* gcc.dg/no-strict-overflow-8.c: New test.
From-SVN: r217895
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index bcf4c2b..a75138f 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -9117,11 +9117,15 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) a known value range VR. If there is one and only one value which will satisfy the - conditional, then return that value. Else return NULL. */ + conditional, then return that value. Else return NULL. + + If signed overflow must be undefined for the value to satisfy + the conditional, then set *STRICT_OVERFLOW_P to true. */ static tree test_for_singularity (enum tree_code cond_code, tree op0, - tree op1, value_range_t *vr) + tree op1, value_range_t *vr, + bool *strict_overflow_p) { tree min = NULL; tree max = NULL; @@ -9172,7 +9176,16 @@ test_for_singularity (enum tree_code cond_code, tree op0, then there is only one value which can satisfy the condition, return that value. */ if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min)) - return min; + { + if ((cond_code == LE_EXPR || cond_code == LT_EXPR) + && is_overflow_infinity (vr->max)) + *strict_overflow_p = true; + if ((cond_code == GE_EXPR || cond_code == GT_EXPR) + && is_overflow_infinity (vr->min)) + *strict_overflow_p = true; + + return min; + } } return NULL; } @@ -9252,9 +9265,12 @@ simplify_cond_using_ranges (gcond *stmt) able to simplify this conditional. */ if (vr->type == VR_RANGE) { - tree new_tree = test_for_singularity (cond_code, op0, op1, vr); + enum warn_strict_overflow_code wc = WARN_STRICT_OVERFLOW_COMPARISON; + bool sop = false; + tree new_tree = test_for_singularity (cond_code, op0, op1, vr, &sop); - if (new_tree) + if (new_tree + && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))) { if (dump_file) { @@ -9275,16 +9291,30 @@ simplify_cond_using_ranges (gcond *stmt) fprintf (dump_file, "\n"); } + if (sop && issue_strict_overflow_warning (wc)) + { + location_t location = input_location; + if (gimple_has_location (stmt)) + location = gimple_location (stmt); + + warning_at (location, OPT_Wstrict_overflow, + "assuming signed overflow does not occur when " + "simplifying conditional"); + } + return true; } /* Try again after inverting the condition. We only deal with integral types here, so no need to worry about issues with inverting FP comparisons. */ - cond_code = invert_tree_comparison (cond_code, false); - new_tree = test_for_singularity (cond_code, op0, op1, vr); + sop = false; + new_tree = test_for_singularity + (invert_tree_comparison (cond_code, false), + op0, op1, vr, &sop); - if (new_tree) + if (new_tree + && (!sop || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))) { if (dump_file) { @@ -9305,6 +9335,17 @@ simplify_cond_using_ranges (gcond *stmt) fprintf (dump_file, "\n"); } + if (sop && issue_strict_overflow_warning (wc)) + { + location_t location = input_location; + if (gimple_has_location (stmt)) + location = gimple_location (stmt); + + warning_at (location, OPT_Wstrict_overflow, + "assuming signed overflow does not occur when " + "simplifying conditional"); + } + return true; } } |