aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog62
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/aclocal.m41
-rw-r--r--gcc/c-family/ChangeLog4
-rw-r--r--gcc/c-family/c-attribs.cc30
-rw-r--r--gcc/c/ChangeLog5
-rw-r--r--gcc/c/c-decl.cc118
-rw-r--r--gcc/c/c-parser.cc7
-rw-r--r--gcc/cfghooks.cc2
-rw-r--r--gcc/config/riscv/bitmanip.md16
-rw-r--r--gcc/config/riscv/predicates.md11
-rw-r--r--gcc/config/riscv/riscv.md39
-rwxr-xr-xgcc/configure405
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/constexpr.cc5
-rw-r--r--gcc/cp/contracts.h15
-rw-r--r--gcc/diagnostics/output-spec.cc585
-rw-r--r--gcc/diagnostics/output-spec.h88
-rw-r--r--gcc/fortran/ChangeLog14
-rw-r--r--gcc/libgdiagnostics.cc3
-rw-r--r--gcc/lto/ChangeLog5
-rw-r--r--gcc/m2/ChangeLog6
-rw-r--r--gcc/m2/gm2-compiler/M2GCCDeclare.mod13
-rw-r--r--gcc/m2/gm2-gcc/m2type.cc2
-rw-r--r--gcc/m2/gm2-gcc/m2type.def2
-rw-r--r--gcc/m2/gm2-gcc/m2type.h2
-rw-r--r--gcc/m2/gm2-libs/M2WIDESET.mod116
-rw-r--r--gcc/m2/pge-boot/Gldtoa.cc2
-rw-r--r--gcc/opts-diagnostic.cc9
-rw-r--r--gcc/testsuite/ChangeLog25
-rw-r--r--gcc/testsuite/gcc.dg/plugin/start_unit_plugin.cc2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr122079-1.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr122079-2.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr122079-3.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-1.c43
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error1.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error2.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error3.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc1.c37
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc2.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc3.c40
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-and-mvc4.c37
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error1.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error10.c13
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error11.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error12.c13
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error2.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error3.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error4.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error5.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error6.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error7.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error8.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-error9.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols1.c38
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols10.c42
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols11.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols12.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols13.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols14.c34
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols2.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols3.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols4.c31
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols5.c36
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols6.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols7.c47
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols8.c47
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mv-symbols9.c44
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-error1.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-error2.c9
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-symbols1.c25
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-symbols2.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-symbols3.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-symbols4.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/mvc-warning1.c13
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr122051.c24
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr122106.c3
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c4
-rw-r--r--gcc/tree-ssa-pre.cc35
-rw-r--r--gcc/tree-vect-loop.cc12
80 files changed, 2292 insertions, 399 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 65a07a1..81c5f80 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,65 @@
+2025-10-01 Jeff Law <jlaw@ventanamicro.com>
+
+ PR target/122106
+ * config/riscv/bitmanip.md (crc expanders): Add predicate for
+ polynomial argument. Drop unnecessary constraints.
+
+2025-10-01 Andreas Schwab <schwab@linux-m68k.org>
+
+ PR target/122066
+ * config/m68k/m68k.md (adddi3, subdi3): Strip POST_INC and PRE_DEC
+ when generating high part of the destination operand.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.cc (afdo_calculate_branch_prob): Improve dump file.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.cc (determine_scale): Break out from ...
+ (afdo_adjust_guessed_profile): ... here.
+ (scale_bb_profile): New function.
+ (afdo_annotate_cfg): Use it.
+ * params.opt (auto-profile-bbs): New parmaeter.
+ * doc/invoke.texi (auto-profile-bbs): Document.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * auto-profile.cc (afdo_unscaled_edge_count): New function based on
+ part of ...
+ (afdo_set_bb_count): ... this function; use it here.
+ (afdo_calculate_branch_prob): Try to determine edge counts using
+ phi args and goto locuses.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * Makefile.in (ALL_FDAS): New variable.
+ (ALL_HOST_BACKEND_OBJ): Use all.fda instead of cc1plus.fda
+ (all.fda): New target
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * cfghooks.cc (merge_blocks): Choose more reliable or higher BB
+ count.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * predict.cc (unlikely_executed_stmt_p): Remove redundant check.
+ (rebuild_frequencies): Also recompute unlikely bbs when profile is
+ present or consistent.
+
+2025-10-01 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/120560
+ * vr-values.cc (range_from_loop_direction): Use wi::ge_p rather
+ than wi::gt_p.
+
+2025-10-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/122110
+ * tree-vect-loop.cc (vectorizable_reduction): Relax restriction
+ to mode-precision operations.
+
2025-09-30 David Malcolm <dmalcolm@redhat.com>
* diagnostics/output-spec.cc (text_scheme_handler::make_sink): Use
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index ce6a0ae..924403e 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20251001
+20251002
diff --git a/gcc/aclocal.m4 b/gcc/aclocal.m4
index 762e949..e44fc5f 100644
--- a/gcc/aclocal.m4
+++ b/gcc/aclocal.m4
@@ -69,6 +69,7 @@ m4_include([../ltversion.m4])
m4_include([../lt~obsolete.m4])
m4_include([../config/acx.m4])
m4_include([../config/cet.m4])
+m4_include([../config/clang-plugin.m4])
m4_include([../config/codeset.m4])
m4_include([../config/depstand.m4])
m4_include([../config/dfp.m4])
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index bf15d94..9054428 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,7 @@
+2025-10-01 Alejandro Colomar <alx@kernel.org>
+
+ * c.opt.urls: Regenerate
+
2025-09-26 Alejandro Colomar <alx@kernel.org>
* c.opt: Add -Wmultiple-parameter-fwd-decl-lists
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index df9ff99..5bc5183 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -249,6 +249,29 @@ static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
ATTR_EXCL ("always_inline", true, true, true),
ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
+ ATTR_EXCL ("omp declare simd", true, true, true),
+ ATTR_EXCL ("simd", true, true, true),
+ ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_target_version_exclusions[] =
+{
+ ATTR_EXCL ("omp declare simd", true, true, true),
+ ATTR_EXCL ("simd", true, true, true),
+ ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_omp_declare_simd_exclusions[] =
+{
+ ATTR_EXCL ("target_version", true, true, true),
+ ATTR_EXCL ("target_clones", true, true, true),
+ ATTR_EXCL (NULL, false, false, false),
+};
+
+static const struct attribute_spec::exclusions attr_simd_exclusions[] =
+{
+ ATTR_EXCL ("target_version", true, true, true),
+ ATTR_EXCL ("target_clones", true, true, true),
ATTR_EXCL (NULL, false, false, false),
};
@@ -536,7 +559,7 @@ const struct attribute_spec c_common_gnu_attributes[] =
attr_target_exclusions },
{ "target_version", 1, 1, true, false, false, false,
handle_target_version_attribute,
- NULL },
+ attr_target_version_exclusions},
{ "target_clones", 1, -1, true, false, false, false,
handle_target_clones_attribute,
attr_target_clones_exclusions },
@@ -563,7 +586,8 @@ const struct attribute_spec c_common_gnu_attributes[] =
{ "returns_nonnull", 0, 0, false, true, true, false,
handle_returns_nonnull_attribute, NULL },
{ "omp declare simd", 0, -1, true, false, false, false,
- handle_omp_declare_simd_attribute, NULL },
+ handle_omp_declare_simd_attribute,
+ attr_omp_declare_simd_exclusions },
{ "omp declare variant base", 0, -1, true, false, false, false,
handle_omp_declare_variant_attribute, NULL },
{ "omp declare variant variant", 0, -1, true, false, false, false,
@@ -572,7 +596,7 @@ const struct attribute_spec c_common_gnu_attributes[] =
false, false,
handle_omp_declare_variant_attribute, NULL },
{ "simd", 0, 1, true, false, false, false,
- handle_simd_attribute, NULL },
+ handle_simd_attribute, attr_simd_exclusions },
{ "omp declare target", 0, -1, true, false, false, false,
handle_omp_declare_target_attribute, NULL },
{ "omp declare target link", 0, 0, true, false, false, false,
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index dea3113..72634fa 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * Make-lang.in: Add c_FDAS
+ (create_fdas_for_cc1): Be sure that build fails if create_gcov fails.
+
2025-09-30 Martin Uecker <uecker@tugraz.at>
PR target/121933
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 7e4c7c2..632bbf0 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -2086,6 +2086,35 @@ previous_tag (tree type)
return NULL_TREE;
}
+/* Subroutine to mark functions as versioned when using the attribute
+ 'target_version'. */
+
+static void
+maybe_mark_function_versioned (tree decl)
+{
+ if (!DECL_FUNCTION_VERSIONED (decl))
+ {
+ /* Check if the name of the function has been overridden. */
+ if (DECL_ASSEMBLER_NAME_SET_P (decl)
+ && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))[0] == '*')
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "cannot use function multiversioning on a renamed function");
+
+ /* We need to insert function version now to make sure the correct
+ pre-mangled assembler name is recorded. */
+ cgraph_node *node = cgraph_node::get_create (decl);
+
+ if (!node->function_version ())
+ node->insert_new_function_version ();
+
+ DECL_FUNCTION_VERSIONED (decl) = 1;
+
+ tree mangled_name
+ = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl));
+ SET_DECL_ASSEMBLER_NAME (decl, mangled_name);
+ }
+}
+
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
Returns true if the caller should proceed to merge the two, false
if OLDDECL should simply be discarded. As a side effect, issues
@@ -2505,6 +2534,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
"but not here");
}
}
+ /* Check if these are unmergable overlapping FMV declarations. */
+ if (!TARGET_HAS_FMV_TARGET_ATTRIBUTE
+ && diagnose_versioned_decls (olddecl, newdecl))
+ return false;
}
else if (VAR_P (newdecl))
{
@@ -2971,6 +3004,12 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ if (DECL_FUNCTION_VERSIONED (olddecl)
+ || DECL_FUNCTION_VERSIONED (newdecl))
+ {
+ maybe_mark_function_versioned (olddecl);
+ maybe_mark_function_versioned (newdecl);
+ }
/* If we're redefining a function previously defined as extern
inline, make sure we emit debug info for the inline before we
throw it away, in case it was inlined into a function that
@@ -3370,6 +3409,53 @@ pushdecl (tree x)
TREE_TYPE (b_use->decl) = b_use->u.type;
}
}
+
+ /* Check if x is part of a FMV set with b_use. */
+ if (b_use && TREE_CODE (b_use->decl) == FUNCTION_DECL
+ && TREE_CODE (x) == FUNCTION_DECL && DECL_FILE_SCOPE_P (b_use->decl)
+ && DECL_FILE_SCOPE_P (x)
+ && disjoint_version_decls (x, b_use->decl)
+ && comptypes (vistype, type) != 0)
+ {
+ maybe_mark_function_versioned (b_use->decl);
+ maybe_mark_function_versioned (b->decl);
+ maybe_mark_function_versioned (x);
+
+ cgraph_node *b_node = cgraph_node::get_create (b_use->decl);
+ cgraph_function_version_info *b_v = b_node->function_version ();
+ if (!b_v)
+ b_v = b_node->insert_new_function_version ();
+
+ /* Check if this new node conflicts with any previous functions
+ in the set. */
+ cgraph_function_version_info *version = b_v;
+ for (; version; version = version->next)
+ if (!disjoint_version_decls (version->this_node->decl, x))
+ {
+ /* The decls define overlapping version, so attempt to merge
+ or diagnose the conflict. */
+ if (duplicate_decls (x, version->this_node->decl))
+ return version->this_node->decl;
+ else
+ return error_mark_node;
+ }
+
+ /* This is a new version to be added to FMV structure. */
+ cgraph_node::add_function_version (b_v, x);
+
+ /* Get the first node from the structure. */
+ cgraph_function_version_info *default_v = b_v;
+ while (default_v->prev)
+ default_v = default_v->prev;
+ /* Always use the default node for the bindings. */
+ b_use->decl = default_v->this_node->decl;
+ b->decl = default_v->this_node->decl;
+
+ /* Node is not a duplicate, so no need to do the rest of the
+ checks. */
+ return x;
+ }
+
if (duplicate_decls (x, b_use->decl))
{
if (b_use != b)
@@ -4494,6 +4580,12 @@ tree
lookup_name (tree name)
{
struct c_binding *b = I_SYMBOL_BINDING (name);
+ /* Do not resolve non-default function versions. */
+ if (b
+ && TREE_CODE (b->decl) == FUNCTION_DECL
+ && DECL_FUNCTION_VERSIONED (b->decl)
+ && !is_function_default_version (b->decl))
+ return NULL_TREE;
if (b && !b->invisible)
{
maybe_record_typedef_use (b->decl);
@@ -5776,6 +5868,17 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
&& VAR_OR_FUNCTION_DECL_P (decl))
objc_check_global_decl (decl);
+ /* To enable versions to be created across TU's we mark and mangle all
+ non-default versioned functions. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && !TARGET_HAS_FMV_TARGET_ATTRIBUTE
+ && get_target_version (decl).is_valid ())
+ {
+ maybe_mark_function_versioned (decl);
+ if (current_scope != file_scope)
+ error ("versioned declarations are only allowed at file scope");
+ }
+
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
if (do_push)
@@ -10754,6 +10857,17 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
warn_parm_array_mismatch (origloc, old_decl, parms);
}
+ /* To enable versions to be created across TU's we mark and mangle all
+ non-default versioned functions. */
+ if (TREE_CODE (decl1) == FUNCTION_DECL
+ && !TARGET_HAS_FMV_TARGET_ATTRIBUTE
+ && get_target_version (decl1).is_valid ())
+ {
+ maybe_mark_function_versioned (decl1);
+ if (current_scope != file_scope)
+ error ("versioned definitions are only allowed at file scope");
+ }
+
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
@@ -13585,6 +13699,10 @@ c_parse_final_cleanups (void)
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+ /* Call this to set cpp_implicit_aliases_done on all nodes. This is
+ important for function multiversioning aliases to get resolved. */
+ symtab->process_same_body_aliases ();
+
if (!in_lto_p)
free_attr_access_data ();
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index df44a91..7c24526 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -27776,6 +27776,13 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
clauses[0].type = CPP_EOF;
return;
}
+ if (DECL_FUNCTION_VERSIONED (fndecl))
+ {
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "%<#pragma omp declare %s%> cannot be used with function "
+ "multi-versioning", kind);
+ return;
+ }
if (parms == NULL_TREE)
parms = DECL_ARGUMENTS (fndecl);
diff --git a/gcc/cfghooks.cc b/gcc/cfghooks.cc
index 8b33468..25bc5d4 100644
--- a/gcc/cfghooks.cc
+++ b/gcc/cfghooks.cc
@@ -819,7 +819,7 @@ merge_blocks (basic_block a, basic_block b)
/* Pick the more reliable count. If both qualities agrees, pick the larger
one since turning mistakely hot code to cold is more harmful. */
- if (a->count.initialized_p ())
+ if (!a->count.initialized_p ())
a->count = b->count;
else if (a->count.quality () < b->count.quality ())
a->count = b->count;
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 5fd139a..59b71ed 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -1218,13 +1218,13 @@
;; Reversed CRC 8, 16, 32 for TARGET_64
(define_expand "crc_rev<ANYI1:mode><ANYI:mode>4"
;; return value (calculated CRC)
- [(set (match_operand:ANYI 0 "register_operand" "=r")
+ [(set (match_operand:ANYI 0 "register_operand")
;; initial CRC
- (unspec:ANYI [(match_operand:ANYI 1 "register_operand" "r")
+ (unspec:ANYI [(match_operand:ANYI 1 "register_operand")
;; data
- (match_operand:ANYI1 2 "register_operand" "r")
+ (match_operand:ANYI1 2 "register_operand")
;; polynomial without leading 1
- (match_operand:ANYI 3)]
+ (match_operand:ANYI 3 "const_int_operand")]
UNSPEC_CRC_REV))]
/* We don't support the case when data's size is bigger than CRC's size. */
"<ANYI:MODE>mode >= <ANYI1:MODE>mode"
@@ -1258,13 +1258,13 @@
;; CRC 8, 16, (32 for TARGET_64)
(define_expand "crc<SUBX1:mode><SUBX:mode>4"
;; return value (calculated CRC)
- [(set (match_operand:SUBX 0 "register_operand" "=r")
+ [(set (match_operand:SUBX 0 "register_operand")
;; initial CRC
- (unspec:SUBX [(match_operand:SUBX 1 "register_operand" "r")
+ (unspec:SUBX [(match_operand:SUBX 1 "register_operand")
;; data
- (match_operand:SUBX1 2 "register_operand" "r")
+ (match_operand:SUBX1 2 "register_operand")
;; polynomial without leading 1
- (match_operand:SUBX 3)]
+ (match_operand:SUBX 3 "const_int_operand")]
UNSPEC_CRC))]
/* We don't support the case when data's size is bigger than CRC's size. */
"(TARGET_ZBKC || TARGET_ZBC || TARGET_ZVBC)
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 777e71b..056f9e2 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -607,13 +607,12 @@
(define_predicate "ge_operator"
(match_code "ge,geu"))
-;; pmode_reg_or_uimm5_operand can be used by vsll.vx/vsrl.vx/vsra.vx instructions.
-;; Since it has the same predicate with vector_length_operand which allows register
-;; or immediate (0 ~ 31), we define this predicate same as vector_length_operand here.
-;; We don't use vector_length_operand directly to predicate vsll.vx/vsrl.vx/vsra.vx
-;; since it may be confusing.
+;; pmode_reg_or_uimm5_operand can be used by vsll.vx/vsrl.vx/vsra.vx instructions
+;; It is *not* equivalent to vector_length_operand due to the vector_length_operand
+;; needing to conditionalize some behavior on XTHEADVECTOR.
(define_special_predicate "pmode_reg_or_uimm5_operand"
- (match_operand 0 "vector_length_operand"))
+ (ior (match_operand 0 "pmode_register_operand")
+ (match_operand 0 "const_csr_operand")))
(define_special_predicate "pmode_reg_or_0_operand"
(ior (match_operand 0 "const_0_operand")
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 843a048..78a01ef 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2322,27 +2322,38 @@
else
{
rtx reg;
- rtx label = gen_label_rtx ();
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ rtx label3 = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
rtx abs_reg = gen_reg_rtx (<ANYF:MODE>mode);
rtx coeff_reg = gen_reg_rtx (<ANYF:MODE>mode);
rtx tmp_reg = gen_reg_rtx (<ANYF:MODE>mode);
- rtx fflags = gen_reg_rtx (SImode);
riscv_emit_move (tmp_reg, operands[1]);
+
+ if (flag_trapping_math)
+ {
+ /* Check if the input is a NaN. */
+ riscv_expand_conditional_branch (label1, EQ,
+ operands[1], operands[1]);
+
+ emit_jump_insn (gen_jump (label3));
+ emit_barrier ();
+
+ emit_label (label1);
+ }
+
riscv_emit_move (coeff_reg,
riscv_vector::get_fp_rounding_coefficient (<ANYF:MODE>mode));
emit_insn (gen_abs<ANYF:mode>2 (abs_reg, operands[1]));
- /* fp compare can set invalid flag for NaN, so backup fflags. */
- if (flag_trapping_math)
- emit_insn (gen_riscv_frflags (fflags));
- riscv_expand_conditional_branch (label, LT, abs_reg, coeff_reg);
+ riscv_expand_conditional_branch (label2, LT, abs_reg, coeff_reg);
emit_jump_insn (gen_jump (end_label));
emit_barrier ();
- emit_label (label);
+ emit_label (label2);
switch (<ANYF:MODE>mode)
{
case SFmode:
@@ -2361,15 +2372,17 @@
emit_insn (gen_copysign<ANYF:mode>3 (tmp_reg, abs_reg, operands[1]));
- emit_label (end_label);
+ emit_jump_insn (gen_jump (end_label));
+ emit_barrier ();
- /* Restore fflags, but after label. This is slightly different
- than glibc implementation which only needs to restore under
- the label, since it checks for NaN first, meaning following fp
- compare can't raise fp exceptons and thus not clobber fflags. */
if (flag_trapping_math)
- emit_insn (gen_riscv_fsflags (fflags));
+ {
+ emit_label (label3);
+ /* Generate a qNaN from an sNaN if needed. */
+ emit_insn (gen_add<ANYF:mode>3 (tmp_reg, operands[1], operands[1]));
+ }
+ emit_label (end_label);
riscv_emit_move (operands[0], tmp_reg);
}
diff --git a/gcc/configure b/gcc/configure
index d6cc7fc..38d8cd9 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -758,6 +758,7 @@ LIPO
NMEDIT
DSYMUTIL
STRIP
+LLVM_CONFIG
OBJDUMP
ac_ct_DUMPBIN
DUMPBIN
@@ -16455,8 +16456,266 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown
-plugin_option=
+
+# Try CLANG_PLUGIN_FILE first since GCC_PLUGIN_OPTION may return the
+# wrong plugin_option with clang.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang" >&5
+$as_echo_n "checking for clang... " >&6; }
+if ${clang_cv_is_clang+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef __clang__
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+ clang_cv_is_clang=yes
+else
+ clang_cv_is_clang=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $clang_cv_is_clang" >&5
+$as_echo "$clang_cv_is_clang" >&6; }
+ plugin_file=
+ if test $clang_cv_is_clang = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang plugin file" >&5
+$as_echo_n "checking for clang plugin file... " >&6; }
+ plugin_names="LLVMgold.so"
+ for plugin in $plugin_names; do
+ plugin_file=`${CC} ${CFLAGS} --print-file-name $plugin`
+ if test x$plugin_file = x$plugin; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}llvm-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}llvm-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LLVM_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$LLVM_CONFIG"; then
+ ac_cv_prog_LLVM_CONFIG="$LLVM_CONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LLVM_CONFIG="${ac_tool_prefix}llvm-config"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LLVM_CONFIG=$ac_cv_prog_LLVM_CONFIG
+if test -n "$LLVM_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LLVM_CONFIG" >&5
+$as_echo "$LLVM_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LLVM_CONFIG"; then
+ ac_ct_LLVM_CONFIG=$LLVM_CONFIG
+ # Extract the first word of "llvm-config", so it can be a program name with args.
+set dummy llvm-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LLVM_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_LLVM_CONFIG"; then
+ ac_cv_prog_ac_ct_LLVM_CONFIG="$ac_ct_LLVM_CONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_LLVM_CONFIG="llvm-config"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LLVM_CONFIG=$ac_cv_prog_ac_ct_LLVM_CONFIG
+if test -n "$ac_ct_LLVM_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LLVM_CONFIG" >&5
+$as_echo "$ac_ct_LLVM_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_LLVM_CONFIG" = x; then
+ LLVM_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LLVM_CONFIG=$ac_ct_LLVM_CONFIG
+ fi
+else
+ LLVM_CONFIG="$ac_cv_prog_LLVM_CONFIG"
+fi
+
+ if test "$?" != 0; then
+ as_fn_error $? "Required tool 'llvm-config' not found on PATH." "$LINENO" 5
+ fi
+ clang_lib_dir=`$LLVM_CONFIG --libdir`
+ if test -f $clang_lib_dir/$plugin; then
+ plugin_file=$clang_lib_dir/$plugin
+ fi
+ if test x$plugin_file != x$plugin; then
+ break;
+ fi
+ fi
+ done
+ if test -z $plugin_file; then
+ as_fn_error $? "Couldn't find clang plugin file for $CC." "$LINENO" 5
+ fi
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+ if test "${AR}" = "" ; then
+ as_fn_error $? "Required archive tool 'ar' not found on PATH." "$LINENO" 5
+ fi
+ plugin_option="--plugin $plugin_file"
+ touch conftest.c
+ ${AR} $plugin_option rc conftest.a conftest.c
+ if test "$?" != 0; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed: $AR $plugin_option rc" >&5
+$as_echo "$as_me: WARNING: Failed: $AR $plugin_option rc" >&2;}
+ plugin_file=
+ fi
+ rm -f conftest.*
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $plugin_file" >&5
+$as_echo "$plugin_file" >&6; }
+ fi
+ plugin_file="$plugin_file"
+
+if test -n "$plugin_file"; then
+ plugin_option="--plugin $plugin_file"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -plugin option" >&5
+$as_echo_n "checking for -plugin option... " >&6; }
+
plugin_names="liblto_plugin.so liblto_plugin-0.dll cyglto_plugin-0.dll"
+plugin_option=
for plugin in $plugin_names; do
plugin_so=`${CC} ${CFLAGS} --print-prog-name $plugin`
if test x$plugin_so = x$plugin; then
@@ -16467,7 +16726,119 @@ for plugin in $plugin_names; do
break
fi
done
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test "${AR}" = "" ; then
+ as_fn_error $? "Required archive tool 'ar' not found on PATH." "$LINENO" 5
+fi
+touch conftest.c
+${AR} $plugin_option rc conftest.a conftest.c
+if test "$?" != 0; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed: $AR $plugin_option rc" >&5
+$as_echo "$as_me: WARNING: Failed: $AR $plugin_option rc" >&2;}
+ plugin_option=
+fi
+rm -f conftest.*
+if test -n "$plugin_option"; then
+ plugin_option="$plugin_option"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $plugin_option" >&5
+$as_echo "$plugin_option" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
@@ -16562,17 +16933,15 @@ fi
test -z "$AR" && AR=ar
if test -n "$plugin_option"; then
- if $AR --help 2>&1 | grep -q "\--plugin"; then
- touch conftest.c
- $AR $plugin_option rc conftest.a conftest.c
- if test "$?" != 0; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed: $AR $plugin_option rc" >&5
-$as_echo "$as_me: WARNING: Failed: $AR $plugin_option rc" >&2;}
- else
+ case "$AR" in
+ *"$plugin_option"*)
+ ;;
+ *)
+ if $AR --help 2>&1 | grep -q "\--plugin"; then
AR="$AR $plugin_option"
fi
- rm -f conftest.*
- fi
+ ;;
+ esac
fi
test -z "$AR_FLAGS" && AR_FLAGS=cru
@@ -16779,9 +17148,15 @@ fi
test -z "$RANLIB" && RANLIB=:
if test -n "$plugin_option" && test "$RANLIB" != ":"; then
- if $RANLIB --help 2>&1 | grep -q "\--plugin"; then
- RANLIB="$RANLIB $plugin_option"
- fi
+ case "$RANLIB" in
+ *"$plugin_option"*)
+ ;;
+ *)
+ if $RANLIB --help 2>&1 | grep -q "\--plugin"; then
+ RANLIB="$RANLIB $plugin_option"
+ fi
+ ;;
+ esac
fi
@@ -21484,7 +21859,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21487 "configure"
+#line 21862 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21590,7 +21965,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21593 "configure"
+#line 21968 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 98b48ff..ab3878b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2025-10-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ * constexpr.cc (cxx_eval_constant_expression): Use revised
+ interfaces to determine if contracts are ignored and, if not,
+ whether they are evaluated.
+ * contracts.h (contract_ignored_p, contract_evaluated_p): New.
+
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * Make-lang.in: Add c++_FDAS
+ (create_fdas_for_cc1plus): Be sure that build fails if create_gcov fails.
+
2025-09-27 Jason Merrill <jason@redhat.com>
PR c++/112632
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6ebe6eb..558ef6e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -10162,14 +10162,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case PRECONDITION_STMT:
case POSTCONDITION_STMT:
{
- contract_semantic semantic = get_contract_semantic (t);
- if (semantic == CCS_IGNORE)
+ if (contract_ignored_p (t))
break;
if (!cxx_eval_assert (ctx, CONTRACT_CONDITION (t),
G_("contract predicate is false in "
"constant expression"),
- EXPR_LOCATION (t), checked_contract_p (semantic),
+ EXPR_LOCATION (t), contract_evaluated_p (t),
non_constant_p, overflow_p))
*non_constant_p = true;
r = void_node;
diff --git a/gcc/cp/contracts.h b/gcc/cp/contracts.h
index ead07d1..54eacd9 100644
--- a/gcc/cp/contracts.h
+++ b/gcc/cp/contracts.h
@@ -334,4 +334,19 @@ set_contract_semantic (tree t, contract_semantic semantic)
}
+/* Will this contract be ignored. */
+
+inline bool
+contract_ignored_p (const_tree contract)
+{
+ return (get_contract_semantic (contract) <= CCS_IGNORE);
+}
+
+/* Will this contract be evaluated? */
+
+inline bool
+contract_evaluated_p (const_tree contract)
+{
+ return (get_contract_semantic (contract) >= CCS_NEVER);
+}
#endif /* ! GCC_CP_CONTRACT_H */
diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc
index 28ea044f..dfde7f0 100644
--- a/gcc/diagnostics/output-spec.cc
+++ b/gcc/diagnostics/output-spec.cc
@@ -73,171 +73,160 @@ struct scheme_name_and_params
class output_factory
{
public:
- output_factory ();
+ output_factory (diagnostics::context &dc);
std::unique_ptr<sink>
make_sink (const context &ctxt,
diagnostics::context &dc,
const scheme_name_and_params &scheme_and_kvs);
- const scheme_handler *get_scheme_handler (const std::string &scheme_name);
+ scheme_handler *get_scheme_handler (const std::string &scheme_name);
private:
std::vector<std::unique_ptr<scheme_handler>> m_scheme_handlers;
};
-class scheme_handler
+enum key_handler::result
+key_handler::parse_bool_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ bool &out) const
{
-public:
- scheme_handler (std::string scheme_name)
- : m_scheme_name (std::move (scheme_name))
- {}
- virtual ~scheme_handler () {}
-
- const std::string &get_scheme_name () const { return m_scheme_name; }
-
- virtual std::unique_ptr<sink>
- make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const = 0;
+ if (value == "yes")
+ {
+ out = true;
+ return result::ok;
+ }
+ else if (value == "no")
+ {
+ out = false;
+ return result::ok;
+ }
+ else
+ {
+ ctxt.report_error
+ ("%<%s%s%>:"
+ " unexpected value %qs for key %qs; expected %qs or %qs",
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
+ value.c_str (),
+ key.c_str (),
+ "yes", "no");
+ return result::malformed_value;
+ }
+}
-protected:
- bool
- parse_bool_value (const context &ctxt,
- const std::string &key,
- const std::string &value,
- bool &out) const
- {
- if (value == "yes")
- {
- out = true;
- return true;
- }
- else if (value == "no")
- {
- out = false;
- return true;
- }
- else
+template <typename EnumType, size_t NumValues>
+key_handler::result
+key_handler::parse_enum_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ const std::array<std::pair<const char *,
+ EnumType>,
+ NumValues> &value_names,
+ EnumType &out) const
+{
+ for (auto &iter : value_names)
+ if (value == iter.first)
{
- ctxt.report_error
- ("%<%s%s%>:"
- " unexpected value %qs for key %qs; expected %qs or %qs",
- ctxt.get_option_name (), ctxt.get_unparsed_spec (),
- value.c_str (),
- key.c_str (),
- "yes", "no");
-
- return false;
+ out = iter.second;
+ return result::ok;
}
- }
- template <typename EnumType, size_t NumValues>
- bool
- parse_enum_value (const context &ctxt,
- const std::string &key,
- const std::string &value,
- const std::array<std::pair<const char *, EnumType>, NumValues> &value_names,
- EnumType &out) const
- {
- for (auto &iter : value_names)
- if (value == iter.first)
- {
- out = iter.second;
- return true;
- }
-
- auto_vec<const char *> known_values;
- for (auto iter : value_names)
- known_values.safe_push (iter.first);
- pp_markup::comma_separated_quoted_strings e (known_values);
- ctxt.report_error
- ("%<%s%s%>:"
- " unexpected value %qs for key %qs; known values: %e",
- ctxt.get_option_name (), ctxt.get_unparsed_spec (),
- value.c_str (),
- key.c_str (),
- &e);
- return false;
- }
-private:
- const std::string m_scheme_name;
-};
+ auto_vec<const char *> known_values;
+ for (auto iter : value_names)
+ known_values.safe_push (iter.first);
+ pp_markup::comma_separated_quoted_strings e (known_values);
+ ctxt.report_error
+ ("%<%s%s%>:"
+ " unexpected value %qs for key %qs; known values: %e",
+ ctxt.get_option_name (), ctxt.get_unparsed_spec (),
+ value.c_str (),
+ key.c_str (),
+ &e);
+ return result::malformed_value;
+}
class text_scheme_handler : public scheme_handler
{
public:
- struct decoded_args
+ text_scheme_handler (diagnostics::context &dc)
+ : scheme_handler ("text"),
+ m_show_color (pp_show_color (dc.get_reference_printer ())),
+ m_show_nesting (true),
+ m_show_locations_in_nesting (true),
+ m_show_levels (false)
{
- bool m_show_color;
- bool m_show_nesting;
- bool m_show_locations_in_nesting;
- bool m_show_levels;
- };
-
- text_scheme_handler () : scheme_handler ("text") {}
+ }
std::unique_ptr<sink>
make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const final override;
+ diagnostics::context &dc) final override;
+
+ enum result
+ maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value) final override;
+
+ void
+ get_keys (auto_vec<const char *> &out) const final override;
- bool
- decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &out_opts) const;
+private:
+ bool m_show_color;
+ bool m_show_nesting;
+ bool m_show_locations_in_nesting;
+ bool m_show_levels;
};
class sarif_scheme_handler : public scheme_handler
{
public:
- struct decoded_args
+ sarif_scheme_handler ()
+ : scheme_handler ("sarif"),
+ m_serialization_kind (sarif_serialization_kind::json)
{
- label_text m_filename;
- enum sarif_serialization_kind m_serialization_kind;
- sarif_generation_options m_generation_opts;
- };
-
- sarif_scheme_handler () : scheme_handler ("sarif") {}
+ }
std::unique_ptr<sink>
make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const final override;
+ diagnostics::context &dc) final override;
- bool
- decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &out_opts) const;
+ enum result
+ maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value) final override;
+
+ void
+ get_keys (auto_vec<const char *> &out) const final override;
private:
static std::unique_ptr<sarif_serialization_format>
make_sarif_serialization_object (enum sarif_serialization_kind);
+
+ label_text m_filename;
+ enum sarif_serialization_kind m_serialization_kind;
+ sarif_generation_options m_generation_opts;
};
class html_scheme_handler : public scheme_handler
{
public:
- struct decoded_args
- {
- label_text m_filename;
- html_generation_options m_html_gen_opts;
- };
-
html_scheme_handler () : scheme_handler ("experimental-html") {}
std::unique_ptr<sink>
make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const final override;
+ diagnostics::context &dc) final override;
+
+ enum result
+ maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value) final override;
- bool
- decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &opts_out) const;
+ void
+ get_keys (auto_vec<const char *> &out) const final override;
+
+private:
+ label_text m_filename;
+ html_generation_options m_html_gen_opts;
};
/* struct context. */
@@ -253,15 +242,38 @@ context::report_error (const char *gmsgid, ...) const
void
context::report_unknown_key (const std::string &key,
- const std::string &scheme_name,
- auto_vec<const char *> &known_keys) const
+ const scheme_handler &scheme) const
{
- pp_markup::comma_separated_quoted_strings e (known_keys);
+ auto_vec<const char *> scheme_key_vec;
+ scheme.get_keys (scheme_key_vec);
+
+ pp_markup::comma_separated_quoted_strings e_scheme_keys (scheme_key_vec);
+
+ const char *scheme_name = scheme.get_scheme_name ().c_str ();
+
+ if (m_client_keys)
+ {
+ auto_vec<const char *> client_key_vec;
+ m_client_keys->get_keys (client_key_vec);
+ if (!client_key_vec.is_empty ())
+ {
+ pp_markup::comma_separated_quoted_strings e_client_keys
+ (client_key_vec);
+ report_error
+ ("%<%s%s%>:"
+ " unknown key %qs for output scheme %qs;"
+ " scheme keys: %e; client keys: %e",
+ get_option_name (), get_unparsed_spec (),
+ key.c_str (), scheme_name,
+ &e_scheme_keys, &e_client_keys);
+ }
+ }
+
report_error
("%<%s%s%>:"
- " unknown key %qs for format %qs; known keys: %e",
+ " unknown key %qs for output scheme %qs; scheme keys: %e",
get_option_name (), get_unparsed_spec (),
- key.c_str (), scheme_name.c_str (), &e);
+ key.c_str (), scheme_name, &e_scheme_keys);
}
void
@@ -348,7 +360,7 @@ context::parse_and_make_sink (diagnostics::context &dc)
if (!parsed_arg)
return nullptr;
- output_factory factory;
+ output_factory factory (dc);
return factory.make_sink (*this, dc, *parsed_arg);
}
@@ -356,14 +368,14 @@ context::parse_and_make_sink (diagnostics::context &dc)
/* class output_factory. */
-output_factory::output_factory ()
+output_factory::output_factory (diagnostics::context &dc)
{
- m_scheme_handlers.push_back (std::make_unique<text_scheme_handler> ());
+ m_scheme_handlers.push_back (std::make_unique<text_scheme_handler> (dc));
m_scheme_handlers.push_back (std::make_unique<sarif_scheme_handler> ());
m_scheme_handlers.push_back (std::make_unique<html_scheme_handler> ());
}
-const scheme_handler *
+scheme_handler *
output_factory::get_scheme_handler (const std::string &scheme_name)
{
for (auto &iter : m_scheme_handlers)
@@ -391,61 +403,91 @@ output_factory::make_sink (const context &ctxt,
return nullptr;
}
- return scheme_handler->make_sink (ctxt, dc, scheme_and_kvs);
-}
-
-/* class text_scheme_handler : public scheme_handler. */
-
-std::unique_ptr<sink>
-text_scheme_handler::make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const
-{
- decoded_args opts;
- opts.m_show_color = pp_show_color (dc.get_reference_printer ());
- opts.m_show_nesting = true;
- opts.m_show_locations_in_nesting = true;
- opts.m_show_levels = false;
+ /* Parse key/value pairs. */
for (auto& iter : scheme_and_kvs.m_kvs)
{
const std::string &key = iter.first;
const std::string &value = iter.second;
- if (!decode_kv (ctxt, key, value, opts))
+ if (!ctxt.handle_kv (key, value, *scheme_handler))
return nullptr;
}
+ return scheme_handler->make_sink (ctxt, dc);
+}
+
+bool
+context::handle_kv (const std::string &key,
+ const std::string &value,
+ scheme_handler &scheme) const
+{
+ auto result = scheme.maybe_handle_kv (*this, key, value);
+ switch (result)
+ {
+ default: gcc_unreachable ();
+ case key_handler::result::ok:
+ return true;
+ case key_handler::result::malformed_value:
+ return false;
+ case key_handler::result::unrecognized:
+ /* Key recognized by the scheme; try the client keys. */
+ if (m_client_keys)
+ {
+ result = m_client_keys->maybe_handle_kv (*this, key, value);
+ switch (result)
+ {
+ default: gcc_unreachable ();
+ case key_handler::result::ok:
+ return true;
+ case key_handler::result::malformed_value:
+ return false;
+ case key_handler::result::unrecognized:
+ break;
+ }
+ }
+ report_unknown_key (key, scheme);
+ return false;
+ }
+}
+
+/* class text_scheme_handler : public scheme_handler. */
+
+std::unique_ptr<sink>
+text_scheme_handler::make_sink (const context &,
+ diagnostics::context &dc)
+{
auto sink = std::make_unique<diagnostics::text_sink> (dc);
- sink->set_show_nesting (opts.m_show_nesting);
- sink->set_show_locations_in_nesting (opts.m_show_locations_in_nesting);
- sink->set_show_nesting_levels (opts.m_show_levels);
- pp_show_color (sink->get_printer ()) = opts.m_show_color;
+ sink->set_show_nesting (m_show_nesting);
+ sink->set_show_locations_in_nesting (m_show_locations_in_nesting);
+ sink->set_show_nesting_levels (m_show_levels);
+ pp_show_color (sink->get_printer ()) = m_show_color;
return sink;
}
-bool
-text_scheme_handler::decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &opts_out) const
+enum key_handler::result
+text_scheme_handler::maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value)
{
if (key == "color")
- return parse_bool_value (ctxt, key, value, opts_out.m_show_color);
+ return parse_bool_value (ctxt, key, value, m_show_color);
if (key == "show-nesting")
- return parse_bool_value (ctxt, key, value, opts_out.m_show_nesting);
+ return parse_bool_value (ctxt, key, value, m_show_nesting);
if (key == "show-nesting-locations")
return parse_bool_value (ctxt, key, value,
- opts_out.m_show_locations_in_nesting);
+ m_show_locations_in_nesting);
if (key == "show-nesting-levels")
- return parse_bool_value (ctxt, key, value, opts_out.m_show_levels);
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("color");
- known_keys.safe_push ("show-nesting");
- known_keys.safe_push ("show-nesting-locations");
- known_keys.safe_push ("show-nesting-levels");
- ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
- return false;
+ return parse_bool_value (ctxt, key, value, m_show_levels);
+
+ return result::unrecognized;
+}
+
+void
+text_scheme_handler::get_keys (auto_vec<const char *> &out) const
+{
+ out.safe_push ("color");
+ out.safe_push ("show-nesting");
+ out.safe_push ("show-nesting-locations");
+ out.safe_push ("show-nesting-levels");
}
/* class sarif_scheme_handler : public scheme_handler. */
@@ -453,23 +495,11 @@ text_scheme_handler::decode_kv (const context &ctxt,
std::unique_ptr<sink>
sarif_scheme_handler::
make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const
+ diagnostics::context &dc)
{
- decoded_args opts;
- opts.m_serialization_kind = sarif_serialization_kind::json;
-
- for (auto& iter : scheme_and_kvs.m_kvs)
- {
- const std::string &key = iter.first;
- const std::string &value = iter.second;
- if (!decode_kv (ctxt, key, value, opts))
- return nullptr;
- }
-
output_file output_file_;
- if (opts.m_filename.get ())
- output_file_ = ctxt.open_output_file (std::move (opts.m_filename));
+ if (m_filename.get ())
+ output_file_ = ctxt.open_output_file (std::move (m_filename));
else
// Default filename
{
@@ -485,33 +515,32 @@ make_sink (const context &ctxt,
= open_sarif_output_file (dc,
ctxt.get_affected_location_mgr (),
basename,
- opts.m_serialization_kind);
+ m_serialization_kind);
}
if (!output_file_)
return nullptr;
auto serialization_obj
- = make_sarif_serialization_object (opts.m_serialization_kind);
+ = make_sarif_serialization_object (m_serialization_kind);
auto sink = make_sarif_sink (dc,
*ctxt.get_affected_location_mgr (),
std::move (serialization_obj),
- opts.m_generation_opts,
+ m_generation_opts,
std::move (output_file_));
return sink;
}
-bool
-sarif_scheme_handler::decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &opts_out) const
+enum key_handler::result
+sarif_scheme_handler::maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value)
{
if (key == "file")
{
- opts_out.m_filename = label_text::take (xstrdup (value.c_str ()));
- return true;
+ m_filename = label_text::take (xstrdup (value.c_str ()));
+ return result::ok;
}
if (key == "serialization")
{
@@ -522,7 +551,7 @@ sarif_scheme_handler::decode_kv (const context &ctxt,
(ctxt,
key, value,
value_names,
- opts_out.m_serialization_kind);
+ m_serialization_kind);
}
if (key == "version")
{
@@ -534,20 +563,22 @@ sarif_scheme_handler::decode_kv (const context &ctxt,
(ctxt,
key, value,
value_names,
- opts_out.m_generation_opts.m_version);
+ m_generation_opts.m_version);
}
if (key == "state-graphs")
return parse_bool_value (ctxt, key, value,
- opts_out.m_generation_opts.m_state_graph);
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("file");
- known_keys.safe_push ("serialization");
- known_keys.safe_push ("state-graphs");
- known_keys.safe_push ("version");
- ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
- return false;
+ m_generation_opts.m_state_graph);
+
+ return result::unrecognized;
+}
+
+void
+sarif_scheme_handler::get_keys (auto_vec<const char *> &out) const
+{
+ out.safe_push ("file");
+ out.safe_push ("serialization");
+ out.safe_push ("state-graphs");
+ out.safe_push ("version");
}
std::unique_ptr<sarif_serialization_format>
@@ -569,21 +600,11 @@ make_sarif_serialization_object (enum sarif_serialization_kind kind)
std::unique_ptr<sink>
html_scheme_handler::
make_sink (const context &ctxt,
- diagnostics::context &dc,
- const scheme_name_and_params &scheme_and_kvs) const
+ diagnostics::context &dc)
{
- decoded_args opts;
- for (auto& iter : scheme_and_kvs.m_kvs)
- {
- const std::string &key = iter.first;
- const std::string &value = iter.second;
- if (!decode_kv (ctxt, key, value, opts))
- return nullptr;
- }
-
output_file output_file_;
- if (opts.m_filename.get ())
- output_file_ = ctxt.open_output_file (std::move (opts.m_filename));
+ if (m_filename.get ())
+ output_file_ = ctxt.open_output_file (std::move (m_filename));
else
// Default filename
{
@@ -606,49 +627,47 @@ make_sink (const context &ctxt,
auto sink = make_html_sink (dc,
*ctxt.get_affected_location_mgr (),
- opts.m_html_gen_opts,
+ m_html_gen_opts,
std::move (output_file_));
return sink;
}
-bool
-html_scheme_handler::decode_kv (const context &ctxt,
- const std::string &key,
- const std::string &value,
- decoded_args &opts_out) const
+enum key_handler::result
+html_scheme_handler::maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value)
{
if (key == "css")
- return parse_bool_value (ctxt, key, value, opts_out.m_html_gen_opts.m_css);
+ return parse_bool_value (ctxt, key, value, m_html_gen_opts.m_css);
if (key == "file")
{
- opts_out.m_filename = label_text::take (xstrdup (value.c_str ()));
- return true;
+ m_filename = label_text::take (xstrdup (value.c_str ()));
+ return result::ok;
}
if (key == "javascript")
return parse_bool_value (ctxt, key, value,
- opts_out.m_html_gen_opts.m_javascript);
+ m_html_gen_opts.m_javascript);
if (key == "show-state-diagrams")
return parse_bool_value (ctxt, key, value,
- opts_out.m_html_gen_opts.m_show_state_diagrams);
+ m_html_gen_opts.m_show_state_diagrams);
if (key == "show-state-diagrams-dot-src")
- return parse_bool_value
- (ctxt, key, value,
- opts_out.m_html_gen_opts.m_show_state_diagrams_dot_src);
+ return parse_bool_value (ctxt, key, value,
+ m_html_gen_opts.m_show_state_diagrams_dot_src);
if (key == "show-state-diagrams-sarif")
- return parse_bool_value
- (ctxt, key, value,
- opts_out.m_html_gen_opts.m_show_state_diagrams_sarif);
-
- /* Key not found. */
- auto_vec<const char *> known_keys;
- known_keys.safe_push ("css");
- known_keys.safe_push ("file");
- known_keys.safe_push ("javascript");
- known_keys.safe_push ("show-state-diagrams");
- known_keys.safe_push ("show-state-diagram-dot-src");
- known_keys.safe_push ("show-state-diagram-sarif");
- ctxt.report_unknown_key (key, get_scheme_name (), known_keys);
- return false;
+ return parse_bool_value (ctxt, key, value,
+ m_html_gen_opts.m_show_state_diagrams_sarif);
+ return result::unrecognized;
+}
+
+void
+html_scheme_handler::get_keys (auto_vec<const char *> &out) const
+{
+ out.safe_push ("css");
+ out.safe_push ("file");
+ out.safe_push ("javascript");
+ out.safe_push ("show-state-diagrams");
+ out.safe_push ("show-state-diagrams-dot-src");
+ out.safe_push ("show-state-diagrams-sarif");
}
} // namespace output_spec
@@ -685,17 +704,19 @@ struct parser_test
class test_spec_context : public diagnostics::output_spec::dc_spec_context
{
public:
- test_spec_context (diagnostics::context &dc,
+ test_spec_context (const char *option_name,
+ const char *unparsed_spec,
+ diagnostics::output_spec::key_handler *client_keys,
line_maps *location_mgr,
- location_t loc,
- const char *option_name,
- const char *unparsed_arg)
- : dc_spec_context (dc,
+ diagnostics::context &dc,
+ location_t loc)
+ : dc_spec_context (option_name,
+ unparsed_spec,
+ client_keys,
location_mgr,
+ dc,
location_mgr,
- loc,
- option_name,
- unparsed_arg)
+ loc)
{
}
@@ -706,9 +727,15 @@ struct parser_test
}
};
- parser_test (const char *unparsed_spec)
+ parser_test (const char *unparsed_spec,
+ diagnostics::output_spec::key_handler *client_keys = nullptr)
: m_dc (),
- m_ctxt (m_dc, line_table, UNKNOWN_LOCATION, "-fOPTION=", unparsed_spec),
+ m_ctxt ("-fOPTION=",
+ unparsed_spec,
+ client_keys,
+ line_table,
+ m_dc,
+ UNKNOWN_LOCATION),
m_fmt (m_dc.get_sink (0))
{
pp_buffer (m_fmt.get_printer ())->m_flush_p = false;
@@ -720,6 +747,12 @@ struct parser_test
return diagnostics::output_spec::parse (m_ctxt);
}
+ std::unique_ptr<diagnostics::sink>
+ parse_and_make_sink ()
+ {
+ return m_ctxt.parse_and_make_sink (m_dc);
+ }
+
bool execution_failed_p () const
{
return m_dc.execution_failed_p ();
@@ -742,9 +775,6 @@ private:
static void
test_output_arg_parsing ()
{
- auto_fix_quotes fix_quotes;
- auto_fix_progname fix_progname;
-
/* Minimal correct example. */
{
parser_test pt ("foo");
@@ -831,12 +861,59 @@ test_output_arg_parsing ()
}
}
+class test_key_handler : public diagnostics::output_spec::key_handler
+{
+public:
+ test_key_handler ()
+ : m_verbose (false),
+ m_strict (false)
+ {
+ }
+
+ enum result
+ maybe_handle_kv (const diagnostics::output_spec::context &ctxt,
+ const std::string &key,
+ const std::string &value) final override
+ {
+ if (key == "verbose")
+ return parse_bool_value (ctxt, key, value, m_verbose);
+ if (key == "strict")
+ return parse_bool_value (ctxt, key, value, m_strict);
+ return result::unrecognized;
+ }
+
+ void
+ get_keys (auto_vec<const char *> &out_known_keys) const final override
+ {
+ out_known_keys.safe_push ("verbose");
+ out_known_keys.safe_push ("strict");
+ }
+
+ bool m_verbose;
+ bool m_strict;
+};
+
+static void
+test_client_arg_parsing ()
+{
+ test_key_handler client_keys;
+ parser_test pt ("text:verbose=yes,strict=no", &client_keys);
+ auto result = pt.parse_and_make_sink ();
+ ASSERT_TRUE (result.get ());
+ ASSERT_TRUE (client_keys.m_verbose);
+ ASSERT_FALSE (client_keys.m_strict);
+}
+
/* Run all of the selftests within this file. */
void
output_spec_cc_tests ()
{
+ auto_fix_quotes fix_quotes;
+ auto_fix_progname fix_progname;
+
test_output_arg_parsing ();
+ test_client_arg_parsing ();
}
} // namespace diagnostics::selftest
diff --git a/gcc/diagnostics/output-spec.h b/gcc/diagnostics/output-spec.h
index e24002b..bfc42c0 100644
--- a/gcc/diagnostics/output-spec.h
+++ b/gcc/diagnostics/output-spec.h
@@ -27,12 +27,71 @@ along with GCC; see the file COPYING3. If not see
namespace diagnostics {
namespace output_spec {
+class context;
+
+/* An abstract base class for schemes, and for client-specific keys. */
+
+class key_handler
+{
+public:
+ enum class result
+ {
+ ok,
+ unrecognized,
+ malformed_value
+ };
+
+ /* Attempt to decode KEY and VALUE, storing the decoded value. */
+ virtual enum result
+ maybe_handle_kv (const context &ctxt,
+ const std::string &key,
+ const std::string &value) = 0;
+
+ virtual void
+ get_keys (auto_vec<const char *> &out) const = 0;
+
+ enum result
+ parse_bool_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ bool &out) const;
+
+ template <typename EnumType, size_t NumValues>
+ enum result
+ parse_enum_value (const context &ctxt,
+ const std::string &key,
+ const std::string &value,
+ const std::array<std::pair<const char *, EnumType>,
+ NumValues> &value_names,
+ EnumType &out) const;
+};
+
+/* Abstract subclass for handling particular schemes and their keys. */
+
+class scheme_handler : public key_handler
+{
+public:
+ scheme_handler (std::string scheme_name)
+ : m_scheme_name (std::move (scheme_name))
+ {}
+ virtual ~scheme_handler () {}
+
+ const std::string &get_scheme_name () const { return m_scheme_name; }
+
+ virtual std::unique_ptr<sink>
+ make_sink (const context &ctxt,
+ diagnostics::context &dc) = 0;
+
+private:
+ const std::string m_scheme_name;
+};
+
/* An abstract base class for handling the DSL of -fdiagnostics-add-output=
and -fdiagnostics-set-output=. */
class context
{
- public:
+public:
std::unique_ptr<sink>
parse_and_make_sink (diagnostics::context &dc);
@@ -42,8 +101,7 @@ class context
void
report_unknown_key (const std::string &key,
- const std::string &scheme_name,
- auto_vec<const char *> &known_keys) const;
+ const scheme_handler &scheme) const;
void
report_missing_key (const std::string &key,
@@ -70,12 +128,19 @@ class context
virtual const char *
get_base_filename () const = 0;
+ bool
+ handle_kv (const std::string &key,
+ const std::string &value,
+ scheme_handler &scheme) const;
+
protected:
context (const char *option_name,
const char *unparsed_spec,
+ key_handler *client_keys,
line_maps *affected_location_mgr)
: m_option_name (option_name),
m_unparsed_spec (unparsed_spec),
+ m_client_keys (client_keys),
m_affected_location_mgr (affected_location_mgr)
{
}
@@ -86,6 +151,9 @@ protected:
// e.g. "scheme:foo=bar,key=value"
const char *m_unparsed_spec;
+ // Optional borrowed ptr to client-specific keys
+ key_handler *m_client_keys;
+
line_maps *m_affected_location_mgr;
};
@@ -94,13 +162,17 @@ protected:
struct dc_spec_context : public output_spec::context
{
public:
- dc_spec_context (diagnostics::context &dc,
+ dc_spec_context (const char *option_name,
+ const char *unparsed_spec,
+ key_handler *client_keys,
line_maps *affected_location_mgr,
+ diagnostics::context &dc,
line_maps *control_location_mgr,
- location_t loc,
- const char *option_name,
- const char *unparsed_spec)
- : context (option_name, unparsed_spec, affected_location_mgr),
+ location_t loc)
+ : context (option_name,
+ unparsed_spec,
+ client_keys,
+ affected_location_mgr),
m_dc (dc),
m_control_location_mgr (control_location_mgr),
m_loc (loc)
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index ad537f7..1453a2a 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2025-10-01 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/122080
+ * trans-array.cc (gfc_conv_array_parameter): Wrap the derivation of
+ bounds and strides for the descriptor of an optional dummy array
+ argument by a test on argument presence when it is supposed to be
+ passed to an optional argument.
+
+2025-10-01 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/122089
+ * decl.cc (gfc_get_pdt_instance): If the pdt_template is use
+ associated, 'module' field should be copied to this instance.
+
2025-09-30 Paul Thomas <pault@gcc.gnu.org>
PR fortran/102241
diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc
index 6b269a1..46714ff 100644
--- a/gcc/libgdiagnostics.cc
+++ b/gcc/libgdiagnostics.cc
@@ -2484,7 +2484,8 @@ public:
const char *unparsed_spec,
diagnostic_manager &affected_mgr,
diagnostic_manager &control_mgr)
- : context (option_name, unparsed_spec, affected_mgr.get_line_table ()),
+ : context (option_name, unparsed_spec, nullptr,
+ affected_mgr.get_line_table ()),
m_control_mgr (control_mgr)
{}
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 4da9ca3..55e0883 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,8 @@
+2025-10-01 Jan Hubicka <hubicka@ucw.cz>
+
+ * Make-lang.in: Add lto_FDAS; enable FDA collection
+ (create_fdas_for_lto1): Be sure that build fails if create_gcov fails.
+
2025-04-15 Kyrylo Tkachov <ktkachov@nvidia.com>
* lto-partition.cc (add_node_references_to_partition): Define.
diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog
index b9e2b4d..1e9f733 100644
--- a/gcc/m2/ChangeLog
+++ b/gcc/m2/ChangeLog
@@ -1,3 +1,9 @@
+2025-10-01 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/122009
+ * pge-boot/Gldtoa.cc (ldtoa_ldtoa): Change int to bool for
+ parameter sign.
+
2025-09-21 Mark Wielaard <mark@klomp.org>
* lang.opt.urls: Regenerate.
diff --git a/gcc/m2/gm2-compiler/M2GCCDeclare.mod b/gcc/m2/gm2-compiler/M2GCCDeclare.mod
index 710976e..24634fd 100644
--- a/gcc/m2/gm2-compiler/M2GCCDeclare.mod
+++ b/gcc/m2/gm2-compiler/M2GCCDeclare.mod
@@ -4447,19 +4447,6 @@ END PrintString ;
(*
- PrintKnown -
-*)
-
-PROCEDURE PrintKnown (sym: CARDINAL) ;
-BEGIN
- IF GccKnowsAbout (sym)
- THEN
- printf0 ("[gcc]")
- END
-END PrintKnown ;
-
-
-(*
PrintVerboseFromList - prints the, i, th element in the list, l.
*)
diff --git a/gcc/m2/gm2-gcc/m2type.cc b/gcc/m2/gm2-gcc/m2type.cc
index 535ab14..184b506 100644
--- a/gcc/m2/gm2-gcc/m2type.cc
+++ b/gcc/m2/gm2-gcc/m2type.cc
@@ -2213,7 +2213,7 @@ gm2_build_enumerator (location_t location, tree name, tree value)
enumvalues, list. It returns a copy of the value. */
tree
-m2type_BuildEnumerator (location_t location, char *name, tree value,
+m2type_BuildEnumerator (location_t location, const char *name, tree value,
tree *enumvalues)
{
tree id = get_identifier (name);
diff --git a/gcc/m2/gm2-gcc/m2type.def b/gcc/m2/gm2-gcc/m2type.def
index 8a72652..6f64c98 100644
--- a/gcc/m2/gm2-gcc/m2type.def
+++ b/gcc/m2/gm2-gcc/m2type.def
@@ -173,7 +173,7 @@ PROCEDURE BuildPointerType (totype: tree) : tree ;
It returns a copy of the value. --fixme-- why do this?
*)
-PROCEDURE BuildEnumerator (location: location_t; name: CharStar; value: tree;
+PROCEDURE BuildEnumerator (location: location_t; name: ConstCharStar; value: tree;
VAR enumvalues: tree) : tree ;
diff --git a/gcc/m2/gm2-gcc/m2type.h b/gcc/m2/gm2-gcc/m2type.h
index afd97f7..68015a0 100644
--- a/gcc/m2/gm2-gcc/m2type.h
+++ b/gcc/m2/gm2-gcc/m2type.h
@@ -183,7 +183,7 @@ EXTERN tree m2type_BuildStartEnumeration (location_t location, char *name,
bool ispacked);
EXTERN tree m2type_BuildEndEnumeration (location_t location, tree enumtype,
tree enumvalues);
-EXTERN tree m2type_BuildEnumerator (location_t location, char *name,
+EXTERN tree m2type_BuildEnumerator (location_t location, const char *name,
tree value, tree *enumvalues);
EXTERN tree m2type_BuildPointerType (tree totype);
EXTERN tree m2type_BuildConstPointerType (tree totype);
diff --git a/gcc/m2/gm2-libs/M2WIDESET.mod b/gcc/m2/gm2-libs/M2WIDESET.mod
index f1b1bed..93df428 100644
--- a/gcc/m2/gm2-libs/M2WIDESET.mod
+++ b/gcc/m2/gm2-libs/M2WIDESET.mod
@@ -490,21 +490,21 @@ PROCEDURE ShiftLeftByteBit (VAR dest: ARRAY OF BYTE; src: ARRAY OF BYTE;
highbit: CARDINAL;
byteshift, bitshift: CARDINAL) ;
VAR
- top, bot, mid : BYTESET ;
- i, h, from, to: CARDINAL ;
+ top, bot, mid : BYTESET ;
+ i, h, fromIdx, toIdx: CARDINAL ;
BEGIN
(* Copy the bytes into dest at the mostly correct position
(modulo byte position). *)
- to := 0 ;
- from := 0 ;
- WHILE to < byteshift DO
- dest[to] := BYTE (0) ;
- INC (to)
+ toIdx := 0 ;
+ fromIdx := 0 ;
+ WHILE toIdx < byteshift DO
+ dest[toIdx] := BYTE (0) ;
+ INC (toIdx)
END ;
- WHILE to <= HIGH (dest) DO
- dest[to] := src[from] ;
- INC (to) ;
- INC (from)
+ WHILE toIdx <= HIGH (dest) DO
+ dest[toIdx] := src[fromIdx] ;
+ INC (toIdx) ;
+ INC (fromIdx)
END ;
(* And adjust by bit shifting. *)
IF bitshift > 0
@@ -567,12 +567,12 @@ PROCEDURE ShiftRightByteBit (VAR dest: ARRAY OF BYTE; src: ARRAY OF BYTE;
highbit: CARDINAL;
byteshift, bitshift: CARDINAL) ;
VAR
- top, bot, mid : BYTESET ;
- i, h, to, from: CARDINAL ;
+ top, bot, mid : BYTESET ;
+ i, h, toIdx, fromIdx: CARDINAL ;
BEGIN
(* Copy the bytes. *)
- to := 0 ;
- from := byteshift ;
+ toIdx := 0 ;
+ fromIdx := byteshift ;
IF EnableDebugging
THEN
printf ("HIGH (dest) = %d\n", HIGH (dest))
@@ -580,15 +580,15 @@ BEGIN
IF byteshift <= HIGH (dest)
THEN
h := HIGH (dest) - byteshift ;
- WHILE to <= h DO
- dest[to] := src[from] ;
- INC (to) ;
- INC (from)
+ WHILE toIdx <= h DO
+ dest[toIdx] := src[fromIdx] ;
+ INC (toIdx) ;
+ INC (fromIdx)
END
END ;
- WHILE to <= HIGH (dest) DO
- dest[to] := BYTE (0) ;
- INC (to)
+ WHILE toIdx <= HIGH (dest) DO
+ dest[toIdx] := BYTE (0) ;
+ INC (toIdx)
END ;
(* And bit shift the remainder. *)
IF EnableDebugging
@@ -691,7 +691,7 @@ VAR
next : BOOLEAN ;
mask,
unused,
- set : BYTESET ;
+ setb : BYTESET ;
BEGIN
IF EnableDebugging
THEN
@@ -704,14 +704,14 @@ BEGIN
bytes. *)
i := 0 ;
WHILE i < high DO
- set := dest[i] ;
- next := MSB IN set ;
- set := SHIFT (set, 1) ; (* Shift left. *)
+ setb := dest[i] ;
+ next := MSB IN setb ;
+ setb := SHIFT (setb, 1) ; (* Shift left. *)
IF carry
THEN
- INCL (set, 0) (* Set bit 0. *)
+ INCL (setb, 0) (* Set bit 0. *)
END ;
- dest[i] := set ;
+ dest[i] := setb ;
carry := next ;
IF EnableDebugging
THEN
@@ -722,27 +722,27 @@ BEGIN
END ;
(* Last byte special case as there may be some unused bits which must be
preserved. *)
- set := dest[high] ;
+ setb := dest[high] ;
unused := BYTESET {} ; (* Will contain all top unused bits of dest[high]. *)
mask := - BYTESET {} ;
topbit := (highbit+1) MOD TBITSIZE (BYTE) ;
WHILE topbit # 0 DO
EXCL (mask, topbit) ;
- IF topbit IN set
+ IF topbit IN setb
THEN
- EXCL (set, topbit) ;
+ EXCL (setb, topbit) ;
INCL (unused, topbit)
END ;
topbit := (topbit+1) MOD TBITSIZE (BYTE)
END ;
- set := SHIFT (set, 1) ; (* Left shift. *)
+ setb := SHIFT (setb, 1) ; (* Left shift. *)
IF carry
THEN
- INCL (set, 0) (* Set bit 0. *)
+ INCL (setb, 0) (* Set bit 0. *)
END ;
- set := set * mask ; (* Remove all unused bits. *)
- set := set + unused ; (* Restore original unused bits. *)
- dest[high] := set ;
+ setb := setb * mask ; (* Remove all unused bits. *)
+ setb := setb + unused ; (* Restore original unused bits. *)
+ dest[high] := setb ;
IF EnableDebugging
THEN
printf ("ArithShiftLeft shifted byte dest[%d]\n", high);
@@ -785,32 +785,32 @@ VAR
next : BOOLEAN ;
mask,
unused,
- set : BYTESET ;
+ setb : BYTESET ;
BEGIN
high := HIGH (dest) ;
(* Clear any unused bits in the highest byte, but save them into unused. *)
- set := dest[high] ;
+ setb := dest[high] ;
unused := BYTESET {} ;
topbit := (highbit+1) MOD TBITSIZE (BYTE) ;
mask := - BYTESET {} ;
WHILE topbit # 0 DO
EXCL (mask, topbit) ;
- IF topbit IN set
+ IF topbit IN setb
THEN
- EXCL (set, topbit) ;
+ EXCL (setb, topbit) ;
INCL (unused, topbit)
END ;
topbit := (topbit+1) MOD TBITSIZE (BYTE)
END ;
(* Start at the top and work down to byte 0. *)
- set := set * mask ; (* Ignore unused bits. *)
- next := 0 IN set ; (* Next carry. *)
- set := SHIFT (set, -1) ; (* Shift right by 1 bit. *)
+ setb := setb * mask ; (* Ignore unused bits. *)
+ next := 0 IN setb ; (* Next carry. *)
+ setb := SHIFT (setb, -1) ; (* Shift right by 1 bit. *)
IF carry
THEN
- INCL (set, highbit MOD TBITSIZE (BYTE))
+ INCL (setb, highbit MOD TBITSIZE (BYTE))
END ;
- dest[high] := set + unused ; (* First byte is a special case as we
+ dest[high] := setb + unused ; (* First byte is a special case as we
have to preserve the unused bits. *)
(* Now we ripple through the remaining bytes, propagating local
carry between bytes. *)
@@ -818,14 +818,14 @@ BEGIN
WHILE i > 0 DO
prev := next ;
DEC (i) ;
- set := dest[i] ;
- next := 0 IN set ;
- set := SHIFT (set, -1) ;
+ setb := dest[i] ;
+ next := 0 IN setb ;
+ setb := SHIFT (setb, -1) ;
IF prev
THEN
- INCL (set, MSB)
+ INCL (setb, MSB)
END ;
- dest[i] := set
+ dest[i] := setb
END
END ArithShiftRightBit ;
@@ -914,7 +914,7 @@ VAR
high,
highplus1,
highbitplus1,
- from, to : CARDINAL ;
+ fromIdx, toIdx: CARDINAL ;
BEGIN
IF EnableDebugging
THEN
@@ -925,21 +925,21 @@ BEGIN
(* Copy the contents rotating on byte granularity, then
arithmetically shift the remaining number of bits. *)
high := HIGH (dest) ;
- from := 0 ;
+ fromIdx := 0 ;
highplus1 := high + 1 ;
highbitplus1 := highbit + 1 ;
- to := RotateCount DIV TBITSIZE (BYTE) ; (* Byte level granularity. *)
+ toIdx := RotateCount DIV TBITSIZE (BYTE) ; (* Byte level granularity. *)
REPEAT
- dest[to] := src[from] ;
+ dest[toIdx] := src[fromIdx] ;
IF EnableDebugging
THEN
printf ("RotateLeft after partial byte movement: dest[%d] := src[%d]\n",
- to, from);
+ toIdx, fromIdx);
DumpSet (dest, highbit)
END ;
- from := (from + 1) MOD highplus1 ;
- to := (to + 1) MOD highplus1 ;
- UNTIL from = 0 ;
+ fromIdx := (fromIdx + 1) MOD highplus1 ;
+ toIdx := (toIdx + 1) MOD highplus1 ;
+ UNTIL fromIdx = 0 ;
IF EnableDebugging
THEN
diff --git a/gcc/m2/pge-boot/Gldtoa.cc b/gcc/m2/pge-boot/Gldtoa.cc
index 0a43de0..9fa2fd2 100644
--- a/gcc/m2/pge-boot/Gldtoa.cc
+++ b/gcc/m2/pge-boot/Gldtoa.cc
@@ -63,7 +63,7 @@ ldtoa_strtold (void *s, bool *error)
}
char *
-ldtoa_ldtoa (long double d, int mode, int ndigits, int *decpt, int *sign)
+ldtoa_ldtoa (long double d, int mode, int ndigits, int *decpt, bool *sign)
{
char format[50];
char *p;
diff --git a/gcc/opts-diagnostic.cc b/gcc/opts-diagnostic.cc
index 6f459ec..a230c21 100644
--- a/gcc/opts-diagnostic.cc
+++ b/gcc/opts-diagnostic.cc
@@ -49,12 +49,13 @@ public:
location_t loc,
const char *option_name,
const char *option_value)
- : dc_spec_context (dc,
+ : dc_spec_context (option_name,
+ option_value,
+ nullptr,
location_mgr,
+ dc,
location_mgr,
- loc,
- option_name,
- option_value),
+ loc),
m_opts (opts)
{}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a7d81ad..7562dc2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,28 @@
+2025-10-01 Jeff Law <jlaw@ventanamicro.com>
+
+ PR target/122106
+ * gcc.target/riscv/pr122106.c: New test.
+
+2025-10-01 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/122080
+ * gfortran.dg/ubsan/missing_optional_dummy_9.f90: New test.
+
+2025-10-01 Andreas Schwab <schwab@linux-m68k.org>
+
+ PR target/122066
+ * gcc.c-torture/compile/pr122066.c: New test.
+
+2025-10-01 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/120560
+ * gcc.dg/pr120560.c: New.
+
+2025-10-01 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/122089
+ * gfortran.dg/pdt_51.f03: New test.
+
2025-09-30 David Malcolm <dmalcolm@redhat.com>
* lib/sarif.py: Remove import of ET.
diff --git a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.cc b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.cc
index 7b4f40e..3b3406e 100644
--- a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.cc
@@ -2,7 +2,7 @@
* By the time a PLUGIN_START_UNIT callback is invoked, the frontend
* initialization should have completed. At least the different *_type_nodes
* should have been created. This plugin creates an artificial global
- * interger variable.
+ * integer variable.
*
*/
#include "gcc-plugin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-1.c b/gcc/testsuite/gcc.dg/torture/pr122079-1.c
new file mode 100644
index 0000000..0af01a5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122079-1.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fcode-hoisting" } */
+
+int a, b, c;
+void e(int *f) {
+ int d = 0;
+ if (f)
+ goto g;
+ goto h;
+i:
+ d = 1 + f[0];
+j:
+ if (c)
+ goto h;
+k:
+ if (b)
+ goto i;
+ if (a)
+ goto j;
+g:
+ if (d + f[0])
+ goto k;
+h:
+ int l[] = {f[0]};
+ if (a)
+ e(l);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-2.c b/gcc/testsuite/gcc.dg/torture/pr122079-2.c
new file mode 100644
index 0000000..40c36b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122079-2.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+int a, b, *c = &a, d, e, f;
+void g(int *p) { a = p[0]; }
+int main() {
+ int h = 0;
+i:
+ d = c[0];
+ c[0] = h;
+ if (a)
+ goto j;
+k:
+ h = c[0] - 1;
+ while (1) {
+ if (b)
+ goto i;
+ if (f)
+ goto k;
+ j:
+ if (!e) {
+ int m[] = {c[0]};
+ g(m);
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr122079-3.c b/gcc/testsuite/gcc.dg/torture/pr122079-3.c
new file mode 100644
index 0000000..df95c71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122079-3.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fno-tree-loop-im" } */
+
+int a, b, c;
+void d(int[]);
+void e(int f[][2]) {
+g:
+ b = f[0][1];
+ if (c)
+ goto h;
+i:
+ if (a)
+ goto g;
+ if (f[1][1])
+ goto j;
+h:
+ if (f[1][1])
+ goto i;
+ goto k;
+j:
+ b--;
+ if (b + f[0][1])
+ goto i;
+k:
+ int l[] = {f[0][1]};
+ d(l);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-1.c b/gcc/testsuite/gcc.target/aarch64/mv-1.c
new file mode 100644
index 0000000..6f095ec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-1.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("rng"))) int
+foo ()
+{
+ return 2;
+}
+
+__attribute__ ((target_version ("flagm"))) int
+foo ()
+{
+ return 3;
+}
+
+__attribute__ ((target_version ("rng+flagm"))) int
+foo ()
+{
+ return 4;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* Check usage of the first two FMV features, in case of off-by-one errors. */
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mrng:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MrngMflagm:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mflagm:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error1.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error1.c
new file mode 100644
index 0000000..b08de29
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo () { return 3; } /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) int
+foo () { return 1; } /* { dg-error "redefinition of .foo \\\[\\\[target_clones\\(.dotprod., .sve.\\)\\\]\\\]." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error2.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error2.c
new file mode 100644
index 0000000..d34b246
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo () { return 1; } /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.default.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "conflicting types for .foo \\\[\\\[target_clones\\(.dotprod., .sve.\\)\\\]\\\].; have .float\\(void\\)." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error3.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error3.c
new file mode 100644
index 0000000..a6a45bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc-error3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+float foo () { return 1; } /* { dg-message "previous definition of .foo." } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error "redefinition of .foo \\\[\\\[target_clones\\(.default., .dotprod., .sve.\\)\\\]\\\]." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc1.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc1.c
new file mode 100644
index 0000000..39ed306
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc1.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_version("default")))
+int foo ()
+{
+ return 0;
+}
+
+__attribute__((target_clones("dotprod", "sve+sve2")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("sve", "sve2")))
+int foo ()
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc2.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc2.c
new file mode 100644
index 0000000..17c7cbd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_version("default")))
+int foo ();
+
+__attribute__((target_clones("dotprod", "sve+sve2")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("sve", "sve2")))
+int foo ()
+{
+ return 2;
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc3.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc3.c
new file mode 100644
index 0000000..8325c8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc3.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("dotprod", "sve+sve2")))
+int foo ();
+
+__attribute__((target_version("default")))
+int foo ()
+{
+ return 0;
+}
+
+__attribute__((target_clones("sve", "sve2")))
+int foo ()
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
+// { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\.default\n" 1 } }
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\._MsveMsve2\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\._Msve\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\._Msve2\n" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-and-mvc4.c b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc4.c
new file mode 100644
index 0000000..951c950
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-and-mvc4.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_version("dotprod")))
+int foo ()
+{
+ return 0;
+}
+
+__attribute__((target_clones("default", "sve+sve2")))
+int foo ()
+{
+ return 1;
+}
+
+__attribute__((target_clones("sve", "sve2")))
+int foo ()
+{
+ return 2;
+}
+
+int bar()
+{
+ return foo ();
+}
+
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Msve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error1.c b/gcc/testsuite/gcc.target/aarch64/mv-error1.c
new file mode 100644
index 0000000..61c9af2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+__attribute__ ((target_version ("default"))) int
+foo () { return 1; } /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.default.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-error "conflicting types for .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\].; have .float\\(void\\)." } */
+
+__attribute__ ((target_version ("sve"))) int
+foo2 () { return 1; } /* { dg-message "previous definition of .foo2 \\\[\\\[target_version\\(.sve.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo2 () { return 3; } /* { dg-error "conflicting types for .foo2 \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\].; have .float\\(void\\)." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error10.c b/gcc/testsuite/gcc.target/aarch64/mv-error10.c
new file mode 100644
index 0000000..218f103
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error10.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+void
+bar ()
+{
+ __attribute__ ((target_version ("dotprod"))) int
+ foo1 (); /* { dg-message "versioned declarations are only allowed at file scope" } */
+
+ __attribute__ ((target_version ("simd"))) int
+ foo2 () { return 1; } /* { dg-message "versioned definitions are only allowed at file scope" } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error11.c b/gcc/testsuite/gcc.target/aarch64/mv-error11.c
new file mode 100644
index 0000000..0fdd660
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error11.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+int fn () asm("name");
+int fn () { return 1; } /* { dg-error "cannot use function multiversioning on a renamed function" } */
+int fn [[gnu::target_version("sve")]] () { return 1; }
+
+int fn2 [[gnu::target_version("sve")]] () asm("name"); /* { dg-warning ".asm. declaration ignored due to conflict with previous rename" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error12.c b/gcc/testsuite/gcc.target/aarch64/mv-error12.c
new file mode 100644
index 0000000..45da85a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error12.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+/* { dg-require-ifunc "" } */
+
+#pragma omp declare simd
+int fn [[gnu::target_version("sve")]] () { return 1; } /* { dg-error ".#pragma omp declare simd. cannot be used with function multi-versioning" } */
+
+#pragma omp declare simd
+int fn2 () { return 1; }
+
+int fn2 [[gnu::target_version("sve")]] (); /* { dg-warning "ignoring attribute .target_version. because it conflicts with attribute .omp declare simd." } */
+
+int fn3 [[gnu::target_version("sve")]] [[gnu::simd]] () { return 1; } /* { dg-warning "ignoring attribute .simd. because it conflicts with attribute .target_version." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error2.c b/gcc/testsuite/gcc.target/aarch64/mv-error2.c
new file mode 100644
index 0000000..19d961d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\]. with type .float\\(void\\)." } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; } /* { dg-error "redefinition of .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\]." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error3.c b/gcc/testsuite/gcc.target/aarch64/mv-error3.c
new file mode 100644
index 0000000..451ce02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) float
+foo () { return 3; }
+
+__attribute__ ((target_version ("default"))) float
+foo () { return 3; } /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.default.\\)\\\]\\\]. with type .float\\(void\\)." } */
+
+__attribute__ ((target_version ("default"))) float
+foo () { return 3; } /* { dg-error "redefinition of .foo \\\[\\\[target_version\\(.default.\\)\\\]\\\]." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error4.c b/gcc/testsuite/gcc.target/aarch64/mv-error4.c
new file mode 100644
index 0000000..44d3195
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error4.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("test"))) float
+foo () { return 3; } /* { dg-error "invalid feature modifier .test. of value .test. in .target_version. attribute" } */
+
+__attribute__ ((target_version ("sve+test"))) float
+foo2 () { return 3; } /* { dg-error "invalid feature modifier .test. of value .sve.test. in .target_version. attribute" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error5.c b/gcc/testsuite/gcc.target/aarch64/mv-error5.c
new file mode 100644
index 0000000..776b80a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error5.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo(); /* { dg-message "previous declaration of .foo \\\[\\\[target_version\\(.sve\\\+sve2.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+int bar () { return foo (); } /* { dg-error "implicit declaration of function .foo." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error6.c b/gcc/testsuite/gcc.target/aarch64/mv-error6.c
new file mode 100644
index 0000000..afc71a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo () {
+ return 1;
+}
+
+__attribute__ ((target_version ("sve"))) int
+foo () { /* { dg-message "previous definition of .foo \\\[\\\[target_version\\(.sve.\\)\\\]\\\]. with type .int\\(void\\)." } */
+ return 1;
+}
+
+int bar () { return foo (); } /* { dg-error "implicit declaration of function .foo." } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo2(); /* { dg-message "previous declaration of .foo2 \\\[\\\[target_version\\(.sve\\\+sve2.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+int bar2 () { return foo2 (); } /* { dg-error "implicit declaration of function .foo2." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error7.c b/gcc/testsuite/gcc.target/aarch64/mv-error7.c
new file mode 100644
index 0000000..68db978
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error7.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo (); /* { dg-message "previous declaration of .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+int bar () { return foo (); } /* { dg-error "implicit declaration of function .foo." } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error8.c b/gcc/testsuite/gcc.target/aarch64/mv-error8.c
new file mode 100644
index 0000000..7599df1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error8.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo (int a, int (*b)[4]) { return 1; }
+
+int bar(void) {
+ __attribute__ ((target_version ("dotprod"))) int
+ foo (int a, int (*b)[5]) { return 3; } /* { dg-error "versioned definitions are only allowed at file scope" } */
+
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-error9.c b/gcc/testsuite/gcc.target/aarch64/mv-error9.c
new file mode 100644
index 0000000..dc982e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-error9.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo (); /* { dg-message "previous declaration of .foo \\\[\\\[target_version\\(.dotprod.\\)\\\]\\\]. with type .int\\(void\\)." } */
+
+int
+bar ()
+{
+ return foo (); /* { dg-error "implicit declaration of function .foo." } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols1.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols1.c
new file mode 100644
index 0000000..7982278
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// Basic case of fmv correctness with all functions and use in one TU.
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mv-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols10.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols10.c
new file mode 100644
index 0000000..d525638
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols10.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int
+foo ();
+
+int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._MsveMsve2\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols11.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols11.c
new file mode 100644
index 0000000..fd3dc34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols11.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// Check that types can be combined
+
+__attribute__ ((target_version ("default"))) int
+foo (int a, int (*b)[4]) { return 1; }
+
+__attribute__ ((target_version ("dotprod"))) int
+foo (int a, int (*b)[]) { return 3; }
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols12.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols12.c
new file mode 100644
index 0000000..1a0b667
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols12.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo () { return 1; }
+
+__attribute__ ((target_version ("dotprod"))) int
+foo () { return 3; }
+
+int bar ()
+{
+ int (*test)() = foo;
+
+ test();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\], foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\], foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols13.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols13.c
new file mode 100644
index 0000000..308dace
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols13.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+int bar ()
+{
+ int (*test)() = foo;
+
+ test();
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo () { return 3; }
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\], foo\._Mdotprod\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\], foo\.default\n" 0 } } */
+
+/* { dg-final { scan-assembler-times "\n\tadrp\tx\[0-9\]+, foo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols14.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols14.c
new file mode 100644
index 0000000..d1af69f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols14.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int foo ();
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols2.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols2.c
new file mode 100644
index 0000000..a8732ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols2.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// FMV correctness with definitions but no call
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols3.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols3.c
new file mode 100644
index 0000000..962bae9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols3.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// FMV correctness with declarations but no implementation
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols4.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols4.c
new file mode 100644
index 0000000..a476800
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols4.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// FMV correctness with a default implementation and declarations of other
+// versions
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols5.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols5.c
new file mode 100644
index 0000000..4df2000
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols5.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+// FMV correctness with default declaration, and implementations of other
+// versions.
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols6.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols6.c
new file mode 100644
index 0000000..cbf8bca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols6.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+int bar()
+{
+ return foo();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "bl\tfoo.default\n" 1 } } */
+/* { dg-final { scan-assembler-times ".global\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times ".set\tfoo,foo.default\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols7.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols7.c
new file mode 100644
index 0000000..2ea4d2e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols7.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+int
+bar ()
+{
+ return foo ();
+}
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._MsveMsve2\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols8.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols8.c
new file mode 100644
index 0000000..3e3eaf2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols8.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+__attribute__ ((target_version ("default"))) int
+foo ();
+
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("default"))) int
+foo ()
+{
+ return 1;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._MsveMsve2\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mv-symbols9.c b/gcc/testsuite/gcc.target/aarch64/mv-symbols9.c
new file mode 100644
index 0000000..8e0864f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mv-symbols9.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ();
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ();
+
+int
+foo ()
+{
+ return 1;
+}
+
+__attribute__ ((target_version ("dotprod"))) int
+foo ()
+{
+ return 3;
+}
+__attribute__ ((target_version ("sve+sve2"))) int
+foo ()
+{
+ return 5;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._MsveMsve2\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\._Mdotprod\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tadrp\tx., foo\.default\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-error1.c b/gcc/testsuite/gcc.target/aarch64/mvc-error1.c
new file mode 100644
index 0000000..482d0a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-error1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default, dotprod"))) float
+foo (); /* { dg-message "previous declaration of .foo \\\[\\\[target_clones\\(.default., .dotprod.\\)\\\]\\\]." } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error ".foo \\\[\\\[target_clones\\(.dotprod., .sve.\\)\\\]\\\]. conflicts with overlapping .target_clone. declaration" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-error2.c b/gcc/testsuite/gcc.target/aarch64/mvc-error2.c
new file mode 100644
index 0000000..482d0a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-error2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default, dotprod"))) float
+foo (); /* { dg-message "previous declaration of .foo \\\[\\\[target_clones\\(.default., .dotprod.\\)\\\]\\\]." } */
+
+__attribute__ ((target_clones ("dotprod", "sve"))) float
+foo () { return 3; } /* { dg-error ".foo \\\[\\\[target_clones\\(.dotprod., .sve.\\)\\\]\\\]. conflicts with overlapping .target_clone. declaration" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-symbols1.c b/gcc/testsuite/gcc.target/aarch64/mvc-symbols1.c
new file mode 100644
index 0000000..3ad15e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-symbols1.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve+sve2"))) int
+foo ()
+{
+ return 1;
+}
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* When updating any of the symbol names in these tests, make sure to also
+ update any tests for their absence in mvc-symbolsN.C */
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-symbols2.c b/gcc/testsuite/gcc.target/aarch64/mvc-symbols2.c
new file mode 100644
index 0000000..78385ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-symbols2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve+sve2"))) int
+foo ()
+{
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-symbols3.c b/gcc/testsuite/gcc.target/aarch64/mvc-symbols3.c
new file mode 100644
index 0000000..1cbe3fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-symbols3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve+sve2"))) int
+foo ();
+
+int
+bar ()
+{
+ return foo ();
+}
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\tbl\tfoo\n" 1 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-symbols4.c b/gcc/testsuite/gcc.target/aarch64/mvc-symbols4.c
new file mode 100644
index 0000000..abaf60f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-symbols4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+__attribute__ ((target_clones ("default", "dotprod", "sve+sve2"))) int
+foo ();
+
+/* { dg-final { scan-assembler-times "\nfoo\.default:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._Mdotprod:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\._MsveMsve2:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\nfoo\.resolver:\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.type\tfoo, %gnu_indirect_function\n" 0 } } */
+/* { dg-final { scan-assembler-times "\n\t\.set\tfoo,foo\.resolver\n" 0 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/mvc-warning1.c b/gcc/testsuite/gcc.target/aarch64/mvc-warning1.c
new file mode 100644
index 0000000..1bae38c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/mvc-warning1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O0" } */
+
+__attribute__((target_clones("default", "dotprod", "sve+sve2")))
+int foo () {
+ return 1;
+}
+
+__attribute__((target_clones("invalid1")))
+int foo () { /* { dg-warning "invalid feature modifier .invalid1. in version .invalid1. for .target_clones. attribute" } */
+ return 2;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/pr122051.c b/gcc/testsuite/gcc.target/riscv/pr122051.c
new file mode 100644
index 0000000..c2f4b87
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr122051.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-additional-options "-mrvv-vector-bits=zvl -mcpu=xt-c920 -w" } */
+
+typedef __attribute__((__vector_size__(4))) char B;
+typedef __attribute__((__vector_size__(16))) long V;
+typedef __attribute__((__vector_size__(32))) double W;
+typedef __attribute__((__vector_size__(32))) char U;
+unsigned u;
+B o;
+char *p;
+int q;
+V v;
+W w;
+
+void
+foo(__int128, __int128, __int128, __int128, B a, B b, B c, B d, B e, B f, B g, B h) {
+ do {
+ w -= q;
+ v ^= u;
+ } while (__builtin_memcmp(p, 1 + p, 7));
+ o = ((U)w)[0] + c + d + e + f + g + h + a + b;
+}
+
+
diff --git a/gcc/testsuite/gcc.target/riscv/pr122106.c b/gcc/testsuite/gcc.target/riscv/pr122106.c
new file mode 100644
index 0000000..b0345b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr122106.c
@@ -0,0 +1,3 @@
+/* { dg-do compile } */
+
+short foo() { return __builtin_rev_crc16_data16(0, 0, 0); }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
index 89af160..bb62ce2 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/math-nearbyint-1.c
@@ -54,5 +54,5 @@ DEF_OP_V (nearbyint, 512, double, __builtin_nearbyint)
/* { dg-final { scan-tree-dump-not "4096,4096" "optimized" } } */
/* { dg-final { scan-assembler-times {vfcvt\.x\.f\.v\s+v[0-9]+,\s*v[0-9]+,\s*v0\.t} 30 } } */
/* { dg-final { scan-assembler-times {vfcvt\.f\.x\.v\s+v[0-9]+,\s*v[0-9]+,\s*v0\.t} 30 } } */
-/* { dg-final { scan-assembler-times {frflags\s+[atx][0-9]+} 32 } } */
-/* { dg-final { scan-assembler-times {fsflags\s+[atx][0-9]+} 32 } } */
+/* { dg-final { scan-assembler-times {frflags\s+[atx][0-9]+} 30 } } */
+/* { dg-final { scan-assembler-times {fsflags\s+[atx][0-9]+} 30 } } */
diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
index 64ffaca..2a7dcbe 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -2049,8 +2049,12 @@ prune_clobbered_mems (bitmap_set_t set, basic_block block, bool clean_traps)
the bitmap_find_leader way to see if there's still an expression
for it. For some ratio of to be removed values and number of
values/expressions in the set this might be faster than rebuilding
- the value-set. */
- if (any_removed)
+ the value-set.
+ Note when there's a MAX solution on one edge (clean_traps) do not
+ prune values as we need to consider the resulting expression set MAX
+ as well. This avoids a later growing ANTIC_IN value-set during
+ iteration, when the explicitly represented expression set grows. */
+ if (any_removed && !clean_traps)
{
bitmap_clear (&set->values);
FOR_EACH_EXPR_ID_IN_SET (set, i, bi)
@@ -2080,6 +2084,7 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
edge e;
edge_iterator ei;
+ bool was_visited = BB_VISITED (block);
bool changed = ! BB_VISITED (block);
bool any_max_on_edge = false;
@@ -2215,6 +2220,32 @@ compute_antic_aux (basic_block block, bool block_has_abnormal_pred_edge)
/* clean (ANTIC_IN (block)) is defered to after the iteration converged
because it can cause non-convergence, see for example PR81181. */
+ if (was_visited
+ && bitmap_and_into (&ANTIC_IN (block)->values, &old->values))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "warning: intersecting with old ANTIC_IN "
+ "shrinks the set\n");
+ /* Prune expressions not in the value set. */
+ bitmap_iterator bi;
+ unsigned int i;
+ unsigned int to_clear = -1U;
+ FOR_EACH_EXPR_ID_IN_SET (ANTIC_IN (block), i, bi)
+ {
+ if (to_clear != -1U)
+ {
+ bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear);
+ to_clear = -1U;
+ }
+ pre_expr expr = expression_for_id (i);
+ unsigned int value_id = get_expr_value_id (expr);
+ if (!bitmap_bit_p (&ANTIC_IN (block)->values, value_id))
+ to_clear = i;
+ }
+ if (to_clear != -1U)
+ bitmap_clear_bit (&ANTIC_IN (block)->expressions, to_clear);
+ }
+
if (!bitmap_set_equal (old, ANTIC_IN (block)))
changed = true;
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 1d549e4..df45adb 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -7177,6 +7177,15 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
tree vectype_out = SLP_TREE_VECTYPE (slp_for_stmt_info);
VECT_REDUC_INFO_VECTYPE (reduc_info) = vectype_out;
+ /* We do not handle mask reductions correctly in the epilogue. */
+ if (VECTOR_BOOLEAN_TYPE_P (vectype_out))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "mask reduction not supported.\n");
+ return false;
+ }
+
gimple_match_op op;
if (!gimple_extract_op (stmt_info->stmt, &op))
gcc_unreachable ();
@@ -7187,8 +7196,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
return false;
/* Do not try to vectorize bit-precision reductions. */
- if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
- && !type_has_mode_precision_p (op.type)
+ if (!type_has_mode_precision_p (op.type)
&& op.code != BIT_AND_EXPR
&& op.code != BIT_IOR_EXPR
&& op.code != BIT_XOR_EXPR)