cudcv@warwick.ac.uk (Rob McMahon) (09/25/88)
GCC 1.28, Gould PN6030 I hope I can explain this coherently, I'm sorry I can't give a test program. During the first scan in reload, find_reloads can find a required value via find_equiv_reg which is no longer available during the second scan in reload_as_needed, due to reloads having taken place (optional in the case that I hit). If this means a block which didn't appear to need reloads first time round now needs a reload, this can mean there is no spill reg available for it, and the compiler aborts at the new test in reload_as_needed marked by the comment: /* If this block has not had spilling done, ... If we have any non-optionals that need a spill reg, abort. */ The change I've made to get me going is to make find_equiv_reg ignore instructions with reloads pending, around line 2499 in reload.c: p = PREV_INSN (p); if (p == 0 || GET_CODE (p) == CODE_LABEL) return 0; => if (GET_CODE (p) == INSN /* If we don't want spill regs (true for all calls in this file) */ && (! (reload_reg_p != 0 && reload_reg_p != (short *)1) by changing the marked line to be if (GET_CODE (p) == INSN && GET_MODE (p) == VOIDmode but I think this may be over conservative. Here are some commented excerpts from the .lreg file to show what I mean. FIRST_PSEUDO_REGISTER is 19. | Register 21 used 7 times across 50 insns; dies in 4 places; crosses calls; | pointer. | Register 23 used 11 times across 118 insns; dies in 4 places; crosses calls; | pref INDEX_REGS; pointer. | Register 30 used 2 times across 2 insns in block 1; GP_REGS or none. | | Basic block 0: first insn 3, last 24. | Registers live at start: 10 16 | | Basic block 1: first insn 25, last 29. | Registers live at start: 10 16 19 20 21 23 24 25 | | ;; Register 30 in 0. reload then assigns: reg_renumber[21] = 7 reg_renumber[23] = -1 reg_renumber[30] = 0 | (insn 5 4 6 (set (reg/v:SI 23) | (mem:SI (plus:SI (reg:SI 18) (const_int 8)))) 40 (nil) | (expr_list (mem:SI (plus:SI (reg:SI 18) (const_int 8))) (nil))) insn 5 gets output reload for reg 23 | (insn 8 7 9 (set (reg/v:SI 21) | (reg/v:SI 23)) 40 (insn_list 5 (nil)) | (nil)) insn 8 gets optional input reload for reg 23 basic block 0 needs reloads. | (insn 27 25 28 (set (reg:SI 30) | (zero_extend:SI (mem/s:QI (plus:SI (reg/v:SI 23) | (const_int 12))))) 55 (insn_list 25 (nil)) | (expr_list:TI (zero_extend:SI (reg:QI 29)) (nil))) insn 27 gets reload of reg 23 but finds reg 7 (was pseudo-reg 21) is equivalent due to insn 8, so basic block 1 needs no reloads. in reload_as_needed insn 5 gets reg 3 for its output reload, and becomes | (insn:QI 5 4 341 (set (reg:SI 3) | (mem:SI (plus:SI (reg:SI 18) (const_int 8)))) 40 (nil) | (expr_list (mem:SI (plus:SI (reg:SI 18) (const_int 8))) (nil))) | | (insn 341 5 6 (set (reg/v:SI 23) | (reg:SI 3)) -1 (nil) | (expr_list:QI (reg:SI 3) (nil))) insn 8 takes up on its optional reload, finding reg 23 still around in reg 3, and becomes | (insn:QI 8 7 9 (set (reg/v:SI 7) | (reg:SI 3)) 40 (insn_list 5 (nil)) | (nil)) insn 27 now can't find an equivalent. insn 8 is not what it was, insn 341 is unusable because it is a reload insn. So the instruction suddenly needs a reload, but basic_block_needs is 0 for this block, so reload_as_needed aborts. Hope this isn't too incomprehensible. Rob -- UUCP: ...!mcvax!ukc!warwick!cudcv PHONE: +44 203 523037 JANET: cudcv@uk.ac.warwick ARPA: cudcv@warwick.ac.uk Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England