OSDN Git Service

* fold-const.c (comparison_to_compcode): New function to convert
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 16:55:24 +0000 (16:55 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 16:55:24 +0000 (16:55 +0000)
an comparison TREE CODE into a bit-based representation.
(compcode_to_comparison): New function to convert from this bit
based representation back to a comparison TREE CODE.
(fold_truthop): Simplify (x<y) && (x==y) and related composite
comparisons.

* gcc.c-tortuture/execute/compare-1.c: New test case.
* gcc.c-tortuture/execute/compare-2.c: New test case.
* gcc.c-tortuture/execute/compare-3.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54647 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 75ee853..b190a54 100644 (file)
@@ -1,3 +1,12 @@
+2002-06-15  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (comparison_to_compcode): New function to convert
+       an comparison TREE CODE into a bit-based representation.
+       (compcode_to_comparison): New function to convert from this bit
+       based representation back to a comparison TREE CODE.
+       (fold_truthop): Simplify (x<y) && (x==y) and related composite
+       comparisons.
+
 2002-06-15  Aldy Hernandez  <aldyh@redhat.com>
 
         * tm.texi (MEMBER_TYPE_FORCES_BLK): Document MODE argument.
index 5c04d78..f9f3a64 100644 (file)
@@ -72,6 +72,8 @@ static int size_htab_eq               PARAMS ((const void *, const void *));
 static tree fold_convert       PARAMS ((tree, tree));
 static enum tree_code invert_tree_comparison PARAMS ((enum tree_code));
 static enum tree_code swap_tree_comparison PARAMS ((enum tree_code));
+static int comparison_to_compcode PARAMS ((enum tree_code));
+static enum tree_code compcode_to_comparison PARAMS ((int));
 static int truth_value_p       PARAMS ((enum tree_code));
 static int operand_equal_for_comparison_p PARAMS ((tree, tree, tree));
 static int twoval_comparison_p PARAMS ((tree, tree *, tree *, int *));
@@ -115,6 +117,18 @@ static bool fold_real_zero_addition_p      PARAMS ((tree, tree, int));
 #define CHARMASK 0x7f
 #endif
 
+/* The following constants represent a bit based encoding of GCC's
+   comparison operators.  This encoding simplifies transformations
+   on relational comparison operators, such as AND and OR.  */
+#define COMPCODE_FALSE   0
+#define COMPCODE_LT      1
+#define COMPCODE_EQ      2
+#define COMPCODE_LE      3
+#define COMPCODE_GT      4
+#define COMPCODE_NE      5
+#define COMPCODE_GE      6
+#define COMPCODE_TRUE    7
+
 /* We know that A1 + B1 = SUM1, using 2's complement arithmetic and ignoring
    overflow.  Suppose A, B and SUM have the same respective signs as A1, B1,
    and SUM1.  Then this yields nonzero if overflow occurred during the
@@ -1709,6 +1723,61 @@ swap_tree_comparison (code)
     }
 }
 
+
+/* Convert a comparison tree code from an enum tree_code representation
+   into a compcode bit-based encoding.  This function is the inverse of
+   compcode_to_comparison.  */
+
+static int
+comparison_to_compcode (code)
+     enum tree_code code;
+{
+  switch (code)
+    {
+    case LT_EXPR:
+      return COMPCODE_LT;
+    case EQ_EXPR:
+      return COMPCODE_EQ;
+    case LE_EXPR:
+      return COMPCODE_LE;
+    case GT_EXPR:
+      return COMPCODE_GT;
+    case NE_EXPR:
+      return COMPCODE_NE;
+    case GE_EXPR:
+      return COMPCODE_GE;
+    default:
+      abort ();
+    }
+}
+
+/* Convert a compcode bit-based encoding of a comparison operator back
+   to GCC's enum tree_code representation.  This function is the
+   inverse of comparison_to_compcode.  */
+
+static enum tree_code
+compcode_to_comparison (code)
+     int code;
+{
+  switch (code)
+    {
+    case COMPCODE_LT:
+      return LT_EXPR;
+    case COMPCODE_EQ:
+      return EQ_EXPR;
+    case COMPCODE_LE:
+      return LE_EXPR;
+    case COMPCODE_GT:
+      return GT_EXPR;
+    case COMPCODE_NE:
+      return NE_EXPR;
+    case COMPCODE_GE:
+      return GE_EXPR;
+    default:
+      abort ();
+    }
+}
+
 /* Return nonzero if CODE is a tree code that represents a truth value.  */
 
 static int
@@ -3498,6 +3567,48 @@ fold_truthop (code, truth_type, lhs, rhs)
   rl_arg = TREE_OPERAND (rhs, 0);
   rr_arg = TREE_OPERAND (rhs, 1);
 
+  /* Simplify (x<y) && (x==y) into (x<=y) and related optimizations.  */
+  if (simple_operand_p (ll_arg)
+      && simple_operand_p (lr_arg)
+      && !FLOAT_TYPE_P (TREE_TYPE (ll_arg)))
+    {
+      int compcode;
+
+      if (operand_equal_p (ll_arg, rl_arg, 0)
+          && operand_equal_p (lr_arg, rr_arg, 0))
+        {
+          int lcompcode, rcompcode;
+
+          lcompcode = comparison_to_compcode (lcode);
+          rcompcode = comparison_to_compcode (rcode);
+          compcode = (code == TRUTH_AND_EXPR)
+                     ? lcompcode & rcompcode
+                     : lcompcode | rcompcode;
+        }
+      else if (operand_equal_p (ll_arg, rr_arg, 0)
+               && operand_equal_p (lr_arg, rl_arg, 0))
+        {
+          int lcompcode, rcompcode;
+
+          rcode = swap_tree_comparison (rcode);
+          lcompcode = comparison_to_compcode (lcode);
+          rcompcode = comparison_to_compcode (rcode);
+          compcode = (code == TRUTH_AND_EXPR)
+                     ? lcompcode & rcompcode
+                     : lcompcode | rcompcode;
+        }
+      else
+       compcode = -1;
+
+      if (compcode == COMPCODE_TRUE)
+       return convert (truth_type, integer_one_node);
+      else if (compcode == COMPCODE_FALSE)
+       return convert (truth_type, integer_zero_node);
+      else if (compcode != -1)
+       return build (compcode_to_comparison (compcode),
+                     truth_type, ll_arg, lr_arg);
+    }
+
   /* If the RHS can be evaluated unconditionally and its operands are
      simple, it wins to evaluate the RHS unconditionally on machines
      with expensive branches.  In this case, this isn't a comparison
index ee641bc..68a9cc1 100644 (file)
@@ -1,3 +1,9 @@
+2002-06-15  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-tortuture/execute/compare-1.c: New test case.
+       * gcc.c-tortuture/execute/compare-2.c: New test case.
+       * gcc.c-tortuture/execute/compare-3.c: New test case.
+
 2002-06-13  Richard Henderson  <rth@redhat.com>
 
        * g++.old-deja/g++.abi/vtable2.C (INC_VDATA): New.  Define for
diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-1.c b/gcc/testsuite/gcc.c-torture/execute/compare-1.c
new file mode 100644 (file)
index 0000000..78b4650
--- /dev/null
@@ -0,0 +1,119 @@
+/* Copyright (C) 2002 Free Software Foundation.
+
+   Test for correctness of composite comparisons.
+
+   Written by Roger Sayle, 3rd June 2002.  */
+
+extern void abort (void);
+
+int ieq (int x, int y, int ok)
+{
+  if ((x<=y) && (x>=y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+
+  if ((x<=y) && (x==y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+
+  if ((x<=y) && (y<=x))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+
+  if ((y==x) && (x<=y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int ine (int x, int y, int ok)
+{
+  if ((x<y) || (x>y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int ilt (int x, int y, int ok)
+{
+  if ((x<y) && (x!=y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int ile (int x, int y, int ok)
+{
+  if ((x<y) || (x==y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int igt (int x, int y, int ok)
+{
+  if ((x>y) && (x!=y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int ige (int x, int y, int ok)
+{
+  if ((x>y) || (x==y))
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int
+main ()
+{
+  ieq (1, 4, 0);
+  ieq (3, 3, 1);
+  ieq (5, 2, 0);
+
+  ine (1, 4, 1);
+  ine (3, 3, 0);
+  ine (5, 2, 1);
+
+  ilt (1, 4, 1);
+  ilt (3, 3, 0);
+  ilt (5, 2, 0);
+
+  ile (1, 4, 1);
+  ile (3, 3, 1);
+  ile (5, 2, 0);
+
+  igt (1, 4, 0);
+  igt (3, 3, 0);
+  igt (5, 2, 1);
+
+  ige (1, 4, 0);
+  ige (3, 3, 1);
+  ige (5, 2, 1);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-2.c b/gcc/testsuite/gcc.c-torture/execute/compare-2.c
new file mode 100644 (file)
index 0000000..858df29
--- /dev/null
@@ -0,0 +1,24 @@
+/* Copyright (C) 2002 Free Software Foundation.
+
+   Ensure that the composite comparison optimization doesn't misfire
+   and attempt to combine a signed comparison with an unsigned one.
+
+   Written by Roger Sayle, 3rd June 2002.  */
+
+extern void abort (void);
+
+int
+foo (int x, int y)
+{
+  /* If miscompiled the following may become "x == y".  */
+  return (x<=y) && ((unsigned int)x >= (unsigned int)y);
+}
+
+int
+main ()
+{
+  if (! foo (-1,0))
+    abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/compare-3.c b/gcc/testsuite/gcc.c-torture/execute/compare-3.c
new file mode 100644 (file)
index 0000000..6549c90
--- /dev/null
@@ -0,0 +1,86 @@
+/* Copyright (C) 2002 Free Software Foundation.
+
+   Test for composite comparison always true/false optimization.
+
+   Written by Roger Sayle, 7th June 2002.  */
+
+extern void link_error0 ();
+extern void link_error1 ();
+
+void
+test1 (int x, int y)
+{
+  if ((x==y) && (x!=y))
+    link_error0();
+}
+
+void
+test2 (int x, int y)
+{
+  if ((x<y) && (x>y))
+    link_error0();
+}
+
+void
+test3 (int x, int y)
+{
+  if ((x<y) && (y<x))
+    link_error0();
+}
+
+void 
+test4 (int x, int y)
+{
+  if ((x==y) || (x!=y))
+    {
+    }
+  else
+    link_error1 ();
+}
+
+void
+test5 (int x, int y)
+{
+  if ((x>=y) || (x<y))
+    {
+    }
+  else
+    link_error1 ();
+}
+
+void
+test6 (int x, int y)
+{
+  if ((x<=y) || (y<x))
+    {
+    }
+  else
+    link_error1 ();
+}
+
+void
+all_tests (int x, int y)
+{
+  test1 (x, y);
+  test2 (x, y);
+  test3 (x, y);
+  test4 (x, y);
+  test5 (x, y);
+  test6 (x, y);
+}
+
+int
+main ()
+{
+  all_tests (0, 0);
+  all_tests (1, 2);
+  all_tests (4, 3);
+
+  return 0;
+}
+
+#ifndef __OPTIMIZE__
+void link_error0() {}
+void link_error1() {}
+#endif /* ! __OPTIMIZE__ */
+