]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
convert.c (convert_to_integer): Don't pass the truncation down when the target type...
authorEric Botcazou <ebotcazou@multimania.com>
Sat, 15 Jun 2002 00:42:25 +0000 (00:42 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 15 Jun 2002 00:42:25 +0000 (17:42 -0700)
* convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
the truncation down when the target type is signed.
[trunc1]: Use unsigned arithmetic for LSHIFT_EXPR.
* fold-const.c (extract_muldiv) [NOP_EXPR]: Don't pass through
the conversion if the target type is a smaller type.

From-SVN: r54628

gcc/ChangeLog
gcc/convert.c
gcc/fold-const.c

index e7b330760ea69ebed12028d5e81bbfc113abc8d5..4ea5b89f7cb318a9098d611df49440e7838a8061 100644 (file)
@@ -1,3 +1,12 @@
+2002-06-14  Eric Botcazou  <ebotcazou@multimania.com>
+
+       PR c/6677
+       * convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
+       the truncation down when the target type is signed.
+       [trunc1]: Use unsigned arithmetic for LSHIFT_EXPR.
+       * fold-const.c (extract_muldiv) [NOP_EXPR]: Don't pass through
+       the conversion if the target type is a smaller type.
+
 Thu Jun 13 18:27:05 CEST 2002  Jan Hubicka  <jh@suse.cz>
        
        * i386.c (ix86_expand_movstr):  Fix pasto.
index 127b22b7eef5747356e67cc0ab9bb7c6fa1c3994..156c2cf40aee7661a3f7dd2129ee22859d1cb3e8 100644 (file)
@@ -227,9 +227,11 @@ convert_to_integer (type, expr)
 
        case LSHIFT_EXPR:
          /* We can pass truncation down through left shifting
-            when the shift count is a nonnegative constant.  */
+            when the shift count is a nonnegative constant and
+            the target type is unsigned.  */
          if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
              && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) >= 0
+             && TREE_UNSIGNED (type)
              && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
            {
              /* If shift count is less than the width of the truncated type,
@@ -311,12 +313,15 @@ convert_to_integer (type, expr)
                    /* Don't do unsigned arithmetic where signed was wanted,
                       or vice versa.
                       Exception: if both of the original operands were
-                      unsigned then can safely do the work as unsigned.
+                      unsigned then we can safely do the work as unsigned;
+                      if we are distributing through a LSHIFT_EXPR, we must
+                      do the work as unsigned to avoid a signed overflow.
                       And we may need to do it as unsigned
                       if we truncate to the original size.  */
                    typex = ((TREE_UNSIGNED (TREE_TYPE (expr))
                              || (TREE_UNSIGNED (TREE_TYPE (arg0))
-                                 && TREE_UNSIGNED (TREE_TYPE (arg1))))
+                                 && TREE_UNSIGNED (TREE_TYPE (arg1)))
+                             || ex_form == LSHIFT_EXPR)
                             ? unsigned_type (typex) : signed_type (typex));
                    return convert (type,
                                    fold (build (ex_form, typex,
index 98e81aa752680281889884fba3e18417cfd15ccb..a7e1e284086996e8aa814805c1daf3eaf8074869 100644 (file)
@@ -4515,17 +4515,22 @@ extract_muldiv (t, c, code, wide_type)
       break;
 
     case CONVERT_EXPR:  case NON_LVALUE_EXPR:  case NOP_EXPR:
-      /* If op0 is an expression, and is unsigned, and the type is
-        smaller than ctype, then we cannot widen the expression.  */
+      /* If op0 is an expression... */
       if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
           || TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
           || TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
           || TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
-         && TREE_UNSIGNED (TREE_TYPE (op0))
-         && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
-               && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
-         && (GET_MODE_SIZE (TYPE_MODE (ctype))
-              > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+         /* ...and is unsigned, and its type is smaller than ctype,
+            then we cannot pass through this widening.  */
+         && ((TREE_UNSIGNED (TREE_TYPE (op0))
+              && ! (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE
+                    && TYPE_IS_SIZETYPE (TREE_TYPE (op0)))
+              && (GET_MODE_SIZE (TYPE_MODE (ctype))
+                  > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))))
+             /* ...and its type is larger than ctype,
+                then we cannot pass through this truncation.  */
+             || (GET_MODE_SIZE (TYPE_MODE (ctype))
+                 < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))))))
        break;
 
       /* Pass the constant down and see if we can make a simplification.  If