Move some comparison simplifications to match.pd
authorMarc Glisse <marc.glisse@inria.fr>
Mon, 31 Aug 2015 14:02:00 +0000 (16:02 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Mon, 31 Aug 2015 14:02:00 +0000 (14:02 +0000)
2015-08-31  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* tree.h (zerop): New function.
* tree.c (zerop): Likewise.
(element_precision): Handle expressions.
* match.pd (define_predicates): Add zerop.
(x <= +Inf): Fix comment.
(abs (x) == 0, A & C == C, A & C != 0): Converted from ...
* fold-const.c (fold_binary_loc): ... here. Remove.

gcc/testsuite/
* gcc.dg/tree-ssa/cmp-1.c: New file.

From-SVN: r227346

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index adc85fe964af83ce4a8978cca291faeb60dc013e..fdc02094e27ed5c76a37af7340530ea9a25b74db 100644 (file)
@@ -1,3 +1,13 @@
+2015-08-31  Marc Glisse  <marc.glisse@inria.fr>
+
+       * tree.h (zerop): New function.
+       * tree.c (zerop): Likewise.
+       (element_precision): Handle expressions.
+       * match.pd (define_predicates): Add zerop.
+       (x <= +Inf): Fix comment.
+       (abs (x) == 0, A & C == C, A & C != 0): Converted from ...
+       * fold-const.c (fold_binary_loc): ... here. Remove.
+
 2015-08-31  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/67381
index a5d58a86692762a695d23be63c8afa9de00fcc87..d478c4dc1c234a7223922d2bf5d987514a7134a1 100644 (file)
@@ -10678,11 +10678,6 @@ fold_binary_loc (location_t loc,
                                    TREE_OPERAND (arg0, 1), arg1);
        }
 
-      /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
-      if (TREE_CODE (arg0) == ABS_EXPR
-         && (integer_zerop (arg1) || real_zerop (arg1)))
-       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), arg1);
-
       /* If this is an EQ or NE comparison with zero and ARG0 is
         (1 << foo) & bar, convert it to (bar >> foo) & 1.  Both require
         two operations, but the latter can be done in one less insn
@@ -10785,21 +10780,6 @@ fold_binary_loc (location_t loc,
            }
        }
 
-      /* If we have (A & C) == C where C is a power of 2, convert this into
-        (A & C) != 0.  Similarly for NE_EXPR.  */
-      if (TREE_CODE (arg0) == BIT_AND_EXPR
-         && integer_pow2p (TREE_OPERAND (arg0, 1))
-         && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
-                           arg0, fold_convert_loc (loc, TREE_TYPE (arg0),
-                                                   integer_zero_node));
-
-      /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign
-        bit, then fold the expression into A < 0 or A >= 0.  */
-      tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1, type);
-      if (tem)
-       return tem;
-
       /* If we have (A & C) == D where D & ~C != 0, convert this into 0.
         Similarly for NE_EXPR.  */
       if (TREE_CODE (arg0) == BIT_AND_EXPR
index 50de7bbf8a63889cd80995c79c1f72b775708058..fb4b342d31d26a03bc756c538f6635f2acf6ddb2 100644 (file)
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
    integer_onep integer_zerop integer_all_onesp integer_minus_onep
    integer_each_onep integer_truep integer_nonzerop
    real_zerop real_onep real_minus_onep
+   zerop
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
    integer_pow2p
@@ -1608,7 +1609,7 @@ along with GCC; see the file COPYING3.  If not see
        /* x <= +Inf is always true, if we don't case about NaNs.  */
        (if (! HONOR_NANS (@0))
        { constant_boolean_node (true, type); }
-       /* x <= +Inf is the same as x == x, i.e. isfinite(x).  */
+       /* x <= +Inf is the same as x == x, i.e. !isnan(x).  */
        (eq @0 @0)))
       /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
       (if (code == EQ_EXPR || code == GE_EXPR)
@@ -1765,6 +1766,12 @@ along with GCC; see the file COPYING3.  If not see
     (if (tem && !TREE_OVERFLOW (tem))
      (scmp @0 { tem; }))))))
 
+/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0.  */
+(for op (eq ne)
+ (simplify
+  (op (abs @0) zerop@1)
+  (op @0 @1)))
+
 /* From fold_sign_changed_comparison and fold_widened_comparison.  */
 (for cmp (simple_comparison)
  (simplify
@@ -1871,6 +1878,28 @@ along with GCC; see the file COPYING3.  If not see
   (if (tree_single_nonzero_warnv_p (@0, NULL))
    { constant_boolean_node (cmp == NE_EXPR, type); })))
 
+/* If we have (A & C) == C where C is a power of 2, convert this into
+   (A & C) != 0.  Similarly for NE_EXPR.  */
+(for cmp (eq ne)
+     icmp (ne eq)
+ (simplify
+  (cmp (bit_and@2 @0 integer_pow2p@1) @1)
+  (icmp @2 { build_zero_cst (TREE_TYPE (@0)); })))
+/* If we have (A & C) != 0 where C is the sign bit of A, convert
+   this into A < 0.  Similarly for (A & C) == 0 into A >= 0.  */
+(for cmp (eq ne)
+     ncmp (ge lt)
+ (simplify
+  (cmp (bit_and (convert?@2 @0) integer_pow2p@1) integer_zerop)
+  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+       && (TYPE_PRECISION (TREE_TYPE (@0))
+          == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0))))
+       && element_precision (@2) >= element_precision (@0)
+       && wi::only_sign_bit_p (@1, element_precision (@0)))
+   (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+    (ncmp (convert:stype @0) { build_zero_cst (stype); })))))
+
 /* When the addresses are not directly of decls compare base and offset.
    This implements some remaining parts of fold_comparison address
    comparisons but still no complete part of it.  Still it is good
index 24f93142db6cecc7a9d94793a18cb51c29f6a95f..15dc00dd211fcb49a51905c650cc8b7e85050767 100644 (file)
@@ -1,3 +1,7 @@
+2015-08-31  Marc Glisse  <marc.glisse@inria.fr>
+
+       * gcc.dg/tree-ssa/cmp-1.c: New file.
+
 2015-08-31  Marc Glisse  <marc.glisse@inria.fr>
 
        * gcc.dg/tree-ssa/complex-7.c: New file.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c
new file mode 100644 (file)
index 0000000..6faa70c
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-gimple -fdump-tree-optimized" } */
+
+int f(int a){
+  int b = -__INT_MAX__-1;
+  a &= b;
+  return a == b;
+}
+int g(int x){
+    x = x < 0 ? -x : x;
+    return x == 0;
+}
+
+/* This should work even if int is not 32 bits, it is just not meaningful in
+   that case.  */
+/* { dg-final { scan-tree-dump-not "-2147483648" "optimized"} } */
+/* { dg-final { scan-tree-dump " < 0" "optimized"} } */
+/* { dg-final { scan-tree-dump "ABS_EXPR" "gimple"} } */
+/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized"} } */
index af3a6a340e4666a20151fc2ebd084dfd8dff7fcc..ed64fe7d273de68bdc1aae334356cb0f2c7065ea 100644 (file)
@@ -2215,6 +2215,17 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
   return v;
 }
 \f
+/* Return 1 if EXPR is the constant zero, whether it is integral, float or
+   fixed, and scalar, complex or vector.  */
+
+int
+zerop (const_tree expr)
+{
+  return (integer_zerop (expr)
+         || real_zerop (expr)
+         || fixed_zerop (expr));
+}
+
 /* Return 1 if EXPR is the integer constant zero or a complex constant
    of zero.  */
 
@@ -7512,6 +7523,8 @@ valid_constant_size_p (const_tree size)
 unsigned int
 element_precision (const_tree type)
 {
+  if (!TYPE_P (type))
+    type = TREE_TYPE (type);
   enum tree_code code = TREE_CODE (type);
   if (code == COMPLEX_TYPE || code == VECTOR_TYPE)
     type = TREE_TYPE (type);
index 2cd6ec475a8832fa47e1b7fd5b10e98ee550200a..e5001510bdc6c13e98200dda7dbb24afe5b9bc7c 100644 (file)
@@ -4109,6 +4109,10 @@ extern tree uniform_vector_p (const_tree);
 
 extern vec<tree, va_gc> *ctor_to_vec (tree);
 
+/* zerop (tree x) is nonzero if X is a constant of value 0.  */
+
+extern int zerop (const_tree);
+
 /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0.  */
 
 extern int integer_zerop (const_tree);