+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.
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,
/* 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,
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