]> gcc.gnu.org Git - gcc.git/commitdiff
re PR rtl-optimization/3995 (i386 optimisation: joining tests)
authorRoger Sayle <roger@eyesopen.com>
Mon, 6 May 2002 22:59:38 +0000 (22:59 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 6 May 2002 22:59:38 +0000 (22:59 +0000)
PR opt/3995
* fold-const.c (sign_bit_p): New function.
(fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and
        (A & C) != 0 into A < 0, when constant C is the sign bit of A's type.
Reapply fold when converting (A & C) == C into (A & C) != 0.
(fold_binary_op_with_conditional_arg): Fix typo in comment.

testsuite/
* gcc.c-torture/execute/20020506-1.c: New test case.

From-SVN: r53241

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20020506-1.c [new file with mode: 0644]

index d88c97359aa0a46375e2e53707aa04e72f1406b4..fd44b153b6d01a7110702593f61748a28c79d41c 100644 (file)
@@ -1,3 +1,12 @@
+2002-05-06  Roger Sayle  <roger@eyesopen.com>
+
+       PR opt/3995
+       * fold-const.c (sign_bit_p): New function.
+       (fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and
+        (A & C) != 0 into A < 0, when constant C is the sign bit of A's type.
+       Reapply fold when converting (A & C) == C into (A & C) != 0.
+       (fold_binary_op_with_conditional_arg): Fix typo in comment.
+
 2002-05-07  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * c-common.c (warn_multichar): New.
index 9142f3d80dc78db5f390e5630094407c2443a724..6b4982aad751b52437bf5f44bfe12de0893a175d 100644 (file)
@@ -86,6 +86,7 @@ static tree decode_field_reference PARAMS ((tree, HOST_WIDE_INT *,
                                            enum machine_mode *, int *,
                                            int *, tree *, tree *));
 static int all_ones_mask_p     PARAMS ((tree, int));
+static tree sign_bit_p         PARAMS ((tree, tree));
 static int simple_operand_p    PARAMS ((tree));
 static tree range_binop                PARAMS ((enum tree_code, tree, tree, int,
                                         tree, int));
@@ -2634,6 +2635,55 @@ all_ones_mask_p (mask, size)
                                     size_int (precision - size), 0));
 }
 
+/* Subroutine for fold: determine if VAL is the INTEGER_CONST that
+   represents the sign bit of EXP's type.  If EXP represents a sign
+   or zero extension, also test VAL against the unextended type.
+   The return value is the (sub)expression whose sign bit is VAL,
+   or NULL_TREE otherwise.  */
+
+static tree
+sign_bit_p (exp, val)
+     tree exp;
+     tree val;
+{
+  unsigned HOST_WIDE_INT lo;
+  HOST_WIDE_INT hi;
+  int width;
+  tree t;
+
+  /* Tree EXP must have a integral type.  */
+  t = TREE_TYPE (exp);
+  if (! INTEGRAL_TYPE_P (t))
+    return NULL_TREE;
+
+  /* Tree VAL must be an integer constant.  */
+  if (TREE_CODE (val) != INTEGER_CST
+      || TREE_CONSTANT_OVERFLOW (val))
+    return NULL_TREE;
+
+  width = TYPE_PRECISION (t);
+  if (width > HOST_BITS_PER_WIDE_INT)
+    {
+      hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
+      lo = 0;
+    }
+  else
+    {
+      hi = 0;
+      lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
+    }
+
+  if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
+    return exp;
+
+  /* Handle extension from a narrower type.  */
+  if (TREE_CODE (exp) == NOP_EXPR
+      && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))) < width)
+    return sign_bit_p (TREE_OPERAND (exp, 0), val);
+
+  return NULL_TREE;
+}
+
 /* Subroutine for fold_truthop: determine if an operand is simple enough
    to be evaluated unconditionally.  */
 
@@ -4173,7 +4223,7 @@ count_cond (expr, lim)
   return MIN (lim, 1 + ctrue + cfalse);
 }
 
-/* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
+/* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
    Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
    CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
    expression, and ARG to `a'.  If COND_FIRST_P is non-zero, then the
@@ -6037,8 +6087,25 @@ fold (expr)
          && TREE_CODE (arg0) == BIT_AND_EXPR
          && integer_pow2p (TREE_OPERAND (arg0, 1))
          && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
-       return build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
-                     arg0, integer_zero_node);
+       return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+                           arg0, integer_zero_node));
+
+      /* 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.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && TREE_CODE (arg0) == BIT_AND_EXPR
+         && integer_zerop (arg1))
+       {
+         tree arg00 = sign_bit_p (TREE_OPERAND (arg0, 0),
+                                  TREE_OPERAND (arg0, 1));
+         if (arg00 != NULL_TREE)
+         {
+           tree stype = (*lang_hooks.types.signed_type) (TREE_TYPE (arg00));
+           return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
+                               convert (stype, arg00),
+                               convert (stype, integer_zero_node)));
+         }
+       }
 
       /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
         and similarly for >= into !=.  */
index 1b8bd7157c5eca75dd3bf7242c1899befa4e3101..c231d99be32af4c546ffafb139ad16ca3437c759 100644 (file)
@@ -1,3 +1,7 @@
+2002-05-06  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/20020506-1.c: New test case.
+
 2002-05-07  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * gcc.dg/cpp/charconst-3.c: Correct tests accordingly.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20020506-1.c b/gcc/testsuite/gcc.c-torture/execute/20020506-1.c
new file mode 100644 (file)
index 0000000..bcbd45b
--- /dev/null
@@ -0,0 +1,333 @@
+/* Copyright (C) 2002  Free Software Foundation.
+
+   Test that (A & C1) op C2 optimizations behave correctly where C1 is
+   a constant power of 2, op is == or !=, and C2 is C1 or zero.
+
+   Written by Roger Sayle, 5th May 2002.  */
+
+#include <limits.h>
+
+extern void abort (void);
+
+void test1 (signed char c, int set);
+void test2 (unsigned char c, int set);
+void test3 (short s, int set);
+void test4 (unsigned short s, int set);
+void test5 (int i, int set);
+void test6 (unsigned int i, int set);
+void test7 (long long l, int set);
+void test8 (unsigned long long l, int set);
+
+#ifndef LONG_LONG_MAX
+#define LONG_LONG_MAX __LONG_LONG_MAX__
+#endif
+#ifndef LONG_LONG_MIN
+#define LONG_LONG_MIN (-LONG_LONG_MAX-1)
+#endif
+#ifndef ULONG_LONG_MAX
+#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1)
+#endif
+
+
+void
+test1 (signed char c, int set)
+{
+  if ((c & (SCHAR_MAX+1)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) == (SCHAR_MAX+1))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) != (SCHAR_MAX+1))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test2 (unsigned char c, int set)
+{
+  if ((c & (SCHAR_MAX+1)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) == (SCHAR_MAX+1))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((c & (SCHAR_MAX+1)) != (SCHAR_MAX+1))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test3 (short s, int set)
+{
+  if ((s & (SHRT_MAX+1)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((s & (SHRT_MAX+1)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((s & (SHRT_MAX+1)) == (SHRT_MAX+1))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((s & (SHRT_MAX+1)) != (SHRT_MAX+1))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test4 (unsigned short s, int set)
+{
+  if ((s & (SHRT_MAX+1)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((s & (SHRT_MAX+1)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((s & (SHRT_MAX+1)) == (SHRT_MAX+1))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((s & (SHRT_MAX+1)) != (SHRT_MAX+1))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test5 (int i, int set)
+{
+  if ((i & (INT_MAX+1U)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((i & (INT_MAX+1U)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((i & (INT_MAX+1U)) == (INT_MAX+1U))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((i & (INT_MAX+1U)) != (INT_MAX+1U))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test6 (unsigned int i, int set)
+{
+  if ((i & (INT_MAX+1U)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((i & (INT_MAX+1U)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((i & (INT_MAX+1U)) == (INT_MAX+1U))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((i & (INT_MAX+1U)) != (INT_MAX+1U))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test7 (long long l, int set)
+{
+  if ((l & (LONG_LONG_MAX+1ULL)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) == (LONG_LONG_MAX+1ULL))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) != (LONG_LONG_MAX+1ULL))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+void
+test8 (unsigned long long l, int set)
+{
+  if ((l & (LONG_LONG_MAX+1ULL)) == 0)
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) != 0)
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) == (LONG_LONG_MAX+1ULL))
+    {
+      if (!set) abort ();
+    }
+  else
+    if (set) abort ();
+
+  if ((l & (LONG_LONG_MAX+1ULL)) != (LONG_LONG_MAX+1ULL))
+    {
+      if (set) abort ();
+    }
+  else
+    if (!set) abort ();
+}
+
+int
+main ()
+{
+  test1 (0, 0);
+  test1 (SCHAR_MAX, 0);
+  test1 (SCHAR_MIN, 1);
+  test1 (UCHAR_MAX, 1);
+
+  test2 (0, 0);
+  test2 (SCHAR_MAX, 0);
+  test2 (SCHAR_MIN, 1);
+  test2 (UCHAR_MAX, 1);
+
+  test3 (0, 0);
+  test3 (SHRT_MAX, 0);
+  test3 (SHRT_MIN, 1);
+  test3 (USHRT_MAX, 1);
+
+  test4 (0, 0);
+  test4 (SHRT_MAX, 0);
+  test4 (SHRT_MIN, 1);
+  test4 (USHRT_MAX, 1);
+
+  test5 (0, 0);
+  test5 (INT_MAX, 0);
+  test5 (INT_MIN, 1);
+  test5 (UINT_MAX, 1);
+
+  test6 (0, 0);
+  test6 (INT_MAX, 0);
+  test6 (INT_MIN, 1);
+  test6 (UINT_MAX, 1);
+
+  test7 (0, 0);
+  test7 (LONG_LONG_MAX, 0);
+  test7 (LONG_LONG_MIN, 1);
+  test7 (ULONG_LONG_MAX, 1);
+
+  test8 (0, 0);
+  test8 (LONG_LONG_MAX, 0);
+  test8 (LONG_LONG_MIN, 1);
+  test8 (ULONG_LONG_MAX, 1);
+
+  return 0;
+}
+
This page took 0.101202 seconds and 5 git commands to generate.