Bug 22002 - [4.0 Regression] internal consistency failure with -funroll-loops
Summary: [4.0 Regression] internal consistency failure with -funroll-loops
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.3
Assignee: Alan Modra
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2005-06-10 14:03 UTC by marcus
Modified: 2005-11-15 01:05 UTC (History)
5 users (show)

See Also:
Host:
Target: powerpc64-*-*
Build:
Known to work: 4.1.0 3.4.0
Known to fail: 4.0.0 4.0.1
Last reconfirmed: 2005-11-08 23:19:44


Attachments
legendre_poly.i (203 bytes, text/plain)
2005-06-10 14:04 UTC, marcus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description marcus 2005-06-10 14:03:57 UTC
the following attached testcase triggers a compiler error on powerpc64 with 
-funroll-loops only: 
 
gcc   -O2  -funroll-loops  -c legendre_poly.i   
legendre_poly.i: In function ‘f’: 
legendre_poly.i:15: fatal error: internal consistency failure 
compilation terminated. 
 
it is extracted from "gsl".
Comment 1 marcus 2005-06-10 14:04:40 UTC
Created attachment 9060 [details]
legendre_poly.i

gcc   -O2  -funroll-loops  -c legendre_poly.i
Comment 2 Andrew Pinski 2005-06-10 14:13:38 UTC
Only happens in 4.0.x.

Works fine in 4.1.0.  Testing the 4.0.x branch right now.
Comment 3 Andrew Pinski 2005-06-10 14:14:42 UTC
Confirmed, still fails in 4.0.1.
Comment 4 Mark Mitchell 2005-07-06 17:02:08 UTC
Postponed until 4.0.2.
Comment 5 Janis Johnson 2005-09-16 19:14:54 UTC
The test case passes on mainline starting with this patch from dje:

  http://gcc.gnu.org/ml/gcc-cvs/2005-03/msg01221.html
Comment 6 Alan Modra 2005-11-08 12:58:27 UTC
Looks like combine is not updating reg life info.

(gdb) set var dump_file=stderr
(gdb) n
(gdb) 
Register 137 died unexpectedly.
(gdb) 
;; basic block 6, loop depth 0, count 0
;; prev block 5, next block 7
;; pred:       5 [50.0%]  (fallthru)
;; succ:       7 [100.0%]  (fallthru)
;; Registers live at start:  1 [1] 31 [31] 67 [ap] 128 134 137 139 141 151
[snip]

==== pr22002.i.16.life
;; Start of basic block 6, registers live: 1 [1] 31 [31] 67 [ap] 128 134 137 139 141 151
(note 136 145 118 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

(insn 118 136 120 6 (set (reg:DF 127 [ D.1135 ])
        (reg:DF 137)) 285 {*movdf_hardfloat64} (nil)
    (expr_list:REG_DEAD (reg:DF 137)
        (expr_list:REG_EQUAL (const_double:DF 2.0e+0 [0x0.8p+2])
            (nil))))

[snip]
(insn 123 122 124 6 (set (reg:DF 141)
        (mult:DF (reg:DF 127 [ D.1135 ])
            (reg:DF 141))) 179 {*muldf3_fpr} (insn_list:REG_DEP_TRUE 118 (nil))
    (expr_list:REG_DEAD (reg:DF 127 [ D.1135 ])
        (expr_list:REG_EQUAL (const_double:DF 2.5132741228718344927983707748353481292724609375e+1 [0x0.c90fdaa22168cp+5])
            (nil))))

====== pr22002.i.17.combine
;; Start of basic block 6, registers live: 1 [1] 31 [31] 67 [ap] 128 134 137 139 141 151
(note 136 145 118 6 [bb 6] NOTE_INSN_BASIC_BLOCK)

(note 118 136 120 6 NOTE_INSN_DELETED)

[snip]
(insn 123 122 124 6 (set (reg:DF 141)
        (plus:DF (reg:DF 141)
            (reg:DF 141))) 177 {*adddf3_fpr} (nil)
    (expr_list:REG_EQUAL (const_double:DF 2.5132741228718344927983707748353481292724609375e+1 [0x0.c90fdaa22168cp+5])
        (nil)))

(note 124 123 125 6 NOTE_INSN_DELETED)

Comment 7 Alan Modra 2005-11-08 23:19:44 UTC
I snipped too much of the dumps.  The problem is that after reg 137 dies in insn 118, it is set, and dies again before insn 123.  When combine tries to find a place for the death note on insn 118, it can't put it on the new (deleted) insn 118, nor on the new insn 123 (because reg 137 isn't used there).  Instead, combine searches back *from insn 123* looking for a suitable place.  It finds the other insn where reg 137 dies, and decides nothing more need be done.  Testing the following:

	PR rtl-optimization/22002
	* combine.c (distribute_notes): Search back for a suitable place
	for a death note from "from_insn", not "i3".

Index: gcc/combine.c
===================================================================
--- gcc/combine.c	(revision 106635)
+++ gcc/combine.c	(working copy)
@@ -12106,7 +12106,9 @@ distribute_notes (rtx notes, rtx from_in
 	    {
 	      basic_block bb = this_basic_block;
 
-	      for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
+	      for (tem = PREV_INSN (from_insn);
+		   place == 0;
+		   tem = PREV_INSN (tem))
 		{
 		  if (! INSN_P (tem))
 		    {
Comment 8 Alan Modra 2005-11-09 00:25:59 UTC
Uggh, that was too simplistic.  We really do need to search back from i3 in other cases, eg. when combine extends a reg lifetime.  It seems that we need to check for other sets of a dead reg between from_insn and i3.
Comment 9 Alan Modra 2005-11-15 00:59:26 UTC
Subject: Bug 22002

Author: amodra
Date: Tue Nov 15 00:59:21 2005
New Revision: 106921

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=106921
Log:
	PR rtl-optimization/22002
	* combine.c (distribute_notes): Detect cases where a reg dies
	two or more times in a bb, including on the insn we are combining,
	and place the death note on the correct range.


Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/combine.c

Comment 10 Alan Modra 2005-11-15 01:00:17 UTC
Subject: Bug 22002

Author: amodra
Date: Tue Nov 15 01:00:09 2005
New Revision: 106922

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=106922
Log:
	PR rtl-optimization/22002
	* combine.c (distribute_notes): Detect cases where a reg dies
	two or more times in a bb, including on the insn we are combining,
	and place the death note on the correct range.


Modified:
    branches/gcc-4_0-branch/gcc/ChangeLog
    branches/gcc-4_0-branch/gcc/combine.c

Comment 11 Alan Modra 2005-11-15 01:05:38 UTC
Fixed on mainline and 4.0 branch