OSDN Git Service

PR c/11449
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jul 2003 12:40:10 +0000 (12:40 +0000)
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 10 Jul 2003 12:40:10 +0000 (12:40 +0000)
* fold-const.c (sign_bit_p): Return EXP if VAL is the sign bit
of HOST_WIDE_INT.
(fold_single_bit_test): If sign_bit_p() fails, assume that the
bit being tested is not a sign bit.

PR c/11449
* gcc.c-torture/compile/20030707-1.c: New.
* config/h8300/h8300.md (a peephole2): New.

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

gcc/fold-const.c
gcc/testsuite/gcc.c-torture/compile/20030707-1.c [new file with mode: 0644]

index 7ef2b22..95a68bc 100644 (file)
@@ -2730,8 +2730,8 @@ all_ones_mask_p (tree mask, int size)
 static tree
 sign_bit_p (tree exp, tree val)
 {
-  unsigned HOST_WIDE_INT lo;
-  HOST_WIDE_INT hi;
+  unsigned HOST_WIDE_INT mask_lo, lo;
+  HOST_WIDE_INT mask_hi, hi;
   int width;
   tree t;
 
@@ -2750,14 +2750,25 @@ sign_bit_p (tree exp, tree val)
     {
       hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT - 1);
       lo = 0;
+
+      mask_hi = ((unsigned HOST_WIDE_INT) -1
+                >> (2 * HOST_BITS_PER_WIDE_INT - width));
+      mask_lo = -1;
     }
   else
     {
       hi = 0;
       lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
+
+      mask_hi = 0;
+      mask_lo = ((unsigned HOST_WIDE_INT) -1
+                >> (HOST_BITS_PER_WIDE_INT - width));
     }
 
-  if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
+  /* We mask off those bits beyond TREE_TYPE (exp) so that we can
+     treat VAL as if it were unsigned.  */
+  if ((TREE_INT_CST_HIGH (val) & mask_hi) == hi
+      && (TREE_INT_CST_LOW (val) & mask_lo) == lo)
     return exp;
 
   /* Handle extension from a narrower type.  */
@@ -4840,6 +4851,10 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                              convert (stype, arg00),
                              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).
@@ -4861,13 +4876,11 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
       /* If we are going to be able to omit the AND below, we must do our
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
-      ops_unsigned = (bitnum == TYPE_PRECISION (type) - 1 ? 1
 #ifdef LOAD_EXTEND_OP
-                     : (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1)
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
 #else
-                     : 1
+      ops_unsigned = 1;
 #endif
-                     );
 
       signed_type = (*lang_hooks.types.type_for_mode) (operand_mode, 0);
       unsigned_type = (*lang_hooks.types.type_for_mode) (operand_mode, 1);
@@ -4881,9 +4894,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
                       inner, integer_one_node);
 
       /* Put the AND last so it can combine with more things.  */
-      if (bitnum != TYPE_PRECISION (type) - 1)
-       inner = build (BIT_AND_EXPR, ops_unsigned ? unsigned_type : signed_type,
-                      inner, integer_one_node);
+      inner = build (BIT_AND_EXPR, ops_unsigned ? unsigned_type : signed_type,
+                    inner, integer_one_node);
 
       /* Make sure to return the proper type.  */
       if (TREE_TYPE (inner) != result_type)
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030707-1.c b/gcc/testsuite/gcc.c-torture/compile/20030707-1.c
new file mode 100644 (file)
index 0000000..8ce9645
--- /dev/null
@@ -0,0 +1,13 @@
+/* PR c/11449.  */
+
+/* sign_bit_p() in fold-const.c failed to notice that (int) 0x80000000
+   was the sign bit of m.  As a result, fold_single_bit_test()
+   returned ((unsigned int) m >> 31), and that was eventually passed
+   to invert_truthvalue(), which did not know how to handle
+   RROTATE_EXPR, causing an ICE.  */
+
+int
+foo (int m)
+{
+  return !(m & ((int) 0x80000000));
+}