YunQiang Su <s...@gcc.gnu.org> writes: > 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.
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