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).