This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR25186, folding of (short)((int)x << cst)
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 1 Dec 2005 16:37:01 +0100 (CET)
- Subject: [PATCH] Fix PR25186, folding of (short)((int)x << cst)
This patch(es) teach the folding logic in convert.c to handle the
case of signed operands, which should be fine according to discussion
on IRC. Still I attached a 2nd version of the patch that does it
only for flag_wrapv, where it is definitely valid (wrt undefinedness
vs. implementation-definedness).
gcc.target/i386/rotate-1.c needs adjusting because we now generate
rorb %al
movzbl %al, %eax
instead of
rolb $7, %al
andl $255, %eax
which is even better.
Boostrapped and tested on x86_64-unknonw-linux-gnu.
Ok for mainline?
Thanks,
Richard.
:ADDPATCH middle-end:
2005-12-01 Richard Guenther <rguenther@gcc.gnu.org>
PR middle-end/25186
* convert.c (convert_to_integer): For LSHIFT_EXPR also
handle unsigned target types. No exception for LSHIFT_EXPR
on truncation.
* gcc.target/i386/rotate-1.c: Scan for rorb instead of rolb.
Index: convert.c
===================================================================
*** convert.c (revision 107813)
--- convert.c (working copy)
*************** convert_to_integer (tree type, tree expr
*** 508,518 ****
case LSHIFT_EXPR:
/* We can pass truncation down through left shifting
! 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
- && TYPE_UNSIGNED (type)
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
/* If shift count is less than the width of the truncated type,
--- 486,494 ----
case LSHIFT_EXPR:
/* We can pass truncation down through left shifting
! when the shift count is a nonnegative constant. */
if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (expr, 1)) >= 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
/* If shift count is less than the width of the truncated type,
*************** convert_to_integer (tree type, tree expr
*** 596,604 ****
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 (TYPE_UNSIGNED (TREE_TYPE (expr))
--- 572,577 ----
*************** convert_to_integer (tree type, tree expr
*** 607,614 ****
|| 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);
--- 580,586 ----
|| ex_form == LSHIFT_EXPR
|| ex_form == RSHIFT_EXPR
|| ex_form == LROTATE_EXPR
! || ex_form == RROTATE_EXPR)))
typex = lang_hooks.types.unsigned_type (typex);
else
typex = lang_hooks.types.signed_type (typex);
Index: testsuite/gcc.target/i386/rotate-1.c
===================================================================
*** testsuite/gcc.target/i386/rotate-1.c (revision 107813)
--- testsuite/gcc.target/i386/rotate-1.c (working copy)
*************** main (void)
*** 13,16 ****
return c;
}
! /* { dg-final { scan-assembler "rolb" { target i?86-*-* x86_64-*-* } } } */
--- 13,16 ----
return c;
}
! /* { dg-final { scan-assembler "rorb" { target i?86-*-* x86_64-*-* } } } */
2nd version:
2005-12-01 Richard Guenther <rguenther@suse.de>
PR middle-end/25186
* convert.c (convert_to_integer): For wrapping integer
arithmetic, convert (T)((T2)T << cst) to T << cst.
Index: convert.c
===================================================================
*** convert.c (revision 107813)
--- convert.c (working copy)
*************** convert_to_integer (tree type, tree expr
*** 512,518 ****
the target type is unsigned. */
if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (expr, 1)) >= 0
! && TYPE_UNSIGNED (type)
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
/* If shift count is less than the width of the truncated type,
--- 490,496 ----
the target type is unsigned. */
if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (expr, 1)) >= 0
! && (TYPE_UNSIGNED (type) || flag_wrapv)
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
/* If shift count is less than the width of the truncated type,
*************** convert_to_integer (tree type, tree expr
*** 608,614 ****
|| 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);
--- 586,592 ----
|| ex_form == RSHIFT_EXPR
|| ex_form == LROTATE_EXPR
|| ex_form == RROTATE_EXPR))
! || (ex_form == LSHIFT_EXPR && !flag_wrapv))
typex = lang_hooks.types.unsigned_type (typex);
else
typex = lang_hooks.types.signed_type (typex);