Bug 9786

Summary: [3.3/3.4 regression] Ice in fixup_abnormal_edges with -fnon-call-exceptions -O2
Product: gcc Reporter: nick
Component: targetAssignee: Eric Botcazou <ebotcazou>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs, gtalbot, hainque, jason, nick
Priority: P1 Keywords: ice-on-valid-code
Version: 3.3   
Target Milestone: 3.3.2   
Host: i686-pc-linux-gnu Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu Known to work:
Known to fail: Last reconfirmed: 2003-07-12 00:23:59
Attachments: foo.C

Description nick 2003-02-21 01:26:00 UTC
the same ICE occurs with both gcc-3.2.2 and the head
of the gcc-3_3-branch:

> /dept/rnd/vendor/gcc-3.3cvs/bin/g++ -v -fnon-call-exceptions -Wall -O2 -c foo.C -o foo.o 
Reading specs from /dept/rnd/vendor/gcc-3.3cvs/lib/gcc-lib/i686-pc-linux-gnu/3.3/specs
Configured with: ../gcc/configure --prefix=/dept/rnd/vendor/gcc-3.3cvs --enable-threads --enable-languages=c,c++
Thread model: posix
gcc version 3.3 20030220 (prerelease)
 /dept/rnd/vendor/gcc-3.3cvs/lib/gcc-lib/i686-pc-linux-gnu/3.3/cc1plus -quiet -v -D__GNUC__=3 -D__GNUC_MINOR__=3 -D__GNUC_PATCHLEVEL__=0 -D_GNU_SOURCE foo
.C -D__GNUG__=3 -quiet -dumpbase foo.C -auxbase-strip foo.o -O2 -Wall -version -fnon-call-exceptions -o /usr/tmp/ccNboRkg.s
GNU C++ version 3.3 20030220 (prerelease) (i686-pc-linux-gnu)
        compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.1 2.96-98).
ignoring nonexistent directory "/dept/rnd/vendor/gcc-3.3cvs/i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /dept/rnd/vendor/gcc-3.3cvs/include/c++/3.3
 /dept/rnd/vendor/gcc-3.3cvs/include/c++/3.3/i686-pc-linux-gnu
 /dept/rnd/vendor/gcc-3.3cvs/include/c++/3.3/backward
 /usr/local/include
 /dept/rnd/vendor/gcc-3.3cvs/include
 /dept/rnd/vendor/gcc-3.3cvs/lib/gcc-lib/i686-pc-linux-gnu/3.3/include
 /usr/include
End of search list.
foo.C: In constructor `B::B(const D2&)':
foo.C:20: internal compiler error: in fixup_abnormal_edges, at reload1.c:9498
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://www.gnu.org/software/gcc/bugs.html> for instructions.

A small test case demonstrating this is attached.

This bug may be related to the previously reported
fixup_abnormal_edges optimization bugs triggered
with gcj compiles - 6581 and 4571.

PR 5785 was a duplicate of this PR.

Release:
gcc-3.2.2, gcc version 3.3 20030220 (prerelease)

Environment:
x86 redhat-7.2 with current updates

How-To-Repeat:
g++ -fnon-call-exceptions -Wall -O2 -c foo.C -o foo.o
Comment 1 Wolfgang Bangerth 2003-02-21 02:05:44 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Confirmed for 3.2.2, 3.3 and 3.4 branches. Used to work
    in 3.0, so is a regression.[
Comment 2 Jason Merrill 2003-03-13 18:24:37 UTC
State-Changed-From-To: open-analyzed
State-Changed-Why: To compute 0.299*l, gcc generates this code to load l:

(insn 63 62 64 (nil) (set (reg:SF 74)
        (mem/s:SF (reg/v/f:SI 69 [ this ]) [13 <variable>.l+0 S4 A32])) -1 (nil)
    (nil))

(insn 64 63 65 (nil) (set (reg:DF 73)
        (float_extend:DF (reg:SF 74))) -1 (nil)
    (nil))

Both of these are deemed to possibly trap, since they involve floating
point math, so they go in separate basic blocks.  By .32.bbro, we have

(insn 63 216 167 2 0x402a2a24 (set (reg:SF 8 st(0) [orig:74 <variable>.l ] [74])
        (mem/s:SF (reg/v/u/f:SI 0 eax [orig:59 mi ] [59]) [13 <variable>.l+0 S4 A32])) 62 {*movsf_1} (insn_list 216 (nil))
    (expr_list:REG_DEAD (reg/v/u/f:SI 0 eax [orig:59 mi ] [59])
        (expr_list:REG_EH_REGION (const_int 2 [0x2])
            (nil))))
;; End of basic block 2, registers live:
 1 [dx] 6 [bp] 7 [sp] 8 [st] 16 [] 20 [frame]

;; Start of basic block 3, registers live: 1 [dx] 6 [bp] 7 [sp] 8 [st] 16 [] 20 [frame]
(note 167 63 64 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(insn 64 167 168 3 0x402a2a24 (set (reg:DF 8 st(0) [73])
        (float_extend:DF (reg:SF 8 st(0) [orig:74 <variable>.l ] [74]))) 93 {*extendsfdf2_1} (nil)
    (expr_list:REG_EH_REGION (const_int 2 [0x2])
        (nil)))
;; End of basic block 3, registers live:
 1 [dx] 6 [bp] 7 [sp] 8 [st] 16 [] 20 [frame]

Next, the reg-stack pass decides that insn 64 is a no-op and deletes it.
But that leaves bb3 as an empty basic block with an EH edge, which doesn't
make any sense, and fixup_abnormal_edges aborts.

Is it actually possible for a float_extend to trap?  If not, the simple fix
is to teach may_trap_p about that.  Otherwise, we need to delete the edge
somewhere along the way.
Comment 3 Jason Merrill 2003-03-13 23:03:00 UTC
Responsible-Changed-From-To: unassigned->jason
Responsible-Changed-Why: i'll take a look
Comment 4 Jason Merrill 2003-03-13 23:30:54 UTC
State-Changed-From-To: analyzed->open
State-Changed-Why: an->an
Comment 5 Jason Merrill 2003-03-14 00:28:41 UTC
Responsible-Changed-From-To: jason->unassigned
Responsible-Changed-Why: rth says that extending a NaN can trap, so we can't just
    change may_trap_p.  So someone else will need to deal.
Comment 6 nick 2003-04-01 11:48:54 UTC
From: Nick Rasmussen <nick@ilm.com>
To: Cc: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Subject: Re: optimization/9786: [3.2/3.3/3.4 regression] Ice in fixup_abnormal_edges
 with -fnon-call-exceptions -O2
Date: Tue, 01 Apr 2003 11:48:54 -0800

 I've already traced down what triggered the ICE:
 
 http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00025.html
 
 And got a reply from Jan Hubicka:
 
 http://gcc.gnu.org/ml/gcc-bugs/2003-03/msg00034.html
 
 It looks like it just didn't get attached to the gnats entry.
 
 -nick
 
 (resend - first reply got spamblocked by the list filters)
 
 Steven Bosscher wrote:
 > http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=9786 
 > 
 > 
 > Janis, this PR is a regression in 3.2, 3.3-to-be and mainline
 > from 3.0, but the breaking patch has not been identified yet.
 > Can you hunt it down?
 > 
 > For me this ICE triggers on i[56]86-pc-linux-gnu with:
 > 
 >    gcc-3.3 -c 9786.cc -fnon-call-exceptions -O -fforce-mem
 > 
 > Without -fforce-mem the ICE does not happen.
 > 
 > Greetz
 > Steven
 >
Comment 7 s.bosscher 2003-04-01 20:30:42 UTC
From: Steven Bosscher <s.bosscher@student.tudelft.nl>
To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org,
	nick@ilm.com, gcc-prs@gcc.gnu.org, janis187@us.ibm.com
Cc:  
Subject: Re: optimization/9786: [3.2/3.3/3.4 regression] Ice in fixup_abnormal_edges
 with -fnon-call-exceptions -O2
Date: Tue, 01 Apr 2003 20:30:42 +0200

 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=9786
 
 Janis, this PR is a regression in 3.2, 3.3-to-be and mainline
 from 3.0, but the breaking patch has not been identified yet.
 Can you hunt it down?
 
 For me this ICE triggers on i[56]86-pc-linux-gnu with:
 
     gcc-3.3 -c 9786.cc -fnon-call-exceptions -O -fforce-mem
 
 Without -fforce-mem the ICE does not happen.
 
 Greetz
 Steven
 
 

Comment 8 George T. Talbot 2003-05-30 19:24:03 UTC
For what it's worth, -mfpmath=sse -msse2 makes this go away for me when
compiling my application, as it uses the SSE instructions instead.  Of course
you don't get the 80-bit accumulators of the x87, and can only be used on later
CPU's with SSE instruction units.
Comment 9 George T. Talbot 2003-05-30 19:39:47 UTC
One other thing.  I just submitted another bug, 11038, for a similar problem,
with a very very short test case (<10 lines).  Are these two related?
Comment 10 Andrew Pinski 2003-07-12 00:23:59 UTC
Still happens on the mainline (20030711).
Comment 11 Eric Botcazou 2003-07-18 07:36:53 UTC
A patch is available here for mainline:
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01772.html
Comment 12 Mark Mitchell 2003-07-22 18:41:26 UTC
I'm confused.

Olivier's message says:

> I first thought that deletion of trapping insns should not occur in the first
> place, but the insn is known to be a no-op there so this seems OK.

I'm not sure that this is OK.  In particular, the instruction shown is:

    (insn 21 19 87 2 (set (reg:DF 8 st(0) [63])
            (float_extend:DF (reg:SF 8 st(0)))) 136 {*extendsfdf2_1} (nil)
        (expr_list:REG_EH_REGION (const_int 1 [0x1])
            (nil)))

In an earlier piece of this audit trail, Jason says that Richard says that if
the value were a NaN this would trap.

Is the point that we do not end up actually generating an x86 instruction for
this operation because we realize that the source and destination register are
the same?  But wouldn't that be wrong, in that we're then throwing a potential
exception that was perhaps implied by the source program?

If it is OK to delete these instructions, then Olivier's patch looks OK to me,
except that the ??? comment should be updated.  If it is not OK to delete these
instructions, then we need to stop reg-stack from doing that.

Ideas?
Comment 13 Olivier Hainque 2003-07-24 07:40:43 UTC
Subject: Re:  [3.3/3.4 regression] Ice in fixup_abnormal_edges with -fnon-call-exceptions -O2


mmitchel at gcc dot gnu dot org wrote:
> I'm not sure that this is OK.  In particular, the instruction shown is:
> 
>     (insn 21 19 87 2 (set (reg:DF 8 st(0) [63])
>             (float_extend:DF (reg:SF 8 st(0)))) 136 {*extendsfdf2_1} (nil)
>         (expr_list:REG_EH_REGION (const_int 1 [0x1])
>             (nil)))
> 
> In an earlier piece of this audit trail, Jason says that Richard says that if
> the value were a NaN this would trap.
 
> Is the point that we do not end up actually generating an x86 instruction
> for this operation because we realize that the source and destination
> register are the same?

 In this case, yes, right after this comment in move_for_stack_reg:

      /* If this appears to be a no-op move, delete it, or else it
	 will confuse the machine description output patterns. 

      if (REGNO (src) == REGNO (dest))

 There are other cases in which some insn may be deleted though (just above
 this comment).

 However,

 - another comment, in the caller (subst_stack_regs), mentions again that
   deletions are performed for no-ops:

  /* subst_stack_regs_pat may have deleted a no-op insn.  If so, any
     REG_UNUSED will already have been dealt with, so just return.  */

 and

 - the file head comment provides a hint that deletions performed in this
   pass are safe because they relate to insns handling *virtual* stack
   registers:

   [...] After the hard register numbers are substituted, the semantics of an
   insn containing stack-like regs are not the same as for an insn with normal
   regs: for instance, it is not safe to delete an insn that appears to be a
   no-op move.

> But wouldn't that be wrong, in that we're then throwing a potential
> exception that was perhaps implied by the source program?

 I'm not sure, which is why I initially asked for advices and ended up with
 a note together with the patch submission.

 The audit trail mentions:

    rth says that extending a NaN can trap, so we can't just
    change may_trap_p. 
 
 It's not quite clear to me if there are conditions in which it couldn't
 trap, and I trusted the "no-op" qualifiers in the comments mentioned above
 in that respect.

 This code is pretty old, tough, so it is possible that the considerations
 we deal with today were not accounted for at that time.

> If it is OK to delete these instructions, then Olivier's patch looks OK to
> me, except that the ??? comment should be updated.  If it is not OK to
> delete these instructions, then we need to stop reg-stack from doing that.
 
 Agreed.

> Ideas?
 
 Does the additional input above ring a bell for anyone ?

 In any case, I think the comments will have to be updated to be more explicit
 on this issue.

 Thanks for your feedback.

 Olivier


 
Comment 14 Mark Mitchell 2003-08-03 16:01:46 UTC
Postponed until GCC 3.3.2.
Comment 15 Olivier Hainque 2003-08-28 00:34:59 UTC
Subject: Re:  [3.3/3.4 regression] Ice in fixup_abnormal_edges with -fnon-call-exceptions -O2


> > If it is OK to delete these instructions, then Olivier's patch looks OK to
> > me, except that the ??? comment should be updated.  If it is not OK to
> > delete these instructions, then we need to stop reg-stack from doing that.

 I thought a bit more about this, and am still unclear wether it is indeed
 appropriate for reg-stack to delete these insns.

 Since those deletions have always been there, could we consider fixing them
 by updating the edges too, and file another PR to investigate the possible
 (different) problem these deletions might cause with respect to exception 
 handling issues ?

 FWIW, merely removing the deletion leads to blowup at build time, which seems
 in accordance with what the associated comment says.

 Olivier


 
Comment 16 Eric Botcazou 2003-09-17 13:20:29 UTC
Trying to get a definitive assessment for Olivier's patch.
Comment 17 Eric Botcazou 2003-09-18 06:56:14 UTC
Olivier's patch applies cleanly (with a few offsets) to the 3.3 branch and cures
the regression.
Comment 18 GCC Commits 2003-09-22 06:59:55 UTC
Subject: Bug 9786

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	ebotcazou@gcc.gnu.org	2003-09-22 06:59:51

Modified files:
	gcc            : ChangeLog reg-stack.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/opt: reg-stack2.C 

Log message:
	PR target/9786
	* reg-stack.c (convert_regs_1): Purge possible dead eh edges
	after potential deletion of trapping insn. Avoids later ICE
	from call to fixup_abnormal_edges.
	(convert_regs_2): Stack the current block successors before
	processing this block, that is, before the potential deletion of
	dead edges by convert_regs_1, because these edges have been used
	to initialize the predecessors count.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.1116&r2=2.1117
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/reg-stack.c.diff?cvsroot=gcc&r1=1.132&r2=1.133
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3075&r2=1.3076
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/reg-stack2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 19 GCC Commits 2003-09-22 07:11:31 UTC
Subject: Bug 9786

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_3-branch
Changes by:	ebotcazou@gcc.gnu.org	2003-09-22 07:11:27

Modified files:
	gcc            : ChangeLog reg-stack.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/opt: reg-stack2.C 

Log message:
	PR target/9786
	* reg-stack.c (convert_regs_1): Purge possible dead eh edges
	after potential deletion of trapping insn. Avoids later ICE
	from call to fixup_abnormal_edges.
	(convert_regs_2): Stack the current block successors before
	processing this block, that is, before the potential deletion of
	dead edges by convert_regs_1, because these edges have been used
	to initialize the predecessors count.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.16114.2.749&r2=1.16114.2.750
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/reg-stack.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.117.2.3&r2=1.117.2.4
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.2261.2.285&r2=1.2261.2.286
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/reg-stack2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1

Comment 20 Eric Botcazou 2003-09-22 07:14:57 UTC
I've applied Olivier's patch.