@@ -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
@@ -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),
@@ -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))
@@ -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>"
@@ -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 } } */
@@ -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 } } */
new file mode 100644
@@ -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 } } */
new file mode 100644
@@ -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 } */
new file mode 100644
@@ -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 } */
new file mode 100644
@@ -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 } */
new file mode 100644
@@ -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 } } */
new file mode 100644
@@ -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 } } */
new file mode 100644
@@ -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 } } */