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.