[Bug target/89965] [8/9 Regression] wrong code with -O -mtune=nano-x2 -fcaller-saves -fexpensive-optimizations -fno-tree-dce -fno-tree-ter
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Tue Apr 9 17:16:00 GMT 2019
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89965
--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, we have:
(insn 41 40 42 6 (parallel [
(set (reg/v:DI 101 [ i ])
(lshiftrt:DI (reg/v:DI 118 [ i ])
(const_int 7 [0x7])))
(clobber (reg:CC 17 flags))
]) "pr89965.c":9 574 {*lshrdi3_doubleword}
(expr_list:REG_DEAD (reg/v:DI 118 [ i ])
(expr_list:REG_UNUSED (reg:CC 17 flags)
(expr_list:REG_EQUIV (mem:DI (reg/f:SI 7 sp) [0 S8 A32])
(nil)))))
(insn 42 41 43 6 (set (reg:QI 89 [ _3 ])
(subreg:QI (reg/v:DI 101 [ i ]) 0)) "pr89965.c":10 88 {*movqi_internal}
(nil))
(insn 43 42 44 6 (parallel [
(set (reg/v:QI 102 [ c ])
(mult:QI (reg:QI 89 [ _3 ])
(subreg:QI (reg:SI 111 [ c ]) 0)))
(clobber (reg:CC 17 flags))
]) "pr89965.c":10 351 {*mulqi3_1}
(expr_list:REG_DEAD (reg:SI 111 [ c ])
(expr_list:REG_DEAD (reg:QI 89 [ _3 ])
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil)))))
(insn 44 43 45 6 (set (mem:DI (plus:SI (reg/f:SI 7 sp)
(const_int 8 [0x8])) [0 S8 A32])
(const_int 12 [0xc])) "pr89965.c":11 85 {*movdi_internal}
(nil))
(insn 45 44 46 6 (set (mem:DI (reg/f:SI 7 sp) [0 S8 A32])
(reg/v:DI 101 [ i ])) "pr89965.c":11 85 {*movdi_internal}
(expr_list:REG_DEAD (reg/v:DI 101 [ i ])
(nil)))
(call_insn/u 46 45 49 6 (set (reg:DI 0 ax)
(call (mem:QI (symbol_ref:SI ("__udivdi3") [flags 0x41]) [0 S1 A8])
(const_int 16 [0x10]))) "pr89965.c":11 699 {*call_value}
(expr_list:REG_UNUSED (reg:DI 0 ax)
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil)))
(expr_list (use (mem:DI (reg/f:SI 7 sp) [0 S8 A8]))
(expr_list (use (mem:DI (plus:SI (reg/f:SI 7 sp)
(const_int 8 [0x8])) [0 S8 A8]))
(nil))))
before RA (and the __udivdi3 call is actually dead - ax after it is not used.
Note the result of i >> 7 is first used in the multiplication and later stored
into the argument slot of the call.
Now, RA decides for some reason to first push the i >> 7 into the stack slot
and then load the single byte from it for the purpose of the multiplication:
(insn 41 116 118 6 (parallel [
(set (reg/v:DI 0 ax [orig:101 i ] [101])
(lshiftrt:DI (reg/v:DI 0 ax [orig:101 i ] [101])
(const_int 7 [0x7])))
(clobber (reg:CC 17 flags))
]) "pr89965.c":9 574 {*lshrdi3_doubleword}
(expr_list:REG_EQUIV (mem:DI (reg/f:SI 7 sp) [0 S8 A32])
(nil)))
(insn 118 41 42 6 (set (mem:DI (reg/f:SI 7 sp) [0 S8 A32])
(reg/v:DI 0 ax [orig:101 i ] [101])) "pr89965.c":9 85 {*movdi_internal}
(nil))
(insn 42 118 119 6 (set (reg:QI 6 bp [orig:89 _3 ] [89])
(mem:QI (reg/f:SI 7 sp) [0 S1 A32])) "pr89965.c":10 88
{*movqi_internal}
(nil))
...
Finally, rtl_dce pass has code to DCE not just dead const/pure calls, but also
their arguments, but unfortunately that code (find_call_stack_args) doesn't
seem to take into account that some code might read again from those arguments
(rather than only the call reading from those stack slots).
So I guess the question is, is what the RA did above ok? If yes, I think
find_call_stack_args needs to be changed to FOR_EACH_SUBRTX NONCONST walk the
SET_SRC (set) and if it finds a MEM that is argument slot, either punt
immediately, or remove those bits from sp_bytes, so that corresponding store
won't be set in arg_stores and we'll punt on that store.
More information about the Gcc-bugs
mailing list