diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-05 19:13:29 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-05 19:13:29 +0100 |
commit | 5de7bf5bc98ec9edc6838a443521204d0eca7605 (patch) | |
tree | 388829cc39978cb2685f30f05b83652575aec353 /gcc/expr.c | |
parent | 6b577a17b26347e78c8b9167f24fc5c9d9724270 (diff) | |
download | gcc-5de7bf5bc98ec9edc6838a443521204d0eca7605.zip gcc-5de7bf5bc98ec9edc6838a443521204d0eca7605.tar.gz gcc-5de7bf5bc98ec9edc6838a443521204d0eca7605.tar.bz2 |
expand: Fold x - y < 0 to x < y during expansion [PR94802]
My earlier patch to simplify x - y < 0 etc. for signed subtraction
with undefined overflow into x < y in match.pd regressed some tests,
even when it was guarded to be post-IPA, the following patch thus
attempts to optimize that during expansion instead (which is the last
time we can do it, afterwards we lose the information whether it was
x - y < 0 or (int) ((unsigned) x - y) < 0 for which we couldn't
optimize it.
2021-01-05 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/94802
* expr.h (maybe_optimize_sub_cmp_0): Declare.
* expr.c: Include tree-pretty-print.h and flags.h.
(maybe_optimize_sub_cmp_0): New function.
(do_store_flag): Use it.
* cfgexpand.c (expand_gimple_cond): Likewise.
* gcc.target/i386/pr94802.c: New test.
* gcc.dg/Wstrict-overflow-25.c: Remove xfail.
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 41 |
1 files changed, 41 insertions, 0 deletions
@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3. If not see #include "ccmp.h" #include "gimple-fold.h" #include "rtx-vector-builder.h" +#include "tree-pretty-print.h" +#include "flags.h" /* If this is nonzero, we do not bother generating VOLATILE @@ -12275,6 +12277,37 @@ maybe_optimize_mod_cmp (enum tree_code code, tree *arg0, tree *arg1) *arg1 = c4; return code == EQ_EXPR ? LE_EXPR : GT_EXPR; } + +/* Optimize x - y < 0 into x < 0 if x - y has undefined overflow. */ + +void +maybe_optimize_sub_cmp_0 (enum tree_code code, tree *arg0, tree *arg1) +{ + gcc_checking_assert (code == GT_EXPR || code == GE_EXPR + || code == LT_EXPR || code == LE_EXPR); + gcc_checking_assert (integer_zerop (*arg1)); + + if (!optimize) + return; + + gimple *stmt = get_def_for_expr (*arg0, MINUS_EXPR); + if (stmt == NULL) + return; + + tree treeop0 = gimple_assign_rhs1 (stmt); + tree treeop1 = gimple_assign_rhs2 (stmt); + if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (treeop0))) + return; + + if (issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_COMPARISON)) + warning_at (gimple_location (stmt), OPT_Wstrict_overflow, + "assuming signed overflow does not occur when " + "simplifying %<X - Y %s 0%> to %<X %s Y%>", + op_symbol_code (code), op_symbol_code (code)); + + *arg0 = treeop0; + *arg1 = treeop1; +} /* Generate code to calculate OPS, and exploded expression using a store-flag instruction and return an rtx for the result. @@ -12363,6 +12396,14 @@ do_store_flag (sepops ops, rtx target, machine_mode mode) } } + /* Optimize (x - y) < 0 into x < y if x - y has undefined overflow. */ + if (!unsignedp + && (ops->code == LT_EXPR || ops->code == LE_EXPR + || ops->code == GT_EXPR || ops->code == GE_EXPR) + && integer_zerop (arg1) + && TREE_CODE (arg0) == SSA_NAME) + maybe_optimize_sub_cmp_0 (ops->code, &arg0, &arg1); + /* Get the rtx comparison code to use. We know that EXP is a comparison operation of some type. Some comparisons against 1 and -1 can be converted to comparisons with zero. Do so here so that the tests |