OSDN Git Service

* lib/prune.exp (prune_gcc_output): Also handle "In member
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 37a0219..edf934d 100644 (file)
@@ -324,8 +324,8 @@ mul_double (l1, h1, l2, h2, lv, hv)
   HOST_WIDE_INT arg1[4];
   HOST_WIDE_INT arg2[4];
   HOST_WIDE_INT prod[4 * 2];
-  register unsigned HOST_WIDE_INT carry;
-  register int i, j, k;
+  unsigned HOST_WIDE_INT carry;
+  int i, j, k;
   unsigned HOST_WIDE_INT toplow, neglow;
   HOST_WIDE_INT tophigh, neghigh;
 
@@ -383,6 +383,8 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
      HOST_WIDE_INT *hv;
      int arith;
 {
+  unsigned HOST_WIDE_INT signmask;
+
   if (count < 0)
     {
       rshift_double (l1, h1, -count, prec, lv, hv, arith);
@@ -412,6 +414,26 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
             | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
       *lv = l1 << count;
     }
+
+  /* Sign extend all bits that are beyond the precision.  */
+
+  signmask = -((prec > HOST_BITS_PER_WIDE_INT
+               ? (*hv >> (prec - HOST_BITS_PER_WIDE_INT - 1))
+               : (*lv >> (prec - 1))) & 1);
+
+  if (prec >= 2 * HOST_BITS_PER_WIDE_INT)
+    ;
+  else if (prec >= HOST_BITS_PER_WIDE_INT)
+    {
+      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
+      *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT);
+    }
+  else
+    {
+      *hv = signmask;
+      *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
+      *lv |= signmask << prec;
+    }
 }
 
 /* Shift the doubleword integer in L1, H1 right by COUNT places
@@ -423,7 +445,7 @@ void
 rshift_double (l1, h1, count, prec, lv, hv, arith)
      unsigned HOST_WIDE_INT l1;
      HOST_WIDE_INT h1, count;
-     unsigned int prec ATTRIBUTE_UNUSED;
+     unsigned int prec;
      unsigned HOST_WIDE_INT *lv;
      HOST_WIDE_INT *hv;
      int arith;
@@ -443,21 +465,40 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
     {
       /* Shifting by the host word size is undefined according to the
         ANSI standard, so we must handle this as a special case.  */
-      *hv = signmask;
-      *lv = signmask;
+      *hv = 0;
+      *lv = 0;
     }
   else if (count >= HOST_BITS_PER_WIDE_INT)
     {
-      *hv = signmask;
-      *lv = ((signmask << (2 * HOST_BITS_PER_WIDE_INT - count - 1) << 1)
-            | ((unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT)));
+      *hv = 0;
+      *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
     }
   else
     {
+      *hv = (unsigned HOST_WIDE_INT) h1 >> count;
       *lv = ((l1 >> count)
             | ((unsigned HOST_WIDE_INT) h1 << (HOST_BITS_PER_WIDE_INT - count - 1) << 1));
-      *hv = ((signmask << (HOST_BITS_PER_WIDE_INT - count))
-            | ((unsigned HOST_WIDE_INT) h1 >> count));
+    }
+
+  /* Zero / sign extend all bits that are beyond the precision.  */
+
+  if (count >= (HOST_WIDE_INT)prec)
+    {
+      *hv = signmask;
+      *lv = signmask;
+    }
+  else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT)
+    ;
+  else if ((prec - count) >= HOST_BITS_PER_WIDE_INT)
+    {
+      *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT));
+      *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT);
+    }
+  else
+    {
+      *hv = signmask;
+      *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count));
+      *lv |= signmask << (prec - count);
     }
 }
 \f
@@ -537,7 +578,7 @@ div_and_round_double (code, uns,
   int quo_neg = 0;
   HOST_WIDE_INT num[4 + 1];    /* extra element for scaling.  */
   HOST_WIDE_INT den[4], quo[4];
-  register int i, j;
+  int i, j;
   unsigned HOST_WIDE_INT work;
   unsigned HOST_WIDE_INT carry = 0;
   unsigned HOST_WIDE_INT lnum = lnum_orig;
@@ -660,7 +701,7 @@ div_and_round_double (code, uns,
          else
            quo_est = BASE - 1;
 
-         /* Refine quo_est so it's usually correct, and at most one high.   */
+         /* Refine quo_est so it's usually correct, and at most one high.  */
          tmp = work - quo_est * den[den_hi_sig];
          if (tmp < BASE
              && (den[den_hi_sig - 1] * quo_est
@@ -1127,8 +1168,7 @@ real_hex_to_f (s, mode)
   shcount = 0;
   while ((c = *p) != '\0')
     {
-      if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
-         || (c >= 'a' && c <= 'f'))
+      if (ISXDIGIT (c))
        {
          k = c & CHARMASK;
          if (k >= 'a' && k <= 'f')
@@ -1486,7 +1526,7 @@ associate_trees (t1, t2, code, type)
 static tree
 int_const_binop (code, arg1, arg2, notrunc)
      enum tree_code code;
-     register tree arg1, arg2;
+     tree arg1, arg2;
      int notrunc;
 {
   unsigned HOST_WIDE_INT int1l, int2l;
@@ -1495,7 +1535,7 @@ int_const_binop (code, arg1, arg2, notrunc)
   HOST_WIDE_INT hi;
   unsigned HOST_WIDE_INT garbagel;
   HOST_WIDE_INT garbageh;
-  register tree t;
+  tree t;
   tree type = TREE_TYPE (arg1);
   int uns = TREE_UNSIGNED (type);
   int is_sizetype
@@ -1744,7 +1784,7 @@ const_binop_1 (data)
 static tree
 const_binop (code, arg1, arg2, notrunc)
      enum tree_code code;
-     register tree arg1, arg2;
+     tree arg1, arg2;
      int notrunc;
 {
   STRIP_NOPS (arg1);
@@ -1800,12 +1840,12 @@ const_binop (code, arg1, arg2, notrunc)
 #endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
   if (TREE_CODE (arg1) == COMPLEX_CST)
     {
-      register tree type = TREE_TYPE (arg1);
-      register tree r1 = TREE_REALPART (arg1);
-      register tree i1 = TREE_IMAGPART (arg1);
-      register tree r2 = TREE_REALPART (arg2);
-      register tree i2 = TREE_IMAGPART (arg2);
-      register tree t;
+      tree type = TREE_TYPE (arg1);
+      tree r1 = TREE_REALPART (arg1);
+      tree i1 = TREE_IMAGPART (arg1);
+      tree r2 = TREE_REALPART (arg2);
+      tree i2 = TREE_IMAGPART (arg2);
+      tree t;
 
       switch (code)
        {
@@ -1839,7 +1879,7 @@ const_binop (code, arg1, arg2, notrunc)
 
        case RDIV_EXPR:
          {
-           register tree magsquared
+           tree magsquared
              = const_binop (PLUS_EXPR,
                             const_binop (MULT_EXPR, r2, r2, notrunc),
                             const_binop (MULT_EXPR, i2, i2, notrunc),
@@ -2047,7 +2087,7 @@ struct fc_args
 {
   tree arg1;                   /* Input: value to convert.  */
   tree type;                   /* Input: type to convert value to.  */
-  tree t;                      /* Ouput: result of conversion.  */
+  tree t;                      /* Output: result of conversion.  */
 };
 
 /* Function to convert floating-point constants, protected by floating
@@ -2069,10 +2109,10 @@ fold_convert_1 (data)
 
 static tree
 fold_convert (t, arg1)
-     register tree t;
-     register tree arg1;
+     tree t;
+     tree arg1;
 {
-  register tree type = TREE_TYPE (t);
+  tree type = TREE_TYPE (t);
   int overflow = 0;
 
   if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type))
@@ -2985,7 +3025,6 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
   enum machine_mode lmode, rmode, nmode;
   int lunsignedp, runsignedp;
   int lvolatilep = 0, rvolatilep = 0;
-  unsigned int alignment;
   tree linner, rinner = NULL_TREE;
   tree mask;
   tree offset;
@@ -2996,7 +3035,7 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
      do anything if the inner expression is a PLACEHOLDER_EXPR since we
      then will no longer be able to replace it.  */
   linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
-                               &lunsignedp, &lvolatilep, &alignment);
+                               &lunsignedp, &lvolatilep);
   if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
       || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR)
     return 0;
@@ -3004,9 +3043,9 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
  if (!const_p)
    {
      /* If this is not a constant, we can only do something if bit positions,
-       sizes, and signedness are the same.   */
+       sizes, and signedness are the same.  */
      rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
-                                  &runsignedp, &rvolatilep, &alignment);
+                                  &runsignedp, &rvolatilep);
 
      if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
         || lunsignedp != runsignedp || offset != 0
@@ -3164,7 +3203,6 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
   tree mask, inner, offset;
   tree unsigned_type;
   unsigned int precision;
-  unsigned int alignment;
 
   /* All the optimizations using this function assume integer fields.
      There are problems with FP fields since the type_for_size call
@@ -3184,7 +3222,7 @@ decode_field_reference (exp, pbitsize, pbitpos, pmode, punsignedp,
     }
 
   inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
-                              punsignedp, pvolatilep, &alignment);
+                              punsignedp, pvolatilep);
   if ((inner == exp && and_mask == 0)
       || *pbitsize < 0 || offset != 0
       || TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -4663,7 +4701,7 @@ extract_muldiv (t, c, code, wide_type)
         multiple of the other, in which case we replace this with either an
         operation or CODE or TCODE.
 
-        If we have an unsigned type that is not a sizetype, we canot do
+        If we have an unsigned type that is not a sizetype, we cannot do
         this since it will change the result if the original computation
         overflowed.  */
       if ((! TREE_UNSIGNED (ctype)
@@ -4796,7 +4834,7 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
      side of the expression to be executed if the condition is true
      will be pointed to by TRUE_LHS.  Similarly, the right-hand side
      of the expression to be executed if the condition is true will be
-     pointed to by TRUE_RHS.  FALSE_LHS and FALSE_RHS are analagous --
+     pointed to by TRUE_RHS.  FALSE_LHS and FALSE_RHS are analogous --
      but apply to the expression to be executed if the conditional is
      false.  */
   tree *true_lhs;
@@ -4913,13 +4951,13 @@ tree
 fold (expr)
      tree expr;
 {
-  register tree t = expr;
+  tree t = expr;
   tree t1 = NULL_TREE;
   tree tem;
   tree type = TREE_TYPE (expr);
-  register tree arg0 = NULL_TREE, arg1 = NULL_TREE;
-  register enum tree_code code = TREE_CODE (t);
-  register int kind = TREE_CODE_CLASS (code);
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  enum tree_code code = TREE_CODE (t);
+  int kind = TREE_CODE_CLASS (code);
   int invert;
   /* WINS will be nonzero when the switch is done
      if all operands are constant.  */
@@ -4966,8 +5004,8 @@ fold (expr)
     }
   else if (IS_EXPR_CODE_CLASS (kind) || kind == 'r')
     {
-      register int len = first_rtl_op (code);
-      register int i;
+      int len = first_rtl_op (code);
+      int i;
       for (i = 0; i < len; i++)
        {
          tree op = TREE_OPERAND (t, i);
@@ -5270,6 +5308,12 @@ fold (expr)
        }
       return fold_convert (t, arg0);
 
+    case VIEW_CONVERT_EXPR:
+      if (TREE_CODE (TREE_OPERAND (t, 0)) == VIEW_CONVERT_EXPR)
+       return build1 (VIEW_CONVERT_EXPR, type,
+                      TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+      return t;
+
 #if 0  /* This loses on &"foo"[0].  */
     case ARRAY_REF:
        {
@@ -5544,7 +5588,7 @@ fold (expr)
       /* (A << B) + (A >> (Z - B)) if A is unsigned and Z is the size of A
         is a rotate of A by B bits.  */
       {
-       register enum tree_code code0, code1;
+       enum tree_code code0, code1;
        code0 = TREE_CODE (arg0);
        code1 = TREE_CODE (arg1);
        if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
@@ -5553,8 +5597,8 @@ fold (expr)
                                TREE_OPERAND (arg1, 0), 0)
            && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
          {
-           register tree tree01, tree11;
-           register enum tree_code code01, code11;
+           tree tree01, tree11;
+           enum tree_code code01, code11;
 
            tree01 = TREE_OPERAND (arg0, 1);
            tree11 = TREE_OPERAND (arg1, 1);
@@ -6859,6 +6903,33 @@ fold (expr)
                              fold (build (code, type, imag0, imag1))));
        }
 
+      /* Optimize comparisons of strlen vs zero to a compare of the
+        first character of the string vs zero.  To wit, 
+               strlen(ptr) == 0   =>  *ptr == 0
+               strlen(ptr) != 0   =>  *ptr != 0
+        Other cases should reduce to one of these two (or a constant)
+        due to the return value of strlen being unsigned.  */
+      if ((code == EQ_EXPR || code == NE_EXPR)
+         && integer_zerop (arg1)
+         && TREE_CODE (arg0) == CALL_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == ADDR_EXPR)
+       {
+         tree fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+         tree arglist;
+
+         if (TREE_CODE (fndecl) == FUNCTION_DECL
+             && DECL_BUILT_IN (fndecl)
+             && DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_MD
+             && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRLEN
+             && (arglist = TREE_OPERAND (arg0, 1))
+             && TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) == POINTER_TYPE
+             && ! TREE_CHAIN (arglist))
+           return fold (build (code, type,
+                               build1 (INDIRECT_REF, char_type_node,
+                                       TREE_VALUE(arglist)),
+                               integer_zero_node));
+       }
+
       /* From here on, the only cases we handle are when the result is
         known to be a constant.