Bug 31605 - [4.2/4.3 Regression] VRP eliminates a useful test due with conversion from unsigned int to int
Summary: [4.2/4.3 Regression] VRP eliminates a useful test due with conversion from un...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.3.0
: P3 blocker
Target Milestone: 4.2.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2007-04-17 14:49 UTC by Daniel Jacobowitz
Modified: 2007-04-24 23:28 UTC (History)
6 users (show)

See Also:
Host:
Target: mips-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-04-17 15:28:24


Attachments
Proposed patch (495 bytes, patch)
2007-04-21 02:08 UTC, Ian Lance Taylor
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Jacobowitz 2007-04-17 14:49:01 UTC
Most floating point tests fail when GDB is built with GCC trunk for mips-linux.  I assume it shows up on all targets.  The miscompiled function is doublest.c:put_field.  Here is a reduced test case:

int put_field (unsigned int start, unsigned int len)
{
  int cur_bitshift = ((start + len) % 8) - 8;

  if (cur_bitshift > -8)
    not_removed ();
}

When compiled with -O2, the resulting assembly file does not include a call to not_removed.  But in fact it should be called in seven out of eight cases.  ((start + len) % 8) is an unsigned int in [0, 7].  "((start + len) % 8) - 8" is an unsigned int in [UINT_MAX - 8, UINT_MAX].  cur_bitshift is an int, which can not represent UINT_MAX; this is an implementation defined conversion, and the GCC manual says that the value is reduced modulo (UINT_MAX+1) until it fits in the range of int.  So the defined result of the conversion is in [-8, -1].

But VRP says:

Value ranges after VRP:

start_1(D): VARYING
len_2(D): VARYING
D.1559_3: [0, +INF]  EQUIVALENCES: { } (0 elements)
D.1560_4: [0, 7]  EQUIVALENCES: { } (0 elements)
D.1561_5: [4294967288, +INF]  EQUIVALENCES: { } (0 elements)
cur_bitshift_6: [-INF(OVF), -2147483648]  EQUIVALENCES: { } (0 elements)


Folding predicate cur_bitshift_6 >= -7 to 0
Removing basic block 3
Merging blocks 2 and 4
put_field (start, len)
{
  int cur_bitshift;
  unsigned int D.1561;
  unsigned int D.1560;
  unsigned int D.1559;

<bb 2>:
  D.1559_3 = start_1(D) + len_2(D);
  D.1560_4 = D.1559_3 & 7;
  D.1561_5 = D.1560_4 + 4294967288;
  cur_bitshift_6 = (int) D.1561_5;
  return;

}
Comment 1 Andrew Pinski 2007-04-17 15:15:05 UTC
The range for cur_bitshift_6 is just completely bogus as there is no overflow with the conversion from unsigned int to int.  I am going to check when I get into work if 4.2 also miscompiles this code.
Comment 2 Andrew Pinski 2007-04-17 15:28:24 UTC
Here is a reduced testcase without the other ranges:
int put_field (unsigned int start)
{
  int cur_bitshift;
  if (start <= 4294967288U)
    return start;
  cur_bitshift = start;

  if (cur_bitshift > -8)
    not_removed ();
  return 0;
}

Comment 3 Andrew Pinski 2007-04-17 20:20:30 UTC
This works with "4.2.0 20070309" but that was before the overflow patch to the 4.2 branch.
Comment 4 Andrew Pinski 2007-04-17 20:27:45 UTC
And it is a bug on the 4.2 branch.
Before Ian's patch we got the following ranges for the testcase in comment #2:

D.1528_1: VARYING
start_2: VARYING
D.1528_3: VARYING
cur_bitshift_4: ~[0, 0]  EQUIVALENCES: { } (0 elements)
start_5: [0, 0fffffff8]  EQUIVALENCES: { start_2 } (1 elements)
<retval>_6: VARYING
start_9: [0fffffff9, +INF]  EQUIVALENCES: { start_2 } (1 elements)

After we get:
D.1528_1: VARYING
start_2: VARYING
D.1528_3: VARYING
cur_bitshift_4: [-INF(OVF), -2147483648]  EQUIVALENCES: { } (0 elements)
start_5: [0, 0fffffff8]  EQUIVALENCES: { start_2 } (1 elements)
<retval>_6: VARYING
start_9: [0fffffff9, +INF]  EQUIVALENCES: { start_2 } (1 elements)



Before:
Visiting statement:
cur_bitshift_4 = (int) start_9;

Found new range for cur_bitshift_4: ~[0, 0]

After:
Visiting statement:
cur_bitshift_4 = (int) start_9;

Found new range for cur_bitshift_4: [-INF(OVF), -2147483648]



That is just incorrect.
Comment 5 Ian Lance Taylor 2007-04-21 02:08:14 UTC
Created attachment 13399 [details]
Proposed patch

Currently testing.
Comment 6 ian@gcc.gnu.org 2007-04-24 23:24:12 UTC
Subject: Bug 31605

Author: ian
Date: Tue Apr 24 23:24:01 2007
New Revision: 124128

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=124128
Log:
./:
	PR tree-optimization/31605
	* tree-vrp.c (set_value_range): Check that min and max are not
	both overflow infinities.
	(set_value_range_to_value): New static function.
	(extract_range_from_binary_expr): Call set_value_range_to_value.
	(extract_range_from_cond_expr): Likewise.
	(extract_range_from_expr): Likewise.
	(extract_range_from_unary_expr): Likewise.  Don't create a range
	which overflows on both sides.
	(vrp_meet): Check for a useless range.
	(vrp_visit_phi_node): If we see a constant which looks like an
	overflow infinity, turn off the TREE_OVERFLOW flag.
testsuite/:
	PR tree-optimizatoin/31605
	* gcc.c-torture/execute/pr31605.c: New test.

Added:
    trunk/gcc/testsuite/gcc.c-torture/execute/pr31605.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-vrp.c

Comment 7 ian@gcc.gnu.org 2007-04-24 23:26:36 UTC
Subject: Bug 31605

Author: ian
Date: Tue Apr 24 23:26:25 2007
New Revision: 124129

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=124129
Log:
./ChangeLog:
	PR tree-optimization/31605
	* tree-vrp.c (set_value_range): Check that min and max are not
	both overflow infinities.
	(set_value_range_to_value): New static function.
	(extract_range_from_binary_expr): Call set_value_range_to_value.
	(extract_range_from_expr): Likewise.
	(extract_range_from_unary_expr): Likewise.  Don't create a range
	which overflows on both sides.
	(vrp_meet): Check for a useless range.
	(vrp_visit_phi_node): If we see a constant which looks like an
	overflow infinity, turn off the TREE_OVERFLOW flag.
testsuite/ChangeLog:
	PR tree-optimization/31605
	* gcc.c-torture/execute/pr31605.c: New test.

Added:
    branches/gcc-4_2-branch/gcc/testsuite/gcc.c-torture/execute/pr31605.c
Modified:
    branches/gcc-4_2-branch/gcc/ChangeLog
    branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_2-branch/gcc/tree-vrp.c

Comment 8 Ian Lance Taylor 2007-04-24 23:28:36 UTC
Fixed on mainline and 4.2 branch.