https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116778

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Denis Chertykov <den...@gcc.gnu.org>:

https://gcc.gnu.org/g:279b3c71702de150eade19635bdbd26ba440b8eb

commit r15-6008-g279b3c71702de150eade19635bdbd26ba440b8eb
Author: Denis Chertykov <cherty...@gmail.com>
Date:   Sat Dec 7 13:47:04 2024 +0400

    The fix for PR116778:

    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.

    Part of the expression `a.u33 * a.u33'
    Before LRA:
    *************************************************************
    (insn 13 11 15 2 (set (reg:QI 184 [ _1+3 ])
            (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 15 13 16 2 (set (reg:QI 64 [ a+4 ])
            (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 20 2 (set (reg:QI 185 [ _1+4 ])
            (zero_extract:QI (reg:QI 64 [ a+4 ])
                (const_int 1 [0x1])
                (const_int 0 [0]))) "bf.c":11:8 985 {*extzvqi_split}
         (nil))
    *************************************************************

    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: ********

    df_worklist_dataflow_doublequeue: n_basic_blocks 14 n_edges 18 count 14 (  
 1)
    df_worklist_dataflow_doublequeue: n_basic_blocks 14 n_edges 18 count 14 (  
 1)

    Cands:
    0 (nop=0, remat_regno=185, reload_regno=359):
    (insn 16 15 572 2 (set (reg:QI 359 [orig:185 _1+4 ] [185])
                        (zero_extract:QI (reg:QI 64 [ a+4 ])
                            (const_int 1 [0x1])
                            (const_int 0 [0]))) "bf.c":11:8 985
{*extzvqi_split}
                     (nil))

   
**************************************************************************************
    [...]
   
**************************************************************************************
    Ranges after the compression:
     r185: [0..1]
               Frame pointer can not be eliminated anymore
               Spilling non-eliminable hard regs: 28 29
             Spilling r113(28)
             Spilling r184(29)
             Spilling r208(29)
             Spilling r209(28)
      Slot 0 regnos (width = 0):     185     209     208     184     113
   
**************************************************************************************

    The bug is here: `r185: [0..1]' wrong live range after compression.
    r185 and r184 can't have the same spill slot !

    Rematerialization in bf.c.317r.reload looks like:
    *************************************************************
       24: r14:QI=r185:QI
        Inserting rematerialization insn before:
      581: r14:QI=zero_extract(r64:QI,0x1,0)

    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.

Reply via email to