* [PATCH v3 1/6] RISC-V: autovec: Add new predicates and function prototypes
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
2023-03-08 3:27 ` [PATCH v3 2/6] RISC-V: autovec: Export policy functions to global scope Michael Collison
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Juzhe Zhong <juzhe.zhong@rivai.ai>
* config/riscv/riscv-protos.h (riscv_classify_vlmul_field):
New external declaration.
(riscv_vector_preferred_simd_mode): Ditto.
(riscv_tuple_mode_p): Ditto.
(riscv_vector_mask_mode_p): Ditto.
(riscv_classify_nf): Ditto.
(riscv_vlmul_regsize): Ditto.
(riscv_vector_preferred_simd_mode): Ditto.
(riscv_vector_get_mask_mode): Ditto.
(emit_vlmax_vsetvl): Ditto.
(get_mask_policy_no_pred): Ditto.
(get_tail_policy_no_pred): Ditto.
* config/riscv/riscv-opts.h (riscv_vector_bits_enum): New enum.
(riscv_vector_lmul_enum): Ditto.
(vlmul_field_enum): Ditto.
* config/riscv/riscv-v.cc (emit_vlmax_vsetvl):
Remove static scope.
* config/riscv/riscv.opt (riscv_vector_lmul):
New option -mriscv_vector_lmul.
* config/riscv/predicates.md (p_reg_or_const_csr_operand):
New predicate.
(vector_reg_or_const_dup_operand): Ditto.
---
gcc/config/riscv/predicates.md | 13 +++++++++++
gcc/config/riscv/riscv-opts.h | 40 +++++++++++++++++++++++++++++++++
gcc/config/riscv/riscv-protos.h | 15 +++++++++++++
gcc/config/riscv/riscv-v.cc | 2 +-
gcc/config/riscv/riscv.opt | 20 +++++++++++++++++
5 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 0d9d7701c7e..19aa5e12920 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -264,6 +264,14 @@
})
;; Predicates for the V extension.
+(define_special_predicate "p_reg_or_const_csr_operand"
+ (match_code "reg, subreg, const_int")
+{
+ if (CONST_INT_P (op))
+ return satisfies_constraint_K (op);
+ return GET_MODE (op) == Pmode;
+})
+
(define_special_predicate "vector_length_operand"
(ior (match_operand 0 "pmode_register_operand")
(match_operand 0 "const_csr_operand")))
@@ -291,6 +299,11 @@
(and (match_code "const_vector")
(match_test "rtx_equal_p (op, riscv_vector::gen_scalar_move_mask (GET_MODE (op)))")))
+(define_predicate "vector_reg_or_const_dup_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_test "const_vec_duplicate_p (op)
+ && !CONST_POLY_INT_P (CONST_VECTOR_ELT (op, 0))")))
+
(define_predicate "vector_mask_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "vector_all_trues_mask_operand")))
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index ff398c0a2ae..c6b6d84fce4 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -67,6 +67,46 @@ enum stack_protector_guard {
SSP_GLOBAL /* global canary */
};
+/* RVV vector register sizes. */
+enum riscv_vector_bits_enum
+{
+ RVV_SCALABLE,
+ RVV_NOT_IMPLEMENTED = RVV_SCALABLE,
+ RVV_64 = 64,
+ RVV_128 = 128,
+ RVV_256 = 256,
+ RVV_512 = 512,
+ RVV_1024 = 1024,
+ RVV_2048 = 2048,
+ RVV_4096 = 4096,
+ RVV_8192 = 8192,
+ RVV_16384 = 16384,
+ RVV_32768 = 32768,
+ RVV_65536 = 65536
+};
+
+/* vectorization factor. */
+enum riscv_vector_lmul_enum
+{
+ RVV_LMUL1 = 1,
+ RVV_LMUL2 = 2,
+ RVV_LMUL4 = 4,
+ RVV_LMUL8 = 8
+};
+
+enum vlmul_field_enum
+{
+ VLMUL_FIELD_000, /* LMUL = 1. */
+ VLMUL_FIELD_001, /* LMUL = 2. */
+ VLMUL_FIELD_010, /* LMUL = 4. */
+ VLMUL_FIELD_011, /* LMUL = 8. */
+ VLMUL_FIELD_100, /* RESERVED. */
+ VLMUL_FIELD_101, /* LMUL = 1/8. */
+ VLMUL_FIELD_110, /* LMUL = 1/4. */
+ VLMUL_FIELD_111, /* LMUL = 1/2. */
+ MAX_VLMUL_FIELD
+};
+
#define MASK_ZICSR (1 << 0)
#define MASK_ZIFENCEI (1 << 1)
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 88a6bf5442f..6a486a1cd61 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -217,4 +217,19 @@ const unsigned int RISCV_BUILTIN_SHIFT = 1;
/* Mask that selects the riscv_builtin_class part of a function code. */
const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1;
+/* Routines implemented in riscv-v.cc. */
+
+namespace riscv_vector {
+extern unsigned int riscv_classify_vlmul_field (enum machine_mode m);
+extern machine_mode riscv_vector_preferred_simd_mode (scalar_mode mode,
+ unsigned vf);
+extern bool riscv_tuple_mode_p (machine_mode);
+extern bool riscv_vector_mask_mode_p (machine_mode);
+extern int riscv_classify_nf (machine_mode);
+extern int riscv_vlmul_regsize (machine_mode);
+extern opt_machine_mode riscv_vector_get_mask_mode (machine_mode mode);
+extern rtx emit_vlmax_vsetvl (machine_mode vmode);
+extern rtx get_mask_policy_no_pred ();
+extern rtx get_tail_policy_no_pred ();
+}
#endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index d65c65b26cd..2d2de6e4a6c 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -109,7 +109,7 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
&& IN_RANGE (INTVAL (elt), minval, maxval));
}
-static rtx
+rtx
emit_vlmax_vsetvl (machine_mode vmode)
{
rtx vl = gen_reg_rtx (Pmode);
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 95535235354..27005fb0f4a 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -70,6 +70,26 @@ Enum(abi_type) String(lp64f) Value(ABI_LP64F)
EnumValue
Enum(abi_type) String(lp64d) Value(ABI_LP64D)
+Enum
+Name(riscv_vector_lmul) Type(enum riscv_vector_lmul_enum)
+The possible vectorization factor:
+
+EnumValue
+Enum(riscv_vector_lmul) String(1) Value(RVV_LMUL1)
+
+EnumValue
+Enum(riscv_vector_lmul) String(2) Value(RVV_LMUL2)
+
+EnumValue
+Enum(riscv_vector_lmul) String(4) Value(RVV_LMUL4)
+
+EnumValue
+Enum(riscv_vector_lmul) String(8) Value(RVV_LMUL8)
+
+mriscv-vector-lmul=
+Target RejectNegative Joined Enum(riscv_vector_lmul) Var(riscv_vector_lmul) Init(RVV_LMUL1)
+-mriscv-vector-lmul=<lmul> Set the vf using lmul in auto-vectorization.
+
mfdiv
Target Mask(FDIV)
Use hardware floating-point divide and square root instructions.
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 2/6] RISC-V: autovec: Export policy functions to global scope
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
2023-03-08 3:27 ` [PATCH v3 1/6] RISC-V: autovec: Add new predicates and function prototypes Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
2023-03-08 3:27 ` [PATCH v3 3/6] RISC-V: autovec: Add auto-vectorization support functions Michael Collison
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Juzhe Zhong <juzhe.zhong@rivai.ai>
* config/riscv/riscv-vector-builtins.cc (get_tail_policy_for_pred):
Remove static declaration to to make externally visible.
(get_mask_policy_for_pred): Ditto.
* config/riscv/riscv-vector-builtins.h (get_tail_policy_for_pred):
New external declaration.
(get_mask_policy_for_pred): Ditto.
---
gcc/config/riscv/riscv-vector-builtins.cc | 4 ++--
gcc/config/riscv/riscv-vector-builtins.h | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index 2d57086262b..352ffd8867d 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -2448,7 +2448,7 @@ use_real_merge_p (enum predication_type_index pred)
/* Get TAIL policy for predication. If predication indicates TU, return the TU.
Otherwise, return the prefer default configuration. */
-static rtx
+rtx
get_tail_policy_for_pred (enum predication_type_index pred)
{
if (pred == PRED_TYPE_tu || pred == PRED_TYPE_tum || pred == PRED_TYPE_tumu)
@@ -2458,7 +2458,7 @@ get_tail_policy_for_pred (enum predication_type_index pred)
/* Get MASK policy for predication. If predication indicates MU, return the MU.
Otherwise, return the prefer default configuration. */
-static rtx
+rtx
get_mask_policy_for_pred (enum predication_type_index pred)
{
if (pred == PRED_TYPE_tumu || pred == PRED_TYPE_mu)
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
index 8464aa9b7e9..d62d2bdab54 100644
--- a/gcc/config/riscv/riscv-vector-builtins.h
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -456,6 +456,8 @@ extern const char *const operand_suffixes[NUM_OP_TYPES];
extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
extern const char *const predication_suffixes[NUM_PRED_TYPES];
extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
+extern rtx get_tail_policy_for_pred (enum predication_type_index pred);
+extern rtx get_mask_policy_for_pred (enum predication_type_index pred);
inline tree
rvv_arg_type_info::get_scalar_type (vector_type_index type_idx) const
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 3/6] RISC-V: autovec: Add auto-vectorization support functions
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
2023-03-08 3:27 ` [PATCH v3 1/6] RISC-V: autovec: Add new predicates and function prototypes Michael Collison
2023-03-08 3:27 ` [PATCH v3 2/6] RISC-V: autovec: Export policy functions to global scope Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
2023-03-08 3:27 ` [PATCH v3 4/6] RISC-V: autovec: Add target vectorization hooks Michael Collison
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Juzhe Zhong <juzhe.zhong@rivai.ai>
* config/riscv/riscv-v.cc (riscv_classify_vlmul_field):
New function.
(riscv_vector_preferred_simd_mode): Ditto.
(get_mask_policy_no_pred): Ditto.
(get_tail_policy_no_pred): Ditto.
(riscv_tuple_mode_p): Ditto.
(riscv_classify_nf): Ditto.
(riscv_vlmul_regsize): Ditto.
(riscv_vector_mask_mode_p): Ditto.
(riscv_vector_get_mask_mode): Ditto.
---
gcc/config/riscv/riscv-v.cc | 176 ++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2d2de6e4a6c..d21bde1bda6 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -39,9 +39,11 @@
#include "emit-rtl.h"
#include "tm_p.h"
#include "target.h"
+#include "targhooks.h"
#include "expr.h"
#include "optabs.h"
#include "tm-constrs.h"
+#include "riscv-vector-builtins.h"
#include "rtx-vector-builder.h"
using namespace riscv_vector;
@@ -109,6 +111,41 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
&& IN_RANGE (INTVAL (elt), minval, maxval));
}
+/* Return the vlmul field for a specific machine mode. */
+unsigned int
+riscv_classify_vlmul_field (enum machine_mode mode)
+{
+ /* Make the decision based on the mode's enum value rather than its
+ properties, so that we keep the correct classification regardless
+ of -mriscv-vector-bits. */
+ switch (mode)
+ {
+ case E_VNx8BImode:
+ return VLMUL_FIELD_111;
+
+ case E_VNx4BImode:
+ return VLMUL_FIELD_110;
+
+ case E_VNx2BImode:
+ return VLMUL_FIELD_101;
+
+ case E_VNx16BImode:
+ return VLMUL_FIELD_000;
+
+ case E_VNx32BImode:
+ return VLMUL_FIELD_001;
+
+ case E_VNx64BImode:
+ return VLMUL_FIELD_010;
+
+ default:
+ break;
+ }
+
+ /* we don't care about VLMUL for Mask. */
+ return VLMUL_FIELD_000;
+}
+
rtx
emit_vlmax_vsetvl (machine_mode vmode)
{
@@ -163,6 +200,64 @@ calculate_ratio (unsigned int sew, enum vlmul_type vlmul)
return ratio;
}
+/* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE for RVV. */
+
+machine_mode
+riscv_vector_preferred_simd_mode (scalar_mode mode, unsigned vf)
+{
+ if (!TARGET_VECTOR)
+ return word_mode;
+
+ switch (mode)
+ {
+ case E_QImode:
+ return vf == 1 ? VNx8QImode
+ : vf == 2 ? VNx16QImode
+ : vf == 4 ? VNx32QImode
+ : VNx64QImode;
+ break;
+ case E_HImode:
+ return vf == 1 ? VNx4HImode
+ : vf == 2 ? VNx8HImode
+ : vf == 4 ? VNx16HImode
+ : VNx32HImode;
+ break;
+ case E_SImode:
+ return vf == 1 ? VNx2SImode
+ : vf == 2 ? VNx4SImode
+ : vf == 4 ? VNx8SImode
+ : VNx16SImode;
+ break;
+ case E_DImode:
+ if (riscv_vector_elen_flags != MASK_VECTOR_ELEN_32
+ && riscv_vector_elen_flags != MASK_VECTOR_ELEN_FP_32)
+ return vf == 1 ? VNx1DImode
+ : vf == 2 ? VNx2DImode
+ : vf == 4 ? VNx4DImode
+ : VNx8DImode;
+ break;
+ case E_SFmode:
+ if (TARGET_HARD_FLOAT && riscv_vector_elen_flags != MASK_VECTOR_ELEN_32
+ && riscv_vector_elen_flags != MASK_VECTOR_ELEN_64)
+ return vf == 1 ? VNx2SFmode
+ : vf == 2 ? VNx4SFmode
+ : vf == 4 ? VNx8SFmode
+ : VNx16SFmode;
+ break;
+ case E_DFmode:
+ if (TARGET_DOUBLE_FLOAT && TARGET_VECTOR_ELEN_FP_64)
+ return vf == 1 ? VNx1DFmode
+ : vf == 2 ? VNx2DFmode
+ : vf == 4 ? VNx4DFmode
+ : VNx8DFmode;
+ break;
+ default:
+ break;
+ }
+
+ return word_mode;
+}
+
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
@@ -375,6 +470,87 @@ get_avl_type_rtx (enum avl_type type)
return gen_int_mode (type, Pmode);
}
+rtx
+get_mask_policy_no_pred ()
+{
+ return get_mask_policy_for_pred (PRED_TYPE_none);
+}
+
+rtx
+get_tail_policy_no_pred ()
+{
+ return get_mask_policy_for_pred (PRED_TYPE_none);
+}
+
+/* Return true if it is a RVV tuple mode. */
+bool
+riscv_tuple_mode_p (machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* Return nf for a machine mode. */
+int
+riscv_classify_nf (machine_mode mode)
+{
+ switch (mode)
+ {
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+/* Return vlmul register size for a machine mode. */
+int
+riscv_vlmul_regsize (machine_mode mode)
+{
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+ return 1;
+ switch (riscv_classify_vlmul_field (mode))
+ {
+ case VLMUL_FIELD_001:
+ return 2;
+ case VLMUL_FIELD_010:
+ return 4;
+ case VLMUL_FIELD_011:
+ return 8;
+ case VLMUL_FIELD_100:
+ gcc_unreachable ();
+ default:
+ return 1;
+ }
+}
+
+/* Return true if it is a RVV mask mode. */
+bool
+riscv_vector_mask_mode_p (machine_mode mode)
+{
+ return (mode == VNx1BImode || mode == VNx2BImode || mode == VNx4BImode
+ || mode == VNx8BImode || mode == VNx16BImode || mode == VNx32BImode
+ || mode == VNx64BImode);
+}
+
+/* Implement TARGET_VECTORIZE_GET_MASK_MODE for RVV. */
+
+opt_machine_mode
+riscv_vector_get_mask_mode (machine_mode mode)
+{
+ machine_mode mask_mode;
+ int nf = 1;
+ if (riscv_tuple_mode_p (mode))
+ nf = riscv_classify_nf (mode);
+
+ FOR_EACH_MODE_IN_CLASS (mask_mode, MODE_VECTOR_BOOL)
+ if (GET_MODE_INNER (mask_mode) == BImode
+ && known_eq (GET_MODE_NUNITS (mask_mode) * nf, GET_MODE_NUNITS (mode))
+ && riscv_vector_mask_mode_p (mask_mode))
+ return mask_mode;
+ return default_get_mask_mode (mode);
+}
+
/* Return the RVV vector mode that has NUNITS elements of mode INNER_MODE.
This function is not only used by builtins, but also will be used by
auto-vectorization in the future. */
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 4/6] RISC-V: autovec: Add target vectorization hooks
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
` (2 preceding siblings ...)
2023-03-08 3:27 ` [PATCH v3 3/6] RISC-V: autovec: Add auto-vectorization support functions Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
2023-03-08 3:27 ` [PATCH v3 5/6] RISC-V: autovec: Add autovectorization patterns for add & sub Michael Collison
2023-03-08 3:27 ` [PATCH v3 6/6] RISC-V: autovec: Add autovectorization tests " Michael Collison
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Juzhe Zhong <juzhe.zhong@rivai.ai>
* config/riscv/riscv.cc (riscv_option_override):
Set riscv_vectorization_factor.
(riscv_estimated_poly_value): Implement
TARGET_ESTIMATED_POLY_VALUE.
(riscv_preferred_simd_mode): Implement
TARGET_VECTORIZE_PREFERRED_SIMD_MODE.
(riscv_autovectorize_vector_modes): Implement
TARGET_AUTOVECTORIZE_VECTOR_MODES.
(riscv_get_mask_mode): Implement TARGET_VECTORIZE_GET_MASK_MODE.
(riscv_empty_mask_is_expensive): Implement
TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE.
(riscv_vectorize_create_costs): Implement
TARGET_VECTORIZE_CREATE_COSTS.
(TARGET_ESTIMATED_POLY_VALUE): Register target macro.
(TARGET_VECTORIZE_PREFERRED_SIMD_MODE): Ditto.
(TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES): Ditto.
(TARGET_VECTORIZE_GET_MASK_MODE): Ditto.
(TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): Ditto.
(TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK): Ditto.
---
gcc/config/riscv/riscv.cc | 156 ++++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index befb9b498b7..1ca9f3c7ae4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -60,6 +60,15 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "cfgloop.h"
+#include "cfgrtl.h"
+#include "sel-sched.h"
+#include "fold-const.h"
+#include "gimple-iterator.h"
+#include "gimple-expr.h"
+#include "tree-vectorizer.h"
/* This file should be included last. */
#include "target-def.h"
@@ -275,6 +284,9 @@ poly_uint16 riscv_vector_chunks;
/* The number of bytes in a vector chunk. */
unsigned riscv_bytes_per_vector_chunk;
+/* Prefer vf for auto-vectorizer. */
+unsigned riscv_vectorization_factor;
+
/* Index R is the smallest register class that contains register R. */
const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
GR_REGS, GR_REGS, GR_REGS, GR_REGS,
@@ -6199,6 +6211,10 @@ riscv_option_override (void)
/* Convert -march to a chunks count. */
riscv_vector_chunks = riscv_convert_vector_bits ();
+
+ if (TARGET_VECTOR)
+ riscv_vectorization_factor = riscv_vector_lmul;
+
}
/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
@@ -6893,6 +6909,128 @@ riscv_dwarf_poly_indeterminate_value (unsigned int i, unsigned int *factor,
return RISCV_DWARF_VLENB;
}
+/* Implement TARGET_ESTIMATED_POLY_VALUE.
+ Look into the tuning structure for an estimate.
+ KIND specifies the type of requested estimate: min, max or likely.
+ For cores with a known RVV width all three estimates are the same.
+ For generic RVV tuning we want to distinguish the maximum estimate from
+ the minimum and likely ones.
+ The likely estimate is the same as the minimum in that case to give a
+ conservative behavior of auto-vectorizing with RVV when it is a win
+ even for 128-bit RVV.
+ When RVV width information is available VAL.coeffs[1] is multiplied by
+ the number of VQ chunks over the initial Advanced SIMD 128 bits. */
+
+static HOST_WIDE_INT
+riscv_estimated_poly_value (poly_int64 val,
+ poly_value_estimate_kind kind = POLY_VALUE_LIKELY)
+{
+ unsigned int width_source = BITS_PER_RISCV_VECTOR.is_constant ()
+ ? (unsigned int) BITS_PER_RISCV_VECTOR.to_constant ()
+ : (unsigned int) RVV_SCALABLE;
+
+ /* If there is no core-specific information then the minimum and likely
+ values are based on 128-bit vectors and the maximum is based on
+ the architectural maximum of 2048 bits. */
+ if (width_source == RVV_SCALABLE)
+ switch (kind)
+ {
+ case POLY_VALUE_MIN:
+ case POLY_VALUE_LIKELY:
+ return val.coeffs[0];
+
+ case POLY_VALUE_MAX:
+ return val.coeffs[0] + val.coeffs[1] * 15;
+ }
+
+ /* Allow BITS_PER_RISCV_VECTOR to be a bitmask of different VL, treating the
+ lowest as likely. This could be made more general if future -mtune
+ options need it to be. */
+ if (kind == POLY_VALUE_MAX)
+ width_source = 1 << floor_log2 (width_source);
+ else
+ width_source = least_bit_hwi (width_source);
+
+ /* If the core provides width information, use that. */
+ HOST_WIDE_INT over_128 = width_source - 128;
+ return val.coeffs[0] + val.coeffs[1] * over_128 / 128;
+}
+
+/* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */
+
+static machine_mode
+riscv_preferred_simd_mode (scalar_mode mode)
+{
+ machine_mode vmode =
+ riscv_vector::riscv_vector_preferred_simd_mode (mode,
+ riscv_vectorization_factor);
+ if (VECTOR_MODE_P (vmode))
+ return vmode;
+
+ return word_mode;
+}
+
+/* Implement TARGET_AUTOVECTORIZE_VECTOR_MODES for RVV. */
+static unsigned int
+riscv_autovectorize_vector_modes (vector_modes *modes, bool)
+{
+ if (!TARGET_VECTOR)
+ return 0;
+
+ if (riscv_vectorization_factor == RVV_LMUL1)
+ {
+ modes->safe_push (VNx16QImode);
+ modes->safe_push (VNx8QImode);
+ modes->safe_push (VNx4QImode);
+ modes->safe_push (VNx2QImode);
+ }
+ else if (riscv_vectorization_factor == RVV_LMUL2)
+ {
+ modes->safe_push (VNx32QImode);
+ modes->safe_push (VNx16QImode);
+ modes->safe_push (VNx8QImode);
+ modes->safe_push (VNx4QImode);
+ }
+ else if (riscv_vectorization_factor == RVV_LMUL4)
+ {
+ modes->safe_push (VNx64QImode);
+ modes->safe_push (VNx32QImode);
+ modes->safe_push (VNx16QImode);
+ modes->safe_push (VNx8QImode);
+ }
+ else
+ {
+ modes->safe_push (VNx64QImode);
+ modes->safe_push (VNx32QImode);
+ modes->safe_push (VNx16QImode);
+ }
+
+ return 0;
+}
+
+/* Implement TARGET_VECTORIZE_GET_MASK_MODE. */
+
+static opt_machine_mode
+riscv_get_mask_mode (machine_mode mode)
+{
+ machine_mode mask_mode = VOIDmode;
+ if (TARGET_VECTOR
+ && riscv_vector::riscv_vector_get_mask_mode (mode).exists (&mask_mode))
+ return mask_mode;
+
+ return default_get_mask_mode (mode);
+}
+
+/* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. Assume for now that
+ it isn't worth branching around empty masked ops (including masked
+ stores). */
+
+static bool
+riscv_empty_mask_is_expensive (unsigned)
+{
+ return false;
+}
+
/* Return true if a shift-amount matches the trailing cleared bits on
a bitmask. */
@@ -7144,6 +7282,24 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT mask)
#undef TARGET_VERIFY_TYPE_CONTEXT
#define TARGET_VERIFY_TYPE_CONTEXT riscv_verify_type_context
+#undef TARGET_ESTIMATED_POLY_VALUE
+#define TARGET_ESTIMATED_POLY_VALUE riscv_estimated_poly_value
+
+#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
+#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE riscv_preferred_simd_mode
+
+#undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES
+#define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES riscv_autovectorize_vector_modes
+
+#undef TARGET_VECTORIZE_GET_MASK_MODE
+#define TARGET_VECTORIZE_GET_MASK_MODE riscv_get_mask_mode
+
+#undef TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE
+#define TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE riscv_empty_mask_is_expensive
+
+#undef TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK
+#define TARGET_VECTORIZE_LOOP_LEN_OVERRIDE_MASK riscv_loop_len_override_mask
+
#undef TARGET_VECTOR_ALIGNMENT
#define TARGET_VECTOR_ALIGNMENT riscv_vector_alignment
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 5/6] RISC-V: autovec: Add autovectorization patterns for add & sub
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
` (3 preceding siblings ...)
2023-03-08 3:27 ` [PATCH v3 4/6] RISC-V: autovec: Add target vectorization hooks Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
2023-03-08 3:27 ` [PATCH v3 6/6] RISC-V: autovec: Add autovectorization tests " Michael Collison
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Juzhe Zhong <juzhe.zhong@rivai.ai>
* config/riscv/riscv.md (riscv_vector_preferred_simd_mode): Include
vector-iterators.md.
* config/riscv/vector-auto.md: New file containing
autovectorization patterns.
* config/riscv/vector-iterators.md (UNSPEC_VADD/UNSPEC_VSUB):
New unspecs for autovectorization patterns.
* config/riscv/vector.md: Remove include of vector-iterators.md
and include vector-auto.md.
---
gcc/config/riscv/riscv.md | 1 +
gcc/config/riscv/vector-auto.md | 172 +++++++++++++++++++++++++++
gcc/config/riscv/vector-iterators.md | 2 +
gcc/config/riscv/vector.md | 4 +-
4 files changed, 177 insertions(+), 2 deletions(-)
create mode 100644 gcc/config/riscv/vector-auto.md
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 6c3176042fb..a504ace72e5 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -131,6 +131,7 @@
(include "predicates.md")
(include "constraints.md")
(include "iterators.md")
+(include "vector-iterators.md")
;; ....................
;;
diff --git a/gcc/config/riscv/vector-auto.md b/gcc/config/riscv/vector-auto.md
new file mode 100644
index 00000000000..5227a73d96d
--- /dev/null
+++ b/gcc/config/riscv/vector-auto.md
@@ -0,0 +1,172 @@
+;; Machine description for RISC-V 'V' Extension for GNU compiler.
+;; Copyright (C) 2022-2023 Free Software Foundation, Inc.
+;; Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
+;; Contributed by Michael Collison (collison@rivosinc.com, Rivos Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Addition
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vadd.vv
+;; - vadd.vx
+;; - vadd.vi
+;; -------------------------------------------------------------------------
+
+(define_expand "add<mode>3"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:VI 1 "register_operand")
+ (match_operand:VI 2 "vector_arith_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = RVV_VUNDEF (<MODE>mode);
+ rtx vl = emit_vlmax_vsetvl (<MODE>mode);
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = CONSTM1_RTX(<VM>mode);
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_add<mode>(operands[0], mask, merge, operands[1], operands[2],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+
+ DONE;
+})
+
+(define_expand "cond_add<mode>"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:<VM> 1 "register_operand")
+ (match_operand:VI 2 "register_operand")
+ (match_operand:VI 3 "vector_reg_or_const_dup_operand")
+ (match_operand:VI 4 "register_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = operands[4];
+ rtx vl = emit_vlmax_vsetvl (<MODE>mode);
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = operands[1];
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_add<mode>(operands[0], mask, merge, operands[2], operands[3],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+ DONE;
+})
+
+(define_expand "len_add<mode>"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:VI 1 "register_operand")
+ (match_operand:VI 2 "vector_reg_or_const_dup_operand")
+ (match_operand 3 "p_reg_or_const_csr_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = RVV_VUNDEF (<MODE>mode);
+ rtx vl = operands[3];
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = CONSTM1_RTX(<VM>mode);
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_add<mode>(operands[0], mask, merge, operands[1], operands[2],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+ DONE;
+})
+
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Subtraction
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vsub.vv
+;; - vsub.vx
+;; - vadd.vi
+;; - vrsub.vx
+;; - vrsub.vi
+;; -------------------------------------------------------------------------
+
+(define_expand "sub<mode>3"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:VI 1 "register_operand")
+ (match_operand:VI 2 "register_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = RVV_VUNDEF (<MODE>mode);
+ rtx vl = emit_vlmax_vsetvl (<MODE>mode);
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = CONSTM1_RTX(<VM>mode);
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_sub<mode>(operands[0], mask, merge, operands[1], operands[2],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+
+ DONE;
+})
+
+(define_expand "cond_sub<mode>"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:<VM> 1 "register_operand")
+ (match_operand:VI 2 "register_operand")
+ (match_operand:VI 3 "register_operand")
+ (match_operand:VI 4 "register_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = operands[4];
+ rtx vl = emit_vlmax_vsetvl (<MODE>mode);
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = operands[1];
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_sub<mode>(operands[0], mask, merge, operands[2], operands[3],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+
+ DONE;
+})
+
+(define_expand "len_sub<mode>"
+ [(match_operand:VI 0 "register_operand")
+ (match_operand:VI 1 "register_operand")
+ (match_operand:VI 2 "register_operand")
+ (match_operand 3 "p_reg_or_const_csr_operand")]
+ "TARGET_VECTOR"
+{
+ using namespace riscv_vector;
+
+ rtx merge = RVV_VUNDEF (<MODE>mode);
+ rtx vl = operands[3];
+ rtx mask_policy = get_mask_policy_no_pred();
+ rtx tail_policy = get_tail_policy_no_pred();
+ rtx mask = CONSTM1_RTX(<VM>mode);
+ rtx vlmax_avl_p = get_avl_type_rtx(NONVLMAX);
+
+ emit_insn(gen_pred_sub<mode>(operands[0], mask, merge, operands[1], operands[2],
+ vl, tail_policy, mask_policy, vlmax_avl_p));
+
+ DONE;
+})
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 61e141e7b64..af80143ce90 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -34,6 +34,8 @@
UNSPEC_VMULHU
UNSPEC_VMULHSU
+ UNSPEC_VADD
+ UNSPEC_VSUB
UNSPEC_VADC
UNSPEC_VSBC
UNSPEC_VMADC
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 2d4eb8bf1cd..85e531c83ef 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -26,8 +26,6 @@
;; - Auto-vectorization (TBD)
;; - Combine optimization (TBD)
-(include "vector-iterators.md")
-
(define_constants [
(INVALID_ATTRIBUTE 255)
(X0_REGNUM 0)
@@ -350,6 +348,8 @@
(symbol_ref "INTVAL (operands[4])")]
(const_int INVALID_ATTRIBUTE)))
+(include "vector-auto.md")
+
;; -----------------------------------------------------------------
;; ---- Miscellaneous Operations
;; -----------------------------------------------------------------
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 6/6] RISC-V: autovec: Add autovectorization tests for add & sub
2023-03-08 3:27 [PATCH v3 0/6] RISC-V: autovec: Add auto-vectorization support Michael Collison
` (4 preceding siblings ...)
2023-03-08 3:27 ` [PATCH v3 5/6] RISC-V: autovec: Add autovectorization patterns for add & sub Michael Collison
@ 2023-03-08 3:27 ` Michael Collison
5 siblings, 0 replies; 7+ messages in thread
From: Michael Collison @ 2023-03-08 3:27 UTC (permalink / raw)
To: gcc-patches
2023-03-02 Michael Collison <collison@rivosinc.com>
Vineet Gupta <vineetg@rivosinc.com>
* gcc.target/riscv/rvv/autovec: New directory
for autovectorization tests.
* gcc.target/riscv/rvv/autovec/loop-add-rv32.c: New
test to verify code generation of vector add on rv32.
* gcc.target/riscv/rvv/autovec/loop-add.c: New
test to verify code generation of vector add on rv64.
* gcc.target/riscv/rvv/autovec/loop-sub-rv32.c: New
test to verify code generation of vector subtract on rv32.
* gcc.target/riscv/rvv/autovec/loop-sub.c: New
test to verify code generation of vector subtract on rv64.
---
.../riscv/rvv/autovec/loop-add-rv32.c | 24 +++++++++++++++++++
.../gcc.target/riscv/rvv/autovec/loop-add.c | 24 +++++++++++++++++++
.../riscv/rvv/autovec/loop-sub-rv32.c | 24 +++++++++++++++++++
.../gcc.target/riscv/rvv/autovec/loop-sub.c | 24 +++++++++++++++++++
4 files changed, 96 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add-rv32.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub-rv32.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub.c
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add-rv32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add-rv32.c
new file mode 100644
index 00000000000..bdc3b6892e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add-rv32.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -march=rv32gcv -mabi=ilp32d" } */
+
+#include <stdint.h>
+
+#define TEST_TYPE(TYPE) \
+ void vadd_##TYPE (TYPE *dst, TYPE *a, TYPE *b, int n) \
+ { \
+ for (int i = 0; i < n; i++) \
+ dst[i] = a[i] + b[i]; \
+ }
+
+/* *int8_t not autovec currently. */
+#define TEST_ALL() \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(uint16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(uint32_t) \
+ TEST_TYPE(int64_t) \
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
+
+/* { dg-final { scan-assembler-times {\tvadd\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add.c
new file mode 100644
index 00000000000..d7f992c7d27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-add.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -march=rv64gcv -mabi=lp64d" } */
+
+#include <stdint.h>
+
+#define TEST_TYPE(TYPE) \
+ void vadd_##TYPE (TYPE *dst, TYPE *a, TYPE *b, int n) \
+ { \
+ for (int i = 0; i < n; i++) \
+ dst[i] = a[i] + b[i]; \
+ }
+
+/* *int8_t not autovec currently. */
+#define TEST_ALL() \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(uint16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(uint32_t) \
+ TEST_TYPE(int64_t) \
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
+
+/* { dg-final { scan-assembler-times {\tvadd\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub-rv32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub-rv32.c
new file mode 100644
index 00000000000..7d0a40ec539
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub-rv32.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -march=rv32gcv -mabi=ilp32d" } */
+
+#include <stdint.h>
+
+#define TEST_TYPE(TYPE) \
+ void vadd_##TYPE (TYPE *dst, TYPE *a, TYPE *b, int n) \
+ { \
+ for (int i = 0; i < n; i++) \
+ dst[i] = a[i] - b[i]; \
+ }
+
+/* *int8_t not autovec currently. */
+#define TEST_ALL() \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(uint16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(uint32_t) \
+ TEST_TYPE(int64_t) \
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
+
+/* { dg-final { scan-assembler-times {\tvsub\.vv} 6 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub.c
new file mode 100644
index 00000000000..c8900884f83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/loop-sub.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O2 -ftree-vectorize -march=rv64gcv -mabi=lp64d" } */
+
+#include <stdint.h>
+
+#define TEST_TYPE(TYPE) \
+ void vadd_##TYPE (TYPE *dst, TYPE *a, TYPE *b, int n) \
+ { \
+ for (int i = 0; i < n; i++) \
+ dst[i] = a[i] - b[i]; \
+ }
+
+/* *int8_t not autovec currently. */
+#define TEST_ALL() \
+ TEST_TYPE(int16_t) \
+ TEST_TYPE(uint16_t) \
+ TEST_TYPE(int32_t) \
+ TEST_TYPE(uint32_t) \
+ TEST_TYPE(int64_t) \
+ TEST_TYPE(uint64_t)
+
+TEST_ALL()
+
+/* { dg-final { scan-assembler-times {\tvsub\.vv} 6 } } */
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread