https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117608

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P3                          |P1

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
int i;

void
foo (void)
{
  __builtin_prefetch (&i, 2, 0);
}

ICEs as well since that revision, and I think it actually ICEs on many targets
as well.

I don't see who approved the middle-end changes in that revision.

Certainly, __builtin_prefetch documentation in extend.texi has not been
adjusted:

"The value of @var{rw} is a compile-time constant one or zero; one
means that the prefetch is preparing for a write to the memory address
and zero, the default, means that the prefetch is preparing for a read."

So, if 2 is now valid, the documentation should say what it means.

And then all targets with "prefetch" optab needs to be analyzed and adjusted. 
Question is if we want to have a warning like before if they don't support this
read shared stuff, whatever it is, what we get e.g. with ptr, 3, 0 instead of
ptr, 2, 0 or what we got in GCC 14 and earlier:
pr117608-3.c: In function ‘foo’:
pr117608-3.c:6:3: warning: invalid second argument to ‘__builtin_prefetch’;
using zero
    6 |   __builtin_prefetch (&i, 3, 0);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
or some other warning, because the value is no longer invalid but just not
supported on almost all targets.

Anyway, the above testcase ICEs on aarch64-linux:
    const char * pftype[2][4] =
    {
      {"prfm\\tPLDL1STRM, %0",
       "prfm\\tPLDL3KEEP, %0",
       "prfm\\tPLDL2KEEP, %0",
       "prfm\\tPLDL1KEEP, %0"},
      {"prfm\\tPSTL1STRM, %0",
       "prfm\\tPSTL3KEEP, %0",
       "prfm\\tPSTL2KEEP, %0",
       "prfm\\tPSTL1KEEP, %0"},
    };

    int locality = INTVAL (operands[2]);

    gcc_assert (IN_RANGE (locality, 0, 3));

    /* PRFM accepts the same addresses as a 64-bit LDR so wrap
       the address into a DImode MEM so that aarch64_print_operand knows
       how to print it.  */
    operands[0] = gen_rtx_MEM (DImode, operands[0]);
    return pftype[INTVAL(operands[1])][locality];
(it doesn't assert IN_RANGE (INTVAL (operands[1]), 0, 1), but the crash is from
just accessing pftype elements which aren't there and at final.cc time crashes
trying to emit garbage.
Alpha won't ICE but will treat rw 2 as 1, not as 0:
  bool write = INTVAL (operands[1]) != 0;
Similarly ARC.
ARM 32-bit ignores all the parameters silently.
i386 has weird formatting (the if (write == 1) line is off by 4 spaces,
|| TARGET_MOVRS" is misaligned as well), and likely should in the else of if
(write == 1) just do if (!TARGET_MOVRS) operands[1] = const0_rtx;, either with
a warning or without.
ia64 will fail the
  gcc_assert (i == 0 || i == 1);
assertion.
loongarch (badly formatted) will do
    default: gcc_unreachable ();
for const2_rtx.
mips mips_prefetch_cookie and mips_loongson_ext2_prefetch_cookie seem to
silently assume write is just 0 or 1 and will just do garbage (which might fail
to assemble).
pa is like alpha.
riscv is like loongarch.
rs6000 is like alpha.
s390 will silently treat 2 as 0.
SH is like ARM 32-bit.
sparc will fail
  gcc_assert (read_or_write == 0 || read_or_write == 1);
assertions (in two places).

Reply via email to