Bug 45967 - [4.5 Regression] gcc-4.5.x optimizes code with side-effects away
Summary: [4.5 Regression] gcc-4.5.x optimizes code with side-effects away
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.5.0
: P2 normal
Target Milestone: 4.5.3
Assignee: Richard Biener
URL:
Keywords: alias, wrong-code
Depends on:
Blocks:
 
Reported: 2010-10-11 13:10 UTC by Nicolai Stange
Modified: 2011-03-08 13:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.6.0
Known to fail: 4.4.3, 4.5.2
Last reconfirmed: 2010-10-11 15:03:59


Attachments
testcase containing failer and workaround (692 bytes, text/x-csrc)
2010-10-11 13:10 UTC, Nicolai Stange
Details
patch for the 4.5 branch (6.03 KB, text/plain)
2011-03-02 15:54 UTC, Richard Biener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolai Stange 2010-10-11 13:10:03 UTC
Created attachment 22016 [details]
testcase containing failer and workaround

Hi everybody,

while debugging a numpy testuite failer addressing refcounts, I came across a strange optimization issue. Since I have no clue where the problem is located, I decided to choose "rtl-optimization" as "Component". Please correct me if I'm wrong. I'm not even sure if this really is a bug (although I'm believing it), but the people in #gcc told me to post it here.

I've broken down the problem to a simple testcase (see attached testcase.c). Compile with 
gcc -c -Wall -O1 testcase.c
and have a look at the produced assembler output with 
objdump -S testcase.o

There are two functions in my testcase:
one that will be empty (PyArray_Item_XDECREF) and one that uses a workaround that works even with -O3 (PyArray_Item_XDECREF_workaround).

The workaround seems to introduce some data dependency, though I don't know exactly what it does, I've found it by trial and error.

To help you locating the issue:
It only appears with -O1. Everything works fine with the options documented in 'man gcc', that is 
-fauto-inc-dec -fcprop-registers -fdce -fdefer-pop -fdelayed-branch
-fdse -fguess-branch-probability -fif-conversion2 -fif-conversion
-fipa-pure-const -fipa-reference -fmerge-constants
-fsplit-wide-types -ftree-builtin-call-dce -ftree-ccp -ftree-ch
-ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse
-ftree-forwprop -ftree-fre -ftree-phiprop -ftree-sra -ftree-pta
-ftree-ter -funit-at-a-time
given explicitly (and without any -O*) on gcc's command line.

I've tested with testcase.c with different gcc versions on different platforms.
The workaround function always contains correct assembler code.
Only the results for PyArray_Item_XDECREF: It either contains correct code or it is empty (except entering and leaving a stack frame).

+----------+------------------------+------------+-------+
|Version   |Platform                |Optimization|Result |
+----------+------------------------+------------+-------+
|4.1.2     |i486-linux-gnu          |-O3         |works  |
|(Debian   |                        |            |       |
|4.1.1-21) |                        |            |       |
+----------+------------------------+------------+-------+
|4.2.0     |sparcv9-sun-solaris2.10 |-O3         |works  |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.3.2     |x86_64-linux-gnu        |-O3         |works  |
|(Debian   |                        |            |       |
|4.3.2-1.1)|                        |            |       |
+----------+------------------------+------------+-------+
|4.4.0     |i686-pc-linux-gnu       |-O3         |works  |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.4.3     |x86_64-unknown-linux-gnu|-O3         |works  |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.4.3     |sparc-sun-solaris2.10   |-O3         |works  |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.5.0     |x86_64-unknown-linux-gnu|-O1         |fail   |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.5.1     |i686-pc-linux-gnu       |-O1         |fail   |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+
|4.5.1     |sparc-sun-solaris2.10   |-O1         |fail   |
|(self     |                        |            |       |
|compiled) |                        |            |       |
+----------+------------------------+------------+-------+

As you can see, the issue is not dependent on the target architecture, but on gcc's version. It seems to have been introduced post-4.4.3 (unfortunately I have no 4.4.4/4.4.5 here)

Thank you very much

Nicolai
Comment 1 Richard Biener 2010-10-11 15:03:59 UTC
I think I have seen a dup of this bug.  The bug is in points-to analysis
which doesn't grok your weird way of initializing a pointer temporary.
So what goes on is that you have

  int *pointer;
  initialize-pointer-by-pieces
  --*pointer;

and points-to analysis doesn't get that initialize-pointer-by-pieces
alters the points-to set of pointer and thus we end up with pointer
pointing to nothing (which makes --*pointer removed by dead code
elimination).

The bug is also latent in 4.4 but there for a pointer that points to
nothing we simply assume it points to anything (which hides bugs).

PR45623 was similar, but I am thinking of another dup.

I will give this mess a little more thought.
Comment 2 Richard Biener 2010-10-13 11:54:58 UTC
Testcase:

extern void abort (void);
void __attribute__((noinline,noclone))
foo (void *p_)
{
  int *p;
  int i;
  for (i = 0; i < sizeof(int *); ++i)
    ((char *)&p)[i] = ((char *)p_)[i];
  *p = 1;
}
int main()
{
  int i = 0;
  int *p = &i;
  foo (&p);
  if (i != 1)
    abort ();
  return 0;
}
Comment 3 Richard Biener 2010-10-18 15:32:03 UTC
Author: rguenth
Date: Mon Oct 18 15:32:00 2010
New Revision: 165641

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=165641
Log:
2010-10-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45967
	* tree-ssa-structalias.c (type_could_have_pointers): Remove.
	(could_have_pointers): Likewise.
	(handle_rhs_call, handle_const_call, handle_pure_call,
	find_func_aliases, intra_create_variable_infos): Remove calls to them.
	(struct fieldoff): Add must_have_pointers field.
	(type_must_have_pointers): New function.
	(field_must_have_pointers): Likewise.
	(push_fields_onto_fieldstack): Remove must_have_pointers_p argument.
	Adjust field merging.
	(create_function_info_for): May-have-pointers of varinfo is
	almost always true.
	(create_variable_info_for_1): Likewise.

	* gcc.dg/torture/pr45967.c: New testcase.
	* gcc.dg/ipa/ipa-pta-10.c: Adjust.
	* gcc.dg/ipa/ipa-pta-13.c: Likewise
	* gcc.dg/torture/pr39074-2.c: Likewise
	* gcc.dg/torture/pta-escape-1.c: Likewise
	* gcc.dg/torture/pta-ptrarith-1.c: Likewise
	* gcc.dg/tree-ssa/pta-callused.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-1.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-2.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-3.c: Likewise
	* gcc.dg/tree-ssa/ssa-pre-21.c: Likewise

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr45967.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gcc.dg/ipa/ipa-pta-10.c
    trunk/gcc/testsuite/gcc.dg/ipa/ipa-pta-13.c
    trunk/gcc/testsuite/gcc.dg/torture/pr39074-2.c
    trunk/gcc/testsuite/gcc.dg/torture/pta-escape-1.c
    trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
    trunk/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
    trunk/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c
    trunk/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c
    trunk/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c
    trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-21.c
    trunk/gcc/tree-ssa-structalias.c
Comment 4 Richard Biener 2010-10-18 15:33:38 UTC
Fixed for trunk sofar.  Let's see if there is any fallout.
Comment 5 Andreas Krebbel 2010-10-25 14:16:38 UTC
(In reply to comment #4)
> Fixed for trunk sofar.  Let's see if there is any fallout.

This seems to have broken bootstrap on s390x. From a first glance it looks like collect2 has been miscompiled. I'll try to gather more infos.
Comment 6 Andreas Krebbel 2010-11-12 14:26:56 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > Fixed for trunk sofar.  Let's see if there is any fallout.
> 
> This seems to have broken bootstrap on s390x. From a first glance it looks like
> collect2 has been miscompiled. I'll try to gather more infos.

My regression tester returned this revision for the failure but the change only revealed the problem with the cfgcleanup/crossjumping patches which have been reverted in the meantime.

I opened #46238 for this problem.
Comment 7 Richard Biener 2010-12-16 13:03:30 UTC
GCC 4.5.2 is being released, adjusting target milestone.
Comment 8 Richard Biener 2011-01-17 11:44:11 UTC
The patch is quite big and a backport is nothing for the faint-hearted.  Do not
hold your breath.

The underlying problem is present since ever btw, and 4.4 can be tricked
into miscompiling with the usual avoid-empty-points-to-sets trick
(conditionally assign (not) to the pointer, thus add something else
to the set):

extern void abort (void);
int b;
void
foo (void *p_, int *q)
{
  int *p;
  int i;
  for (i = 0; i < sizeof(int *); ++i)
    ((char *)&p)[i] = ((char *)p_)[i];
  if (b)
    p = q;
  *p = 1;
}
int main()
{
  int i = 0, j;
  int *p = &i;
  foo (&p, &j);
  if (i != 1)
    abort ();
  return 0;
}

I'll add some more testcases.
Comment 9 Richard Biener 2011-01-17 11:50:50 UTC
Author: rguenth
Date: Mon Jan 17 11:50:47 2011
New Revision: 168896

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=168896
Log:
2011-01-17  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45967
	* gcc.dg/torture/pr45967-2.c: New testcase.
	* gcc.dg/torture/pr45967-3.c: Likewise.

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr45967-2.c
    trunk/gcc/testsuite/gcc.dg/torture/pr45967-3.c
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 10 Richard Biener 2011-03-02 15:54:36 UTC
Created attachment 23515 [details]
patch for the 4.5 branch
Comment 11 Richard Biener 2011-03-08 13:31:21 UTC
Author: rguenth
Date: Tue Mar  8 13:31:13 2011
New Revision: 170776

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=170776
Log:
2011-03-08  Richard Guenther  <rguenther@suse.de>

	Backport from mainline
	2011-02-10  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (bitpos_of_field): Use BITS_PER_UNIT, not 8.

	2010-10-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45967
	* tree-ssa-structalias.c (type_could_have_pointers): Remove.
	(could_have_pointers): Likewise.
	(handle_rhs_call, handle_const_call, handle_pure_call,
	find_func_aliases, intra_create_variable_infos): Remove calls to them.
	(struct fieldoff): Add must_have_pointers field.
	(type_must_have_pointers): New function.
	(field_must_have_pointers): Likewise.
	(push_fields_onto_fieldstack): Remove must_have_pointers_p argument.
	Adjust field merging.
	(create_function_info_for): May-have-pointers of varinfo is
	almost always true.
	(create_variable_info_for_1): Likewise.

	* gcc.dg/torture/pr45967.c: New testcase.
	* gcc.dg/torture/pr45967-2.c: Likewise.
	* gcc.dg/torture/pr45967-3.c: Likewise.
	* gcc.dg/torture/pr39074-2.c: Adjust. 
	* gcc.dg/torture/pta-escape-1.c: Likewise
	* gcc.dg/torture/pta-ptrarith-1.c: Likewise
	* gcc.dg/tree-ssa/pta-callused.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-1.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-2.c: Likewise
	* gcc.dg/tree-ssa/pta-escape-3.c: Likewise
	* gcc.dg/tree-ssa/ssa-pre-21.c: Likewise

	2010-10-12  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-structalias.c (get_constraint_for_1): Constants
	only point to nonlocal, not anything.

Added:
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pr45967-2.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pr45967-3.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pr45967.c
Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pr39074-2.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pta-escape-1.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c
    branches/gcc-4_5-branch/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-21.c
    branches/gcc-4_5-branch/gcc/tree-ssa-structalias.c
Comment 12 Richard Biener 2011-03-08 13:32:29 UTC
Fixed.