Bug 8328

Summary: get_secondary_mem called during reload_as_needed
Product: gcc Reporter: Alan Modra <amodra>
Component: rtl-optimizationAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: amodra, gcc-bugs
Priority: P3 Keywords: ice-on-valid-code
Version: 3.2.1   
Target Milestone: 3.4.0   
Host: Target: powerpc64-linux-gnu
Build: Known to work:
Known to fail: Last reconfirmed:

Description Alan Modra 2002-10-23 18:56:01 UTC
The testcase triggers at least two bugs in handling of a register
holding a common subexpression, "(void *) &loc".  The first one being
that gcse incorrectly inserts code around a label.  We replace

=========
(note 308 131 310 NOTE_INSN_LOOP_END)

(code_label 310 308 363 3 ("exit") "" [4 uses])

(note 363 310 311 [bb 10] NOTE_INSN_BASIC_BLOCK)

(note 311 363 316 0x401e3dc0 NOTE_INSN_BLOCK_BEG)

(insn 316 311 318 (set (reg/f:DI 177)
        (plus:DI (reg/f:DI 31 r31)
            (const_int 116 [0x74]))) 220 {*adddi3_internal1} (nil)
    (nil))

(insn 318 316 321 (set (mem/s:DI (plus:DI (reg/f:DI 31 r31)
                (const_int 384 [0x180])) [9 <variable>.data+0 S8 A64])
        (reg/f:DI 177)) 316 {*movdi_internal64} (nil)
    (nil))
=========

with

=========
(note 308 404 406 NOTE_INSN_LOOP_END)

(code_label 406 308 405 12 "" "" [1 uses])

(note 405 406 383 [bb 12] NOTE_INSN_BASIC_BLOCK)

(insn 383 405 310 (set (reg/f:DI 186)
        (plus:DI (reg/f:DI 31 r31)
            (const_int 116 [0x74]))) 220 {*adddi3_internal1} (nil)
    (nil))

(code_label 310 383 363 3 ("exit") "" [4 uses])

(note 363 310 311 [bb 13] NOTE_INSN_BASIC_BLOCK)

(note 311 363 318 0x401e3dc0 NOTE_INSN_BLOCK_BEG)

(insn 318 311 321 (set (mem/s:DI (plus:DI (reg/f:DI 31 r31)
                (const_int 384 [0x180])) [9 <variable>.data+0 S8 A64])
        (reg/f:DI 186)) 316 {*movdi_internal64} (nil)
    (nil))
=========

Note how insn 383 has moved before "exit".  Also, I believe that gcse
should be using register DI 131 here as that is the one used in a
previous replacement of "(void *) &loc".

The second problem is that reg DI 186 is allocated a fp reg, and thus
needs secondary mem to transfer the result of r31+116.

#0  assign_stack_local_1 (mode=DImode, size=8, align=1075958620, 
    function=0x4001c400) at /src/gcc-ppc64-32/gcc/function.c:621
#1  0x080f08fc in assign_stack_local (mode=1075958620, size=48320598876, 
    align=1075958620) at /src/gcc-ppc64-32/gcc/function.c:641
#2  0x0818cf46 in get_secondary_mem (x=0x40017000, mode=DImode, opnum=1, 
    type=RELOAD_FOR_INPUT) at /src/gcc-ppc64-32/gcc/reload.c:620
#3  0x081a750c in gen_reload (out=0x401ead34, in=0x40017000, opnum=1, 
    type=RELOAD_FOR_INPUT) at /src/gcc-ppc64-32/gcc/reload1.c:7535
#4  0x081a7346 in gen_reload (out=0x401ead34, in=0x4021d26c, opnum=1, 
    type=RELOAD_FOR_INPUT) at /src/gcc-ppc64-32/gcc/reload1.c:7519
#5  0x081a55c1 in emit_input_reload_insns (chain=0x4021d35c, rl=0x83512a0, 
    old=0x4021d26c, j=0) at /src/gcc-ppc64-32/gcc/reload1.c:6608
#6  0x081a5cab in do_input_reload (chain=0x83953a0, rl=0x83512a0, j=0)
    at /src/gcc-ppc64-32/gcc/reload1.c:6858
#7  0x081a612f in emit_reload_insns (chain=0x0)
    at /src/gcc-ppc64-32/gcc/reload1.c:7015
#8  0x0819f992 in reload_as_needed (live_known=1)
    at /src/gcc-ppc64-32/gcc/reload1.c:3914
#9  0x0819abb9 in reload (first=0x401e3e80, global=1)
    at /src/gcc-ppc64-32/gcc/reload1.c:1109
#10 0x0822a626 in global_alloc (file=0x0) at /src/gcc-ppc64-32/gcc/global.c:590

Release:
3.2.1 20021023 (prerelease)

Environment:
configured with: /src/gcc-3.2/configure --prefix=/usr/local --build=i686-linux --host=i686-linux --target=powerpc64-linux --disable-nls --with-headers=/usr/local/powerpc64-linux/include --enable-languages=c

How-To-Repeat:
gcc64-3.2/gcc/xgcc -Bgcc64-3.2/gcc/ -O2 wjybug.i -c    
/src/tmp/wjybug.c: In function `myfunc':
/src/tmp/wjybug.c:113: Internal compiler error in reload, at reload1.c:1112

# 1 "/src/tmp/wjybug.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "/src/tmp/wjybug.c"

struct list
{
  unsigned short type;
  unsigned int len;
  void *data;
  short *ind;
};

extern int foo (int *);
extern int bar (void);
extern int qwe (struct list *);
extern long check (int *);
extern void display (int *);
extern void trace (int *);

int
myfunc (int *opts, char *str)
{
  short num;
  int loc;
  int start;
  int len;
  int code;
  int rc = 0;

  if (code && (rc = check (opts)))
    goto exit;

  foo (&code);
  {
    struct list mylist[1];
    mylist[0].type = 960;
    mylist[0].len = 4;
    mylist[0].data = (void *) &loc;
    mylist[0].ind = 0L;
    qwe (mylist);
  }
  bar ();

  if (code && (rc = check (opts)))
    goto exit;

  foo (&code);
  bar ();

  if (code && (rc = check (opts)))
    goto exit;

  if (opts)
    trace (opts);

  display (opts);

  while (code >= 0)
    {
      foo (&code);
      {
        struct list mylist[1];
        mylist[0].type = 500;
        mylist[0].len = 2;
        mylist[0].data = (void *) &num;
        mylist[0].ind = 0L;
        qwe (mylist);
      }
      bar ();
      {
        struct list mylist[3];
        mylist[0].type = 960;
        mylist[0].len = 4;
        mylist[0].data = (void *) &loc;
        mylist[0].ind = 0L;
        mylist[1].type = 496;
        mylist[1].len = 4;
        mylist[1].data = (void *) &start;
        mylist[1].ind = 0L;
        mylist[2].type = 496;
        mylist[2].len = 4;
        mylist[2].data = (void *) &len;
        mylist[2].ind = 0L;
        qwe (mylist);
      }
      {
        struct list mylist[4];
        mylist[0].type = 460;
        mylist[0].len = 129;
        mylist[0].data = (void *) str;
        mylist[0].ind = 0L;
        mylist[1].type = 460;
        mylist[1].len = 129;
        mylist[1].data = (void *) str;
        mylist[1].ind = 0L;
        mylist[2].type = 460;
        mylist[2].len = 9;
        mylist[2].data = (void *) str;
        mylist[2].ind = 0L;
        mylist[3].type = 500;
        mylist[3].len = 2;
        mylist[3].data = (void *) str;
        mylist[3].ind = 0L;
        qwe (mylist);
      }
    }

exit:
  {
    struct list mylist[1];
    mylist[0].data = (void *) &loc;
    mylist[0].ind = 0L;
    qwe (mylist);
  }
  return (rc);
}
Comment 1 Alan Modra 2002-10-23 18:56:01 UTC
Fix:
I'm going to poke at the gcse problem, but would appreciate pointers.
mainline gcc doesn't exhibit this ICE.
Comment 2 Alan Modra 2002-10-24 15:05:03 UTC
From: Alan Modra <amodra@bigpond.net.au>
To: gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: optimization/8328: powerpc64 ICE in reload
Date: Thu, 24 Oct 2002 15:05:03 +0930

 On Thu, Oct 24, 2002 at 11:18:38AM +0930, Alan Modra wrote:
 > holding a common subexpression, "(void *) &loc".  The first one being
 > that gcse incorrectly inserts code around a label.  We replace
 
 No, I was wrong about this.  The inserted code is actually correct, if
 not ideal.
 
 > Note how insn 383 has moved before "exit".  Also, I believe that gcse
 > should be using register DI 131 here as that is the one used in a
 > previous replacement of "(void *) &loc".
 
 And this one is related to this FIXME in gcse.c, I think:
 
 	      /* FIXME: If it turns out that the insn isn't deletable,
 		 then we may have unnecessarily extended register lifetimes
 		 and made things worse.  */
 
 So we're down to just the reload problem.
 
 -- 
 Alan Modra
 IBM OzLabs - Linux Technology Centre
Comment 3 Eric Botcazou 2003-02-18 15:01:08 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Already analyzed by Alan.
Comment 4 Andrew Pinski 2004-01-01 20:48:41 UTC
Fixed for 3.4.
Comment 5 GCC Commits 2005-01-05 09:17:17 UTC
Subject: Bug 8328

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_2-rhl8-branch
Changes by:	jakub@gcc.gnu.org	2005-01-05 09:17:00

Modified files:
	gcc            : ChangeLog 
	gcc/config/rs6000: rs6000.md 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/gcc.dg: pr8328.c 

Log message:
	2004-07-25  David Edelsohn  <edelsohn@gnu.org>
	
	PR target/16239
	* config/rs6000/rs6000.md (movdi_internal64): Further disparage
	f->f.
	
	2002-11-06  David Edelsohn  <edelsohn@gnu.org>
	
	PR target/8480, optimization/8328
	* config/rs6000/rs6000.md (movdi_internal64): Discourage
	FPR to FPR moves.
	
	2004-12-22  Ben Elliston  <bje@au.ibm.com>
	
	PR optimization/8328
	* gcc.dg/pr8328.c: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.13152.2.657.2.27.2.208&r2=1.13152.2.657.2.27.2.209
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/rs6000/rs6000.md.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.170.2.11.4.12&r2=1.170.2.11.4.13
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.1672.2.166.2.8.2.89&r2=1.1672.2.166.2.8.2.90
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/pr8328.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.2.1