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 PR44828


Yet another broken frontend optimization.  When narrowing a MULT_EXPR
we have to care for overflow as well.  The fancy double-precision
check is needed to make the vectorizer pattern matching happy.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2010-07-06  Richard Guenther  <rguenther@suse.de>

	PR middle-end/44828
	* convert.c (convert_to_integer): Watch out for overflowing
	MULT_EXPR as well.

	* gcc.c-torture/execute/pr44828.c: New testcase.

Index: gcc/testsuite/gcc.c-torture/execute/pr44828.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr44828.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr44828.c	(revision 0)
***************
*** 0 ****
--- 1,19 ----
+ extern void abort (void);
+ 
+ static char
+ foo (char si1, char si2)
+ {
+   return si1 * si2;
+ }
+ 
+ int a = 0x105F61CA;
+ 
+ int
+ main (void)
+ {
+   int b = 0x0332F5C8;
+   if (foo (b, a) > 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc/convert.c
===================================================================
*** gcc/convert.c	(revision 161865)
--- gcc/convert.c	(working copy)
*************** convert_to_integer (tree type, tree expr
*** 768,780 ****
  			|| ex_form == LSHIFT_EXPR
  			/* If we have !flag_wrapv, and either ARG0 or
  			   ARG1 is of a signed type, we have to do
! 			   PLUS_EXPR or MINUS_EXPR in an unsigned
! 			   type.  Otherwise, we would introduce
  			   signed-overflow undefinedness.  */
  			|| ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
  			     || !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
  			    && (ex_form == PLUS_EXPR
! 				|| ex_form == MINUS_EXPR)))
  		      typex = unsigned_type_for (typex);
  		    else
  		      typex = signed_type_for (typex);
--- 768,786 ----
  			|| ex_form == LSHIFT_EXPR
  			/* If we have !flag_wrapv, and either ARG0 or
  			   ARG1 is of a signed type, we have to do
! 			   PLUS_EXPR, MINUS_EXPR or MULT_EXPR in an unsigned
! 			   type in case the operation in outprec precision
! 			   could overflow.  Otherwise, we would introduce
  			   signed-overflow undefinedness.  */
  			|| ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
  			     || !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
+ 			    && ((TYPE_PRECISION (TREE_TYPE (arg0)) * 2u
+ 				 > outprec)
+ 				|| (TYPE_PRECISION (TREE_TYPE (arg1)) * 2u
+ 				    > outprec))
  			    && (ex_form == PLUS_EXPR
! 				|| ex_form == MINUS_EXPR
! 				|| ex_form == MULT_EXPR)))
  		      typex = unsigned_type_for (typex);
  		    else
  		      typex = signed_type_for (typex);


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