This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR35163, wrong folding of comparisons
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 12 Feb 2008 22:22:18 +0100 (CET)
- Subject: [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;
+ }
+