YunQiang Su <[email protected]> writes:
> Richard Sandiford <[email protected]> 于2024年6月5日周三 23:20写道:
>>
>> YunQiang Su <[email protected]> writes:
>> > Richard Sandiford <[email protected]> 于2024年6月5日周三 22:14写道:
>> >>
>> >> YunQiang Su <[email protected]> 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.
Yeah. AIUI, the change above behaves correcty there. It maintains
the type correctness of the output.
> and
>
> bool
> gcn_truly_noop_truncation (poly_uint64 outprec, poly_uint64 inprec)
> {
> return ((inprec <= 32) && (outprec <= inprec));
> }
Not sure why GCN requires this TBH, but...
> I am worrying that we may break nvptx/amdgcn as I have little
> knowledge about them.
...I think the targets are asking for the same behaviour as MIPS.
The reason for the patch is that the code really is doing a
truncation from value_mode to op_mode. If the target says that
that isn't a no-op, we have to use the target's truncation pattern
instead of a subreg.
Thanks,
Richard
>
>
>> > 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