]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 00:40:49 +0000 (00:40 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 15 Jun 2002 00:40:49 +0000 (00:40 +0000)
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.

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

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

index 197ac511706143aa73c3642c00f16ee3466c283a..30640c70bfe54600f96238d864c987c66b704a9e 100644 (file)
@@ -1,3 +1,11 @@
+2002-06-14  Eric Botcazou  <ebotcazou@multimania.com>
+
+       * 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.
+
 2002-06-14  Richard Henderson  <rth@redhat.com>
 
        * fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
index 970b05cd37476845e6f7ec5f62399a0ffff26e33..e90ce4c88d6f564c32e5c33336777df73b26954b 100644 (file)
@@ -229,9 +229,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,
@@ -313,12 +315,22 @@ 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.
+                      Exception: shift operations take their type solely
+                      from the first argument.
+                      Exception: the LSHIFT_EXPR case above requires that
+                      we perform this operation unsigned lest we produce
+                      signed-overflow undefinedness.
                       And we may need to do it as unsigned
                       if we truncate to the original size.  */
                    if (TREE_UNSIGNED (TREE_TYPE (expr))
                        || (TREE_UNSIGNED (TREE_TYPE (arg0))
-                           && TREE_UNSIGNED (TREE_TYPE (arg1))))
+                           && (TREE_UNSIGNED (TREE_TYPE (arg1))
+                               || ex_form == LSHIFT_EXPR
+                               || ex_form == RSHIFT_EXPR
+                               || ex_form == LROTATE_EXPR
+                               || ex_form == RROTATE_EXPR))
+                       || ex_form == LSHIFT_EXPR)
                      typex = (*lang_hooks.types.unsigned_type) (typex);
                    else
                      typex = (*lang_hooks.types.signed_type) (typex);
index 31bcddba89b56a3387cd69f306e44b6a2b577b69..5c04d78a90df071ace257601257fb151102b1403 100644 (file)
@@ -3969,17 +3969,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 as 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)))))
+             /* ... or 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