Richard Sandiford <richard.sandif...@arm.com> 于2024年6月5日周三 23:20写道:
>
> YunQiang Su <s...@gcc.gnu.org> writes:
> > Richard Sandiford <richard.sandif...@arm.com> 于2024年6月5日周三 22:14写道:
> >>
> >> YunQiang Su <s...@gcc.gnu.org> writes:
> >> > PR target/113179.
> >> >
> >> > In `store_bit_field_using_insv`, we just use SUBREG if value_mode
> >> >>= op_mode, while in some ports, a sign_extend will be needed,
> >> > such as MIPS64:
> >> >   If either GPR rs or GPR rt does not contain sign-extended 32-bit
> >> >   values (bits 63..31 equal), then the result of the operation is
> >> >   UNPREDICTABLE.
> >> >
> >> > The problem happens for the code like:
> >> >   struct xx {
> >> >         int a:4;
> >> >         int b:24;
> >> >         int c:3;
> >> >         int d:1;
> >> >   };
> >> >
> >> >   void xx (struct xx *a, long long b) {
> >> >         a->d = b;
> >> >   }
> >> >
> >> > In the above code, the hard register contains `b`, may be note well
> >> > sign-extended.
> >> >
> >> > gcc/
> >> >       PR target/113179
> >> >       * expmed.c(store_bit_field_using_insv): TRUNCATE value1 if
> >> >       needed.
> >> >
> >> > gcc/testsuite
> >> >       PR target/113179
> >> >       * gcc.target/mips/pr113179.c: New tests.
> >> > ---
> >> >  gcc/expmed.cc                            | 12 +++++++++---
> >> >  gcc/testsuite/gcc.target/mips/pr113179.c | 18 ++++++++++++++++++
> >> >  2 files changed, 27 insertions(+), 3 deletions(-)
> >> >  create mode 100644 gcc/testsuite/gcc.target/mips/pr113179.c
> >> >
> >> > diff --git a/gcc/expmed.cc b/gcc/expmed.cc
> >> > index 4ec035e4843..6a582593da8 100644
> >> > --- a/gcc/expmed.cc
> >> > +++ b/gcc/expmed.cc
> >> > @@ -704,9 +704,15 @@ store_bit_field_using_insv (const extraction_insn 
> >> > *insv, rtx op0,
> >> >           }
> >> >         else
> >> >           {
> >> > -           tmp = gen_lowpart_if_possible (op_mode, value1);
> >> > -           if (! tmp)
> >> > -             tmp = gen_lowpart (op_mode, force_reg (value_mode, 
> >> > value1));
> >> > +           if (targetm.mode_rep_extended (op_mode, value_mode))
> >> > +             tmp = simplify_gen_unary (TRUNCATE, op_mode,
> >> > +                                       value1, value_mode);
> >> > +           else
> >> > +             {
> >> > +               tmp = gen_lowpart_if_possible (op_mode, value1);
> >> > +               if (! tmp)
> >> > +                 tmp = gen_lowpart (op_mode, force_reg (value_mode, 
> >> > value1));
> >> > +             }
> >> >           }
> >> >         value1 = tmp;
> >> >       }
> >>
> >> I notice this patch is already applied.  Was it approved?  I didn't
> >> see an approval in my feed or in the archives.
> >>
> >
> > Sorry. I was supposed that it only effects MIPS targets since only MIPS 
> > defines
> >   targetm.mode_rep_extended
> >
> >> Although it might not make any difference on current targets,
> >> I think the conditional should logically be based on
> >> TRULY_NOOP_TRUNCATION(_MODES_P) rather than targetm.mode_rep_extended.
> >>
> >> TRULY_NOOP_TRUNCATION is a correctness question: can I use subregs
> >> to do this truncation?  targetm.mode_rep_extended is instead an
> >> optimisation question: can I assume that a particular extension is free?
> >> Here we're trying to avoid a subreg for correctness, rather than trying
> >> to take advantage of a cheap extension.
> >>
> >> So I think the code should be:
> >>
> >>           if (GET_MODE_SIZE (value_mode) < GET_MODE_SIZE (op_mode))
> >>             {
> >>               tmp = simplify_subreg (op_mode, value1, value_mode, 0);
> >>               if (! tmp)
> >>                 tmp = simplify_gen_subreg (op_mode,
> >>                                            force_reg (value_mode, value1),
> >>                                            value_mode, 0);
> >>             }
> >>           else if (GET_MODE_SIZE (op_mode) < GET_MODE_SIZE (value_mode)
> >>                    && !TRULY_NOOP_TRUNCATION_MODES_P (op_mode, value_mode))
> >
> > In fact I don't think so. For other targets besides MIPS, it is safe even
> >     !TRULY_NOOP_TRUNCATION_MODES_P (op_mode, value_mode)
> > as INS instruction may use the low part of a register safely.
>
> Not sure what you mean.  The change above is no-op for targets other
> than MIPS and SH5 (now removed).  But I think it's the correct way of
> representing the restriction on MIPS and SH5.
>
> >
> > It is only not true on MIPS ISA documents as
> >      If either GPR rs or GPR rt does not contain sign-extended 32-bit
> >      values (bits 63..31 equal), then the result of the operation is
> >      UNPREDICTABLE.
>
> Right.  The reason that TRULY_NOOP_TRUNCATION_MODES_P (SImode, DImode)
> is false for MIPS isn't that a subreg is impossible on MIPS targets.
> It's that the MIPS port needs to ensure that SImode values are stored
> in sign-extended form in order to avoid the problem above.  So a
> truncation needs to be a sign-extension.
>

Thanks for your explanation. NVPTX defines TRULY_NOOP_TRUNCATION_MODES_P
to always false.

and

bool
gcn_truly_noop_truncation (poly_uint64 outprec, poly_uint64 inprec)
{
  return ((inprec <= 32) && (outprec <= inprec));
}

I am worrying that we may break nvptx/amdgcn as I have little
knowledge about them.


> > It is very annoying. I haven't noticed a similar problem on any other
> > ISA documents.
> > In fact I don't know any real MIPS hardware that is "UNPREDICTABLE" in
> > this case.
>
> I think the Broadcom SB-1 took advantage of the freedom.
>
> Thanks,
> Richard

Reply via email to