subreg vs vec_select
Segher Boessenkool
segher@kernel.crashing.org
Thu Sep 10 22:30:16 GMT 2020
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
More information about the Gcc
mailing list