aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-01-05 19:13:29 +0100
committerJakub Jelinek <jakub@redhat.com>2021-01-05 19:13:29 +0100
commit5de7bf5bc98ec9edc6838a443521204d0eca7605 (patch)
tree388829cc39978cb2685f30f05b83652575aec353
parent6b577a17b26347e78c8b9167f24fc5c9d9724270 (diff)
downloadgcc-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.
-rw-r--r--gcc/cfgexpand.c8
-rw-r--r--gcc/expr.c41
-rw-r--r--gcc/expr.h1
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-25.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94802.c59
5 files changed, 110 insertions, 1 deletions
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 1d3f96f..b73019b 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2621,6 +2621,14 @@ expand_gimple_cond (basic_block bb, gcond *stmt)
&& TREE_CODE (op1) == INTEGER_CST)
code = maybe_optimize_mod_cmp (code, &op0, &op1);
+ /* Optimize (x - y) < 0 into x < y if x - y has undefined overflow. */
+ if (!TYPE_UNSIGNED (TREE_TYPE (op0))
+ && (code == LT_EXPR || code == LE_EXPR
+ || code == GT_EXPR || code == GE_EXPR)
+ && integer_zerop (op1)
+ && TREE_CODE (op0) == SSA_NAME)
+ maybe_optimize_sub_cmp_0 (code, &op0, &op1);
+
last2 = last = get_last_insn ();
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
diff --git a/gcc/expr.c b/gcc/expr.c
index d472eea..04ef5ad 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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
diff --git a/gcc/expr.h b/gcc/expr.h
index 6f99680..1f0177a 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -298,6 +298,7 @@ extern tree string_constant (tree, tree *, tree *, tree *);
extern tree byte_representation (tree, tree *, tree *, tree *);
extern enum tree_code maybe_optimize_mod_cmp (enum tree_code, tree *, tree *);
+extern void maybe_optimize_sub_cmp_0 (enum tree_code, tree *, tree *);
/* Two different ways of generating switch statements. */
extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c
index 774474d..0091644 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-25.c
@@ -7,5 +7,5 @@
int
foo (int x, int y)
{
- return x - y < 0; /* { dg-warning "assuming signed overflow does not occur" "correct warning" { xfail *-*-* } } */
+ return x - y < 0; /* { dg-warning "assuming signed overflow does not occur" "correct warning" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/pr94802.c b/gcc/testsuite/gcc.target/i386/pr94802.c
new file mode 100644
index 0000000..6c1bc66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr94802.c
@@ -0,0 +1,59 @@
+/* PR tree-optimization/94802 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -masm=att" } */
+/* { dg-final { scan-assembler-not "\ttestl\t" } } */
+/* { dg-final { scan-assembler-times "\tcmpl\t" 8 } } */
+
+void foo (void);
+
+int
+f1 (int a, int b)
+{
+ return (a - b) >= 0;
+}
+
+int
+f2 (int a, int b)
+{
+ return (a - b) > 0;
+}
+
+int
+f3 (int a, int b)
+{
+ return (a - b) <= 0;
+}
+
+int
+f4 (int a, int b)
+{
+ return (a - b) < 0;
+}
+
+void
+f5 (int a, int b)
+{
+ if ((a - b) >= 0)
+ foo ();
+}
+
+void
+f6 (int a, int b)
+{
+ if ((a - b) > 0)
+ foo ();
+}
+
+void
+f7 (int a, int b)
+{
+ if ((a - b) <= 0)
+ foo ();
+}
+
+void
+f8 (int a, int b)
+{
+ if ((a - b) < 0)
+ foo ();
+}