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

            Bug ID: 86939
           Summary: IRA incorrectly creates an interference between a
                    pseudo register and a hard register
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bergner at gcc dot gnu.org
  Target Milestone: ---

IRA incorrectly creates an interference between a pseudo register and a hard
register that should not interfere, leading to an extra register copy that is
not needed:

bergner@pike:~/gcc/BUGS$ cat bug.i
typedef long (*fptr_t) (void);
long
func (fptr_t *p)
{
  if (p)
    return (*p) ();
  return 0;
}

bergner@pike:~/gcc/BUGS$
/home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc/xgcc
-B/home/bergner/gcc/build/gcc-fsf-mainline-debug/gcc -O2 -S bug.i
bergner@pike:~/gcc/BUGS$ cat bug.s 
[snip]
        ld 9,0(9)
        std 2,24(1)
        mtctr 9
        mr 12,9
        bctrl

The indirect call above requires r12 to be set before the bctrl, but we should
have just loaded its value directly into r12 instead of into r9.  Looking at
the RTL during IRA, we have:

(insn 10 34 11 3 (set (reg/f:DI 125 [ *p_4(D) ])
        (mem/f:DI (reg/v/f:DI 127 [orig:123 pD.2807 ] [123]) [1 *p_4(D)+0 S8
A64])) "bug.i":6 608 {*movdi_internal64}
     (expr_list:REG_DEAD (reg/v/f:DI 127 [orig:123 pD.2807 ] [123])
        (nil)))
(insn 11 10 12 3 (set (reg:DI 12 12)
        (reg/f:DI 125 [ *p_4(D) ])) "bug.i":6 608 {*movdi_internal64}
     (nil))
(call_insn 12 11 13 3 (parallel [
            (set (reg:DI 3 3) 
                (call (mem:SI (reg/f:DI 125 [ *p_4(D) ]) [0 *_1 S4 A8])
                    (const_int 0 [0])))
            (set (reg:DI 2 2)
                (unspec:DI [
                        (const_int 24 [0x18])
                    ] UNSPEC_TOCSLOT))
            (clobber (reg:DI 65 lr))
        ]) "bug.i":6 691 {*call_value_indirect_elfv2di}
     (expr_list:REG_DEAD (reg/f:DI 125 [ *p_4(D) ])
        (expr_list:REG_DEAD (reg:DI 12 12)
            (expr_list:REG_CALL_DECL (nil)
                (nil))))
    (expr_list (use (reg:DI 12 12))
        (nil)))
(insn 13 12 31 3 (set (reg:DI 122 [ <retval> ])
        (reg:DI 3 3)) "bug.i":6 608 {*movdi_internal64}
     (expr_list:REG_DEAD (reg:DI 3 3)
        (nil)))
(jump_insn 31 13 32 3 (set (pc)
        (label_ref 18)) "bug.i":6 780 {jump}
     (nil)
 -> 18)

and:

      Allocno a1r125 of GENERAL_REGS(29) has 28 avail. regs  0 3-11 14-31,
node:  0 3-11 14-31 (confl regs =  1 2 12 13 32-113)

Now pseudo 125 is live when r12 is defined, which is normally enough to make
two regs/pseudos interfere, but since they have the same value, an interference
should not be created between them.  If we can stop the interference from being
generated, then we should get the allocation and code generated that we want.

Reply via email to