On Wed, Nov 20, 2024 at 11:29 AM Georg-Johann Lay via Gcc
<gcc@gcc.gnu.org> wrote:
>
> Consider the following RTL peephole from avr.md:
>
> (define_peephole2               ; avr.md:5387
>    [(match_scratch:QI 3 "d")
>     (parallel [(set (match_operand:ALL4 0 "register_operand" "")
>                     (ashift:ALL4 (match_operand:ALL4 1
> "register_operand" "")
>                                  (match_operand:QI 2 "const_int_operand"
> "")))
>                (clobber (reg:CC REG_CC))])]
>    ""
>    [(parallel [(set (match_dup 0)
>                     (ashift:ALL4 (match_dup 1)
>                                  (match_dup 2)))
>                (clobber (match_dup 3))
>                (clobber (reg:CC REG_CC))])])
>
> As far as I understand, its purpose is to provide a QImode
> scratch register provided such a scratch is available.
>
> However, in the .peephole2 RTL dump with -da I see the following:
>
> Splitting with gen_peephole2_100 (avr.md:5387)
> ...
> (insn 24 8 15 2 (parallel [
>              (set (reg:SI 22 r22 [orig:47 _3 ] [47])
>                   (ashift:SI (reg:SI 20 r20 [orig:48 x ] [48])
>                              (const_int 7 [0x7])))
>              (clobber (reg:QI 24 r24))
>              (clobber (reg:CC 36 cc))
>          ])
>       (nil))
>
> That is, the scratch r24:QI is overlapping the output in
> r22:SI.  All hard registers are 8-bit regs and hence r22:SI
> extends from r22...r25.
>
> A scratch that overlaps the operands is pretty much useless
> or even plain wrong.  recog.cc::peep2_find_free_register()
> has this comment:  /* Don't use registers set or clobbered by the insn.  */
>
>    from = peep2_buf_position (peep2_current + from);
>    to = peep2_buf_position (peep2_current + to);
>
>    gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
>    REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
>
>    while (from != to)
>      {
>        gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
>
>        /* Don't use registers set or clobbered by the insn.  */
>        FOR_EACH_INSN_DEF (def, peep2_insn_data[from].insn)
>         SET_HARD_REG_BIT (live, DF_REF_REGNO (def));
>
>        from = peep2_buf_position (from + 1);
>      }
>
> So it this bogus in that it assumes all registers extend only
> over one hard reg?

Yes, looks like a bug to me.

>
> FYI, the purpose is to provide a scratch without increasing the register
> pressure (which "match_scratch" would do).  Therefore, the RTL peephole
> is used instead of forcing reload to come up with a scratch.
>
> More specifically, I see this with
>
> $ avr-gcc bogus-peep2.c -S -Os -da
>
> long ashl32_7 (int i, long x)
> {
>      return x << 7;
> }
>
> with the attached WIP patch atop trunk b222ee10045d.
>
> Johann
>
> Target: avr
> Configured with: ../../source/gcc-master/configure --target=avr
> --disable-nls --with-dwarf2 --with-gnu-as --with-gnu-ld --disable-shared
>   --enable-languages=c,c++
> Thread model: single
> Supported LTO compression algorithms: zlib
> gcc version 15.0.0 20241119 (experimental) (GCC)

Reply via email to