diff options
author | Martin Liska <mliska@suse.cz> | 2021-08-26 11:23:40 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-08-26 11:23:40 +0200 |
commit | e88d1c83cdd1d349dc34f402e92363ba9393ee46 (patch) | |
tree | 777a21dcb14b6ea3fcac49a569d0dd3a5d30e857 /gcc | |
parent | 7572f9cd10edd3bc1889a8f513dbf77b7f4e470d (diff) | |
parent | e370a2482d41fd382055695b9a0a638ce75e1038 (diff) | |
download | gcc-e88d1c83cdd1d349dc34f402e92363ba9393ee46.zip gcc-e88d1c83cdd1d349dc34f402e92363ba9393ee46.tar.gz gcc-e88d1c83cdd1d349dc34f402e92363ba9393ee46.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
101 files changed, 3614 insertions, 512 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0183764..fe8242b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,345 @@ +2021-08-25 Martin Sebor <msebor@redhat.com> + + * gimple-range-cache.cc (ssa_global_cache::dump): Avoid printing + range table header alone. + * gimple-range.cc (gimple_ranger::export_global_ranges): Same. + +2021-08-25 Jan Hubicka <hubicka@ucw.cz> + + * doc/invoke.texi: Document --param modref-max-adjustments. + * ipa-modref-tree.c (test_insert_search_collapse): Update. + (test_merge): Update. + * ipa-modref-tree.h (struct modref_access_node): Add adjustments; + (modref_access_node::operator==): Fix handling of access ranges. + (modref_access_node::contains): Constify parameter; handle also + mismatched parm offsets. + (modref_access_node::update): New function. + (modref_access_node::merge): New function. + (unspecified_modref_access_node): Update constructor. + (modref_ref_node::insert_access): Add record_adjustments parameter; + handle merging. + (modref_ref_node::try_merge_with): New private function. + (modref_tree::insert): New record_adjustments parameter. + (modref_tree::merge): New record_adjustments parameter. + (modref_tree::copy_from): Update. + * ipa-modref.c (dump_access): Dump adjustments field. + (get_access): Update constructor. + (record_access): Update call of insert. + (record_access_lto): Update call of insert. + (merge_call_side_effects): Add record_adjustments parameter. + (get_access_for_fnspec): Update. + (process_fnspec): Update. + (analyze_call): Update. + (analyze_function): Update. + (read_modref_records): Update. + (ipa_merge_modref_summary_after_inlining): Update. + (propagate_unknown_call): Update. + (modref_propagate_in_scc): Update. + * params.opt (param-max-modref-adjustments=): New. + +2021-08-25 Michael Meissner <meissner@linux.ibm.com> + + * config/rs6000/vsx.md (UNSPEC_XXSPLTIDP): Rename from + UNSPEC_XXSPLTID. + (xxspltiw_v4si): Use vecperm type attribute. + (xxspltiw_v4si_inst): Use vecperm type attribute. + (xxspltiw_v4sf_inst): Likewise. + (xxspltidp_v2df): Use vecperm type attribute. Use + UNSPEC_XXSPLTIDP instead of UNSPEC_XXSPLTID. + (xxspltidp_v2df_inst): Likewise. + (xxsplti32dx_v4si): Use vecperm type attribute. + (xxsplti32dx_v4si_inst): Likewise. + (xxsplti32dx_v4sf_inst): Likewise. + (xxblend_<mode>): Likewise. + (xxpermx): Likewise. + (xxpermx_inst): Likewise. + (xxeval): Likewise. + +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * coretypes.h (typedef diagnostic_input_charset_callback): Declare. + * diagnostic.c (diagnostic_initialize_input_context): New function. + * diagnostic.h (diagnostic_initialize_input_context): Declare. + * input.c (default_charset_callback): New function. + (file_cache::initialize_input_context): New function. + (file_cache_slot::create): Added ability to convert the input + according to the input context. + (file_cache::file_cache): Initialize the new input context. + (class file_cache_slot): Added new m_alloc_offset member. + (file_cache_slot::file_cache_slot): Initialize the new member. + (file_cache_slot::~file_cache_slot): Handle potentially offset buffer. + (file_cache_slot::maybe_grow): Likewise. + (file_cache_slot::needs_read_p): Handle NULL fp, which is now possible. + (file_cache_slot::get_next_line): Likewise. + * input.h (class file_cache): Added input context member. + +2021-08-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102046 + * tree-vect-slp.c (vect_build_slp_tree_2): Conservatively + update ->any_pattern when swapping operands. + +2021-08-25 Hongyu Wang <hongyu.wang@intel.com> + + PR target/101716 + * config/i386/i386.c (ix86_live_on_entry): Adjust comment. + (ix86_decompose_address): Remove retval check for ASHIFT, + allow non-canonical zero extend if AND mask covers ASHIFT + count. + (ix86_legitimate_address_p): Adjust condition for decompose. + (ix86_rtx_costs): Adjust cost for lea with non-canonical + zero-extend. + Co-Authored by: Uros Bizjak <ubizjak@gmail.com> + +2021-08-25 Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/101145 + * tree-ssa-loop-niter.c (number_of_iterations_until_wrap): + New function. + (number_of_iterations_lt): Invoke above function. + (adjust_cond_for_loop_until_wrap): + Merge to number_of_iterations_until_wrap. + (number_of_iterations_cond): Update invokes for + adjust_cond_for_loop_until_wrap and number_of_iterations_lt. + +2021-08-25 konglin1 <lingling.kong@intel.com> + + PR target/101471 + * config/i386/avx512dqintrin.h (_mm512_fpclass_ps_mask): Fix + macro define in O0. + (_mm512_mask_fpclass_ps_mask): Ditto. + +2021-08-25 Kewen Lin <linkw@linux.ibm.com> + + * config/rs6000/altivec.md (vec_unpacku_hi_v16qi): Remove. + (vec_unpacku_hi_v8hi): Likewise. + (vec_unpacku_lo_v16qi): Likewise. + (vec_unpacku_lo_v8hi): Likewise. + (vec_unpacku_hi_<VP_small_lc>): New define_expand. + (vec_unpacku_lo_<VP_small_lc>): Likewise. + +2021-08-24 David Edelsohn <dje.gcc@gmail.com> + + * config/rs6000/aix.h (SYSTEM_IMPLICIT_EXTERN_C): Delete. + * config/rs6000/aix71.h (SYSTEM_IMPLICIT_EXTERN_C): Define. + * config/rs6000/aix72.h (SYSTEM_IMPLICIT_EXTERN_C): Define. + * config/rs6000/aix73.h (TARGET_AIX_VERSION): Increase to 73. + +2021-08-24 Roger Sayle <roger@nextmovesoftware.com> + + PR middle-end/102031 + * simplify-rtx.c (simplify_truncation): When comparing precisions + use "subreg_prec" variable, not "subreg_mode". + +2021-08-24 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-builtin-new.def: Add power10 and power10-64 + stanzas. + +2021-08-24 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-call.c (rs6000_init_builtins): Initialize + various pointer type nodes. + * config/rs6000/rs6000.h (rs6000_builtin_type_index): Add enum + values for various pointer types. + (ptr_V16QI_type_node): New macro. + (ptr_V1TI_type_node): New macro. + (ptr_V2DI_type_node): New macro. + (ptr_V2DF_type_node): New macro. + (ptr_V4SI_type_node): New macro. + (ptr_V4SF_type_node): New macro. + (ptr_V8HI_type_node): New macro. + (ptr_unsigned_V16QI_type_node): New macro. + (ptr_unsigned_V1TI_type_node): New macro. + (ptr_unsigned_V8HI_type_node): New macro. + (ptr_unsigned_V4SI_type_node): New macro. + (ptr_unsigned_V2DI_type_node): New macro. + (ptr_bool_V16QI_type_node): New macro. + (ptr_bool_V8HI_type_node): New macro. + (ptr_bool_V4SI_type_node): New macro. + (ptr_bool_V2DI_type_node): New macro. + (ptr_bool_V1TI_type_node): New macro. + (ptr_pixel_type_node): New macro. + (ptr_intQI_type_node): New macro. + (ptr_uintQI_type_node): New macro. + (ptr_intHI_type_node): New macro. + (ptr_uintHI_type_node): New macro. + (ptr_intSI_type_node): New macro. + (ptr_uintSI_type_node): New macro. + (ptr_intDI_type_node): New macro. + (ptr_uintDI_type_node): New macro. + (ptr_intTI_type_node): New macro. + (ptr_uintTI_type_node): New macro. + (ptr_long_integer_type_node): New macro. + (ptr_long_unsigned_type_node): New macro. + (ptr_float_type_node): New macro. + (ptr_double_type_node): New macro. + (ptr_long_double_type_node): New macro. + (ptr_dfloat64_type_node): New macro. + (ptr_dfloat128_type_node): New macro. + (ptr_ieee128_type_node): New macro. + (ptr_ibm128_type_node): New macro. + (ptr_vector_pair_type_node): New macro. + (ptr_vector_quad_type_node): New macro. + (ptr_long_long_integer_type_node): New macro. + (ptr_long_long_unsigned_type_node): New macro. + +2021-08-24 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-builtin-new.def: Add power9-vector, power9, + and power9-64 stanzas. + +2021-08-24 Roger Sayle <roger@nextmovesoftware.com> + Tom de Vries <tdevries@suse.de> + + * config.gcc (nvptx-*-*): Define {c,c++}_target_objs. + * config/nvptx/nvptx-protos.h (nvptx_cpu_cpp_builtins): Prototype. + * config/nvptx/nvptx.h (TARGET_CPU_CPP_BUILTINS): Implement with + a call to the new nvptx_cpu_cpp_builtins function in nvptx-c.c. + * config/nvptx/t-nvptx (nvptx-c.o): New rule. + * config/nvptx/nvptx-c.c: New source file. + (nvptx_cpu_cpp_builtins): Move implementation here. + +2021-08-24 Martin Sebor <msebor@redhat.com> + + PR middle-end/101600 + PR middle-end/101977 + * gimple-ssa-warn-access.cc (maybe_warn_for_bound): Tighten up + the phrasing of a warning. + (check_access): Use the remaining size after subtracting any offset + rather than the whole object size. + * pointer-query.cc (access_ref::get_ref): Clear BASE0 flag if it's + clear for any nonnull PHI argument. + (compute_objsize): Clear argument. + +2021-08-24 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-builtin-new.def: Add power8-vector stanza. + +2021-08-24 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-builtin-new.def: Add power7 and power7-64 + stanzas. + +2021-08-24 Andrew MacLeod <amacleod@redhat.com> + + * value-relation.cc (rr_transitive_table): New. + (relation_transitive): New. + (value_relation::swap): Remove. + (value_relation::apply_transitive): New. + (relation_oracle::relation_oracle): Allocate a new tmp bitmap. + (relation_oracle::register_relation): Call register_transitives. + (relation_oracle::register_transitives): New. + * value-relation.h (relation_oracle): Add new temporary bitmap and + methods. + +2021-08-24 H.J. Lu <hjl.tools@gmail.com> + + PR target/102021 + * config/i386/i386-expand.c (ix86_expand_vector_move): Broadcast + from integer to a pseudo vector register. + +2021-08-24 Richard Biener <rguenther@suse.de> + + PR tree-optimization/100089 + * tree-vectorizer.h (vect_slp_bb): Rename to ... + (vect_slp_if_converted_bb): ... this and get the original + loop as new argument. + * tree-vectorizer.c (try_vectorize_loop_1): Revert previous fix, + pass original loop to vect_slp_if_converted_bb. + * tree-vect-slp.c (vect_bb_vectorization_profitable_p): + If orig_loop was passed scan the not vectorized stmts + for COND_EXPRs and force not profitable if found. + (vect_slp_region): Pass down all SLP instances to costing + if orig_loop was specified. + (vect_slp_bbs): Pass through orig_loop. + (vect_slp_bb): Rename to ... + (vect_slp_if_converted_bb): ... this and get the original + loop as new argument. + (vect_slp_function): Adjust. + +2021-08-24 Richard Earnshaw <rearnsha@arm.com> + + PR target/102035 + * config/arm/arm.md (attribute arch): Add fix_vlldm. + (arch_enabled): Use it. + * config/arm/vfp.md (lazy_store_multiple_insn): Add alternative to + use when erratum mitigation is needed. + +2021-08-24 Richard Earnshaw <rearnsha@arm.com> + + PR target/102035 + * config/arm/arm.opt (mfix-cmse-cve-2021-35465): New option. + * doc/invoke.texi (Arm Options): Document it. + * config/arm/arm-cpus.in (quirk_vlldm): New feature bit. + (ALL_QUIRKS): Add quirk_vlldm. + (cortex-m33): Add quirk_vlldm. + (cortex-m35p, cortex-m55): Likewise. + * config/arm/arm.c (arm_option_override): Enable fix_vlldm if + targetting an affected CPU and not explicitly controlled on + the command line. + +2021-08-24 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/vfp.md (lazy_store_multiple_insn): Rewrite as valid RTL. + (lazy_load_multiple_insn): Likewise. + +2021-08-24 liuhongt <hongtao.liu@intel.com> + + PR target/101989 + * config/i386/sse.md (<avx512>_vternlog<mode><sd_maskz_name>): + Enable avx512 embedded broadcast. + (*<avx512>_vternlog<mode>_all): Ditto. + (<avx512>_vternlog<mode>_mask): Ditto. + +2021-08-24 liuhongt <hongtao.liu@intel.com> + + PR target/101989 + * config/i386/i386.c (ix86_rtx_costs): Define cost for + UNSPEC_VTERNLOG. + * config/i386/i386.h (STRIP_UNARY): New macro. + * config/i386/predicates.md (reg_or_notreg_operand): New + predicate. + * config/i386/sse.md (*<avx512>_vternlog<mode>_all): New define_insn. + (*<avx512>_vternlog<mode>_1): New pre_reload + define_insn_and_split. + (*<avx512>_vternlog<mode>_2): Ditto. + (*<avx512>_vternlog<mode>_3): Ditto. + (any_logic1,any_logic2): New code iterator. + (logic_op): New code attribute. + (ternlogsuffix): Extend to VNxDF and VNxSF. + +2021-08-24 Richard Biener <rguenther@suse.de> + + * doc/invoke.texi (vect-inner-loop-cost-factor): Adjust. + * params.opt (--param vect-inner-loop-cost-factor): Adjust + maximum value. + * tree-vect-loop.c (vect_analyze_loop_form): Initialize + inner_loop_cost_factor to the minimum of the estimated number + of iterations of the inner loop and vect-inner-loop-cost-factor. + +2021-08-24 Roger Sayle <roger@nextmovesoftware.com> + Richard Biener <rguenther@suse.de> + + * config/i386/i386-features.c (compute_convert_gain): Provide + more accurate values for CONST_INT, when optimizing for size. + * config/i386/i386.c (COSTS_N_BYTES): Move definition from here... + * config/i386/i386.h (COSTS_N_BYTES): to here. + +2021-08-24 Roger Sayle <roger@nextmovesoftware.com> + Jakub Jelinek <jakub@redhat.com> + + PR middle-end/102029 + * match.pd (shift transformations): Add an additional check for + !POINTER_TYPE_P in the recently added left shift transformation. + +2021-08-24 liuhongt <hongtao.liu@intel.com> + + PR tree-optimization/100089 + * tree-vectorizer.c (try_vectorize_loop_1): Disable slp in + loop vectorizer when cost model is very-cheap. + 2021-08-23 Bill Schmidt <wschmidt@linux.ibm.com> * config/rs6000/rs6000-gen-builtins.c (parse_bif_entry): Don't call diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 83a5291..98be008 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20210824 +20210826 diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 211f34c..c7e8ba92 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,9 @@ +2021-08-25 Ankur Saini <arsenic@sourceware.org> + + PR analyzer/101980 + * engine.cc (exploded_graph::maybe_create_dynamic_call): Don't create + calls if max recursion limit is reached. + 2021-08-23 David Malcolm <dmalcolm@redhat.com> * analyzer.h (struct rejected_constraint): Convert to... diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 4ee9279..9c604d1 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -3059,6 +3059,20 @@ exploded_graph::maybe_create_dynamic_call (const gcall *call, new_point.push_to_call_stack (sn_exit, next_point.get_supernode()); + + /* Impose a maximum recursion depth and don't analyze paths + that exceed it further. + This is something of a blunt workaround, but it only + applies to recursion (and mutual recursion), not to + general call stacks. */ + if (new_point.get_call_string ().calc_recursion_depth () + > param_analyzer_max_recursion_depth) + { + if (logger) + logger->log ("rejecting call edge: recursion limit exceeded"); + return false; + } + next_state.push_call (*this, node, call, uncertainty); if (next_state.m_valid) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 873d7ab..5e3ac92 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * c-opts.c (c_common_input_charset_cb): New function. + (c_common_post_options): Call new function + diagnostic_initialize_input_context(). + 2021-08-20 Tobias Burnus <tobias@codesourcery.com> * c-format.c (gcc_gfc_length_specs): Add 'll' and 'w'. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index 373af0c..fdde082 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -188,6 +188,14 @@ c_common_diagnostics_set_defaults (diagnostic_context *context) context->opt_permissive = OPT_fpermissive; } +/* Input charset configuration for diagnostics. */ +static const char * +c_common_input_charset_cb (const char * /*filename*/) +{ + const char *cs = cpp_opts->input_charset; + return cpp_input_conversion_is_trivial (cs) ? nullptr : cs; +} + /* Whether options from all C-family languages should be accepted quietly. */ static bool accept_all_c_family_options = false; @@ -1136,6 +1144,11 @@ c_common_post_options (const char **pfilename) cpp_post_options (parse_in); init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in)); + /* Let diagnostics infrastructure know how to convert input files the same + way libcpp will do it, namely using the configured input charset and + skipping a UTF-8 BOM if present. */ + diagnostic_initialize_input_context (global_dc, + c_common_input_charset_cb, true); input_location = UNKNOWN_LOCATION; *pfilename = this_input_filename diff --git a/gcc/cgraph.h b/gcc/cgraph.h index d54a258..4cdb373 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1006,13 +1006,16 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET of the declaration. + If VERSION_DECL is set true, use clone_function_name_numbered for the + function clone. Otherwise, use clone_function_name. + Return the new version's cgraph node. */ cgraph_node *create_version_clone_with_body (vec<cgraph_edge *> redirect_callers, vec<ipa_replace_map *, va_gc> *tree_map, ipa_param_adjustments *param_adjustments, bitmap bbs_to_copy, basic_block new_entry_block, const char *clone_name, - tree target_attributes = NULL_TREE); + tree target_attributes = NULL_TREE, bool version_decl = true); /* Insert a new cgraph_function_version_info node into cgraph_fnver_htab corresponding to cgraph_node. */ diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index b16e681..ae91dcc 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -987,6 +987,9 @@ cgraph_node::create_version_clone (tree new_decl, that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET of the declaration. + If VERSION_DECL is set true, use clone_function_name_numbered for the + function clone. Otherwise, use clone_function_name. + Return the new version's cgraph node. */ cgraph_node * @@ -995,7 +998,7 @@ cgraph_node::create_version_clone_with_body vec<ipa_replace_map *, va_gc> *tree_map, ipa_param_adjustments *param_adjustments, bitmap bbs_to_copy, basic_block new_entry_block, const char *suffix, - tree target_attributes) + tree target_attributes, bool version_decl) { tree old_decl = decl; cgraph_node *new_version_node = NULL; @@ -1016,8 +1019,10 @@ cgraph_node::create_version_clone_with_body new_decl = copy_node (old_decl); /* Generate a new name for the new version. */ - DECL_NAME (new_decl) = clone_function_name_numbered (old_decl, suffix); - SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); + tree fnname = (version_decl ? clone_function_name_numbered (old_decl, suffix) + : clone_function_name (old_decl, suffix)); + DECL_NAME (new_decl) = fnname; + SET_DECL_ASSEMBLER_NAME (new_decl, fnname); SET_DECL_RTL (new_decl, NULL); DECL_VIRTUAL_P (new_decl) = 0; diff --git a/gcc/config.gcc b/gcc/config.gcc index 94199d7..0ff5cac 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -468,6 +468,8 @@ nios2-*-*) ;; nvptx-*-*) cpu_type=nvptx + c_target_objs="nvptx-c.o" + cxx_target_objs="nvptx-c.o" ;; or1k*-*-*) cpu_type=or1k diff --git a/gcc/config/i386/avx512dqintrin.h b/gcc/config/i386/avx512dqintrin.h index 51c0b12..9794f5d 100644 --- a/gcc/config/i386/avx512dqintrin.h +++ b/gcc/config/i386/avx512dqintrin.h @@ -2814,7 +2814,7 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) #define _mm512_mask_fpclass_ps_mask(u, x, c) \ ((__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) (__m512) (x),\ - (int) (c),(__mmask8)(u))) + (int) (c),(__mmask16)(u))) #define _mm512_fpclass_pd_mask(X, C) \ ((__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) (__m512d) (X), \ @@ -2822,7 +2822,7 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm) #define _mm512_fpclass_ps_mask(x, c) \ ((__mmask16) __builtin_ia32_fpclassps512_mask ((__v16sf) (__m512) (x),\ - (int) (c),(__mmask8)-1)) + (int) (c),(__mmask16)-1)) #define _mm_reduce_sd(A, B, C) \ ((__m128d) __builtin_ia32_reducesd_mask ((__v2df)(__m128d)(A), \ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index ebec866..ddbbbce 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10018,8 +10018,7 @@ ix86_live_on_entry (bitmap regs) /* Extract the parts of an RTL expression that is a valid memory address for an instruction. Return 0 if the structure of the address is - grossly off. Return -1 if the address contains ASHIFT, so it is not - strictly valid, but still used for computing length of lea instruction. */ + grossly off. */ int ix86_decompose_address (rtx addr, struct ix86_address *out) @@ -10029,7 +10028,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) HOST_WIDE_INT scale = 1; rtx scale_rtx = NULL_RTX; rtx tmp; - int retval = 1; addr_space_t seg = ADDR_SPACE_GENERIC; /* Allow zero-extended SImode addresses, @@ -10053,6 +10051,27 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) if (CONST_INT_P (addr)) return 0; } + else if (GET_CODE (addr) == AND) + { + /* For ASHIFT inside AND, combine will not generate + canonical zero-extend. Merge mask for AND and shift_count + to check if it is canonical zero-extend. */ + tmp = XEXP (addr, 0); + rtx mask = XEXP (addr, 1); + if (tmp && GET_CODE(tmp) == ASHIFT) + { + rtx shift_val = XEXP (tmp, 1); + if (CONST_INT_P (mask) && CONST_INT_P (shift_val) + && (((unsigned HOST_WIDE_INT) INTVAL(mask) + | ((HOST_WIDE_INT_1U << INTVAL(shift_val)) - 1)) + == 0xffffffff)) + { + addr = lowpart_subreg (SImode, XEXP (addr, 0), + DImode); + } + } + + } } /* Allow SImode subregs of DImode addresses, @@ -10179,7 +10198,6 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) if ((unsigned HOST_WIDE_INT) scale > 3) return 0; scale = 1 << scale; - retval = -1; } else disp = addr; /* displacement */ @@ -10252,7 +10270,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) out->scale = scale; out->seg = seg; - return retval; + return 1; } /* Return cost of the memory address x. @@ -10765,7 +10783,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) HOST_WIDE_INT scale; addr_space_t seg; - if (ix86_decompose_address (addr, &parts) <= 0) + if (ix86_decompose_address (addr, &parts) == 0) /* Decomposition failed. */ return false; @@ -20419,6 +20437,12 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, << (GET_MODE (XEXP (x, 1)) != DImode))); return true; } + else if (code == AND + && address_no_seg_operand (x, mode)) + { + *total = cost->lea; + return true; + } /* FALLTHRU */ case NEG: diff --git a/gcc/config/nvptx/nvptx-c.c b/gcc/config/nvptx/nvptx-c.c new file mode 100644 index 0000000..72594a82e --- /dev/null +++ b/gcc/config/nvptx/nvptx-c.c @@ -0,0 +1,47 @@ +/* Subroutines for the C front end on the NVPTX architecture. + * Copyright (C) 2021 Free Software Foundation, Inc. + * + * This file is part of GCC. + * + * GCC is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 3, or (at your + * option) any later version. + * + * GCC is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GCC; see the file COPYING3. If not see + * <http://www.gnu.org/licenses/>. */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "c-family/c-common.h" +#include "memmodel.h" +#include "tm_p.h" +#include "c-family/c-pragma.h" + +/* Function to tell the preprocessor about the defines for the target. */ +void +nvptx_cpu_cpp_builtins (void) +{ + cpp_assert (parse_in, "machine=nvptx"); + cpp_assert (parse_in, "cpu=nvptx"); + cpp_define (parse_in, "__nvptx__"); + if (TARGET_SOFT_STACK) + cpp_define (parse_in, "__nvptx_softstack__"); + if (TARGET_UNIFORM_SIMT) + cpp_define (parse_in,"__nvptx_unisimt__"); + if (TARGET_SM35) + cpp_define (parse_in, "__PTX_SM__=350"); + else + cpp_define (parse_in,"__PTX_SM__=300"); +} + diff --git a/gcc/config/nvptx/nvptx-protos.h b/gcc/config/nvptx/nvptx-protos.h index b7e6ae2..b29ddc9 100644 --- a/gcc/config/nvptx/nvptx-protos.h +++ b/gcc/config/nvptx/nvptx-protos.h @@ -40,6 +40,7 @@ extern void nvptx_output_aligned_decl (FILE *file, const char *name, extern void nvptx_function_end (FILE *); extern void nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT); extern void nvptx_output_ascii (FILE *, const char *, unsigned HOST_WIDE_INT); +extern void nvptx_cpu_cpp_builtins (void); extern void nvptx_register_pragmas (void); extern unsigned int nvptx_data_alignment (const_tree, unsigned int); diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index fdaacdd..d367174 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -34,17 +34,7 @@ nvptx-as. */ #define ASM_SPEC "%{misa=*:-m %*; :-m sm_35}" -#define TARGET_CPU_CPP_BUILTINS() \ - do \ - { \ - builtin_assert ("machine=nvptx"); \ - builtin_assert ("cpu=nvptx"); \ - builtin_define ("__nvptx__"); \ - if (TARGET_SOFT_STACK) \ - builtin_define ("__nvptx_softstack__"); \ - if (TARGET_UNIFORM_SIMT) \ - builtin_define ("__nvptx_unisimt__"); \ - } while (0) +#define TARGET_CPU_CPP_BUILTINS() nvptx_cpu_cpp_builtins () /* Avoid the default in ../../gcc.c, which adds "-pthread", which is not supported for nvptx. */ diff --git a/gcc/config/nvptx/t-nvptx b/gcc/config/nvptx/t-nvptx index 6c1010d..d33bacd 100644 --- a/gcc/config/nvptx/t-nvptx +++ b/gcc/config/nvptx/t-nvptx @@ -1,3 +1,7 @@ +nvptx-c.o: $(srcdir)/config/nvptx/nvptx-c.c + $(COMPILE) $< + $(POSTCOMPILE) + CFLAGS-mkoffload.o += $(DRIVER_DEFINES) \ -DGCC_INSTALL_NAME=\"$(GCC_INSTALL_NAME)\" mkoffload.o: $(srcdir)/config/nvptx/mkoffload.c diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index 662785c..0f4d8cb 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-or-later /* Definitions of target machine for GNU compiler, for IBM RS/6000 POWER running AIX. Copyright (C) 2000-2021 Free Software Foundation, Inc. @@ -23,9 +24,6 @@ #undef TARGET_AIX #define TARGET_AIX 1 -/* System headers are not C++-aware. */ -#define SYSTEM_IMPLICIT_EXTERN_C 1 - /* Linux64.h wants to redefine TARGET_AIX based on -m64, but it can't be used in the #if conditional in options-default.h, so provide another macro. */ #undef TARGET_AIX_OS diff --git a/gcc/config/rs6000/aix71.h b/gcc/config/rs6000/aix71.h index 38cfa9e..1bc1560 100644 --- a/gcc/config/rs6000/aix71.h +++ b/gcc/config/rs6000/aix71.h @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-3.0-or-later /* Definitions of target machine for GNU compiler, for IBM RS/6000 POWER running AIX V7.1. Copyright (C) 2002-2021 Free Software Foundation, Inc. @@ -268,6 +269,9 @@ extern long long int atoll(const char *); #define SET_CMODEL(opt) do {} while (0) #endif +/* System headers are not C++-aware. */ +#define SYSTEM_IMPLICIT_EXTERN_C 1 + /* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION, but does not have crtbegin/end. */ diff --git a/gcc/config/rs6000/aix72.h b/gcc/config/rs6000/aix72.h index a497a7d..cca64f1 100644 --- a/gcc/config/rs6000/aix72.h +++ b/gcc/config/rs6000/aix72.h @@ -270,6 +270,9 @@ extern long long int atoll(const char *); #define SET_CMODEL(opt) do {} while (0) #endif +/* System headers are not C++-aware. */ +#define SYSTEM_IMPLICIT_EXTERN_C 1 + /* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION, but does not have crtbegin/end. */ diff --git a/gcc/config/rs6000/aix73.h b/gcc/config/rs6000/aix73.h index c707c7e..f0ca1a5 100644 --- a/gcc/config/rs6000/aix73.h +++ b/gcc/config/rs6000/aix73.h @@ -274,7 +274,7 @@ extern long long int atoll(const char *); /* This target defines SUPPORTS_WEAK and TARGET_ASM_NAMED_SECTION, but does not have crtbegin/end. */ -#define TARGET_AIX_VERSION 72 +#define TARGET_AIX_VERSION 73 /* AIX 7.2 supports DWARF3+ debugging. */ #define DWARF2_DEBUGGING_INFO 1 diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 2c73dde..93d23715 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -134,10 +134,8 @@ UNSPEC_VMULWLUH UNSPEC_VMULWHSH UNSPEC_VMULWLSH - UNSPEC_VUPKHUB - UNSPEC_VUPKHUH - UNSPEC_VUPKLUB - UNSPEC_VUPKLUH + UNSPEC_VUPKHU + UNSPEC_VUPKLU UNSPEC_VPERMSI UNSPEC_VPERMHI UNSPEC_INTERHI @@ -3688,143 +3686,45 @@ [(set_attr "type" "vecperm") (set_attr "isa" "p9v,*")]) -(define_expand "vec_unpacku_hi_v16qi" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] - UNSPEC_VUPKHUB))] - "TARGET_ALTIVEC" -{ - rtx vzero = gen_reg_rtx (V8HImode); - rtx mask = gen_reg_rtx (V16QImode); - rtvec v = rtvec_alloc (16); - bool be = BYTES_BIG_ENDIAN; - - emit_insn (gen_altivec_vspltish (vzero, const0_rtx)); - - RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7); - RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 0 : 16); - RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 6); - RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16); - RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5); - RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 2 : 16); - RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 4); - RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16); - RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3); - RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 4 : 16); - RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 2); - RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16); - RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1); - RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 6 : 16); - RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 0); - RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - - emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); - emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); - DONE; -}) - -(define_expand "vec_unpacku_hi_v8hi" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] - UNSPEC_VUPKHUH))] +(define_expand "vec_unpacku_hi_<VP_small_lc>" + [(set (match_operand:VP 0 "register_operand" "=v") + (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")] + UNSPEC_VUPKHU))] "TARGET_ALTIVEC" { - rtx vzero = gen_reg_rtx (V4SImode); - rtx mask = gen_reg_rtx (V16QImode); - rtvec v = rtvec_alloc (16); - bool be = BYTES_BIG_ENDIAN; + rtx vzero = gen_reg_rtx (<VP_small>mode); + emit_insn (gen_altivec_vspltis<VU_char> (vzero, const0_rtx)); - emit_insn (gen_altivec_vspltisw (vzero, const0_rtx)); - - RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 7); - RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 6); - RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 0 : 17); - RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 1 : 16); - RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 5); - RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 4); - RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 2 : 17); - RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 3 : 16); - RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 3); - RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 2); - RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 4 : 17); - RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 5 : 16); - RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 1); - RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 0); - RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 6 : 17); - RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 7 : 16); - - emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); - emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); - DONE; -}) + rtx res = gen_reg_rtx (<VP_small>mode); + rtx op1 = operands[1]; -(define_expand "vec_unpacku_lo_v16qi" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] - UNSPEC_VUPKLUB))] - "TARGET_ALTIVEC" -{ - rtx vzero = gen_reg_rtx (V8HImode); - rtx mask = gen_reg_rtx (V16QImode); - rtvec v = rtvec_alloc (16); - bool be = BYTES_BIG_ENDIAN; - - emit_insn (gen_altivec_vspltish (vzero, const0_rtx)); - - RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15); - RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 8 : 16); - RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 16 : 14); - RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16); - RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13); - RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 10 : 16); - RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 16 : 12); - RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16); - RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11); - RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 12 : 16); - RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 16 : 10); - RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16); - RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9); - RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 14 : 16); - RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 16 : 8); - RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrgh<VU_char> (res, vzero, op1)); + else + emit_insn (gen_altivec_vmrgl<VU_char> (res, op1, vzero)); - emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); - emit_insn (gen_vperm_v16qiv8hi (operands[0], operands[1], vzero, mask)); + emit_insn (gen_move_insn (operands[0], gen_lowpart (<MODE>mode, res))); DONE; }) -(define_expand "vec_unpacku_lo_v8hi" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] - UNSPEC_VUPKLUH))] +(define_expand "vec_unpacku_lo_<VP_small_lc>" + [(set (match_operand:VP 0 "register_operand" "=v") + (unspec:VP [(match_operand:<VP_small> 1 "register_operand" "v")] + UNSPEC_VUPKLU))] "TARGET_ALTIVEC" { - rtx vzero = gen_reg_rtx (V4SImode); - rtx mask = gen_reg_rtx (V16QImode); - rtvec v = rtvec_alloc (16); - bool be = BYTES_BIG_ENDIAN; + rtx vzero = gen_reg_rtx (<VP_small>mode); + emit_insn (gen_altivec_vspltis<VU_char> (vzero, const0_rtx)); - emit_insn (gen_altivec_vspltisw (vzero, const0_rtx)); - - RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, be ? 16 : 15); - RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, be ? 17 : 14); - RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, be ? 8 : 17); - RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, be ? 9 : 16); - RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, be ? 16 : 13); - RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, be ? 17 : 12); - RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, be ? 10 : 17); - RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, be ? 11 : 16); - RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, be ? 16 : 11); - RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, be ? 17 : 10); - RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, be ? 12 : 17); - RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, be ? 13 : 16); - RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, be ? 16 : 9); - RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, be ? 17 : 8); - RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, be ? 14 : 17); - RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, be ? 15 : 16); + rtx res = gen_reg_rtx (<VP_small>mode); + rtx op1 = operands[1]; - emit_insn (gen_vec_initv16qiqi (mask, gen_rtx_PARALLEL (V16QImode, v))); - emit_insn (gen_vperm_v8hiv4si (operands[0], operands[1], vzero, mask)); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vmrgl<VU_char> (res, vzero, op1)); + else + emit_insn (gen_altivec_vmrgh<VU_char> (res, op1, vzero)); + + emit_insn (gen_move_insn (operands[0], gen_lowpart (<MODE>mode, res))); DONE; }) diff --git a/gcc/config/rs6000/rs6000-builtin-new.def b/gcc/config/rs6000/rs6000-builtin-new.def index 2a2c913..b6fc994 100644 --- a/gcc/config/rs6000/rs6000-builtin-new.def +++ b/gcc/config/rs6000/rs6000-builtin-new.def @@ -2438,3 +2438,894 @@ const double __builtin_vsx_xscvspdpn (vf); XSCVSPDPN vsx_xscvspdpn {} + + +; Power9 vector builtins. +[power9-vector] + const vss __builtin_altivec_convert_4f32_8f16 (vf, vf); + CONVERT_4F32_8F16 convert_4f32_8f16 {} + + const vss __builtin_altivec_convert_4f32_8i16 (vf, vf); + CONVERT_4F32_8I16 convert_4f32_8i16 {} + + const signed int __builtin_altivec_first_match_index_v16qi (vsc, vsc); + VFIRSTMATCHINDEX_V16QI first_match_index_v16qi {} + + const signed int __builtin_altivec_first_match_index_v8hi (vss, vss); + VFIRSTMATCHINDEX_V8HI first_match_index_v8hi {} + + const signed int __builtin_altivec_first_match_index_v4si (vsi, vsi); + VFIRSTMATCHINDEX_V4SI first_match_index_v4si {} + + const signed int __builtin_altivec_first_match_or_eos_index_v16qi (vsc, vsc); + VFIRSTMATCHOREOSINDEX_V16QI first_match_or_eos_index_v16qi {} + + const signed int __builtin_altivec_first_match_or_eos_index_v8hi (vss, vss); + VFIRSTMATCHOREOSINDEX_V8HI first_match_or_eos_index_v8hi {} + + const signed int __builtin_altivec_first_match_or_eos_index_v4si (vsi, vsi); + VFIRSTMATCHOREOSINDEX_V4SI first_match_or_eos_index_v4si {} + + const signed int __builtin_altivec_first_mismatch_index_v16qi (vsc, vsc); + VFIRSTMISMATCHINDEX_V16QI first_mismatch_index_v16qi {} + + const signed int __builtin_altivec_first_mismatch_index_v8hi (vss, vss); + VFIRSTMISMATCHINDEX_V8HI first_mismatch_index_v8hi {} + + const signed int __builtin_altivec_first_mismatch_index_v4si (vsi, vsi); + VFIRSTMISMATCHINDEX_V4SI first_mismatch_index_v4si {} + + const signed int __builtin_altivec_first_mismatch_or_eos_index_v16qi (vsc, vsc); + VFIRSTMISMATCHOREOSINDEX_V16QI first_mismatch_or_eos_index_v16qi {} + + const signed int __builtin_altivec_first_mismatch_or_eos_index_v8hi (vss, vss); + VFIRSTMISMATCHOREOSINDEX_V8HI first_mismatch_or_eos_index_v8hi {} + + const signed int __builtin_altivec_first_mismatch_or_eos_index_v4si (vsi, vsi); + VFIRSTMISMATCHOREOSINDEX_V4SI first_mismatch_or_eos_index_v4si {} + + const vsc __builtin_altivec_vadub (vsc, vsc); + VADUB vaduv16qi3 {} + + const vss __builtin_altivec_vaduh (vss, vss); + VADUH vaduv8hi3 {} + + const vsi __builtin_altivec_vaduw (vsi, vsi); + VADUW vaduv4si3 {} + + const vsll __builtin_altivec_vbpermd (vsll, vsc); + VBPERMD altivec_vbpermd {} + + const signed int __builtin_altivec_vclzlsbb_v16qi (vsc); + VCLZLSBB_V16QI vclzlsbb_v16qi {} + + const signed int __builtin_altivec_vclzlsbb_v4si (vsi); + VCLZLSBB_V4SI vclzlsbb_v4si {} + + const signed int __builtin_altivec_vclzlsbb_v8hi (vss); + VCLZLSBB_V8HI vclzlsbb_v8hi {} + + const vsc __builtin_altivec_vctzb (vsc); + VCTZB ctzv16qi2 {} + + const vsll __builtin_altivec_vctzd (vsll); + VCTZD ctzv2di2 {} + + const vss __builtin_altivec_vctzh (vss); + VCTZH ctzv8hi2 {} + + const vsi __builtin_altivec_vctzw (vsi); + VCTZW ctzv4si2 {} + + const signed int __builtin_altivec_vctzlsbb_v16qi (vsc); + VCTZLSBB_V16QI vctzlsbb_v16qi {} + + const signed int __builtin_altivec_vctzlsbb_v4si (vsi); + VCTZLSBB_V4SI vctzlsbb_v4si {} + + const signed int __builtin_altivec_vctzlsbb_v8hi (vss); + VCTZLSBB_V8HI vctzlsbb_v8hi {} + + const signed int __builtin_altivec_vcmpaeb_p (vsc, vsc); + VCMPAEB_P vector_ae_v16qi_p {} + + const signed int __builtin_altivec_vcmpaed_p (vsll, vsll); + VCMPAED_P vector_ae_v2di_p {} + + const signed int __builtin_altivec_vcmpaedp_p (vd, vd); + VCMPAEDP_P vector_ae_v2df_p {} + + const signed int __builtin_altivec_vcmpaefp_p (vf, vf); + VCMPAEFP_P vector_ae_v4sf_p {} + + const signed int __builtin_altivec_vcmpaeh_p (vss, vss); + VCMPAEH_P vector_ae_v8hi_p {} + + const signed int __builtin_altivec_vcmpaew_p (vsi, vsi); + VCMPAEW_P vector_ae_v4si_p {} + + const vsc __builtin_altivec_vcmpneb (vsc, vsc); + VCMPNEB vcmpneb {} + + const signed int __builtin_altivec_vcmpneb_p (vsc, vsc); + VCMPNEB_P vector_ne_v16qi_p {} + + const signed int __builtin_altivec_vcmpned_p (vsll, vsll); + VCMPNED_P vector_ne_v2di_p {} + + const signed int __builtin_altivec_vcmpnedp_p (vd, vd); + VCMPNEDP_P vector_ne_v2df_p {} + + const signed int __builtin_altivec_vcmpnefp_p (vf, vf); + VCMPNEFP_P vector_ne_v4sf_p {} + + const vss __builtin_altivec_vcmpneh (vss, vss); + VCMPNEH vcmpneh {} + + const signed int __builtin_altivec_vcmpneh_p (vss, vss); + VCMPNEH_P vector_ne_v8hi_p {} + + const vsi __builtin_altivec_vcmpnew (vsi, vsi); + VCMPNEW vcmpnew {} + + const signed int __builtin_altivec_vcmpnew_p (vsi, vsi); + VCMPNEW_P vector_ne_v4si_p {} + + const vsc __builtin_altivec_vcmpnezb (vsc, vsc); + CMPNEZB vcmpnezb {} + + const signed int __builtin_altivec_vcmpnezb_p (signed int, vsc, vsc); + VCMPNEZB_P vector_nez_v16qi_p {pred} + + const vss __builtin_altivec_vcmpnezh (vss, vss); + CMPNEZH vcmpnezh {} + + const signed int __builtin_altivec_vcmpnezh_p (signed int, vss, vss); + VCMPNEZH_P vector_nez_v8hi_p {pred} + + const vsi __builtin_altivec_vcmpnezw (vsi, vsi); + CMPNEZW vcmpnezw {} + + const signed int __builtin_altivec_vcmpnezw_p (signed int, vsi, vsi); + VCMPNEZW_P vector_nez_v4si_p {pred} + + const signed int __builtin_altivec_vextublx (signed int, vsc); + VEXTUBLX vextublx {} + + const signed int __builtin_altivec_vextubrx (signed int, vsc); + VEXTUBRX vextubrx {} + + const signed int __builtin_altivec_vextuhlx (signed int, vss); + VEXTUHLX vextuhlx {} + + const signed int __builtin_altivec_vextuhrx (signed int, vss); + VEXTUHRX vextuhrx {} + + const signed int __builtin_altivec_vextuwlx (signed int, vsi); + VEXTUWLX vextuwlx {} + + const signed int __builtin_altivec_vextuwrx (signed int, vsi); + VEXTUWRX vextuwrx {} + + const vsq __builtin_altivec_vmsumudm (vsll, vsll, vsq); + VMSUMUDM altivec_vmsumudm {} + + const vsll __builtin_altivec_vprtybd (vsll); + VPRTYBD parityv2di2 {} + + const vsq __builtin_altivec_vprtybq (vsq); + VPRTYBQ parityv1ti2 {} + + const vsi __builtin_altivec_vprtybw (vsi); + VPRTYBW parityv4si2 {} + + const vsll __builtin_altivec_vrldmi (vsll, vsll, vsll); + VRLDMI altivec_vrldmi {} + + const vsll __builtin_altivec_vrldnm (vsll, vsll); + VRLDNM altivec_vrldnm {} + + const vsi __builtin_altivec_vrlwmi (vsi, vsi, vsi); + VRLWMI altivec_vrlwmi {} + + const vsi __builtin_altivec_vrlwnm (vsi, vsi); + VRLWNM altivec_vrlwnm {} + + const vsll __builtin_altivec_vsignextsb2d (vsc); + VSIGNEXTSB2D vsignextend_qi_v2di {} + + const vsi __builtin_altivec_vsignextsb2w (vsc); + VSIGNEXTSB2W vsignextend_qi_v4si {} + + const vsll __builtin_altivec_visgnextsh2d (vss); + VSIGNEXTSH2D vsignextend_hi_v2di {} + + const vsi __builtin_altivec_vsignextsh2w (vss); + VSIGNEXTSH2W vsignextend_hi_v4si {} + + const vsll __builtin_altivec_vsignextsw2d (vsi); + VSIGNEXTSW2D vsignextend_si_v2di {} + + const vsc __builtin_altivec_vslv (vsc, vsc); + VSLV vslv {} + + const vsc __builtin_altivec_vsrv (vsc, vsc); + VSRV vsrv {} + + const signed int __builtin_scalar_byte_in_range (signed int, signed int); + CMPRB cmprb {} + + const signed int __builtin_scalar_byte_in_either_range (signed int, signed int); + CMPRB2 cmprb2 {} + + const vsll __builtin_vsx_extract4b (vsc, const int[0,12]); + EXTRACT4B extract4b {} + + const vd __builtin_vsx_extract_exp_dp (vd); + VEEDP xvxexpdp {} + + const vf __builtin_vsx_extract_exp_sp (vf); + VEESP xvxexpsp {} + + const vd __builtin_vsx_extract_sig_dp (vd); + VESDP xvxsigdp {} + + const vf __builtin_vsx_extract_sig_sp (vf); + VESSP xvxsigsp {} + + const vsc __builtin_vsx_insert4b (vsi, vsc, const int[0,12]); + INSERT4B insert4b {} + + const vd __builtin_vsx_insert_exp_dp (vd, vd); + VIEDP xviexpdp {} + + const vf __builtin_vsx_insert_exp_sp (vf, vf); + VIESP xviexpsp {} + + const signed int __builtin_vsx_scalar_cmp_exp_dp_eq (double, double); + VSCEDPEQ xscmpexpdp_eq {} + + const signed int __builtin_vsx_scalar_cmp_exp_dp_gt (double, double); + VSCEDPGT xscmpexpdp_gt {} + + const signed int __builtin_vsx_scalar_cmp_exp_dp_lt (double, double); + VSCEDPLT xscmpexpdp_lt {} + + const signed int __builtin_vsx_scalar_cmp_exp_dp_unordered (double, double); + VSCEDPUO xscmpexpdp_unordered {} + + const signed int __builtin_vsx_scalar_test_data_class_dp (double, const int<7>); + VSTDCDP xststdcdp {} + + const signed int __builtin_vsx_scalar_test_data_class_sp (float, const int<7>); + VSTDCSP xststdcsp {} + + const signed int __builtin_vsx_scalar_test_neg_dp (double); + VSTDCNDP xststdcnegdp {} + + const signed int __builtin_vsx_scalar_test_neg_sp (float); + VSTDCNSP xststdcnegsp {} + + const vsll __builtin_vsx_test_data_class_dp (vd, const int<7>); + VTDCDP xvtstdcdp {} + + const vsi __builtin_vsx_test_data_class_sp (vf, const int<7>); + VTDCSP xvtstdcsp {} + + const vf __builtin_vsx_vextract_fp_from_shorth (vss); + VEXTRACT_FP_FROM_SHORTH vextract_fp_from_shorth {} + + const vf __builtin_vsx_vextract_fp_from_shortl (vss); + VEXTRACT_FP_FROM_SHORTL vextract_fp_from_shortl {} + + const vd __builtin_vsx_xxbrd_v2df (vd); + XXBRD_V2DF p9_xxbrd_v2df {} + + const vsll __builtin_vsx_xxbrd_v2di (vsll); + XXBRD_V2DI p9_xxbrd_v2di {} + + const vss __builtin_vsx_xxbrh_v8hi (vss); + XXBRH_V8HI p9_xxbrh_v8hi {} + + const vsc __builtin_vsx_xxbrq_v16qi (vsc); + XXBRQ_V16QI p9_xxbrq_v16qi {} + + const vsq __builtin_vsx_xxbrq_v1ti (vsq); + XXBRQ_V1TI p9_xxbrq_v1ti {} + + const vf __builtin_vsx_xxbrw_v4sf (vf); + XXBRW_V4SF p9_xxbrw_v4sf {} + + const vsi __builtin_vsx_xxbrw_v4si (vsi); + XXBRW_V4SI p9_xxbrw_v4si {} + + +; Miscellaneous P9 functions +[power9] + signed long long __builtin_darn (); + DARN darn {} + + signed int __builtin_darn_32 (); + DARN_32 darn_32 {} + + signed long long __builtin_darn_raw (); + DARN_RAW darn_raw {} + + double __builtin_mffsl (); + MFFSL rs6000_mffsl {} + + const signed int __builtin_dtstsfi_eq_dd (const int<6>, _Decimal64); + TSTSFI_EQ_DD dfptstsfi_eq_dd {} + + const signed int __builtin_dtstsfi_eq_td (const int<6>, _Decimal128); + TSTSFI_EQ_TD dfptstsfi_eq_td {} + + const signed int __builtin_dtstsfi_gt_dd (const int<6>, _Decimal64); + TSTSFI_GT_DD dfptstsfi_gt_dd {} + + const signed int __builtin_dtstsfi_gt_td (const int<6>, _Decimal128); + TSTSFI_GT_TD dfptstsfi_gt_td {} + + const signed int __builtin_dtstsfi_lt_dd (const int<6>, _Decimal64); + TSTSFI_LT_DD dfptstsfi_lt_dd {} + + const signed int __builtin_dtstsfi_lt_td (const int<6>, _Decimal128); + TSTSFI_LT_TD dfptstsfi_lt_td {} + + const signed int __builtin_dtstsfi_ov_dd (const int<6>, _Decimal64); + TSTSFI_OV_DD dfptstsfi_unordered_dd {} + + const signed int __builtin_dtstsfi_ov_td (const int<6>, _Decimal128); + TSTSFI_OV_TD dfptstsfi_unordered_td {} + + +[power9-64] + void __builtin_altivec_xst_len_r (vsc, void *, long); + XST_LEN_R xst_len_r {} + + void __builtin_altivec_stxvl (vsc, void *, long); + STXVL stxvl {} + + const signed int __builtin_scalar_byte_in_set (signed int, signed long long); + CMPEQB cmpeqb {} + + pure vsc __builtin_vsx_lxvl (const void *, signed long); + LXVL lxvl {} + + const signed long __builtin_vsx_scalar_extract_exp (double); + VSEEDP xsxexpdp {} + + const signed long __builtin_vsx_scalar_extract_sig (double); + VSESDP xsxsigdp {} + + const double __builtin_vsx_scalar_insert_exp (unsigned long long, unsigned long long); + VSIEDP xsiexpdp {} + + const double __builtin_vsx_scalar_insert_exp_dp (double, unsigned long long); + VSIEDPF xsiexpdpf {} + + pure vsc __builtin_vsx_xl_len_r (void *, signed long); + XL_LEN_R xl_len_r {} + + +[power10] + const vbq __builtin_altivec_cmpge_1ti (vsq, vsq); + CMPGE_1TI vector_nltv1ti {} + + const vbq __builtin_altivec_cmpge_u1ti (vuq, vuq); + CMPGE_U1TI vector_nltuv1ti {} + + const vbq __builtin_altivec_cmple_1ti (vsq, vsq); + CMPLE_1TI vector_ngtv1ti {} + + const vbq __builtin_altivec_cmple_u1ti (vuq, vuq); + CMPLE_U1TI vector_ngtuv1ti {} + + const unsigned long long __builtin_altivec_cntmbb (vuc, const int<1>); + VCNTMBB vec_cntmb_v16qi {} + + const unsigned long long __builtin_altivec_cntmbd (vull, const int<1>); + VCNTMBD vec_cntmb_v2di {} + + const unsigned long long __builtin_altivec_cntmbh (vus, const int<1>); + VCNTMBH vec_cntmb_v8hi {} + + const unsigned long long __builtin_altivec_cntmbw (vui, const int<1>); + VCNTMBW vec_cntmb_v4si {} + + const vsq __builtin_altivec_div_v1ti (vsq, vsq); + DIV_V1TI vsx_div_v1ti {} + + const vsq __builtin_altivec_dives (vsq, vsq); + DIVES_V1TI vsx_dives_v1ti {} + + const vuq __builtin_altivec_diveu (vuq, vuq); + DIVEU_V1TI vsx_diveu_v1ti {} + + const vsq __builtin_altivec_mods (vsq, vsq); + MODS_V1TI vsx_mods_v1ti {} + + const vuq __builtin_altivec_modu (vuq, vuq); + MODU_V1TI vsx_modu_v1ti {} + + const vuc __builtin_altivec_mtvsrbm (unsigned long long); + MTVSRBM vec_mtvsr_v16qi {} + + const vull __builtin_altivec_mtvsrdm (unsigned long long); + MTVSRDM vec_mtvsr_v2di {} + + const vus __builtin_altivec_mtvsrhm (unsigned long long); + MTVSRHM vec_mtvsr_v8hi {} + + const vuq __builtin_altivec_mtvsrqm (unsigned long long); + MTVSRQM vec_mtvsr_v1ti {} + + const vui __builtin_altivec_mtvsrwm (unsigned long long); + MTVSRWM vec_mtvsr_v4si {} + + pure signed __int128 __builtin_altivec_se_lxvrbx (signed long, const signed char *); + SE_LXVRBX vsx_lxvrbx {lxvrse} + + pure signed __int128 __builtin_altivec_se_lxvrhx (signed long, const signed short *); + SE_LXVRHX vsx_lxvrhx {lxvrse} + + pure signed __int128 __builtin_altivec_se_lxvrwx (signed long, const signed int *); + SE_LXVRWX vsx_lxvrwx {lxvrse} + + pure signed __int128 __builtin_altivec_se_lxvrdx (signed long, const signed long long *); + SE_LXVRDX vsx_lxvrdx {lxvrse} + + void __builtin_altivec_tr_stxvrbx (vsq, signed long, signed char *); + TR_STXVRBX vsx_stxvrbx {stvec} + + void __builtin_altivec_tr_stxvrhx (vsq, signed long, signed int *); + TR_STXVRHX vsx_stxvrhx {stvec} + + void __builtin_altivec_tr_stxvrwx (vsq, signed long, signed short *); + TR_STXVRWX vsx_stxvrwx {stvec} + + void __builtin_altivec_tr_stxvrdx (vsq, signed long, signed long long *); + TR_STXVRDX vsx_stxvrdx {stvec} + + const vuq __builtin_altivec_udiv_v1ti (vuq, vuq); + UDIV_V1TI vsx_udiv_v1ti {} + + const vull __builtin_altivec_vcfuged (vull, vull); + VCFUGED vcfuged {} + + const vsc __builtin_altivec_vclrlb (vsc, signed int); + VCLRLB vclrlb {} + + const vsc __builtin_altivec_vclrrb (vsc, signed int); + VCLRRB vclrrb {} + + const signed int __builtin_altivec_vcmpaet_p (vsq, vsq); + VCMPAET_P vector_ae_v1ti_p {} + + const vbq __builtin_altivec_vcmpequt (vsq, vsq); + VCMPEQUT vector_eqv1ti {} + + const signed int __builtin_altivec_vcmpequt_p (signed int, vsq, vsq); + VCMPEQUT_P vector_eq_v1ti_p {pred} + + const vbq __builtin_altivec_vcmpgtst (vsq, vsq); + VCMPGTST vector_gtv1ti {} + + const signed int __builtin_altivec_vcmpgtst_p (signed int, vsq, vsq); + VCMPGTST_P vector_gt_v1ti_p {pred} + + const vbq __builtin_altivec_vcmpgtut (vuq, vuq); + VCMPGTUT vector_gtuv1ti {} + + const signed int __builtin_altivec_vcmpgtut_p (signed int, vuq, vuq); + VCMPGTUT_P vector_gtu_v1ti_p {pred} + + const vbq __builtin_altivec_vcmpnet (vsq, vsq); + VCMPNET vcmpnet {} + + const signed int __builtin_altivec_vcmpnet_p (vsq, vsq); + VCMPNET_P vector_ne_v1ti_p {} + + const vull __builtin_altivec_vclzdm (vull, vull); + VCLZDM vclzdm {} + + const vull __builtin_altivec_vctzdm (vull, vull); + VCTZDM vctzdm {} + + const vsll __builtin_altivec_vdivesd (vsll, vsll); + VDIVESD dives_v2di {} + + const vsi __builtin_altivec_vdivesw (vsi, vsi); + VDIVESW dives_v4si {} + + const vull __builtin_altivec_vdiveud (vull, vull); + VDIVEUD diveu_v2di {} + + const vui __builtin_altivec_vdiveuw (vui, vui); + VDIVEUW diveu_v4si {} + + const vsll __builtin_altivec_vdivsd (vsll, vsll); + VDIVSD divv2di3 {} + + const vsi __builtin_altivec_vdivsw (vsi, vsi); + VDIVSW divv4si3 {} + + const vull __builtin_altivec_vdivud (vull, vull); + VDIVUD udivv2di3 {} + + const vui __builtin_altivec_vdivuw (vui, vui); + VDIVUW udivv4si3 {} + + const vuc __builtin_altivec_vexpandmb (vuc); + VEXPANDMB vec_expand_v16qi {} + + const vull __builtin_altivec_vexpandmd (vull); + VEXPANDMD vec_expand_v2di {} + + const vus __builtin_altivec_vexpandmh (vus); + VEXPANDMH vec_expand_v8hi {} + + const vuq __builtin_altivec_vexpandmq (vuq); + VEXPANDMQ vec_expand_v1ti {} + + const vui __builtin_altivec_vexpandmw (vui); + VEXPANDMW vec_expand_v4si {} + + const vull __builtin_altivec_vextddvhx (vull, vull, unsigned int); + VEXTRACTDR vextractrv2di {} + + const vull __builtin_altivec_vextddvlx (vull, vull, unsigned int); + VEXTRACTDL vextractlv2di {} + + const vull __builtin_altivec_vextdubvhx (vuc, vuc, unsigned int); + VEXTRACTBR vextractrv16qi {} + + const vull __builtin_altivec_vextdubvlx (vuc, vuc, unsigned int); + VEXTRACTBL vextractlv16qi {} + + const vull __builtin_altivec_vextduhvhx (vus, vus, unsigned int); + VEXTRACTHR vextractrv8hi {} + + const vull __builtin_altivec_vextduhvlx (vus, vus, unsigned int); + VEXTRACTHL vextractlv8hi {} + + const vull __builtin_altivec_vextduwvhx (vui, vui, unsigned int); + VEXTRACTWR vextractrv4si {} + + const vull __builtin_altivec_vextduwvlx (vui, vui, unsigned int); + VEXTRACTWL vextractlv4si {} + + const signed int __builtin_altivec_vextractmb (vsc); + VEXTRACTMB vec_extract_v16qi {} + + const signed int __builtin_altivec_vextractmd (vsll); + VEXTRACTMD vec_extract_v2di {} + + const signed int __builtin_altivec_vextractmh (vss); + VEXTRACTMH vec_extract_v8hi {} + + const signed int __builtin_altivec_vextractmq (vsq); + VEXTRACTMQ vec_extract_v1ti {} + + const signed int __builtin_altivec_vextractmw (vsi); + VEXTRACTMW vec_extract_v4si {} + + const unsigned long long __builtin_altivec_vgnb (vull, const int <2,7>); + VGNB vgnb {} + + const vuc __builtin_altivec_vinsgubvlx (unsigned int, vuc, unsigned int); + VINSERTGPRBL vinsertgl_v16qi {} + + const vsc __builtin_altivec_vinsgubvrx (signed int, vsc, signed int); + VINSERTGPRBR vinsertgr_v16qi {} + + const vull __builtin_altivec_vinsgudvlx (unsigned int, vull, unsigned int); + VINSERTGPRDL vinsertgl_v2di {} + + const vsll __builtin_altivec_vinsgudvrx (signed int, vsll, signed int); + VINSERTGPRDR vinsertgr_v2di {} + + const vus __builtin_altivec_vinsguhvlx (unsigned int, vus, unsigned int); + VINSERTGPRHL vinsertgl_v8hi {} + + const vss __builtin_altivec_vinsguhvrx (signed int, vss, signed int); + VINSERTGPRHR vinsertgr_v8hi {} + + const vui __builtin_altivec_vinsguwvlx (unsigned int, vui, unsigned int); + VINSERTGPRWL vinsertgl_v4si {} + + const vsi __builtin_altivec_vinsguwvrx (signed int, vsi, signed int); + VINSERTGPRWR vinsertgr_v4si {} + + const vuc __builtin_altivec_vinsvubvlx (vuc, vuc, unsigned int); + VINSERTVPRBL vinsertvl_v16qi {} + + const vsc __builtin_altivec_vinsvubvrx (vsc, vsc, signed int); + VINSERTVPRBR vinsertvr_v16qi {} + + const vus __builtin_altivec_vinsvuhvlx (vus, vus, unsigned int); + VINSERTVPRHL vinsertvl_v8hi {} + + const vss __builtin_altivec_vinsvuhvrx (vss, vss, signed int); + VINSERTVPRHR vinsertvr_v8hi {} + + const vui __builtin_altivec_vinsvuwvlx (vui, vui, unsigned int); + VINSERTVPRWL vinsertvl_v4si {} + + const vsi __builtin_altivec_vinsvuwvrx (vsi, vsi, signed int); + VINSERTVPRWR vinsertvr_v4si {} + + const vsll __builtin_altivec_vmodsd (vsll, vsll); + VMODSD modv2di3 {} + + const vsi __builtin_altivec_vmodsw (vsi, vsi); + VMODSW modv4si3 {} + + const vull __builtin_altivec_vmodud (vull, vull); + VMODUD umodv2di3 {} + + const vui __builtin_altivec_vmoduw (vui, vui); + VMODUW umodv4si3 {} + + const vsq __builtin_altivec_vmulesd (vsll, vsll); + VMULESD vec_widen_smult_even_v2di {} + + const vuq __builtin_altivec_vmuleud (vull, vull); + VMULEUD vec_widen_umult_even_v2di {} + + const vsll __builtin_altivec_vmulhsd (vsll, vsll); + VMULHSD smulv2di3_highpart {} + + const vsi __builtin_altivec_vmulhsw (vsi, vsi); + VMULHSW smulv4si3_highpart {} + + const vull __builtin_altivec_vmulhud (vull, vull); + VMULHUD umulv2di3_highpart {} + + const vui __builtin_altivec_vmulhuw (vui, vui); + VMULHUW umulv4si3_highpart {} + + const vsll __builtin_altivec_vmulld (vsll, vsll); + VMULLD mulv2di3 {} + + const vsq __builtin_altivec_vmulosd (vsll, vsll); + VMULOSD vec_widen_smult_odd_v2di {} + + const vuq __builtin_altivec_vmuloud (vull, vull); + VMULOUD vec_widen_umult_odd_v2di {} + + const vsq __builtin_altivec_vnor_v1ti (vsq, vsq); + VNOR_V1TI norv1ti3 {} + + const vuq __builtin_altivec_vnor_v1ti_uns (vuq, vuq); + VNOR_V1TI_UNS norv1ti3 {} + + const vull __builtin_altivec_vpdepd (vull, vull); + VPDEPD vpdepd {} + + const vull __builtin_altivec_vpextd (vull, vull); + VPEXTD vpextd {} + + const vull __builtin_altivec_vreplace_un_uv2di (vull, unsigned long long, const int<4>); + VREPLACE_UN_UV2DI vreplace_un_v2di {} + + const vui __builtin_altivec_vreplace_un_uv4si (vui, unsigned int, const int<4>); + VREPLACE_UN_UV4SI vreplace_un_v4si {} + + const vd __builtin_altivec_vreplace_un_v2df (vd, double, const int<4>); + VREPLACE_UN_V2DF vreplace_un_v2df {} + + const vsll __builtin_altivec_vreplace_un_v2di (vsll, signed long long, const int<4>); + VREPLACE_UN_V2DI vreplace_un_v2di {} + + const vf __builtin_altivec_vreplace_un_v4sf (vf, float, const int<4>); + VREPLACE_UN_V4SF vreplace_un_v4sf {} + + const vsi __builtin_altivec_vreplace_un_v4si (vsi, signed int, const int<4>); + VREPLACE_UN_V4SI vreplace_un_v4si {} + + const vull __builtin_altivec_vreplace_uv2di (vull, unsigned long long, const int<1>); + VREPLACE_ELT_UV2DI vreplace_elt_v2di {} + + const vui __builtin_altivec_vreplace_uv4si (vui, unsigned int, const int<2>); + VREPLACE_ELT_UV4SI vreplace_elt_v4si {} + + const vd __builtin_altivec_vreplace_v2df (vd, double, const int<1>); + VREPLACE_ELT_V2DF vreplace_elt_v2df {} + + const vsll __builtin_altivec_vreplace_v2di (vsll, signed long long, const int<1>); + VREPLACE_ELT_V2DI vreplace_elt_v2di {} + + const vf __builtin_altivec_vreplace_v4sf (vf, float, const int<2>); + VREPLACE_ELT_V4SF vreplace_elt_v4sf {} + + const vsi __builtin_altivec_vreplace_v4si (vsi, signed int, const int<2>); + VREPLACE_ELT_V4SI vreplace_elt_v4si {} + + const vsq __builtin_altivec_vrlq (vsq, vuq); + VRLQ vrotlv1ti3 {} + + const vsq __builtin_altivec_vrlqmi (vsq, vsq, vuq); + VRLQMI altivec_vrlqmi {} + + const vsq __builtin_altivec_vrlqnm (vsq, vuq); + VRLQNM altivec_vrlqnm {} + + const vsq __builtin_altivec_vsignext (vsll); + VSIGNEXTSD2Q vsignextend_v2di_v1ti {} + + const vsc __builtin_altivec_vsldb_v16qi (vsc, vsc, const int<3>); + VSLDB_V16QI vsldb_v16qi {} + + const vsll __builtin_altivec_vsldb_v2di (vsll, vsll, const int<3>); + VSLDB_V2DI vsldb_v2di {} + + const vsi __builtin_altivec_vsldb_v4si (vsi, vsi, const int<3>); + VSLDB_V4SI vsldb_v4si {} + + const vss __builtin_altivec_vsldb_v8hi (vss, vss, const int<3>); + VSLDB_V8HI vsldb_v8hi {} + + const vsq __builtin_altivec_vslq (vsq, vuq); + VSLQ vashlv1ti3 {} + + const vsq __builtin_altivec_vsraq (vsq, vuq); + VSRAQ vashrv1ti3 {} + + const vsc __builtin_altivec_vsrdb_v16qi (vsc, vsc, const int<3>); + VSRDB_V16QI vsrdb_v16qi {} + + const vsll __builtin_altivec_vsrdb_v2di (vsll, vsll, const int<3>); + VSRDB_V2DI vsrdb_v2di {} + + const vsi __builtin_altivec_vsrdb_v4si (vsi, vsi, const int<3>); + VSRDB_V4SI vsrdb_v4si {} + + const vss __builtin_altivec_vsrdb_v8hi (vss, vss, const int<3>); + VSRDB_V8HI vsrdb_v8hi {} + + const vsq __builtin_altivec_vsrq (vsq, vuq); + VSRQ vlshrv1ti3 {} + + const vsc __builtin_altivec_vstribl (vsc); + VSTRIBL vstril_v16qi {} + + const signed int __builtin_altivec_vstribl_p (vsc); + VSTRIBL_P vstril_p_v16qi {} + + const vsc __builtin_altivec_vstribr (vsc); + VSTRIBR vstrir_v16qi {} + + const signed int __builtin_altivec_vstribr_p (vsc); + VSTRIBR_P vstrir_p_v16qi {} + + const vss __builtin_altivec_vstrihl (vss); + VSTRIHL vstril_v8hi {} + + const signed int __builtin_altivec_vstrihl_p (vss); + VSTRIHL_P vstril_p_v8hi {} + + const vss __builtin_altivec_vstrihr (vss); + VSTRIHR vstrir_v8hi {} + + const signed int __builtin_altivec_vstrihr_p (vss); + VSTRIHR_P vstrir_p_v8hi {} + + const signed int __builtin_vsx_xvtlsbb_all_ones (vsc); + XVTLSBB_ONES xvtlsbbo {} + + const signed int __builtin_vsx_xvtlsbb_all_zeros (vsc); + XVTLSBB_ZEROS xvtlsbbz {} + + const vf __builtin_vsx_vxxsplti32dx_v4sf (vf, const int<1>, float); + VXXSPLTI32DX_V4SF xxsplti32dx_v4sf {} + + const vsi __builtin_vsx_vxxsplti32dx_v4si (vsi, const int<1>, signed int); + VXXSPLTI32DX_V4SI xxsplti32dx_v4si {} + + const vd __builtin_vsx_vxxspltidp (float); + VXXSPLTIDP xxspltidp_v2df {} + + const vf __builtin_vsx_vxxspltiw_v4sf (float); + VXXSPLTIW_V4SF xxspltiw_v4sf {} + + const vsi __builtin_vsx_vxxspltiw_v4si (signed int); + VXXSPLTIW_V4SI xxspltiw_v4si {} + + const vuc __builtin_vsx_xvcvbf16spn (vuc); + XVCVBF16SPN vsx_xvcvbf16spn {} + + const vuc __builtin_vsx_xvcvspbf16 (vuc); + XVCVSPBF16 vsx_xvcvspbf16 {} + + const vuc __builtin_vsx_xxblend_v16qi (vuc, vuc, vuc); + VXXBLEND_V16QI xxblend_v16qi {} + + const vd __builtin_vsx_xxblend_v2df (vd, vd, vd); + VXXBLEND_V2DF xxblend_v2df {} + + const vull __builtin_vsx_xxblend_v2di (vull, vull, vull); + VXXBLEND_V2DI xxblend_v2di {} + + const vf __builtin_vsx_xxblend_v4sf (vf, vf, vf); + VXXBLEND_V4SF xxblend_v4sf {} + + const vui __builtin_vsx_xxblend_v4si (vui, vui, vui); + VXXBLEND_V4SI xxblend_v4si {} + + const vus __builtin_vsx_xxblend_v8hi (vus, vus, vus); + VXXBLEND_V8HI xxblend_v8hi {} + + const vull __builtin_vsx_xxeval (vull, vull, vull, const int <8>); + XXEVAL xxeval {} + + const vuc __builtin_vsx_xxgenpcvm_v16qi (vuc, const int <2>); + XXGENPCVM_V16QI xxgenpcvm_v16qi {} + + const vull __builtin_vsx_xxgenpcvm_v2di (vull, const int <2>); + XXGENPCVM_V2DI xxgenpcvm_v2di {} + + const vui __builtin_vsx_xxgenpcvm_v4si (vui, const int <2>); + XXGENPCVM_V4SI xxgenpcvm_v4si {} + + const vus __builtin_vsx_xxgenpcvm_v8hi (vus, const int <2>); + XXGENPCVM_V8HI xxgenpcvm_v8hi {} + + const vuc __builtin_vsx_xxpermx_uv16qi (vuc, vuc, vuc, const int<3>); + XXPERMX_UV16QI xxpermx {} + + const vull __builtin_vsx_xxpermx_uv2di (vull, vull, vuc, const int<3>); + XXPERMX_UV2DI xxpermx {} + + const vui __builtin_vsx_xxpermx_uv4si (vui, vui, vuc, const int<3>); + XXPERMX_UV4SI xxpermx {} + + const vus __builtin_vsx_xxpermx_uv8hi (vus, vus, vuc, const int<3>); + XXPERMX_UV8HI xxpermx {} + + const vsc __builtin_vsx_xxpermx_v16qi (vsc, vsc, vuc, const int<3>); + XXPERMX_V16QI xxpermx {} + + const vd __builtin_vsx_xxpermx_v2df (vd, vd, vuc, const int<3>); + XXPERMX_V2DF xxpermx {} + + const vsll __builtin_vsx_xxpermx_v2di (vsll, vsll, vuc, const int<3>); + XXPERMX_V2DI xxpermx {} + + const vf __builtin_vsx_xxpermx_v4sf (vf, vf, vuc, const int<3>); + XXPERMX_V4SF xxpermx {} + + const vsi __builtin_vsx_xxpermx_v4si (vsi, vsi, vuc, const int<3>); + XXPERMX_V4SI xxpermx {} + + const vss __builtin_vsx_xxpermx_v8hi (vss, vss, vuc, const int<3>); + XXPERMX_V8HI xxpermx {} + + pure unsigned __int128 __builtin_altivec_ze_lxvrbx (signed long, const unsigned char *); + ZE_LXVRBX vsx_lxvrbx {lxvrze} + + pure unsigned __int128 __builtin_altivec_ze_lxvrhx (signed long, const unsigned short *); + ZE_LXVRHX vsx_lxvrhx {lxvrze} + + pure unsigned __int128 __builtin_altivec_ze_lxvrwx (signed long, const unsigned int *); + ZE_LXVRWX vsx_lxvrwx {lxvrze} + + pure unsigned __int128 __builtin_altivec_ze_lxvrdx (signed long, const unsigned long long *); + ZE_LXVRDX vsx_lxvrdx {lxvrze} + + +[power10-64] + const unsigned long long __builtin_cfuged (unsigned long long, unsigned long long); + CFUGED cfuged {} + + const unsigned long long __builtin_cntlzdm (unsigned long long, unsigned long long); + CNTLZDM cntlzdm {} + + const unsigned long long __builtin_cnttzdm (unsigned long long, unsigned long long); + CNTTZDM cnttzdm {} + + const unsigned long long __builtin_pdepd (unsigned long long, unsigned long long); + PDEPD pdepd {} + + const unsigned long long __builtin_pextd (unsigned long long, unsigned long long); + PEXTD pextd {} diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 3c3108a..fd7f24d 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -13294,6 +13294,7 @@ rs6000_init_builtins (void) { tree tdecl; tree ftype; + tree t; machine_mode mode; if (TARGET_DEBUG_BUILTIN) @@ -13304,25 +13305,63 @@ rs6000_init_builtins (void) V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector long" : "__vector long long", long_long_integer_type_node, 2); + ptr_V2DI_type_node + = build_pointer_type (build_qualified_type (V2DI_type_node, + TYPE_QUAL_CONST)); + V2DF_type_node = rs6000_vector_type ("__vector double", double_type_node, 2); + ptr_V2DF_type_node + = build_pointer_type (build_qualified_type (V2DF_type_node, + TYPE_QUAL_CONST)); + V4SI_type_node = rs6000_vector_type ("__vector signed int", intSI_type_node, 4); + ptr_V4SI_type_node + = build_pointer_type (build_qualified_type (V4SI_type_node, + TYPE_QUAL_CONST)); + V4SF_type_node = rs6000_vector_type ("__vector float", float_type_node, 4); + ptr_V4SF_type_node + = build_pointer_type (build_qualified_type (V4SF_type_node, + TYPE_QUAL_CONST)); + V8HI_type_node = rs6000_vector_type ("__vector signed short", intHI_type_node, 8); + ptr_V8HI_type_node + = build_pointer_type (build_qualified_type (V8HI_type_node, + TYPE_QUAL_CONST)); + V16QI_type_node = rs6000_vector_type ("__vector signed char", intQI_type_node, 16); + ptr_V16QI_type_node + = build_pointer_type (build_qualified_type (V16QI_type_node, + TYPE_QUAL_CONST)); unsigned_V16QI_type_node = rs6000_vector_type ("__vector unsigned char", unsigned_intQI_type_node, 16); + ptr_unsigned_V16QI_type_node + = build_pointer_type (build_qualified_type (unsigned_V16QI_type_node, + TYPE_QUAL_CONST)); + unsigned_V8HI_type_node = rs6000_vector_type ("__vector unsigned short", unsigned_intHI_type_node, 8); + ptr_unsigned_V8HI_type_node + = build_pointer_type (build_qualified_type (unsigned_V8HI_type_node, + TYPE_QUAL_CONST)); + unsigned_V4SI_type_node = rs6000_vector_type ("__vector unsigned int", unsigned_intSI_type_node, 4); + ptr_unsigned_V4SI_type_node + = build_pointer_type (build_qualified_type (unsigned_V4SI_type_node, + TYPE_QUAL_CONST)); + unsigned_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector unsigned long" : "__vector unsigned long long", long_long_unsigned_type_node, 2); + ptr_unsigned_V2DI_type_node + = build_pointer_type (build_qualified_type (unsigned_V2DI_type_node, + TYPE_QUAL_CONST)); opaque_V4SI_type_node = build_opaque_vector_type (intSI_type_node, 4); @@ -13336,9 +13375,15 @@ rs6000_init_builtins (void) { V1TI_type_node = rs6000_vector_type ("__vector __int128", intTI_type_node, 1); + ptr_V1TI_type_node + = build_pointer_type (build_qualified_type (V1TI_type_node, + TYPE_QUAL_CONST)); unsigned_V1TI_type_node = rs6000_vector_type ("__vector unsigned __int128", unsigned_intTI_type_node, 1); + ptr_unsigned_V1TI_type_node + = build_pointer_type (build_qualified_type (unsigned_V1TI_type_node, + TYPE_QUAL_CONST)); } /* The 'vector bool ...' types must be kept distinct from 'vector unsigned ...' @@ -13372,6 +13417,76 @@ rs6000_init_builtins (void) dfloat128_type_internal_node = dfloat128_type_node; void_type_internal_node = void_type_node; + ptr_intQI_type_node + = build_pointer_type (build_qualified_type (intQI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_uintQI_type_node + = build_pointer_type (build_qualified_type (uintQI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_intHI_type_node + = build_pointer_type (build_qualified_type (intHI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_uintHI_type_node + = build_pointer_type (build_qualified_type (uintHI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_intSI_type_node + = build_pointer_type (build_qualified_type (intSI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_uintSI_type_node + = build_pointer_type (build_qualified_type (uintSI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_intDI_type_node + = build_pointer_type (build_qualified_type (intDI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_uintDI_type_node + = build_pointer_type (build_qualified_type (uintDI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_intTI_type_node + = build_pointer_type (build_qualified_type (intTI_type_internal_node, + TYPE_QUAL_CONST)); + ptr_uintTI_type_node + = build_pointer_type (build_qualified_type (uintTI_type_internal_node, + TYPE_QUAL_CONST)); + + t = build_qualified_type (long_integer_type_internal_node, TYPE_QUAL_CONST); + ptr_long_integer_type_node = build_pointer_type (t); + + t = build_qualified_type (long_unsigned_type_internal_node, TYPE_QUAL_CONST); + ptr_long_unsigned_type_node = build_pointer_type (t); + + ptr_float_type_node + = build_pointer_type (build_qualified_type (float_type_internal_node, + TYPE_QUAL_CONST)); + ptr_double_type_node + = build_pointer_type (build_qualified_type (double_type_internal_node, + TYPE_QUAL_CONST)); + ptr_long_double_type_node + = build_pointer_type (build_qualified_type (long_double_type_internal_node, + TYPE_QUAL_CONST)); + if (dfloat64_type_node) + { + t = build_qualified_type (dfloat64_type_internal_node, TYPE_QUAL_CONST); + ptr_dfloat64_type_node = build_pointer_type (t); + } + else + ptr_dfloat64_type_node = NULL; + + if (dfloat128_type_node) + { + t = build_qualified_type (dfloat128_type_internal_node, TYPE_QUAL_CONST); + ptr_dfloat128_type_node = build_pointer_type (t); + } + else + ptr_dfloat128_type_node = NULL; + + t = build_qualified_type (long_long_integer_type_internal_node, + TYPE_QUAL_CONST); + ptr_long_long_integer_type_node = build_pointer_type (t); + + t = build_qualified_type (long_long_unsigned_type_internal_node, + TYPE_QUAL_CONST); + ptr_long_long_unsigned_type_node = build_pointer_type (t); + /* 128-bit floating point support. KFmode is IEEE 128-bit floating point. IFmode is the IBM extended 128-bit format that is a pair of doubles. TFmode will be either IEEE 128-bit floating point or the IBM double-double @@ -13399,7 +13514,8 @@ rs6000_init_builtins (void) SET_TYPE_MODE (ibm128_float_type_node, IFmode); layout_type (ibm128_float_type_node); } - + t = build_qualified_type (ibm128_float_type_node, TYPE_QUAL_CONST); + ptr_ibm128_float_type_node = build_pointer_type (t); lang_hooks.types.register_builtin_type (ibm128_float_type_node, "__ibm128"); @@ -13407,7 +13523,8 @@ rs6000_init_builtins (void) ieee128_float_type_node = long_double_type_node; else ieee128_float_type_node = float128_type_node; - + t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST); + ptr_ieee128_float_type_node = build_pointer_type (t); lang_hooks.types.register_builtin_type (ieee128_float_type_node, "__ieee128"); } @@ -13427,6 +13544,8 @@ rs6000_init_builtins (void) TYPE_USER_ALIGN (vector_pair_type_node) = 0; lang_hooks.types.register_builtin_type (vector_pair_type_node, "__vector_pair"); + t = build_qualified_type (vector_pair_type_node, TYPE_QUAL_CONST); + ptr_vector_pair_type_node = build_pointer_type (t); vector_quad_type_node = make_node (OPAQUE_TYPE); SET_TYPE_MODE (vector_quad_type_node, XOmode); @@ -13437,6 +13556,8 @@ rs6000_init_builtins (void) TYPE_USER_ALIGN (vector_quad_type_node) = 0; lang_hooks.types.register_builtin_type (vector_quad_type_node, "__vector_quad"); + t = build_qualified_type (vector_quad_type_node, TYPE_QUAL_CONST); + ptr_vector_quad_type_node = build_pointer_type (t); } /* Initialize the modes for builtin_function_type, mapping a machine mode to @@ -13487,18 +13608,41 @@ rs6000_init_builtins (void) bool_V16QI_type_node = rs6000_vector_type ("__vector __bool char", bool_char_type_node, 16); + ptr_bool_V16QI_type_node + = build_pointer_type (build_qualified_type (bool_V16QI_type_node, + TYPE_QUAL_CONST)); + bool_V8HI_type_node = rs6000_vector_type ("__vector __bool short", bool_short_type_node, 8); + ptr_bool_V8HI_type_node + = build_pointer_type (build_qualified_type (bool_V8HI_type_node, + TYPE_QUAL_CONST)); + bool_V4SI_type_node = rs6000_vector_type ("__vector __bool int", bool_int_type_node, 4); + ptr_bool_V4SI_type_node + = build_pointer_type (build_qualified_type (bool_V4SI_type_node, + TYPE_QUAL_CONST)); + bool_V2DI_type_node = rs6000_vector_type (TARGET_POWERPC64 ? "__vector __bool long" : "__vector __bool long long", bool_long_long_type_node, 2); + ptr_bool_V2DI_type_node + = build_pointer_type (build_qualified_type (bool_V2DI_type_node, + TYPE_QUAL_CONST)); + bool_V1TI_type_node = rs6000_vector_type ("__vector __bool __int128", intTI_type_node, 1); + ptr_bool_V1TI_type_node + = build_pointer_type (build_qualified_type (bool_V1TI_type_node, + TYPE_QUAL_CONST)); + pixel_V8HI_type_node = rs6000_vector_type ("__vector __pixel", pixel_type_node, 8); + ptr_pixel_V8HI_type_node + = build_pointer_type (build_qualified_type (pixel_V8HI_type_node, + TYPE_QUAL_CONST)); pcvoid_type_node = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST)); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index c5d20d2..3eba1c0 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2461,6 +2461,47 @@ enum rs6000_builtin_type_index RS6000_BTI_vector_pair, /* unsigned 256-bit types (vector pair). */ RS6000_BTI_vector_quad, /* unsigned 512-bit types (vector quad). */ RS6000_BTI_const_ptr_void, /* const pointer to void */ + RS6000_BTI_ptr_V16QI, + RS6000_BTI_ptr_V1TI, + RS6000_BTI_ptr_V2DI, + RS6000_BTI_ptr_V2DF, + RS6000_BTI_ptr_V4SI, + RS6000_BTI_ptr_V4SF, + RS6000_BTI_ptr_V8HI, + RS6000_BTI_ptr_unsigned_V16QI, + RS6000_BTI_ptr_unsigned_V1TI, + RS6000_BTI_ptr_unsigned_V8HI, + RS6000_BTI_ptr_unsigned_V4SI, + RS6000_BTI_ptr_unsigned_V2DI, + RS6000_BTI_ptr_bool_V16QI, + RS6000_BTI_ptr_bool_V8HI, + RS6000_BTI_ptr_bool_V4SI, + RS6000_BTI_ptr_bool_V2DI, + RS6000_BTI_ptr_bool_V1TI, + RS6000_BTI_ptr_pixel_V8HI, + RS6000_BTI_ptr_INTQI, + RS6000_BTI_ptr_UINTQI, + RS6000_BTI_ptr_INTHI, + RS6000_BTI_ptr_UINTHI, + RS6000_BTI_ptr_INTSI, + RS6000_BTI_ptr_UINTSI, + RS6000_BTI_ptr_INTDI, + RS6000_BTI_ptr_UINTDI, + RS6000_BTI_ptr_INTTI, + RS6000_BTI_ptr_UINTTI, + RS6000_BTI_ptr_long_integer, + RS6000_BTI_ptr_long_unsigned, + RS6000_BTI_ptr_float, + RS6000_BTI_ptr_double, + RS6000_BTI_ptr_long_double, + RS6000_BTI_ptr_dfloat64, + RS6000_BTI_ptr_dfloat128, + RS6000_BTI_ptr_ieee128_float, + RS6000_BTI_ptr_ibm128_float, + RS6000_BTI_ptr_vector_pair, + RS6000_BTI_ptr_vector_quad, + RS6000_BTI_ptr_long_long, + RS6000_BTI_ptr_long_long_unsigned, RS6000_BTI_MAX }; @@ -2517,6 +2558,47 @@ enum rs6000_builtin_type_index #define vector_pair_type_node (rs6000_builtin_types[RS6000_BTI_vector_pair]) #define vector_quad_type_node (rs6000_builtin_types[RS6000_BTI_vector_quad]) #define pcvoid_type_node (rs6000_builtin_types[RS6000_BTI_const_ptr_void]) +#define ptr_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V16QI]) +#define ptr_V1TI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V1TI]) +#define ptr_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V2DI]) +#define ptr_V2DF_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V2DF]) +#define ptr_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V4SI]) +#define ptr_V4SF_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V4SF]) +#define ptr_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_V8HI]) +#define ptr_unsigned_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_unsigned_V16QI]) +#define ptr_unsigned_V1TI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_unsigned_V1TI]) +#define ptr_unsigned_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_unsigned_V8HI]) +#define ptr_unsigned_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_unsigned_V4SI]) +#define ptr_unsigned_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_unsigned_V2DI]) +#define ptr_bool_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_bool_V16QI]) +#define ptr_bool_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_bool_V8HI]) +#define ptr_bool_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_bool_V4SI]) +#define ptr_bool_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_bool_V2DI]) +#define ptr_bool_V1TI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_bool_V1TI]) +#define ptr_pixel_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_pixel_V8HI]) +#define ptr_intQI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_INTQI]) +#define ptr_uintQI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_UINTQI]) +#define ptr_intHI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_INTHI]) +#define ptr_uintHI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_UINTHI]) +#define ptr_intSI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_INTSI]) +#define ptr_uintSI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_UINTSI]) +#define ptr_intDI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_INTDI]) +#define ptr_uintDI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_UINTDI]) +#define ptr_intTI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_INTTI]) +#define ptr_uintTI_type_node (rs6000_builtin_types[RS6000_BTI_ptr_UINTTI]) +#define ptr_long_integer_type_node (rs6000_builtin_types[RS6000_BTI_ptr_long_integer]) +#define ptr_long_unsigned_type_node (rs6000_builtin_types[RS6000_BTI_ptr_long_unsigned]) +#define ptr_float_type_node (rs6000_builtin_types[RS6000_BTI_ptr_float]) +#define ptr_double_type_node (rs6000_builtin_types[RS6000_BTI_ptr_double]) +#define ptr_long_double_type_node (rs6000_builtin_types[RS6000_BTI_ptr_long_double]) +#define ptr_dfloat64_type_node (rs6000_builtin_types[RS6000_BTI_ptr_dfloat64]) +#define ptr_dfloat128_type_node (rs6000_builtin_types[RS6000_BTI_ptr_dfloat128]) +#define ptr_ieee128_float_type_node (rs6000_builtin_types[RS6000_BTI_ptr_ieee128_float]) +#define ptr_ibm128_float_type_node (rs6000_builtin_types[RS6000_BTI_ptr_ibm128_float]) +#define ptr_vector_pair_type_node (rs6000_builtin_types[RS6000_BTI_ptr_vector_pair]) +#define ptr_vector_quad_type_node (rs6000_builtin_types[RS6000_BTI_ptr_vector_quad]) +#define ptr_long_long_integer_type_node (rs6000_builtin_types[RS6000_BTI_ptr_long_long]) +#define ptr_long_long_unsigned_type_node (rs6000_builtin_types[RS6000_BTI_ptr_long_long_unsigned]) extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX]; extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index e4ca6e9..bf033e3 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -374,7 +374,7 @@ UNSPEC_VDIVEU UNSPEC_XXEVAL UNSPEC_XXSPLTIW - UNSPEC_XXSPLTID + UNSPEC_XXSPLTIDP UNSPEC_XXSPLTI32DX UNSPEC_XXBLEND UNSPEC_XXPERMX @@ -6414,7 +6414,7 @@ UNSPEC_XXSPLTIW))] "TARGET_POWER10" "xxspltiw %x0,%1" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) (define_expand "xxspltiw_v4sf" @@ -6434,14 +6434,14 @@ UNSPEC_XXSPLTIW))] "TARGET_POWER10" "xxspltiw %x0,%1" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) ;; XXSPLTIDP built-in function support (define_expand "xxspltidp_v2df" [(set (match_operand:V2DF 0 "register_operand" ) (unspec:V2DF [(match_operand:SF 1 "const_double_operand")] - UNSPEC_XXSPLTID))] + UNSPEC_XXSPLTIDP))] "TARGET_POWER10" { long value = rs6000_const_f32_to_i32 (operands[1]); @@ -6452,10 +6452,10 @@ (define_insn "xxspltidp_v2df_inst" [(set (match_operand:V2DF 0 "register_operand" "=wa") (unspec:V2DF [(match_operand:SI 1 "c32bit_cint_operand" "n")] - UNSPEC_XXSPLTID))] + UNSPEC_XXSPLTIDP))] "TARGET_POWER10" "xxspltidp %x0,%1" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) ;; XXSPLTI32DX built-in function support @@ -6476,7 +6476,7 @@ GEN_INT (index), operands[3])); DONE; } - [(set_attr "type" "vecsimple")]) + [(set_attr "type" "vecperm")]) (define_insn "xxsplti32dx_v4si_inst" [(set (match_operand:V4SI 0 "register_operand" "=wa") @@ -6486,7 +6486,7 @@ UNSPEC_XXSPLTI32DX))] "TARGET_POWER10" "xxsplti32dx %x0,%2,%3" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) (define_expand "xxsplti32dx_v4sf" @@ -6515,7 +6515,7 @@ UNSPEC_XXSPLTI32DX))] "TARGET_POWER10" "xxsplti32dx %x0,%2,%3" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) ;; XXBLEND built-in function support @@ -6527,7 +6527,7 @@ UNSPEC_XXBLEND))] "TARGET_POWER10" "xxblendv<VM3_char> %x0,%x1,%x2,%x3" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) ;; XXPERMX built-in function support @@ -6562,7 +6562,7 @@ DONE; } - [(set_attr "type" "vecsimple")]) + [(set_attr "type" "vecperm")]) (define_insn "xxpermx_inst" [(set (match_operand:V2DI 0 "register_operand" "+v") @@ -6573,7 +6573,7 @@ UNSPEC_XXPERMX))] "TARGET_POWER10" "xxpermx %x0,%x1,%x2,%x3,%4" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) ;; XXEVAL built-in function support @@ -6586,6 +6586,6 @@ UNSPEC_XXEVAL))] "TARGET_POWER10" "xxeval %0,%1,%2,%3,%4" - [(set_attr "type" "vecsimple") + [(set_attr "type" "vecperm") (set_attr "prefixed" "yes")]) diff --git a/gcc/coretypes.h b/gcc/coretypes.h index 406572e..726fcad 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -154,6 +154,7 @@ struct cl_option_handlers; struct diagnostic_context; class pretty_printer; class diagnostic_event_id_t; +typedef const char * (*diagnostic_input_charset_callback)(const char *); template<typename T> struct array_traits; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ddea2a2..0b92ee4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2021-08-25 Andrew Pinski <apinski@marvell.com> + + PR c++/66590 + * cp-objcp-common.c (cxx_block_may_fallthru): Handle + CLEANUP_STMT for the case which will be try/finally. + +2021-08-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/102019 + * init.c (build_value_init_noctor): Ignore unnamed zero-width + bitfields. + 2021-08-23 Jakub Jelinek <jakub@redhat.com> * parser.c (cp_parser_omp_clause_num_tasks, diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index 98fd962..28f2d7b 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -317,6 +317,15 @@ cxx_block_may_fallthru (const_tree stmt) return true; return block_may_fallthru (ELSE_CLAUSE (stmt)); + case CLEANUP_STMT: + /* Just handle the try/finally cases. */ + if (!CLEANUP_EH_ONLY (stmt)) + { + return (block_may_fallthru (CLEANUP_BODY (stmt)) + && block_may_fallthru (CLEANUP_EXPR (stmt))); + } + return true; + default: return c_block_may_fallthru (stmt); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 229c84e..1426f9a 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -427,6 +427,11 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) == NULL_TREE)) continue; + /* Ignore unnamed zero-width bitfields. */ + if (DECL_UNNAMED_BIT_FIELD (field) + && integer_zerop (DECL_SIZE (field))) + continue; + /* We could skip vfields and fields of types with user-defined constructors, but I think that won't improve performance at all; it should be simpler in general just diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 3bf2eec..db85ffc 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,10 @@ +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * d-lang.cc (d_input_charset_callback): New function. + (d_init): Call new function + diagnostic_initialize_input_context(). + 2021-07-30 Iain Buclaw <ibuclaw@gdcproject.org> * expr.cc (binary_op): Remove dead code. diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc index 4386a48..fa29a46a 100644 --- a/gcc/d/d-lang.cc +++ b/gcc/d/d-lang.cc @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "print-tree.h" #include "debug.h" +#include "input.h" #include "d-tree.h" #include "id.h" @@ -362,6 +363,19 @@ d_option_lang_mask (void) return CL_D; } +/* Implements input charset and BOM skipping configuration for + diagnostics. */ +static const char *d_input_charset_callback (const char * /*filename*/) +{ + /* TODO: The input charset is automatically determined by code in + dmd/dmodule.c based on the contents of the file. If this detection + logic were factored out and could be reused here, then we would be able + to return UTF-16 or UTF-32 as needed here. For now, we return always + NULL, which means no conversion is necessary, i.e. the input is assumed + to be UTF-8 when diagnostics read this file. */ + return nullptr; +} + /* Implements the lang_hooks.init routine for language D. */ static bool @@ -373,6 +387,11 @@ d_init (void) Expression::_init (); Objc::_init (); + /* Diagnostics input init, to enable BOM skipping and + input charset conversion. */ + diagnostic_initialize_input_context (global_dc, + d_input_charset_callback, true); + /* Back-end init. */ global_binding_level = ggc_cleared_alloc <binding_level> (); current_binding_level = global_binding_level; diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 8361f68..b3afbea 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -293,6 +293,17 @@ diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */) = determine_url_format ((diagnostic_url_rule_t) value); } +/* Create the file_cache, if not already created, and tell it how to + translate files on input. */ +void diagnostic_initialize_input_context (diagnostic_context *context, + diagnostic_input_charset_callback ccb, + bool should_skip_bom) +{ + if (!context->m_file_cache) + context->m_file_cache = new file_cache; + context->m_file_cache->initialize_input_context (ccb, should_skip_bom); +} + /* Do any cleaning up required after the last diagnostic is emitted. */ void diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 7227dae..f90d20a 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -446,6 +446,25 @@ extern void diagnostic_show_locus (diagnostic_context *, diagnostic_t diagnostic_kind); extern void diagnostic_show_any_path (diagnostic_context *, diagnostic_info *); +/* Because we read source files a second time after the frontend did it the + first time, we need to know how the frontend handled things like character + set conversion and UTF-8 BOM stripping, in order to make everything + consistent. This function needs to be called by each frontend that requires + non-default behavior, to inform the diagnostics infrastructure how input is + to be processed. The default behavior is to do no conversion and not to + strip a UTF-8 BOM. + + The callback should return the input charset to be used to convert the given + file's contents to UTF-8, or it should return NULL if no conversion is needed + for this file. SHOULD_SKIP_BOM only applies in case no conversion was + performed, and if true, it will cause a UTF-8 BOM to be skipped at the + beginning of the file. (In case a conversion was performed, the BOM is + rather skipped as part of the conversion process.) */ + +void diagnostic_initialize_input_context (diagnostic_context *context, + diagnostic_input_charset_callback ccb, + bool should_skip_bom); + /* Force diagnostics controlled by OPTIDX to be kind KIND. */ extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, int /* optidx */, diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 671b9bf..f4f6121 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2782,16 +2782,16 @@ On some targets the attributes also accept an integer argument to specify a priority to control the order in which constructor and destructor functions are run. A constructor with a smaller priority number runs before a constructor with a larger -priority number; the opposite relationship holds for destructors. So, -if you have a constructor that allocates a resource and a destructor -that deallocates the same resource, both functions typically have the -same priority. The priorities for constructor and destructor -functions are the same as those specified for namespace-scope C++ -objects (@pxref{C++ Attributes}). However, at present, the order in which -constructors for C++ objects with static storage duration and functions -decorated with attribute @code{constructor} are invoked is unspecified. -In mixed declarations, attribute @code{init_priority} can be used to -impose a specific ordering. +priority number; the opposite relationship holds for destructors. Note +that priorities 0-100 are reserved. So, if you have a constructor that +allocates a resource and a destructor that deallocates the same +resource, both functions typically have the same priority. The +priorities for constructor and destructor functions are the same as +those specified for namespace-scope C++ objects (@pxref{C++ Attributes}). +However, at present, the order in which constructors for C++ objects +with static storage duration and functions decorated with attribute +@code{constructor} are invoked is unspecified. In mixed declarations, +attribute @code{init_priority} can be used to impose a specific ordering. Using the argument forms of the @code{constructor} and @code{destructor} attributes on targets where the feature is not supported is rejected with diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 164f586..185b7d2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -13386,6 +13386,10 @@ Setting to 0 disables the analysis completely. @item modref-max-escape-points Specifies the maximum number of escape points tracked by modref per SSA-name. +@item modref-max-adjustments +Specifies the maximum number the access range is enlarged during modref dataflow +analysis. + @item profile-func-internal-id A parameter to control whether to use function internal id in profile database lookup. If the value is 0, the compiler uses an id that diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 307886d..9679f35 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * cpp.c (gfc_cpp_post_options): Call new function + diagnostic_initialize_input_context(). + +2021-08-24 Harald Anlauf <anlauf@gmx.de> + + PR fortran/98411 + * trans-decl.c (gfc_finish_var_decl): Adjust check to handle + implicit SAVE as well as variables in the main program. Improve + warning message text. + 2021-08-23 Tobias Burnus <tobias@codesourcery.com> * openmp.c (gfc_match_dupl_check, gfc_match_dupl_memorder, diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 419cd6a..83c4517 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -493,6 +493,12 @@ gfc_cpp_post_options (void) cpp_post_options (cpp_in); + + /* Let diagnostics infrastructure know how to convert input files the same + way libcpp will do it, namely, with no charset conversion but with + skipping of a UTF-8 BOM if present. */ + diagnostic_initialize_input_context (global_dc, nullptr, true); + gfc_cpp_register_include_paths (); } diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 784f7b6..bed61e2 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -743,8 +743,10 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) /* Keep variables larger than max-stack-var-size off stack. */ if (!(sym->ns->proc_name && sym->ns->proc_name->attr.recursive) + && !(sym->ns->proc_name && sym->ns->proc_name->attr.is_main_program) && !sym->attr.automatic && sym->attr.save != SAVE_EXPLICIT + && sym->attr.save != SAVE_IMPLICIT && INTEGER_CST_P (DECL_SIZE_UNIT (decl)) && !gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl)) /* Put variable length auto array pointers always into stack. */ @@ -757,13 +759,17 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) { if (flag_max_stack_var_size > 0) gfc_warning (OPT_Wsurprising, - "Array %qs at %L is larger than limit set by" - " %<-fmax-stack-var-size=%>, moved from stack to static" - " storage. This makes the procedure unsafe when called" - " recursively, or concurrently from multiple threads." - " Consider using %<-frecursive%>, or increase the" - " %<-fmax-stack-var-size=%> limit, or change the code to" - " use an ALLOCATABLE array.", + "Array %qs at %L is larger than limit set by " + "%<-fmax-stack-var-size=%>, moved from stack to static " + "storage. This makes the procedure unsafe when called " + "recursively, or concurrently from multiple threads. " + "Consider increasing the %<-fmax-stack-var-size=%> " + "limit (or use %<-frecursive%>, which implies " + "unlimited %<-fmax-stack-var-size%>) - or change the " + "code to use an ALLOCATABLE array. If the variable is " + "never accessed concurrently, this warning can be " + "ignored, and the variable could also be declared with " + "the SAVE attribute.", sym->name, &sym->declared_at); TREE_STATIC (decl) = 1; diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index 4138d05..facf981 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -628,20 +628,32 @@ ssa_global_cache::clear () void ssa_global_cache::dump (FILE *f) { - unsigned x; - int_range_max r; - fprintf (f, "Non-varying global ranges:\n"); - fprintf (f, "=========================:\n"); - for ( x = 1; x < num_ssa_names; x++) - if (gimple_range_ssa_p (ssa_name (x)) && - get_global_range (r, ssa_name (x)) && !r.varying_p ()) - { - print_generic_expr (f, ssa_name (x), TDF_NONE); - fprintf (f, " : "); - r.dump (f); - fprintf (f, "\n"); - } - fputc ('\n', f); + /* Cleared after the table header has been printed. */ + bool print_header = true; + for (unsigned x = 1; x < num_ssa_names; x++) + { + int_range_max r; + if (gimple_range_ssa_p (ssa_name (x)) && + get_global_range (r, ssa_name (x)) && !r.varying_p ()) + { + if (print_header) + { + /* Print the header only when there's something else + to print below. */ + fprintf (f, "Non-varying global ranges:\n"); + fprintf (f, "=========================:\n"); + print_header = false; + } + + print_generic_expr (f, ssa_name (x), TDF_NONE); + fprintf (f, " : "); + r.dump (f); + fprintf (f, "\n"); + } + } + + if (!print_header) + fputc ('\n', f); } // -------------------------------------------------------------------------- diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index ef3afea..d74cea3 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -259,16 +259,11 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) void gimple_ranger::export_global_ranges () { - unsigned x; - int_range_max r; - if (dump_file) - { - fprintf (dump_file, "Exported global range table\n"); - fprintf (dump_file, "===========================\n"); - } - - for ( x = 1; x < num_ssa_names; x++) + /* Cleared after the table header has been printed. */ + bool print_header = true; + for (unsigned x = 1; x < num_ssa_names; x++) { + int_range_max r; tree name = ssa_name (x); if (name && !SSA_NAME_IN_FREE_LIST (name) && gimple_range_ssa_p (name) @@ -276,21 +271,29 @@ gimple_ranger::export_global_ranges () && !r.varying_p()) { bool updated = update_global_range (r, name); + if (!updated || !dump_file || !(dump_flags & TDF_DETAILS)) + continue; - if (updated && dump_file) + if (print_header) { - value_range vr = r; - print_generic_expr (dump_file, name , TDF_SLIM); - fprintf (dump_file, " --> "); - vr.dump (dump_file); + /* Print the header only when there's something else + to print below. */ + fprintf (dump_file, "Exported global range table:\n"); + fprintf (dump_file, "============================\n"); + print_header = false; + } + + value_range vr = r; + print_generic_expr (dump_file, name , TDF_SLIM); + fprintf (dump_file, " : "); + vr.dump (dump_file); + fprintf (dump_file, "\n"); + int_range_max same = vr; + if (same != r) + { + fprintf (dump_file, " irange : "); + r.dump (dump_file); fprintf (dump_file, "\n"); - int_range_max same = vr; - if (same != r) - { - fprintf (dump_file, " irange : "); - r.dump (dump_file); - fprintf (dump_file, "\n"); - } } } } diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 4a2dd9a..5df97a6 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -704,6 +704,15 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, if (opt == OPT_Wstringop_overread) { bool maybe = pad && pad->src.phi (); + if (maybe) + { + /* Issue a "maybe" warning only if the PHI refers to objects + at least one of which has more space remaining than the bound. + Otherwise, if the bound is greater, use the definitive form. */ + offset_int remmax = pad->src.size_remaining (); + if (remmax < wi::to_offset (bndrng[0])) + maybe = false; + } if (tree_int_cst_lt (maxobjsize, bndrng[0])) { @@ -788,6 +797,15 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, } bool maybe = pad && pad->dst.phi (); + if (maybe) + { + /* Issue a "maybe" warning only if the PHI refers to objects + at least one of which has more space remaining than the bound. + Otherwise, if the bound is greater, use the definitive form. */ + offset_int remmax = pad->dst.size_remaining (); + if (remmax < wi::to_offset (bndrng[0])) + maybe = false; + } if (tree_int_cst_lt (maxobjsize, bndrng[0])) { if (bndrng[0] == bndrng[1]) @@ -1418,7 +1436,7 @@ check_access (GimpleOrTree exp, tree dstwrite, location_t loc = get_location (exp); tree size = dstsize; if (pad && pad->mode == access_read_only) - size = wide_int_to_tree (sizetype, pad->src.sizrng[1]); + size = wide_int_to_tree (sizetype, pad->src.size_remaining ()); if (range[0] && maxread && tree_fits_uhwi_p (size)) { diff --git a/gcc/input.c b/gcc/input.c index de20d98..4b80986 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "intl.h" #include "diagnostic.h" -#include "diagnostic-core.h" #include "selftest.h" #include "cpplib.h" @@ -30,6 +29,20 @@ along with GCC; see the file COPYING3. If not see #define HAVE_ICONV 0 #endif +/* Input charset configuration. */ +static const char *default_charset_callback (const char *) +{ + return nullptr; +} + +void +file_cache::initialize_input_context (diagnostic_input_charset_callback ccb, + bool should_skip_bom) +{ + in_context.ccb = (ccb ? ccb : default_charset_callback); + in_context.should_skip_bom = should_skip_bom; +} + /* This is a cache used by get_next_line to store the content of a file to be searched for file lines. */ class file_cache_slot @@ -51,7 +64,8 @@ public: void inc_use_count () { m_use_count++; } - void create (const char *file_path, FILE *fp, unsigned highest_use_count); + bool create (const file_cache::input_context &in_context, + const char *file_path, FILE *fp, unsigned highest_use_count); void evict (); private: @@ -110,6 +124,10 @@ public: far. */ char *m_data; + /* The allocated buffer to be freed may start a little earlier than DATA, + e.g. if a UTF8 BOM was skipped at the beginning. */ + int m_alloc_offset; + /* The size of the DATA array above.*/ size_t m_size; @@ -147,6 +165,17 @@ public: doesn't explode. We thus scale total_lines down to line_record_size. */ vec<line_info, va_heap> m_line_record; + + void offset_buffer (int offset) + { + gcc_assert (offset < 0 ? m_alloc_offset + offset >= 0 + : (size_t) offset <= m_size); + gcc_assert (m_data); + m_alloc_offset += offset; + m_data += offset; + m_size -= offset; + } + }; /* Current position in real source file. */ @@ -419,21 +448,25 @@ file_cache::add_file (const char *file_path) unsigned highest_use_count = 0; file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count); - r->create (file_path, fp, highest_use_count); + if (!r->create (in_context, file_path, fp, highest_use_count)) + return NULL; return r; } /* Populate this slot for use on FILE_PATH and FP, dropping any existing cached content within it. */ -void -file_cache_slot::create (const char *file_path, FILE *fp, +bool +file_cache_slot::create (const file_cache::input_context &in_context, + const char *file_path, FILE *fp, unsigned highest_use_count) { m_file_path = file_path; if (m_fp) fclose (m_fp); m_fp = fp; + if (m_alloc_offset) + offset_buffer (-m_alloc_offset); m_nb_read = 0; m_line_start_idx = 0; m_line_num = 0; @@ -443,6 +476,36 @@ file_cache_slot::create (const char *file_path, FILE *fp, m_use_count = ++highest_use_count; m_total_lines = total_lines_num (file_path); m_missing_trailing_newline = true; + + + /* Check the input configuration to determine if we need to do any + transformations, such as charset conversion or BOM skipping. */ + if (const char *input_charset = in_context.ccb (file_path)) + { + /* Need a full-blown conversion of the input charset. */ + fclose (m_fp); + m_fp = NULL; + const cpp_converted_source cs + = cpp_get_converted_source (file_path, input_charset); + if (!cs.data) + return false; + if (m_data) + XDELETEVEC (m_data); + m_data = cs.data; + m_nb_read = m_size = cs.len; + m_alloc_offset = cs.data - cs.to_free; + } + else if (in_context.should_skip_bom) + { + if (read_data ()) + { + const int offset = cpp_check_utf8_bom (m_data, m_nb_read); + offset_buffer (offset); + m_nb_read -= offset; + } + } + + return true; } /* file_cache's ctor. */ @@ -450,6 +513,7 @@ file_cache_slot::create (const char *file_path, FILE *fp, file_cache::file_cache () : m_file_slots (new file_cache_slot[num_file_slots]) { + initialize_input_context (nullptr, false); } /* file_cache's dtor. */ @@ -478,8 +542,8 @@ file_cache::lookup_or_add_file (const char *file_path) file_cache_slot::file_cache_slot () : m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0), - m_size (0), m_nb_read (0), m_line_start_idx (0), m_line_num (0), - m_total_lines (0), m_missing_trailing_newline (true) + m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0), + m_line_num (0), m_total_lines (0), m_missing_trailing_newline (true) { m_line_record.create (0); } @@ -495,6 +559,7 @@ file_cache_slot::~file_cache_slot () } if (m_data) { + offset_buffer (-m_alloc_offset); XDELETEVEC (m_data); m_data = 0; } @@ -509,7 +574,7 @@ file_cache_slot::~file_cache_slot () bool file_cache_slot::needs_read_p () const { - return (m_nb_read == 0 + return m_fp && (m_nb_read == 0 || m_nb_read == m_size || (m_line_start_idx >= m_nb_read - 1)); } @@ -531,9 +596,20 @@ file_cache_slot::maybe_grow () if (!needs_grow_p ()) return; - size_t size = m_size == 0 ? buffer_size : m_size * 2; - m_data = XRESIZEVEC (char, m_data, size); - m_size = size; + if (!m_data) + { + gcc_assert (m_size == 0 && m_alloc_offset == 0); + m_size = buffer_size; + m_data = XNEWVEC (char, m_size); + } + else + { + const int offset = m_alloc_offset; + offset_buffer (-offset); + m_size *= 2; + m_data = XRESIZEVEC (char, m_data, m_size); + offset_buffer (offset); + } } /* Read more data into the cache. Extends the cache if need be. @@ -632,7 +708,7 @@ file_cache_slot::get_next_line (char **line, ssize_t *line_len) m_missing_trailing_newline = false; } - if (ferror (m_fp)) + if (m_fp && ferror (m_fp)) return false; /* At this point, we've found the end of the of line. It either diff --git a/gcc/input.h b/gcc/input.h index bbcec84..e688107 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -111,6 +111,15 @@ class file_cache file_cache_slot *lookup_or_add_file (const char *file_path); void forcibly_evict_file (const char *file_path); + /* See comments in diagnostic.h about the input conversion context. */ + struct input_context + { + diagnostic_input_charset_callback ccb; + bool should_skip_bom; + }; + void initialize_input_context (diagnostic_input_charset_callback ccb, + bool should_skip_bom); + private: file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count); file_cache_slot *add_file (const char *file_path); @@ -119,6 +128,7 @@ class file_cache private: static const size_t num_file_slots = 16; file_cache_slot *m_file_slots; + input_context in_context; }; extern expanded_location diff --git a/gcc/ipa-modref-tree.c b/gcc/ipa-modref-tree.c index 64e57f5..69395b0 100644 --- a/gcc/ipa-modref-tree.c +++ b/gcc/ipa-modref-tree.c @@ -41,7 +41,7 @@ test_insert_search_collapse () ASSERT_FALSE (t->every_base); /* Insert into an empty tree. */ - t->insert (1, 2, a); + t->insert (1, 2, a, false); ASSERT_NE (t->bases, NULL); ASSERT_EQ (t->bases->length (), 1); ASSERT_FALSE (t->every_base); @@ -59,7 +59,7 @@ test_insert_search_collapse () ASSERT_EQ (ref_node->ref, 2); /* Insert when base exists but ref does not. */ - t->insert (1, 3, a); + t->insert (1, 3, a, false); ASSERT_NE (t->bases, NULL); ASSERT_EQ (t->bases->length (), 1); ASSERT_EQ (t->search (1), base_node); @@ -72,7 +72,7 @@ test_insert_search_collapse () /* Insert when base and ref exist, but access is not dominated by nor dominates other accesses. */ - t->insert (1, 2, a); + t->insert (1, 2, a, false); ASSERT_EQ (t->bases->length (), 1); ASSERT_EQ (t->search (1), base_node); @@ -80,12 +80,12 @@ test_insert_search_collapse () ASSERT_NE (ref_node, NULL); /* Insert when base and ref exist and access is dominated. */ - t->insert (1, 2, a); + t->insert (1, 2, a, false); ASSERT_EQ (t->search (1), base_node); ASSERT_EQ (base_node->search (2), ref_node); /* Insert ref to trigger ref list collapse for base 1. */ - t->insert (1, 4, a); + t->insert (1, 4, a, false); ASSERT_EQ (t->search (1), base_node); ASSERT_EQ (base_node->refs, NULL); ASSERT_EQ (base_node->search (2), NULL); @@ -93,7 +93,7 @@ test_insert_search_collapse () ASSERT_TRUE (base_node->every_ref); /* Further inserts to collapsed ref list are ignored. */ - t->insert (1, 5, a); + t->insert (1, 5, a, false); ASSERT_EQ (t->search (1), base_node); ASSERT_EQ (base_node->refs, NULL); ASSERT_EQ (base_node->search (2), NULL); @@ -101,13 +101,13 @@ test_insert_search_collapse () ASSERT_TRUE (base_node->every_ref); /* Insert base to trigger base list collapse. */ - t->insert (5, 6, a); + t->insert (5, 6, a, false); ASSERT_TRUE (t->every_base); ASSERT_EQ (t->bases, NULL); ASSERT_EQ (t->search (1), NULL); /* Further inserts to collapsed base list are ignored. */ - t->insert (7, 8, a); + t->insert (7, 8, a, false); ASSERT_TRUE (t->every_base); ASSERT_EQ (t->bases, NULL); ASSERT_EQ (t->search (1), NULL); @@ -123,22 +123,22 @@ test_merge () modref_access_node a = unspecified_modref_access_node; t1 = new modref_tree<alias_set_type>(3, 4, 1); - t1->insert (1, 1, a); - t1->insert (1, 2, a); - t1->insert (1, 3, a); - t1->insert (2, 1, a); - t1->insert (3, 1, a); + t1->insert (1, 1, a, false); + t1->insert (1, 2, a, false); + t1->insert (1, 3, a, false); + t1->insert (2, 1, a, false); + t1->insert (3, 1, a, false); t2 = new modref_tree<alias_set_type>(10, 10, 10); - t2->insert (1, 2, a); - t2->insert (1, 3, a); - t2->insert (1, 4, a); - t2->insert (3, 2, a); - t2->insert (3, 3, a); - t2->insert (3, 4, a); - t2->insert (3, 5, a); - - t1->merge (t2, NULL); + t2->insert (1, 2, a, false); + t2->insert (1, 3, a, false); + t2->insert (1, 4, a, false); + t2->insert (3, 2, a, false); + t2->insert (3, 3, a, false); + t2->insert (3, 4, a, false); + t2->insert (3, 5, a, false); + + t1->merge (t2, NULL, false); ASSERT_FALSE (t1->every_base); ASSERT_NE (t1->bases, NULL); diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h index 2e26b75..6f6932f 100644 --- a/gcc/ipa-modref-tree.h +++ b/gcc/ipa-modref-tree.h @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see Again ref is an template to allow LTO streaming. 3) Access: this level represent info about individual accesses. Presently we record whether access is through a dereference of a function parameter + and if so we record the access range. */ #ifndef GCC_MODREF_TREE_H @@ -57,6 +58,9 @@ struct GTY(()) modref_access_node a function parameter. */ int parm_index; bool parm_offset_known; + /* Number of times interval was extended during dataflow. + This has to be limited in order to keep dataflow finite. */ + unsigned char adjustments; /* Return true if access node holds no useful info. */ bool useful_p () const @@ -84,6 +88,8 @@ struct GTY(()) modref_access_node && !known_eq (parm_offset, a.parm_offset)) return false; } + if (range_info_useful_p () != a.range_info_useful_p ()) + return false; if (range_info_useful_p () && (!known_eq (a.offset, offset) || !known_eq (a.size, size) @@ -92,16 +98,24 @@ struct GTY(()) modref_access_node return true; } /* Return true A is a subaccess. */ - bool contains (modref_access_node &a) const + bool contains (const modref_access_node &a) const { - if (parm_index != a.parm_index) - return false; + poly_int64 aoffset_adj = 0; if (parm_index >= 0) { - if (parm_offset_known - && (!a.parm_offset_known - || !known_eq (parm_offset, a.parm_offset))) + if (parm_index != a.parm_index) return false; + if (parm_offset_known) + { + if (!a.parm_offset_known) + return false; + /* Accesses are never below parm_offset, so look + for smaller offset. */ + if (!known_le (parm_offset, a.parm_offset)) + return false; + aoffset_adj = (a.parm_offset - parm_offset) + << LOG2_BITS_PER_UNIT; + } } if (range_info_useful_p ()) { @@ -111,20 +125,181 @@ struct GTY(()) modref_access_node to fit the store, so smaller or unknown sotre is more general than large store. */ if (known_size_p (size) - && !known_le (size, a.size)) + && (!known_size_p (a.size) + || !known_le (size, a.size))) return false; if (known_size_p (max_size)) - return known_subrange_p (a.offset, a.max_size, offset, max_size); + return known_subrange_p (a.offset + aoffset_adj, + a.max_size, offset, max_size); else - return known_le (offset, a.offset); + return known_le (offset, a.offset + aoffset_adj); } return true; } + /* Update access range to new parameters. + If RECORD_ADJUSTMENTS is true, record number of changes in the access + and if threshold is exceeded start dropping precision + so only constantly many updates are possible. This makes dataflow + to converge. */ + void update (poly_int64 parm_offset1, + poly_int64 offset1, poly_int64 size1, poly_int64 max_size1, + bool record_adjustments) + { + if (known_eq (offset, offset1) + && known_eq (size, size1) + && known_eq (max_size, max_size1)) + return; + if (!record_adjustments + || (++adjustments) < param_modref_max_adjustments) + { + parm_offset = parm_offset1; + offset = offset1; + size = size1; + max_size = max_size1; + } + else + { + if (dump_file) + fprintf (dump_file, + "--param param=modref-max-adjustments limit reached:"); + if (!known_eq (parm_offset, parm_offset1)) + { + if (dump_file) + fprintf (dump_file, " parm_offset cleared"); + parm_offset_known = false; + } + if (!known_eq (size, size1)) + { + size = -1; + if (dump_file) + fprintf (dump_file, " size cleared"); + } + if (!known_eq (max_size, max_size1)) + { + max_size = -1; + if (dump_file) + fprintf (dump_file, " max_size cleared"); + } + if (!known_eq (offset, offset1)) + { + offset = 0; + if (dump_file) + fprintf (dump_file, " offset cleared"); + } + if (dump_file) + fprintf (dump_file, "\n"); + } + } + /* Merge in access A if it is possible to do without losing + precision. Return true if successful. + If RECORD_ADJUSTMENTs is true, remember how many interval + was prolonged and punt when there are too many. */ + bool merge (const modref_access_node &a, bool record_adjustments) + { + poly_int64 aoffset_adj = 0, offset_adj = 0; + poly_int64 new_parm_offset = parm_offset; + + /* We assume that containment was tested earlier. */ + gcc_checking_assert (!contains (a) && !a.contains (*this)); + if (parm_index >= 0) + { + if (parm_index != a.parm_index) + return false; + if (parm_offset_known) + { + if (!a.parm_offset_known) + return false; + if (known_le (a.parm_offset, parm_offset)) + { + offset_adj = (parm_offset - a.parm_offset) + << LOG2_BITS_PER_UNIT; + aoffset_adj = 0; + new_parm_offset = a.parm_offset; + } + else if (known_le (parm_offset, a.parm_offset)) + { + aoffset_adj = (a.parm_offset - parm_offset) + << LOG2_BITS_PER_UNIT; + offset_adj = 0; + } + else + return false; + } + } + /* See if we can merge ranges. */ + if (range_info_useful_p ()) + { + poly_int64 offset1 = offset + offset_adj; + poly_int64 aoffset1 = a.offset + aoffset_adj; + + /* In this case we have containment that should be + handled earlier. */ + gcc_checking_assert (a.range_info_useful_p ()); + + /* If a.size is less specified than size, merge only + if intervals are otherwise equivalent. */ + if (known_size_p (size) + && (!known_size_p (a.size) || known_lt (a.size, size))) + { + if (((known_size_p (max_size) || known_size_p (a.max_size)) + && !known_eq (max_size, a.max_size)) + || !known_eq (offset1, aoffset1)) + return false; + update (new_parm_offset, offset1, a.size, max_size, + record_adjustments); + return true; + } + /* If sizes are same, we can extend the interval. */ + if ((known_size_p (size) || known_size_p (a.size)) + && !known_eq (size, a.size)) + return false; + if (known_le (offset1, aoffset1)) + { + if (!known_size_p (max_size)) + { + update (new_parm_offset, offset1, size, max_size, + record_adjustments); + return true; + } + else if (known_ge (offset1 + max_size, aoffset1)) + { + poly_int64 new_max_size = max_size; + if (known_le (max_size, a.max_size + aoffset1 - offset1)) + new_max_size = a.max_size + aoffset1 - offset1; + update (new_parm_offset, offset1, size, new_max_size, + record_adjustments); + return true; + } + } + else if (known_le (aoffset1, offset1)) + { + if (!known_size_p (a.max_size)) + { + update (new_parm_offset, aoffset1, size, a.max_size, + record_adjustments); + return true; + } + else if (known_ge (aoffset1 + a.max_size, offset1)) + { + poly_int64 new_max_size = a.max_size; + if (known_le (a.max_size, max_size + offset1 - aoffset1)) + new_max_size = max_size + offset1 - aoffset1; + update (new_parm_offset, aoffset1, size, new_max_size, + record_adjustments); + return true; + } + } + return false; + } + update (new_parm_offset, offset + offset_adj, + size, max_size, record_adjustments); + return true; + } }; /* Access node specifying no useful info. */ const modref_access_node unspecified_modref_access_node - = {0, -1, -1, 0, -1, false}; + = {0, -1, -1, 0, -1, false, 0}; template <typename T> struct GTY((user)) modref_ref_node @@ -149,8 +324,10 @@ struct GTY((user)) modref_ref_node /* Insert access with OFFSET and SIZE. Collapse tree if it has more than MAX_ACCESSES entries. + If RECORD_ADJUSTMENTs is true avoid too many interval extensions. Return true if record was changed. */ - bool insert_access (modref_access_node a, size_t max_accesses) + bool insert_access (modref_access_node a, size_t max_accesses, + bool record_adjustments) { /* If this base->ref pair has no access information, bail out. */ if (every_access) @@ -176,7 +353,17 @@ struct GTY((user)) modref_ref_node return false; if (a.contains (*a2)) { - *a2 = a; + a.adjustments = 0; + a2->parm_index = a.parm_index; + a2->parm_offset_known = a.parm_offset_known; + a2->update (a.parm_offset, a.offset, a.size, a.max_size, + record_adjustments); + try_merge_with (i); + return true; + } + if (a2->merge (a, record_adjustments)) + { + try_merge_with (i); return true; } gcc_checking_assert (!(a == *a2)); @@ -192,9 +379,28 @@ struct GTY((user)) modref_ref_node collapse (); return true; } + a.adjustments = 0; vec_safe_push (accesses, a); return true; } +private: + /* Try to optimize the access list after entry INDEX was modified. */ + void + try_merge_with (size_t index) + { + modref_access_node *a2; + size_t i; + + FOR_EACH_VEC_SAFE_ELT (accesses, i, a2) + if (i != index) + if ((*accesses)[index].contains (*a2) + || (*accesses)[index].merge (*a2, false)) + { + if (index == accesses->length () - 1) + index = i; + accesses->unordered_remove (i); + } + } }; /* Base of an access. */ @@ -342,7 +548,8 @@ struct GTY((user)) modref_tree /* Insert memory access to the tree. Return true if something changed. */ - bool insert (T base, T ref, modref_access_node a) + bool insert (T base, T ref, modref_access_node a, + bool record_adjustments) { if (every_base) return false; @@ -387,7 +594,8 @@ struct GTY((user)) modref_tree { if (ref_node->every_access) return changed; - changed |= ref_node->insert_access (a, max_accesses); + changed |= ref_node->insert_access (a, max_accesses, + record_adjustments); /* See if we failed to add useful access. */ if (ref_node->every_access) { @@ -456,7 +664,8 @@ struct GTY((user)) modref_tree PARM_MAP, if non-NULL, maps parm indexes of callee to caller. -2 is used to signalize that parameter is local and does not need to be tracked. Return true if something has changed. */ - bool merge (modref_tree <T> *other, vec <modref_parm_map> *parm_map) + bool merge (modref_tree <T> *other, vec <modref_parm_map> *parm_map, + bool record_accesses) { if (!other || every_base) return false; @@ -501,7 +710,8 @@ struct GTY((user)) modref_tree { changed |= insert (base_node->base, ref_node->ref, - unspecified_modref_access_node); + unspecified_modref_access_node, + record_accesses); } else FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node) @@ -525,7 +735,8 @@ struct GTY((user)) modref_tree = (*parm_map) [a.parm_index].parm_index; } } - changed |= insert (base_node->base, ref_node->ref, a); + changed |= insert (base_node->base, ref_node->ref, a, + record_accesses); } } } @@ -537,7 +748,7 @@ struct GTY((user)) modref_tree /* Copy OTHER to THIS. */ void copy_from (modref_tree <T> *other) { - merge (other, NULL); + merge (other, NULL, false); } /* Search BASE in tree; return NULL if failed. */ diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 6ab687a..0d5ab9c 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -426,6 +426,8 @@ dump_access (modref_access_node *a, FILE *out) print_dec ((poly_int64_pod)a->size, out, SIGNED); fprintf (out, " max_size:"); print_dec ((poly_int64_pod)a->max_size, out, SIGNED); + if (a->adjustments) + fprintf (out, " adjusted %i times", a->adjustments); } fprintf (out, "\n"); } @@ -656,7 +658,7 @@ get_access (ao_ref *ref) base = ao_ref_base (ref); modref_access_node a = {ref->offset, ref->size, ref->max_size, - 0, -1, false}; + 0, -1, false, 0}; if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF) { tree memref = base; @@ -708,7 +710,7 @@ record_access (modref_records *tt, ao_ref *ref) fprintf (dump_file, " - Recording base_set=%i ref_set=%i parm=%i\n", base_set, ref_set, a.parm_index); } - tt->insert (base_set, ref_set, a); + tt->insert (base_set, ref_set, a, false); } /* IPA version of record_access_tree. */ @@ -774,7 +776,7 @@ record_access_lto (modref_records_lto *tt, ao_ref *ref) a.parm_index); } - tt->insert (base_type, ref_type, a); + tt->insert (base_type, ref_type, a, false); } /* Returns true if and only if we should store the access to EXPR. @@ -858,12 +860,15 @@ parm_map_for_arg (gimple *stmt, int i) /* Merge side effects of call STMT to function with CALLEE_SUMMARY int CUR_SUMMARY. Return true if something changed. - If IGNORE_STORES is true, do not merge stores. */ + If IGNORE_STORES is true, do not merge stores. + If RECORD_ADJUSTMENTS is true cap number of adjustments to + a given access to make dataflow finite. */ bool merge_call_side_effects (modref_summary *cur_summary, gimple *stmt, modref_summary *callee_summary, - bool ignore_stores, cgraph_node *callee_node) + bool ignore_stores, cgraph_node *callee_node, + bool record_adjustments) { auto_vec <modref_parm_map, 32> parm_map; bool changed = false; @@ -902,11 +907,13 @@ merge_call_side_effects (modref_summary *cur_summary, fprintf (dump_file, "\n"); /* Merge with callee's summary. */ - changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map); + changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map, + record_adjustments); if (!ignore_stores) { changed |= cur_summary->stores->merge (callee_summary->stores, - &parm_map); + &parm_map, + record_adjustments); if (!cur_summary->writes_errno && callee_summary->writes_errno) { @@ -941,7 +948,7 @@ get_access_for_fnspec (gcall *call, attr_fnspec &fnspec, } modref_access_node a = {0, -1, -1, map.parm_offset, map.parm_index, - map.parm_offset_known}; + map.parm_offset_known, 0}; poly_int64 size_hwi; if (size && poly_int_tree_p (size, &size_hwi) @@ -1044,12 +1051,14 @@ process_fnspec (modref_summary *cur_summary, cur_summary->loads->insert (0, 0, get_access_for_fnspec (call, fnspec, i, - map)); + map), + false); if (cur_summary_lto) cur_summary_lto->loads->insert (0, 0, get_access_for_fnspec (call, fnspec, i, - map)); + map), + false); } } if (ignore_stores) @@ -1077,12 +1086,14 @@ process_fnspec (modref_summary *cur_summary, cur_summary->stores->insert (0, 0, get_access_for_fnspec (call, fnspec, i, - map)); + map), + false); if (cur_summary_lto) cur_summary_lto->stores->insert (0, 0, get_access_for_fnspec (call, fnspec, i, - map)); + map), + false); } if (fnspec.errno_maybe_written_p () && flag_errno_math) { @@ -1168,7 +1179,7 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto, } merge_call_side_effects (cur_summary, stmt, callee_summary, ignore_stores, - callee_node); + callee_node, false); return true; } @@ -2134,6 +2145,7 @@ analyze_function (function *f, bool ipa) if (!ipa) { bool changed = true; + bool first = true; while (changed) { changed = false; @@ -2144,13 +2156,14 @@ analyze_function (function *f, bool ipa) ignore_stores_p (current_function_decl, gimple_call_flags (recursive_calls[i])), - fnode); + fnode, !first); if (!summary->useful_p (ecf_flags, false)) { remove_summary (lto, nolto, ipa); return; } } + first = false; } } if (summary && !summary->useful_p (ecf_flags)) @@ -2501,11 +2514,11 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, } } modref_access_node a = {offset, size, max_size, parm_offset, - parm_index, parm_offset_known}; + parm_index, parm_offset_known, false}; if (nolto_ref_node) - nolto_ref_node->insert_access (a, max_accesses); + nolto_ref_node->insert_access (a, max_accesses, false); if (lto_ref_node) - lto_ref_node->insert_access (a, max_accesses); + lto_ref_node->insert_access (a, max_accesses, false); } } } @@ -3187,16 +3200,18 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge) if (!ignore_stores) { if (to_info && callee_info) - to_info->stores->merge (callee_info->stores, &parm_map); + to_info->stores->merge (callee_info->stores, &parm_map, false); if (to_info_lto && callee_info_lto) - to_info_lto->stores->merge (callee_info_lto->stores, &parm_map); + to_info_lto->stores->merge (callee_info_lto->stores, &parm_map, + false); } if (!(flags & (ECF_CONST | ECF_NOVOPS))) { if (to_info && callee_info) - to_info->loads->merge (callee_info->loads, &parm_map); + to_info->loads->merge (callee_info->loads, &parm_map, false); if (to_info_lto && callee_info_lto) - to_info_lto->loads->merge (callee_info_lto->loads, &parm_map); + to_info_lto->loads->merge (callee_info_lto->loads, &parm_map, + false); } } @@ -3346,7 +3361,7 @@ get_access_for_fnspec (cgraph_edge *e, attr_fnspec &fnspec, size = TYPE_SIZE_UNIT (get_parm_type (e->callee->decl, i)); modref_access_node a = {0, -1, -1, map.parm_offset, map.parm_index, - map.parm_offset_known}; + map.parm_offset_known, 0}; poly_int64 size_hwi; if (size && poly_int_tree_p (size, &size_hwi) @@ -3399,10 +3414,10 @@ propagate_unknown_call (cgraph_node *node, } if (cur_summary) changed |= cur_summary->loads->insert - (0, 0, get_access_for_fnspec (e, fnspec, i, map)); + (0, 0, get_access_for_fnspec (e, fnspec, i, map), false); if (cur_summary_lto) changed |= cur_summary_lto->loads->insert - (0, 0, get_access_for_fnspec (e, fnspec, i, map)); + (0, 0, get_access_for_fnspec (e, fnspec, i, map), false); } } if (ignore_stores_p (node->decl, ecf_flags)) @@ -3429,10 +3444,10 @@ propagate_unknown_call (cgraph_node *node, } if (cur_summary) changed |= cur_summary->stores->insert - (0, 0, get_access_for_fnspec (e, fnspec, i, map)); + (0, 0, get_access_for_fnspec (e, fnspec, i, map), false); if (cur_summary_lto) changed |= cur_summary_lto->stores->insert - (0, 0, get_access_for_fnspec (e, fnspec, i, map)); + (0, 0, get_access_for_fnspec (e, fnspec, i, map), false); } } if (fnspec.errno_maybe_written_p () && flag_errno_math) @@ -3491,6 +3506,7 @@ static void modref_propagate_in_scc (cgraph_node *component_node) { bool changed = true; + bool first = true; int iteration = 0; while (changed) @@ -3628,11 +3644,12 @@ modref_propagate_in_scc (cgraph_node *component_node) if (callee_summary) { changed |= cur_summary->loads->merge - (callee_summary->loads, &parm_map); + (callee_summary->loads, &parm_map, !first); if (!ignore_stores) { changed |= cur_summary->stores->merge - (callee_summary->stores, &parm_map); + (callee_summary->stores, &parm_map, + !first); if (!cur_summary->writes_errno && callee_summary->writes_errno) { @@ -3644,11 +3661,13 @@ modref_propagate_in_scc (cgraph_node *component_node) if (callee_summary_lto) { changed |= cur_summary_lto->loads->merge - (callee_summary_lto->loads, &parm_map); + (callee_summary_lto->loads, &parm_map, + !first); if (!ignore_stores) { changed |= cur_summary_lto->stores->merge - (callee_summary_lto->stores, &parm_map); + (callee_summary_lto->stores, &parm_map, + !first); if (!cur_summary_lto->writes_errno && callee_summary_lto->writes_errno) { @@ -3674,6 +3693,7 @@ modref_propagate_in_scc (cgraph_node *component_node) } } iteration++; + first = false; } if (dump_file) fprintf (dump_file, diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c index 6c05658..28d5f95 100644 --- a/gcc/multiple_target.c +++ b/gcc/multiple_target.c @@ -166,9 +166,8 @@ create_dispatcher_calls (struct cgraph_node *node) } } - symtab->change_decl_assembler_name (node->decl, - clone_function_name_numbered ( - node->decl, "default")); + tree fname = clone_function_name (node->decl, "default"); + symtab->change_decl_assembler_name (node->decl, fname); if (node->definition) { @@ -309,9 +308,9 @@ create_target_clone (cgraph_node *node, bool definition, char *name, if (definition) { - new_node = node->create_version_clone_with_body (vNULL, NULL, - NULL, NULL, - NULL, name, attributes); + new_node + = node->create_version_clone_with_body (vNULL, NULL, NULL, NULL, NULL, + name, attributes, false); if (new_node == NULL) return NULL; new_node->force_output = true; @@ -322,9 +321,8 @@ create_target_clone (cgraph_node *node, bool definition, char *name, new_node = cgraph_node::get_create (new_decl); DECL_ATTRIBUTES (new_decl) = attributes; /* Generate a new name for the new version. */ - symtab->change_decl_assembler_name (new_node->decl, - clone_function_name_numbered ( - node->decl, name)); + tree fname = clone_function_name (node->decl, name); + symtab->change_decl_assembler_name (new_node->decl, fname); } return new_node; } diff --git a/gcc/params.opt b/gcc/params.opt index f414dc1..cec43d2 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -1013,6 +1013,10 @@ Maximum depth of DFS walk used by modref escape analysis. Common Joined UInteger Var(param_modref_max_escape_points) Init(256) Param Optimization Maximum number of escape points tracked by modref per SSA-name. +-param=modref-max-adjustments= +Common Joined UInteger Var(param_modref_max_adjustments) Init(8) IntegerRange (0, 254) Param Optimization +Maximum number of times a given range is adjusted during the dataflow + -param=tm-max-aggregate-size= Common Joined UInteger Var(param_tm_max_aggregate_size) Init(9) Param Optimization Size in bytes after which thread-local aggregates should be instrumented with the logging functions instead of save/restore pairs. diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index 99caf78..ba8f8a9 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -634,10 +634,10 @@ access_ref::phi () const return as_a <gphi *> (def_stmt); } -/* Determine and return the largest object to which *THIS. If *THIS - refers to a PHI and PREF is nonnull, fill *PREF with the details - of the object determined by compute_objsize(ARG, OSTYPE) for each - PHI argument ARG. */ +/* Determine and return the largest object to which *THIS refers. If + *THIS refers to a PHI and PREF is nonnull, fill *PREF with the details + of the object determined by compute_objsize(ARG, OSTYPE) for each PHI + argument ARG. */ tree access_ref::get_ref (vec<access_ref> *all_refs, @@ -659,21 +659,25 @@ access_ref::get_ref (vec<access_ref> *all_refs, if (!psnlim->visit_phi (ref)) return NULL_TREE; - /* Reflects the range of offsets of all PHI arguments refer to the same - object (i.e., have the same REF). */ - access_ref same_ref; - /* The conservative result of the PHI reflecting the offset and size - of the largest PHI argument, regardless of whether or not they all - refer to the same object. */ pointer_query empty_qry; if (!qry) qry = &empty_qry; + /* The conservative result of the PHI reflecting the offset and size + of the largest PHI argument, regardless of whether or not they all + refer to the same object. */ access_ref phi_ref; if (pref) { + /* The identity of the object has not been determined yet but + PREF->REF is set by the caller to the PHI for convenience. + The size is negative/invalid and the offset is zero (it's + updated only after the identity of the object has been + established). */ + gcc_assert (pref->sizrng[0] < 0); + gcc_assert (pref->offrng[0] == 0 && pref->offrng[1] == 0); + phi_ref = *pref; - same_ref = *pref; } /* Set if any argument is a function array (or VLA) parameter not @@ -682,8 +686,6 @@ access_ref::get_ref (vec<access_ref> *all_refs, /* The size of the smallest object referenced by the PHI arguments. */ offset_int minsize = 0; const offset_int maxobjsize = wi::to_offset (max_object_size ()); - /* The offset of the PHI, not reflecting those of its arguments. */ - const offset_int orng[2] = { phi_ref.offrng[0], phi_ref.offrng[1] }; const unsigned nargs = gimple_phi_num_args (phi_stmt); for (unsigned i = 0; i < nargs; ++i) @@ -695,28 +697,31 @@ access_ref::get_ref (vec<access_ref> *all_refs, /* A PHI with all null pointer arguments. */ return NULL_TREE; - /* Add PREF's offset to that of the argument. */ - phi_arg_ref.add_offset (orng[0], orng[1]); if (TREE_CODE (arg) == SSA_NAME) qry->put_ref (arg, phi_arg_ref); if (all_refs) all_refs->safe_push (phi_arg_ref); - const bool arg_known_size = (phi_arg_ref.sizrng[0] != 0 - || phi_arg_ref.sizrng[1] != maxobjsize); - parmarray |= phi_arg_ref.parmarray; const bool nullp = integer_zerop (arg) && (i || i + 1 < nargs); if (phi_ref.sizrng[0] < 0) { + /* If PHI_REF doesn't contain a meaningful result yet set it + to the result for the first argument. */ if (!nullp) - same_ref = phi_arg_ref; - phi_ref = phi_arg_ref; + phi_ref = phi_arg_ref; + + /* Set if the current argument refers to one or more objects of + known size (or range of sizes), as opposed to referring to + one or more unknown object(s). */ + const bool arg_known_size = (phi_arg_ref.sizrng[0] != 0 + || phi_arg_ref.sizrng[1] != maxobjsize); if (arg_known_size) minsize = phi_arg_ref.sizrng[0]; + continue; } @@ -740,8 +745,10 @@ access_ref::get_ref (vec<access_ref> *all_refs, offset_int phirem[2]; phirem[1] = phi_ref.size_remaining (phirem); - if (phi_arg_ref.ref != same_ref.ref) - same_ref.ref = NULL_TREE; + /* Reset the PHI's BASE0 flag if any of the nonnull arguments + refers to an object at an unknown offset. */ + if (!phi_arg_ref.base0) + phi_ref.base0 = false; if (phirem[1] < argrem[1] || (phirem[1] == argrem[1] @@ -749,32 +756,13 @@ access_ref::get_ref (vec<access_ref> *all_refs, /* Use the argument with the most space remaining as the result, or the larger one if the space is equal. */ phi_ref = phi_arg_ref; - - /* Set SAME_REF.OFFRNG to the maximum range of all arguments. */ - if (phi_arg_ref.offrng[0] < same_ref.offrng[0]) - same_ref.offrng[0] = phi_arg_ref.offrng[0]; - if (same_ref.offrng[1] < phi_arg_ref.offrng[1]) - same_ref.offrng[1] = phi_arg_ref.offrng[1]; } - if (!same_ref.ref && same_ref.offrng[0] != 0) - /* Clear BASE0 if not all the arguments refer to the same object and - if not all their offsets are zero-based. This allows the final - PHI offset to out of bounds for some arguments but not for others - (or negative even of all the arguments are BASE0), which is overly - permissive. */ - phi_ref.base0 = false; - - if (same_ref.ref) - phi_ref = same_ref; - else - { - /* Replace the lower bound of the largest argument with the size - of the smallest argument, and set PARMARRAY if any argument - was one. */ - phi_ref.sizrng[0] = minsize; - phi_ref.parmarray = parmarray; - } + /* Replace the lower bound of the largest argument with the size + of the smallest argument, and set PARMARRAY if any argument + was one. */ + phi_ref.sizrng[0] = minsize; + phi_ref.parmarray = parmarray; if (phi_ref.sizrng[0] < 0) { @@ -804,6 +792,14 @@ access_ref::size_remaining (offset_int *pmin /* = NULL */) const if (!pmin) pmin = &minbuf; + if (sizrng[0] < 0) + { + /* If the identity of the object hasn't been determined return + the maximum size range. */ + *pmin = 0; + return wi::to_offset (max_object_size ()); + } + /* add_offset() ensures the offset range isn't inverted. */ gcc_checking_assert (offrng[0] <= offrng[1]); @@ -1597,6 +1593,11 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, { pref->ref = ptr; + /* Reset the offset in case it was set by a prior call and not + cleared by the caller. The offset is only adjusted after + the identity of the object has been determined. */ + pref->offrng[0] = pref->offrng[1] = 0; + if (!addr && POINTER_TYPE_P (TREE_TYPE (ptr))) { /* Set the maximum size if the reference is to the pointer @@ -1607,6 +1608,9 @@ compute_objsize_r (tree ptr, int ostype, access_ref *pref, return true; } + /* Valid offsets into the object are nonnegative. */ + pref->base0 = true; + if (tree size = decl_init_size (ptr, false)) if (TREE_CODE (size) == INTEGER_CST) { @@ -1960,6 +1964,11 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, { pointer_query qry; qry.rvals = rvals; + + /* Clear and invalidate in case *PREF is being reused. */ + pref->offrng[0] = pref->offrng[1] = 0; + pref->sizrng[0] = pref->sizrng[1] = -1; + ssa_name_limit_t snlim; if (!compute_objsize_r (ptr, ostype, pref, snlim, &qry)) return NULL_TREE; @@ -1982,6 +1991,10 @@ compute_objsize (tree ptr, int ostype, access_ref *pref, pointer_query *ptr_qry) else ptr_qry = &qry; + /* Clear and invalidate in case *PREF is being reused. */ + pref->offrng[0] = pref->offrng[1] = 0; + pref->sizrng[0] = pref->sizrng[1] = -1; + ssa_name_limit_t snlim; if (!compute_objsize_r (ptr, ostype, pref, snlim, ptr_qry)) return NULL_TREE; diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 8eea9fb..c81e27e 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -841,7 +841,7 @@ simplify_context::simplify_truncation (machine_mode mode, rtx op, { unsigned int int_op_prec = GET_MODE_PRECISION (int_op_mode); unsigned int subreg_prec = GET_MODE_PRECISION (subreg_mode); - if (int_op_prec > subreg_mode) + if (int_op_prec > subreg_prec) { if (int_mode == subreg_mode) return SUBREG_REG (op); @@ -851,7 +851,7 @@ simplify_context::simplify_truncation (machine_mode mode, rtx op, } /* Simplification of (truncate:A (subreg:B X:C 0)) where A is narrower than B and B is narrower than C. */ - else if (int_op_prec < subreg_mode + else if (int_op_prec < subreg_prec && GET_MODE_PRECISION (int_mode) < int_op_prec) return simplify_gen_unary (TRUNCATE, int_mode, SUBREG_REG (op), subreg_mode); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5c49bd3..251af30 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,158 @@ +2021-08-25 Martin Sebor <msebor@redhat.com> + + * gcc.dg/tree-ssa/evrp1.c: Add -details to dump option. + * gcc.dg/tree-ssa/evrp2.c: Same. + * gcc.dg/tree-ssa/evrp3.c: Same. + * gcc.dg/tree-ssa/evrp4.c: Same. + * gcc.dg/tree-ssa/evrp6.c: Same. + * gcc.dg/tree-ssa/pr64130.c: Same. + +2021-08-25 Michael Meissner <meissner@linux.ibm.com> + + PR target/94630 + * gcc.target/powerpc/pr70117.c: Specify that we need the long double + type to be IBM 128-bit. Remove the code to use __ibm128. + * c-c++-common/dfp/convert-bfp-11.c: Specify that we need the long + double type to be IBM 128-bit. Run the test at -O2 optimization. + * lib/target-supports.exp (add_options_for_long_double_ibm128): New + function. + (check_effective_target_long_double_ibm128): New function. + (add_options_for_long_double_ieee128): New function. + (check_effective_target_long_double_ieee128): New function. + (add_options_for_long_double_64bit): New function. + (check_effective_target_long_double_64bit): New function. + +2021-08-25 Andrew Pinski <apinski@marvell.com> + + PR c++/66590 + * g++.dg/warn/Wreturn-5.C: New test. + +2021-08-25 Jan Hubicka <hubicka@ucw.cz> + + * gcc.dg/ipa/modref-1.c: Update testcase. + * gcc.dg/tree-ssa/modref-4.c: Update testcase. + * gcc.dg/tree-ssa/modref-8.c: New test. + +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * gcc.dg/diagnostic-input-charset-1.c: New test. + * gcc.dg/diagnostic-input-utf8-bom.c: New test. + +2021-08-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102046 + * gcc.dg/vect/pr102046.c: New testcase. + +2021-08-25 Hongyu Wang <hongyu.wang@intel.com> + + PR target/101716 + * gcc.target/i386/pr101716.c: New test. + +2021-08-25 Jiufu Guo <guojiufu@linux.ibm.com> + + PR tree-optimization/101145 + * gcc.dg/vect/pr101145.c: New test. + * gcc.dg/vect/pr101145.inc: New test. + * gcc.dg/vect/pr101145_1.c: New test. + * gcc.dg/vect/pr101145_2.c: New test. + * gcc.dg/vect/pr101145_3.c: New test. + * gcc.dg/vect/pr101145inf.c: New test. + * gcc.dg/vect/pr101145inf.inc: New test. + * gcc.dg/vect/pr101145inf_1.c: New test. + +2021-08-25 konglin1 <lingling.kong@intel.com> + + PR target/101471 + * gcc.target/i386/avx512f-pr101471.c: New test. + +2021-08-25 Kewen Lin <linkw@linux.ibm.com> + + * gcc.target/powerpc/unpack-vectorize-1.c: New test. + * gcc.target/powerpc/unpack-vectorize-1.h: New test. + * gcc.target/powerpc/unpack-vectorize-2.c: New test. + * gcc.target/powerpc/unpack-vectorize-2.h: New test. + * gcc.target/powerpc/unpack-vectorize-3.c: New test. + * gcc.target/powerpc/unpack-vectorize-3.h: New test. + * gcc.target/powerpc/unpack-vectorize-run-1.c: New test. + * gcc.target/powerpc/unpack-vectorize-run-2.c: New test. + * gcc.target/powerpc/unpack-vectorize-run-3.c: New test. + * gcc.target/powerpc/unpack-vectorize.h: New test. + +2021-08-25 liuhongt <hongtao.liu@intel.com> + + PR target/101989 + * gcc.target/i386/avx2-shiftqihi-constant-1.c: Add -mno-avx512f. + * gcc.target/i386/sse2-shiftqihi-constant-1.c: Add -mno-avx + +2021-08-24 Harald Anlauf <anlauf@gmx.de> + + PR fortran/98411 + * gfortran.dg/pr98411.f90: Adjust testcase options to restrict to + F2008, and verify case of implicit SAVE. + +2021-08-24 Martin Sebor <msebor@redhat.com> + + PR middle-end/101600 + PR middle-end/101977 + * g++.dg/pr100574.C: Prune out valid warning. + * gcc.dg/pr20126.c: Same. + * gcc.dg/Wstringop-overread.c: Adjust text of expected warnings. + Add new instances. + * gcc.dg/warn-strnlen-no-nul.c: Same. + * g++.dg/warn/Warray-bounds-26.C: New test. + * gcc.dg/Warray-bounds-88.c: New test. + +2021-08-24 Andrew MacLeod <amacleod@redhat.com> + + * gcc.dg/predict-1.c: Disable evrp. + * gcc.dg/tree-ssa/evrp-trans.c: New. + +2021-08-24 H.J. Lu <hjl.tools@gmail.com> + + PR target/102021 + * gcc.target/i386/pr100865-10b.c: Expect vzeroupper. + * gcc.target/i386/pr100865-4b.c: Likewise. + * gcc.target/i386/pr100865-6b.c: Expect vmovdqu and vzeroupper. + * gcc.target/i386/pr100865-7b.c: Likewise. + * gcc.target/i386/pr102021.c: New test. + +2021-08-24 Richard Earnshaw <rearnsha@arm.com> + + PR target/102035 + * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-13a.c: New test. + * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-7a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/soft/cmse-8a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-7a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/softfp-sp/cmse-8a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-13a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-7a.c: Likewise. + * gcc.target/arm/cmse/mainline/8_1m/softfp/cmse-8a.c: Likewise. + +2021-08-24 Richard Earnshaw <rearnsha@arm.com> + + * lib/target-supports.exp (check_effective_target_arm_cmse_hw): + Check the CMSE feature register, rather than relying on the + SG operation causing an execution fault. + +2021-08-24 liuhongt <hongtao.liu@intel.com> + + PR target/101989 + * gcc.target/i386/pr101989-broadcast-1.c: New test. + +2021-08-24 liuhongt <hongtao.liu@intel.com> + + PR target/101989 + * gcc.target/i386/pr101989-1.c: New test. + * gcc.target/i386/pr101989-2.c: New test. + * gcc.target/i386/avx512bw-shiftqihi-constant-1.c: Adjust testcase. + +2021-08-24 Roger Sayle <roger@nextmovesoftware.com> + Jakub Jelinek <jakub@redhat.com> + + PR middle-end/102029 + * gcc.dg/fold-convlshift-3.c: New test case. + 2021-08-23 David Malcolm <dmalcolm@redhat.com> * gcc.dg/analyzer/switch.c: Remove xfail. Add various tests. diff --git a/gcc/testsuite/c-c++-common/dfp/convert-bfp-11.c b/gcc/testsuite/c-c++-common/dfp/convert-bfp-11.c index 95c433d..c09c834 100644 --- a/gcc/testsuite/c-c++-common/dfp/convert-bfp-11.c +++ b/gcc/testsuite/c-c++-common/dfp/convert-bfp-11.c @@ -1,9 +1,16 @@ -/* { dg-skip-if "" { ! "powerpc*-*-linux*" } } */ +/* { dg-require-effective-target dfp } */ -/* Test decimal float conversions to and from IBM 128-bit long double. - Checks are skipped at runtime if long double is not 128 bits. - Don't force 128-bit long doubles because runtime support depends - on glibc. */ +/* We need the long double type to be IBM 128-bit because the CONVERT_TO_PINF + tests will fail if we use IEEE 128-bit floating point. This is due to IEEE + 128-bit having a larger exponent range than IBM 128-bit extended double. So + tests that would generate an infinity with IBM 128-bit will generate a + normal number with IEEE 128-bit. */ + +/* { dg-require-effective-target long_double_ibm128 } */ +/* { dg-options "-O2" } */ +/* { dg-add-options long_double_ibm128 } */ + +/* Test decimal float conversions to and from IBM 128-bit long double. */ #include "convert.h" @@ -36,9 +43,6 @@ CONVERT_TO_PINF (312, tf, sd, 1.6e+308L, d32) int main () { - if (sizeof (long double) != 16) - return 0; - convert_101 (); convert_102 (); diff --git a/gcc/testsuite/g++.dg/pr100574.C b/gcc/testsuite/g++.dg/pr100574.C index 42ba040..0df62aa 100644 --- a/gcc/testsuite/g++.dg/pr100574.C +++ b/gcc/testsuite/g++.dg/pr100574.C @@ -40,6 +40,8 @@ template <typename _Tp, typename _Alloc> template <typename...> void vector<_Tp, _Alloc>::_M_realloc_insert() { __alloc_traits::pointer __trans_tmp_5; + /* __len is used uninitialized below, which might trigger warnings, + even without -Wall (and other than -Wuninitialized). */ long __len(__len || max_size()), __elems_before; __trans_tmp_5 = _M_allocate___n ? __alloc_traits::allocate(_M_impl, _M_allocate___n) @@ -62,3 +64,5 @@ void ReadTrackChunk() case MIDIST_PITCHBEND: block.data.push_back(); } + +// { dg-prune-output "warning" } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-26.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-26.C new file mode 100644 index 0000000..f72ac9d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-26.C @@ -0,0 +1,27 @@ +/* PR middle-end/101600 - Spurious -Warray-bounds downcasting a polymorphic + pointer + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct S1 { virtual ~S1(); }; +struct S2 { int m; }; +struct S3 { virtual ~S3(); }; +struct S4: S1, S2, S3 {}; + +int f1 (); + +void f2 (S3 *); + +void f3 (S2 *p) +{ + for (int i = f1 (); f1 (); ) + { + if (i == 0) + { + p = 0; + break; + } + } + + f2 (static_cast<S4 *>(p)); // { dg-bogus "-Warray-bounds" } +} diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-5.C b/gcc/testsuite/g++.dg/warn/Wreturn-5.C new file mode 100644 index 0000000..543e33e --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wreturn-5.C @@ -0,0 +1,15 @@ +// PR C++/66590 +// { dg-do compile } +// { dg-options "-Wall" } + +struct A{ ~A();}; + +int f(int x) +{ + A a; + switch (x) + { + case 1: { A tmp; return 1; } break; + default: return 0; + } +} // { dg-bogus "control reaches end of non-void function" } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-88.c b/gcc/testsuite/gcc.dg/Warray-bounds-88.c new file mode 100644 index 0000000..8cee8d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-88.c @@ -0,0 +1,134 @@ +/* PR middle-end/101977 - bogus -Warray-bounds on a negative index into + a parameter in conditional with null + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +struct A { int i; }; +struct B { struct A a1; struct A a2; }; + + +void nowarn_p_0_0 (struct A *p, int i) +{ + struct A *q = i < 0 ? p : 0 < i ? (struct A*)0 : 0; + struct B *r = (struct B*)((char *)q - __builtin_offsetof (struct B, a2)); + r->a1.i = 0; +} + +void nowarn_0_p_0 (struct A *p, int i) +{ + struct A *q = i < 0 ? 0 : 0 < i ? p : 0; + struct B *r = (struct B*)((char *)q - __builtin_offsetof (struct B, a2)); + r->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + +void nowarn_0_0_p (struct A *p, int i) +{ + struct A *q = i < 0 ? 0 : 0 < i ? 0 : p; + struct B *r = (struct B*)((char *)q - __builtin_offsetof (struct B, a2)); + r->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + + +void nowarn_p_q_0 (struct A *p, struct A *q, int i) +{ + struct A *r = i < 0 ? p : 0 < i ? q : 0; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + +void nowarn_p_0_q (struct A *p, struct A *q, int i) +{ + struct A *r = i < 0 ? p : 0 < i ? 0 : q; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + +void nowarn_0_p_q (struct A *p, struct A *q, int i) +{ + struct A *r = i < 0 ? 0 : 0 < i ? p : q; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; +} + + +void nowarn_p_q_r (struct A *p, struct A *q, struct A *r, int i) +{ + struct A *s = i < 0 ? p : 0 < i ? q : r; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + + +extern struct B b1, b2, b3; + +void nowarn_p_b1_0 (struct A *p, int i) +{ + struct A *r = i < 0 ? p : 0 < i ? &b1.a2 : 0; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + +void nowarn_p_0_b1 (struct A *p, int i) +{ + struct A *r = i < 0 ? p : 0 < i ? 0 : &b1.a2; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; // { dg-bogus "-Warray-bounds" } +} + +void nowarn_0_p_b1 (struct A *p, int i) +{ + struct A *r = i < 0 ? 0 : 0 < i ? p : &b1.a2; + struct B *s = (struct B*)((char *)r - __builtin_offsetof (struct B, a2)); + s->a1.i = 0; +} + + +void nowarn_p_b1_b2 (struct A *p, int i) +{ + struct A *s = i < 0 ? p : 0 < i ? &b1.a2 : &b2.a2; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + +void nowarn_b1_p_b2 (struct A *p, int i) +{ + struct A *s = i < 0 ? &b1.a2 : 0 < i ? p : &b2.a2; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + +void nowarn_b1_b2_p (struct A *p, int i) +{ + struct A *s = i < 0 ? &b1.a2 : 0 < i ? &b2.a2 : p; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + +void nowarn_b1_b2_b3 (struct A *p, int i) +{ + struct A *s = i < 0 ? &b1.a2 : 0 < i ? &b2.a2 : &b3.a2; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + + +void nowarn_0_b1_b2 (int i) +{ + struct A *s = i < 0 ? 0 : 0 < i ? &b1.a2 : &b2.a2; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + +void warn_b1_0_b2 (int i) +{ + struct A *s = i < 0 ? &b1.a2 : 0 < i ? 0 : &b2.a2; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} + +void warn_b1_b2_0 (int i) +{ + struct A *s = i < 0 ? &b1.a2 : 0 < i ? &b2.a2 : 0; + struct B *t = (struct B*)((char *)s - __builtin_offsetof (struct B, a2)); + t->a1.i = 0; +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overread.c b/gcc/testsuite/gcc.dg/Wstringop-overread.c index 0343e43..7db7402 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overread.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overread.c @@ -317,9 +317,9 @@ void test_strnlen_array (int i, int i0, unsigned n) T (strnlen (a1, n)); T (strnlen (a1 + 1, 0)); - T (strnlen (a1 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a1 + 1, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" } T (strnlen (a1 + 1, i0)); - T (strnlen (a1 + 1, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strnlen (a1 + 1, i0 + 1)); // { dg-warning "'strnlen' specified bound \\\[1, \\d+] exceeds source size 0" } T (strnlen (a1 + 1, n)); T (strnlen (a1 + i, 0)); T (strnlen (a1 + i, 1)); @@ -335,7 +335,7 @@ void test_strnlen_array (int i, int i0, unsigned n) T (strnlen (a1 + i0, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" } T (strnlen (a1 + i0, n)); T (strnlen (a1 + i0 + 1, 0)); - T (strnlen (a1 + i0 + 1, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a1 + i0 + 1, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" } T (strnlen (a1 + i0 + 1, n)); T (strnlen (a2, 0)); @@ -344,10 +344,10 @@ void test_strnlen_array (int i, int i0, unsigned n) T (strnlen (a2, n)); T (strnlen (a2 + 1, 0)); T (strnlen (a2 + 1, 1)); - T (strnlen (a2 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" { xfail *-*-* } } + T (strnlen (a2 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" "pr87492" } T (strnlen (a2 + 1, n)); T (strnlen (a2 + 2, 0)); - T (strnlen (a2 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a2 + 2, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" } T (strnlen (a2 + 2, n)); T (strnlen (a2 + i, 0)); T (strnlen (a2 + i, 1)); @@ -365,13 +365,13 @@ void test_strnlen_array (int i, int i0, unsigned n) T (strnlen (a2 + i0 + 1, 0)); T (strnlen (a2 + i0 + 1, 1)); - T (strnlen (a2 + i0 + 1, 2)); + T (strnlen (a2 + i0 + 1, 2)); // { dg-warning "'strnlen' specified bound 2 exceeds source size 1" } T (strnlen (a2 + i0 + 1, n)); T (strnlen (a2 + i0 + 2, 0)); - T (strnlen (a2 + i0 + 2, 1)); // { dg-warning "'strnlen' reading 1 byte from a region of size 0" } + T (strnlen (a2 + i0 + 2, 1)); // { dg-warning "'strnlen' specified bound 1 exceeds source size 0" } T (strnlen (a2 + i0 + 2, i0)); - T (strnlen (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strnlen' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strnlen (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strnlen' specified bound \\\[1, \\d+] exceeds source size 0" } T (strnlen (a2 + i0 + 2, n)); } @@ -512,9 +512,9 @@ void test_strndup_array (int i, int i0, unsigned n) T (strndup (a1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } T (strndup (a1, n)); T (strndup (a1 + 1, 0)); - T (strndup (a1 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a1 + 1, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" } T (strndup (a1 + 1, i0)); - T (strndup (a1 + 1, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strndup (a1 + 1, i0 + 1)); // { dg-warning "'strndup' specified bound \\\[1, \\d+] exceeds source size 0" } T (strndup (a1 + 1, n)); T (strndup (a1 + i, 0)); T (strndup (a1 + i, 1)); @@ -529,7 +529,7 @@ void test_strndup_array (int i, int i0, unsigned n) T (strndup (a1 + i0, 1)); T (strndup (a1 + i0, n)); T (strndup (a1 + i0 + 1, 0)); - T (strndup (a1 + i0 + 1, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a1 + i0 + 1, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" } T (strndup (a1 + i0 + 1, n)); T (strndup (a2, 0)); @@ -538,10 +538,10 @@ void test_strndup_array (int i, int i0, unsigned n) T (strndup (a2, n)); T (strndup (a2 + 1, 0)); T (strndup (a2 + 1, 1)); - T (strndup (a2 + 1, 2)); + T (strndup (a2 + 1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } T (strndup (a2 + 1, n)); T (strndup (a2 + 2, 0)); - T (strndup (a2 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a2 + 2, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" } T (strndup (a2 + 2, n)); T (strndup (a2 + i, 0)); T (strndup (a2 + i, 1)); @@ -559,13 +559,13 @@ void test_strndup_array (int i, int i0, unsigned n) T (strndup (a2 + i0 + 1, 0)); T (strndup (a2 + i0 + 1, 1)); - T (strndup (a2 + i0 + 1, 2)); + T (strndup (a2 + i0 + 1, 2)); // { dg-warning "'strndup' specified bound 2 exceeds source size 1" } T (strndup (a2 + i0 + 1, n)); T (strndup (a2 + i0 + 2, 0)); - T (strndup (a2 + i0 + 2, 1)); // { dg-warning "'strndup' reading 1 byte from a region of size 0" } + T (strndup (a2 + i0 + 2, 1)); // { dg-warning "'strndup' specified bound 1 exceeds source size 0" } T (strndup (a2 + i0 + 2, i0)); - T (strndup (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strndup' reading between 1 and \[0-9\]+ bytes from a region of size 0" } + T (strndup (a2 + i0 + 2, i0 + 1)); // { dg-warning "'strndup' specified bound \\\[1, \\d+] exceeds source size 0" } T (strndup (a2 + i0 + 2, n)); } diff --git a/gcc/testsuite/gcc.dg/diagnostic-input-charset-1.c b/gcc/testsuite/gcc.dg/diagnostic-input-charset-1.c new file mode 100644 index 0000000..4e56833 --- /dev/null +++ b/gcc/testsuite/gcc.dg/diagnostic-input-charset-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-iconv "CP850" } */ +/* { dg-options "-finput-charset=CP850 -fdiagnostics-show-caret" } */ + +/* Test that diagnostics are converted to UTF-8; this file is encoded in + CP850. Why CP850? -finput-charset only supports encodings that are a + superset of ASCII. But encodings that look like latin-1 are automatically + converted by expect to UTF-8, and hence by the time dg sees them, it can't + verify they were actually output in UTF-8. So codepage 850 was chosen as one + that is hopefully available and meets the requirements of matching ASCII and + not matching latin-1. */ +const char *section = "õ" +/* { dg-error "expected .* at end of input" "" { target *-*-*} .-1 } */ +/* { dg-begin-multiline-output "" } + const char *section = "§" + ^~~~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/diagnostic-input-utf8-bom.c b/gcc/testsuite/gcc.dg/diagnostic-input-utf8-bom.c new file mode 100644 index 0000000..1a3f352 --- /dev/null +++ b/gcc/testsuite/gcc.dg/diagnostic-input-utf8-bom.c @@ -0,0 +1,14 @@ +int 1; +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-show-caret" } */ + +/* This file begins with a UTF-8 byte order mark. Verify that diagnostics + still point to the right place, since the stripping of the BOM happens twice, + once when libcpp reads the file, and once when diagnostics infrastucture + reads it. */ + +/* { dg-error "expected .* before numeric constant" "" { target *-*-*} 1 } */ +/* { dg-begin-multiline-output "" } + int 1; + ^ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/ipa/modref-1.c b/gcc/testsuite/gcc.dg/ipa/modref-1.c index 858567d..5314e7d 100644 --- a/gcc/testsuite/gcc.dg/ipa/modref-1.c +++ b/gcc/testsuite/gcc.dg/ipa/modref-1.c @@ -10,15 +10,15 @@ void a(char *ptr, char *ptr2) __attribute__((noinline)) void b(char *ptr) { - a(ptr+1,&ptr[2]); + a(ptr+1,&ptr[3]); } int main() { - char c[3]={0,1,0}; + char c[4]={0,1,0,0}; b(c); - return c[0]+c[2]; + return c[0]+c[3]; } /* Check that both param offsets are determined correctly. */ /* { dg-final { scan-ipa-dump "param offset:1" "modref" } } */ -/* { dg-final { scan-ipa-dump "param offset:2" "modref" } } */ +/* { dg-final { scan-ipa-dump "param offset:3" "modref" } } */ diff --git a/gcc/testsuite/gcc.dg/pr20126.c b/gcc/testsuite/gcc.dg/pr20126.c index a421ce1..10aeec7 100644 --- a/gcc/testsuite/gcc.dg/pr20126.c +++ b/gcc/testsuite/gcc.dg/pr20126.c @@ -34,6 +34,10 @@ foo (S *x, S *y) while (e <= g) { const char *t = e + 1; + /* The pointer E below increases but the bound H stays constant, + letting the latter exceed the size remaining in the argument + pointed to by the formed, which might be detected by + -Wstringop-overread. */ if (__builtin_memcmp (e, f, h) == 0) return 1; e = t; @@ -48,3 +52,5 @@ main (void) abort (); return 0; } + +/* { dg-prune-output "-Wstringop-overread" } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp1.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp1.c index 8c6e4e6..f5f38c4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ int foo (int i); int bar (int j) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp2.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp2.c index e6d4235..fc92cdf 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ int foo (int i); int bar2 (int j) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp3.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp3.c index 1a3bbd5..805652b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ int foo (int i); void bar (int j) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp4.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp4.c index 6710e6b..e3f4531 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ int foo (int *p); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c index 35d4d74..aaeec68 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c @@ -1,6 +1,5 @@ - /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-4.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-4.c index 3ac217b..a277c70 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/modref-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-4.c @@ -10,17 +10,17 @@ void a(char *ptr, char *ptr2) __attribute__((noinline)) void b(char *ptr) { - a(ptr+1,&ptr[2]); + a(ptr+1,&ptr[3]); } int main() { - char c[4]={0,1,2,0}; + char c[5]={0,1,2,0,0}; b(c); - return c[0]+c[3]; + return c[0]+c[4]; } /* Check that both param offsets are determined correctly and the computation is optimized out. */ /* { dg-final { scan-tree-dump "param offset:1" "modref1" } } */ -/* { dg-final { scan-tree-dump "param offset:2" "modref1" } } */ +/* { dg-final { scan-tree-dump "param offset:3" "modref1" } } */ /* { dg-final { scan-tree-dump "return 0" "modref1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c new file mode 100644 index 0000000..15ae4ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-8.c @@ -0,0 +1,25 @@ +/* { dg-options "-O2 --param modref-max-adjustments=8 -fdump-tree-modref1" } */ +/* { dg-do compile } */ +void +set (char *p) +{ + p[1]=1; + p[0]=0; + p[2]=2; + p[4]=4; + p[3]=3; +} + +void +recurse (char *p, int n) +{ + *p = 0; + if (n) + recurse (p+1,n-1); +} +/* { dg-final { scan-tree-dump-not "param=modref-max-accesses" "modref1" } } */ +/* { dg-final { scan-tree-dump "param=modref-max-adjustments" "modref1" } } */ +/* In set all accesses should merge together. */ +/* { dg-final { scan-tree-dump "access: Parm 0 param offset:0 offset:0 size:8 max_size:40" "modref1" } } */ +/* In recurse we should cap the recrusion after 8 attempts and set max_size to -1. */ +/* { dg-final { scan-tree-dump "access: Parm 0 param offset:0 offset:0 size:8 max_size:-1 adjusted 8 times" "modref1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr64130.c b/gcc/testsuite/gcc.dg/tree-ssa/pr64130.c index 28ffbb7..b694ec1 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr64130.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr64130.c @@ -1,6 +1,5 @@ - /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ __extension__ typedef __UINT32_TYPE__ uint32_t; diff --git a/gcc/testsuite/gcc.dg/vect/pr101145.c b/gcc/testsuite/gcc.dg/vect/pr101145.c new file mode 100644 index 0000000..74031b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145.c @@ -0,0 +1,187 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-options "-O3 -fdump-tree-vect-details" } */ +#include <limits.h> + +unsigned __attribute__ ((noinline)) +foo (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + while (n < ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +foo_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) +{ + while (UINT_MAX - 64 < ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +foo_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + l = UINT_MAX - 32; + while (n < ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +foo_3 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + while (n <= ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +foo_4 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ // infininate + while (0 <= ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +foo_5 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + //no loop + l = UINT_MAX; + while (n < ++l) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +bar (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + while (--l < n) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +bar_1 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned) +{ + while (--l < 64) + *a++ = *b++ + 1; + return l; +} + +unsigned __attribute__ ((noinline)) +bar_2 (int *__restrict__ a, int *__restrict__ b, unsigned l, unsigned n) +{ + l = 32; + while (--l < n) + *a++ = *b++ + 1; + return l; +} + + +int a[3200], b[3200]; +int fail; + +int +main () +{ + unsigned l, n; + unsigned res; + /* l > n*/ + n = UINT_MAX - 64; + l = n + 32; + res = foo (a, b, l, n); + if (res != 0) + fail++; + + l = n; + res = foo (a, b, l, n); + if (res != 0) + fail++; + + l = n - 1; + res = foo (a, b, l, n); + if (res != l + 1) + fail++; + + l = n - 32; + res = foo (a, b, l, n); + if (res != l + 1) + fail++; + + l = UINT_MAX; + res = foo (a, b, l, n); + if (res != 0) + fail++; + + l = n + 32; + res = foo_1 (a, b, l, n); + if (res != 0) + fail++; + + l = n + 32; + res = foo_2 (a, b, l, n); + if (res != 0) + fail++; + + l = n; + res = foo_3 (a, b, l, n); + if (res != 0) + fail++; + + l = n - 1; + res = foo_3 (a, b, l, n); + if (res != 0) + fail++; + + l = n - 2; + res = foo_3 (a, b, l, n); + if (res != l + 1) + fail++; + + res = foo_5 (a, b, l, n); + if (res != 0) + fail++; + + n = 64; + l = n - 32; + res = bar (a, b, l, n); + res++; + if (res != 0) + fail++; + + l = n; + res = bar (a, b, l, n); + res++; + if (res != 0) + fail++; + + l = n + 1; + res = bar (a, b, l, n); + res++; + if (res != l) + fail++; + + l = 0; + res = bar (a, b, l, n); + res++; + if (res != l) + fail++; + + l = 32; + res = bar_1 (a, b, l, n); + res++; + if (res != 0) + fail++; + + res = bar_1 (a, b, l, n); + res++; + if (res != 0) + fail++; + + if (fail) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 7 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145.inc b/gcc/testsuite/gcc.dg/vect/pr101145.inc new file mode 100644 index 0000000..615d2e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145.inc @@ -0,0 +1,65 @@ +TYPE __attribute__ ((noinline)) +foo_sign (int *__restrict__ a, int *__restrict__ b, TYPE l, TYPE n) +{ + TYPE i; + for (i = l; n < i; i += C) + *a++ = *b++ + 1; + return i; +} + +TYPE __attribute__ ((noinline)) +bar_sign (int *__restrict__ a, int *__restrict__ b, TYPE l, TYPE n) +{ + TYPE i; + for (i = l; i < n; i -= C) + *a++ = *b++ + 1; + return i; +} + +int __attribute__ ((noinline)) neq (int a, int b) { return a != b; } + +int a[1000], b[1000]; +int fail; + +int +main () +{ + TYPE res; + TYPE l; + TYPE n; + n = N_BASE; + l = n - C; + res = foo_sign (a, b, l, n); + if (res != l) + fail++; + + l = n; + res = foo_sign (a, b, l, n); + if (res != l) + fail++; + + l = n + C; + res = foo_sign (a, b, l, n); + if (neq ((res - MIN) / C, 0)) + fail++; + + n = N_BASE_DOWN; + l = n - C; + res = bar_sign (a, b, l, n); + if (neq ((MAX - res) / C, 0)) + fail++; + + l = n; + res = bar_sign (a, b, l, n); + if (res != l) + fail++; + + l = n + C; + res = bar_sign (a, b, l, n); + if (res != l) + fail++; + + if (fail) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_1.c b/gcc/testsuite/gcc.dg/vect/pr101145_1.c new file mode 100644 index 0000000..8bc26e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145_1.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-options "-O3 -fdump-tree-vect-details" } */ +#define TYPE signed char +#define MIN -128 +#define MAX 127 +#define N_BASE (MAX - 32) +#define N_BASE_DOWN (MIN + 32) + +#define C 3 + +#include "pr101145.inc" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_2.c b/gcc/testsuite/gcc.dg/vect/pr101145_2.c new file mode 100644 index 0000000..b14c4b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145_2.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-options "-O3 -fdump-tree-vect-details" } */ +#define TYPE unsigned char +#define MIN 0 +#define MAX 255 +#define N_BASE (MAX - 32 + 1) +#define N_BASE_DOWN (MIN + 32) + +#define C 2 + +#include "pr101145.inc" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145_3.c b/gcc/testsuite/gcc.dg/vect/pr101145_3.c new file mode 100644 index 0000000..99289af --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145_3.c @@ -0,0 +1,13 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-options "-O3 -fdump-tree-vect-details" } */ +#define TYPE int * +#define MIN ((TYPE)0) +#define MAX ((TYPE)((long long)-1)) +#define N_BASE (MIN - 32) +#define N_BASE_DOWN (MIN + 32) + +#define C 1 + +#include "pr101145.inc" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr101145inf.c b/gcc/testsuite/gcc.dg/vect/pr101145inf.c new file mode 100644 index 0000000..ed49f56 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145inf.c @@ -0,0 +1,25 @@ +/* { dg-do run { target *-*-linux* *-*-gnu* *-*-uclinux* } } */ +/* { dg-options "-O3" } */ +#include <limits.h> +#include "pr101145inf.inc" + +__attribute__ ((noinline)) +unsigned foo(unsigned val, unsigned start) +{ + unsigned cnt = 0; + for (unsigned i = start; val <= i; i+=16) + cnt++; + return cnt; +} + +void test_finite () +{ + unsigned n = foo (16, UINT_MAX - 32); + if (n != 3) + __builtin_abort (); +} + +void test_infinite () +{ + foo (15, UINT_MAX - 32); +} diff --git a/gcc/testsuite/gcc.dg/vect/pr101145inf.inc b/gcc/testsuite/gcc.dg/vect/pr101145inf.inc new file mode 100644 index 0000000..4aa3d04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145inf.inc @@ -0,0 +1,28 @@ +#include <unistd.h> +#include <signal.h> +#include <stdlib.h> + +void test_finite (); +void test_infinite (); + +void do_exit (int i) +{ + exit (0); +} + +int main(void) +{ + test_finite (); + struct sigaction s; + sigemptyset (&s.sa_mask); + s.sa_handler = do_exit; + s.sa_flags = 0; + sigaction (SIGALRM, &s, NULL); + alarm (1); + + test_infinite (); + + __builtin_abort (); + return 1; +} + diff --git a/gcc/testsuite/gcc.dg/vect/pr101145inf_1.c b/gcc/testsuite/gcc.dg/vect/pr101145inf_1.c new file mode 100644 index 0000000..4ee3e31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr101145inf_1.c @@ -0,0 +1,23 @@ +/* { dg-do run { target *-*-linux* *-*-gnu* *-*-uclinux* } } */ +/* { dg-options "-O3" } */ +#include <limits.h> +#include "pr101145inf.inc" + +__attribute__ ((noinline)) +unsigned foo(unsigned val, unsigned start) +{ + unsigned cnt = 0; + for (unsigned i = start; i < val; i-=16) + cnt++; + return cnt; +} + +void test_finite () +{ + foo (UINT_MAX - 15, 32); +} + +void test_infinite () +{ + foo (UINT_MAX - 14, 32); +} diff --git a/gcc/testsuite/gcc.dg/vect/pr102046.c b/gcc/testsuite/gcc.dg/vect/pr102046.c new file mode 100644 index 0000000..ae48b49 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr102046.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O3 -fvect-cost-model=dynamic" } */ +/* { dg-additional-options "-march=btver2" { target x86_64-*-* i?86-*-* } } */ + +struct S +{ + unsigned a, b; +}; + +struct S g; + +void +foo (struct S *o) +{ + struct S s = g; + s.b *= 3; + s.a -= s.a / 2; + *o = s; +} diff --git a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c index 2afd2b5..846e930 100644 --- a/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c +++ b/gcc/testsuite/gcc.dg/warn-strnlen-no-nul.c @@ -143,14 +143,17 @@ T (v0 ? b[1] : "", bsz); T (v0 ? b[2] : "", bsz); T (v0 ? b[3] : "", bsz); -T (v0 ? "" : b[0], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */ -T (v0 ? "" : b[1], bsz + 1); -T (v0 ? "" : b[2], bsz + 1); -T (v0 ? "" : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[0] : "", bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" } */ -T (v0 ? b[1] : "", bsz + 1); -T (v0 ? b[2] : "", bsz + 1); -T (v0 ? b[3] : "", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ +/* The warnings below are strictly correct but the strnlen calls are safe + because the reads are bounded by the length of the constant arguments. + It might make sense to relax the warning to avoid triggering for them. */ +T (v0 ? "" : b[0], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? "" : b[1], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? "" : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? "" : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[0] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[1] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[2] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[3] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ T (v0 ? "" : b[i0], bsz); T (v0 ? "" : b[i1], bsz); @@ -164,11 +167,11 @@ T (v0 ? b[i3] : "", bsz); T (v0 ? "" : b[i0], bsz + 1); T (v0 ? "" : b[i1], bsz + 1); T (v0 ? "" : b[i2], bsz + 1); -T (v0 ? "" : b[i3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ +T (v0 ? "" : b[i3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr86937" } */ T (v0 ? b[i0] : "", bsz + 1); T (v0 ? b[i1] : "", bsz + 1); T (v0 ? b[i2] : "", bsz + 1); -T (v0 ? b[i3] : "", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ +T (v0 ? b[i3] : "", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" "pr86937" } */ T (v0 ? "1234" : b[3], bsz); T (v0 ? "1234" : b[i3], bsz); @@ -180,15 +183,15 @@ T (v0 ? b[0] : b[2], bsz); T (v0 ? b[2] : b[3], bsz); T (v0 ? b[3] : b[2], bsz); -T (v0 ? "1234" : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? "1234" : b[i3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[i3] : "1234", bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ +T (v0 ? "1234" : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? "1234" : b[i3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[3] : "1234", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[i3] : "1234", bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ -T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" { xfail *-*-*} } */ -T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 may exceed source size 5" "pr86937" } */ -T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ -T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "unterminated" "pr86937" { xfail *-*-* } } */ +T (v0 ? a : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[0] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[2] : b[3], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ +T (v0 ? b[3] : b[2], bsz + 1); /* { dg-warning "bound 6 exceeds source size 5" } */ struct A { char a[5], b[5]; }; diff --git a/gcc/testsuite/gcc.target/i386/avx2-shiftqihi-constant-1.c b/gcc/testsuite/gcc.target/i386/avx2-shiftqihi-constant-1.c index 7206503..801f570 100644 --- a/gcc/testsuite/gcc.target/i386/avx2-shiftqihi-constant-1.c +++ b/gcc/testsuite/gcc.target/i386/avx2-shiftqihi-constant-1.c @@ -1,6 +1,6 @@ /* PR target/95524 */ /* { dg-do compile } */ -/* { dg-options "-O2 -mavx2" } */ +/* { dg-options "-O2 -mavx2 -mno-avx512f" } */ /* { dg-final { scan-assembler-times "vpand\[^\n\]*%ymm" 3 } } */ typedef char v32qi __attribute__ ((vector_size (32))); typedef unsigned char v32uqi __attribute__ ((vector_size (32))); diff --git a/gcc/testsuite/gcc.target/i386/avx512f-pr101471.c b/gcc/testsuite/gcc.target/i386/avx512f-pr101471.c new file mode 100644 index 0000000..4a0057b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512f-pr101471.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "-mavx512dq -O0" } */ +/* { dg-require-effective-target avx512dq } */ + +#include "avx512f-check.h" + +static void +avx512f_test (void) +{ + __m512 x = { + 1, 1, 1, 1, + 1, 1, 1, 1, + 0, 0, 0, 0, + 0, 0, 0, 0, }; + int ret = _mm512_fpclass_ps_mask(x, 0x26); + if (ret != 65280) + __builtin_abort(); +} diff --git a/gcc/testsuite/gcc.target/i386/mvc5.c b/gcc/testsuite/gcc.target/i386/mvc5.c index 677f79f..0e02bf6 100644 --- a/gcc/testsuite/gcc.target/i386/mvc5.c +++ b/gcc/testsuite/gcc.target/i386/mvc5.c @@ -3,6 +3,10 @@ /* { dg-options "-fno-inline" } */ /* { dg-final { scan-assembler "foo,foo.resolver" } } */ +/* Verify that foo clones are not numbered. */ +/* { dg-final { scan-assembler "foo.default:" } } */ +/* { dg-final { scan-assembler "foo.avx:" } } */ + __attribute__((target_clones("default","avx","avx2"))) int foo () diff --git a/gcc/testsuite/gcc.target/i386/mvc7.c b/gcc/testsuite/gcc.target/i386/mvc7.c index a3697ba..7fb9dde 100644 --- a/gcc/testsuite/gcc.target/i386/mvc7.c +++ b/gcc/testsuite/gcc.target/i386/mvc7.c @@ -1,7 +1,11 @@ /* { dg-do compile } */ /* { dg-require-ifunc "" } */ -/* { dg-final { scan-assembler "foo.resolver" } } */ -/* { dg-final { scan-assembler "avx" } } */ + +/* Verify that foo clones are not numbered. */ +/* { dg-final { scan-assembler "foo.resolver," } } */ +/* { dg-final { scan-assembler "foo.default," } } */ +/* { dg-final { scan-assembler "foo.avx," } } */ + /* { dg-final { scan-assembler "slm" } } */ /* { dg-final { scan-assembler "foo,foo.resolver" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr101716.c b/gcc/testsuite/gcc.target/i386/pr101716.c new file mode 100644 index 0000000..5e3ea64 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr101716.c @@ -0,0 +1,11 @@ +/* PR target/101716 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +/* { dg-final { scan-assembler "leal\[\\t \]\[^\\n\]*eax" } } */ +/* { dg-final { scan-assembler-not "movl\[\\t \]\[^\\n\]*eax" } } */ + +unsigned long long sample1(unsigned long long m) { + unsigned int t = -1; + return (m << 1) & t; +} diff --git a/gcc/testsuite/gcc.target/i386/pr95778-1.c b/gcc/testsuite/gcc.target/i386/pr95778-1.c index 3238303..18f8383 100644 --- a/gcc/testsuite/gcc.target/i386/pr95778-1.c +++ b/gcc/testsuite/gcc.target/i386/pr95778-1.c @@ -17,5 +17,5 @@ g2(int *p) return f2(p); } -/* { dg-final { scan-assembler "g2.default.1:\n\tjmp\tf2.default.1\n" } } */ -/* { dg-final { scan-assembler "g2.avx2.0:\n\tjmp\tf2.avx2.0\n" } } */ +/* { dg-final { scan-assembler "g2.default:\n\tjmp\tf2.default\n" } } */ +/* { dg-final { scan-assembler "g2.avx2:\n\tjmp\tf2.avx2\n" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr95778-2.c b/gcc/testsuite/gcc.target/i386/pr95778-2.c index e88702d..9ef513a 100644 --- a/gcc/testsuite/gcc.target/i386/pr95778-2.c +++ b/gcc/testsuite/gcc.target/i386/pr95778-2.c @@ -17,5 +17,5 @@ g2(int *p) return f2(p); } -/* { dg-final { scan-assembler "g2.default.1:\n\tjmp\tf2.default.1\n" } } */ -/* { dg-final { scan-assembler "g2.avx2.0:\n\tjmp\tf2.avx2.0\n" } } */ +/* { dg-final { scan-assembler "g2.default:\n\tjmp\tf2.default\n" } } */ +/* { dg-final { scan-assembler "g2.avx2:\n\tjmp\tf2.avx2\n" } } */ diff --git a/gcc/testsuite/gcc.target/i386/sse2-shiftqihi-constant-1.c b/gcc/testsuite/gcc.target/i386/sse2-shiftqihi-constant-1.c index f1c68cb..015450f 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-shiftqihi-constant-1.c +++ b/gcc/testsuite/gcc.target/i386/sse2-shiftqihi-constant-1.c @@ -1,6 +1,6 @@ /* PR target/95524 */ /* { dg-do compile } */ -/* { dg-options "-O2 -msse2" } */ +/* { dg-options "-O2 -msse2 -mno-avx" } */ /* { dg-final { scan-assembler-times "pand\[^\n\]*%xmm" 3 { xfail *-*-* } } } */ typedef char v16qi __attribute__ ((vector_size (16))); typedef unsigned char v16uqi __attribute__ ((vector_size (16))); diff --git a/gcc/testsuite/gcc.target/powerpc/pr70117.c b/gcc/testsuite/gcc.target/powerpc/pr70117.c index 3bbd2c5..4a51f58 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr70117.c +++ b/gcc/testsuite/gcc.target/powerpc/pr70117.c @@ -1,26 +1,18 @@ -/* { dg-do run { target { powerpc*-*-linux* powerpc*-*-darwin* powerpc*-*-aix* rs6000-*-* } } } */ -/* { dg-options "-std=c99 -mlong-double-128 -O2" } */ +/* { dg-do run } */ +/* { dg-require-effective-target long_double_ibm128 } */ +/* { dg-options "-std=c99 -O2" } */ +/* { dg-add-options long_double_ibm128 } */ #include <float.h> -#if defined(__LONG_DOUBLE_IEEE128__) -/* If long double is IEEE 128-bit, we need to use the __ibm128 type instead of - long double. We can't use __ibm128 on systems that don't support IEEE - 128-bit floating point, because the type is not enabled on those - systems. */ -#define LDOUBLE __ibm128 - -#elif defined(__LONG_DOUBLE_IBM128__) -#define LDOUBLE long double - -#else -#error "long double must be either IBM 128-bit or IEEE 128-bit" +#ifndef __LONG_DOUBLE_IBM128__ +#error "long double must be IBM 128-bit" #endif union gl_long_double_union { struct { double hi; double lo; } dd; - LDOUBLE ld; + long double ld; }; /* This is gnulib's LDBL_MAX which, being 107 bits in precision, is @@ -36,7 +28,7 @@ volatile double dnan = 0.0/0.0; int main (void) { - LDOUBLE ld; + long double ld; ld = gl_LDBL_MAX.ld; if (__builtin_isinf (ld)) diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.c new file mode 100644 index 0000000..dceb5b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-maltivec -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test if unpack vectorization succeeds for type signed/unsigned + short and char. */ + +#include "unpack-vectorize-1.h" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 4 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvupkhsb\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvupklsb\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvupkhsh\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvupklsh\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvmrghb\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvmrglb\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvmrghh\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvmrglh\M} 2 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.h b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.h new file mode 100644 index 0000000..1cb89ab --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-1.h @@ -0,0 +1,14 @@ +#include "unpack-vectorize.h" + +DEF_ARR (si) +DEF_ARR (ui) +DEF_ARR (sh) +DEF_ARR (uh) +DEF_ARR (sc) +DEF_ARR (uc) + +TEST1 (sh, si) +TEST1 (uh, ui) +TEST1 (sc, sh) +TEST1 (uc, uh) + diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.c new file mode 100644 index 0000000..4f2e6eb --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-mdejagnu-cpu=power7 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test if unsigned int unpack vectorization succeeds. V2DImode is + supported since Power7 so guard it under Power7 and up. */ + +#include "unpack-vectorize-2.h" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { scan-assembler-times {\mxxmrghw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxxmrglw\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.h b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.h new file mode 100644 index 0000000..e199229 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-2.h @@ -0,0 +1,7 @@ +#include "unpack-vectorize.h" + +DEF_ARR (ui) +DEF_ARR (ull) + +TEST1 (ui, ull) + diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.c new file mode 100644 index 0000000..520a279 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2 -ftree-vectorize -fno-vect-cost-model -fno-unroll-loops -fdump-tree-vect-details" } */ + +/* Test if signed int unpack vectorization succeeds. */ + +#include "unpack-vectorize-3.h" + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { scan-assembler-times {\mvupkhsw\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvupklsw\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.h b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.h new file mode 100644 index 0000000..6a5191d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-3.h @@ -0,0 +1,7 @@ +#include "unpack-vectorize.h" + +DEF_ARR (si) +DEF_ARR (sll) + +TEST1 (si, sll) + diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-1.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-1.c new file mode 100644 index 0000000..51f0e67 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-1.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vmx_hw } */ +/* { dg-options "-maltivec -O2 -ftree-vectorize -fno-vect-cost-model" } */ + +#include "unpack-vectorize-1.h" + +/* Test if unpack vectorization cases on signed/unsigned short and char + run successfully. */ + +CHECK1 (sh, si) +CHECK1 (uh, ui) +CHECK1 (sc, sh) +CHECK1 (uc, uh) + +int +main () +{ + check1_sh_si (); + check1_uh_ui (); + check1_sc_sh (); + check1_uc_uh (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-2.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-2.c new file mode 100644 index 0000000..6d24360 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-2.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-mdejagnu-cpu=power7 -O2 -ftree-vectorize -fno-vect-cost-model" } */ + +#include "unpack-vectorize-2.h" + +/* Test if unpack vectorization cases on unsigned int run successfully. */ + +CHECK1 (ui, ull) + +int +main () +{ + check1_ui_ull (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-3.c b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-3.c new file mode 100644 index 0000000..fec33c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize-run-3.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-require-effective-target p8vector_hw } */ +/* { dg-options "-mdejagnu-cpu=power8 -O2 -ftree-vectorize -fno-vect-cost-model" } */ + +#include "unpack-vectorize-3.h" + +/* Test if unpack vectorization cases on signed int run successfully. */ + +CHECK1 (si, sll) + +int +main () +{ + check1_si_sll (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/unpack-vectorize.h b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize.h new file mode 100644 index 0000000..11fa7d4 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/unpack-vectorize.h @@ -0,0 +1,42 @@ +typedef signed long long sll; +typedef unsigned long long ull; +typedef signed int si; +typedef unsigned int ui; +typedef signed short sh; +typedef unsigned short uh; +typedef signed char sc; +typedef unsigned char uc; + +#ifndef ALIGN +#define ALIGN 32 +#endif + +#define ALIGN_ATTR __attribute__((__aligned__(ALIGN))) + +#define N 128 + +#define DEF_ARR(TYPE) \ + TYPE TYPE##_a[N] ALIGN_ATTR; \ + TYPE TYPE##_b[N] ALIGN_ATTR; \ + TYPE TYPE##_c[N] ALIGN_ATTR; + +#define TEST1(NTYPE, WTYPE) \ + __attribute__((noipa)) void test1_##NTYPE##_##WTYPE() { \ + for (int i = 0; i < N; i++) \ + WTYPE##_c[i] = NTYPE##_a[i] + NTYPE##_b[i]; \ + } + +#define CHECK1(NTYPE, WTYPE) \ + __attribute__((noipa, optimize(0))) void check1_##NTYPE##_##WTYPE() { \ + for (int i = 0; i < N; i++) { \ + NTYPE##_a[i] = 2 * i * sizeof(NTYPE) + 10; \ + NTYPE##_b[i] = 7 * i * sizeof(NTYPE) / 5 - 10; \ + } \ + test1_##NTYPE##_##WTYPE(); \ + for (int i = 0; i < N; i++) { \ + WTYPE exp = NTYPE##_a[i] + NTYPE##_b[i]; \ + if (WTYPE##_c[i] != exp) \ + __builtin_abort(); \ + } \ + } + diff --git a/gcc/testsuite/gfortran.dg/pr98411.f90 b/gcc/testsuite/gfortran.dg/pr98411.f90 index 249afae..7c906a9 100644 --- a/gcc/testsuite/gfortran.dg/pr98411.f90 +++ b/gcc/testsuite/gfortran.dg/pr98411.f90 @@ -1,5 +1,5 @@ ! { dg-do compile } -! { dg-options "-Wall -fautomatic -fmax-stack-var-size=100" } +! { dg-options "-std=f2008 -Wall -fautomatic -fmax-stack-var-size=100" } ! PR fortran/98411 - Pointless warning for static variables module try @@ -9,8 +9,10 @@ contains subroutine initmodule real, save :: b(1000) logical :: c(1000) ! { dg-warning "moved from stack to static storage" } + integer :: e(1000) = 1 a(1) = 42 b(2) = 3.14 c(3) = .true. + e(5) = -1 end subroutine initmodule end module try diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 06f5b1e..350dbdb 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2360,6 +2360,134 @@ proc check_effective_target_ppc_ieee128_ok { } { }] } +# Check if GCC and GLIBC supports explicitly specifying that the long double +# format uses the IBM 128-bit extended double format. Under little endian +# PowerPC Linux, you need GLIBC 2.32 or later to be able to use a different +# long double format for running a program than the system default. + +proc check_effective_target_long_double_ibm128 { } { + return [check_runtime_nocache long_double_ibm128 { + #include <string.h> + #include <stdio.h> + /* use volatile to prevent optimization. */ + volatile __ibm128 a = (__ibm128) 3.0; + volatile long double one = 1.0L; + volatile long double two = 2.0L; + volatile long double b; + char buffer[20]; + int main() + { + __ibm128 a2; + long double b2; + if (sizeof (long double) != 16) + return 1; + b = one + two; + /* eliminate removing volatile cast warning. */ + a2 = a; + b2 = b; + if (memcmp (&a2, &b2, 16) != 0) + return 1; + sprintf (buffer, "%lg", b); + return strcmp (buffer, "3") != 0; + } + } [add_options_for_long_double_ibm128 ""]] +} + +# Return the appropriate options to specify that long double uses the IBM +# 128-bit format on PowerPC. + +proc add_options_for_long_double_ibm128 { flags } { + if { [istarget powerpc*-*-*] } { + return "$flags -mlong-double-128 -Wno-psabi -mabi=ibmlongdouble" + } + return "$flags" +} + +# Check if GCC and GLIBC supports explicitly specifying that the long double +# format uses the IEEE 128-bit format. Under little endian PowerPC Linux, you +# need GLIBC 2.32 or later to be able to use a different long double format for +# running a program than the system default. + +proc check_effective_target_long_double_ieee128 { } { + return [check_runtime_nocache long_double_ieee128 { + #include <string.h> + #include <stdio.h> + /* use volatile to prevent optimization. */ + volatile _Float128 a = 3.0f128; + volatile long double one = 1.0L; + volatile long double two = 2.0L; + volatile long double b; + char buffer[20]; + int main() + { + _Float128 a2; + long double b2; + if (sizeof (long double) != 16) + return 1; + b = one + two; + /* eliminate removing volatile cast warning. */ + a2 = a; + b2 = b; + if (memcmp (&a2, &b2, 16) != 0) + return 1; + sprintf (buffer, "%lg", b); + return strcmp (buffer, "3") != 0; + } + } [add_options_for_long_double_ieee128 ""]] +} + +# Return the appropriate options to specify that long double uses the IBM +# 128-bit format on PowerPC. +proc add_options_for_long_double_ieee128 { flags } { + if { [istarget powerpc*-*-*] } { + return "$flags -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" + } + return "$flags" +} + +# Check if GCC and GLIBC supports explicitly specifying that the long double +# format uses the IEEE 64-bit. Under little endian PowerPC Linux, you need +# GLIBC 2.32 or later to be able to use a different long double format for +# running a program than the system default. + +proc check_effective_target_long_double_64bit { } { + return [check_runtime_nocache long_double_64bit { + #include <string.h> + #include <stdio.h> + /* use volatile to prevent optimization. */ + volatile double a = 3.0; + volatile long double one = 1.0L; + volatile long double two = 2.0L; + volatile long double b; + char buffer[20]; + int main() + { + double a2; + long double b2; + if (sizeof (long double) != 8) + return 1; + b = one + two; + /* eliminate removing volatile cast warning. */ + a2 = a; + b2 = b; + if (memcmp (&a2, &b2, 16) != 0) + return 1; + sprintf (buffer, "%lg", b); + return strcmp (buffer, "3") != 0; + } + } [add_options_for_ppc_long_double_override_64bit ""]] +} + +# Return the appropriate options to specify that long double uses the IEEE +# 64-bit format on PowerPC. + +proc add_options_for_long_double_64bit { flags } { + if { [istarget powerpc*-*-*] } { + return "$flags -mlong-double-64" + } + return "$flags" +} + # Return 1 if the target supports executing VSX instructions, 0 # otherwise. Cache the result. diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 466158a..7af92d1 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1474,6 +1474,93 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1, } /* Determines number of iterations of loop whose ending condition + is IV0 < IV1 which likes: {base, -C} < n, or n < {base, C}. + The number of iterations is stored to NITER. */ + +static bool +number_of_iterations_until_wrap (class loop *, tree type, affine_iv *iv0, + affine_iv *iv1, class tree_niter_desc *niter) +{ + tree niter_type = unsigned_type_for (type); + tree step, num, assumptions, may_be_zero; + wide_int high, low, max, min; + + may_be_zero = fold_build2 (LE_EXPR, boolean_type_node, iv1->base, iv0->base); + if (integer_onep (may_be_zero)) + return false; + + int prec = TYPE_PRECISION (type); + signop sgn = TYPE_SIGN (type); + min = wi::min_value (prec, sgn); + max = wi::max_value (prec, sgn); + + /* n < {base, C}. */ + if (integer_zerop (iv0->step) && !tree_int_cst_sign_bit (iv1->step)) + { + step = iv1->step; + /* MIN + C - 1 <= n. */ + tree last = wide_int_to_tree (type, min + wi::to_wide (step) - 1); + assumptions = fold_build2 (LE_EXPR, boolean_type_node, last, iv0->base); + if (integer_zerop (assumptions)) + return false; + + num = fold_build2 (MINUS_EXPR, niter_type, wide_int_to_tree (type, max), + iv1->base); + high = max; + if (TREE_CODE (iv1->base) == INTEGER_CST) + low = wi::to_wide (iv1->base) - 1; + else if (TREE_CODE (iv0->base) == INTEGER_CST) + low = wi::to_wide (iv0->base); + else + low = min; + } + /* {base, -C} < n. */ + else if (tree_int_cst_sign_bit (iv0->step) && integer_zerop (iv1->step)) + { + step = fold_build1 (NEGATE_EXPR, TREE_TYPE (iv0->step), iv0->step); + /* MAX - C + 1 >= n. */ + tree last = wide_int_to_tree (type, max - wi::to_wide (step) + 1); + assumptions = fold_build2 (GE_EXPR, boolean_type_node, last, iv1->base); + if (integer_zerop (assumptions)) + return false; + + num = fold_build2 (MINUS_EXPR, niter_type, iv0->base, + wide_int_to_tree (type, min)); + low = min; + if (TREE_CODE (iv0->base) == INTEGER_CST) + high = wi::to_wide (iv0->base) + 1; + else if (TREE_CODE (iv1->base) == INTEGER_CST) + high = wi::to_wide (iv1->base); + else + high = max; + } + else + return false; + + /* (delta + step - 1) / step */ + step = fold_convert (niter_type, step); + num = fold_convert (niter_type, num); + num = fold_build2 (PLUS_EXPR, niter_type, num, step); + niter->niter = fold_build2 (FLOOR_DIV_EXPR, niter_type, num, step); + + widest_int delta, s; + delta = widest_int::from (high, sgn) - widest_int::from (low, sgn); + s = wi::to_widest (step); + delta = delta + s - 1; + niter->max = wi::udiv_floor (delta, s); + + niter->may_be_zero = may_be_zero; + + if (!integer_nonzerop (assumptions)) + niter->assumptions = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, + niter->assumptions, assumptions); + + niter->control.no_overflow = false; + + return true; +} + +/* Determines number of iterations of loop whose ending condition is IV0 < IV1. TYPE is the type of the iv. The number of iterations is stored to NITER. BNDS bounds the difference IV1->base - IV0->base. EXIT_MUST_BE_TAKEN is true if we know @@ -1501,6 +1588,11 @@ number_of_iterations_lt (class loop *loop, tree type, affine_iv *iv0, niter->bound = iv0->base; } + /* {base, -C} < n, or n < {base, C} */ + if (tree_int_cst_sign_bit (iv0->step) + || (!integer_zerop (iv1->step) && !tree_int_cst_sign_bit (iv1->step))) + return number_of_iterations_until_wrap (loop, type, iv0, iv1, niter); + delta = fold_build2 (MINUS_EXPR, niter_type, fold_convert (niter_type, iv1->base), fold_convert (niter_type, iv0->base)); @@ -1665,62 +1757,6 @@ dump_affine_iv (FILE *file, affine_iv *iv) } } -/* Given exit condition IV0 CODE IV1 in TYPE, this function adjusts - the condition for loop-until-wrap cases. For example: - (unsigned){8, -1}_loop < 10 => {0, 1} != 9 - 10 < (unsigned){0, max - 7}_loop => {0, 1} != 8 - Return true if condition is successfully adjusted. */ - -static bool -adjust_cond_for_loop_until_wrap (tree type, affine_iv *iv0, tree_code *code, - affine_iv *iv1) -{ - /* Only support simple cases for the moment. */ - if (TREE_CODE (iv0->base) != INTEGER_CST - || TREE_CODE (iv1->base) != INTEGER_CST) - return false; - - tree niter_type = unsigned_type_for (type), high, low; - /* Case: i-- < 10. */ - if (integer_zerop (iv1->step)) - { - /* TODO: Should handle case in which abs(step) != 1. */ - if (!integer_minus_onep (iv0->step)) - return false; - /* Give up on infinite loop. */ - if (*code == LE_EXPR - && tree_int_cst_equal (iv1->base, TYPE_MAX_VALUE (type))) - return false; - high = fold_build2 (PLUS_EXPR, niter_type, - fold_convert (niter_type, iv0->base), - build_int_cst (niter_type, 1)); - low = fold_convert (niter_type, TYPE_MIN_VALUE (type)); - } - else if (integer_zerop (iv0->step)) - { - /* TODO: Should handle case in which abs(step) != 1. */ - if (!integer_onep (iv1->step)) - return false; - /* Give up on infinite loop. */ - if (*code == LE_EXPR - && tree_int_cst_equal (iv0->base, TYPE_MIN_VALUE (type))) - return false; - high = fold_convert (niter_type, TYPE_MAX_VALUE (type)); - low = fold_build2 (MINUS_EXPR, niter_type, - fold_convert (niter_type, iv1->base), - build_int_cst (niter_type, 1)); - } - else - gcc_unreachable (); - - iv0->base = low; - iv0->step = fold_convert (niter_type, integer_one_node); - iv1->base = high; - iv1->step = build_int_cst (niter_type, 0); - *code = NE_EXPR; - return true; -} - /* Determine the number of iterations according to condition (for staying inside loop) which compares two induction variables using comparison operator CODE. The induction variable on left side of the comparison @@ -1855,15 +1891,6 @@ number_of_iterations_cond (class loop *loop, return true; } - /* Handle special case loops: while (i-- < 10) and while (10 < i++) by - adjusting iv0, iv1 and code. */ - if (code != NE_EXPR - && (tree_int_cst_sign_bit (iv0->step) - || (!integer_zerop (iv1->step) - && !tree_int_cst_sign_bit (iv1->step))) - && !adjust_cond_for_loop_until_wrap (type, iv0, &code, iv1)) - return false; - /* OK, now we know we have a senseful loop. Handle several cases, depending on what comparison operator is used. */ bound_difference (loop, iv1->base, iv0->base, &bnds); diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index edc11c6..4d688c7 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2311,6 +2311,10 @@ out: } if (dump_enabled_p ()) dump_printf (MSG_NOTE, "\n"); + /* After swapping some operands we lost track whether an + operand has any pattern defs so be conservative here. */ + if (oprnds_info[0]->any_pattern || oprnds_info[1]->any_pattern) + oprnds_info[0]->any_pattern = oprnds_info[1]->any_pattern = true; /* And try again with scratch 'matches' ... */ bool *tem = XALLOCAVEC (bool, group_size); if ((child = vect_build_slp_tree (vinfo, oprnd_info->def_stmts, |