"A 2-bit unsigned immediate."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 0, 3)")))
+
+(define_constraint "Q"
+ "An address operand that is valid for a prefetch instruction"
+ (match_operand 0 "prefetch_operand"))
(ior (match_operand 0 "const_arith_operand")
(match_operand 0 "register_operand")))
+;; REG or REG+D where D fits in a simm12 and has the low 4 bits
+;; off. The REG+D form can be reloaded into a temporary if needed
+;; after FP elimination if that exposes an invalid offset.
+(define_predicate "prefetch_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_test "const_arith_operand (op, VOIDmode)")
+ (match_test "(INTVAL (op) & 0xf) == 0"))
+ (and (match_code "plus")
+ (match_test "register_operand (XEXP (op, 0), word_mode)")
+ (match_test "const_arith_operand (XEXP (op, 1), VOIDmode)")
+ (match_test "(INTVAL (XEXP (op, 1)) & 0xf) == 0"))))
+
(define_predicate "lui_operand"
(and (match_code "const_int")
(match_test "LUI_OPERAND (INTVAL (op))")))
)
(define_insn "prefetch"
- [(prefetch (match_operand 0 "address_operand" "r")
+ [(prefetch (match_operand 0 "prefetch_operand" "Q")
(match_operand 1 "imm5_operand" "i")
(match_operand 2 "const_int_operand" "n"))]
"TARGET_ZICBOP"
(const_string "4")))])
(define_insn "riscv_prefetchi_<mode>"
- [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
+ [(unspec_volatile:X [(match_operand:X 0 "prefetch_operand" "Q")
(match_operand:X 1 "imm5_operand" "i")]
UNSPECV_PREI)]
"TARGET_ZICBOP"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicbop" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicbop" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" } } */
+
+void test1() { __builtin_prefetch((int *)2047); }
+void test2() { __builtin_prefetch((int *)1024); }
+void test3(char *x) { __builtin_prefetch(&x); }
+void test4(char *x) { __builtin_prefetch(&x[2]); }
+void test5(char *x) { __builtin_prefetch(&x[1024]); }
+
+/* So we expect test1, test3 and test4 to be a prefetch
+ with zero offset. test2 and test5 will have a 1k offset. */
+/* { dg-final { scan-assembler-times "prefetch.r\t0\\(\[a-x0-9\]+\\)" 3 } } */
+/* { dg-final { scan-assembler-times "prefetch.r\t1024" 2 } } */
+