Bug 25654 - [4.0/4.1/4.2 Regression] RTL alias analysis unprepared to handle stack slot sharing
Summary: [4.0/4.1/4.2 Regression] RTL alias analysis unprepared to handle stack slot s...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.2.0
: P1 critical
Target Milestone: 4.0.3
Assignee: Richard Biener
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: alias, patch, wrong-code
Depends on:
Blocks:
 
Reported: 2006-01-03 23:01 UTC by Steven Bosscher
Modified: 2006-01-23 09:54 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.4.4
Known to fail: 4.0.3 4.1.0 4.2.0
Last reconfirmed: 2006-01-03 23:23:36


Attachments
patch (967 bytes, patch)
2006-01-16 11:23 UTC, Richard Biener
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Steven Bosscher 2006-01-03 23:01:15 UTC
In the following C code, the order of loads and stores is messed up, leading to wrong code:

extern void abort (void) __attribute__((noreturn));

union setconflict
{
  short a[20];
  int b[10];
};

int
main ()
{
  int sum = 0;
  {
    union setconflict a;
    short *c;
    c = a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 0;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }
  {
    union setconflict a;
    int *c;
    c = a.b;
    asm ("": "=r" (c):"0" (c));
    *c = 1;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }

  printf ("%d\n",sum);
  if (sum != 1)
    abort();
  return 0;
}



	.file	"t.c"
# GNU C version 4.2.0 20060101 (experimental) (x86_64-unknown-linux-gnu)
#	compiled by GNU C version 4.0.2 20050901 (prerelease) (SUSE Linux).
# GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
# options passed:  -iprefix -isystem -m32 -march=pentiumpro -auxbase -O2
# -fdump-tree-vars -fomit-frame-pointer -fverbose-asm
# options enabled:  -falign-loops -fargument-alias -fbranch-count-reg
# -fcaller-saves -fcommon -fcprop-registers -fcrossjumping
# -fcse-follow-jumps -fcse-skip-blocks -fdefer-pop
# -fdelete-null-pointer-checks -fearly-inlining
# -feliminate-unused-debug-types -fexpensive-optimizations -ffunction-cse
# -fgcse -fgcse-lm -fguess-branch-probability -fident -fif-conversion
# -fif-conversion2 -finline-functions-called-once -fipa-pure-const
# -fipa-reference -fipa-type-escape -fivopts -fkeep-static-consts
# -fleading-underscore -floop-optimize -floop-optimize2 -fmath-errno
# -fmerge-constants -fomit-frame-pointer -foptimize-register-move
# -foptimize-sibling-calls -fpcc-struct-return -fpeephole -fpeephole2
# -fregmove -freorder-blocks -freorder-functions -frerun-cse-after-loop
# -frerun-loop-opt -fsched-interblock -fsched-spec
# -fsched-stalled-insns-dep -fschedule-insns2 -fshow-column
# -fsplit-ivs-in-unroller -fstrength-reduce -fstrict-aliasing
# -fthread-jumps -ftrapping-math -ftree-ccp -ftree-ch -ftree-copy-prop
# -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-fre
# -ftree-loop-im -ftree-loop-ivcanon -ftree-loop-optimize -ftree-lrs
# -ftree-pre -ftree-salias -ftree-sink -ftree-sra -ftree-store-ccp
# -ftree-store-copy-prop -ftree-ter -ftree-vect-loop-version -ftree-vrp
# -funit-at-a-time -fverbose-asm -fzero-initialized-in-bss -m32 -m80387
# -m96bit-long-double -maccumulate-outgoing-args -malign-stringops
# -mfancy-math-387 -mfp-ret-in-387 -mieee-fp -mno-red-zone -mpush-args
# -mtls-direct-seg-refs

# Compiler executable checksum: 6d90f1c30ff8027bc6976ab2dbfe2320

	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"%d\n"
	.text
	.p2align 4,,15
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx	#,
	andl	$-16, %esp	#,
	pushl	-4(%ecx)	#
	subl	$76, %esp	#,
	leal	28(%esp), %eax	#, tmp64
	movl	%ecx, 68(%esp)	#,
	movl	%eax, %edx	# tmp64, c
	movl	%ebx, 72(%esp)	#,
	movw	$0, (%edx)	#,* c
	movl	$1, (%eax)	#,* c
	movswl	(%edx),%ebx	#* c, sum
	movl	(%eax), %edx	#* c,
	movl	$.LC0, (%esp)	#,
	addl	%edx, %ebx	#, sum
	movl	%ebx, 4(%esp)	# sum,
	call	printf	#
	decl	%ebx	# sum
	jne	.L6	#,
	movl	68(%esp), %ecx	#,
	xorl	%eax, %eax	# <result>
	movl	72(%esp), %ebx	#,
	addl	$76, %esp	#,
	leal	-4(%ecx), %esp	#,
	ret
.L6:
	call	abort	#
	.size	main, .-main
	.ident	"GCC: (GNU) 4.2.0 20060101 (experimental)"
	.section	.note.GNU-stack,"",@progbits

See also the thread on the gcc@ mailing list starting here: http://gcc.gnu.org/ml/gcc/2006-01/msg00008.html.
Comment 1 Andrew Pinski 2006-01-03 23:23:36 UTC
Confirmed.
Comment 2 Steven Bosscher 2006-01-13 21:30:51 UTC
I wonder if this problem can also be triggered without using two variables of the same union type.  There is code in add_alias_set_conflicts to avoid the situation we're running into:

static void
add_alias_set_conflicts (void)
{
  size_t i, j, n = stack_vars_num;

  for (i = 0; i < n; ++i)
    {
      tree type_i = TREE_TYPE (stack_vars[i].decl);
      bool aggr_i = AGGREGATE_TYPE_P (type_i);

      for (j = 0; j < i; ++j)
        {
          tree type_j = TREE_TYPE (stack_vars[j].decl);
          bool aggr_j = AGGREGATE_TYPE_P (type_j);
          if (aggr_i != aggr_j || !objects_must_conflict_p (type_i, type_j))
            add_stack_var_conflict (i, j);
        }
    }
}

but if you have two stack variables of the same union type, aggr_i == aggr_j, and type_i == type_j so objects_must_conflict_p returns true.  So perhaps if type_i and type_j are unions and type_i == type_j, we should also do an add_stack_var_conflict...?

Comment 3 Richard Biener 2006-01-13 22:04:26 UTC
I think we need to add a conflict if type_i and type_j are or contain a union of the same type.
Comment 4 Richard Biener 2006-01-13 22:11:26 UTC
Like consider the case of

void foo(void)
{
 struct A { union U u; } a; struct B { union U u; } b;

}

with a same-type union wrapped in different structs.
Comment 5 Steven Bosscher 2006-01-14 00:10:57 UTC
Hmm, not sure...  Consider this modified test case:

nion setconflict
{
  short a[20];
  int b[10];
};

int
foo (void)
{
  int sum = 0;
  {
    struct A { union setconflict u; } a;
    short *c;
    c = a.u.a;
    asm ("": "=r" (c):"0" (c));
    *c = 2;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }
  {
    struct B { union setconflict u; } a;
    int *c;
    c = a.u.b;
    asm ("": "=r" (c):"0" (c));
    *c = 1;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }

  return sum;
}


The two objects called a are put into different partitions because objects_must_conflict_p (type_i, type_j) now says the types A and B don't have to conflict, and we get:

;; Function foo (foo)

Partition 0: size 40 align 4
        a, offset 0
Partition 1: size 40 align 4
        a, offset 0

This happens because the alias sets for A and B are different.
Comment 6 Richard Biener 2006-01-16 11:23:34 UTC
Created attachment 10651 [details]
patch

Testing the attached patch.
Comment 7 Jan Hubicka 2006-01-16 14:56:54 UTC
These two testcases seems to still fail for me even with the patch. (I use  b.c -mpreferred-stack-boundary=2 -S -march=i686 -frename-registers)
extern void abort (void) __attribute__((noreturn));

struct setconflict
{
  char a[36];
  int b;
};

int
main ()
{
  int sum = 0;
  {
    struct setconflict a;
    short *c;
    c = (void *)a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 0;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }
  {
    struct setconflict a;
    int *c;
    c = (void *)a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 1;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }

  printf ("%d\n",sum);
  if (sum != 1)
    abort();
  return 0;
}

extern void abort (void) __attribute__((noreturn));

struct wrapper {
union setconflict
{
  short a[20];
  int b[10];
} a;
};

int
main ()
{
  int sum = 0;
  {
    struct wrapper a;
    short *c;
    c = a.a.a;
    asm ("": "=r" (c):"0" (c));
    *c = 0;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }
  {
    struct wrapper a;
    int *c;
    c = a.a.b;
    asm ("": "=r" (c):"0" (c));
    *c = 1;
    asm ("": "=r" (c):"0" (c));
    sum += *c;
  }

  printf ("%d\n",sum);
  if (sum != 1)
    abort();
  return 0;
}

So looking for unions is IMO not strong enought test.  Not sure what proper solution shall be :(
Honza
Comment 8 Richard Biener 2006-01-16 15:03:48 UTC
Your char testcase is invalid - it violates type based aliasing rules as you
access memory of type char as int and short.  Is it solved with -fno-strict-aliasing?
Comment 9 Richard Biener 2006-01-16 15:38:59 UTC
It is solved (all are) with -fno-strict-aliasing.  Whether the failure mode is that of an aliasing problem or not, is another question.
Comment 10 Jan Hubicka 2006-01-19 00:14:28 UTC
My understanding of C type based aliasing rules always was that char, as an exception, might alias with everything.  Perhaps I lived in false belief for a while, but at least -Wstrict-aliasing seems to think so:
ibm:~ # more t.c
char a[10];
short b[10];
main()
{
  *(int *)a=5;
  *(int *)b=5;
}
ibm:~ # gcc -O2 -Wstrict-aliasing t.c
t.c: In function main:
t.c:6: warning: dereferencing type-punned pointer will break strict-aliasing rules
Comment 11 Andrew Pinski 2006-01-19 00:19:17 UTC
(In reply to comment #10)
> My understanding of C type based aliasing rules always was that char, as an
> exception, might alias with everything.  Perhaps I lived in false belief for a
> while, but at least -Wstrict-aliasing seems to think so:

The aliasing rules are asymmetrical.

See http://gcc.gnu.org/ml/gcc-patches/2005-11/msg00980.html
Comment 12 Jan Hubicka 2006-01-19 00:38:30 UTC
Right, forgot about that...  At the moment I can't think of testcase that would break the transitivity without use of unions...

Honza
Comment 13 Mark Mitchell 2006-01-20 22:37:59 UTC
RTH's comments are here:

http://gcc.gnu.org/ml/gcc-patches/2006-01/msg01390.html
Comment 14 Richard Biener 2006-01-23 09:47:07 UTC
Subject: Bug 25654

Author: rguenth
Date: Mon Jan 23 09:47:01 2006
New Revision: 110109

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=110109
Log:
2006-01-23  Steven Bosscher  <stevenb.gcc@gmail.com>
	Jan Hubicka  <jh@suse.cz>
	Richard Guenther  <rguenther@suse.de>

	PR rtl-optimization/25654
	* cfgexpand.c (aggregate_contains_union_type): New function.
	(add_alias_set_conflicts): Call it.  Make sure to add conflicts
	for structure variables that contain a union type.

	* gcc.dg/torture/pr25654.c: New testcase.
	* gcc.target/i386/pr25654.c: Likewise.

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr25654.c
    trunk/gcc/testsuite/gcc.target/i386/pr25654.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cfgexpand.c
    trunk/gcc/testsuite/ChangeLog

Comment 15 Richard Biener 2006-01-23 09:50:11 UTC
Subject: Bug 25654

Author: rguenth
Date: Mon Jan 23 09:50:07 2006
New Revision: 110110

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=110110
Log:
2006-01-23  Steven Bosscher  <stevenb.gcc@gmail.com>
	Jan Hubicka  <jh@suse.cz>
	Richard Guenther  <rguenther@suse.de>

	PR rtl-optimization/25654
	* cfgexpand.c (aggregate_contains_union_type): New function.
	(add_alias_set_conflicts): Call it.  Make sure to add conflicts
	for structure variables that contain a union type.

	* gcc.dg/torture/pr25654.c: New testcase.
	* gcc.target/i386/pr25654.c: Likewise.

Added:
    branches/gcc-4_1-branch/gcc/testsuite/gcc.dg/torture/pr25654.c
    branches/gcc-4_1-branch/gcc/testsuite/gcc.target/i386/pr25654.c
Modified:
    branches/gcc-4_1-branch/gcc/ChangeLog
    branches/gcc-4_1-branch/gcc/cfgexpand.c
    branches/gcc-4_1-branch/gcc/testsuite/ChangeLog

Comment 16 Richard Biener 2006-01-23 09:54:16 UTC
Subject: Bug 25654

Author: rguenth
Date: Mon Jan 23 09:54:12 2006
New Revision: 110111

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=110111
Log:
2006-01-23  Steven Bosscher  <stevenb.gcc@gmail.com>
	Jan Hubicka  <jh@suse.cz>
	Richard Guenther  <rguenther@suse.de>

	PR rtl-optimization/25654
	* cfgexpand.c (aggregate_contains_union_type): New function.
	(add_alias_set_conflicts): Call it.  Make sure to add conflicts
	for structure variables that contain a union type.

	* gcc.dg/torture/pr25654.c: New testcase.
	* gcc.target/i386/pr25654.c: Likewise.

Added:
    branches/gcc-4_0-branch/gcc/testsuite/gcc.dg/torture/pr25654.c
    branches/gcc-4_0-branch/gcc/testsuite/gcc.target/i386/pr25654.c
Modified:
    branches/gcc-4_0-branch/gcc/ChangeLog
    branches/gcc-4_0-branch/gcc/cfgexpand.c
    branches/gcc-4_0-branch/gcc/testsuite/ChangeLog

Comment 17 Richard Biener 2006-01-23 09:54:21 UTC
Fixed.