Hi,
This adds an -mmax-vectorization option to riscv, copied verbatimly from
aarch64 :) It is an option for vector code analysis. Internally it
increases scalar costs by a large factor so every vector approach will be
profitable. As opposed to -fno-vect-cost-model, we will still compare
the vector approaches amongst each other, though.
In order to handle this argument without an '=' needed to change the
parsing flow slightly. It's not ideal but just to get it working,
I'm sure Kito has comments on that.
Regtested on riscv64.
Regards
Robin
gcc/ChangeLog:
* config/riscv/riscv-target-attr.cc
(riscv_target_attr_parser::handle_max_vect):
New parser entry.
(riscv_target_attr_parser::update_settings): Set max-vect
option.
(riscv_process_one_target_attr): Change null-arg handling.
* config/riscv/riscv.cc (riscv_override_options_internal): Set
max-vect option.
* config/riscv/riscv.opt: Add -mmax-vectorization option.
* doc/extend.texi: Document new option.
* doc/invoke.texi: Ditto.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/autovec/max-vect-1.c: New test.
* gcc.target/riscv/rvv/autovec/max-vect-2.c: New test.
---
gcc/config/riscv/riscv-target-attr.cc | 60 +++++++++++++------
gcc/config/riscv/riscv.cc | 6 ++
gcc/config/riscv/riscv.opt | 4 ++
gcc/doc/extend.texi | 10 ++++
gcc/doc/invoke.texi | 8 +++
.../gcc.target/riscv/rvv/autovec/max-vect-1.c | 21 +++++++
.../gcc.target/riscv/rvv/autovec/max-vect-2.c | 21 +++++++
7 files changed, 111 insertions(+), 19 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
diff --git a/gcc/config/riscv/riscv-target-attr.cc
b/gcc/config/riscv/riscv-target-attr.cc
index 54edeebf93c..63c4ea2cb6c 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -51,6 +51,7 @@ public:
bool handle_cpu (const char *);
bool handle_tune (const char *);
bool handle_priority (const char *);
+ bool handle_max_vect (const char *);
void update_settings (struct gcc_options *opts) const;
private:
@@ -66,6 +67,7 @@ private:
const riscv_cpu_info *m_cpu_info;
const char *m_tune;
int m_priority;
+ bool m_max_vect;
};
}
@@ -77,20 +79,22 @@ struct riscv_attribute_info
{
const char *name;
bool (riscv_target_attr_parser::*handler) (const char *);
+ bool setter;
};
/* The target attributes that we support. */
static const struct riscv_attribute_info riscv_target_attrs[]
- = {{"arch", &riscv_target_attr_parser::handle_arch},
- {"cpu", &riscv_target_attr_parser::handle_cpu},
- {"tune", &riscv_target_attr_parser::handle_tune},
- {NULL, NULL}};
+ = {{"arch", &riscv_target_attr_parser::handle_arch, true},
+ {"cpu", &riscv_target_attr_parser::handle_cpu, true},
+ {"tune", &riscv_target_attr_parser::handle_tune, true},
+ {"max-vectorization", &riscv_target_attr_parser::handle_max_vect, false},
+ {NULL, NULL, true}};
static const struct riscv_attribute_info riscv_target_version_attrs[]
- = {{"arch", &riscv_target_attr_parser::handle_arch},
- {"priority", &riscv_target_attr_parser::handle_priority},
- {NULL, NULL}};
+ = {{"arch", &riscv_target_attr_parser::handle_arch, true},
+ {"priority", &riscv_target_attr_parser::handle_priority, true},
+ {NULL, NULL, true}};
bool
riscv_target_attr_parser::parse_arch (const char *str)
@@ -254,6 +258,17 @@ riscv_target_attr_parser::handle_priority (const char *str)
return true;
}
+/* Handle max-vectorization. There are no further options, just
+ enable it. */
+
+bool
+riscv_target_attr_parser::handle_max_vect (const char *str ATTRIBUTE_UNUSED)
+{
+ m_max_vect = true;
+
+ return true;
+}
+
void
riscv_target_attr_parser::update_settings (struct gcc_options *opts) const
{
@@ -279,6 +294,9 @@ riscv_target_attr_parser::update_settings (struct
gcc_options *opts) const
if (m_priority)
opts->x_riscv_fmv_priority = m_priority;
+
+ if (m_max_vect)
+ opts->x_riscv_max_vectorization = true;
}
/* Parse ARG_STR which contains the definition of one target attribute.
@@ -303,18 +321,6 @@ riscv_process_one_target_attr (char *arg_str,
char *str_to_check = buf.get();
strcpy (str_to_check, arg_str);
- char *arg = strchr (str_to_check, '=');
-
- if (!arg)
- {
- if (loc)
- error_at (*loc, "attribute %<target(\"%s\")%> does not "
- "accept an argument", str_to_check);
- return false;
- }
-
- arg[0] = '\0';
- ++arg;
for (const auto *attr = attrs;
attr->name;
++attr)
@@ -325,6 +331,22 @@ riscv_process_one_target_attr (char *arg_str,
if (strncmp (str_to_check, attr->name, strlen (attr->name)) != 0)
continue;
+ char *arg = strchr (str_to_check, '=');
+
+ if (arg)
+ {
+ arg[0] = '\0';
+ ++arg;
+ }
+
+ if (attr->setter && !arg)
+ {
+ if (loc)
+ error_at (*loc, "attribute %<target(\"%s\")%> expects "
+ "an argument", str_to_check);
+ return false;
+ }
+
return (&attr_parser->*attr->handler) (arg);
}
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index ccaef67ada7..b0314016f01 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12115,6 +12115,12 @@ riscv_override_options_internal (struct gcc_options
*opts)
/* Convert -march and -mrvv-vector-bits to a chunks count. */
riscv_vector_chunks = riscv_convert_vector_chunks (opts);
+ /* Set scalar costing to a high value such that we always pick
+ vectorization. Increase scalar costing by 100x. */
+ if (opts->x_riscv_max_vectorization)
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ param_vect_scalar_cost_multiplier, 10000);
+
if (opts->x_flag_cf_protection != CF_NONE)
{
if ((opts->x_flag_cf_protection & CF_RETURN) == CF_RETURN
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 6543fd1c4a7..486805a0f0c 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -341,6 +341,10 @@ Target Undocumented RejectNegative Joined
Enum(vsetvl_strategy) Var(vsetvl_strat
Target Undocumented Uinteger Var(riscv_two_source_permutes) Init(0)
-param=riscv-two-source-permutes Enable permutes with two source vectors.
+mmax-vectorization
+Target Var(riscv_max_vectorization) Save
+Override the scalar cost model such that vectorization is always profitable.
+
Enum
Name(stringop_strategy) Type(enum stringop_strategy_enum)
Valid arguments to -mstringop-strategy=:
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 616e05ebbd2..7174ab5b509 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5774,6 +5774,16 @@ Specifies the core for which to tune the performance of
this function and also
whose architectural features to use. The behavior and valid arguments are the
same as for the @option{-mcpu=} command-line option.
+@cindex @code{max-vectorization} function attribute, RISC-V
+@item max-vectorization
+@itemx no-max-vectorization
+@code{max-vectorization} tells GCC's vectorizer to treat all vector
+loops as being more profitable than the original scalar loops when
+optimizing the current function. @code{no-max-vectorization} disables
+this behavior.
+This corresponds to the behavior of the command-line options
+@option{-mmax-vectorization} and @option{-mno-max-vectorization}.
+
@end table
The above target attributes can be specified as follows:
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index de38cab887a..d6d4be8f022 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -31764,6 +31764,14 @@ Do not or do generate unaligned vector memory
accesses. The default is set
to off unless the processor we are optimizing for explicitly supports
element-misaligned vector memory access.
+@item -mmax-vectorization
+@itemx -mno-max-vectorization
+Enable or disable an override to vectorizer cost model making vectorization
+always appear profitable. This option can be combined with
+@option{-mautovec-preference} allowing precise control over which ISA will be
+used for auto-vectorization. Unlike @option{-fno-vect-cost-model} or
+@option{-fvect-cost-model=unlimited} this option does not turn off cost
+comparison between different vector modes.
@opindex mcmodel=
@opindex mcmodel=medlow
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
new file mode 100644
index 00000000000..923c1f8fb9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -fdump-tree-vect-details" } */
+
+void __attribute__ (( target ("max-vectorization")))
+foo (char *restrict a, int *restrict b, short *restrict c,
+ int *restrict d, int stride)
+{
+ if (stride <= 1)
+ return;
+
+ for (int i = 0; i < 3; i++)
+ {
+ int res = c[i];
+ int t = b[d[i]];
+ if (a[c[i]] != 0)
+ res = t * b[d[i]];
+ c[i] = res;
+ }
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
new file mode 100644
index 00000000000..fc5c2ada224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/max-vect-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -mmax-vectorization
-fdump-tree-vect-details" } */
+
+void
+foo (char *restrict a, int *restrict b, short *restrict c,
+ int *restrict d, int stride)
+{
+ if (stride <= 1)
+ return;
+
+ for (int i = 0; i < 3; i++)
+ {
+ int res = c[i];
+ int t = b[d[i]];
+ if (a[c[i]] != 0)
+ res = t * b[d[i]];
+ c[i] = res;
+ }
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
--
2.51.0