Re: [PATCH] expand: Fold x - y < 0 to x < y during expansion [PR94802]

2021-01-05 Thread Jeff Law via Gcc-patches



On 1/5/21 8:30 AM, Jakub Jelinek wrote:
> Hi!
>
> 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.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2021-01-05  Jakub Jelinek  
>
>   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.
OK
jeff



[PATCH] expand: Fold x - y < 0 to x < y during expansion [PR94802]

2021-01-05 Thread Jakub Jelinek via Gcc-patches
Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-01-05  Jakub Jelinek  

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.

--- gcc/expr.h.jj   2021-01-04 10:25:37.700246654 +0100
+++ gcc/expr.h  2021-01-05 12:55:20.673233214 +0100
@@ -298,6 +298,7 @@ extern tree string_constant (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);
--- gcc/expr.c.jj   2021-01-04 10:25:38.0 +0100
+++ gcc/expr.c  2021-01-05 14:12:26.826136638 +0100
@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3.
 #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 c
   *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 % to %",
+   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, m
}
 }
 
+  /* 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, , );
+
   /* 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
--- gcc/cfgexpand.c.jj  2021-01-04 10:25:38.437238308 +0100
+++ gcc/cfgexpand.c 2021-01-05 12:58:51.718857608 +0100
@@ -2621,6 +2621,14 @@ expand_gimple_cond (basic_block bb, gcon
   && TREE_CODE (op1) == INTEGER_CST)
 code = maybe_optimize_mod_cmp (code, , );
 
+  /* 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, , );
+
   last2 = last = get_last_insn ();
 
   extract_true_false_edges_from_block (bb, _edge, _edge);
--- gcc/testsuite/gcc.target/i386/pr94802.c.jj  2021-01-05 13:08:11.044567008 
+0100
+++ gcc/testsuite/gcc.target/i386/pr94802.c 2021-01-05 13:07:50.093802618 
+0100
@@ -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;