On Fri, Feb 13, 2026 at 03:10:41PM +0100, Stefan Schulze Frielinghaus wrote:
> On Wed, Feb 11, 2026 at 08:53:08PM +0100, Robin Dapp wrote:
> > Hi,
> > 
> > In the PR code we have the somewhat rare case that we need to reload
> > a vector subreg of a scalar register, (subreg:V2HI (reg:DI)).
> > What complicates things is that the test is compiled with
> > -mrvv-vector-bits=zvl, so VLS-only mode.
> > Unfortunately, we can still get VLA-named modes that are actually VLS
> > modes (i.e. a constant number of units).
> > 
> > For moving real VLS modes we simply use
> > 
> >  (define_insn_and_split "*mov<mode>"
> >    [(set (match_operand:VLS_AVL_IMM 0 "reg_or_mem_operand" "=vr, m, vr")
> >     (match_operand:VLS_AVL_IMM 1 "reg_or_mem_operand" "  m,vr, vr"))]
> > 
> > Here, lra recognizes cycle danger, quickly switches to the memory
> > alternative and the resulting code is as expected - we perform a vector
> > load from that memory the DImode reg was spilled to.
> > 
> > For VLA (named) modes the mov insn is
> > 
> > (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
> >   [(set (match_operand:V_FRACT 0 "reg_or_mem_operand" "=vr, m,vr")
> >     (match_operand:V_FRACT 1 "reg_or_mem_operand" "  m,vr,vr"))
> >    (clobber (match_scratch:P 2 "=&r,&r,X"))]
> > 
> > The extra clobber here is an optimization:  For modes smaller than a full 
> > register we want to store the actual size, rather than always the full
> > vector size.  If that mode size happens to exceed 32, instead of using an 
> > immediate we need to move it to a register so vsetvl can consume it.
> > 
> > As the second mov insn above has three operands lra never checks for cycle 
> > danger and promptly creates a cycle :)  This patch loosens the conditions on
> > the cycle check by allowing a third operand that is a clobber.  As a 
> > consequence, we also need to prevent scratch regs to be "written back".
> 
> So this is just a different form of a mov and therefore it is not
> completely unrelated to cycle danger.  At a first glance it sounds
> reasonable.
> 
> I might be completely off here, but a quick idea which came up is
> whether a secondary reload could be utilized in order to get a scratch
> register, rendering the initial mov into an ordinary mov with two
> operands so that LRA would again detect a cycle.

Ah I have just realized that the original insn might have been deleted
which means we would run into the same problem as without a secondary
reload:

  lra_process_new_insns (curr_insn, before, NULL, "Inserting the move");
  if (new_reg != NULL_RTX)
    SET_SRC (curr_insn_set) = new_reg;
  else
    {
      if (lra_dump_file != NULL)
        {
          fprintf (lra_dump_file, "Deleting move %u\n", INSN_UID (curr_insn));
          dump_insn_slim (lra_dump_file, curr_insn);
        }
      lra_set_insn_deleted (curr_insn);
      return true;

So never mind.

Cheers,
Stefan

> 
> Cheers,
> Stefan
> 
> > 
> > I'm not 100% on this but figured I'll just send the patch out for further 
> > comments.
> > 
> > Regtested and bootstrapped on x86 and aarch64.  The power10 cfarm machine 
> > that
> > I normally use is currently unreachable.  Regtested on rv64gcv_zvl512b.
> > 
> > Regards
> >  Robin
> > 
> >     PR rtl-optimization/123381
> > 
> > gcc/ChangeLog:
> > 
> >     * lra-constraints.cc (process_alt_operands): Detect cycles in
> >     three-operand moves with clobber.
> >     (curr_insn_transform): Don't write back a scratch operand.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * gcc.target/riscv/rvv/autovec/pr123381.c: New test.
> > ---
> >  gcc/lra-constraints.cc                               | 12 +++++++++++-
> >  .../gcc.target/riscv/rvv/autovec/pr123381.c          | 11 +++++++++++
> >  2 files changed, 22 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123381.c
> > 
> > diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> > index 87b18f30c98..0d073724043 100644
> > --- a/gcc/lra-constraints.cc
> > +++ b/gcc/lra-constraints.cc
> > @@ -3315,7 +3315,15 @@ process_alt_operands (int only_alternative)
> >         early_clobbered_nops[early_clobbered_regs_num++] = nop;
> >     }
> >  
> > -      if (curr_insn_set != NULL_RTX && n_operands == 2
> > +      if (curr_insn_set != NULL_RTX
> > +     /* Allow just two operands or three operands where the third
> > +        is a clobber.  */
> > +     && (n_operands == 2
> > +         || (n_operands == 3
> > +             && GET_CODE (PATTERN (curr_insn)) == PARALLEL
> > +             && XVECLEN (PATTERN (curr_insn), 0) == 2
> > +             && GET_CODE (XVECEXP (PATTERN (curr_insn), 0, 1))
> > +                == CLOBBER))
> >       /* Prevent processing non-move insns.  */
> >       && (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG
> >           || SET_SRC (curr_insn_set) == no_subreg_reg_operand[1])
> > @@ -4919,6 +4927,8 @@ curr_insn_transform (bool check_only_p)
> >           && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX
> >           /* OLD can be an equivalent constant here.  */
> >           && !CONSTANT_P (old)
> > +         /* No need to write back anything for a scratch.  */
> > +         && GET_CODE (old) != SCRATCH
> >           && (!REG_P(old) || !ira_former_scratch_p (REGNO (old))))
> >         {
> >           start_sequence ();
> > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123381.c 
> > b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123381.c
> > new file mode 100644
> > index 00000000000..cc21b0feca4
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123381.c
> > @@ -0,0 +1,11 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Ofast -mcpu=xiangshan-kunminghu -mrvv-vector-bits=zvl 
> > -fno-tree-ccp -fno-vect-cost-model" } */
> > +
> > +char c;
> > +
> > +void
> > +foo(short, short, short, short, int, int, int, int, long x)
> > +{
> > +  x /= *(_Complex short *)&x;
> > +  c = x;
> > +}
> > -- 
> > 2.52.0
> > 

Reply via email to