Bug 35163 - [4.1/4.2 Regression] folding comparison loses cast
Summary: [4.1/4.2 Regression] folding comparison loses cast
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: 4.1.3
Assignee: Richard Biener
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2008-02-11 09:29 UTC by Tom de Vries
Modified: 2008-03-25 10:18 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 2.95.4 4.1.3 4.2.4 4.3.0
Known to fail: 3.3.6 4.1.2 4.2.3
Last reconfirmed: 2008-02-12 17:07:57


Attachments
patch to fix testsuite breakage on 16 bit integer targets (269 bytes, patch)
2008-02-17 03:58 UTC, Paulo Marques
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tom de Vries 2008-02-11 09:29:42 UTC
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
Comment 1 Steven Bosscher 2008-02-11 10:44:42 UTC
CCing fold guru.
Comment 2 Richard Biener 2008-02-12 17:07:57 UTC
I'll have a look.
Comment 3 Richard Biener 2008-02-12 19:59:39 UTC
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.
Comment 4 Richard Biener 2008-02-12 21:27:33 UTC
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

Comment 5 Richard Biener 2008-02-12 21:30:08 UTC
Fixed on the trunk.
Comment 6 Paulo Marques 2008-02-17 03:58:46 UTC
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.
Comment 7 Richard Biener 2008-03-25 10:14:59 UTC
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

Comment 8 Richard Biener 2008-03-25 10:18:10 UTC
Fixed.
Comment 9 Richard Biener 2008-03-25 10:18:38 UTC
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