From: Tsukasa OI <research_tra...@irq.a4lg.com> A "prefetch" instruction on RISC-V GCC emits a machine hint instruction directly when the 'Zicbop' extension is enabled but it could cause an ICE when the address argument of __builtin_prefetch is a integral constant (such like 0 [NULL] or some other [but possibly not all] fixed addresses).
It fixes the problem by changing "prefetch" from a native instruction to an expansion and coercing the address to a register there. gcc/ChangeLog: * config/riscv/riscv.md (prefetch): Expand to a native prefetch instruction instead of emitting a machine instruction directly. Coerce the address argument into a register. gcc/testsuite/ChangeLog: * gcc.target/riscv/cmo-zicbop-by-common-ice-1.c: New ICE test. * gcc.target/riscv/cmo-zicbop-by-common-ice-2.c: Ditto. --- gcc/config/riscv/riscv.md | 43 ++++++++++++------- .../riscv/cmo-zicbop-by-common-ice-1.c | 13 ++++++ .../riscv/cmo-zicbop-by-common-ice-2.c | 7 +++ 3 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-2.c diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index eaa8b6a9f085..12e78b60980e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -3451,21 +3451,6 @@ [(set_attr "type" "cbo")] ) -(define_insn "prefetch" - [(prefetch (match_operand 0 "address_operand" "r") - (match_operand 1 "imm5_operand" "i") - (match_operand 2 "const_int_operand" "n"))] - "TARGET_ZICBOP" -{ - switch (INTVAL (operands[1])) - { - case 0: return "prefetch.r\t%a0"; - case 1: return "prefetch.w\t%a0"; - default: gcc_unreachable (); - } -} - [(set_attr "type" "cbo")]) - (define_insn "riscv_prefetch_i_<mode>" [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r") (match_operand:X 1 "const_int_operand" "n")] @@ -3490,6 +3475,34 @@ "prefetch.w\t%1(%0)" [(set_attr "type" "cbo")]) +(define_expand "prefetch" + [(prefetch (match_operand 0 "address_operand" "") + (match_operand 1 "const_int_operand" "") + (match_operand 2 "const_int_operand" ""))] + "TARGET_ZICBOP" +{ + operands[0] = force_reg (Pmode, operands[0]); + switch (INTVAL (operands[1])) + { + case 0: + if (TARGET_64BIT) + emit_insn (gen_riscv_prefetch_r_di (operands[0], const0_rtx)); + else + emit_insn (gen_riscv_prefetch_r_si (operands[0], const0_rtx)); + break; + case 1: + if (TARGET_64BIT) + emit_insn (gen_riscv_prefetch_w_di (operands[0], const0_rtx)); + else + emit_insn (gen_riscv_prefetch_w_si (operands[0], const0_rtx)); + break; + default: + gcc_unreachable (); + } + DONE; +} + [(set_attr "type" "cbo")]) + (define_expand "extv<mode>" [(set (match_operand:GPR 0 "register_operand" "=r") (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r") diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-1.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-1.c new file mode 100644 index 000000000000..47e83f29cc5c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */ + +void foo (void) +{ + /* Second argument defaults to zero (read). */ + __builtin_prefetch (0); + __builtin_prefetch (0, 0); + __builtin_prefetch (0, 1); +} + +/* { dg-final { scan-assembler-times "prefetch\\.r" 2 } } */ +/* { dg-final { scan-assembler-times "prefetch\\.w" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-2.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-2.c new file mode 100644 index 000000000000..a245b8163c1f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-ice-2.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i_zicbop -mabi=lp64" } */ + +#include "cmo-zicbop-by-common-ice-1.c" + +/* { dg-final { scan-assembler-times "prefetch\\.r" 2 } } */ +/* { dg-final { scan-assembler-times "prefetch\\.w" 1 } } */ -- 2.42.0