Brief:
The bug appears in LRA after rematerialization pass while creating live ranges.
File lra.cc:
*************************************************************
/* Now we know what pseudos should be spilled. Try to
rematerialize them first. */
if (lra_remat ())
{
/* We need full live info -- see the comment above. */
lra_create_live_ranges (lra_reg_spill_p, true);
*************************************************************
Wrong call `lra_create_live_ranges (lra_reg_spill_p, true)'
It have to be `lra_create_live_ranges (true, true)'.
The explanation:
**********************************
int main (void)
{
if (a.u33 * a.u33 != 0)
------^^^^^^^^^^^^^
goto abrt;
if (a.u33 * a.u40 * a.u33 != 0)
**********************************
The bug appears here.
After LRA:
*************************************************************
(insn 587 11 13 2 (set (reg:QI 24 r24 [368])
(mem/c:QI (const:HI (plus:HI (symbol_ref:HI ("a") [flags 0x2] <var_decl 0x7c866435d000 a>)
(const_int 3 [0x3]))) [1 a+3 S1 A8])) "bf.c":11:8 86 {movqi_insn_split}
(nil))
(insn 13 587 15 2 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [4 %sfp+1 S1 A8])
(reg:QI 24 r24 [368])) "bf.c":11:8 86 {movqi_insn_split}
(nil))
(insn 15 13 16 2 (set (reg:QI 6 r6 [orig:64 a+4 ] [64])
(mem/c:QI (const:HI (plus:HI (symbol_ref:HI ("a") [flags 0x2] <var_decl 0x7c866435d000 a>)
(const_int 4 [0x4]))) [1 a+4 S1 A8])) "bf.c":11:8 86 {movqi_insn_split}
(nil))
(insn 16 15 572 2 (set (reg:QI 24 r24 [orig:185 _1+4 ] [185])
(zero_extract:QI (reg:QI 6 r6 [orig:64 a+4 ] [64])
(const_int 1 [0x1])
(const_int 0 [0]))) "bf.c":11:8 985 {*extzvqi_split}
(nil))
(insn 572 16 20 2 (set (mem/c:QI (plus:HI (reg/f:HI 28 r28)
(const_int 1 [0x1])) [4 %sfp+1 S1 A8])
(reg:QI 24 r24 [orig:185 _1+4 ] [185])) "bf.c":11:8 86 {movqi_insn_split}
(nil))
*************************************************************
Insn 13 and insn 572 use sfp+1 as a spill slot, but in IRA pass it was a two
different pseudos r184 and r185.
Insns 13 use sfp+1 as a spill slot for r184
Insns 572 use the same slot for r185. It's wrong.
Here we have a rematerialization.
Fragment from bf.c.317r.reload:
**************************************************************************************
******** Rematerialization #1: ********
deleting insn with uid = 24.
Considering alt=0 of insn 16: (0) =r (1) rYil (2) n
overall=0,losers=0,rld_nregs=0
32: r22:QI=r185:QI
Inserting rematerialization insn before:
582: r22:QI=zero_extract(r64:QI,0x1,0)
deleting insn with uid = 32.
*************************************************************
It's happened because:
Fragment from lra.c (lra):
*************************************************************************
if (! live_p)
{
/* We need full live info for spilling pseudos into
registers instead of memory. */
lra_create_live_ranges (lra_reg_spill_p, true);
live_p = true;
}
/* We should check necessity for spilling here as the above live
range pass can remove spilled pseudos. */
if (! lra_need_for_spills_p ())
break;
/* Now we know what pseudos should be spilled. Try to
rematerialize them first. */
if (lra_remat ())
{
/* We need full live info -- see the comment above. */
lra_create_live_ranges (lra_reg_spill_p, true);
----------------------------------^^^^^^^^^^^^^^^
live_p = true;
*************************************************************************
The bug is here.
Rematerialization sometimes can be like spilling pseudos into registers.
582: r22:QI=zero_extract(r64:QI,0x1,0)
So, here we need a live ranges for all pseudos.
PS: the patch will not affect any target with usable definition of
TARGET_SPILL_CLASS hook.
PR target/116778
gcc/
* lra-lives.cc (complete_info_p): Clarification of the comment.
* lra.cc (lra): Create a full live info after rematerialization.