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".
Created attachment 9060 [details] legendre_poly.i gcc -O2 -funroll-loops -c legendre_poly.i
Only happens in 4.0.x. Works fine in 4.1.0. Testing the 4.0.x branch right now.
Confirmed, still fails in 4.0.1.
Postponed until 4.0.2.
The test case passes on mainline starting with this patch from dje: http://gcc.gnu.org/ml/gcc-cvs/2005-03/msg01221.html
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)
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)) {
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.
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
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
Fixed on mainline and 4.0 branch