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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2024-07-01
     Ever confirmed|0                           |1
                 CC|                            |rsandifo at gcc dot gnu.org,
                   |                            |segher at gcc dot gnu.org
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed.  The interesting thing is that the non-volatile case has the
(subreg:QI (reg:HI ...)) in the store right from expansion but the volatile
case has the subreg split out initially:

(insn 10 9 11 2 (set (reg:QI 45 [ _3 ])
        (subreg:QI (reg:HI 50 [ _2 ]) 0)) "t.c":13:9 86 {movqi_insn_split}
     (nil))
(insn 11 10 0 2 (set (mem/v/c:QI (symbol_ref:HI ("vol") [flags 0x2]  <var_decl
0x7ffff6959090 vol>) [0 vol+0 S1 A8])
        (reg:QI 45 [ _3 ])) "t.c":13:9 86 {movqi_insn_split}
     (nil))

and CSE1 "combines" those to

(insn 11 10 0 2 (set (mem/v/c:QI (symbol_ref:HI ("vol") [flags 0x2]  <var_decl
0x7ffff6959090 vol>) [0 vol+0 S1 A8])
        (subreg:QI (reg:HI 50 [ _2 ]) 0)) "t.c":13:9 86 {movqi_insn_split}
     (expr_list:REG_DEAD (reg:QI 45 [ _3 ])
        (nil)))

and yes, combine doesn't consider combining into volatile instructions by
means of calling init_recog_no_volatile () which results in

Trying 9 -> 11:
    9: r50:HI=r51:HI<<r48:QI
      REG_DEAD r51:HI
      REG_DEAD r48:QI
      REG_EQUAL 0x1<<r48:QI
   11: [`vol']=r50:HI#0
      REG_DEAD r50:HI
Failed to match this instruction:
(set (mem/v/c:QI (symbol_ref:HI ("vol") [flags 0x2]  <var_decl 0x7ffff6959090
vol>) [0 vol+0 S1 A8])
    (subreg:QI (ashift:HI (reg:HI 51)
            (reg:QI 48 [ x_5 ])) 0))

compared to the non-volatile case which does

Trying 9 -> 10:
    9: r50:HI=r51:HI<<r48:QI
      REG_DEAD r51:HI
      REG_DEAD r48:QI
      REG_EQUAL 0x1<<r48:QI
   10: [`val']=r50:HI#0
      REG_DEAD r50:HI
Successfully matched this instruction:
(set (mem/c:QI (symbol_ref:HI ("val") [flags 0x2]  <var_decl 0x7ffff6959000
val>) [0 val+0 S1 A8])
    (subreg:QI (ashift:HI (reg:HI 51)
            (reg:QI 48 [ x_5 ])) 0))

I'm quite sure the combine restriction is overly pessimistic here (of
course with the argument that volatile is hands-off - but then we shouldn't
combine the subreg into its RHS either).

I fear improving combine is difficult (disabling init_recog_no_volatile
around the final store insn after checking only the original non-modified
parts have a volatile flag?), but let's ask Segher.

-fdisable-rtl-cse1 -fdisable-rtl-cse2 -fdisable-rtl-fwprop1
-fdisable-rtl-fwprop2 makes us optimize this OK, so it seems disallowing those
passes
to put the subreg into the volatile insn would resolve this.

I'm not sure about RTL "volatile" semantics but maybe combine could split
the volatile again?  Does it need a define_split for this?

Reply via email to