https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88796
Bug ID: 88796 Summary: -fstack-protector* kills RTL DSE opportunities Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: jakub at gcc dot gnu.org Target Milestone: --- Marek has noticed that the gcc.target/i386/pr87370.c testcase FAILs when built with -fstack-protector-strong ( make check-gcc RUNTESTFLAGS='--target_board=unix\{-m64,-m64/-fstack-protector-strong\} i386.exp=pr87370.c' ). It isn't a wrong-code, but seems quite severe anyway. Before the RTL DSE pass, the dumps look roughly comparable, except that there is the store to the stack canary at the beginning and read from the stack canary at the end of the function. In DSE dump for f2 function, one can see without -fstack-protector-strong: starting the processing of deferred insns ending the processing of deferred insns df_analyze called **scanning insn=5 mems_found = 0, cannot_delete = true **scanning insn=14 mem: (plus:DI (reg/f:DI 19 frame) (const_int -16 [0xfffffffffffffff0])) after canon_rtx address: (plus:DI (reg/f:DI 19 frame) (const_int -16 [0xfffffffffffffff0])) gid=0 offset=-16 processing const base store gid=0[-16..0) mems_found = 1, cannot_delete = false **scanning insn=11 mems_found = 0, cannot_delete = true **scanning insn=12 mems_found = 0, cannot_delete = false Locally deleting insn 14 deferring deletion of insn with uid = 14. group 0 is frame related group 0(16+0): n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 p starting the processing of deferred insns ending the processing of deferred insns df_analyze called df_worklist_dataflow_doublequeue: n_basic_blocks 3 n_edges 2 count 3 ( 1) but with -fstack-protector-strong instead: starting the processing of deferred insns ending the processing of deferred insns df_analyze called **scanning insn=4 mem: (const_int 40 [0x28]) after canon_rtx address: (const_int 40 [0x28]) after cselib_expand address: (const_int 40 [0x28]) after canon_rtx address: (const_int 40 [0x28]) varying cselib base=1:4426 offset = 0 processing cselib load mem:(mem/f:DI (const_int 40 [0x28]) [4 MEM[(<address-space-1> long unsigned int *)40B]+0 S8 A64 AS1]) mem: (plus:DI (reg/f:DI 19 frame) (const_int -8 [0xfffffffffffffff8])) after canon_rtx address: (plus:DI (reg/f:DI 19 frame) (const_int -8 [0xfffffffffffffff8])) gid=0 offset=-8 processing const base store gid=0[-8..0) mems_found = 1, cannot_delete = true **scanning insn=7 mems_found = 0, cannot_delete = true **scanning insn=24 mem: (plus:DI (reg/f:DI 19 frame) (const_int -32 [0xffffffffffffffe0])) after canon_rtx address: (plus:DI (reg/f:DI 19 frame) (const_int -32 [0xffffffffffffffe0])) gid=0 offset=-32 processing const base store gid=0[-32..-16) trying store in insn=4 gid=0[-8..0) mems_found = 1, cannot_delete = false **scanning insn=13 mems_found = 0, cannot_delete = true **scanning insn=15 mem: (const_int 40 [0x28]) after canon_rtx address: (const_int 40 [0x28]) after cselib_expand address: (const_int 40 [0x28]) after canon_rtx address: (const_int 40 [0x28]) varying cselib base=1:4426 offset = 0 processing cselib load mem:(mem/f:DI (const_int 40 [0x28]) [4 MEM[(<address-space-1> long unsigned int *)40B]+0 S8 A64 AS1]) processing cselib load against insn 24 removing from active insn=24 has store processing cselib load against insn 4 removing from active insn=4 has store adding wild read, volatile or barrier. mems_found = 0, cannot_delete = true **scanning insn=16 mems_found = 0, cannot_delete = true **scanning insn=17 mem: (symbol_ref:DI ("__stack_chk_fail") [flags 0x41] <function_decl 0x7f43b618b500 __stack_chk_fail>) after canon_rtx address: (symbol_ref:DI ("__stack_chk_fail") [flags 0x41] <function_decl 0x7f43b618b500 __stack_chk_fail>) gid=1 offset=0 processing const load gid=1[0..1) **scanning insn=20 mems_found = 0, cannot_delete = false group 0 is frame related group 0(24+0): n 1, 2, 3, 4, 5, 6, 7, 8, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 p group 1(0+0): n p starting the processing of deferred insns ending the processing of deferred insns df_analyze called doing global processing df_worklist_dataflow_doublequeue: n_basic_blocks 5 n_edges 4 count 5 ( 1) So, the (insn 15 13 16 2 (parallel [ (set (reg:CCZ 17 flags) (unspec:CCZ [ (mem/v/f/c:DI (plus:DI (reg/f:DI 19 frame) (const_int -8 [0xfffffffffffffff8])) [3 D.1950+0 S8 A64]) (mem/f:DI (const_int 40 [0x28]) [4 MEM[(<address-space-1> long unsigned int *)40B]+0 S8 A64 AS1]) ] UNSPEC_SP_TEST)) (clobber (scratch:DI)) ]) "pr87370.c":30:1 978 {stack_protect_test_di} (nil)) stack canary read invalidates the opportunity to remove the dead (insn 24 7 13 2 (set (mem/c:V1TI (plus:DI (reg/f:DI 19 frame) (const_int -32 [0xffffffffffffffe0])) [5 D.1928+0 S16 A128]) (reg:V1TI 86)) "pr87370.c":29:10 -1 (expr_list:REG_DEAD (reg:V1TI 86) (nil))) store. Any thoughts how we could arrange for RTL DSE to understand how the ssp set and test patterns work and the test pattern only makes the ssp canary set insn necessary and no other stores?