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 PR35163, wrong folding of comparisons


fold_widened_comparison uses get_unwidened to get at unwidened
operands of a comparison, but uses a mode of that function that
does not guarantee value-preserving, resulting in the bug where
we fold (int)(signed char)-30 <= (int)(unsigned short)(signed char)-31
to false.  The fix is easy - just do not use this non-value-preserving
mode.

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

Richard.

2008-02-12  Richard Guenther  <rguenther@suse.de>

	PR middle-end/35163
	* fold-const.c (fold_widened_comparison): Use get_unwidened in
	value-preserving mode.  Disallow final truncation.

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

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 132265)
--- fold-const.c	(working copy)
*************** fold_widened_comparison (enum tree_code 
*** 7045,7056 ****
    if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
      return NULL_TREE;
  
!   arg1_unw = get_unwidened (arg1, shorter_type);
  
    /* If possible, express the comparison in the shorter mode.  */
    if ((code == EQ_EXPR || code == NE_EXPR
         || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
        && (TREE_TYPE (arg1_unw) == shorter_type
  	  || (TREE_CODE (arg1_unw) == INTEGER_CST
  	      && (TREE_CODE (shorter_type) == INTEGER_TYPE
  		  || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
--- 7045,7058 ----
    if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
      return NULL_TREE;
  
!   arg1_unw = get_unwidened (arg1, NULL_TREE);
  
    /* If possible, express the comparison in the shorter mode.  */
    if ((code == EQ_EXPR || code == NE_EXPR
         || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
        && (TREE_TYPE (arg1_unw) == shorter_type
+ 	  || (TYPE_PRECISION (shorter_type)
+ 	      >= TYPE_PRECISION (TREE_TYPE (arg1_unw)))
  	  || (TREE_CODE (arg1_unw) == INTEGER_CST
  	      && (TREE_CODE (shorter_type) == INTEGER_TYPE
  		  || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
Index: testsuite/gcc.c-torture/execute/pr35163.c
===================================================================
*** testsuite/gcc.c-torture/execute/pr35163.c	(revision 0)
--- testsuite/gcc.c-torture/execute/pr35163.c	(revision 0)
***************
*** 0 ****
--- 1,11 ----
+ extern void abort(void);
+ 
+ int main()
+ {
+   signed char a = -30;
+   signed char b = -31;
+   if (a > (unsigned short)b)
+     abort ();
+   return 0;
+ }
+ 


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