test.c: ... int main() { signed char a = -30; /* a == sE2 (-30 signed char) */ signed char b = -31; /* b == sE1 (-31 signed char) */ int r = a <= (unsigned short)b; /* (unsigned short)b == uFFE1 (65505 unsigned short) */ /* r == a <= (unsigned short)b == sE2 <= uFFE1 == arithmetic conversion, rule integral promotion sFFFFFFE2 <= s0000FFE1 == -30 <= 65505 == 1 */ /* gcc evaluates r to 0 instead */ return r; } ... The problem seems to occur during a call to fold-const.c:fold_widened_comparison(), which calls tree.c:get_unwidened(): ... /* Return OP, stripped of any conversions to wider types as much as is safe. Converting the value back to OP's type makes a value equivalent to OP. If FOR_TYPE is nonzero, we return a value which, if converted to type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE. If FOR_TYPE is nonzero, unaligned bit-field references may be changed to the narrowest type that can hold the value, even if they don't exactly fit. Otherwise, bit-field references are changed to a narrower type only if they can be fetched directly from memory in that type. OP must have integer, real or enumeral type. Pointers are not allowed! There are some cases where the obvious value we could return would regenerate to OP if converted to OP's type, but would not extend like OP to wider types. If FOR_TYPE indicates such extension is contemplated, we eschew such values. For example, if OP is (unsigned short)(signed char)-1, we avoid returning (signed char)-1 if FOR_TYPE is int, even though extending that to an unsigned short would regenerate OP, since the result of extending (signed char)-1 to (int) is different from (int) OP. */ tree get_unwidened (tree op, tree for_type) ... get_unwidened() is called with op == (int)(unsigned short)-31sc and for_type == signed char. get unwidened() returns -31sc. However, 'Converting the value back to OP's type makes a value equivalent to OP' would mean convert (int)-31sc == (int)(unsigned short)-31sc, which is not correct: (int)-31sc == (int)(unsigned short)-31sc <==> (int)-31sc == (int)65505us <==> -31si == 65505si <==> FALSE
CCing fold guru.
I'll have a look.
get_unwidened behaves as documented: If FOR_TYPE is nonzero, we return a value which, if converted to type FOR_TYPE, would be equivalent to converting OP to type FOR_TYPE. thus indeed, (signed char)(int)(unsigned short)-41sc == -41sc. But the bug instead is that fold specifies FOR_TYPE, where it rather should not specify it and convert the result to shorter_type if and only if this conversion is not a truncation.
Subject: Bug 35163 Author: rguenth Date: Tue Feb 12 21:26:49 2008 New Revision: 132269 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=132269 Log: 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. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr35163.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog
Fixed on the trunk.
Created attachment 15171 [details] patch to fix testsuite breakage on 16 bit integer targets Unfortunately, the testcase assumes 32 bit integers and fails on the avr target. The attached patch makes the expected type sizes explicit, so that it doesn't depend on the natural integer size of the target. The patch was tested for te avr target and it works as expected.
Subject: Bug 35163 Author: rguenth Date: Tue Mar 25 10:14:15 2008 New Revision: 133508 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133508 Log: 2008-03-25 Richard Guenther <rguenther@suse.de> Backport from mainline: 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. Added: branches/gcc-4_2-branch/gcc/testsuite/gcc.c-torture/execute/pr35163.c - copied unchanged from r132269, trunk/gcc/testsuite/gcc.c-torture/execute/pr35163.c Modified: branches/gcc-4_2-branch/gcc/ChangeLog branches/gcc-4_2-branch/gcc/fold-const.c branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
Fixed.
Subject: Bug 35163 Author: rguenth Date: Tue Mar 25 10:17:54 2008 New Revision: 133509 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=133509 Log: 2008-03-25 Richard Guenther <rguenther@suse.de> Backport from mainline: 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. Added: branches/gcc-4_1-branch/gcc/testsuite/gcc.c-torture/execute/pr35163.c - copied unchanged from r132269, trunk/gcc/testsuite/gcc.c-torture/execute/pr35163.c Modified: branches/gcc-4_1-branch/gcc/ChangeLog branches/gcc-4_1-branch/gcc/fold-const.c branches/gcc-4_1-branch/gcc/testsuite/ChangeLog