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