Bug 48335

Summary: [4.6/4.7 Regression] ICE in convert_move
Product: gcc Reporter: Jakub Jelinek <jakub>
Component: middle-endAssignee: Jakub Jelinek <jakub>
Status: RESOLVED FIXED    
Severity: normal CC: yufeng
Priority: P3 Keywords: ice-on-valid-code
Version: 4.6.0   
Target Milestone: 4.6.1   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54429
Host: Target:
Build: Known to work: 4.5.2
Known to fail: 4.6.0, 4.7.0 Last reconfirmed: 2011-03-29 15:50:00
Bug Depends on: 48358    
Bug Blocks:    
Attachments: gcc46-pr48335.patch
gcc46-pr48335.patch
gcc46-pr48335.patch

Description Jakub Jelinek 2011-03-29 14:21:44 UTC
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-sra -msse2" } */

#include <emmintrin.h>

struct S
{
  _Complex double d __attribute__((aligned (16)));
};

void bar (struct S);

void
foo (__m128d x, struct S y)
{
  struct S s;
  _mm_store_pd ((double *) &s.d, x);
  __real__ s.d *= 7.0;
  bar (s);
}

ICEs in convert_move, starting with
http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=161655
Comment 1 Jakub Jelinek 2011-03-29 14:55:51 UTC
And:
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-sra" } */

typedef __float128 T __attribute__((__may_alias__));

struct S
{
  _Complex double d __attribute__((aligned (16)));
};

void bar (struct S);

void
foo (T x)
{
  struct S s;
  *(T *) &s.d = x;
  __real__ s.d *= 7.0;
  bar (s);
}

seems to be quietly miscompiled (instead of storing the 128 bit __float128 over both real and imaginary parts (it is __may_alias__, so it should be fine aliasing-wise) it converts the __float128 to double and stores just over real part.  In 4.5 &s.d was present and s was addressable, but ADDR_EXPR in MEM_EXPR is ignored and thus in 4.6 we happily put s into (concat:DC (reg:DF ...) (reg:DF ...)).
Comment 2 Jakub Jelinek 2011-03-29 14:59:50 UTC
Yet another testcase:
/* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-sra" } */

typedef long long T __attribute__((__may_alias__));

struct S
{
  _Complex float d __attribute__((aligned (8)));
};

void bar (struct S);

void
foo (T x)
{
  struct S s;
  *(T *) &s.d = x;
  __real__ s.d *= 7.0;
  bar (s);
}

which ICEs too.  BTW, in the original testcase from
https://bugzilla.redhat.com/show_bug.cgi?id=691133 -fno-tree-sra wasn't used, just delta did a poor job on it even after many hours (got it to 32KB), so I've decided to try to write a testcase myself and for that I needed -fno-tree-sra.
Comment 3 Jakub Jelinek 2011-03-30 08:59:55 UTC
Created attachment 23814 [details]
gcc46-pr48335.patch

WIP patch I've been playing with.  Unfortunately, it shows that even without CONCAT we ICE, e.g. on:
struct S { float d; };
void bar (struct S);
void foo (int x) { struct S s = { .d = 0.0f }; *(char *) &s.d = x; s.d *= 7.0; bar (s); }
at -O2 -fno-tree-sra.
Comment 4 Jakub Jelinek 2011-03-30 09:53:25 UTC
Created attachment 23815 [details]
gcc46-pr48335.patch

Updated patch, with more testcases.
gcc.dg/pr48335-2.c still ICEs with -m32 and gcc.dg/pr48335-3.c for both -m32/-m64 (gcc.dg/pr48335-3.c is not complex related BTW).
Comment 5 Richard Biener 2011-03-30 10:05:13 UTC
A patch that might fix most of the issues could also be

Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c      (revision 171716)
+++ gcc/tree-ssa.c      (working copy)
@@ -1976,7 +1976,8 @@ maybe_optimize_var (tree var, bitmap add
       /* Do not change TREE_ADDRESSABLE if we need to preserve var as
         a non-register.  Otherwise we are confused and forget to
         add virtual operands for it.  */
-      && (!is_gimple_reg_type (TREE_TYPE (var))
+      && ((!is_gimple_reg_type (TREE_TYPE (var))
+          && TYPE_MODE (TREE_TYPE (var)) == BLKmode)
          || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
     {
       TREE_ADDRESSABLE (var) = 0;

pessimizing tree alias analysis (but only to be as bad as 4.5, maybe
a little worse for register types with components (vectors and complex vars)).
Comment 6 Jakub Jelinek 2011-03-30 11:55:14 UTC
Created attachment 23818 [details]
gcc46-pr48335.patch

Updated patch, all the new tests now compile, on i386/x86_64/ppc/ppc64/s390/s390x.
Comment 7 Jakub Jelinek 2011-04-01 21:13:31 UTC
Author: jakub
Date: Fri Apr  1 21:13:29 2011
New Revision: 171855

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171855
Log:
	PR middle-end/48335
	* expr.c (expand_assignment): Handle all possibilities
	if TO_RTX is CONCAT.
	* expmed.c (store_bit_field_1): Avoid trying to create
	invalid SUBREGs.
	(store_split_bit_field): If SUBREG_REG (op0) or
	op0 itself has smaller mode than word, return it
	for offset 0 and const0_rtx for out-of-bounds stores.
	If word is const0_rtx, skip it.

	* gcc.c-torture/compile/pr48335-1.c: New test.
	* gcc.dg/pr48335-1.c: New test.
	* gcc.dg/pr48335-2.c: New test.
	* gcc.dg/pr48335-3.c: New test.
	* gcc.dg/pr48335-4.c: New test.
	* gcc.dg/pr48335-5.c: New test.
	* gcc.dg/pr48335-6.c: New test.
	* gcc.dg/pr48335-7.c: New test.
	* gcc.dg/pr48335-8.c: New test.
	* gcc.target/i386/pr48335-1.c: New test.

Added:
    trunk/gcc/testsuite/gcc.c-torture/compile/pr48335-1.c
    trunk/gcc/testsuite/gcc.dg/pr48335-1.c
    trunk/gcc/testsuite/gcc.dg/pr48335-2.c
    trunk/gcc/testsuite/gcc.dg/pr48335-3.c
    trunk/gcc/testsuite/gcc.dg/pr48335-4.c
    trunk/gcc/testsuite/gcc.dg/pr48335-5.c
    trunk/gcc/testsuite/gcc.dg/pr48335-6.c
    trunk/gcc/testsuite/gcc.dg/pr48335-7.c
    trunk/gcc/testsuite/gcc.dg/pr48335-8.c
    trunk/gcc/testsuite/gcc.target/i386/pr48335-1.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/expmed.c
    trunk/gcc/expr.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 Jakub Jelinek 2011-04-06 20:39:24 UTC
Author: jakub
Date: Wed Apr  6 20:39:20 2011
New Revision: 172063

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=172063
Log:
	Backported from mainline
	2011-04-01  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/48335
	* expr.c (expand_assignment): Handle all possibilities
	if TO_RTX is CONCAT.
	* expmed.c (store_bit_field_1): Avoid trying to create
	invalid SUBREGs.
	(store_split_bit_field): If SUBREG_REG (op0) or
	op0 itself has smaller mode than word, return it
	for offset 0 and const0_rtx for out-of-bounds stores.
	If word is const0_rtx, skip it.

	* gcc.c-torture/compile/pr48335-1.c: New test.
	* gcc.dg/pr48335-1.c: New test.
	* gcc.dg/pr48335-2.c: New test.
	* gcc.dg/pr48335-3.c: New test.
	* gcc.dg/pr48335-4.c: New test.
	* gcc.dg/pr48335-5.c: New test.
	* gcc.dg/pr48335-6.c: New test.
	* gcc.dg/pr48335-7.c: New test.
	* gcc.dg/pr48335-8.c: New test.
	* gcc.target/i386/pr48335-1.c: New test.

Added:
    branches/gcc-4_6-branch/gcc/testsuite/gcc.c-torture/compile/pr48335-1.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-1.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-2.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-3.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-4.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-5.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-6.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-7.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.dg/pr48335-8.c
    branches/gcc-4_6-branch/gcc/testsuite/gcc.target/i386/pr48335-1.c
Modified:
    branches/gcc-4_6-branch/gcc/ChangeLog
    branches/gcc-4_6-branch/gcc/expmed.c
    branches/gcc-4_6-branch/gcc/expr.c
    branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
Comment 9 Jakub Jelinek 2011-04-06 20:40:52 UTC
Fixed.
Comment 10 Yufeng Zhang 2011-04-07 13:30:04 UTC
(In reply to comment #6)
> Created attachment 23818 [details]
> gcc46-pr48335.patch
> 
> Updated patch, all the new tests now compile, on
> i386/x86_64/ppc/ppc64/s390/s390x.

Hi Jakub,

The test gcc.dg/pr48335-2.c unfortunately fails in the arm-eabi testing with an ICE:

gcc.dg/pr48335-2.c: In function 'f1':
gcc.dg/pr48335-2.c:19:30: internal compiler error: in expand_expr_addr_expr_1, at expr.c:6922

I've raised the bug 48493 for this. I'm not sure how it is related with this bugzilla as the compiler before your commit fails on the test as well.

Cheers,
Yufeng