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?

Reply via email to