re PR c++/15069 (a bit test on a variable of enum type is miscompiled)
authorRoger Sayle <roger@eyesopen.com>
Mon, 31 May 2004 17:01:17 +0000 (17:01 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 31 May 2004 17:01:17 +0000 (17:01 +0000)
PR middle-end/15069
* fold-const.c (fold_single_bit_test): Only perform "(X & C) != 0"
into "X < 0" (where C is the signbit) if X's type is a full mode.

* g++.dg/opt/fold3.C: New test case.

From-SVN: r82490

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/fold3.C [new file with mode: 0644]

index c639b56d06695235820266a3e250afc7a52ec0ef..cea33d1852c65bfd7d3c34eb3b8f70be3f63896d 100644 (file)
@@ -1,3 +1,9 @@
+2004-05-31  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/15069
+       * fold-const.c (fold_single_bit_test): Only perform "(X & C) != 0"
+       into "X < 0" (where C is the signbit) if X's type is a full mode.
+
 2004-05-31  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * pa.md: Disable the peephole2 patterns that generate indexed
index d2e333e0d42e14821dd04363182bcde2ffadade6..b0d1db29237d4fcd2422ecb6f03963cf77332afb 100644 (file)
@@ -5413,7 +5413,11 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       /* 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.  */
       arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
-      if (arg00 != NULL_TREE)
+      if (arg00 != NULL_TREE
+         /* This is only a win if casting to a signed type is cheap,
+            i.e. when arg00's type is not a partial mode.  */
+         && TYPE_PRECISION (TREE_TYPE (arg00))
+            == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg00))))
        {
          tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
          return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
@@ -5421,10 +5425,6 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                               fold_convert (stype, integer_zero_node)));
        }
 
-      /* At this point, we know that arg0 is not testing the sign bit.  */
-      if (TYPE_PRECISION (type) - 1 == bitnum)
-       abort ();
-      
       /* Otherwise we have (A & C) != 0 where C is a single bit, 
         convert that into ((A >> C2) & 1).  Where C2 = log2(C).
         Similarly for (A & C) == 0.  */
index 6d5e0a563eb13d4843f5235e42bb7f1f472850b3..47ed126ef8b7b608fc3ad4f30204840ae0c50faf 100644 (file)
@@ -1,3 +1,8 @@
+2004-05-31  Roger Sayle  <roger@eyesopen.com>
+
+       PR middle-end/15069
+       * g++.dg/opt/fold3.C: New test case.
+
 2004-05-30  Graham Stott  <graham.stott@btinternet.com>
 
        * lib/target-supports.exp (check_iconv_available): Fix fallout
diff --git a/gcc/testsuite/g++.dg/opt/fold3.C b/gcc/testsuite/g++.dg/opt/fold3.C
new file mode 100644 (file)
index 0000000..87a36b9
--- /dev/null
@@ -0,0 +1,21 @@
+// PR middle-end/15069
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort (void);
+
+typedef enum {
+  FOUR = 4,
+  FIVE = 5
+} direction_t;
+
+int main ()
+{
+  direction_t four = FOUR;
+  int flags = (four & 4L) ? (32L | 128L) : 0;
+  flags &= 32L;
+
+  if (flags == 0)
+    abort ();
+}
+