This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]