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

--- Comment #6 from Konstantinos Eleftheriou <konstantinos.eleftheriou at vrull 
dot eu> ---
(In reply to Drea Pinski from comment #5)
> (In reply to Konstantinos Eleftheriou from comment #3)
> > `store_bit_field_1` in `gcc/expmed.cc` may take the `gen_lowpart`
> > narrowing branch when its destination register's mode has no equal
> > integral mode (e.g. a multi-register vector tuple such as `V4x4BF`):
> > 
> > ```
> > opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0));
> > scalar_int_mode imode;
> > if (!op0_mode.exists (&imode) || imode != GET_MODE (op0))
> >   {
> >     if (MEM_P (op0))
> >       op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
> >                                           0, MEM_SIZE (op0));
> >     else if (!op0_mode.exists ())
> >       {
> >         ...
> > 
> >         /* Stack-temp branch: result is copied back into op0.  */
> >         rtx temp = assign_stack_temp (GET_MODE (op0),
> >                                       GET_MODE_SIZE (GET_MODE (op0)));
> >         emit_move_insn (temp, op0);
> >         store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value,
> >                            reverse, fallback_p, undefined_p);
> >         emit_move_insn (op0, temp);          /* <-- copy back  */
> >         return true;
> >       }
> >     else
> >       op0 = gen_lowpart (op0_mode.require (), op0);   /* <-- no copy back  
> > */
> >   }
> > 
> > return store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum,
> >                                  bitregion_start, bitregion_end,
> >                                  fieldmode, value, reverse, fallback_p);
> > ```
> > 
> > When `gen_lowpart` returns a fresh register (because the source mode
> > cannot be reinterpreted into the chosen integral mode via a valid
> > subreg), `store_integral_bit_field` writes the inserted value into
> > that fresh register.  The caller's `str_rtx` is never updated, so the
> > insertion is silently dropped.
> > 
> > The sibling `!op0_mode.exists()` branch already performs the
> > analogous copy-back via the stack-temp pattern (the final
> > `emit_move_insn (op0, temp)`).  The `gen_lowpart` branch is missing
> > that copy-back.
> > 
> > Suggested fix:
> > 
> > Mirror the stack-temp branch's copy-back at the end of
> > `store_bit_field_1`: after `store_integral_bit_field` returns, if the
> > register reached via `op0` differs from the one reached via
> > `str_rtx`, copy the value back into `str_rtx`.
> 
> This smells of LLM usage, please discuss such issue if you are using LLMs.
> My bet the problem is the caller to favoid-store-forwarding is doing
> something which store_bit_field is not expected to handle and the code
> calling store_bit_field* in asf should change.

ASF's output:                                                                   
```                                                                             
  Store forwarding detected:                                                    
  From: (insn 14 19 15 2 (set (mem/c:V4SI (plus:DI (reg/f:DI 64 sfp)            
                  (const_int -16 [0xfffffffffffffff0])) [0 MEM <char[1:32]>
[(void *)&v]+16 S16 A128])                                                      
          (reg:V4SI 143 [ MEM <char[1:32]> [(void *)data_24(D)]+16 ]))
"../testcase.c":26:14 discrim 1 1384 {*aarch64_simd_movv4si}                    
       (expr_list:REG_DEAD (reg:V4SI 143 [ MEM <char[1:32]> [(void
*)data_24(D)]+16 ])                                                             
          (nil)))                                                               
  To: (insn 15 14 16 2 (set (reg:V4x4BF 60 v28)                                 
          (mem/c:V4x4BF (plus:DI (reg/f:DI 64 sfp)                              
                  (const_int -32 [0xffffffffffffffe0])) [3 v+0 S32 A128])) 4935
{*aarch64_movv4x4bf}                                                            
       (nil))

  Store forwarding avoided with bit inserts:                                    
  With sequence:                                                                
    (insn 131 0 132 (set (reg:V4x4BF 186)                                       
          (reg:V4x4BF 60 v28)) 4935 {*aarch64_movv4x4bf}                        
       (nil))                                                                   
    (insn 132 131 133 (set (subreg:DI (reg:V4x4BF 186) 16)                      
          (subreg:DI (reg:V4SI 185) 0)) 106 {*movdi_aarch64}                    
       (nil))                                                                   
    (insn 133 132 0 (set (subreg:DI (reg:V4x4BF 186) 24)                        
          (subreg:DI (reg:V4SI 185) 8)) 106 {*movdi_aarch64}
       (nil))                                                                   
```

The code then updates `reg:V4x4BF 60 v28` and writes it to memory. Here,
`reg:V4x4BF 186` should have been used instead:

```                                                                             
  (insn 16 133 123 2 (set (reg:V4x4BF 60 v28)
          (unspec:V4x4BF [
                  (mem:BLK (reg/f:DI 184 [ overwrite ]) [0  S8 A8])             
                  (reg:V4x4BF 60 v28)
                  (const_int 3 [0x3])                                           
              ] UNSPEC_LD4_LANE)) ".../arm_neon.h":28500:10 4694
{aarch64_vec_load_lanesv4x4bf_lanev4bf}
       (nil))                                                                   
  (insn 123 16 17 2 (set (reg:DI 181)                                           
          (reg:DI 63 v31)) 106 {*movdi_aarch64}
       (nil))                                                                   
  (insn 17 123 20 2 (set (mem/c:V4x4BF (plus:DI (reg/f:DI 64 sfp)
                  (const_int -32 [0xffffffffffffffe0])) [3 v+0 S32 A128])       
          (reg:V4x4BF 60 v28)) 4935 {*aarch64_movv4x4bf}
       (expr_list:REG_DEAD (reg:V4x4BF 60 v28)                                  
          (nil)))
```

It seems more like a `store_bit_field` issue. And history has showed that
`store_bit_field` has several gaps that we have exposed, as ASF is one of its
few users.

Reply via email to