From 3330e673959d44e5c7663956803e1e7a703dd626 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 14 Apr 2021 10:26:33 +0200 Subject: VEC_COND_EXPR verification adjustment This adjusts GIMPLE verification with respect to the VEC_COND_EXPR changes forcing a split out condition. 2021-04-14 Richard Biener * tree-cfg.c (verify_gimple_assign_ternary): Verify that VEC_COND_EXPRs have a gimple_val condition. * tree-ssa-propagate.c (valid_gimple_rhs_p): VEC_COND_EXPR can no longer have a GENERIC condition. --- gcc/tree-cfg.c | 2 ++ gcc/tree-ssa-propagate.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 7e3aae5..4f63aa6 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -4246,6 +4246,8 @@ verify_gimple_assign_ternary (gassign *stmt) debug_generic_expr (rhs1_type); return true; } + if (!is_gimple_val (rhs1)) + return true; /* Fallthrough. */ case COND_EXPR: if (!is_gimple_val (rhs1) diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index def16c0..17dd1ef 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -515,7 +515,7 @@ valid_gimple_rhs_p (tree expr) default: if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS) { - if (((code == VEC_COND_EXPR || code == COND_EXPR) + if ((code == COND_EXPR ? !is_gimple_condexpr (TREE_OPERAND (expr, 0)) : !is_gimple_val (TREE_OPERAND (expr, 0))) || !is_gimple_val (TREE_OPERAND (expr, 1)) -- cgit v1.1 From d253a6f7bb1748405bd9d12967f40dc19c8f77c4 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 5 Apr 2021 18:46:18 +0200 Subject: d: Add TARGET_D_HAS_STDCALL_CONVENTION This replaces the use of the D front-end `is64bit' parameter in determining whether to insert the "stdcall" function attribute. It is also used to determine whether `extern(System)' should be the same as `extern(Windows)' in the implementation of Target::systemLinkage. gcc/ChangeLog: * config/i386/i386-d.c (ix86_d_has_stdcall_convention): New function. * config/i386/i386-protos.h (ix86_d_has_stdcall_convention): Declare. * config/i386/i386.h (TARGET_D_HAS_STDCALL_CONVENTION): Define. * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_HAS_STDCALL_CONVENTION. gcc/d/ChangeLog: * d-target.cc (Target::systemLinkage): Return LINKwindows if d_has_stdcall_convention applies to LINKsystem. * d-target.def (d_has_stdcall_convention): New hook. * types.cc (TypeVisitor::visit (TypeFunction *)): Insert "stdcall" function attribute if d_has_stdcall_convention applies to LINKwindows. --- gcc/config/i386/i386-d.c | 20 ++++++++++++++++++++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.h | 3 ++- gcc/d/d-target.cc | 12 +++++++++++- gcc/d/d-target.def | 13 +++++++++++++ gcc/d/types.cc | 19 +++++++++++++------ gcc/doc/tm.texi | 8 ++++++++ gcc/doc/tm.texi.in | 2 ++ 8 files changed, 70 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c index b79be85..58b4790 100644 --- a/gcc/config/i386/i386-d.c +++ b/gcc/config/i386/i386-d.c @@ -44,3 +44,23 @@ ix86_d_target_versions (void) else d_add_builtin_version ("D_SoftFloat"); } + +/* Implement TARGET_D_HAS_STDCALL_CONVENTION for x86 targets. */ + +bool +ix86_d_has_stdcall_convention (unsigned int *link_system, + unsigned int *link_windows) +{ + if (ix86_abi == MS_ABI) + { + *link_system = 1; + *link_windows = (!TARGET_64BIT) ? 1 : 0; + } + else + { + *link_system = 0; + *link_windows = 0; + } + + return true; +} diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 9f8a69e..acfb9f5 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void); /* In i386-d.c */ extern void ix86_d_target_versions (void); +extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *); /* In winnt.c */ extern void i386_pe_unique_section (tree, int); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index fab1b3c..4b525d2 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -802,8 +802,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* Target Pragmas. */ #define REGISTER_TARGET_PRAGMAS() ix86_register_pragmas () -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS ix86_d_target_versions +#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index a1dc2ee..f1814df 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -435,11 +435,21 @@ TargetCPP::derivedClassOffset(ClassDeclaration *base_class) return base_class->structsize; } -/* Return the default system linkage for the target. */ +/* Return the default `extern (System)' linkage for the target. */ LINK Target::systemLinkage (void) { + unsigned link_system, link_windows; + + if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) + { + /* In [attribute/linkage], `System' is the same as `Windows' on Windows + platforms, and `C' on other platforms. */ + if (link_system) + return LINKwindows; + } + return LINKc; } diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index d1426a1..f79ffb9 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -71,5 +71,18 @@ as the name of the symbol indicating the end address of the module info\n\ section", const char *, NULL) +/* The "stdcall" convention is really supported on 32-bit x86/Windows only. + The following hook is a helper to determine whether to apply the attribute + on declarations with `extern(System)' and `extern(Windows)' linkage. */ +DEFHOOK +(d_has_stdcall_convention, + "Returns @code{true} if the target supports the stdcall calling convention.\n\ +The hook should also set @var{link_system} to @code{1} if the @code{stdcall}\n\ +attribute should be applied to functions with @code{extern(System)} linkage,\n\ +and @var{link_windows} to @code{1} to apply @code{stdcall} to functions with\n\ +@code{extern(Windows)} linkage.", + bool, (unsigned int *link_system, unsigned int *link_windows), + hook_bool_uintp_uintp_false) + /* Close the 'struct gcc_targetdm' definition. */ HOOK_VECTOR_END (C90_EMPTY_HACK) diff --git a/gcc/d/types.cc b/gcc/d/types.cc index ec61740..3b121f5 100644 --- a/gcc/d/types.cc +++ b/gcc/d/types.cc @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "d-tree.h" +#include "d-target.h" /* Return the signed or unsigned version of TYPE, an integral type, the @@ -800,13 +801,19 @@ public: switch (t->linkage) { case LINKwindows: - /* [attribute/linkage] + { + /* [attribute/linkage] - The Windows convention is distinct from the C convention only - on Win32, where it is equivalent to the stdcall convention. */ - if (!global.params.is64bit) - t->ctype = insert_type_attribute (t->ctype, "stdcall"); - break; + The Windows convention is distinct from the C convention only + on Win32, where it is equivalent to the stdcall convention. */ + unsigned link_system, link_windows; + if (targetdm.d_has_stdcall_convention (&link_system, &link_windows)) + { + if (link_windows) + t->ctype = insert_type_attribute (t->ctype, "stdcall"); + } + break; + } case LINKc: case LINKcpp: diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b272fa4..71607c4 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10828,6 +10828,14 @@ as the name of the symbol indicating the end address of the module info section @end deftypevr +@deftypefn {D Target Hook} bool TARGET_D_HAS_STDCALL_CONVENTION (unsigned int *@var{link_system}, unsigned int *@var{link_windows}) +Returns @code{true} if the target supports the stdcall calling convention. +The hook should also set @var{link_system} to @code{1} if the @code{stdcall} +attribute should be applied to functions with @code{extern(System)} linkage, +and @var{link_windows} to @code{1} to apply @code{stdcall} to functions with +@code{extern(Windows)} linkage. +@end deftypefn + @node Named Address Spaces @section Adding support for named address spaces @cindex named address spaces diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index bf724dc..c8880da 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7363,6 +7363,8 @@ floating-point support; they are not included in this mechanism. @hook TARGET_D_MINFO_END_NAME +@hook TARGET_D_HAS_STDCALL_CONVENTION + @node Named Address Spaces @section Adding support for named address spaces @cindex named address spaces -- cgit v1.1 From 3785d2b207f1958f31a79fbbb5705b261551950d Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 5 Apr 2021 19:37:31 +0200 Subject: d: Add TARGET_D_REGISTER_CPU_TARGET_INFO This implements `__traits(getTargetInfo, "floatAbi")' for all targets that have D support files. gcc/ChangeLog: * config/aarch64/aarch64-d.c (aarch64_d_handle_target_float_abi): New function. (aarch64_d_register_target_info): New function. * config/aarch64/aarch64-protos.h (aarch64_d_register_target_info): Declare. * config/aarch64/aarch64.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/arm/arm-d.c (arm_d_handle_target_float_abi): New function. (arm_d_register_target_info): New function. * config/arm/arm-protos.h (arm_d_register_target_info): Declare. * config/arm/arm.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/i386/i386-d.c (ix86_d_handle_target_float_abi): New function. (ix86_d_register_target_info): New function. * config/i386/i386-protos.h (ix86_d_register_target_info): Declare. * config/i386/i386.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/mips/mips-d.c (mips_d_handle_target_float_abi): New function. (mips_d_register_target_info): New function. * config/mips/mips-protos.h (mips_d_register_target_info): Declare. * config/mips/mips.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/pa/pa-d.c (pa_d_handle_target_float_abi): New function. (pa_d_register_target_info): New function. * config/pa/pa-protos.h (pa_d_register_target_info): Declare. * config/pa/pa.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/riscv/riscv-d.c (riscv_d_handle_target_float_abi): New function. (riscv_d_register_target_info): New function. * config/riscv/riscv-protos.h (riscv_d_register_target_info): Declare. * config/riscv/riscv.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/rs6000/rs6000-d.c (rs6000_d_handle_target_float_abi): New function. (rs6000_d_register_target_info): New function. * config/rs6000/rs6000-protos.h (rs6000_d_register_target_info): Declare. * config/rs6000/rs6000.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/s390/s390-d.c (s390_d_handle_target_float_abi): New function. (s390_d_register_target_info): New function. * config/s390/s390-protos.h (s390_d_register_target_info): Declare. * config/s390/s390.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * config/sparc/sparc-d.c (sparc_d_handle_target_float_abi): New function. (sparc_d_register_target_info): New function. * config/sparc/sparc-protos.h (sparc_d_register_target_info): Declare. * config/sparc/sparc.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_REGISTER_CPU_TARGET_INFO. gcc/d/ChangeLog: * d-target.cc (Target::_init): Call new targetdm hook to register CPU specific target info keys. * d-target.def (d_register_cpu_target_info): New hook. --- gcc/config/aarch64/aarch64-d.c | 23 +++++++++++++++++++ gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64.h | 3 ++- gcc/config/arm/arm-d.c | 42 +++++++++++++++++++++++++++++++++ gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.h | 3 ++- gcc/config/i386/i386-d.c | 28 ++++++++++++++++++++++ gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.h | 1 + gcc/config/mips/mips-d.c | 30 ++++++++++++++++++++++++ gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.h | 3 ++- gcc/config/pa/pa-d.c | 28 ++++++++++++++++++++++ gcc/config/pa/pa-protos.h | 1 + gcc/config/pa/pa.h | 3 ++- gcc/config/riscv/riscv-d.c | 46 +++++++++++++++++++++++++++++++++++++ gcc/config/riscv/riscv-protos.h | 1 + gcc/config/riscv/riscv.h | 3 ++- gcc/config/rs6000/rs6000-d.c | 30 ++++++++++++++++++++++++ gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.h | 3 ++- gcc/config/s390/s390-d.c | 30 ++++++++++++++++++++++++ gcc/config/s390/s390-protos.h | 1 + gcc/config/s390/s390.h | 3 ++- gcc/config/sparc/sparc-d.c | 28 ++++++++++++++++++++++ gcc/config/sparc/sparc-protos.h | 1 + gcc/config/sparc/sparc.h | 3 ++- gcc/d/d-target.cc | 1 + gcc/d/d-target.def | 12 ++++++++++ gcc/doc/tm.texi | 9 ++++++++ gcc/doc/tm.texi.in | 2 ++ 31 files changed, 335 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64-d.c b/gcc/config/aarch64/aarch64-d.c index 4fce593..416bb7c 100644 --- a/gcc/config/aarch64/aarch64-d.c +++ b/gcc/config/aarch64/aarch64-d.c @@ -31,3 +31,26 @@ aarch64_d_target_versions (void) d_add_builtin_version ("AArch64"); d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +aarch64_d_handle_target_float_abi (void) +{ + const char *abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +aarch64_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", aarch64_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index d5d5417..c203338 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -1011,6 +1011,7 @@ std::string aarch64_get_extension_string_for_isa_flags (uint64_t, uint64_t); /* Defined in aarch64-d.c */ extern void aarch64_d_target_versions (void); +extern void aarch64_d_register_target_info (void); rtl_opt_pass *make_pass_fma_steering (gcc::context *); rtl_opt_pass *make_pass_track_speculation (gcc::context *); diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index d0bae61..bfffbcd 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -26,8 +26,9 @@ #define TARGET_CPU_CPP_BUILTINS() \ aarch64_cpu_cpp_builtins (pfile) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS aarch64_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO aarch64_d_register_target_info diff --git a/gcc/config/arm/arm-d.c b/gcc/config/arm/arm-d.c index 2cb9f4b..5f43ef9 100644 --- a/gcc/config/arm/arm-d.c +++ b/gcc/config/arm/arm-d.c @@ -53,3 +53,45 @@ arm_d_target_versions (void) else if (TARGET_HARD_FLOAT) d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +arm_d_handle_target_float_abi (void) +{ + const char *abi; + + switch (arm_float_abi) + { + case ARM_FLOAT_ABI_HARD: + abi = "hard"; + break; + + case ARM_FLOAT_ABI_SOFT: + abi = "soft"; + break; + + case ARM_FLOAT_ABI_SOFTFP: + abi = "softfp"; + break; + + default: + abi = ""; + break; + } + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +arm_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", arm_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 952a825..2521541 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -397,6 +397,7 @@ extern void arm_cpu_cpp_builtins (struct cpp_reader *); /* Defined in arm-d.c */ extern void arm_d_target_versions (void); +extern void arm_d_register_target_info (void); extern bool arm_is_constant_pool_ref (rtx); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 113c015..c70af57 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -47,8 +47,9 @@ extern char arm_arch_name[]; /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() arm_cpu_cpp_builtins (pfile) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS arm_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO arm_d_register_target_info #include "config/arm/arm-opts.h" diff --git a/gcc/config/i386/i386-d.c b/gcc/config/i386/i386-d.c index 58b4790..da5958c 100644 --- a/gcc/config/i386/i386-d.c +++ b/gcc/config/i386/i386-d.c @@ -45,6 +45,34 @@ ix86_d_target_versions (void) d_add_builtin_version ("D_SoftFloat"); } +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +ix86_d_handle_target_float_abi (void) +{ + const char *abi; + + if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387)) + abi = "soft"; + else + abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +ix86_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", ix86_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} + /* Implement TARGET_D_HAS_STDCALL_CONVENTION for x86 targets. */ bool diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index acfb9f5..7782cf11 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -264,6 +264,7 @@ extern void ix86_register_pragmas (void); /* In i386-d.c */ extern void ix86_d_target_versions (void); +extern void ix86_d_register_target_info (void); extern bool ix86_d_has_stdcall_convention (unsigned int *, unsigned int *); /* In winnt.c */ diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 4b525d2..97700d7 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -804,6 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS ix86_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info #define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention #ifndef CC1_SPEC diff --git a/gcc/config/mips/mips-d.c b/gcc/config/mips/mips-d.c index dc57127..e03f486 100644 --- a/gcc/config/mips/mips-d.c +++ b/gcc/config/mips/mips-d.c @@ -56,3 +56,33 @@ mips_d_target_versions (void) d_add_builtin_version ("D_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +mips_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT_ABI) + abi = "hard"; + else if (TARGET_SOFT_FLOAT_ABI) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +mips_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", mips_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 72bbbe2..2cf4ed5 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -388,5 +388,6 @@ extern void mips_expand_vec_cond_expr (machine_mode, machine_mode, rtx *); /* Routines implemented in mips-d.c */ extern void mips_d_target_versions (void); +extern void mips_d_register_target_info (void); #endif /* ! GCC_MIPS_PROTOS_H */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index b4a60a5..47aac9d 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -658,8 +658,9 @@ struct mips_cpu_info { } \ while (0) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS mips_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO mips_d_register_target_info /* Default target_flags if no switches are specified */ diff --git a/gcc/config/pa/pa-d.c b/gcc/config/pa/pa-d.c index 663e749..41b2f18 100644 --- a/gcc/config/pa/pa-d.c +++ b/gcc/config/pa/pa-d.c @@ -39,3 +39,31 @@ pa_d_target_versions (void) else d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +pa_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = "hard"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +pa_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", pa_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h index 0e1e471..5bf6fef 100644 --- a/gcc/config/pa/pa-protos.h +++ b/gcc/config/pa/pa-protos.h @@ -115,3 +115,4 @@ extern const int pa_magic_milli[]; /* Routines implemented in pa-d.c */ extern void pa_d_target_versions (void); +extern void pa_d_register_target_info (void); diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index 3ec015a..fbb9604 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -1302,8 +1302,9 @@ do { \ #define NEED_INDICATE_EXEC_STACK 0 -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS pa_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO pa_d_register_target_info /* Output default function prologue for hpux. */ #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue diff --git a/gcc/config/riscv/riscv-d.c b/gcc/config/riscv/riscv-d.c index b20b778..8883cec 100644 --- a/gcc/config/riscv/riscv-d.c +++ b/gcc/config/riscv/riscv-d.c @@ -39,3 +39,49 @@ riscv_d_target_versions (void) else d_add_builtin_version ("D_SoftFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +riscv_d_handle_target_float_abi (void) +{ + const char *abi; + + switch (riscv_abi) + { + case ABI_ILP32E: + case ABI_ILP32: + case ABI_LP64: + abi = "soft"; + break; + + case ABI_ILP32F: + case ABI_LP64F: + abi = "single"; + break; + + case ABI_ILP32D: + case ABI_LP64D: + abi = "double"; + break; + + default: + abi = ""; + break; + } + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +riscv_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", riscv_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index cc0be7e..43d7224 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -80,6 +80,7 @@ void riscv_cpu_cpp_builtins (cpp_reader *); /* Routines implemented in riscv-d.c */ extern void riscv_d_target_versions (void); +extern void riscv_d_register_target_info (void); /* Routines implemented in riscv-builtins.c. */ extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 3cc3e86..d17096e 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -27,8 +27,9 @@ along with GCC; see the file COPYING3. If not see /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() riscv_cpu_cpp_builtins (pfile) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS riscv_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO riscv_d_register_target_info #ifdef TARGET_BIG_ENDIAN_DEFAULT #define DEFAULT_ENDIAN_SPEC "b" diff --git a/gcc/config/rs6000/rs6000-d.c b/gcc/config/rs6000/rs6000-d.c index 6bfe813..755de42 100644 --- a/gcc/config/rs6000/rs6000-d.c +++ b/gcc/config/rs6000/rs6000-d.c @@ -45,3 +45,33 @@ rs6000_d_target_versions (void) d_add_builtin_version ("D_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +rs6000_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT) + abi = "hard"; + else if (TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +rs6000_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", rs6000_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index c44fd3d..a06a147 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -298,6 +298,7 @@ extern void (*rs6000_target_modify_macros_ptr) (bool, HOST_WIDE_INT, /* Declare functions in rs6000-d.c */ extern void rs6000_d_target_versions (void); +extern void rs6000_d_register_target_info (void); #ifdef NO_DOLLAR_IN_LABEL const char * rs6000_xcoff_strip_dollar (const char *); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 233a92b..164d359 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -641,8 +641,9 @@ extern unsigned char rs6000_recip_bits[]; #define TARGET_CPU_CPP_BUILTINS() \ rs6000_cpu_cpp_builtins (pfile) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS rs6000_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO rs6000_d_register_target_info /* This is used by rs6000_cpu_cpp_builtins to indicate the byte order we're compiling for. Some configurations may need to override it. */ diff --git a/gcc/config/s390/s390-d.c b/gcc/config/s390/s390-d.c index 2f945eb..1a99063 100644 --- a/gcc/config/s390/s390-d.c +++ b/gcc/config/s390/s390-d.c @@ -41,3 +41,33 @@ s390_d_target_versions (void) else if (TARGET_HARD_FLOAT) d_add_builtin_version ("D_HardFloat"); } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +s390_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_HARD_FLOAT) + abi = "hard"; + else if (TARGET_SOFT_FLOAT) + abi = "soft"; + else + abi = ""; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +s390_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", s390_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index acbdf66..289e018 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -173,6 +173,7 @@ extern bool s390_const_operand_ok (tree, int, int, tree); /* s390-d.c routines */ extern void s390_d_target_versions (void); +extern void s390_d_register_target_info (void); /* Pass management. */ namespace gcc { class context; } diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 991af96..3b87616 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -247,8 +247,9 @@ enum processor_flags /* Target CPU builtins. */ #define TARGET_CPU_CPP_BUILTINS() s390_cpu_cpp_builtins (pfile) -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS s390_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO s390_d_register_target_info #ifdef DEFAULT_TARGET_64BIT #define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP \ diff --git a/gcc/config/sparc/sparc-d.c b/gcc/config/sparc/sparc-d.c index 0eb663b..cfb8dae 100644 --- a/gcc/config/sparc/sparc-d.c +++ b/gcc/config/sparc/sparc-d.c @@ -48,3 +48,31 @@ sparc_d_target_versions (void) d_add_builtin_version ("SPARC_SoftFloat"); } } + +/* Handle a call to `__traits(getTargetInfo, "floatAbi")'. */ + +static tree +sparc_d_handle_target_float_abi (void) +{ + const char *abi; + + if (TARGET_FPU) + abi = "hard"; + else + abi = "soft"; + + return build_string_literal (strlen (abi) + 1, abi); +} + +/* Implement TARGET_D_REGISTER_CPU_TARGET_INFO. */ + +void +sparc_d_register_target_info (void) +{ + const struct d_target_info_spec handlers[] = { + { "floatAbi", sparc_d_handle_target_float_abi }, + { NULL, NULL }, + }; + + d_add_target_info_handlers (handlers); +} diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index ef94d4f..ad875cc 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -113,5 +113,6 @@ extern rtl_opt_pass *make_pass_work_around_errata (gcc::context *); /* Routines implemented in sparc-d.c */ extern void sparc_d_target_versions (void); +extern void sparc_d_register_target_info (void); #endif /* __SPARC_PROTOS_H__ */ diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index cec2f5a..4834575 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -27,8 +27,9 @@ along with GCC; see the file COPYING3. If not see #define TARGET_CPU_CPP_BUILTINS() sparc_target_macros () -/* Target CPU versions for D. */ +/* Target hooks for D language. */ #define TARGET_D_CPU_VERSIONS sparc_d_target_versions +#define TARGET_D_REGISTER_CPU_TARGET_INFO sparc_d_register_target_info /* Specify this in a cover file to provide bi-architecture (32/64) support. */ /* #define SPARC_BI_ARCH */ diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index f1814df..d576b74 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -198,6 +198,7 @@ Target::_init (const Param &) /* Initialize target info tables, the keys required by the language are added last, so that the OS and CPU handlers can override. */ + targetdm.d_register_cpu_target_info (); d_add_target_info_handlers (d_language_target_info); } diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index f79ffb9..cd0397c 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -46,6 +46,18 @@ relating to the target operating system.", void, (void), hook_void_void) +/* getTargetInfo keys relating to the target CPU. */ +DEFHOOK +(d_register_cpu_target_info, + "Register all target information keys relating to the target CPU using the\n\ +function @code{d_add_target_info_handlers}, which takes a\n\ +@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}). The keys\n\ +added by this hook are made available at compile time by the\n\ +@code{__traits(getTargetInfo)} extension, the result is an expression\n\ +describing the requested target information.", + void, (void), + hook_void_void) + /* ModuleInfo section name and brackets. */ DEFHOOKPOD (d_minfo_section, diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 71607c4..6201df9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10808,6 +10808,15 @@ Similarly to @code{TARGET_D_CPU_VERSIONS}, but is used for versions relating to the target operating system. @end deftypefn +@deftypefn {D Target Hook} void TARGET_D_REGISTER_CPU_TARGET_INFO (void) +Register all target information keys relating to the target CPU using the +function @code{d_add_target_info_handlers}, which takes a +@samp{struct d_target_info_spec} (defined in @file{d/d-target.h}). The keys +added by this hook are made available at compile time by the +@code{__traits(getTargetInfo)} extension, the result is an expression +describing the requested target information. +@end deftypefn + @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION Contains the name of the section in which module info references should be placed. This section is expected to be bracketed by two symbols to indicate diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index c8880da..bde5758 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7357,6 +7357,8 @@ floating-point support; they are not included in this mechanism. @hook TARGET_D_OS_VERSIONS +@hook TARGET_D_REGISTER_CPU_TARGET_INFO + @hook TARGET_D_MINFO_SECTION @hook TARGET_D_MINFO_START_NAME -- cgit v1.1 From 5b63eb17d863ac080cf3c7df08233054b09d3747 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 13 Apr 2021 16:19:03 +0200 Subject: d: Move call to set_linkage_for_decl to declare_extern_var. This both prevents against it being called twice for declarations that are defined, and fixes an issue where variables defined in the compilation get one kind of linkage (weak), and the same variables declared via declare_extern_var get another (extern). gcc/d/ChangeLog: PR d/99914 * decl.cc (DeclVisitor::visit (StructDeclaration *)): Don't set DECL_INSTANTIATED on static initializer declarations. (DeclVisitor::visit (ClassDeclaration *)): Likewise. (DeclVisitor::visit (EnumDeclaration *)): Likewise. (d_finish_decl): Move call to set_linkage_for_decl to... (declare_extern_var): ...here. --- gcc/d/decl.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc index b07068e..8948e40 100644 --- a/gcc/d/decl.cc +++ b/gcc/d/decl.cc @@ -387,7 +387,6 @@ public: /* Generate static initializer. */ d->sinit = aggregate_initializer_decl (d); DECL_INITIAL (d->sinit) = layout_struct_initializer (d); - DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL); d_finish_decl (d->sinit); /* Put out the members. There might be static constructors in the members @@ -500,7 +499,6 @@ public: /* Generate static initializer. */ DECL_INITIAL (d->sinit) = layout_class_initializer (d); - DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL); d_finish_decl (d->sinit); /* Put out the TypeInfo. */ @@ -611,7 +609,6 @@ public: /* Generate static initializer. */ d->sinit = enum_initializer_decl (d); DECL_INITIAL (d->sinit) = build_expr (tc->sym->defaultval, true); - DECL_INSTANTIATED (d->sinit) = (d->isInstantiated () != NULL); d_finish_decl (d->sinit); } @@ -1379,6 +1376,8 @@ declare_extern_var (tree ident, tree type) /* The decl has not been defined -- yet. */ DECL_EXTERNAL (decl) = 1; + set_linkage_for_decl (decl); + return decl; } @@ -1540,7 +1539,6 @@ d_finish_decl (tree decl) set_decl_tls_model (decl, decl_default_tls_model (decl)); relayout_decl (decl); - set_linkage_for_decl (decl); if (flag_checking && DECL_INITIAL (decl)) { -- cgit v1.1 From a5e4abac26b815fe0b0d421930bfdfd2901adfe3 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 14 Apr 2021 12:19:54 +0200 Subject: d: Remove setting of target-specific global.params flags from front-end Now that all dependencies on these flags have been removed, there's no need to test and set them. gcc/d/ChangeLog: * d-builtins.cc (d_add_builtin_version): Remove all setting of target-specific global.params. * typeinfo.cc (create_typeinfo): Don't add argType fields to TypeInfo_Struct. --- gcc/d/d-builtins.cc | 19 ------------------- gcc/d/typeinfo.cc | 5 +---- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'gcc') diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc index ce09861..400bce0 100644 --- a/gcc/d/d-builtins.cc +++ b/gcc/d/d-builtins.cc @@ -418,25 +418,6 @@ d_eval_constant_expression (const Loc &loc, tree cst) void d_add_builtin_version (const char* ident) { - /* For now, we need to tell the D frontend what platform is being targeted. - This should be removed once the frontend has been fixed. */ - if (strcmp (ident, "linux") == 0) - global.params.isLinux = true; - else if (strcmp (ident, "OSX") == 0) - global.params.isOSX = true; - else if (strcmp (ident, "Windows") == 0) - global.params.isWindows = true; - else if (strcmp (ident, "FreeBSD") == 0) - global.params.isFreeBSD = true; - else if (strcmp (ident, "OpenBSD") == 0) - global.params.isOpenBSD = true; - else if (strcmp (ident, "Solaris") == 0) - global.params.isSolaris = true; - /* The is64bit field only refers to x86_64 target. */ - else if (strcmp (ident, "X86_64") == 0) - global.params.is64bit = true; - /* No other fields are required to be set for the frontend. */ - VersionCondition::addPredefinedGlobalIdent (ident); } diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc index f8ffcbf..503480b 100644 --- a/gcc/d/typeinfo.cc +++ b/gcc/d/typeinfo.cc @@ -1562,9 +1562,6 @@ create_typeinfo (Type *type, Module *mod) case TK_STRUCT_TYPE: if (!tinfo_types[tk]) { - /* Some ABIs add extra TypeInfo fields on the end. */ - tree argtype = global.params.is64bit ? ptr_type_node : NULL_TREE; - ident = Identifier::idPool ("TypeInfo_Struct"); make_internal_typeinfo (tk, ident, array_type_node, array_type_node, @@ -1572,7 +1569,7 @@ create_typeinfo (Type *type, Module *mod) ptr_type_node, ptr_type_node, d_uint_type, ptr_type_node, ptr_type_node, d_uint_type, - ptr_type_node, argtype, argtype, NULL); + ptr_type_node, NULL); } t->vtinfo = TypeInfoStructDeclaration::create (t); break; -- cgit v1.1 From 2ccc05a5141506fde0e20dec702c717fd67bf6ee Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 14 Apr 2021 08:54:30 -0400 Subject: c++: Fix deduction with reference NTTP [PR83476] In the testcase ref11.C below, during deduction for the call f(a), uses_deducible_template_parms returns false for the dependent specialization A because the generic template argument V here is wrapped in an implicit INDIRECT_REF (formed from template_parm_to_arg). Since uses_deducible_template_parms returns false, unify_one_argument exits early without ever attempting to deduce 'n' for 'V'. This patch fixes this by making deducible_expression look through such implicit INDIRECT_REFs. gcc/cp/ChangeLog: PR c++/83476 PR c++/99885 * pt.c (deducible_expression): Look through implicit INDIRECT_REFs as well. gcc/testsuite/ChangeLog: PR c++/83476 PR c++/99885 * g++.dg/cpp1z/class-deduction85.C: New test. * g++.dg/template/ref11.C: New test. --- gcc/cp/pt.c | 6 ++++-- gcc/testsuite/g++.dg/cpp1z/class-deduction85.C | 16 ++++++++++++++++ gcc/testsuite/g++.dg/template/ref11.C | 9 +++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction85.C create mode 100644 gcc/testsuite/g++.dg/template/ref11.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 59df794..f488a5a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -21902,8 +21902,10 @@ static bool uses_deducible_template_parms (tree type); static bool deducible_expression (tree expr) { - /* Strip implicit conversions. */ - while (CONVERT_EXPR_P (expr) || TREE_CODE (expr) == VIEW_CONVERT_EXPR) + /* Strip implicit conversions and implicit INDIRECT_REFs. */ + while (CONVERT_EXPR_P (expr) + || TREE_CODE (expr) == VIEW_CONVERT_EXPR + || REFERENCE_REF_P (expr)) expr = TREE_OPERAND (expr, 0); return (TREE_CODE (expr) == TEMPLATE_PARM_INDEX); } diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction85.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction85.C new file mode 100644 index 0000000..0b22f8e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction85.C @@ -0,0 +1,16 @@ +// PR c++/99885 +// { dg-do compile { target c++17 } } + +template +struct Foo {}; + +template +struct Bar { + constexpr auto foo() const -> Foo { + return {}; + } +}; + +constexpr int a = 1; +constexpr Bar bar; +Foo foo = bar.foo(); // <-- CTAD failure diff --git a/gcc/testsuite/g++.dg/template/ref11.C b/gcc/testsuite/g++.dg/template/ref11.C new file mode 100644 index 0000000..c43c67e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ref11.C @@ -0,0 +1,9 @@ +// PR c++/83476 + +int n; +template struct A {}; +template void f(A); +int main() { + A a; + f(a); +} -- cgit v1.1 From 527bc0181d3ea36f11dcaa8aea7704466bd0f01b Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 5 Apr 2021 20:40:38 +0200 Subject: d: Add TARGET_D_REGISTER_OS_TARGET_INFO This allows target platforms that have D support files to defined their own target-specific information keys. gcc/ChangeLog: * doc/tm.texi: Regenerate. * doc/tm.texi.in (D language and ABI): Add @hook for TARGET_D_REGISTER_OS_TARGET_INFO. gcc/d/ChangeLog: * d-target.cc (Target::_init): Call new targetdm hook to register OS specific target info keys. * d-target.def (d_register_os_target_info): New hook. --- gcc/d/d-target.cc | 1 + gcc/d/d-target.def | 8 ++++++++ gcc/doc/tm.texi | 5 +++++ gcc/doc/tm.texi.in | 2 ++ 4 files changed, 16 insertions(+) (limited to 'gcc') diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index d576b74..be354d9 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -199,6 +199,7 @@ Target::_init (const Param &) /* Initialize target info tables, the keys required by the language are added last, so that the OS and CPU handlers can override. */ targetdm.d_register_cpu_target_info (); + targetdm.d_register_os_target_info (); d_add_target_info_handlers (d_language_target_info); } diff --git a/gcc/d/d-target.def b/gcc/d/d-target.def index cd0397c..aa6bf55 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -58,6 +58,14 @@ describing the requested target information.", void, (void), hook_void_void) +/* getTargetInfo keys relating to the target OS. */ +DEFHOOK +(d_register_os_target_info, + "Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to\n\ +the target operating system.", + void, (void), + hook_void_void) + /* ModuleInfo section name and brackets. */ DEFHOOKPOD (d_minfo_section, diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 6201df9..97c8eeb 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10817,6 +10817,11 @@ added by this hook are made available at compile time by the describing the requested target information. @end deftypefn +@deftypefn {D Target Hook} void TARGET_D_REGISTER_OS_TARGET_INFO (void) +Same as @code{TARGET_D_CPU_TARGET_INFO}, but is used for keys relating to +the target operating system. +@end deftypefn + @deftypevr {D Target Hook} {const char *} TARGET_D_MINFO_SECTION Contains the name of the section in which module info references should be placed. This section is expected to be bracketed by two symbols to indicate diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index bde5758..e2d49ee 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7359,6 +7359,8 @@ floating-point support; they are not included in this mechanism. @hook TARGET_D_REGISTER_CPU_TARGET_INFO +@hook TARGET_D_REGISTER_OS_TARGET_INFO + @hook TARGET_D_MINFO_SECTION @hook TARGET_D_MINFO_START_NAME -- cgit v1.1 From 3191c1f4488d1f7563b563d7ae2a102a26f16d82 Mon Sep 17 00:00:00 2001 From: Andreas Krebbel Date: Wed, 14 Apr 2021 16:07:17 +0200 Subject: IBM Z: Fix error checking for immediate builtin operands This fixes the error checking for two of the vector builtins which accept irregular (e.g. non-contigiuous) ranges of values. gcc/ChangeLog: * config/s390/s390-builtins.def (O_M5, O_M12, ...): Add new macros for mask operand types. (s390_vec_permi_s64, s390_vec_permi_b64, s390_vec_permi_u64) (s390_vec_permi_dbl, s390_vpdi): Use the M5 type for the immediate operand. (s390_vec_msum_u128, s390_vmslg): Use the M12 type for the immediate operand. * config/s390/s390.c (s390_const_operand_ok): Check the new operand types and generate a list of valid values. gcc/testsuite/ChangeLog: * gcc.target/s390/zvector/imm-range-error-1.c: New test. * gcc.target/s390/zvector/vec_msum_u128-1.c: New test. --- gcc/config/s390/s390-builtins.def | 85 ++++++++++++++-------- gcc/config/s390/s390.c | 35 +++++++-- .../gcc.target/s390/zvector/imm-range-error-1.c | 26 +++++++ .../gcc.target/s390/zvector/vec_msum_u128-1.c | 45 ++++++++++++ 4 files changed, 156 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/gcc.target/s390/zvector/imm-range-error-1.c create mode 100644 gcc/testsuite/gcc.target/s390/zvector/vec_msum_u128-1.c (limited to 'gcc') diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def index 129d712..f77ab75 100644 --- a/gcc/config/s390/s390-builtins.def +++ b/gcc/config/s390/s390-builtins.def @@ -29,6 +29,9 @@ #undef O_U16 #undef O_U32 +#undef O_M5 +#undef O_M12 + #undef O_S2 #undef O_S3 #undef O_S4 @@ -37,6 +40,7 @@ #undef O_S12 #undef O_S16 #undef O_S32 + #undef O_ELEM #undef O_LIT @@ -85,6 +89,16 @@ #undef O3_U32 #undef O4_U32 +#undef O1_M5 +#undef O2_M5 +#undef O3_M5 +#undef O4_M5 + +#undef O1_M12 +#undef O2_M12 +#undef O3_M12 +#undef O4_M12 + #undef O1_S2 #undef O2_S2 #undef O3_S2 @@ -140,31 +154,34 @@ #undef O_UIMM_P #undef O_SIMM_P -#define O_U1 1 /* unsigned 1 bit literal */ -#define O_U2 2 /* unsigned 2 bit literal */ -#define O_U3 3 /* unsigned 3 bit literal */ -#define O_U4 4 /* unsigned 4 bit literal */ -#define O_U5 5 /* unsigned 5 bit literal */ -#define O_U8 6 /* unsigned 8 bit literal */ -#define O_U12 7 /* unsigned 16 bit literal */ -#define O_U16 8 /* unsigned 16 bit literal */ -#define O_U32 9 /* unsigned 32 bit literal */ - -#define O_S2 10 /* signed 2 bit literal */ -#define O_S3 11 /* signed 3 bit literal */ -#define O_S4 12 /* signed 4 bit literal */ -#define O_S5 13 /* signed 5 bit literal */ -#define O_S8 14 /* signed 8 bit literal */ -#define O_S12 15 /* signed 12 bit literal */ -#define O_S16 16 /* signed 16 bit literal */ -#define O_S32 17 /* signed 32 bit literal */ - -#define O_ELEM 18 /* Element selector requiring modulo arithmetic. */ -#define O_LIT 19 /* Operand must be a literal fitting the target type. */ +#define O_U1 1 /* unsigned 1 bit literal */ +#define O_U2 2 /* unsigned 2 bit literal */ +#define O_U3 3 /* unsigned 3 bit literal */ +#define O_U4 4 /* unsigned 4 bit literal */ +#define O_U5 5 /* unsigned 5 bit literal */ +#define O_U8 6 /* unsigned 8 bit literal */ +#define O_U12 7 /* unsigned 16 bit literal */ +#define O_U16 8 /* unsigned 16 bit literal */ +#define O_U32 9 /* unsigned 32 bit literal */ + +#define O_M5 10 /* matches bitmask of 5 */ +#define O_M12 11 /* matches bitmask of 12 */ + +#define O_S2 12 /* signed 2 bit literal */ +#define O_S3 13 /* signed 3 bit literal */ +#define O_S4 14 /* signed 4 bit literal */ +#define O_S5 15 /* signed 5 bit literal */ +#define O_S8 16 /* signed 8 bit literal */ +#define O_S12 17 /* signed 12 bit literal */ +#define O_S16 18 /* signed 16 bit literal */ +#define O_S32 19 /* signed 32 bit literal */ + +#define O_ELEM 20 /* Element selector requiring modulo arithmetic. */ +#define O_LIT 21 /* Operand must be a literal fitting the target type. */ #define O_SHIFT 5 -#define O_UIMM_P(X) ((X) >= O_U1 && (X) <= O_U32) +#define O_UIMM_P(X) ((X) >= O_U1 && (X) <= O_M12) #define O_SIMM_P(X) ((X) >= O_S2 && (X) <= O_S32) #define O_IMM_P(X) ((X) == O_LIT || ((X) >= O_U1 && (X) <= O_S32)) @@ -213,6 +230,16 @@ #define O3_U32 (O_U32 << (2 * O_SHIFT)) #define O4_U32 (O_U32 << (3 * O_SHIFT)) +#define O1_M5 O_M5 +#define O2_M5 (O_M5 << O_SHIFT) +#define O3_M5 (O_M5 << (2 * O_SHIFT)) +#define O4_M5 (O_M5 << (3 * O_SHIFT)) + +#define O1_M12 O_M12 +#define O2_M12 (O_M12 << O_SHIFT) +#define O3_M12 (O_M12 << (2 * O_SHIFT)) +#define O4_M12 (O_M12 << (3 * O_SHIFT)) + #define O1_S2 O_S2 #define O2_S2 (O_S2 << O_SHIFT) @@ -644,12 +671,12 @@ OB_DEF_VAR (s390_vec_perm_dbl, s390_vperm, 0, B_DEF (s390_vperm, vec_permv16qi, 0, B_VX, 0, BT_FN_UV16QI_UV16QI_UV16QI_UV16QI) OB_DEF (s390_vec_permi, s390_vec_permi_s64, s390_vec_permi_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI_INT) -OB_DEF_VAR (s390_vec_permi_s64, s390_vpdi, 0, O3_U2, BT_OV_V2DI_V2DI_V2DI_INT) -OB_DEF_VAR (s390_vec_permi_b64, s390_vpdi, 0, O3_U2, BT_OV_BV2DI_BV2DI_BV2DI_INT) -OB_DEF_VAR (s390_vec_permi_u64, s390_vpdi, 0, O3_U2, BT_OV_UV2DI_UV2DI_UV2DI_INT) -OB_DEF_VAR (s390_vec_permi_dbl, s390_vpdi, 0, O3_U2, BT_OV_V2DF_V2DF_V2DF_INT) +OB_DEF_VAR (s390_vec_permi_s64, s390_vpdi, 0, O3_M5, BT_OV_V2DI_V2DI_V2DI_INT) +OB_DEF_VAR (s390_vec_permi_b64, s390_vpdi, 0, O3_M5, BT_OV_BV2DI_BV2DI_BV2DI_INT) +OB_DEF_VAR (s390_vec_permi_u64, s390_vpdi, 0, O3_M5, BT_OV_UV2DI_UV2DI_UV2DI_INT) +OB_DEF_VAR (s390_vec_permi_dbl, s390_vpdi, 0, O3_M5, BT_OV_V2DF_V2DF_V2DF_INT) -B_DEF (s390_vpdi, vec_permiv2di, 0, B_VX, O3_U2, BT_FN_UV2DI_UV2DI_UV2DI_INT) +B_DEF (s390_vpdi, vec_permiv2di, 0, B_VX, O3_M5, BT_FN_UV2DI_UV2DI_UV2DI_INT) OB_DEF (s390_vec_splat, s390_vec_splat2_s8, s390_vec_splat2_dbl,B_VX, BT_FN_OV4SI_OV4SI_UCHAR) OB_DEF_VAR (s390_vec_splat2_s8, s390_vrepb, 0, O2_U4, BT_OV_V16QI_V16QI_UCHAR) @@ -2287,8 +2314,8 @@ OB_DEF_VAR (s390_vec_test_mask_dbl, s390_vtm, 0, B_DEF (s390_vtm, vec_test_mask_intv16qi,0, B_VX, 0, BT_FN_INT_UV16QI_UV16QI) -B_DEF (s390_vec_msum_u128, vec_msumv2di, 0, B_VXE, O4_U2, BT_FN_UV16QI_UV2DI_UV2DI_UV16QI_INT) -B_DEF (s390_vmslg, vmslg, 0, B_VXE, O4_U4, BT_FN_INT128_UV2DI_UV2DI_INT128_INT) +B_DEF (s390_vec_msum_u128, vec_msumv2di, 0, B_VXE, O4_M12, BT_FN_UV16QI_UV2DI_UV2DI_UV16QI_INT) +B_DEF (s390_vmslg, vmslg, 0, B_VXE, O4_M12, BT_FN_INT128_UV2DI_UV2DI_INT128_INT) OB_DEF (s390_vec_eqv, s390_vec_eqv_b8, s390_vec_eqv_dbl_c, B_VXE, BT_FN_OV4SI_OV4SI_OV4SI) OB_DEF_VAR (s390_vec_eqv_b8, s390_vnx, 0, 0, BT_OV_BV16QI_BV16QI_BV16QI) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f7b1c03..a9c945c 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -734,15 +734,38 @@ s390_const_operand_ok (tree arg, int argnum, int op_flags, tree decl) { if (O_UIMM_P (op_flags)) { - int bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32 }; - int bitwidth = bitwidths[op_flags - O_U1]; + unsigned HOST_WIDE_INT bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32, 4, 4 }; + unsigned HOST_WIDE_INT bitmasks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 12 }; + unsigned HOST_WIDE_INT bitwidth = bitwidths[op_flags - O_U1]; + unsigned HOST_WIDE_INT bitmask = bitmasks[op_flags - O_U1]; if (!tree_fits_uhwi_p (arg) - || tree_to_uhwi (arg) > (HOST_WIDE_INT_1U << bitwidth) - 1) + || tree_to_uhwi (arg) > (HOST_WIDE_INT_1U << bitwidth) - 1 + || (bitmask && tree_to_uhwi (arg) & ~bitmask)) { - error ("constant argument %d for builtin %qF is out of range " - "(0..%wu)", argnum, decl, - (HOST_WIDE_INT_1U << bitwidth) - 1); + if (bitmask) + { + gcc_assert (bitmask < 16); + char values[120] = ""; + + for (unsigned HOST_WIDE_INT i = 0; i <= bitmask; i++) + { + char buf[5]; + if (i & ~bitmask) + continue; + int ret = snprintf (buf, 5, HOST_WIDE_INT_PRINT_UNSIGNED, i & bitmask); + gcc_assert (ret < 5); + strcat (values, buf); + if (i < bitmask) + strcat (values, ", "); + } + error ("constant argument %d for builtin %qF is invalid (%s)", + argnum, decl, values); + } + else + error ("constant argument %d for builtin %qF is out of range (0..%wu)", + argnum, decl, (HOST_WIDE_INT_1U << bitwidth) - 1); + return false; } } diff --git a/gcc/testsuite/gcc.target/s390/zvector/imm-range-error-1.c b/gcc/testsuite/gcc.target/s390/zvector/imm-range-error-1.c new file mode 100644 index 0000000..1fe68f5 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/zvector/imm-range-error-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mzarch -march=z14 -mzvector" } */ + +#include + +__vector unsigned char q; +__vector unsigned short int h; +__vector unsigned int s; +__vector unsigned long long d; + +int +main () +{ + vec_msum_u128 (d, d, q, 5); /* { dg-error "constant argument 4 for builtin '__builtin_s390_vec_msum_u128' is invalid \\(0, 4, 8, 12\\)" } */ + + /* Using the resolved low-level builtins here makes the errors to be + triggered from s390_expand_builtin. Otherwise they would come + from the parser already preventing other errors from showing + up. */ + __builtin_s390_vrepb (q, 17); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepb' is out of range \\(0..15\\)" } */ + __builtin_s390_vreph (h, 8); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vreph' is out of range \\(0..7\\)" } */ + __builtin_s390_vrepf (s, 4); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepf' is out of range \\(0..3\\)" } */ + __builtin_s390_vrepg (d, 2); /* { dg-error "constant argument 2 for builtin '__builtin_s390_vrepg' is out of range \\(0..1\\)" } */ + + __builtin_s390_vpdi (d, d, 2); /* { dg-error "constant argument 3 for builtin '__builtin_s390_vpdi' is invalid \\(0, 1, 4, 5\\)" } */ +} diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_msum_u128-1.c b/gcc/testsuite/gcc.target/s390/zvector/vec_msum_u128-1.c new file mode 100644 index 0000000..2f5fbca --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_msum_u128-1.c @@ -0,0 +1,45 @@ +/* { dg-do run } */ +/* { dg-require-effective-target s390_vxe } */ +/* { dg-options "-O3 -mzarch -march=z14 -mzvector --save-temps" } */ + +#include + +typedef vector unsigned char uv16qi; +typedef vector unsigned long long uv2di; + +uv2di a = (uv2di){ 12, 42 }; +uv2di b = (uv2di){ 54, 120 }; +uv2di c = (uv2di){ 0, 200 }; + +int +main () +{ + uv2di result; + + result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 0); + + if (result[1] != a[0] * b[0] + a[1] * b[1] + c[1]) + __builtin_abort(); + + result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 4); + + if (result[1] != a[0] * b[0] + a[1] * b[1] * 2 + c[1]) + __builtin_abort(); + + result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 8); + + if (result[1] != a[0] * b[0] * 2 + a[1] * b[1] + c[1]) + __builtin_abort(); + + result = (uv2di)vec_msum_u128 (a, b, (uv16qi)c, 12); + + if (result[1] != a[0] * b[0] * 2 + a[1] * b[1] * 2 + c[1]) + __builtin_abort(); + + return 0; +} + +/* { dg-final { scan-assembler-times "vmslg\t.*0" 1 } } */ +/* { dg-final { scan-assembler-times "vmslg\t.*4" 1 } } */ +/* { dg-final { scan-assembler-times "vmslg\t.*8" 1 } } */ +/* { dg-final { scan-assembler-times "vmslg\t.*12" 1 } } */ -- cgit v1.1 From a065e0bb092a010664777394530ab1a52bb5293b Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 14 Apr 2021 16:19:46 +0100 Subject: aarch64: Handle more SVE vector constants [PR99246] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR99246 is about a case in which we failed to handle a CONST_VECTOR with NELTS_PER_PATTERN==2, i.e. a vector with a “foreground” sequence of N vectors followed by a repeating “background” sequence of N vectors. At the moment, it's difficult to produce these vectors directly, but I'm hoping that for GCC 12 we'll do more folding, which will in turn make this easier to test and easier to optimise. Until then, the patch simply relies on the testcase in the PR. gcc/ PR target/99246 * config/aarch64/aarch64.c (aarch64_expand_sve_const_vector_sel): New function. (aarch64_expand_sve_const_vector): Use it for nelts_per_pattern==2. gcc/testsuite/ PR target/99246 * gcc.target/aarch64/sve/acle/general/pr99246.c: New test. --- gcc/config/aarch64/aarch64.c | 54 ++++++++++++++++++++++ .../gcc.target/aarch64/sve/acle/general/pr99246.c | 17 +++++++ 2 files changed, 71 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr99246.c (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 6405504..04b55d9 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -5166,6 +5166,56 @@ aarch64_expand_sve_ld1rq (rtx dest, rtx src) return true; } +/* SRC is an SVE CONST_VECTOR that contains N "foreground" values followed + by N "background" values. Try to move it into TARGET using: + + PTRUE PRED., VL + MOV TRUE., # + MOV FALSE., # + SEL TARGET., PRED., TRUE., FALSE. + + The PTRUE is always a single instruction but the MOVs might need a + longer sequence. If the background value is zero (as it often is), + the sequence can sometimes collapse to a PTRUE followed by a + zero-predicated move. + + Return the target on success, otherwise return null. */ + +static rtx +aarch64_expand_sve_const_vector_sel (rtx target, rtx src) +{ + gcc_assert (CONST_VECTOR_NELTS_PER_PATTERN (src) == 2); + + /* Make sure that the PTRUE is valid. */ + machine_mode mode = GET_MODE (src); + machine_mode pred_mode = aarch64_sve_pred_mode (mode); + unsigned int npatterns = CONST_VECTOR_NPATTERNS (src); + if (aarch64_svpattern_for_vl (pred_mode, npatterns) + == AARCH64_NUM_SVPATTERNS) + return NULL_RTX; + + rtx_vector_builder pred_builder (pred_mode, npatterns, 2); + rtx_vector_builder true_builder (mode, npatterns, 1); + rtx_vector_builder false_builder (mode, npatterns, 1); + for (unsigned int i = 0; i < npatterns; ++i) + { + true_builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, i)); + pred_builder.quick_push (CONST1_RTX (BImode)); + } + for (unsigned int i = 0; i < npatterns; ++i) + { + false_builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, i + npatterns)); + pred_builder.quick_push (CONST0_RTX (BImode)); + } + expand_operand ops[4]; + create_output_operand (&ops[0], target, mode); + create_input_operand (&ops[1], true_builder.build (), mode); + create_input_operand (&ops[2], false_builder.build (), mode); + create_input_operand (&ops[3], pred_builder.build (), pred_mode); + expand_insn (code_for_vcond_mask (mode, mode), 4, ops); + return target; +} + /* Return a register containing CONST_VECTOR SRC, given that SRC has an SVE data mode and isn't a legitimate constant. Use TARGET for the result if convenient. @@ -5300,6 +5350,10 @@ aarch64_expand_sve_const_vector (rtx target, rtx src) if (GET_MODE_NUNITS (mode).is_constant ()) return NULL_RTX; + if (nelts_per_pattern == 2) + if (rtx res = aarch64_expand_sve_const_vector_sel (target, src)) + return res; + /* Expand each pattern individually. */ gcc_assert (npatterns > 1); rtx_vector_builder builder; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr99246.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr99246.c new file mode 100644 index 0000000..7f1079c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pr99246.c @@ -0,0 +1,17 @@ +/* { dg-options "-Os" } */ + +#include +extern char b[]; +int x; +void f() { + while (x) { + x = svaddv( + svnot_z(svnot_z(svptrue_pat_b8(SV_VL6), + svmov_z(svptrue_pat_b8(SV_VL1), + svptrue_pat_b16(SV_VL3))), + svptrue_pat_b64(SV_VL2)), + svdup_s32(8193)); + for (int j = x; j; j++) + b[j] = 0; + } +} -- cgit v1.1 From 785209fc464ee3efec2b2a8e8244b7292c251ad8 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Wed, 14 Apr 2021 10:43:22 -0600 Subject: PR testsuite/100073 - test case gcc.dg/pr86058.c fails on arm, powerpc64 gcc/testsuite/ChangeLog: * gcc.dg/pr86058.c: Limit to just x86_64. --- gcc/testsuite/gcc.dg/pr86058.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/pr86058.c b/gcc/testsuite/gcc.dg/pr86058.c index 0b030b0..e39b720 100644 --- a/gcc/testsuite/gcc.dg/pr86058.c +++ b/gcc/testsuite/gcc.dg/pr86058.c @@ -1,8 +1,9 @@ /* PR middle-end/86058 - TARGET_MEM_REF causing incorrect message for -Wmaybe-uninitialized warning - { dg-do compile } + The test fails on a number of non-x86_64 targets due to pr100073. + { dg-do compile { target x86_64-*-* } } { dg-options "-O2 -Wuninitialized -Wmaybe-uninitialized" } */ - + extern void foo (int *); void zip (int *out, int indx) @@ -10,9 +11,9 @@ void zip (int *out, int indx) int arr[10]; for (int i = 0; i < indx; ++i) - out[i] = arr[i] + 1; // { dg-warning "'arr\\\[i]' may be used uninitialized" "pr?????" { xfail *-*-* } } + out[i] = arr[i] + 1; // { dg-warning "'arr\\\[i]' may be used uninitialized" "pr99944" { xfail *-*-* } } // { dg-warning "'arr' may be used uninitialized" "actual" { target *-*-* } .-1 } - + foo (arr); foo (out); } -- cgit v1.1 From f99f64f69db49ce6343d79a39eab28dcc6b91865 Mon Sep 17 00:00:00 2001 From: "Vladimir N. Makarov" Date: Wed, 14 Apr 2021 13:21:40 -0400 Subject: [PR100066] Check paradoxical subreg when splitting hard reg live range When splitting live range of a hard reg, LRA actually split multi-register containing the hard reg. So we need to check the biggest used mode of the hard reg on paradoxical subregister when the natural and the biggest mode are ordered. gcc/ChangeLog: PR rtl-optimization/100066 * lra-constraints.c (split_reg): Check paradoxical_subreg_p for ordered modes when choosing splitting mode for hard reg. gcc/testsuite/ChangeLog: PR rtl-optimization/100066 * gcc.target/i386/pr100066.c: New. --- gcc/lra-constraints.c | 12 ++++++++---- gcc/testsuite/gcc.target/i386/pr100066.c | 13 +++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr100066.c (limited to 'gcc') diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 62bcfc3..9425f2d 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -5797,10 +5797,14 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, mode = lra_reg_info[hard_regno].biggest_mode; machine_mode reg_rtx_mode = GET_MODE (regno_reg_rtx[hard_regno]); /* A reg can have a biggest_mode of VOIDmode if it was only ever seen as - part of a multi-word register. In that case, just use the reg_rtx. - Otherwise, limit the size to that of the biggest access in the - function. */ - if (mode == VOIDmode) + part of a multi-word register. In that case, just use the reg_rtx + mode. Do the same also if the biggest mode was larger than a register + or we can not compare the modes. Otherwise, limit the size to that of + the biggest access in the function. */ + if (mode == VOIDmode + || !ordered_p (GET_MODE_PRECISION (mode), + GET_MODE_PRECISION (reg_rtx_mode)) + || paradoxical_subreg_p (mode, reg_rtx_mode)) { original_reg = regno_reg_rtx[hard_regno]; mode = reg_rtx_mode; diff --git a/gcc/testsuite/gcc.target/i386/pr100066.c b/gcc/testsuite/gcc.target/i386/pr100066.c new file mode 100644 index 0000000..a795864 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr100066.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { int128 } } } */ +/* { dg-options "-O1 -w" } */ +int pm; + +void +w3 (int, int, int); + +void +e6 (__int128 rt, long int mo) +{ + mo += rt / 0; + w3 (pm / mo, pm, 0); +} -- cgit v1.1 From 9b53edc796d284b6adec7f2996772dbddf4c341e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 14 Apr 2021 09:30:05 -0400 Subject: c++: non-static member, array bound, sizeof [PR93314] N2253 allowed referring to non-static data members without an object in unevaluated operands like that of sizeof, but in a constant-expression context like an array bound or template argument within such an unevaluated operand we do actually need a value, so that permission cannot apply. gcc/cp/ChangeLog: PR c++/93314 * semantics.c (finish_id_expression_1): Clear cp_unevaluated_operand for a non-static data member in a constant-expression. gcc/testsuite/ChangeLog: PR c++/93314 * g++.dg/parse/uneval1.C: New test. --- gcc/cp/semantics.c | 10 ++++++++++ gcc/testsuite/g++.dg/parse/uneval1.C | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 gcc/testsuite/g++.dg/parse/uneval1.C (limited to 'gcc') diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1257722..4520181 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4093,6 +4093,12 @@ finish_id_expression_1 (tree id_expression, cp_warn_deprecated_use_scopes (scope); + /* In a constant-expression context, turn off cp_unevaluated_operand + so finish_non_static_data_member will complain (93314). */ + auto eval = make_temp_override (cp_unevaluated_operand); + if (integral_constant_expression_p && TREE_CODE (decl) == FIELD_DECL) + cp_unevaluated_operand = 0; + if (TYPE_P (scope)) decl = finish_qualified_id_expr (scope, decl, @@ -4106,6 +4112,10 @@ finish_id_expression_1 (tree id_expression, } else if (TREE_CODE (decl) == FIELD_DECL) { + auto eval = make_temp_override (cp_unevaluated_operand); + if (integral_constant_expression_p) + cp_unevaluated_operand = 0; + /* Since SCOPE is NULL here, this is an unqualified name. Access checking has been performed during name lookup already. Turn off checking to avoid duplicate errors. */ diff --git a/gcc/testsuite/g++.dg/parse/uneval1.C b/gcc/testsuite/g++.dg/parse/uneval1.C new file mode 100644 index 0000000..dfc1bb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/uneval1.C @@ -0,0 +1,14 @@ +// PR c++/93314 + +struct S { + int m; + static int f() { + return sizeof(char[m]); // { dg-error "S::m" } + } +}; + +int main() +{ + return S().f() + + sizeof(char[S::m]); // { dg-error "S::m" } +} -- cgit v1.1 From 00a2774923c1dc5666cd26bb9b8c37b1b7dd689d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 14 Apr 2021 14:14:31 -0400 Subject: c++: premature overload resolution redux [PR100078] My patch for PR93085 didn't consider that a default template argument can also make a template dependent. gcc/cp/ChangeLog: PR c++/100078 PR c++/93085 * pt.c (uses_outer_template_parms): Also look at default template argument. gcc/testsuite/ChangeLog: PR c++/100078 * g++.dg/template/dependent-tmpl2.C: New test. --- gcc/cp/pt.c | 5 +++++ gcc/testsuite/g++.dg/template/dependent-tmpl2.C | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 gcc/testsuite/g++.dg/template/dependent-tmpl2.C (limited to 'gcc') diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f488a5a..0f119a5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10856,6 +10856,7 @@ uses_outer_template_parms (tree decl) for (int i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i) { tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); + tree defarg = TREE_PURPOSE (TREE_VEC_ELT (parms, i)); if (TREE_CODE (parm) == PARM_DECL && for_each_template_parm (TREE_TYPE (parm), template_parm_outer_level, @@ -10864,6 +10865,10 @@ uses_outer_template_parms (tree decl) if (TREE_CODE (parm) == TEMPLATE_DECL && uses_outer_template_parms (parm)) return true; + if (defarg + && for_each_template_parm (defarg, template_parm_outer_level, + &depth, NULL, /*nondeduced*/true)) + return true; } } tree ci = get_constraints (decl); diff --git a/gcc/testsuite/g++.dg/template/dependent-tmpl2.C b/gcc/testsuite/g++.dg/template/dependent-tmpl2.C new file mode 100644 index 0000000..040ddb4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-tmpl2.C @@ -0,0 +1,10 @@ +// PR c++/100078 +// { dg-do compile { target c++11 } } + +template struct enable_if; +template struct HashMapBucket { + template + static typename enable_if::type selectStructure() { + selectStructure(); + } +}; -- cgit v1.1 From 1fce5932a3af575cd02c1d2b786dd1b39b922ebe Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 14 Apr 2021 20:06:44 +0100 Subject: Better const_vector printing Looking at PR99929 showed that we weren't dumping enough information about variable-length CONST_VECTORs. Something like: (const_vector:VNx4SI [(const_int 1) (const_int 0)]) could be either: (a) 1, 0, 1, 0, repeating (b) 1 followed by all zeros This patch adds more information to the dumps. There are four cases: (a) above: (const_vector:VNx4SI repeat [ (const_int 1) (const_int 0) ]) (b) above: (const_vector:VNx4SI [ (const_int 1) repeat [ (const_int 0) ] ]) a single stepped sequence: (const_vector:VNx4SI [ (const_int 0) stepped [ (const_int 1) (const_int 2) ] ]) interleaved stepped sequences: (const_vector:VNx4SI [ (const_int 0) (const_int 40) stepped (interleave 2) [ (const_int 1) (const_int 41) (const_int 2) (const_int 42) ] ]) There are probably better syntaxes, but hopefully this is at least an improvement on the status quo. gcc/ * print-rtl.c (rtx_writer::print_rtx_operand_codes_E_and_V): Print more information about variable-length CONST_VECTORs. --- gcc/print-rtl.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index c7982bc..081fc50 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -370,6 +370,10 @@ rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx) print_rtx_head, m_indent * 2, ""); m_sawclose = 0; } + if (GET_CODE (in_rtx) == CONST_VECTOR + && !GET_MODE_NUNITS (GET_MODE (in_rtx)).is_constant () + && CONST_VECTOR_DUPLICATE_P (in_rtx)) + fprintf (m_outfile, " repeat"); fputs (" [", m_outfile); if (XVEC (in_rtx, idx) != NULL) { @@ -377,12 +381,32 @@ rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx) if (XVECLEN (in_rtx, idx)) m_sawclose = 1; + int barrier = XVECLEN (in_rtx, idx); + if (GET_CODE (in_rtx) == CONST_VECTOR + && !GET_MODE_NUNITS (GET_MODE (in_rtx)).is_constant ()) + barrier = CONST_VECTOR_NPATTERNS (in_rtx); + for (int j = 0; j < XVECLEN (in_rtx, idx); j++) { int j1; + if (j == barrier) + { + fprintf (m_outfile, "\n%s%*s", + print_rtx_head, m_indent * 2, ""); + if (!CONST_VECTOR_STEPPED_P (in_rtx)) + fprintf (m_outfile, "repeat ["); + else if (CONST_VECTOR_NPATTERNS (in_rtx) == 1) + fprintf (m_outfile, "stepped ["); + else + fprintf (m_outfile, "stepped (interleave %d) [", + CONST_VECTOR_NPATTERNS (in_rtx)); + m_indent += 2; + } + print_rtx (XVECEXP (in_rtx, idx, j)); - for (j1 = j + 1; j1 < XVECLEN (in_rtx, idx); j1++) + int limit = MIN (barrier, XVECLEN (in_rtx, idx)); + for (j1 = j + 1; j1 < limit; j1++) if (XVECEXP (in_rtx, idx, j) != XVECEXP (in_rtx, idx, j1)) break; @@ -393,6 +417,12 @@ rtx_writer::print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx) } } + if (barrier < XVECLEN (in_rtx, idx)) + { + m_indent -= 2; + fprintf (m_outfile, "\n%s%*s]", print_rtx_head, m_indent * 2, ""); + } + m_indent -= 2; } if (m_sawclose) -- cgit v1.1 From a87d3f964df31d4fbceb822c6d293e85c117d992 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 14 Apr 2021 20:06:45 +0100 Subject: Check for matching CONST_VECTOR encodings [PR99929] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR99929 is one of those “how did we get away with this for so long” bugs: the equality routines weren't checking whether two variable-length CONST_VECTORs had the same encoding. This meant that: { 1, 0, 0, 0, 0, 0, ... } would appear to be equal to: { 1, 0, 1, 0, 1, 0, ... } since both are represented using the elements { 1, 0 }. gcc/ PR rtl-optimization/99929 * rtl.h (same_vector_encodings_p): New function. * cse.c (exp_equiv_p): Check that CONST_VECTORs have the same encoding. * cselib.c (rtx_equal_for_cselib_1): Likewise. * jump.c (rtx_renumbered_equal_p): Likewise. * lra-constraints.c (operands_match_p): Likewise. * reload.c (operands_match_p): Likewise. * rtl.c (rtx_equal_p_cb, rtx_equal_p): Likewise. gcc/testsuite/ * gcc.target/aarch64/sve/pr99929_1.c: New file. * gcc.target/aarch64/sve/pr99929_2.c: Likewise. --- gcc/cse.c | 5 +++++ gcc/cselib.c | 5 +++++ gcc/jump.c | 5 +++++ gcc/lra-constraints.c | 5 +++++ gcc/reload.c | 5 +++++ gcc/rtl.c | 10 ++++++++++ gcc/rtl.h | 17 +++++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c | 16 ++++++++++++++++ gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c | 5 +++++ 9 files changed, 73 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c (limited to 'gcc') diff --git a/gcc/cse.c b/gcc/cse.c index 37c6959..df191d5 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -2637,6 +2637,11 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse) CASE_CONST_UNIQUE: return x == y; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case LABEL_REF: return label_ref_label (x) == label_ref_label (y); diff --git a/gcc/cselib.c b/gcc/cselib.c index 2d34a91..779874e 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -1048,6 +1048,11 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, machine_mode memmode, int depth) case DEBUG_EXPR: return 0; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case DEBUG_IMPLICIT_PTR: return DEBUG_IMPLICIT_PTR_DECL (x) == DEBUG_IMPLICIT_PTR_DECL (y); diff --git a/gcc/jump.c b/gcc/jump.c index 561dbb7..67b5c33 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -1777,6 +1777,11 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y) CASE_CONST_UNIQUE: return 0; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case LABEL_REF: /* We can't assume nonlocal labels have their following insns yet. */ if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y)) diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 9425f2d..5c2a2d7 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -834,6 +834,11 @@ operands_match_p (rtx x, rtx y, int y_hard_regno) CASE_CONST_UNIQUE: return false; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case LABEL_REF: return label_ref_label (x) == label_ref_label (y); case SYMBOL_REF: diff --git a/gcc/reload.c b/gcc/reload.c index 461fd02..e18e27c 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -2310,6 +2310,11 @@ operands_match_p (rtx x, rtx y) CASE_CONST_UNIQUE: return 0; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case LABEL_REF: return label_ref_label (x) == label_ref_label (y); case SYMBOL_REF: diff --git a/gcc/rtl.c b/gcc/rtl.c index 1aa794c..e4ae168 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -466,6 +466,11 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) CASE_CONST_UNIQUE: return 0; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case DEBUG_IMPLICIT_PTR: return DEBUG_IMPLICIT_PTR_DECL (x) == DEBUG_IMPLICIT_PTR_DECL (y); @@ -608,6 +613,11 @@ rtx_equal_p (const_rtx x, const_rtx y) CASE_CONST_UNIQUE: return 0; + case CONST_VECTOR: + if (!same_vector_encodings_p (x, y)) + return false; + break; + case DEBUG_IMPLICIT_PTR: return DEBUG_IMPLICIT_PTR_DECL (x) == DEBUG_IMPLICIT_PTR_DECL (y); diff --git a/gcc/rtl.h b/gcc/rtl.h index a392721..398d745 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3087,6 +3087,23 @@ vec_series_p (const_rtx x, rtx *base_out, rtx *step_out) return const_vec_series_p (x, base_out, step_out); } +/* Return true if CONST_VECTORs X and Y, which are known to have the same mode, + also have the same encoding. This means that they are equal whenever their + operands are equal. */ + +inline bool +same_vector_encodings_p (const_rtx x, const_rtx y) +{ + /* Don't be fussy about the encoding of constant-length vectors, + since XVECEXP (X, 0) and XVECEXP (Y, 0) list all the elements anyway. */ + if (poly_uint64 (CONST_VECTOR_NUNITS (x)).is_constant ()) + return true; + + return (CONST_VECTOR_NPATTERNS (x) == CONST_VECTOR_NPATTERNS (y) + && (CONST_VECTOR_NELTS_PER_PATTERN (x) + == CONST_VECTOR_NELTS_PER_PATTERN (y))); +} + /* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X. */ inline scalar_int_mode diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c b/gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c new file mode 100644 index 0000000..1fe1813 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr99929_1.c @@ -0,0 +1,16 @@ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include + +static void e(short *g, short p2) { *g ^= p2; } +static short m[23]; +int main() { + for (unsigned i = 0; i < 23; ++i) + m[i] = 4; + if (svaddv(svptrue_pat_b32(SV_VL1), svdup_u32(1)) != 1) + __builtin_abort(); + for (unsigned i = 0; i < 3; ++i) + e(m, m[i]); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c b/gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c new file mode 100644 index 0000000..50d432d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr99929_2.c @@ -0,0 +1,5 @@ +/* { dg-options "-O2 -ftree-vectorize" } */ + +#include "pr99929_1.c" + +/* { dg-final { scan-assembler {\tptrue\tp[0-7].[bhsd], vl1\n} } } */ -- cgit v1.1 From df3b1289521e6f24d5151fc5f7b135b8bf3009bc Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 15 Apr 2021 00:16:47 +0000 Subject: Daily bump. --- gcc/ChangeLog | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 42 +++++++++++++++++ gcc/d/ChangeLog | 37 +++++++++++++++ gcc/fortran/ChangeLog | 5 ++ gcc/testsuite/ChangeLog | 64 ++++++++++++++++++++++++++ 6 files changed, 269 insertions(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0eebc87..90860a7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,123 @@ +2021-04-14 Richard Sandiford + + PR rtl-optimization/99929 + * rtl.h (same_vector_encodings_p): New function. + * cse.c (exp_equiv_p): Check that CONST_VECTORs have the same encoding. + * cselib.c (rtx_equal_for_cselib_1): Likewise. + * jump.c (rtx_renumbered_equal_p): Likewise. + * lra-constraints.c (operands_match_p): Likewise. + * reload.c (operands_match_p): Likewise. + * rtl.c (rtx_equal_p_cb, rtx_equal_p): Likewise. + +2021-04-14 Richard Sandiford + + * print-rtl.c (rtx_writer::print_rtx_operand_codes_E_and_V): Print + more information about variable-length CONST_VECTORs. + +2021-04-14 Vladimir N. Makarov + + PR rtl-optimization/100066 + * lra-constraints.c (split_reg): Check paradoxical_subreg_p for + ordered modes when choosing splitting mode for hard reg. + +2021-04-14 Richard Sandiford + + PR target/99246 + * config/aarch64/aarch64.c (aarch64_expand_sve_const_vector_sel): + New function. + (aarch64_expand_sve_const_vector): Use it for nelts_per_pattern==2. + +2021-04-14 Andreas Krebbel + + * config/s390/s390-builtins.def (O_M5, O_M12, ...): Add new macros + for mask operand types. + (s390_vec_permi_s64, s390_vec_permi_b64, s390_vec_permi_u64) + (s390_vec_permi_dbl, s390_vpdi): Use the M5 type for the immediate + operand. + (s390_vec_msum_u128, s390_vmslg): Use the M12 type for the + immediate operand. + * config/s390/s390.c (s390_const_operand_ok): Check the new + operand types and generate a list of valid values. + +2021-04-14 Iain Buclaw + + * doc/tm.texi: Regenerate. + * doc/tm.texi.in (D language and ABI): Add @hook for + TARGET_D_REGISTER_OS_TARGET_INFO. + +2021-04-14 Iain Buclaw + + * config/aarch64/aarch64-d.c (aarch64_d_handle_target_float_abi): New + function. + (aarch64_d_register_target_info): New function. + * config/aarch64/aarch64-protos.h (aarch64_d_register_target_info): + Declare. + * config/aarch64/aarch64.h (TARGET_D_REGISTER_CPU_TARGET_INFO): + Define. + * config/arm/arm-d.c (arm_d_handle_target_float_abi): New function. + (arm_d_register_target_info): New function. + * config/arm/arm-protos.h (arm_d_register_target_info): Declare. + * config/arm/arm.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/i386/i386-d.c (ix86_d_handle_target_float_abi): New function. + (ix86_d_register_target_info): New function. + * config/i386/i386-protos.h (ix86_d_register_target_info): Declare. + * config/i386/i386.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/mips/mips-d.c (mips_d_handle_target_float_abi): New function. + (mips_d_register_target_info): New function. + * config/mips/mips-protos.h (mips_d_register_target_info): Declare. + * config/mips/mips.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/pa/pa-d.c (pa_d_handle_target_float_abi): New function. + (pa_d_register_target_info): New function. + * config/pa/pa-protos.h (pa_d_register_target_info): Declare. + * config/pa/pa.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/riscv/riscv-d.c (riscv_d_handle_target_float_abi): New + function. + (riscv_d_register_target_info): New function. + * config/riscv/riscv-protos.h (riscv_d_register_target_info): Declare. + * config/riscv/riscv.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/rs6000/rs6000-d.c (rs6000_d_handle_target_float_abi): New + function. + (rs6000_d_register_target_info): New function. + * config/rs6000/rs6000-protos.h (rs6000_d_register_target_info): + Declare. + * config/rs6000/rs6000.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/s390/s390-d.c (s390_d_handle_target_float_abi): New function. + (s390_d_register_target_info): New function. + * config/s390/s390-protos.h (s390_d_register_target_info): Declare. + * config/s390/s390.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * config/sparc/sparc-d.c (sparc_d_handle_target_float_abi): New + function. + (sparc_d_register_target_info): New function. + * config/sparc/sparc-protos.h (sparc_d_register_target_info): Declare. + * config/sparc/sparc.h (TARGET_D_REGISTER_CPU_TARGET_INFO): Define. + * doc/tm.texi: Regenerate. + * doc/tm.texi.in (D language and ABI): Add @hook for + TARGET_D_REGISTER_CPU_TARGET_INFO. + +2021-04-14 Iain Buclaw + + * config/i386/i386-d.c (ix86_d_has_stdcall_convention): New function. + * config/i386/i386-protos.h (ix86_d_has_stdcall_convention): Declare. + * config/i386/i386.h (TARGET_D_HAS_STDCALL_CONVENTION): Define. + * doc/tm.texi: Regenerate. + * doc/tm.texi.in (D language and ABI): Add @hook for + TARGET_D_HAS_STDCALL_CONVENTION. + +2021-04-14 Richard Biener + + * tree-cfg.c (verify_gimple_assign_ternary): Verify that + VEC_COND_EXPRs have a gimple_val condition. + * tree-ssa-propagate.c (valid_gimple_rhs_p): VEC_COND_EXPR + can no longer have a GENERIC condition. + +2021-04-14 Richard Earnshaw + + PR target/100067 + * config/arm/arm.c (arm_configure_build_target): Strip isa_all_fpbits + from the isa_delta when -mfpu has been used. + (arm_options_perform_arch_sanity_checks): It's the architecture that + lacks an FPU not the processor. + 2021-04-13 Richard Biener PR tree-optimization/100053 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 3219cc3..e9d3aa7 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210414 +20210415 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9145630..e508222 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,45 @@ +2021-04-14 Jason Merrill + + PR c++/100078 + PR c++/93085 + * pt.c (uses_outer_template_parms): Also look at default + template argument. + +2021-04-14 Jason Merrill + + PR c++/93314 + * semantics.c (finish_id_expression_1): Clear cp_unevaluated_operand + for a non-static data member in a constant-expression. + +2021-04-14 Patrick Palka + + PR c++/83476 + PR c++/99885 + * pt.c (deducible_expression): Look through implicit + INDIRECT_REFs as well. + +2021-04-14 Jason Merrill + + PR c++/99478 + * parser.c (cp_parser_lambda_expression): Reject lambda + in template parameter type. + +2021-04-14 Jason Merrill + + PR c++/90674 + * decl.c (duplicate_decls): Don't propagate + DECL_INITIALIZED_IN_CLASS_P to a specialization. + +2021-04-14 Jason Merrill + + PR c++/88742 + PR c++/49951 + PR c++/58123 + * semantics.c (set_cleanup_locs): New. + (do_poplevel): Call it. + * parser.c (cp_parser_compound_statement): Consume the } + before finish_compound_stmt. + 2021-04-13 Jason Merrill PR c++/100032 diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 11206f2..fe89d7b 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,40 @@ +2021-04-14 Iain Buclaw + + * d-target.cc (Target::_init): Call new targetdm hook to register OS + specific target info keys. + * d-target.def (d_register_os_target_info): New hook. + +2021-04-14 Iain Buclaw + + * d-builtins.cc (d_add_builtin_version): Remove all setting of + target-specific global.params. + * typeinfo.cc (create_typeinfo): Don't add argType fields to + TypeInfo_Struct. + +2021-04-14 Iain Buclaw + + PR d/99914 + * decl.cc (DeclVisitor::visit (StructDeclaration *)): Don't set + DECL_INSTANTIATED on static initializer declarations. + (DeclVisitor::visit (ClassDeclaration *)): Likewise. + (DeclVisitor::visit (EnumDeclaration *)): Likewise. + (d_finish_decl): Move call to set_linkage_for_decl to... + (declare_extern_var): ...here. + +2021-04-14 Iain Buclaw + + * d-target.cc (Target::_init): Call new targetdm hook to register CPU + specific target info keys. + * d-target.def (d_register_cpu_target_info): New hook. + +2021-04-14 Iain Buclaw + + * d-target.cc (Target::systemLinkage): Return LINKwindows if + d_has_stdcall_convention applies to LINKsystem. + * d-target.def (d_has_stdcall_convention): New hook. + * types.cc (TypeVisitor::visit (TypeFunction *)): Insert "stdcall" + function attribute if d_has_stdcall_convention applies to LINKwindows. + 2021-04-10 Iain Buclaw * dmd/MERGE: Merge upstream dmd 0450061c8. diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 8fc1159..1f8578c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,8 @@ +2021-04-14 Martin Liska + + * intrinsic.texi: The table has first column empty and it makes + trouble when processing makeinfo --xml output. + 2021-04-09 Tobias Burnus PR fortran/99817 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1f79bc3..d9e9168 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,67 @@ +2021-04-14 Richard Sandiford + + * gcc.target/aarch64/sve/pr99929_1.c: New file. + * gcc.target/aarch64/sve/pr99929_2.c: Likewise. + +2021-04-14 Jason Merrill + + PR c++/100078 + * g++.dg/template/dependent-tmpl2.C: New test. + +2021-04-14 Jason Merrill + + PR c++/93314 + * g++.dg/parse/uneval1.C: New test. + +2021-04-14 Vladimir N. Makarov + + PR rtl-optimization/100066 + * gcc.target/i386/pr100066.c: New. + +2021-04-14 Martin Sebor + + * gcc.dg/pr86058.c: Limit to just x86_64. + +2021-04-14 Richard Sandiford + + PR target/99246 + * gcc.target/aarch64/sve/acle/general/pr99246.c: New test. + +2021-04-14 Andreas Krebbel + + * gcc.target/s390/zvector/imm-range-error-1.c: New test. + * gcc.target/s390/zvector/vec_msum_u128-1.c: New test. + +2021-04-14 Patrick Palka + + PR c++/83476 + PR c++/99885 + * g++.dg/cpp1z/class-deduction85.C: New test. + * g++.dg/template/ref11.C: New test. + +2021-04-14 Jason Merrill + + PR c++/99478 + * g++.dg/cpp2a/lambda-uneval14.C: New test. + +2021-04-14 Jason Merrill + + PR c++/90674 + * g++.dg/debug/defaulted1.C: New test. + +2021-04-14 Jason Merrill + + PR c++/88742 + * g++.dg/debug/cleanup1.C: New test. + * c-c++-common/Wimplicit-fallthrough-6.c: Adjust diagnostic line. + * c-c++-common/Wimplicit-fallthrough-7.c: Likewise. + * g++.dg/cpp2a/constexpr-dtor3.C: Likewise. + * g++.dg/ext/constexpr-attr-cleanup1.C: Likewise. + * g++.dg/tm/inherit2.C: Likewise. + * g++.dg/tm/unsafe1.C: Likewise. + * g++.dg/warn/Wimplicit-fallthrough-1.C: Likewise. + * g++.dg/gcov/gcov-2.C: Adjust coverage counts. + 2021-04-13 Martin Sebor PR tree-optimization/82800 -- cgit v1.1 From 417c36cfd620bf2b047852c2aa9ac49004aed2bc Mon Sep 17 00:00:00 2001 From: Stefan Schulze Frielinghaus Date: Thu, 15 Apr 2021 08:03:47 +0200 Subject: re PR tree-optimization/93210 (Sub-optimal code optimization on struct/combound constexpr (gcc vs. clang)) Regarding test gcc.dg/pr93210.c, on different targets GIMPLE code may slightly differ which is why the scan-tree-dump-times directive may fail. For example, for a RETURN_EXPR on x86_64 we have return 0x11100f0e0d0c0a090807060504030201; whereas on IBM Z the first operand is a RESULT_DECL like = 0x102030405060708090a0c0d0e0f1011; return ; gcc/testsuite/ChangeLog: * gcc.dg/pr93210.c: Adapt regex in order to also support a RESULT_DECL as an operand for a RETURN_EXPR. --- gcc/testsuite/gcc.dg/pr93210.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/pr93210.c b/gcc/testsuite/gcc.dg/pr93210.c index ec4194b..134d32b 100644 --- a/gcc/testsuite/gcc.dg/pr93210.c +++ b/gcc/testsuite/gcc.dg/pr93210.c @@ -1,7 +1,7 @@ /* PR tree-optimization/93210 */ /* { dg-do run } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ -/* { dg-final { scan-tree-dump-times "return \[0-9]\[0-9a-fA-FxX]*;" 31 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "(?:return| =) \[0-9]\[0-9a-fA-FxX]*;" 31 "optimized" } } */ #ifdef __SIZEOF_INT128__ typedef unsigned __int128 L; -- cgit v1.1 From 9a0e09f3dd5339bb18cc47317f2298d9157ced29 Mon Sep 17 00:00:00 2001 From: Paul Thomas Date: Thu, 15 Apr 2021 07:34:26 +0100 Subject: Fortran: Fix class reallocate on assignment [PR99307]. 2021-04-15 Paul Thomas gcc/fortran PR fortran/99307 * symbol.c: Remove trailing white space. * trans-array.c (gfc_trans_create_temp_array): Create a class temporary for class expressions and assign the new descriptor to the data field. (build_class_array_ref): If the class expr can be extracted, then use that for 'decl'. Class function results are reliably handled this way. Call gfc_find_and_cut_at_last_class_ref to eliminate largely redundant code. Remove dead code and recast the rest of the code to extract 'decl' for remaining cases. Call gfc_build_spanned_array_ref. (gfc_alloc_allocatable_for_assignment): Use class descriptor element length for 'elemsize1'. Eliminate repeat set of dtype for class expressions. * trans-expr.c (gfc_find_and_cut_at_last_class_ref): Include additional code from build_class_array_ref, and use optional gfc_typespec pointer argument. (gfc_trans_scalar_assign): Make use of pre and post blocks for all class expressions. * trans.c (get_array_span): For unlimited polymorphic exprs multiply the span by the value of the _len field. (gfc_build_spanned_array_ref): New function. (gfc_build_array_ref): Call gfc_build_spanned_array_ref and eliminate repeated code. * trans.h: Add arg to gfc_find_and_cut_at_last_class_ref and add prototype for gfc_build_spanned_array_ref. --- gcc/fortran/symbol.c | 2 +- gcc/fortran/trans-array.c | 204 ++++++++++++++++++---------------------------- gcc/fortran/trans-expr.c | 98 +++++++++++++++------- gcc/fortran/trans.c | 36 +++++--- gcc/fortran/trans.h | 6 +- 5 files changed, 177 insertions(+), 169 deletions(-) (limited to 'gcc') diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index e982374..6d61bf4 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -4391,7 +4391,7 @@ get_iso_c_binding_dt (int sym_id) if (dt_list->from_intmod != INTMOD_NONE && dt_list->intmod_sym_id == sym_id) return dt_list; - + dt_list = dt_list->dt_next; } } diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index be5eb89..ca90142 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -1403,9 +1403,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, desc = gfc_create_var (type, "atmp"); GFC_DECL_PACKED_ARRAY (desc) = 1; - info->descriptor = desc; - size = gfc_index_one_node; - /* Emit a DECL_EXPR for the variable sized array type in GFC_TYPE_ARRAY_DATAPTR_TYPE so the gimplification of its type sizes works correctly. */ @@ -1416,9 +1413,40 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss, gfc_add_expr_to_block (pre, build1 (DECL_EXPR, arraytype, TYPE_NAME (arraytype))); - /* Fill in the array dtype. */ - tmp = gfc_conv_descriptor_dtype (desc); - gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc))); + if (class_expr != NULL_TREE) + { + tree class_data; + tree dtype; + + /* Create a class temporary. */ + tmp = gfc_create_var (TREE_TYPE (class_expr), "ctmp"); + gfc_add_modify (pre, tmp, class_expr); + + /* Assign the new descriptor to the _data field. This allows the + vptr _copy to be used for scalarized assignment since the class + temporary can be found from the descriptor. */ + class_data = gfc_class_data_get (tmp); + tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR, + TREE_TYPE (desc), desc); + gfc_add_modify (pre, class_data, tmp); + + /* Take the dtype from the class expression. */ + dtype = gfc_conv_descriptor_dtype (gfc_class_data_get (class_expr)); + tmp = gfc_conv_descriptor_dtype (class_data); + gfc_add_modify (pre, tmp, dtype); + + /* Point desc to the class _data field. */ + desc = class_data; + } + else + { + /* Fill in the array dtype. */ + tmp = gfc_conv_descriptor_dtype (desc); + gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc))); + } + + info->descriptor = desc; + size = gfc_index_one_node; /* Fill in the bounds and stride. This is a packed array, so: @@ -3424,134 +3452,73 @@ conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i, static bool build_class_array_ref (gfc_se *se, tree base, tree index) { - tree type; tree size; - tree offset; tree decl = NULL_TREE; tree tmp; gfc_expr *expr = se->ss->info->expr; - gfc_ref *ref; - gfc_ref *class_ref = NULL; + gfc_expr *class_expr; gfc_typespec *ts; + gfc_symbol *sym; - if (se->expr && DECL_P (se->expr) && DECL_LANG_SPECIFIC (se->expr) - && GFC_DECL_SAVED_DESCRIPTOR (se->expr) - && GFC_CLASS_TYPE_P (TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (se->expr)))) - decl = se->expr; + tmp = !VAR_P (base) ? gfc_get_class_from_expr (base) : NULL_TREE; + + if (tmp != NULL_TREE) + decl = tmp; else { - if (expr == NULL + /* The base expression does not contain a class component, either + because it is a temporary array or array descriptor. Class + array functions are correctly resolved above. */ + if (!expr || (expr->ts.type != BT_CLASS - && !gfc_is_class_array_function (expr) && !gfc_is_class_array_ref (expr, NULL))) return false; - if (expr->symtree && expr->symtree->n.sym->ts.type == BT_CLASS) - ts = &expr->symtree->n.sym->ts; - else - ts = NULL; - - for (ref = expr->ref; ref; ref = ref->next) - { - if (ref->type == REF_COMPONENT - && ref->u.c.component->ts.type == BT_CLASS - && ref->next && ref->next->type == REF_COMPONENT - && strcmp (ref->next->u.c.component->name, "_data") == 0 - && ref->next->next - && ref->next->next->type == REF_ARRAY - && ref->next->next->u.ar.type != AR_ELEMENT) - { - ts = &ref->u.c.component->ts; - class_ref = ref; - break; - } - } + /* Obtain the expression for the class entity or component that is + followed by an array reference, which is not an element, so that + the span of the array can be obtained. */ + class_expr = gfc_find_and_cut_at_last_class_ref (expr, false, &ts); - if (ts == NULL) + if (!ts) return false; - } - if (class_ref == NULL && expr && expr->symtree->n.sym->attr.function - && expr->symtree->n.sym == expr->symtree->n.sym->result - && expr->symtree->n.sym->backend_decl == current_function_decl) - { - decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0); - } - else if (expr && gfc_is_class_array_function (expr)) - { - size = NULL_TREE; - decl = NULL_TREE; - for (tmp = base; tmp; tmp = TREE_OPERAND (tmp, 0)) - { - tree type; - type = TREE_TYPE (tmp); - while (type) - { - if (GFC_CLASS_TYPE_P (type)) - decl = tmp; - if (type != TYPE_CANONICAL (type)) - type = TYPE_CANONICAL (type); - else - type = NULL_TREE; - } - if (VAR_P (tmp)) - break; + sym = (!class_expr && expr) ? expr->symtree->n.sym : NULL; + if (sym && sym->attr.function + && sym == sym->result + && sym->backend_decl == current_function_decl) + /* The temporary is the data field of the class data component + of the current function. */ + decl = gfc_get_fake_result_decl (sym, 0); + else if (sym) + { + if (decl == NULL_TREE) + decl = expr->symtree->n.sym->backend_decl; + /* For class arrays the tree containing the class is stored in + GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl. + For all others it's sym's backend_decl directly. */ + if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl)) + decl = GFC_DECL_SAVED_DESCRIPTOR (decl); } + else + decl = gfc_get_class_from_gfc_expr (class_expr); - if (decl == NULL_TREE) - return false; + if (POINTER_TYPE_P (TREE_TYPE (decl))) + decl = build_fold_indirect_ref_loc (input_location, decl); - se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre); - } - else if (class_ref == NULL) - { - if (decl == NULL_TREE) - decl = expr->symtree->n.sym->backend_decl; - /* For class arrays the tree containing the class is stored in - GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl. - For all others it's sym's backend_decl directly. */ - if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl)) - decl = GFC_DECL_SAVED_DESCRIPTOR (decl); - } - else - { - /* Remove everything after the last class reference, convert the - expression and then recover its tailend once more. */ - gfc_se tmpse; - ref = class_ref->next; - class_ref->next = NULL; - gfc_init_se (&tmpse, NULL); - gfc_conv_expr (&tmpse, expr); - gfc_add_block_to_block (&se->pre, &tmpse.pre); - decl = tmpse.expr; - class_ref->next = ref; + if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl))) + return false; } - if (POINTER_TYPE_P (TREE_TYPE (decl))) - decl = build_fold_indirect_ref_loc (input_location, decl); - - if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl))) - return false; + se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre); size = gfc_class_vtab_size_get (decl); - /* For unlimited polymorphic entities then _len component needs to be multiplied with the size. */ size = gfc_resize_class_size_with_len (&se->pre, decl, size); - size = fold_convert (TREE_TYPE (index), size); - /* Build the address of the element. */ - type = TREE_TYPE (TREE_TYPE (base)); - offset = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, - index, size); - tmp = gfc_build_addr_expr (pvoid_type_node, base); - tmp = fold_build_pointer_plus_loc (input_location, tmp, offset); - tmp = fold_convert (build_pointer_type (type), tmp); - /* Return the element in the se expression. */ - se->expr = build_fold_indirect_ref_loc (input_location, tmp); + se->expr = gfc_build_spanned_array_ref (base, index, size); return true; } @@ -10280,23 +10247,10 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, } else if (expr1->ts.type == BT_CLASS) { - tmp = expr1->rank ? gfc_get_class_from_expr (desc) : NULL_TREE; - if (tmp == NULL_TREE) - tmp = gfc_get_class_from_gfc_expr (expr1); - - if (tmp != NULL_TREE) - { - tmp2 = gfc_class_vptr_get (tmp); - cond = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, tmp2, - build_int_cst (TREE_TYPE (tmp2), 0)); - elemsize1 = gfc_class_vtab_size_get (tmp); - elemsize1 = fold_build3_loc (input_location, COND_EXPR, - gfc_array_index_type, cond, - elemsize1, gfc_index_zero_node); - } - else - elemsize1 = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&CLASS_DATA (expr1)->ts)); + /* Unfortunately, the lhs vptr is set too early in many cases. + Play it safe by using the descriptor element length. */ + tmp = gfc_conv_descriptor_elem_len (desc); + elemsize1 = fold_convert (gfc_array_index_type, tmp); } else elemsize1 = NULL_TREE; @@ -10770,11 +10724,11 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, /* We already set the dtype in the case of deferred character - length arrays and unlimited polymorphic arrays. */ + length arrays and class lvalues. */ if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)) && ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred) || coarray)) - && !UNLIMITED_POLY (expr1)) + && expr1->ts.type != BT_CLASS) { tmp = gfc_conv_descriptor_dtype (desc); gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc))); diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 2fa17b3..213f32b 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -380,15 +380,20 @@ gfc_vptr_size_get (tree vptr) #undef VTABLE_FINAL_FIELD -/* Search for the last _class ref in the chain of references of this - expression and cut the chain there. Albeit this routine is similiar - to class.c::gfc_add_component_ref (), is there a significant - difference: gfc_add_component_ref () concentrates on an array ref to - be the last ref in the chain. This routine is oblivious to the kind - of refs following. */ +/* IF ts is null (default), search for the last _class ref in the chain + of references of the expression and cut the chain there. Although + this routine is similiar to class.c:gfc_add_component_ref (), there + is a significant difference: gfc_add_component_ref () concentrates + on an array ref that is the last ref in the chain and is oblivious + to the kind of refs following. + ELSE IF ts is non-null the cut is at the class entity or component + that is followed by an array reference, which is not an element. + These calls come from trans-array.c:build_class_array_ref, which + handles scalarized class array references.*/ gfc_expr * -gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold) +gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold, + gfc_typespec **ts) { gfc_expr *base_expr; gfc_ref *ref, *class_ref, *tail = NULL, *array_ref; @@ -396,27 +401,59 @@ gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold) /* Find the last class reference. */ class_ref = NULL; array_ref = NULL; - for (ref = e->ref; ref; ref = ref->next) + + if (ts) { - if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT) - array_ref = ref; + if (e->symtree + && e->symtree->n.sym->ts.type == BT_CLASS) + *ts = &e->symtree->n.sym->ts; + else + *ts = NULL; + } - if (ref->type == REF_COMPONENT - && ref->u.c.component->ts.type == BT_CLASS) + for (ref = e->ref; ref; ref = ref->next) + { + if (ts) { - /* Component to the right of a part reference with nonzero rank - must not have the ALLOCATABLE attribute. If attempts are - made to reference such a component reference, an error results - followed by an ICE. */ - if (array_ref && CLASS_DATA (ref->u.c.component)->attr.allocatable) - return NULL; - class_ref = ref; + if (ref->type == REF_COMPONENT + && ref->u.c.component->ts.type == BT_CLASS + && ref->next && ref->next->type == REF_COMPONENT + && !strcmp (ref->next->u.c.component->name, "_data") + && ref->next->next + && ref->next->next->type == REF_ARRAY + && ref->next->next->u.ar.type != AR_ELEMENT) + { + *ts = &ref->u.c.component->ts; + class_ref = ref; + break; + } + + if (ref->next == NULL) + break; } + else + { + if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT) + array_ref = ref; - if (ref->next == NULL) - break; + if (ref->type == REF_COMPONENT + && ref->u.c.component->ts.type == BT_CLASS) + { + /* Component to the right of a part reference with nonzero + rank must not have the ALLOCATABLE attribute. If attempts + are made to reference such a component reference, an error + results followed by an ICE. */ + if (array_ref + && CLASS_DATA (ref->u.c.component)->attr.allocatable) + return NULL; + class_ref = ref; + } + } } + if (ts && *ts == NULL) + return NULL; + /* Remove and store all subsequent references after the CLASS reference. */ if (class_ref) @@ -10005,17 +10042,20 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts, gfc_add_modify (&block, lse->expr, tmp); } /* If possible use the rhs vptr copy with trans_scalar_class_assign.... */ - else if (ts.type == BT_CLASS - && !trans_scalar_class_assign (&block, lse, rse)) + else if (ts.type == BT_CLASS) { gfc_add_block_to_block (&block, &lse->pre); gfc_add_block_to_block (&block, &rse->pre); - /* ...otherwise assignment suffices. Note the use of VIEW_CONVERT_EXPR - for the lhs which ensures that class data rhs cast as a string assigns - correctly. */ - tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR, - TREE_TYPE (rse->expr), lse->expr); - gfc_add_modify (&block, tmp, rse->expr); + + if (!trans_scalar_class_assign (&block, lse, rse)) + { + /* ...otherwise assignment suffices. Note the use of VIEW_CONVERT_EXPR + for the lhs which ensures that class data rhs cast as a string assigns + correctly. */ + tmp = fold_build1_loc (input_location, VIEW_CONVERT_EXPR, + TREE_TYPE (rse->expr), lse->expr); + gfc_add_modify (&block, tmp, rse->expr); + } } else if (ts.type != BT_CLASS) { diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index ab53fc5..9e8e861 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -422,6 +422,9 @@ get_array_span (tree type, tree decl) return NULL_TREE; } span = gfc_class_vtab_size_get (decl); + /* For unlimited polymorphic entities then _len component needs + to be multiplied with the size. */ + span = gfc_resize_class_size_with_len (NULL, decl, span); } else if (GFC_DECL_PTR_ARRAY_P (decl)) { @@ -439,13 +442,31 @@ get_array_span (tree type, tree decl) } +tree +gfc_build_spanned_array_ref (tree base, tree offset, tree span) +{ + tree type; + tree tmp; + type = TREE_TYPE (TREE_TYPE (base)); + offset = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, + offset, span); + tmp = gfc_build_addr_expr (pvoid_type_node, base); + tmp = fold_build_pointer_plus_loc (input_location, tmp, offset); + tmp = fold_convert (build_pointer_type (type), tmp); + if ((TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != ARRAY_TYPE) + || !TYPE_STRING_FLAG (type)) + tmp = build_fold_indirect_ref_loc (input_location, tmp); + return tmp; +} + + /* Build an ARRAY_REF with its natural type. */ tree gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr) { tree type = TREE_TYPE (base); - tree tmp; tree span = NULL_TREE; if (GFC_ARRAY_TYPE_P (type) && GFC_TYPE_ARRAY_RANK (type) == 0) @@ -488,18 +509,7 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr) /* If a non-null span has been generated reference the element with pointer arithmetic. */ if (span != NULL_TREE) - { - offset = fold_build2_loc (input_location, MULT_EXPR, - gfc_array_index_type, - offset, span); - tmp = gfc_build_addr_expr (pvoid_type_node, base); - tmp = fold_build_pointer_plus_loc (input_location, tmp, offset); - tmp = fold_convert (build_pointer_type (type), tmp); - if ((TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != ARRAY_TYPE) - || !TYPE_STRING_FLAG (type)) - tmp = build_fold_indirect_ref_loc (input_location, tmp); - return tmp; - } + return gfc_build_spanned_array_ref (base, offset, span); /* Otherwise use a straightforward array reference. */ else return build4_loc (input_location, ARRAY_REF, type, base, offset, diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 44cbfb6..8c6f82f 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -424,7 +424,8 @@ tree gfc_class_vptr_get (tree); tree gfc_class_len_get (tree); tree gfc_class_len_or_zero_get (tree); tree gfc_resize_class_size_with_len (stmtblock_t *, tree, tree); -gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *, bool is_mold = false); +gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *, bool is_mold = false, + gfc_typespec **ts = NULL); /* Get an accessor to the class' vtab's * field, when a class handle is available. */ tree gfc_class_vtab_hash_get (tree); @@ -622,6 +623,9 @@ tree gfc_build_addr_expr (tree, tree); /* Build an ARRAY_REF. */ tree gfc_build_array_ref (tree, tree, tree, tree vptr = NULL_TREE); +/* Build an array ref using pointer arithmetic. */ +tree gfc_build_spanned_array_ref (tree base, tree offset, tree span); + /* Creates a label. Decl is artificial if label_id == NULL_TREE. */ tree gfc_build_label_decl (tree); -- cgit v1.1 From 39d23b7960e4efb11bbe1eff056ae9da0884c539 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 15 Apr 2021 10:45:09 +0200 Subject: aarch64: Fix several *_ashl3 related regressions [PR100056] Before combiner added 2 to 2 combinations, the following testcase functions have been all compiled into 2 instructions, zero/sign extensions or and followed by orr with lsl, e.g. for the first function Trying 7 -> 8: 7: r96:SI=r94:SI<<0xb 8: r95:SI=r96:SI|r94:SI REG_DEAD r96:SI REG_DEAD r94:SI Successfully matched this instruction: (set (reg:SI 95) (ior:SI (ashift:SI (reg/v:SI 94 [ i ]) (const_int 11 [0xb])) (reg/v:SI 94 [ i ]))) is the important successful try_combine and so we end up with and w0, w0, 255 orr w0, w0, w0, lsl 11 in the body. With 2 to 2 combination, before that can trigger, another successful combination: Trying 2 -> 7: 2: r94:SI=zero_extend(x0:QI) REG_DEAD x0:QI 7: r96:SI=r94:SI<<0xb is replaced with: (set (reg/v:SI 94 [ i ]) (zero_extend:SI (reg:QI 0 x0 [ i ]))) and (set (reg:SI 96) (and:SI (ashift:SI (reg:SI 0 x0 [ i ]) (const_int 11 [0xb])) (const_int 522240 [0x7f800]))) and in the end results in 3 instructions in the body: and w1, w0, 255 ubfiz w0, w0, 11, 8 orr w0, w0, w1 The following combine splitters help undo that when combiner tries to combine 3 instructions - the zero/sign extend or and, the other insn from the 2 to 2 combination ([us]bfiz) and the logical op, the CPUs don't have an insn to do everything in one op, but we can split it back into the zero/sign extend or and followed by logical with lsl. 2021-04-15 Jakub Jelinek PR target/100056 * config/aarch64/aarch64.md (*_3): Add combine splitters for *_ashl3 with ZERO_EXTEND, SIGN_EXTEND or AND. * gcc.target/aarch64/pr100056.c: New test. --- gcc/config/aarch64/aarch64.md | 53 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/pr100056.c | 58 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr100056.c (limited to 'gcc') diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 9a7ed78..962640b 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4431,6 +4431,59 @@ [(set_attr "type" "logic_shift_imm")] ) +(define_split + [(set (match_operand:GPI 0 "register_operand") + (LOGICAL:GPI + (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand") + (match_operand:QI 2 "aarch64_shift_imm_")) + (match_operand:GPI 3 "const_int_operand")) + (zero_extend:GPI (match_operand 4 "register_operand"))))] + "can_create_pseudo_p () + && ((paradoxical_subreg_p (operands[1]) + && rtx_equal_p (SUBREG_REG (operands[1]), operands[4])) + || (REG_P (operands[1]) + && REG_P (operands[4]) + && REGNO (operands[1]) == REGNO (operands[4]))) + && (trunc_int_for_mode (GET_MODE_MASK (GET_MODE (operands[4])) + << INTVAL (operands[2]), mode) + == INTVAL (operands[3]))" + [(set (match_dup 5) (zero_extend:GPI (match_dup 4))) + (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 5) (match_dup 2)) + (match_dup 5)))] + "operands[5] = gen_reg_rtx (mode);" +) + +(define_split + [(set (match_operand:GPI 0 "register_operand") + (LOGICAL:GPI + (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand") + (match_operand:QI 2 "aarch64_shift_imm_")) + (match_operand:GPI 4 "const_int_operand")) + (and:GPI (match_dup 1) (match_operand:GPI 3 "const_int_operand"))))] + "can_create_pseudo_p () + && pow2_or_zerop (UINTVAL (operands[3]) + 1) + && (trunc_int_for_mode (UINTVAL (operands[3]) + << INTVAL (operands[2]), mode) + == INTVAL (operands[4]))" + [(set (match_dup 5) (and:GPI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 5) (match_dup 2)) + (match_dup 5)))] + "operands[5] = gen_reg_rtx (mode);" +) + +(define_split + [(set (match_operand:GPI 0 "register_operand") + (LOGICAL:GPI + (ashift:GPI (sign_extend:GPI (match_operand 1 "register_operand")) + (match_operand:QI 2 "aarch64_shift_imm_")) + (sign_extend:GPI (match_dup 1))))] + "can_create_pseudo_p ()" + [(set (match_dup 3) (sign_extend:GPI (match_dup 1))) + (set (match_dup 0) (LOGICAL:GPI (ashift:GPI (match_dup 3) (match_dup 2)) + (match_dup 3)))] + "operands[3] = gen_reg_rtx (mode);" +) + (define_insn "*_rol3" [(set (match_operand:GPI 0 "register_operand" "=r") (LOGICAL:GPI (rotate:GPI diff --git a/gcc/testsuite/gcc.target/aarch64/pr100056.c b/gcc/testsuite/gcc.target/aarch64/pr100056.c new file mode 100644 index 0000000..0b77824 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr100056.c @@ -0,0 +1,58 @@ +/* PR target/100056 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not {\t[us]bfiz\tw[0-9]+, w[0-9]+, 11} } } */ + +int +or_shift_u8 (unsigned char i) +{ + return i | (i << 11); +} + +int +or_shift_u3a (unsigned i) +{ + i &= 7; + return i | (i << 11); +} + +int +or_shift_u3b (unsigned i) +{ + i = (i << 29) >> 29; + return i | (i << 11); +} + +int +or_shift_s16 (signed short i) +{ + return i | (i << 11); +} + +int +or_shift_s8 (signed char i) +{ + return i | (i << 11); +} + +int +or_shift_s13 (int i) +{ + i = (i << 19) >> 19; + return i | (i << 11); +} + +int +or_shift_s3 (int i) +{ + i = (i << 29) >> 29; + return i | (i << 11); +} + +int +or_shift_u8_asm (unsigned char x) +{ + unsigned char i = x; + asm volatile ("" : "+r" (i)); + return i | (i << 11); +} -- cgit v1.1 From b5f644a98b3f3543d3a8d2dfea7785c22879013f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 15 Apr 2021 11:40:40 +0200 Subject: Fix handling of clones in lto_wpa_write_files [PR98599] 2021-04-15 Jan Hubicka PR lto/98599 * lto.c (lto_wpa_write_files): Fix handling of clones. --- gcc/lto/lto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc') diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index ceb61bb..5903f75 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -306,7 +306,7 @@ lto_wpa_write_files (void) cgraph_node *node; /* Do body modifications needed for streaming before we fork out worker processes. */ - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) + FOR_EACH_FUNCTION (node) if (!node->clone_of && gimple_has_body_p (node->decl)) lto_prepare_function_for_streaming (node); -- cgit v1.1 From a3317f7b3c02907a122f89879e5b6e90c386e64d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 15 Apr 2021 11:37:38 +0100 Subject: c: Don't drop vector attributes that affect type identity [PR98852] types are distinct from GNU vector types in at least their mangling. However, there used to be nothing explicit in the VECTOR_TYPE itself to indicate the difference: we simply treated them as distinct TYPE_MAIN_VARIANTs. This caused problems like the ones reported in PR95726. The fix for that PR was to add type attributes to the types, in order to maintain the distinction between them and GNU vectors. However, this in turn caused PR98852, where c_common_type would unconditionally drop the attributes on the source types. This meant that: vector + vector had a GNU vector type rather than an vector type. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96377#c2 for Jakub's analysis of the history of this c_common_type code. TBH I'm not sure which case the build_type_attribute_variant code is handling, but I think we should at least avoid dropping attributes that affect type identity. I've tried to audit the C and target-specific attributes to look for other types that might be affected by this, but I couldn't see any. We are only dealing with: gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE || code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE || code1 == INTEGER_TYPE); which excludes most affects_type_identity attributes. The closest was s390_vector_bool, but the handler for that attribute changes the type node and drops the attribute itself (*no_add_attrs = true). I put the main list handling into a separate function (remove_attributes_matching) because a later patch will need it for something else. gcc/ PR c/98852 * attribs.h (affects_type_identity_attributes): Declare. * attribs.c (remove_attributes_matching): New function. (affects_type_identity_attributes): Likewise. gcc/c/ PR c/98852 * c-typeck.c (c_common_type): Do not drop attributes that affect type identity. gcc/testsuite/ PR c/98852 * gcc.target/aarch64/advsimd-intrinsics/pr98852.c: New test. --- gcc/attribs.c | 54 +++++++++ gcc/attribs.h | 2 + gcc/c/c-typeck.c | 10 +- .../aarch64/advsimd-intrinsics/pr98852.c | 129 +++++++++++++++++++++ 4 files changed, 193 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/pr98852.c (limited to 'gcc') diff --git a/gcc/attribs.c b/gcc/attribs.c index 16c6b12..2fb2954 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -1366,6 +1366,60 @@ comp_type_attributes (const_tree type1, const_tree type2) return targetm.comp_type_attributes (type1, type2); } +/* PREDICATE acts as a function of type: + + (const_tree attr, const attribute_spec *as) -> bool + + where ATTR is an attribute and AS is its possibly-null specification. + Return a list of every attribute in attribute list ATTRS for which + PREDICATE is true. Return ATTRS itself if PREDICATE returns true + for every attribute. */ + +template +tree +remove_attributes_matching (tree attrs, Predicate predicate) +{ + tree new_attrs = NULL_TREE; + tree *ptr = &new_attrs; + const_tree start = attrs; + for (const_tree attr = attrs; attr; attr = TREE_CHAIN (attr)) + { + tree name = get_attribute_name (attr); + const attribute_spec *as = lookup_attribute_spec (name); + const_tree end; + if (!predicate (attr, as)) + end = attr; + else if (start == attrs) + continue; + else + end = TREE_CHAIN (attr); + + for (; start != end; start = TREE_CHAIN (start)) + { + *ptr = tree_cons (TREE_PURPOSE (start), + TREE_VALUE (start), NULL_TREE); + TREE_CHAIN (*ptr) = NULL_TREE; + ptr = &TREE_CHAIN (*ptr); + } + start = TREE_CHAIN (attr); + } + gcc_assert (!start || start == attrs); + return start ? attrs : new_attrs; +} + +/* If VALUE is true, return the subset of ATTRS that affect type identity, + otherwise return the subset of ATTRS that don't affect type identity. */ + +tree +affects_type_identity_attributes (tree attrs, bool value) +{ + auto predicate = [value](const_tree, const attribute_spec *as) -> bool + { + return bool (as && as->affects_type_identity) == value; + }; + return remove_attributes_matching (attrs, predicate); +} + /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. diff --git a/gcc/attribs.h b/gcc/attribs.h index 898e73d..eadb1d0 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -65,6 +65,8 @@ extern bool attribute_value_equal (const_tree, const_tree); warning to be generated). */ extern int comp_type_attributes (const_tree, const_tree); +extern tree affects_type_identity_attributes (tree, bool = true); + /* Default versions of target-overridable functions. */ extern tree merge_decl_attributes (tree, tree); extern tree merge_type_attributes (tree, tree); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 21eab00..51a62c8 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -740,10 +740,16 @@ c_common_type (tree t1, tree t2) t2 = TYPE_MAIN_VARIANT (t2); if (TYPE_ATTRIBUTES (t1) != NULL_TREE) - t1 = build_type_attribute_variant (t1, NULL_TREE); + { + tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t1)); + t1 = build_type_attribute_variant (t1, attrs); + } if (TYPE_ATTRIBUTES (t2) != NULL_TREE) - t2 = build_type_attribute_variant (t2, NULL_TREE); + { + tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t2)); + t2 = build_type_attribute_variant (t2, attrs); + } /* Save time if the two types are the same. */ diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/pr98852.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/pr98852.c new file mode 100644 index 0000000..31e51b0d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/pr98852.c @@ -0,0 +1,129 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c99" } */ + +#include + +typedef __typeof(((int32x4_t *) 0)[0][0]) int32_elt; +typedef __typeof(((uint32x4_t *) 0)[0][0]) uint32_elt; + +typedef int32_elt gnu_int32x4_t __attribute__((vector_size(16))); +typedef uint32_elt gnu_uint32x4_t __attribute__((vector_size(16))); + +#define X_gnu_int32x4_t 1 +#define X_gnu_uint32x4_t 2 +#define X_int32x4_t 3 +#define X_uint32x4_t 4 + +#define CHECK(T) T: X_##T + +#define CHECK_TYPE(EXPR, TYPE) \ + do { \ + int x[_Generic (EXPR, \ + CHECK (gnu_int32x4_t), \ + CHECK (gnu_uint32x4_t), \ + CHECK (int32x4_t), \ + CHECK (uint32x4_t), \ + default : 0) == X_##TYPE ? 1 : -1]; \ + } while (0) + +void +f (gnu_int32x4_t sg, gnu_uint32x4_t ug, int32x4_t sn, uint32x4_t un, int c) +{ + CHECK_TYPE (sg, gnu_int32x4_t); + CHECK_TYPE (ug, gnu_uint32x4_t); + CHECK_TYPE (sn, int32x4_t); + CHECK_TYPE (un, uint32x4_t); + + CHECK_TYPE (sg + 1, gnu_int32x4_t); + CHECK_TYPE (ug + 1, gnu_uint32x4_t); + CHECK_TYPE (sn + 1, int32x4_t); + CHECK_TYPE (un + 1, uint32x4_t); + + CHECK_TYPE (1 + sg, gnu_int32x4_t); + CHECK_TYPE (1 + ug, gnu_uint32x4_t); + CHECK_TYPE (1 + sn, int32x4_t); + CHECK_TYPE (1 + un, uint32x4_t); + + CHECK_TYPE (sg + sg, gnu_int32x4_t); + CHECK_TYPE (ug + ug, gnu_uint32x4_t); + CHECK_TYPE (sn + sn, int32x4_t); + CHECK_TYPE (un + un, uint32x4_t); + + /* Traditional behavior for mixed signs is to pick the signedness of the + first operand. We don't have any Arm-specific reason for preferring that + behavior, but including the tests helps to demonstrate the points in the + comments below. */ + CHECK_TYPE (sg + ug, gnu_int32x4_t); + CHECK_TYPE (ug + sg, gnu_uint32x4_t); + CHECK_TYPE (sn + un, int32x4_t); + CHECK_TYPE (un + sn, uint32x4_t); + + /* Nothing specifies the type of mixed GNU and arm_neon.h operations, but: + + - it would be surprising if sg + un had a different signedness from + sg + ug + + - it would also be mildly surprising if sg + un had a different type from + both of its operands + + So in cases where the operands differ in both signedness and ABI, it seems + more consistent to ignore the ABI difference and apply the usual rules for + differences in sign. */ + CHECK_TYPE (sg + un, gnu_int32x4_t); + CHECK_TYPE (ug + sn, gnu_uint32x4_t); + CHECK_TYPE (sn + ug, int32x4_t); + CHECK_TYPE (un + sg, uint32x4_t); + + /* And if the first vector wins when operands differ in both signedness + and ABI, it seems more consistent to do the same if the operands differ + only in ABI. */ + CHECK_TYPE (sg + sn, gnu_int32x4_t); + CHECK_TYPE (ug + un, gnu_uint32x4_t); + CHECK_TYPE (sn + sg, int32x4_t); + CHECK_TYPE (un + ug, uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn, int32x4_t); + CHECK_TYPE (c ? un + un : un, uint32x4_t); + + CHECK_TYPE (c ? sg + 1 : sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + 1 : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + 1 : sn, int32x4_t); + CHECK_TYPE (c ? un + 1 : un, uint32x4_t); + + CHECK_TYPE (c ? 1 + sg : sg, gnu_int32x4_t); + CHECK_TYPE (c ? 1 + ug : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? 1 + sn : sn, int32x4_t); + CHECK_TYPE (c ? 1 + un : un, uint32x4_t); + + CHECK_TYPE (c ? sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? un : un + un, uint32x4_t); + + CHECK_TYPE (c ? sg : sg + 1, gnu_int32x4_t); + CHECK_TYPE (c ? ug : ug + 1, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : sn + 1, int32x4_t); + CHECK_TYPE (c ? un : un + 1, uint32x4_t); + + CHECK_TYPE (c ? sg : 1 + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug : 1 + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : 1 + sn, int32x4_t); + CHECK_TYPE (c ? un : 1 + un, uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? un + un : un + un, uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg + 1, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug + 1, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn + 1, int32x4_t); + CHECK_TYPE (c ? un + un : un + 1, uint32x4_t); + + CHECK_TYPE (c ? 1 + sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? 1 + ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? 1 + sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? 1 + un : un + un, uint32x4_t); +} -- cgit v1.1 From 1696fc1ea01d5c9dce96b5d3122921aab9308f59 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 15 Apr 2021 11:37:39 +0100 Subject: c++: Tweak merging of vector attributes that affect type identity [PR98852] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit types are distinct from GNU vector types in at least their mangling. However, there used to be nothing explicit in the VECTOR_TYPE itself to indicate the difference: we simply treated them as distinct TYPE_MAIN_VARIANTs. This caused problems like the ones reported in PR95726. The fix for that PR was to add type attributes to the types, in order to maintain the distinction between them and GNU vectors. However, this in turn caused PR98852, where cp_common_type would merge the type attributes from the two source types and attach the result to the common type. For example: unsigned vector with no attribute + signed vector with attribute X would get converted to: unsigned vector with attribute X That isn't what we want in this case, since X describes the mangling of the original type. But even if we dropped the mangling from X and worked it out from context, we would still have a situation in which the common type was provably distinct from both of the source types: it would take its -ness from one side and its signedness from the other. I guess there are other cases where the common type doesn't match either side, but I'm not sure it's the obvious behaviour here. It's also different from GCC 10.1 and earlier, where the unsigned vector “won” in its original form. This patch instead merges only the attributes that don't affect type identity. For now I've restricted it to vector types, since we're so close to GCC 11, but it might make sense to use this elsewhere. I've tried to audit the C and target-specific attributes to look for other types that might be affected by this, but I couldn't see any. The closest was s390_vector_bool, but the handler for that attribute changes the type node and drops the attribute itself (*no_add_attrs = true). gcc/ PR c++/98852 * attribs.h (restrict_type_identity_attributes_to): Declare. * attribs.c (restrict_type_identity_attributes_to): New function. gcc/cp/ PR c++/98852 * typeck.c (merge_type_attributes_from): New function. (cp_common_type): Use it for vector types. --- gcc/attribs.c | 23 +++++ gcc/attribs.h | 1 + gcc/cp/typeck.c | 15 ++- .../advsimd-intrinsics/advsimd-intrinsics.exp | 72 ++++++++++++++ .../aarch64/advsimd-intrinsics/pr98852.C | 110 +++++++++++++++++++++ 5 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/advsimd-intrinsics.exp create mode 100644 gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/pr98852.C (limited to 'gcc') diff --git a/gcc/attribs.c b/gcc/attribs.c index 2fb2954..3ffa1b6 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -1420,6 +1420,29 @@ affects_type_identity_attributes (tree attrs, bool value) return remove_attributes_matching (attrs, predicate); } +/* Remove attributes that affect type identity from ATTRS unless the + same attributes occur in OK_ATTRS. */ + +tree +restrict_type_identity_attributes_to (tree attrs, tree ok_attrs) +{ + auto predicate = [ok_attrs](const_tree attr, + const attribute_spec *as) -> bool + { + if (!as || !as->affects_type_identity) + return true; + + for (tree ok_attr = lookup_attribute (as->name, ok_attrs); + ok_attr; + ok_attr = lookup_attribute (as->name, TREE_CHAIN (ok_attr))) + if (simple_cst_equal (TREE_VALUE (ok_attr), TREE_VALUE (attr)) == 1) + return true; + + return false; + }; + return remove_attributes_matching (attrs, predicate); +} + /* Return a type like TTYPE except that its TYPE_ATTRIBUTE is ATTRIBUTE. diff --git a/gcc/attribs.h b/gcc/attribs.h index eadb1d0..df78eb1 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -66,6 +66,7 @@ extern bool attribute_value_equal (const_tree, const_tree); extern int comp_type_attributes (const_tree, const_tree); extern tree affects_type_identity_attributes (tree, bool = true); +extern tree restrict_type_identity_attributes_to (tree, tree); /* Default versions of target-overridable functions. */ extern tree merge_decl_attributes (tree, tree); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 11dee7d..50d0f1e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -261,6 +261,17 @@ original_type (tree t) return cp_build_qualified_type (t, quals); } +/* Merge the attributes of type OTHER_TYPE into the attributes of type TYPE + and return a variant of TYPE with the merged attributes. */ + +static tree +merge_type_attributes_from (tree type, tree other_type) +{ + tree attrs = targetm.merge_type_attributes (type, other_type); + attrs = restrict_type_identity_attributes_to (attrs, TYPE_ATTRIBUTES (type)); + return cp_build_type_attribute_variant (type, attrs); +} + /* Return the common type for two arithmetic types T1 and T2 under the usual arithmetic conversions. The default conversions have already been applied, and enumerated types converted to their compatible @@ -320,9 +331,9 @@ cp_common_type (tree t1, tree t2) /* When we get here we should have two vectors of the same size. Just prefer the unsigned one if present. */ if (TYPE_UNSIGNED (t1)) - return build_type_attribute_variant (t1, attributes); + return merge_type_attributes_from (t1, t2); else - return build_type_attribute_variant (t2, attributes); + return merge_type_attributes_from (t2, t1); } /* If only one is real, use it as the result. */ diff --git a/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/advsimd-intrinsics.exp b/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/advsimd-intrinsics.exp new file mode 100644 index 0000000..268e221 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/advsimd-intrinsics.exp @@ -0,0 +1,72 @@ +# Copyright (C) 2014-2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't an ARM or AArch64 target. +if {![istarget arm*-*-*] + && ![istarget aarch64*-*-*]} then { + return +} + +# Load support procs. +load_lib g++-dg.exp + +# Initialize `dg'. +load_lib c-torture.exp + +dg-init + +# The default action for a test is 'run'. Save current default. +global dg-do-what-default +set save-dg-do-what-default ${dg-do-what-default} + +# For ARM, make sure that we have a target compatible with NEON, and do +# not attempt to run execution tests if the hardware doesn't support it. +if {[istarget arm*-*-*]} then { + if {![check_effective_target_arm_neon_ok]} then { + return + } + if {![is-effective-target arm_neon_hw]} then { + set dg-do-what-default compile + } else { + set dg-do-what-default run + } +} else { + set dg-do-what-default run +} + +torture-init +set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS + +# Make sure Neon flags are provided, if necessary. Use fp16 if we can. +# Use fp16 arithmetic operations if the hardware supports it. +if {[check_effective_target_arm_v8_2a_fp16_neon_hw]} then { + set additional_flags [add_options_for_arm_v8_2a_fp16_neon ""] +} elseif {[check_effective_target_arm_neon_fp16_ok]} then { + set additional_flags [add_options_for_arm_neon_fp16 ""] +} else { + set additional_flags [add_options_for_arm_neon ""] +} + +# Main loop. +gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \ + "" ${additional_flags} + +# All done. +set dg-do-what-default ${save-dg-do-what-default} +torture-finish +dg-finish diff --git a/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/pr98852.C b/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/pr98852.C new file mode 100644 index 0000000..0cb5c89 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/advsimd-intrinsics/pr98852.C @@ -0,0 +1,110 @@ +/* { dg-do compile } */ + +#include + +using int32_elt = __typeof(((int32x4_t *) nullptr)[0][0]); +using uint32_elt = __typeof(((uint32x4_t *) nullptr)[0][0]); + +typedef int32_elt gnu_int32x4_t __attribute__((vector_size(16))); +typedef uint32_elt gnu_uint32x4_t __attribute__((vector_size(16))); + +template struct id; +template<> struct id { static const int value = 1; }; +template<> struct id { static const int value = 2; }; +template<> struct id { static const int value = 3; }; +template<> struct id { static const int value = 4; }; + +#define CHECK_TYPE(EXPR, TYPE) \ + static_assert(id::value == id::value, "foo") + +void +f (gnu_int32x4_t sg, gnu_uint32x4_t ug, int32x4_t sn, uint32x4_t un, bool c) +{ + CHECK_TYPE (sg, gnu_int32x4_t); + CHECK_TYPE (ug, gnu_uint32x4_t); + CHECK_TYPE (sn, int32x4_t); + CHECK_TYPE (un, uint32x4_t); + + CHECK_TYPE (sg + 1, gnu_int32x4_t); + CHECK_TYPE (ug + 1, gnu_uint32x4_t); + CHECK_TYPE (sn + 1, int32x4_t); + CHECK_TYPE (un + 1, uint32x4_t); + + CHECK_TYPE (1 + sg, gnu_int32x4_t); + CHECK_TYPE (1 + ug, gnu_uint32x4_t); + CHECK_TYPE (1 + sn, int32x4_t); + CHECK_TYPE (1 + un, uint32x4_t); + + CHECK_TYPE (sg + sg, gnu_int32x4_t); + CHECK_TYPE (ug + ug, gnu_uint32x4_t); + CHECK_TYPE (sn + sn, int32x4_t); + CHECK_TYPE (un + un, uint32x4_t); + + // In C++, unlike C, the behavior is to prefer unsigned types over + // signed types. + CHECK_TYPE (sg + ug, gnu_uint32x4_t); + CHECK_TYPE (ug + sg, gnu_uint32x4_t); + CHECK_TYPE (sn + un, uint32x4_t); + CHECK_TYPE (un + sn, uint32x4_t); + + // That being the case, it seems more consistent to do the same thing + // for mixed GNU and arm_neon.h operations. + CHECK_TYPE (sg + un, uint32x4_t); + CHECK_TYPE (un + sg, uint32x4_t); + CHECK_TYPE (sn + ug, gnu_uint32x4_t); + CHECK_TYPE (ug + sn, gnu_uint32x4_t); + + // If the types have the same signedness, the traditional behavior is + // to pick the first type if it is unsigned and the second type otherwise. + // This is not necessarily sensible, but dates back to at least GCC 9.1. + // We could probably change it. + CHECK_TYPE (sg + sn, int32x4_t); + CHECK_TYPE (sn + sg, gnu_int32x4_t); + CHECK_TYPE (un + ug, uint32x4_t); + CHECK_TYPE (ug + un, gnu_uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn, int32x4_t); + CHECK_TYPE (c ? un + un : un, uint32x4_t); + + CHECK_TYPE (c ? sg + 1 : sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + 1 : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + 1 : sn, int32x4_t); + CHECK_TYPE (c ? un + 1 : un, uint32x4_t); + + CHECK_TYPE (c ? 1 + sg : sg, gnu_int32x4_t); + CHECK_TYPE (c ? 1 + ug : ug, gnu_uint32x4_t); + CHECK_TYPE (c ? 1 + sn : sn, int32x4_t); + CHECK_TYPE (c ? 1 + un : un, uint32x4_t); + + CHECK_TYPE (c ? sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? un : un + un, uint32x4_t); + + CHECK_TYPE (c ? sg : sg + 1, gnu_int32x4_t); + CHECK_TYPE (c ? ug : ug + 1, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : sn + 1, int32x4_t); + CHECK_TYPE (c ? un : un + 1, uint32x4_t); + + CHECK_TYPE (c ? sg : 1 + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug : 1 + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn : 1 + sn, int32x4_t); + CHECK_TYPE (c ? un : 1 + un, uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? un + un : un + un, uint32x4_t); + + CHECK_TYPE (c ? sg + sg : sg + 1, gnu_int32x4_t); + CHECK_TYPE (c ? ug + ug : ug + 1, gnu_uint32x4_t); + CHECK_TYPE (c ? sn + sn : sn + 1, int32x4_t); + CHECK_TYPE (c ? un + un : un + 1, uint32x4_t); + + CHECK_TYPE (c ? 1 + sg : sg + sg, gnu_int32x4_t); + CHECK_TYPE (c ? 1 + ug : ug + ug, gnu_uint32x4_t); + CHECK_TYPE (c ? 1 + sn : sn + sn, int32x4_t); + CHECK_TYPE (c ? 1 + un : un + un, uint32x4_t); +} -- cgit v1.1 From ddcf111d0554c0cd4f80c1ce033af0304f8ff024 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Thu, 15 Apr 2021 12:57:00 +0200 Subject: Deprecate gimple-builder.h API This adds a deprecation note to the undocumented gimple-builder.h API only used by asan and sancov. 2021-04-15 Richard Biener * gimple-builder.h: Add deprecation note. --- gcc/gimple-builder.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gcc') diff --git a/gcc/gimple-builder.h b/gcc/gimple-builder.h index 61cf08c..ae273ce 100644 --- a/gcc/gimple-builder.h +++ b/gcc/gimple-builder.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_GIMPLE_BUILDER_H #define GCC_GIMPLE_BUILDER_H +/* ??? This API is legacy and should not be used in new code. */ + gassign *build_assign (enum tree_code, tree, int, tree lhs = NULL_TREE); gassign *build_assign (enum tree_code, gimple *, int, tree lhs = NULL_TREE); gassign *build_assign (enum tree_code, tree, tree, tree lhs = NULL_TREE); -- cgit v1.1 From 4d1fa72894e3fbc5f331d2e8984e990307396124 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 15 Apr 2021 14:08:03 +0200 Subject: testsuite: enable pr86058.c also on i?86-*-* [PR100073] The test also works with -m32 or -mx32 the same as it does for -m64, therefore it should be enabled for i?86-*-* x86_64-*-* targets, x86_64-*-* alone is never right. 2021-04-15 Jakub Jelinek PR testsuite/100073 * gcc.dg/pr86058.c: Enable also on i?86-*-*. --- gcc/testsuite/gcc.dg/pr86058.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc') diff --git a/gcc/testsuite/gcc.dg/pr86058.c b/gcc/testsuite/gcc.dg/pr86058.c index e39b720..89628c9 100644 --- a/gcc/testsuite/gcc.dg/pr86058.c +++ b/gcc/testsuite/gcc.dg/pr86058.c @@ -1,7 +1,7 @@ /* PR middle-end/86058 - TARGET_MEM_REF causing incorrect message for -Wmaybe-uninitialized warning - The test fails on a number of non-x86_64 targets due to pr100073. - { dg-do compile { target x86_64-*-* } } + The test fails on a number of non-x86 targets due to pr100073. + { dg-do compile { target i?86-*-* x86_64-*-* } } { dg-options "-O2 -Wuninitialized -Wmaybe-uninitialized" } */ extern void foo (int *); -- cgit v1.1 From ca7d451d985b31a0b593b50115971e70ae0767da Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 15 Apr 2021 14:50:04 +0200 Subject: docs: remove itemx for a param gcc/ChangeLog: * doc/invoke.texi: Other params don't use it, remove it. --- gcc/doc/invoke.texi | 1 - 1 file changed, 1 deletion(-) (limited to 'gcc') diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1755124..096cebc 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -13049,7 +13049,6 @@ also use other heuristics to decide whether if-conversion is likely to be profitable. @item max-rtl-if-conversion-predictable-cost -@itemx max-rtl-if-conversion-unpredictable-cost RTL if-conversion will try to remove conditional branches around a block and replace them with conditionally executed instructions. These parameters give the maximum permissible cost for the sequence that would be generated -- cgit v1.1