Bug 42536 - [4.7 regression] ICE in spill_failure, at reload1.c:2141
Summary: [4.7 regression] ICE in spill_failure, at reload1.c:2141
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.5.0
: P2 normal
Target Milestone: 4.8.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ra
Depends on:
Blocks:
 
Reported: 2009-12-29 12:40 UTC by Debian GCC Maintainers
Modified: 2014-06-12 12:55 UTC (History)
6 users (show)

See Also:
Host:
Target: i486-linux-gnu
Build:
Known to work: 4.3.4, 4.8.0
Known to fail: 4.4.2, 4.5.0
Last reconfirmed: 2012-09-02 00:00:00


Attachments
preprocessed source (63.49 KB, application/x-gzip)
2009-12-29 12:41 UTC, Debian GCC Maintainers
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Debian GCC Maintainers 2009-12-29 12:40:53 UTC
seen with 20091228 trunk and 4.4 branch on i486-linux-gnu, not seen with 4.3 branch (opening new report, because PR39431 is fixed for 4.4 and 4.5). Adding -fomit-frame-pointer avoids the ice.

  Matthias

$ /usr/lib/gcc-snapshot/bin/gcc -g -O2 -fno-gcse -fno-inline-functions -fno-unit-at-a-time -fstack-protector -c cvm.i 
cvm.c: In function '_ILCVMInterpreter':
cvm.c:889:1: error: unable to find a register to spill in class 'GENERAL_REGS'
cvm.c:889:1: error: this is the insn:
(insn 11992 11991 11993 863 cvm_ptr.c:66 (set (mem:DI (plus:SI (plus:SI (mult:SI (reg:SI 6750 [ D.20325 ])
                        (const_int 8 [0x8]))
                    (reg/f:SI 6746 [ tempptr.3460 ]))
                (const_int 4 [0x4])) [16 S8 A64])
        (reg:DI 12123)) 88 {*movdi_2} (expr_list:REG_DEAD (reg:DI 12123)
        (expr_list:REG_DEAD (reg:SI 6750 [ D.20325 ])
            (expr_list:REG_DEAD (reg/f:SI 6746 [ tempptr.3460 ])
                (nil)))))
cvm.c:889:1: internal compiler error: in spill_failure, at reload1.c:2141
Please submit a full bug report,
with preprocessed source if appropriate.
Comment 1 Debian GCC Maintainers 2009-12-29 12:41:21 UTC
Created attachment 19411 [details]
preprocessed source
Comment 2 Jakub Jelinek 2010-01-02 14:30:25 UTC
With 3 register vars in the function (ebx, edi, esi) on the register starved ix86 the error is tollerable.  From the 8 registers the programmer takes 3, %esp is fixed, without -fomit-frame-pointer %ebp is fixed too, which leaves just %eax, %edx and %ecx for register allocation.  Even if this happens to compile, the result can't work fast, as almost all insns need to have temporaries spilled and reread back.
Comment 3 Jakub Jelinek 2010-01-02 16:44:28 UTC
Reduced testcase:
/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
/* { dg-options "-O2 -fno-gcse" } */

struct C;
struct B { struct C *b; };
struct C { void (*baz) (struct B *, void *, int); };
typedef union { int f; void *e; } D;
struct E { struct B *e; };
struct A { struct E *a1; D *a2; D *a3; };

void
foo (long *x, long y)
{
  *(long long *) x = y;
}

extern long fn1 (D);
extern void fn2 (void);

void
_bar (struct A *x)
{
  register int a asm ("esi");
  register D *volatile b asm ("edi");
  register int c asm ("ebx");
  void *d;
  asm volatile ("" : "=r" (a), "=r" (b), "=r" (c) : : "memory");
  if ((d = b[-2].e) != 0 && b [-2].e < d)
    {
      foo (&(((long *) d) + 1) [b[0].f], fn1 (b[-1]));
      x->a2 = (D *) c;
      x->a3 = b;
      fn2 ();
    }
  x->a1->e->b->baz (x->a1->e, (void *) (long) a, 1);
}

Wonder why RA doesn't try to force the memory address into register, that would free up one register from the 4 otherwise needed (2 for the address, 2 for DImode value being stored into the memory). 
Comment 4 Jakub Jelinek 2010-11-29 19:50:18 UTC
Jeff/Vlad, how hard would it be to try to split the insn into two insns instead of a spill failure (for insns using a MEM whose address uses more than one hard register) - one which forces the address into register (assuming it is supported) and the store (or load) which would use a simpler address form?
Comment 5 Jeffrey A. Law 2010-11-29 20:33:14 UTC
I guess it would be possible for reload to split an insn in some circumstances, particularly when there's complex addressing modes and multiple registers dying within the insn.

As you know, I've been poking at range splitting and we might be able to model this case too.  Right now I split based on unallocated pseudos and expect to split ranges based on pseudos getting the wrong kind of register in the future.

However, there's a couple areas were we still want to split ranges and we may be able to come up with a generic way to express the other ranges we want to split:
Comment 6 Vladimir Makarov 2010-11-29 20:39:39 UTC
(In reply to comment #4)
> Jeff/Vlad, how hard would it be to try to split the insn into two insns instead
> of a spill failure (for insns using a MEM whose address uses more than one hard
> register) - one which forces the address into register (assuming it is
> supported) and the store (or load) which would use a simpler address form?

If it is done in reload (and imho this is the most right place to do), I think it would be hard.  It needs some person with a good knowledge of the reload.

It is also possible to do some splitting in other parts of compiler but it would an approximate solution (it means not all such cases will be avoided or/and it will hurt performance in general case).
Comment 7 Andrew Pinski 2012-01-24 01:27:30 UTC
I cannot reproduce this bug on the trunk or 4.6.
Comment 8 Andrew Pinski 2012-01-24 01:30:36 UTC
(In reply to comment #7)
> I cannot reproduce this bug on the trunk or 4.6.

I want to say this is really a dup of bug 44174.
Comment 9 Jakub Jelinek 2012-03-13 12:47:03 UTC
4.4 branch is being closed, moving to 4.5.4 target.
Comment 10 Richard Biener 2012-07-02 11:09:19 UTC
The 4.5 branch is being closed, adjusting target milestone.
Comment 11 Uroš Bizjak 2012-09-02 09:22:34 UTC
(In reply to comment #7)
> I cannot reproduce this bug on the trunk or 4.6.

Try with "-O2 -fno-gcse -fno-omit-frame-pointer -m32", it fails on 4.6+.

Reconfirmed.
Comment 12 Uroš Bizjak 2012-09-02 09:44:12 UTC
(In reply to comment #11)

> Reconfirmed.

BTW: Moving the complex address to the temporary (as proposed in Comment #4) would help "atomic_compare_and_swap<dwi>_doubleword" on 32bit x86 targets, too. This pattern uses cmpxchg8b_pic_memory_operand predicate to limit the number of address registers for 32bit x86 targets, in order to avoid spill failures. Please see i386/sync.md.
Comment 13 Steven Bosscher 2012-11-11 21:34:36 UTC
bug 55277 tracks the similar ICE in LRA instead of reload.
Comment 14 Jakub Jelinek 2013-04-12 15:16:43 UTC
GCC 4.6.4 has been released and the branch has been closed.
Comment 15 Richard Biener 2014-06-12 12:55:09 UTC
Fixed in 4.8.0 by means of using LRA.