Hi!

On Thu, Sep 10, 2020 at 12:21:47PM +0200, Ilya Leoshkevich wrote:
> On Wed, 2020-09-09 at 16:09 -0500, Segher Boessenkool wrote:
> > On Wed, Sep 09, 2020 at 11:50:56AM +0200, Ilya Leoshkevich via Gcc
> > wrote:
> > > I have a vector pseudo containing a single 128-bit value (V1TFmode)
> > > and
> > > I need to access its last 64 bits (DFmode). Which of the two
> > > options
> > > is better?
> > > 
> > > (subreg:DF (reg:V1TF) 8)
> > > 
> > > or
> > > 
> > > (vec_select:DF (subreg:V2DF (reg:V1TF) 0) (parallel [(const_int
> > > 1)]))
> > > 
> > > If I use the first one, I run into a problem with set_noop_p (): it
> > > thinks that
> > > 
> > > (set (subreg:DF (reg:TF %f0) 8) (subreg:DF (reg:V1TF %f0) 8))
> > > 
> > > is a no-op, because it doesn't check the mode after stripping the
> > > subreg:
> > > 
> > > https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/rtlanal.c;h=5ae38b79#l1616
> > > 
> > > However this is not correct, because SET_DEST is the second
> > > register in
> > > a register pair, and SET_SRC is half of a vector register that
> > > overlaps
> > > the first register in the corresponding pair. So it looks as if
> > > mode
> > > needs to be considered there.
> > 
> > Yes.
> > 
> > > This helps:
> > > 
> > > --- a/gcc/rtlanal.c
> > > +++ b/gcc/rtlanal.c
> > > @@ -1619,6 +1619,8 @@ set_noop_p (const_rtx set)
> > >         return 0;
> > >        src = SUBREG_REG (src);
> > >        dst = SUBREG_REG (dst);
> > > +      if (GET_MODE (src) != GET_MODE (dst))
> > > +       return 0;
> > >      }
> > > 
> > > but I'm not sure whether I'm not missing something about subreg
> > > semantics in the first place.
> > 
> > You probably should just see if both modes are the same number of
> > hard
> > registers?  HARD_REGNO_NREGS.
> 
> I've refined my patch as follows:
> 
> --- a/gcc/rtlanal.c
> +++ b/gcc/rtlanal.c
> @@ -1619,6 +1619,11 @@ set_noop_p (const_rtx set)
>         return 0;
>        src = SUBREG_REG (src);
>        dst = SUBREG_REG (dst);
> +      if (REG_P (src) && HARD_REGISTER_P (src) && REG_P (dst)
> +         && HARD_REGISTER_P (dst)
> +         && hard_regno_nregs (REGNO (src), GET_MODE (src))
> +                != hard_regno_nregs (REGNO (dst), GET_MODE (dst)))

(The "!" should align with the "h".)

> +       return 0;
>      }

Looks good to me, thanks!

> This also helps, and is less restrictive than my first variant.
> Two questions, just for my understanding:
> 
> 1) This mode confusion problem must never happen to pseudos, because,
>    unlike hard registers, pseudos must be always referred to in their
>    natural mode.  Is this correct?

Only hard registers can be accessed in more than one mode, yes.  To
access pseudos in another mode you need a subreg.

> 2) Can there be a hypothetical machine, where modes XF and YF refer to
>    64-bit and 128-bit register pairs respectively?  This would cause
>    the mode confusion problem again.  Is there anything in RTL
>    semantics that would prohibit existence of such modes?

They would have to be the same hard register number as well.  Not very
likely, but I don't see why it couldn't happen theoretically.


Segher

Reply via email to