diff options
author | Martin Liska <mliska@suse.cz> | 2021-04-15 14:51:21 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-04-15 14:51:21 +0200 |
commit | e524607beb2e179c7b981eca37eefd1aee71b5b3 (patch) | |
tree | a51183dd802994df10dd7af7a05c6495fa02ed27 /gcc | |
parent | ecb7b9c41347dba4087efe3c87d195e70297594c (diff) | |
parent | ca7d451d985b31a0b593b50115971e70ae0767da (diff) | |
download | gcc-e524607beb2e179c7b981eca37eefd1aee71b5b3.zip gcc-e524607beb2e179c7b981eca37eefd1aee71b5b3.tar.gz gcc-e524607beb2e179c7b981eca37eefd1aee71b5b3.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
85 files changed, 1825 insertions, 267 deletions
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 <richard.sandiford@arm.com> + + 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 <richard.sandiford@arm.com> + + * 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 <vmakarov@redhat.com> + + 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 <richard.sandiford@arm.com> + + 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 <krebbel@linux.ibm.com> + + * 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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> + + * 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 <rguenther@suse.de> + + * 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 <rearnsha@arm.com> + + 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 <rguenther@suse.de> 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/attribs.c b/gcc/attribs.c index 16c6b12..3ffa1b6 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -1366,6 +1366,83 @@ 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<typename Predicate> +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); +} + +/* 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 898e73d..df78eb1 100644 --- a/gcc/attribs.h +++ b/gcc/attribs.h @@ -65,6 +65,9 @@ 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); +extern tree restrict_type_identity_attributes_to (tree, tree); + /* 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/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.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.<T>, VL<N> + MOV TRUE.<T>, #<foreground> + MOV FALSE.<T>, #<background> + SEL TARGET.<T>, PRED.<T>, TRUE.<T>, FALSE.<T> + + 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/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/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_<mode>")) + (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>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>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_<mode>")) + (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>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>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_<mode>")) + (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>mode);" +) + (define_insn "*<optab>_rol<mode>3" [(set (match_operand:GPI 0 "register_operand" "=r") (LOGICAL:GPI (rotate:GPI 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 b79be85..da5958c 100644 --- a/gcc/config/i386/i386-d.c +++ b/gcc/config/i386/i386-d.c @@ -44,3 +44,51 @@ ix86_d_target_versions (void) else 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 +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..7782cf11 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -264,6 +264,8 @@ 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 */ extern void i386_pe_unique_section (tree, int); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index fab1b3c..97700d7 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -802,8 +802,10 @@ 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_REGISTER_CPU_TARGET_INFO ix86_d_register_target_info +#define TARGET_D_HAS_STDCALL_CONVENTION ix86_d_has_stdcall_convention #ifndef CC1_SPEC #define CC1_SPEC "%(cc1_cpu) " 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-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-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.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/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/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 <jason@redhat.com> + + PR c++/100078 + PR c++/93085 + * pt.c (uses_outer_template_parms): Also look at default + template argument. + +2021-04-14 Jason Merrill <jason@redhat.com> + + 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 <ppalka@redhat.com> + + PR c++/83476 + PR c++/99885 + * pt.c (deducible_expression): Look through implicit + INDIRECT_REFs as well. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/99478 + * parser.c (cp_parser_lambda_expression): Reject lambda + in template parameter type. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/90674 + * decl.c (duplicate_decls): Don't propagate + DECL_INITIALIZED_IN_CLASS_P to a specialization. + +2021-04-14 Jason Merrill <jason@redhat.com> + + 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 <jason@redhat.com> PR c++/100032 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 59df794..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); @@ -21902,8 +21907,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/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/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. */ @@ -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/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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> + + 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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> + + * 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 <ibuclaw@gdcproject.org> * dmd/MERGE: Merge upstream dmd 0450061c8. 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/d-target.cc b/gcc/d/d-target.cc index a1dc2ee..be354d9 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -198,6 +198,8 @@ 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); } @@ -435,11 +437,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..aa6bf55 100644 --- a/gcc/d/d-target.def +++ b/gcc/d/d-target.def @@ -46,6 +46,26 @@ 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) + +/* 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, @@ -71,5 +91,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/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)) { 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; 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/invoke.texi b/gcc/doc/invoke.texi index 671db2d..23e155f 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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b272fa4..97c8eeb 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10808,6 +10808,20 @@ 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 + +@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 @@ -10828,6 +10842,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..e2d49ee 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7357,12 +7357,18 @@ 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_REGISTER_OS_TARGET_INFO + @hook TARGET_D_MINFO_SECTION @hook TARGET_D_MINFO_START_NAME @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 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 <mliska@suse.cz> + + * intrinsic.texi: The table has first column empty and it makes + trouble when processing makeinfo --xml output. + 2021-04-09 Tobias Burnus <tobias@codesourcery.com> PR fortran/99817 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); 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); @@ -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 62bcfc3..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: @@ -5797,10 +5802,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/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); 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) 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: @@ -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); @@ -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/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 <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/pr99929_1.c: New file. + * gcc.target/aarch64/sve/pr99929_2.c: Likewise. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/100078 + * g++.dg/template/dependent-tmpl2.C: New test. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/93314 + * g++.dg/parse/uneval1.C: New test. + +2021-04-14 Vladimir N. Makarov <vmakarov@redhat.com> + + PR rtl-optimization/100066 + * gcc.target/i386/pr100066.c: New. + +2021-04-14 Martin Sebor <msebor@redhat.com> + + * gcc.dg/pr86058.c: Limit to just x86_64. + +2021-04-14 Richard Sandiford <richard.sandiford@arm.com> + + PR target/99246 + * gcc.target/aarch64/sve/acle/general/pr99246.c: New test. + +2021-04-14 Andreas Krebbel <krebbel@linux.ibm.com> + + * 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 <ppalka@redhat.com> + + 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 <jason@redhat.com> + + PR c++/99478 + * g++.dg/cpp2a/lambda-uneval14.C: New test. + +2021-04-14 Jason Merrill <jason@redhat.com> + + PR c++/90674 + * g++.dg/debug/defaulted1.C: New test. + +2021-04-14 Jason Merrill <jason@redhat.com> + + 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 <msebor@redhat.com> PR tree-optimization/82800 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 <auto const& A> +struct Foo {}; + +template <auto const& A> +struct Bar { + constexpr auto foo() const -> Foo<A> { + return {}; + } +}; + +constexpr int a = 1; +constexpr Bar<a> bar; +Foo foo = bar.foo(); // <-- CTAD failure 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" } +} 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 <bool> struct enable_if; +template <typename Data> struct HashMapBucket { + template <typename T = Data> + static typename enable_if<T ::value>::type selectStructure() { + selectStructure(); + } +}; 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 <int& V> struct A {}; +template <int& V> void f(A<V>); +int main() { + A<n> a; + f(a); +} 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 +# <http://www.gnu.org/licenses/>. + +# 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 <arm_neon.h> + +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<typename T> struct id; +template<> struct id<gnu_int32x4_t> { static const int value = 1; }; +template<> struct id<gnu_uint32x4_t> { static const int value = 2; }; +template<> struct id<int32x4_t> { static const int value = 3; }; +template<> struct id<uint32x4_t> { static const int value = 4; }; + +#define CHECK_TYPE(EXPR, TYPE) \ + static_assert(id<decltype(EXPR)>::value == id<TYPE>::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); +} diff --git a/gcc/testsuite/gcc.dg/pr86058.c b/gcc/testsuite/gcc.dg/pr86058.c index 0b030b0..89628c9 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 targets due to pr100073. + { dg-do compile { target i?86-*-* 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); } 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|<retval> =) \[0-9]\[0-9a-fA-FxX]*;" 31 "optimized" } } */ #ifdef __SIZEOF_INT128__ typedef unsigned __int128 L; 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 <arm_neon.h> + +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); +} 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); +} 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 <arm_sve.h> +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; + } +} 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 <arm_sve.h> + +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} } } */ 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); +} 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 <vecintrin.h> + +__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 <vecintrin.h> + +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 } } */ 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)) |