* [PATCH 1/2] RISC-V: Define not broken prefetch builtins
2023-09-22 7:11 [PATCH 0/2] RISC-V: Define not broken prefetch builtins Tsukasa OI
@ 2023-09-22 7:11 ` Tsukasa OI
2023-09-22 7:11 ` [PATCH 2/2] RISC-V: Fix ICE by expansion and register coercion Tsukasa OI
2023-09-26 21:38 ` [PATCH 0/2] RISC-V: Define not broken prefetch builtins Jeff Law
2 siblings, 0 replies; 6+ messages in thread
From: Tsukasa OI @ 2023-09-22 7:11 UTC (permalink / raw)
To: Tsukasa OI, Kito Cheng, Palmer Dabbelt, Andrew Waterman,
Jim Wilson, Jeff Law
Cc: gcc-patches
From: Tsukasa OI <research_trasio@irq.a4lg.com>
__builtin_riscv_zicbop_cbo_prefetchi (corresponding "prefetch.i"
instruction from the 'Zicbop' extension) is completely broken and new
builtin is required for replacement.
However, it required more than defining new builtin and/or instruction.
1. Support for variable argument function prototype for RISC-V builtins
(corresponding "..." on C-based languages)
2. Support for (non-vector) RISC-V builtins with custom expansion
(on RVV intrinsics, custom expansion is already implemented)
Along with other minor changes, not broken "prefetch.i" intrinsic is
defined as follows:
void __builtin_riscv_prefetch_i (void *addr, ...);
Optional second argument (defaults to zero and must be a compile-time
constant integer) is the offset from given address (-2048 <= x < 2048 and
must be a multiple of 32, due to "prefetch.i" constraints). Third or later
arguments are ignored (like other builtin functions).
This commit also defines builtin functions for "prefetch.r" and "prefetch.w"
instructions for consistency:
void __builtin_riscv_prefetch_r (void *addr, ...);
void __builtin_riscv_prefetch_w (void *addr, ...);
Those instructions can be emitted using __builtin_prefetch but has no
control of the offset field.
gcc/ChangeLog:
* config/riscv/riscv-builtins.cc: Rename availabilities
"prefetchi{32,64}" to "prefetch{32,64}".
(RISCV_FTYPE_NAME_VAR1): Similar to RISCV_FTYPE_NAME1 but for
variable argument function prototype.
(DEF_RISCV_FTYPE_VAR): Similar to DEF_RISCV_FTYPE but calls
RISCV_FTYPE_NAME_VAR* instead.
(enum riscv_builtin_type): Add RISCV_BUILTIN_CUSTOM for builtin
with custom expansion.
(struct riscv_builtin_description): Add custom expansion function.
(RISCV_BUILTIN): Modified to set "expand_function".
(RISCV_CUSTOM_BUILTIN): New. Similar to RISCV_BUILTIN but only for
builtins with custom expansion function.
(riscv_expand_builtin): Handle RISCV_BUILTIN_CUSTOM builtin.
(expand_builtin_prefetch_riscv): New custom expansion function for
"prefetch.[irw]" instructions from the 'Zicbop' extension.
* config/riscv/riscv-cmo.def
(__builtin_riscv_zicbop_cbo_prefetchi): Remove since it's broken.
(__builtin_riscv_prefetch_i): New.
(__builtin_riscv_prefetch_r): New.
(__builtin_riscv_prefetch_w): New.
* config/riscv/riscv-ftypes.def: Add variable argument prototype
for "void func(void*, ...)".
* config/riscv/riscv.md (unspecv): Remove UNSPECV_PREI and add
UNSPECV_PREFETCH_[IRW].
(riscv_prefetchi_<mode>): Remove.
(riscv_prefetch_i_<mode>): New.
(riscv_prefetch_r_<mode>): New.
(riscv_prefetch_w_<mode>): New.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/cmo-zicbop-1.c: Refine to test new builtins.
* gcc.target/riscv/cmo-zicbop-2.c: Ditto.
* gcc.target/riscv/cmo-zicbop-3.c: New NULL prefetching test.
* gcc.target/riscv/cmo-zicbop-4.c: New failure test.
* gcc.target/riscv/cmo-zicbop-5.c: Ditto.
* gcc.target/riscv/cmo-zicbop-6.c: Ditto.
* gcc.target/riscv/cmo-zicbop-by-common-1.c: New test for
__builtin_prefetch and the 'Zicbop' extension.
* gcc.target/riscv/cmo-zicbop-by-common-2.c: Ditto.
* gcc.target/riscv/cmo-zicbop-by-common-3.c: Ditto.
---
gcc/config/riscv/riscv-builtins.cc | 112 +++++++++++++++++-
gcc/config/riscv/riscv-cmo.def | 8 +-
gcc/config/riscv/riscv-ftypes.def | 1 +
gcc/config/riscv/riscv.md | 30 ++++-
gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c | 41 ++++---
gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c | 33 ++----
gcc/testsuite/gcc.target/riscv/cmo-zicbop-3.c | 29 +++++
gcc/testsuite/gcc.target/riscv/cmo-zicbop-4.c | 14 +++
gcc/testsuite/gcc.target/riscv/cmo-zicbop-5.c | 14 +++
gcc/testsuite/gcc.target/riscv/cmo-zicbop-6.c | 38 ++++++
.../gcc.target/riscv/cmo-zicbop-by-common-1.c | 17 +++
.../gcc.target/riscv/cmo-zicbop-by-common-2.c | 7 ++
.../gcc.target/riscv/cmo-zicbop-by-common-3.c | 13 ++
13 files changed, 305 insertions(+), 52 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-3.c
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 3fe3a89dcc25..4f422e0891c2 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -47,12 +47,16 @@ along with GCC; see the file COPYING3. If not see
#define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
#define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C
#define RISCV_FTYPE_NAME3(A, B, C, D) RISCV_##A##_FTYPE_##B##_##C##_##D
+/* Similar, but for variable argument function prototype. */
+#define RISCV_FTYPE_NAME_VAR1(A, B) RISCV_##A##_FTYPE_##B##_VAR
/* Classifies the prototype of a built-in function. */
enum riscv_function_type {
#define DEF_RISCV_FTYPE(NARGS, LIST) RISCV_FTYPE_NAME##NARGS LIST,
+#define DEF_RISCV_FTYPE_VAR(NARGS, LIST) RISCV_FTYPE_NAME_VAR##NARGS LIST,
#include "config/riscv/riscv-ftypes.def"
#undef DEF_RISCV_FTYPE
+#undef DEF_RISCV_FTYPE_VAR
RISCV_MAX_FTYPE_MAX
};
@@ -62,7 +66,10 @@ enum riscv_builtin_type {
RISCV_BUILTIN_DIRECT,
/* Likewise, but with return type VOID. */
- RISCV_BUILTIN_DIRECT_NO_TARGET
+ RISCV_BUILTIN_DIRECT_NO_TARGET,
+
+ /* The function which requires custom expansion. */
+ RISCV_BUILTIN_CUSTOM,
};
/* Declare an availability predicate for built-in functions. */
@@ -90,6 +97,9 @@ struct riscv_builtin_description {
/* Whether the function is available. */
unsigned int (*avail) (void);
+
+ /* Custom expansion function if builtin_type is RISCV_BUILTIN_CUSTOM. */
+ rtx (*expand_function) (enum insn_code icode, rtx target, tree exp);
};
AVAIL (hard_float, TARGET_HARD_FLOAT || TARGET_ZFINX)
@@ -101,8 +111,8 @@ AVAIL (inval32, TARGET_ZICBOM && !TARGET_64BIT)
AVAIL (inval64, TARGET_ZICBOM && TARGET_64BIT)
AVAIL (zero32, TARGET_ZICBOZ && !TARGET_64BIT)
AVAIL (zero64, TARGET_ZICBOZ && TARGET_64BIT)
-AVAIL (prefetchi32, TARGET_ZICBOP && !TARGET_64BIT)
-AVAIL (prefetchi64, TARGET_ZICBOP && TARGET_64BIT)
+AVAIL (prefetch32, TARGET_ZICBOP && !TARGET_64BIT)
+AVAIL (prefetch64, TARGET_ZICBOP && TARGET_64BIT)
AVAIL (crypto_zbkb32, TARGET_ZBKB && !TARGET_64BIT)
AVAIL (crypto_zbkb64, TARGET_ZBKB && TARGET_64BIT)
AVAIL (crypto_zbkx32, TARGET_ZBKX && !TARGET_64BIT)
@@ -123,7 +133,7 @@ AVAIL (clmulr_zbc32, TARGET_ZBC && !TARGET_64BIT)
AVAIL (clmulr_zbc64, TARGET_ZBC && TARGET_64BIT)
AVAIL (hint_pause, (!0))
-/* Construct a riscv_builtin_description from the given arguments.
+/* Construct a simple riscv_builtin_description from the given arguments.
INSN is the name of the associated instruction pattern, without the
leading CODE_FOR_riscv_.
@@ -137,7 +147,7 @@ AVAIL (hint_pause, (!0))
riscv_builtin_avail_. */
#define RISCV_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \
{ CODE_FOR_riscv_ ## INSN, "__builtin_riscv_" NAME, \
- BUILTIN_TYPE, FUNCTION_TYPE, riscv_builtin_avail_ ## AVAIL }
+ BUILTIN_TYPE, FUNCTION_TYPE, riscv_builtin_avail_ ## AVAIL, NULL }
/* Define __builtin_riscv_<INSN>, which is a RISCV_BUILTIN_DIRECT function
mapped to instruction CODE_FOR_riscv_<INSN>, FUNCTION_TYPE and AVAIL
@@ -152,6 +162,25 @@ AVAIL (hint_pause, (!0))
RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT_NO_TARGET, \
FUNCTION_TYPE, AVAIL)
+/* Construct a custom riscv_builtin_description from the given arguments.
+
+ INSN is the name of the associated instruction pattern, without the
+ leading CODE_FOR_riscv_.
+
+ NAME is the name of the function itself, without the leading
+ "__builtin_riscv_".
+
+ FTYPE is the prototype field in riscv_builtin_description.
+
+ AVAIL is the name of the availability predicate, without the leading
+ riscv_builtin_avail_.
+
+ EXPANDER is the function to expand the builtin. */
+#define RISCV_CUSTOM_BUILTIN(INSN, NAME, FTYPE, AVAIL, EXPANDER) \
+ { CODE_FOR_riscv_ ## INSN, "__builtin_riscv_" NAME, \
+ RISCV_BUILTIN_CUSTOM, FTYPE, \
+ riscv_builtin_avail_ ## AVAIL, EXPANDER }
+
/* Argument types. */
#define RISCV_ATYPE_VOID void_type_node
#define RISCV_ATYPE_UQI unsigned_intQI_type_node
@@ -171,6 +200,8 @@ AVAIL (hint_pause, (!0))
#define RISCV_FTYPE_ATYPES3(A, B, C, D) \
RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C, RISCV_ATYPE_##D
+static rtx expand_builtin_prefetch_riscv (enum insn_code icode, rtx target, tree exp);
+
static const struct riscv_builtin_description riscv_builtins[] = {
#include "riscv-cmo.def"
#include "riscv-scalar-crypto.def"
@@ -209,8 +240,15 @@ riscv_build_function_type (enum riscv_function_type type)
= build_function_type_list (RISCV_FTYPE_ATYPES##NUM ARGS, \
NULL_TREE); \
break;
+#define DEF_RISCV_FTYPE_VAR(NUM, ARGS) \
+ case RISCV_FTYPE_NAME_VAR##NUM ARGS: \
+ types[(int) type] \
+ = build_varargs_function_type_list (RISCV_FTYPE_ATYPES##NUM ARGS, \
+ NULL_TREE); \
+ break;
#include "config/riscv/riscv-ftypes.def"
#undef DEF_RISCV_FTYPE
+#undef DEF_RISCV_FTYPE_VAR
default:
gcc_unreachable ();
}
@@ -387,6 +425,9 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case RISCV_BUILTIN_DIRECT_NO_TARGET:
return riscv_expand_builtin_direct (d->icode, target, exp, false);
+
+ case RISCV_BUILTIN_CUSTOM:
+ return d->expand_function (d->icode, target, exp);
}
}
}
@@ -394,6 +435,67 @@ riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
gcc_unreachable ();
}
+static rtx
+expand_builtin_prefetch_riscv (enum insn_code icode,
+ rtx target ATTRIBUTE_UNUSED,
+ tree exp)
+{
+ struct expand_operand ops[2];
+ tree arg0, arg1;
+ rtx op1;
+
+ char name_suffix = 'i';
+ switch (icode)
+ {
+ case CODE_FOR_riscv_prefetch_i_si:
+ case CODE_FOR_riscv_prefetch_i_di:
+ break;
+ case CODE_FOR_riscv_prefetch_r_si:
+ case CODE_FOR_riscv_prefetch_r_di:
+ name_suffix = 'r';
+ break;
+ case CODE_FOR_riscv_prefetch_w_si:
+ case CODE_FOR_riscv_prefetch_w_di:
+ name_suffix = 'w';
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Argument 0 is an address. */
+ arg0 = CALL_EXPR_ARG (exp, 0);
+
+ /* Argument 1 (offset) is an optional compile-time constant and defaults
+ to zero. It must be a valid offset for a S-type instruction AND must be
+ a multiple of 32. */
+ if (call_expr_nargs (exp) > 1)
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ else
+ arg1 = integer_zero_node;
+ if (TREE_CODE (arg1) != INTEGER_CST)
+ {
+ error ("second argument to %<__builtin_riscv_prefetch_%c%> must be a"
+ " constant", name_suffix);
+ arg1 = integer_zero_node;
+ }
+ op1 = expand_normal (arg1);
+ if (INTVAL (op1) < -IMM_REACH / 2
+ || INTVAL (op1) >= IMM_REACH / 2
+ || INTVAL (op1) % 32 != 0)
+ {
+ error ("second argument to %<__builtin_riscv_prefetch_%c%> must be a"
+ " valid offset for the prefetch instruction", name_suffix);
+ arg1 = integer_zero_node;
+ op1 = expand_normal (arg1);
+ }
+
+ create_input_operand (&ops[0], expand_normal (arg0),
+ TYPE_MODE (TREE_TYPE (arg0)));
+ create_input_operand (&ops[1], op1,
+ TYPE_MODE (TREE_TYPE (arg1)));
+ return riscv_expand_builtin_insn (icode, 2, ops, false);
+}
+
/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
void
diff --git a/gcc/config/riscv/riscv-cmo.def b/gcc/config/riscv/riscv-cmo.def
index ff713b78e19e..3be77710095e 100644
--- a/gcc/config/riscv/riscv-cmo.def
+++ b/gcc/config/riscv/riscv-cmo.def
@@ -13,8 +13,12 @@ RISCV_BUILTIN (zero_si, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV
RISCV_BUILTIN (zero_di, "zicboz_cbo_zero", RISCV_BUILTIN_DIRECT_NO_TARGET, RISCV_VOID_FTYPE_VOID_PTR, zero64),
// zicbop
-RISCV_BUILTIN (prefetchi_si, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI, prefetchi32),
-RISCV_BUILTIN (prefetchi_di, "zicbop_cbo_prefetchi", RISCV_BUILTIN_DIRECT, RISCV_UDI_FTYPE_UDI, prefetchi64),
+RISCV_CUSTOM_BUILTIN (prefetch_i_si, "prefetch_i", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch32, expand_builtin_prefetch_riscv),
+RISCV_CUSTOM_BUILTIN (prefetch_i_di, "prefetch_i", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch64, expand_builtin_prefetch_riscv),
+RISCV_CUSTOM_BUILTIN (prefetch_r_si, "prefetch_r", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch32, expand_builtin_prefetch_riscv),
+RISCV_CUSTOM_BUILTIN (prefetch_r_di, "prefetch_r", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch64, expand_builtin_prefetch_riscv),
+RISCV_CUSTOM_BUILTIN (prefetch_w_si, "prefetch_w", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch32, expand_builtin_prefetch_riscv),
+RISCV_CUSTOM_BUILTIN (prefetch_w_di, "prefetch_w", RISCV_VOID_FTYPE_VOID_PTR_VAR, prefetch64, expand_builtin_prefetch_riscv),
// zbkc or zbc
RISCV_BUILTIN (clmul_si, "clmul", RISCV_BUILTIN_DIRECT, RISCV_USI_FTYPE_USI_USI, clmul_zbkc32_or_zbc32),
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index 33620c57ca06..052acf0159d3 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -41,3 +41,4 @@ DEF_RISCV_FTYPE (2, (UDI, USI, USI))
DEF_RISCV_FTYPE (2, (UDI, UDI, USI))
DEF_RISCV_FTYPE (2, (UDI, UDI, UDI))
DEF_RISCV_FTYPE (3, (USI, USI, USI, USI))
+DEF_RISCV_FTYPE_VAR (1, (VOID, VOID_PTR))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index e00b8ee3579d..eaa8b6a9f085 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -118,7 +118,9 @@
UNSPECV_FLUSH
UNSPECV_INVAL
UNSPECV_ZERO
- UNSPECV_PREI
+ UNSPECV_PREFETCH_I
+ UNSPECV_PREFETCH_R
+ UNSPECV_PREFETCH_W
;; Zihintpause unspec
UNSPECV_PAUSE
@@ -3464,12 +3466,28 @@
}
[(set_attr "type" "cbo")])
-(define_insn "riscv_prefetchi_<mode>"
- [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
- (match_operand:X 1 "imm5_operand" "i")]
- UNSPECV_PREI)]
+(define_insn "riscv_prefetch_i_<mode>"
+ [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")
+ (match_operand:X 1 "const_int_operand" "n")]
+ UNSPECV_PREFETCH_I)]
"TARGET_ZICBOP"
- "prefetch.i\t%a0"
+ "prefetch.i\t%1(%0)"
+ [(set_attr "type" "cbo")])
+
+(define_insn "riscv_prefetch_r_<mode>"
+ [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")
+ (match_operand:X 1 "const_int_operand" "n")]
+ UNSPECV_PREFETCH_R)]
+ "TARGET_ZICBOP"
+ "prefetch.r\t%1(%0)"
+ [(set_attr "type" "cbo")])
+
+(define_insn "riscv_prefetch_w_<mode>"
+ [(unspec_volatile:X [(match_operand:X 0 "register_operand" "r")
+ (match_operand:X 1 "const_int_operand" "n")]
+ UNSPECV_PREFETCH_W)]
+ "TARGET_ZICBOP"
+ "prefetch.w\t%1(%0)"
[(set_attr "type" "cbo")])
(define_expand "extv<mode>"
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
index c5d78c1763d3..f275d4633cce 100644
--- a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-1.c
@@ -1,23 +1,28 @@
-/* { dg-do compile target { { rv64-*-*}}} */
-/* { dg-options "-march=rv64gc_zicbop -mabi=lp64" } */
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
void foo (char *p)
{
- __builtin_prefetch (p, 0, 0);
- __builtin_prefetch (p, 0, 1);
- __builtin_prefetch (p, 0, 2);
- __builtin_prefetch (p, 0, 3);
- __builtin_prefetch (p, 1, 0);
- __builtin_prefetch (p, 1, 1);
- __builtin_prefetch (p, 1, 2);
- __builtin_prefetch (p, 1, 3);
+ __builtin_riscv_prefetch_i (p);
+ __builtin_riscv_prefetch_i (p, 0);
+ __builtin_riscv_prefetch_i (p, 32);
+ __builtin_riscv_prefetch_i (p, -64);
+ __builtin_riscv_prefetch_r (p);
+ __builtin_riscv_prefetch_r (p, 0);
+ __builtin_riscv_prefetch_r (p, 32);
+ __builtin_riscv_prefetch_r (p, -64);
+ __builtin_riscv_prefetch_w (p);
+ __builtin_riscv_prefetch_w (p, 0);
+ __builtin_riscv_prefetch_w (p, 32);
+ __builtin_riscv_prefetch_w (p, -64);
}
-int foo1()
-{
- return __builtin_riscv_zicbop_cbo_prefetchi(1);
-}
-
-/* { dg-final { scan-assembler-times "prefetch.i" 1 } } */
-/* { dg-final { scan-assembler-times "prefetch.r" 4 } } */
-/* { dg-final { scan-assembler-times "prefetch.w" 4 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t-64\\(" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
index 6576365b39ca..17fff9e199da 100644
--- a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-2.c
@@ -1,23 +1,14 @@
-/* { dg-do compile target { { rv32-*-*}}} */
-/* { dg-options "-march=rv32gc_zicbop -mabi=ilp32" } */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zicbop -mabi=lp64" } */
-void foo (char *p)
-{
- __builtin_prefetch (p, 0, 0);
- __builtin_prefetch (p, 0, 1);
- __builtin_prefetch (p, 0, 2);
- __builtin_prefetch (p, 0, 3);
- __builtin_prefetch (p, 1, 0);
- __builtin_prefetch (p, 1, 1);
- __builtin_prefetch (p, 1, 2);
- __builtin_prefetch (p, 1, 3);
-}
+#include "cmo-zicbop-1.c"
-int foo1()
-{
- return __builtin_riscv_zicbop_cbo_prefetchi(1);
-}
-
-/* { dg-final { scan-assembler-times "prefetch.i" 1 } } */
-/* { dg-final { scan-assembler-times "prefetch.r" 4 } } */
-/* { dg-final { scan-assembler-times "prefetch.w" 4 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t-64\\(" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-3.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-3.c
new file mode 100644
index 000000000000..89bf6c57a390
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-3.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+
+void foo (void)
+{
+ /* Use NULL (0) instead of a pointer. */
+ __builtin_riscv_prefetch_i (0);
+ __builtin_riscv_prefetch_i (0, 0);
+ __builtin_riscv_prefetch_i (0, 32);
+ __builtin_riscv_prefetch_i (0, -64);
+ __builtin_riscv_prefetch_r (0);
+ __builtin_riscv_prefetch_r (0, 0);
+ __builtin_riscv_prefetch_r (0, 32);
+ __builtin_riscv_prefetch_r (0, -64);
+ __builtin_riscv_prefetch_w (0);
+ __builtin_riscv_prefetch_w (0, 0);
+ __builtin_riscv_prefetch_w (0, 32);
+ __builtin_riscv_prefetch_w (0, -64);
+}
+
+/* { dg-final { scan-assembler-times "prefetch\\.i\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.i\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.r\t-64\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t0\\(" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t32\\(" 1 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w\t-64\\(" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-4.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-4.c
new file mode 100644
index 000000000000..372fdfa3d868
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+int foo (char* p, int offset)
+{
+ __builtin_riscv_prefetch_i();
+ __builtin_riscv_prefetch_r();
+ __builtin_riscv_prefetch_w();
+}
+
+/* { dg-error "too few arguments to function '__builtin_riscv_prefetch_i'" "" { target *-*-* } 7 } */
+/* { dg-error "too few arguments to function '__builtin_riscv_prefetch_r'" "" { target *-*-* } 8 } */
+/* { dg-error "too few arguments to function '__builtin_riscv_prefetch_w'" "" { target *-*-* } 9 } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-5.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-5.c
new file mode 100644
index 000000000000..7dbfe49b24fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+int foo (char* p, int offset)
+{
+ __builtin_riscv_prefetch_i(p, offset);
+ __builtin_riscv_prefetch_r(p, offset);
+ __builtin_riscv_prefetch_w(p, offset);
+}
+
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a constant" "not compile-time constant" { target *-*-* } 7 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a constant" "not compile-time constant" { target *-*-* } 8 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a constant" "not compile-time constant" { target *-*-* } 9 } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-6.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-6.c
new file mode 100644
index 000000000000..b8deb2d6c807
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-6.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+
+int foo (char* p)
+{
+ __builtin_riscv_prefetch_i(p, 1);
+ __builtin_riscv_prefetch_r(p, 1);
+ __builtin_riscv_prefetch_w(p, 1);
+ __builtin_riscv_prefetch_i(p, 16);
+ __builtin_riscv_prefetch_r(p, 16);
+ __builtin_riscv_prefetch_w(p, 16);
+ __builtin_riscv_prefetch_i(p, -2080);
+ __builtin_riscv_prefetch_r(p, -2080);
+ __builtin_riscv_prefetch_w(p, -2080);
+ __builtin_riscv_prefetch_i(p, +2048);
+ __builtin_riscv_prefetch_r(p, +2048);
+ __builtin_riscv_prefetch_w(p, +2048);
+ __builtin_riscv_prefetch_i(p, 0x800000000000000llu);
+ __builtin_riscv_prefetch_r(p, 0x800000000000000llu);
+ __builtin_riscv_prefetch_w(p, 0x800000000000000llu);
+}
+
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a valid offset for the prefetch instruction" "unaligned offset 1" { target *-*-* } 7 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a valid offset for the prefetch instruction" "unaligned offset 1" { target *-*-* } 8 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a valid offset for the prefetch instruction" "unaligned offset 1" { target *-*-* } 9 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a valid offset for the prefetch instruction" "unaligned offset 2" { target *-*-* } 10 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a valid offset for the prefetch instruction" "unaligned offset 2" { target *-*-* } 11 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a valid offset for the prefetch instruction" "unaligned offset 2" { target *-*-* } 12 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a valid offset for the prefetch instruction" "out of range (negative)" { target *-*-* } 13 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a valid offset for the prefetch instruction" "out of range (negative)" { target *-*-* } 14 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a valid offset for the prefetch instruction" "out of range (negative)" { target *-*-* } 15 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a valid offset for the prefetch instruction" "out of range (positive 1)" { target *-*-* } 16 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a valid offset for the prefetch instruction" "out of range (positive 1)" { target *-*-* } 17 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a valid offset for the prefetch instruction" "out of range (positive 1)" { target *-*-* } 18 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_i' must be a valid offset for the prefetch instruction" "out of range (positive 2)" { target *-*-* } 19 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_r' must be a valid offset for the prefetch instruction" "out of range (positive 2)" { target *-*-* } 20 } */
+/* { dg-error "second argument to '__builtin_riscv_prefetch_w' must be a valid offset for the prefetch instruction" "out of range (positive 2)" { target *-*-* } 21 } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-1.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-1.c
new file mode 100644
index 000000000000..14b89b8ddf35
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+
+void foo (char *p)
+{
+ __builtin_prefetch (p, 0, 0);
+ __builtin_prefetch (p, 0, 1);
+ __builtin_prefetch (p, 0, 2);
+ __builtin_prefetch (p, 0, 3);
+ __builtin_prefetch (p, 1, 0);
+ __builtin_prefetch (p, 1, 1);
+ __builtin_prefetch (p, 1, 2);
+ __builtin_prefetch (p, 1, 3);
+}
+
+/* { dg-final { scan-assembler-times "prefetch\\.r" 4 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-2.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-2.c
new file mode 100644
index 000000000000..2fa38dccfcb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i_zicbop -mabi=lp64" } */
+
+#include "cmo-zicbop-by-common-1.c"
+
+/* { dg-final { scan-assembler-times "prefetch\\.r" 4 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-3.c b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-3.c
new file mode 100644
index 000000000000..37505d3d13c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/cmo-zicbop-by-common-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i_zicbop -mabi=ilp32" } */
+
+void foo (char *p)
+{
+ /* Second argument defaults to zero (read). */
+ __builtin_prefetch (p);
+ __builtin_prefetch (p, 0);
+ __builtin_prefetch (p, 1);
+}
+
+/* { dg-final { scan-assembler-times "prefetch\\.r" 2 } } */
+/* { dg-final { scan-assembler-times "prefetch\\.w" 1 } } */
--
2.42.0
^ permalink raw reply [flat|nested] 6+ messages in thread