diff options
author | Martin Liska <mliska@suse.cz> | 2021-10-21 11:51:37 +0200 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2021-10-21 11:51:37 +0200 |
commit | 9345234b2a80fbb26342f8c72aa8714d673c7dad (patch) | |
tree | d0c6a2f68a3f04ec322ebb6599f3e929d90ae809 /gcc | |
parent | 39887dd2c2c81cf3e98466827d59cafda279a258 (diff) | |
parent | 7878981f1d44b4c9bb6c4a3137b37f06c725b73d (diff) | |
download | gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.zip gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.tar.gz gcc-9345234b2a80fbb26342f8c72aa8714d673c7dad.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
253 files changed, 7185 insertions, 3474 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8175862..115f32e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,510 @@ +2021-10-20 Alex Coplan <alex.coplan@arm.com> + + * calls.c (initialize_argument_information): Remove some dead + code, remove handling for function_arg returning const_int. + * doc/tm.texi: Delete documentation for unused target hooks. + * doc/tm.texi.in: Likewise. + * target.def (load_bounds_for_arg): Delete. + (store_bounds_for_arg): Delete. + (load_returned_bounds): Delete. + (store_returned_bounds): Delete. + * targhooks.c (default_load_bounds_for_arg): Delete. + (default_store_bounds_for_arg): Delete. + (default_load_returned_bounds): Delete. + (default_store_returned_bounds): Delete. + * targhooks.h (default_load_bounds_for_arg): Delete. + (default_store_bounds_for_arg): Delete. + (default_load_returned_bounds): Delete. + (default_store_returned_bounds): Delete. + +2021-10-20 Jonathan Wakely <jwakely@redhat.com> + + * doc/extend.texi (Basic Asm): Clarify that asm is not an + extension in C++. + * doc/invoke.texi (-fno-asm): Fix description for C++. + +2021-10-20 Jonathan Wakely <jwakely@redhat.com> + + * doc/install.texi: Remove link to old.html + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_cmtst_same_<mode>): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_narrow_trunc<mode>): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (aarch64_simd_ashr<mode>): Add case cmp + case. + * config/aarch64/constraints.md (D1): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md + (*aarch64_<srn_op>topbits_shuffle<mode>_le): New. + (*aarch64_topbits_shuffle<mode>_le): New. + (*aarch64_<srn_op>topbits_shuffle<mode>_be): New. + (*aarch64_topbits_shuffle<mode>_be): New. + * config/aarch64/predicates.md + (aarch64_simd_shift_imm_vec_exact_top): New. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_<srn_op>shrn<mode>_vect, + *aarch64_<srn_op>shrn<mode>2_vect_le, + *aarch64_<srn_op>shrn<mode>2_vect_be): New. + * config/aarch64/iterators.md (srn_op): New. + +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * omp-low.c (omp_copy_decl_2): For !ctx, use record_vars to add new copy + as local variable. + (scan_sharing_clauses): Place copy of OMP_CLAUSE_IN_REDUCTION decl in + ctx->outer instead of ctx. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * config/i386/i386-options.c (ix86_valid_target_attribute_inner_p): Strip whitespaces. + * system.h (strip_whilespaces): New function. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * config/aarch64/aarch64.c (aarch64_process_one_target_attr): + Strip whitespaces. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (aarch64_case_values_threshold): + Change to 8 with -Os, 11 otherwise. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + * config/aarch64/aarch64.c (neoversev1_tunings): + Enable AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND. + (neoversen2_tunings): Likewise. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + PR target/100966 + * config/aarch64/aarch64.md (frint_pattern): Update comment. + * config/aarch64/aarch64-simd-builtins.def: Change frintn to roundeven. + * config/aarch64/arm_fp16.h: Change frintn to roundeven. + * config/aarch64/arm_neon.h: Likewise. + * config/aarch64/iterators.md (frint_pattern): Use roundeven for FRINTN. + +2021-10-20 Martin Liska <mliska@suse.cz> + + * config/arm/arm.c (arm_unwind_emit_sequence): Do not declare + already declared global variable. + (arm_unwind_emit_set): Use out_file as function argument. + (arm_unwind_emit): Likewise. + * config/darwin.c (machopic_output_data_section_indirection): Likewise. + (machopic_output_stub_indirection): Likewise. + (machopic_output_indirection): Likewise. + (machopic_finish): Likewise. + * config/i386/i386.c (ix86_asm_output_function_label): Likewise. + * config/i386/winnt.c (i386_pe_seh_unwind_emit): Likewise. + * config/ia64/ia64.c (process_epilogue): Likewise. + (process_cfa_adjust_cfa): Likewise. + (process_cfa_register): Likewise. + (process_cfa_offset): Likewise. + (ia64_asm_unwind_emit): Likewise. + * config/s390/s390.c (s390_asm_output_function_label): Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * config/aarch64/aarch64-builtins.c + (aarch64_general_gimple_fold_builtin): + lower vld1 and vst1 variants of the neon builtins + * config/aarch64/aarch64-protos.h: + (aarch64_general_gimple_fold_builtin): Add gsi parameter. + * config/aarch64/aarch64.c (aarch64_general_gimple_fold_builtin): + Likwise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * match.pd: Generate IFN_TRUNC. + +2021-10-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102853 + * tree-data-ref.c (split_constant_offset_1): Bail out + immediately if the expression traps on overflow. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (back_threader::~back_threader): Remove. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadupdate.c (back_jt_path_registry::adjust_paths_after_duplication): + Remove superflous debugging message. + (back_jt_path_registry::duplicate_thread_path): Same. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (back_threader_registry::back_threader_registry): + Remove. + (back_threader_registry::register_path): Remove m_threaded_paths. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/102814 + * doc/invoke.texi: Document --param=max-fsm-thread-length. + * params.opt: Add --param=max-fsm-thread-length. + * tree-ssa-threadbackward.c + (back_threader_profitability::profitable_path_p): Fail on paths + longer than max-fsm-thread-length. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/102764 + * cfgexpand.c (expand_gimple_basic_block): Disregard a final debug + statement to reset the current location for the outgoing edges. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + Richard Biener <rguenther@suse.de> + + * tree-ssa-threadupdate.c (cancel_thread): Dump threading reason + on the same line as the threading cancellation. + (jt_path_registry::cancel_invalid_paths): Avoid rotating loops. + Avoid threading through loop headers where the path remains in the + loop. + +2021-10-20 Siddhesh Poyarekar <siddhesh@gotplt.org> + + * tree-object-size.c (unknown): Make into a function. Adjust + all uses. + (unknown_object_size): Simplify implementation. + +2021-10-20 Hongtao Liu <hongtao.liu@intel.com> + Kewen Lin <linkw@linux.ibm.com> + + * doc/sourcebuild.texi (Effective-Target Keywords): Document + vect_slp_v2qi_store, vect_slp_v4qi_store, vect_slp_v8qi_store, + vect_slp_v16qi_store, vect_slp_v2hi_store, + vect_slp_v4hi_store, vect_slp_v2si_store, vect_slp_v4si_store. + +2021-10-19 Jonathan Wakely <jwakely@redhat.com> + + * doc/extend.texi (Basic PowerPC Built-in Functions): Fix typo. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + PR target/101893 + PR target/102719 + * config/rs6000/emmintrin.h: Guard POWER8 intrinsics. + * config/rs6000/pmmintrin.h: Same. + * config/rs6000/smmintrin.h: Same. + * config/rs6000/tmmintrin.h: Same. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + * config.gcc (extra_headers): Add nmmintrin.h. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_supportable_dr_alignment): Add + misalignment parameter. + * tree-vect-data-refs.c (vect_get_peeling_costs_all_drs): + Do not change DR_MISALIGNMENT in place, instead pass the + adjusted misalignment to vect_supportable_dr_alignment. + (vect_peeling_supportable): Likewise. + (vect_peeling_hash_get_lowest_cost): Adjust. + (vect_enhance_data_refs_alignment): Likewise. + (vect_vfa_access_size): Likewise. + (vect_supportable_dr_alignment): Add misalignment + parameter and simplify. + * tree-vect-stmts.c (get_negative_load_store_type): Adjust. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + +2021-10-19 Clément Chigot <clement.chigot@atos.net> + + * config/rs6000/rs6000.c (rs6000_xcoff_file_end): Move + __tls_get_addr reference to .text csect. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * config/aarch64/aarch64.c (aarch64_process_one_target_attr): + Strip whitespaces. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_get_store_cost): Adjust signature. + (vect_get_load_cost): Likewise. + * tree-vect-data-refs.c (vect_get_data_access_cost): Get + alignment support scheme and misalignment as arguments + and pass them down. + (vect_get_peeling_costs_all_drs): Compute that info here + and note that we shouldn't need to. + * tree-vect-stmts.c (vect_model_store_cost): Get + alignment support scheme and misalignment as arguments. + (vect_get_store_cost): Likewise. + (vect_model_load_cost): Likewise. + (vect_get_load_cost): Likewise. + (vectorizable_store): Pass down alignment support scheme + and misalignment to costing. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (get_negative_load_store_type): Add + offset output parameter and initialize it. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + (vectorizable_store): Use offset as computed by + get_load_store_type. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102827 + * tree-if-conv.c (predicate_statements): Add pe parameter + and use that edge to insert invariant stmts on. + (combine_blocks): Pass through pe. + (tree_if_conversion): Compute the edge to insert invariant + stmts on and pass it along. + +2021-10-19 Roger Sayle <roger@nextmovesoftware.com> + + PR target/102785 + * config/bfin/bfin.md (addsubv2hi3, subaddv2hi3, ssaddsubv2hi3, + sssubaddv2hi3): Swap the order of operators in vec_concat. + +2021-10-19 Xionghu Luo <luoxhu@linux.ibm.com> + + * config/rs6000/altivec.md (*altivec_vmrghb_internal): Delete. + (altivec_vmrghb_direct): New. + (*altivec_vmrghh_internal): Delete. + (altivec_vmrghh_direct): New. + (*altivec_vmrghw_internal): Delete. + (altivec_vmrghw_direct_<mode>): New. + (altivec_vmrghw_direct): Delete. + (*altivec_vmrglb_internal): Delete. + (altivec_vmrglb_direct): New. + (*altivec_vmrglh_internal): Delete. + (altivec_vmrglh_direct): New. + (*altivec_vmrglw_internal): Delete. + (altivec_vmrglw_direct_<mode>): New. + (altivec_vmrglw_direct): Delete. + * config/rs6000/rs6000-p8swap.c (rtx_is_swappable_p): Adjust. + * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): + Adjust. + * config/rs6000/vsx.md (vsx_xxmrghw_<mode>): Adjust. + (vsx_xxmrglw_<mode>): Adjust. + +2021-10-19 Aldy Hernandez <aldyh@redhat.com> + + * passes.def: Change threading comment before pass_ccp pass. + +2021-10-19 Haochen Gui <guihaoc@gcc.gnu.org> + + * config/rs6000/rs6000-call.c (altivec_expand_lxvr_builtin): + Modify the expansion for sign extension. All extensions are done + within VSX registers. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (get_group_load_store_type): Add + misalignment output parameter and initialize it. + (get_group_load_store_type): Likewise. + (vectorizable_store): Remove now redundant queries. + (vectorizable_load): Likewise. + +2021-10-19 Richard Biener <rguenther@suse.de> + + * tree-vectorizer.h (vect_supportable_dr_alignment): Remove + check_aligned argument. + * tree-vect-data-refs.c (vect_supportable_dr_alignment): + Likewise. + (vect_peeling_hash_insert): Add supportable_if_not_aligned + argument and do not call vect_supportable_dr_alignment here. + (vect_peeling_supportable): Adjust. + (vect_enhance_data_refs_alignment): Compute whether the + access is supported with different alignment here and + pass that down to vect_peeling_hash_insert. + (vect_vfa_access_size): Adjust. + * tree-vect-stmts.c (vect_get_store_cost): Likewise. + (vect_get_load_cost): Likewise. + (get_negative_load_store_type): Likewise. + (get_group_load_store_type): Likewise. + (get_load_store_type): Likewise. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * config/i386/i386-options.c (ix86_valid_target_attribute_inner_p): Strip whitespaces. + * system.h (strip_whilespaces): New function. + +2021-10-19 dianhong xu <dianhong.xu@intel.com> + + * config/i386/avx512fp16intrin.h: + (_mm512_set1_pch): New intrinsic. + * config/i386/avx512fp16vlintrin.h: + (_mm256_set1_pch): New intrinsic. + (_mm_set1_pch): Ditto. + +2021-10-18 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/102796 + * gimple-range.cc (gimple_ranger::range_on_edge): Process EH edges + normally. Return get_tree_range for non gimple_range_ssa_p names. + (gimple_ranger::range_of_stmt): Use get_tree_range for non + gimple_range_ssa_p names. + +2021-10-18 Uroš Bizjak <ubizjak@gmail.com> + + PR target/102761 + * config/i386/i386.c (ix86_print_operand_address): + Error out for non-address_operand asm operands. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-data-refs.c (vect_peeling_hash_insert): Do + not auto-convert dr_alignment_support to bool. + (vect_peeling_supportable): Likewise. + (vect_enhance_data_refs_alignment): Likewise. + (vect_supportable_dr_alignment): Commonize read/write case. + * tree-vect-stmts.c (vect_get_store_cost): Use + dr_alignment_support, not int, for the vect_supportable_dr_alignment + result. + (vect_get_load_cost): Likewise. + +2021-10-18 Siddhesh Poyarekar <siddhesh@gotplt.org> + + * tree-object-size.c (object_sizes_execute): Consolidate LHS + null check and do it early. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (vectorizable_store): Use the + computed alignment scheme instead of querying + aligned_access_p. + +2021-10-18 Richard Biener <rguenther@suse.de> + + * tree-vect-stmts.c (vectorizable_store): Do not recompute + alignment scheme already determined by get_load_store_type. + +2021-10-18 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-threadbackward.c (class pass_thread_jumps_full): + Clone corresponding pass. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * combine.c (recog_for_combine): For an unrecognized move/set of + a constant, try force_const_mem to place it in the constant pool. + * cse.c (constant_pool_entries_cost, constant_pool_entries_regcost): + Delete global variables (that are no longer assigned a cost value). + (cse_insn): Simplify logic for deciding whether to place a folded + constant in the constant pool using force_const_mem. + (cse_main): Remove zero initialization of constant_pool_entries_cost + and constant_pool_entries_regcost. + * config/i386/i386.c (ix86_rtx_costs): Make memory accesses + fractionally more expensive, when optimizing for speed. + +2021-10-18 Martin Liska <mliska@suse.cz> + + PR gcov-profile/102746 + PR gcov-profile/102747 + * gcov.c (main): Return return_code. + (output_gcov_file): Mark return_code when error happens. + (generate_results): Likewise. + (read_graph_file): Likewise. + (read_count_file): Likewise. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * config/bfin/bfin.md (define_constants): Remove UNSPEC_ONES. + (define_insn "ones"): Replace UNSPEC_ONES with a truncate of + a popcount, allowing compile-time evaluation/simplification. + (popcountsi2, popcounthi2): New expanders using a "ones" insn. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102788 + * tree-vect-patterns.c (vect_init_pattern_stmt): Allow + a NULL vectype. + (vect_pattern_recog_1): Likewise. + (vect_recog_bool_pattern): Continue matching the pattern + even if we do not have a vector type for a conversion + result. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * simplify-rtx.c (simplify_const_unary_operation) [SS_NEG, SS_ABS]: + Evalute SS_NEG and SS_ABS of a constant argument. + +2021-10-18 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gimple-match-head.c (try_conditional_simplification): Add case for single operand. + * internal-fn.def: Add entry for COND_NEG internal function. + * internal-fn.c (FOR_EACH_CODE_MAPPING): Add entry for + NEGATE_EXPR, COND_NEG mapping. + * optabs.def: Add entry for cond_neg_optab. + * match.pd (UNCOND_UNARY, COND_UNARY): New operator lists. + (vec_cond COND (foo A) B) -> (IFN_COND_FOO COND A B): New pattern. + (vec_cond COND B (foo A)) -> (IFN_COND_FOO ~COND A B): Likewise. + +2021-10-18 Aldy Hernandez <aldyh@redhat.com> + + * tree-ssa-strlen.c (class strlen_pass): Rename from + strlen_dom_walker. + (handle_builtin_stxncpy_strncat): Move to strlen_pass. + (handle_assign): Same. + (adjust_last_stmt): Same. + (maybe_warn_overflow): Same. + (handle_builtin_strlen): Same. + (handle_builtin_strchr): Same. + (handle_builtin_strcpy): Same. + (handle_builtin_strncat): Same. + (handle_builtin_stxncpy_strncat): Same. + (handle_builtin_memcpy): Same. + (handle_builtin_strcat): Same. + (handle_alloc_call): Same. + (handle_builtin_memset): Same. + (handle_builtin_memcmp): Same. + (get_len_or_size): Same. + (strxcmp_eqz_result): Same. + (handle_builtin_string_cmp): Same. + (handle_pointer_plus): Same. + (count_nonzero_bytes_addr): Same. + (count_nonzero_bytes): Same. + (handle_store): Same. + (strlen_check_and_optimize_call): Same. + (handle_integral_assign): Same. + (check_and_optimize_stmt): Same. + (printf_strlen_execute): Rename strlen_dom_walker to strlen_pass. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102798 + * tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): + Only copy points-to info to newly generated SSA names. + +2021-10-18 Martin Liska <mliska@suse.cz> + + * dbgcnt.c (dbg_cnt_process_opt): Remove unused but set variable. + * gcov.c (get_cycles_count): Likewise. + * lto-compress.c (lto_compression_zlib): Likewise. + (lto_uncompression_zlib): Likewise. + * targhooks.c (default_pch_valid_p): Likewise. + 2021-10-17 Aldy Hernandez <aldyh@redhat.com> * tree-pass.h (make_pass_thread_jumps_full): New. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 1a35f32..9b3296b 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20211018 +20211021 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c6d856a..13f349c 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,252 @@ +2021-10-20 Bob Duff <duff@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity): Remove unnecessary + call to No_Uint_To_0. + +2021-10-20 Richard Kenner <kenner@adacore.com> + + * exp_unst.adb (Visit_Node, when N_Subprogram_Call): Never treat + instrinsic subprograms as nested. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * libgnat/s-widlllu.ads: Mark in SPARK. + * libgnat/s-widllu.ads: Likewise. + * libgnat/s-widuns.ads: Likewise. + * libgnat/s-widthu.adb: Add ghost code and a + pseudo-postcondition. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * libgnat/a-nbnbin__ghost.adb (Signed_Conversions, + Unsigned_Conversions): Mark subprograms as not imported. + * libgnat/a-nbnbin__ghost.ads: Provide a dummy body. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.adb (Eval_Type_Conversion): If the target subtype is + a static floating-point subtype and the result is a real literal, + consider its machine-rounded value to raise Constraint_Error. + (Test_In_Range): Turn local variables into constants. + +2021-10-20 Doug Rupp <rupp@adacore.com> + + * libgnat/g-io-put__vxworks.adb: Remove (unused) + * libgnat/s-parame__ae653.ads: Likewise. + * libgnat/s-thread.ads: Likewise. + * libgnat/s-thread__ae653.adb: Likewise. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.ads (Machine_Number): New inline function. + * sem_eval.adb (Machine_Number): New function body implementing + the machine rounding operation specified by RM 4.9(38/2). + (Check_Non_Static_Context): Call Machine_Number and set the + Is_Machine_Number flag consistently on the resulting node. + * sem_attr.adb (Eval_Attribute) <Attribute_Machine>: Likewise. + * checks.adb (Apply_Float_Conversion_Check): Call Machine_Number. + (Round_Machine): Likewise. + +2021-10-20 Johannes Kliemann <kliemann@adacore.com> + + * vxworks7-cert-rtp-link.spec: Add the definition of + __wrs_rtp_base. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * sem_aggr.adb (Resolve_Delta_Record_Aggregate): Reject boxes in + record delta aggregates. + +2021-10-20 Justin Squirek <squirek@adacore.com> + + * sem_ch6.adb (Check_Return_Construct_Accessibility): Modify + generation of accessibility checks to be more consolidated and + get triggered properly in required cases. + * sem_util.adb (Accessibility_Level): Add extra check within + condition to handle aliased formals properly in more cases. + +2021-10-20 Justin Squirek <squirek@adacore.com> + + * exp_ch7.adb (Make_Final_Call): Detect expanded protected types + and use original protected type in order to calculate + appropriate finalization routine. + +2021-10-20 Johannes Kliemann <kliemann@adacore.com> + + * libgnat/a-nbnbin__ghost.ads: Add ghost package. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * sem_aggr.adb (Variant_Depth): Refine type from Integer to + Natural. + +2021-10-20 Bob Duff <duff@adacore.com> + + * atree.ads: Comment improvements. How is a "completely new + node" different from a "new node"? Document default values + corresponding to field types. + * exp_ch7.adb (Process_Tagged_Type_Declaration): Use + higher-level Scope_Depth instead of Scope_Depth_Value. Remove + confusing comment: not clear what a "true" library level package + is. + * uintp.adb (Image_Out): Print No_Uint in a more readable way. + * gen_il-gen.adb, gen_il-gen-gen_entities.adb, + gen_il-gen-gen_nodes.adb, gen_il-types.ads: Tighten up the + subtypes of fields whose type is Uint, where possible; use + more-constrained subtypes such as Unat. + * einfo-utils.adb, einfo-utils.ads, exp_attr.adb, + exp_ch3.adb, exp_intr.adb, exp_unst.adb, exp_util.adb, + freeze.adb, repinfo.adb, sem.adb, sem_ch12.adb, sem_ch13.adb, + sem_ch3.adb, sem_ch8.adb, sem_util.adb, sprint.adb, treepr.adb: + No longer use Uint_0 to indicate "unknown" or "not yet known" + for various fields whose type is Uint. Use No_Uint for that, + except in a small number of legacy cases that cause test + failures. Protect many queries of such fields with calls to + Known_... functions. Improve comments. + * exp_aggr.adb: Likewise. + (Is_OK_Aggregate): Check whether Csiz is present. + (Aggr_Assignment_OK_For_Backend): Ensure we do not access an + uninitialized size. + * exp_strm.adb (Build_Elementary_Input_Call, + Build_Elementary_Write_Call): Check whether P_Size is present. + * cstand.adb: Leave Component_Size of Any_Composite unknown. + Similar for RM_Size of Standard_Exception_Type. These should + not be used. + * einfo.ads: Comment improvements. + * exp_disp.ads: Minor. + * gen_il-internals.ads, gen_il-internals.adb: Minor. + * sinfo-utils.adb: Take advantage of full-coverage rules. + * types.h: Minor. + +2021-10-20 Gary Dismukes <dismukes@adacore.com> + + * sem_ch6.adb: Add with and use of Warnsw. + (Check_Conformance): Report a warning when subtypes or + designated subtypes of formal parameters or result subtypes + denote different declarations between the spec and body of the + (Subprogram_Subtypes_Have_Same_Declaration): New function nested + within Check_Conformance that determines whether two subtype + entities referenced in a subprogram come from the same + declaration. Returns True immediately if the subprogram is in a + generic instantiation, or the subprogram is marked Is_Internal + or is declared in an internal (GNAT library) unit, or GNAT_Mode + is enabled, otherwise compares the nonlimited views of the + entities (or their designated subtypes' nonlimited views in the + anonymous access cases). + (Nonlimited_View_Of_Subtype): New function nested within + function Subprogram_Subtypes_Have_Same_Declaration that returns + Non_Limited_View of a type or subtype that is an incomplete or + class-wide type that comes from a limited of a + package (From_Limited_With is True for the entity), or returns + Full_View when the nonlimited view is an incomplete type. + Otherwise returns the entity passed in. + * warnsw.ads (Warn_On_Pedantic_Checks): New warning flag. + (type Warning_Record): New component Warn_On_Pedantic_Checks. + * warnsw.adb (All_Warnings): Set Warn_On_Pedantic_Checks from + parameter Setting. + (Restore_Warnings): Restore the value of the + Warn_On_Pedantic_Checks flag. + (Save_Warnings): Save the value of the Warn_On_Pedantic_Checks + flag. + (Set_Underscore_Warning_Switch): Add settings of the + Warn_On_Pedantic flag according to the switch ("-gnatw_p" vs. + "-gnatw_P"). + * doc/gnat_ugn/building_executable_programs_with_gnat.rst: Add + documentation of new switches -gnatw_p and -gnatw_P (warnings + for pedantic checks). + * gnat_ugn.texi: Regenerate. + * usage.adb: Add Warn_On_Pedantic_Checks. + +2021-10-20 Piotr Trojanek <trojanek@adacore.com> + + * exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Guard + against equality of an uninitialized RM_Size field. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_ch12.adb (Analyze_Subprogram_Instantiation): Also propagate an + interface name on an intrinsic subprogram. Remove obsolete comment. + * libgnat/s-atopri.ads (Atomic_Load): New generic intrinsic function + (Atomic_Load_8): Rewrite into instantiation. + (Atomic_Load_16): Likewise. + (Atomic_Load_32): Likewise. + (Atomic_Load_64): Likewise. + (Sync_Compare_And_Swap): New generic intrinsic function. + (Sync_Compare_And_Swap_8): Rewrite into instantiation. + (Sync_Compare_And_Swap_16): Likewise. + (Sync_Compare_And_Swap_32): Likewise. + (Sync_Compare_And_Swap_64): Likewise. + (Lock_Free_Read): New generic inline function. + (Lock_Free_Read_8): Rewrite into instantiation. + (Lock_Free_Read_16): Likewise. + (Lock_Free_Read_32): Likewise. + (Lock_Free_Read_64): Likewise. + (Lock_Free_Try_Write): New generic inline function. + (Lock_Free_Try_Write_8): Rewrite into instantiation. + (Lock_Free_Try_Write_16): Likewise. + (Lock_Free_Try_Write_32): Likewise. + (Lock_Free_Try_Write_64): Likewise. + * libgnat/s-atopri.adb (Lock_Free_Read): New function body. + (Lock_Free_Read_8): Delete. + (Lock_Free_Read_16): Likewise. + (Lock_Free_Read_32): Likewise. + (Lock_Free_Read_64): Likewise. + (Lock_Free_Try_Write): New function body. + (Lock_Free_Try_Write_8): Delete. + (Lock_Free_Try_Write_16): Likewise. + (Lock_Free_Try_Write_32): Likewise. + (Lock_Free_Try_Write_64): Likewise. + * libgnat/s-aoinar.adb (Atomic_Fetch_And_Add): Use type-generic GCC + atomic builtin and tidy up implementation. + (Atomic_Fetch_And_Subtract): Likewise. + * libgnat/s-aomoar.adb (Atomic_Fetch_And_Add): Likewise. + (Atomic_Fetch_And_Subtract): Likewise. + * libgnat/s-atopex.adb (Atomic_Exchange): Likewise. + (Atomic_Compare_And_Exchange): Likewise. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Subprogram_Type>: + Replace test on Convention_Intrinsic with Is_Intrinsic_Subprogram. + (gnat_to_gnu_param): Likewise. + (gnat_to_gnu_subprog_type): Likewise. + * gcc-interface/trans.c (elaborate_all_entities_for_package): Ditto. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * sem_eval.ads (Check_Non_Static_Context): Update documentation. + * sem_eval.adb (In_Any_Integer_Context): Change parameter type, + adjust accordingly and remove unreachable case. + (Eval_Integer_Literal): Consider the node kind throughout and + trim down verbose condition. + +2021-10-20 Doug Rupp <rupp@adacore.com> + + * Makefile.rtl: Remove references to system-vxworks-ppc.ads + and system-vxworks-x86.ads. + * libgnat/system-vxworks-ppc.ads: Remove. + * libgnat/system-vxworks-ppc-ravenscar.ads: Likewise. + * libgnat/system-vxworks-x86.ads: Likewise. + +2021-10-20 Yannick Moy <moy@adacore.com> + + * sem_ch4.adb (Analyze_QUantified_Expression): Issue warning on + conjunct/disjunct sub-expression of the full expression inside a + quantified expression, when it does not reference the quantified + variable. + +2021-10-20 Marc Poulhiès <poulhies@adacore.com> + + * checks.adb (Insert_Valid_Check): in case of checked type + conversion, update Typ to match Exp's type and add call to + Analyze_And_Resolve. + +2021-10-20 Arnaud Charlet <charlet@adacore.com> + + PR ada/100486 + * sem_prag.adb (Check_Valid_Library_Unit_Pragma): Do not raise an + exception as part of the bootstrap. + 2021-10-15 Richard Biener <rguenther@suse.de> * gcc-interface/misc.c (gnat_post_options): Do not warn diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl index 7fef517..ebfbe95 100644 --- a/gcc/ada/Makefile.rtl +++ b/gcc/ada/Makefile.rtl @@ -1166,9 +1166,6 @@ ifeq ($(strip $(filter-out powerpc% wrs vxworks vxworksspe vxworks7% vxworks7spe s-vxwext.ads<libgnarl/s-vxwext__kernel.ads \ s-vxwext.adb<libgnarl/s-vxwext__kernel.adb \ system.ads<libgnat/$(SVX)-$(ARCH_STR)-kernel.ads - else - LIBGNAT_TARGET_PAIRS += \ - system.ads<libgnat/system-vxworks-ppc.ads endif endif EXTRA_GNATRTL_NONTASKING_OBJS+=i-vxinco.o i-vxwork.o i-vxwoio.o @@ -1315,9 +1312,6 @@ ifeq ($(strip $(filter-out %86 x86_64 wrs vxworks vxworks7%,$(target_cpu) $(targ s-vxwext.ads<libgnarl/s-vxwext__kernel.ads \ s-vxwext.adb<libgnarl/s-vxwext__kernel.adb \ system.ads<libgnat/$(SVX)-x86-kernel.ads - else - LIBGNAT_TARGET_PAIRS += \ - system.ads<libgnat/system-vxworks-x86.ads endif endif diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads index 2f3ca40..4861236 100644 --- a/gcc/ada/atree.ads +++ b/gcc/ada/atree.ads @@ -230,11 +230,18 @@ package Atree is function New_Node (New_Node_Kind : Node_Kind; New_Sloc : Source_Ptr) return Node_Id; - -- Allocates a completely new node with the given node type and source - -- location values. All other fields are set to their standard defaults: + -- Allocates a new node with the given node type and source location + -- values. Fields have defaults depending on their type: + + -- Flag: False + -- Node_Id: Empty + -- List_Id: Empty + -- Elist_Id: No_Elist + -- Uint: No_Uint -- - -- Empty for all FieldN fields - -- False for all FlagN fields + -- Name_Id, String_Id, Valid_Uint, Unat, Upos, Nonzero_Uint, Ureal: + -- No default. This means it is an error to call the getter before + -- calling the setter. -- -- The usual approach is to build a new node using this function and -- then, using the value returned, use the Set_xxx functions to set @@ -288,16 +295,16 @@ package Atree is -- with copying aspect specifications where this is required. function New_Copy (Source : Node_Id) return Node_Id; - -- This function allocates a completely new node, and then initializes - -- it by copying the contents of the source node into it. The contents of - -- the source node is not affected. The target node is always marked as - -- not being in a list (even if the source is a list member), and not - -- overloaded. The new node will have an extension if the source has - -- an extension. New_Copy (Empty) returns Empty, and New_Copy (Error) - -- returns Error. Note that, unlike Copy_Separate_Tree, New_Copy does not - -- recursively copy any descendants, so in general parent pointers are not - -- set correctly for the descendants of the copied node. Both normal and - -- extended nodes (entities) may be copied using New_Copy. + -- This function allocates a new node, and then initializes it by copying + -- the contents of the source node into it. The contents of the source node + -- is not affected. The target node is always marked as not being in a list + -- (even if the source is a list member), and not overloaded. The new node + -- will have an extension if the source has an extension. New_Copy (Empty) + -- returns Empty, and New_Copy (Error) returns Error. Note that, unlike + -- Copy_Separate_Tree, New_Copy does not recursively copy any descendants, + -- so in general parent pointers are not set correctly for the descendants + -- of the copied node. Both normal and extended nodes (entities) may be + -- copied using New_Copy. function Relocate_Node (Source : Node_Id) return Node_Id; -- Source is a non-entity node that is to be relocated. A new node is @@ -340,11 +347,11 @@ package Atree is -- Exchange the contents of two entities. The parent pointers are switched -- as well as the Defining_Identifier fields in the parents, so that the -- entities point correctly to their original parents. The effect is thus - -- to leave the tree completely unchanged in structure, except that the - -- entity ID values of the two entities are interchanged. Neither of the - -- two entities may be list members. Note that entities appear on two - -- semantic chains: Homonym and Next_Entity: the corresponding links must - -- be adjusted by the caller, according to context. + -- to leave the tree unchanged in structure, except that the entity ID + -- values of the two entities are interchanged. Neither of the two entities + -- may be list members. Note that entities appear on two semantic chains: + -- Homonym and Next_Entity: the corresponding links must be adjusted by the + -- caller, according to context. procedure Extend_Node (Source : Node_Id); -- This turns a node into an entity; it function is used only by Sinfo.CN. diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb index a58a495..c85cba9a5 100644 --- a/gcc/ada/checks.adb +++ b/gcc/ada/checks.adb @@ -2171,7 +2171,7 @@ package body Checks is Lo_OK := (Ifirst > 0); else - Lo := Machine (Expr_Type, UR_From_Uint (Ifirst), Round_Even, Expr); + Lo := Machine_Number (Expr_Type, UR_From_Uint (Ifirst), Expr); Lo_OK := (Lo >= UR_From_Uint (Ifirst)); end if; @@ -2214,7 +2214,7 @@ package body Checks is Hi := UR_From_Uint (Ilast) + Ureal_Half; Hi_OK := (Ilast < 0); else - Hi := Machine (Expr_Type, UR_From_Uint (Ilast), Round_Even, Expr); + Hi := Machine_Number (Expr_Type, UR_From_Uint (Ilast), Expr); Hi_OK := (Hi <= UR_From_Uint (Ilast)); end if; @@ -5563,7 +5563,7 @@ package body Checks is -- the results in Lo_Right, Hi_Right, Lo_Left, Hi_Left. function Round_Machine (B : Ureal) return Ureal; - -- B is a real bound. Round it using mode Round_Even. + -- B is a real bound. Round it to the nearest machine number. ----------------- -- OK_Operands -- @@ -5589,7 +5589,7 @@ package body Checks is function Round_Machine (B : Ureal) return Ureal is begin - return Machine (Typ, B, Round_Even, N); + return Machine_Number (Typ, B, N); end Round_Machine; -- Start of processing for Determine_Range_R @@ -8077,7 +8077,7 @@ package body Checks is Is_High_Bound : Boolean := False) is Loc : constant Source_Ptr := Sloc (Expr); - Typ : constant Entity_Id := Etype (Expr); + Typ : Entity_Id := Etype (Expr); Exp : Node_Id; begin @@ -8137,6 +8137,7 @@ package body Checks is while Nkind (Exp) = N_Type_Conversion loop Exp := Expression (Exp); end loop; + Typ := Etype (Exp); -- Do not generate a check for a variable which already validates the -- value of an assignable object. @@ -8217,6 +8218,14 @@ package body Checks is Set_Do_Range_Check (Validated_Object (Var_Id), False); end if; + -- In case of a type conversion, an expansion of the expr may be + -- needed (eg. fixed-point as actual). + + if Exp /= Expr then + pragma Assert (Nkind (Expr) = N_Type_Conversion); + Analyze_And_Resolve (Expr); + end if; + PV := New_Occurrence_Of (Var_Id, Loc); -- Otherwise the expression does not denote a variable. Force its diff --git a/gcc/ada/cstand.adb b/gcc/ada/cstand.adb index 41de2a5..3822d93 100644 --- a/gcc/ada/cstand.adb +++ b/gcc/ada/cstand.adb @@ -1233,10 +1233,11 @@ package body CStand is Mutate_Ekind (Any_Composite, E_Array_Type); Set_Scope (Any_Composite, Standard_Standard); Set_Etype (Any_Composite, Any_Composite); - Set_Component_Size (Any_Composite, Uint_0); Set_Component_Type (Any_Composite, Standard_Integer); Reinit_Size_Align (Any_Composite); + pragma Assert (not Known_Component_Size (Any_Composite)); + Any_Discrete := New_Standard_Entity ("a discrete type"); Mutate_Ekind (Any_Discrete, E_Signed_Integer_Type); Set_Scope (Any_Discrete, Standard_Standard); @@ -1508,10 +1509,11 @@ package body CStand is Set_Scope (Standard_Exception_Type, Standard_Standard); Set_Stored_Constraint (Standard_Exception_Type, No_Elist); - Set_RM_Size (Standard_Exception_Type, Uint_0); Set_Size_Known_At_Compile_Time (Standard_Exception_Type, True); + pragma Assert (not Known_RM_Size (Standard_Exception_Type)); + Make_Aliased_Component (Standard_Exception_Type, Standard_Boolean, "Not_Handled_By_Others"); Make_Aliased_Component (Standard_Exception_Type, Standard_Character, diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst index 67fd130..48b7623 100644 --- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst +++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst @@ -3582,6 +3582,25 @@ of the pragma in the :title:`GNAT_Reference_manual`). ordering. +.. index:: -gnatw_p (gcc) + +:switch:`-gnatw_p` + *Activate warnings for pedantic checks.* + + This switch activates warnings for the failure of certain pedantic checks. + The only case currently supported is a check that the subtype_marks given + for corresponding formal parameter and function results in a subprogram + declaration and its body denote the same subtype declaration. The default + is that such warnings are not given. + +.. index:: -gnatw_P (gcc) + +:switch:`-gnatw_P` + *Suppress warnings for pedantic checks.* + + This switch suppresses warnings on violations of pedantic checks. + + .. index:: -gnatwq (gcc) .. index:: Parentheses, warnings diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb index 0274e6b..0c89c82 100644 --- a/gcc/ada/einfo-utils.adb +++ b/gcc/ada/einfo-utils.adb @@ -390,34 +390,23 @@ package body Einfo.Utils is function Known_Static_Component_Bit_Offset (E : Entity_Id) return B is begin - return Present (Component_Bit_Offset (E)) + return Known_Component_Bit_Offset (E) and then Component_Bit_Offset (E) >= Uint_0; end Known_Static_Component_Bit_Offset; function Known_Component_Size (E : Entity_Id) return B is begin - return Component_Size (E) /= Uint_0 - and then Present (Component_Size (E)); + return Present (Component_Size (E)); end Known_Component_Size; function Known_Static_Component_Size (E : Entity_Id) return B is begin - return Component_Size (E) > Uint_0; + return Known_Component_Size (E) and then Component_Size (E) >= Uint_0; end Known_Static_Component_Size; - Use_New_Unknown_Rep : constant Boolean := False; - -- If False, we represent "unknown" as Uint_0, which is wrong. - -- We intend to make it True (and remove it), and represent - -- "unknown" as Field_Is_Initial_Zero. We also need to change - -- the type of Esize and RM_Size from Uint to Valid_Uint. - function Known_Esize (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return not Field_Is_Initial_Zero (E, F_Esize); - else - return Present (Esize (E)) and then Esize (E) /= Uint_0; - end if; + return Present (Esize (E)); end Known_Esize; function Known_Static_Esize (E : Entity_Id) return B is @@ -429,11 +418,7 @@ package body Einfo.Utils is procedure Reinit_Esize (Id : E) is begin - if Use_New_Unknown_Rep then - Reinit_Field_To_Zero (Id, F_Esize); - else - Set_Esize (Id, Uint_0); - end if; + Reinit_Field_To_Zero (Id, F_Esize); end Reinit_Esize; procedure Copy_Esize (To, From : E) is @@ -452,7 +437,7 @@ package body Einfo.Utils is function Known_Static_Normalized_First_Bit (E : Entity_Id) return B is begin - return Present (Normalized_First_Bit (E)) + return Known_Normalized_First_Bit (E) and then Normalized_First_Bit (E) >= Uint_0; end Known_Static_Normalized_First_Bit; @@ -463,43 +448,25 @@ package body Einfo.Utils is function Known_Static_Normalized_Position (E : Entity_Id) return B is begin - return Present (Normalized_Position (E)) + return Known_Normalized_Position (E) and then Normalized_Position (E) >= Uint_0; end Known_Static_Normalized_Position; function Known_RM_Size (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return not Field_Is_Initial_Zero (E, F_RM_Size); - else - return Present (RM_Size (E)) - and then (RM_Size (E) /= Uint_0 - or else Is_Discrete_Type (E) - or else Is_Fixed_Point_Type (E)); - end if; + return Present (RM_Size (E)); end Known_RM_Size; function Known_Static_RM_Size (E : Entity_Id) return B is begin - if Use_New_Unknown_Rep then - return Known_RM_Size (E) - and then RM_Size (E) >= Uint_0 - and then not Is_Generic_Type (E); - else - return (RM_Size (E) > Uint_0 - or else Is_Discrete_Type (E) - or else Is_Fixed_Point_Type (E)) - and then not Is_Generic_Type (E); - end if; + return Known_RM_Size (E) + and then RM_Size (E) >= Uint_0 + and then not Is_Generic_Type (E); end Known_Static_RM_Size; procedure Reinit_RM_Size (Id : E) is begin - if Use_New_Unknown_Rep then - Reinit_Field_To_Zero (Id, F_RM_Size); - else - Set_RM_Size (Id, Uint_0); - end if; + Reinit_Field_To_Zero (Id, F_RM_Size); end Reinit_RM_Size; procedure Copy_RM_Size (To, From : E) is @@ -541,9 +508,8 @@ package body Einfo.Utils is begin pragma Assert (Is_Type (Id)); pragma Assert (not Known_Esize (Id) or else Esize (Id) = V); - if Use_New_Unknown_Rep then - pragma Assert (not Known_RM_Size (Id) or else RM_Size (Id) = V); - end if; + pragma Assert (not Known_RM_Size (Id) or else RM_Size (Id) = V); + Set_Esize (Id, UI_From_Int (V)); Set_RM_Size (Id, UI_From_Int (V)); end Init_Size; @@ -2593,6 +2559,16 @@ package body Einfo.Utils is return Scope_Depth_Value (Scop); end Scope_Depth; + function Scope_Depth_Default_0 (Id : E) return U is + begin + if Scope_Depth_Set (Id) then + return Scope_Depth (Id); + + else + return Uint_0; + end if; + end Scope_Depth_Default_0; + --------------------- -- Scope_Depth_Set -- --------------------- diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads index 8046722..0e6c8cd 100644 --- a/gcc/ada/einfo-utils.ads +++ b/gcc/ada/einfo-utils.ads @@ -274,14 +274,21 @@ package Einfo.Utils is function Safe_Emax_Value (Id : E) return U; function Safe_First_Value (Id : E) return R; function Safe_Last_Value (Id : E) return R; - function Scope_Depth (Id : E) return U; - function Scope_Depth_Set (Id : E) return B; function Size_Clause (Id : E) return N; function Stream_Size_Clause (Id : E) return N; function Type_High_Bound (Id : E) return N; function Type_Low_Bound (Id : E) return N; function Underlying_Type (Id : E) return E; + function Scope_Depth (Id : E) return U; + function Scope_Depth_Set (Id : E) return B; + + function Scope_Depth_Default_0 (Id : E) return U; + -- In rare cases, the Scope_Depth_Value (queried by Scope_Depth) is + -- not correctly set before querying it; this may be used instead of + -- Scope_Depth in such cases. It returns Uint_0 if the Scope_Depth_Value + -- has not been set. See documentation in Einfo. + pragma Inline (Address_Clause); pragma Inline (Alignment_Clause); pragma Inline (Base_Type); @@ -314,41 +321,58 @@ package Einfo.Utils is -- Type Representation Attribute Fields -- ------------------------------------------ - -- Each of the following fields can be in a "known" or "unknown" state: + function Known_Alignment (E : Entity_Id) return B with Inline; + procedure Reinit_Alignment (Id : E) with Inline; + procedure Copy_Alignment (To, From : E); + + function Known_Component_Bit_Offset (E : Entity_Id) return B with Inline; + function Known_Static_Component_Bit_Offset (E : Entity_Id) return B + with Inline; + + function Known_Component_Size (E : Entity_Id) return B with Inline; + function Known_Static_Component_Size (E : Entity_Id) return B with Inline; + + function Known_Esize (E : Entity_Id) return B with Inline; + function Known_Static_Esize (E : Entity_Id) return B with Inline; + procedure Reinit_Esize (Id : E) with Inline; + procedure Copy_Esize (To, From : E); + + function Known_Normalized_First_Bit (E : Entity_Id) return B with Inline; + function Known_Static_Normalized_First_Bit (E : Entity_Id) return B + with Inline; + + function Known_Normalized_Position (E : Entity_Id) return B with Inline; + function Known_Static_Normalized_Position (E : Entity_Id) return B + with Inline; + + function Known_RM_Size (E : Entity_Id) return B with Inline; + function Known_Static_RM_Size (E : Entity_Id) return B with Inline; + procedure Reinit_RM_Size (Id : E) with Inline; + procedure Copy_RM_Size (To, From : E); - -- Alignment - -- Component_Size - -- Component_Bit_Offset - -- Digits_Value - -- Esize - -- Normalized_First_Bit - -- Normalized_Position - -- RM_Size - -- -- NOTE: "known" here does not mean "known at compile time". It means that -- the compiler has computed the value of the field (either by default, or -- by noting some representation clauses), and the field has not been -- reinitialized. -- - -- We document the Esize functions here; the others are analogous: + -- We document the Esize functions here; the others above are analogous: -- -- Known_Esize: True if Set_Esize has been called without a subsequent -- Reinit_Esize. -- -- Known_Static_Esize: True if Known_Esize and the Esize is known at -- compile time. (We're not using "static" in the Ada RM sense here. We - -- are using it to mean "known at compile time.) + -- are using it to mean "known at compile time".) -- -- Reinit_Esize: Set the Esize field to its initial unknown state. -- -- Copy_Esize: Copies the Esize from From to To; Known_Esize (From) may -- be False, in which case Known_Esize (To) becomes False. -- - -- Esize: This is the normal automatially-generated getter for Esize, - -- declared elsewhere. It is an error to call this if Set_Esize has not - -- yet been called, or if Reinit_Esize has been called subsequently. + -- Esize: This is the normal automatically-generated getter for Esize, + -- declared elsewhere. Returns No_Uint if not Known_Esize. -- - -- Set_Esize: This is the normal automatially-generated setter for + -- Set_Esize: This is the normal automatically-generated setter for -- Esize. After a call to this, Known_Esize is True. It is an error -- to call this with a No_Uint value. -- @@ -357,13 +381,6 @@ package Einfo.Utils is -- before calling Esize, because the code is written in such a way that we -- don't know whether Set_Esize has already been called. -- - -- We intend to use the initial zero value to represent "unknown". Note - -- that this value is different from No_Uint, and different from Uint_0. - -- However, this is work in progress; we are still using No_Uint or Uint_0 - -- to represent "unknown" in some cases. Using Uint_0 leads to several - -- bugs, because zero is a legitimate value (T'Size can be zero bits) -- - -- Uint_0 shouldn't mean two different things. - -- -- In two cases, Known_Static_Esize and Known_Static_RM_Size, there is one -- more consideration, which is that we always return False for generic -- types. Within a template, the size can look Known_Static, because of the @@ -371,35 +388,6 @@ package Einfo.Utils is -- Known_Static and anyone testing if they are Known_Static within the -- template should get False as a result to prevent incorrect assumptions. - function Known_Alignment (E : Entity_Id) return B with Inline; - procedure Reinit_Alignment (Id : E) with Inline; - procedure Copy_Alignment (To, From : E); - - function Known_Component_Bit_Offset (E : Entity_Id) return B with Inline; - function Known_Static_Component_Bit_Offset (E : Entity_Id) return B - with Inline; - - function Known_Component_Size (E : Entity_Id) return B with Inline; - function Known_Static_Component_Size (E : Entity_Id) return B with Inline; - - function Known_Esize (E : Entity_Id) return B with Inline; - function Known_Static_Esize (E : Entity_Id) return B with Inline; - procedure Reinit_Esize (Id : E) with Inline; - procedure Copy_Esize (To, From : E); - - function Known_Normalized_First_Bit (E : Entity_Id) return B with Inline; - function Known_Static_Normalized_First_Bit (E : Entity_Id) return B - with Inline; - - function Known_Normalized_Position (E : Entity_Id) return B with Inline; - function Known_Static_Normalized_Position (E : Entity_Id) return B - with Inline; - - function Known_RM_Size (E : Entity_Id) return B with Inline; - function Known_Static_RM_Size (E : Entity_Id) return B with Inline; - procedure Reinit_RM_Size (Id : E) with Inline; - procedure Copy_RM_Size (To, From : E); - --------------------------------------------------------- -- Procedures for setting multiple of the above fields -- --------------------------------------------------------- diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads index 0239a70..13440ce 100644 --- a/gcc/ada/einfo.ads +++ b/gcc/ada/einfo.ads @@ -4323,7 +4323,8 @@ package Einfo is -- Indicates the number of scopes that statically enclose the declaration -- of the unit or type. Library units have a depth of zero. Note that -- record types can act as scopes but do NOT have this field set (see --- Scope_Depth above). +-- Scope_Depth above). Queries should normally be via Scope_Depth, +-- and not call Scope_Depth_Value directly. -- Scope_Depth_Set (synthesized) -- Applies to a special predicate function that returns a Boolean value @@ -4555,7 +4556,7 @@ package Einfo is -- in inheritance of subprograms between views of the same type. -- Subps_Index --- Present in subprogram entries. Set if the subprogram contains nested +-- Present in subprogram entities. Set if the subprogram contains nested -- subprograms, or is a subprogram nested within such a subprogram. Holds -- the index in the Exp_Unst.Subps table for the subprogram. Note that -- for the outer level subprogram, this is the starting index in the Subp diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index ebc7a87..f3d83a5 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -490,7 +490,7 @@ package body Exp_Aggr is -- Fat pointers are rejected as they are not really elementary -- for the backend. - if Csiz /= System_Address_Size then + if No (Csiz) or else Csiz /= System_Address_Size then return False; end if; @@ -504,8 +504,7 @@ package body Exp_Aggr is -- Scalar types are OK if their size is a multiple of Storage_Unit - elsif Is_Scalar_Type (Ctyp) then - pragma Assert (Present (Csiz)); + elsif Is_Scalar_Type (Ctyp) and then Present (Csiz) then if Csiz mod System_Storage_Unit /= 0 then return False; @@ -9098,11 +9097,11 @@ package body Exp_Aggr is ----------------------------- function Is_Two_Dim_Packed_Array (Typ : Entity_Id) return Boolean is - C : constant Int := UI_To_Int (Component_Size (Typ)); + C : constant Uint := Component_Size (Typ); begin return Number_Dimensions (Typ) = 2 and then Is_Bit_Packed_Array (Typ) - and then (C = 1 or else C = 2 or else C = 4); + and then C in Uint_1 | Uint_2 | Uint_4; -- False if No_Uint end Is_Two_Dim_Packed_Array; -------------------- diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index 096671f..49f5c94 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -6294,7 +6294,7 @@ package body Exp_Attr is -- size. This applies to both types and objects. The size of an -- object can be specified in the following ways: - -- An explicit size object is given for an object + -- An explicit size clause is given for an object -- A component size is specified for an indexed component -- A component clause is specified for a selected component -- The object is a component of a packed composite object @@ -6310,7 +6310,7 @@ package body Exp_Attr is or else Is_Packed (Etype (Prefix (Pref))))) or else (Nkind (Pref) = N_Indexed_Component - and then (Component_Size (Etype (Prefix (Pref))) /= 0 + and then (Known_Component_Size (Etype (Prefix (Pref))) or else Is_Packed (Etype (Prefix (Pref))))) then Set_Attribute_Name (N, Name_Size); @@ -7970,7 +7970,6 @@ package body Exp_Attr is elsif Id = Attribute_Size and then Is_Entity_Name (Pref) and then Is_Object (Entity (Pref)) - and then Known_Esize (Entity (Pref)) and then Known_Static_Esize (Entity (Pref)) then Siz := Esize (Entity (Pref)); diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb index d4373ee..e7eed28 100644 --- a/gcc/ada/exp_ch3.adb +++ b/gcc/ada/exp_ch3.adb @@ -942,11 +942,11 @@ package body Exp_Ch3 is (Case_Id : Entity_Id; Variant : Node_Id) return Node_Id; -- Build a case statement containing only two alternatives. The first - -- alternative corresponds exactly to the discrete choices given on the - -- variant with contains the components that we are generating the - -- checks for. If the discriminant is one of these return False. The - -- second alternative is an OTHERS choice that will return True - -- indicating the discriminant did not match. + -- alternative corresponds to the discrete choices given on the variant + -- that contains the components that we are generating the checks + -- for. If the discriminant is one of these return False. The second + -- alternative is an OTHERS choice that returns True indicating the + -- discriminant did not match. function Build_Dcheck_Function (Case_Id : Entity_Id; @@ -976,6 +976,7 @@ package body Exp_Ch3 is begin Case_Node := New_Node (N_Case_Statement, Loc); + Set_End_Span (Case_Node, Uint_0); -- Replace the discriminant which controls the variant with the name -- of the formal of the checking function. diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 71cad98..cd9ff21 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -3613,11 +3613,10 @@ package body Exp_Ch7 is and then (not Is_Library_Level_Entity (Spec_Id) - -- Nested packages are considered to be library level entities, - -- but do not need to be processed separately. True library level - -- packages have a scope value of 1. + -- Nested packages are library level entities, but do not need to + -- be processed separately. - or else Scope_Depth_Value (Spec_Id) /= Uint_1 + or else Scope_Depth (Spec_Id) /= Uint_1 or else (Is_Generic_Instance (Spec_Id) and then Package_Instantiation (Spec_Id) /= N)) @@ -8954,11 +8953,12 @@ package body Exp_Ch7 is Typ : Entity_Id; Skip_Self : Boolean := False) return Node_Id is - Loc : constant Source_Ptr := Sloc (Obj_Ref); - Atyp : Entity_Id; - Fin_Id : Entity_Id := Empty; - Ref : Node_Id; - Utyp : Entity_Id; + Loc : constant Source_Ptr := Sloc (Obj_Ref); + Atyp : Entity_Id; + Prot_Typ : Entity_Id := Empty; + Fin_Id : Entity_Id := Empty; + Ref : Node_Id; + Utyp : Entity_Id; begin Ref := Obj_Ref; @@ -9036,6 +9036,19 @@ package body Exp_Ch7 is Set_Assignment_OK (Ref); end if; + -- Detect if Typ is a protected type or an expanded protected type and + -- store the relevant type within Prot_Typ for later processing. + + if Is_Protected_Type (Typ) then + Prot_Typ := Typ; + + elsif Ekind (Typ) = E_Record_Type + and then Present (Corresponding_Concurrent_Type (Typ)) + and then Is_Protected_Type (Corresponding_Concurrent_Type (Typ)) + then + Prot_Typ := Corresponding_Concurrent_Type (Typ); + end if; + -- The underlying type may not be present due to a missing full view. In -- this case freezing did not take place and there is no [Deep_]Finalize -- primitive to call. @@ -9081,7 +9094,7 @@ package body Exp_Ch7 is -- Protected types: these also require finalization even though they -- are not marked controlled explicitly. - elsif Is_Protected_Type (Typ) then + elsif Present (Prot_Typ) then -- Protected objects do not need to be finalized on restricted -- runtimes. @@ -9091,7 +9104,7 @@ package body Exp_Ch7 is -- ??? Only handle the simple case for now. Will not support a record -- or array containing protected objects. - elsif Is_Simple_Protected_Type (Typ) then + elsif Is_Simple_Protected_Type (Prot_Typ) then Fin_Id := RTE (RE_Finalize_Protection); else raise Program_Error; diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads index 9d9811b..f286763 100644 --- a/gcc/ada/exp_disp.ads +++ b/gcc/ada/exp_disp.ads @@ -373,9 +373,9 @@ package Exp_Disp is -- target object in its first argument; such implicit argument is explicit -- in the IP procedures built here. - procedure Set_DT_Position_Value (Prim : Entity_Id; Value : Uint); - -- Set the position of a dispatching primitive its dispatch table. For - -- subprogram wrappers propagate the value to the wrapped subprogram. + procedure Set_DT_Position_Value (Prim : Entity_Id; Value : Uint); + -- Set the position of a dispatching primitive in its dispatch table. + -- For subprogram wrappers propagate the value to the wrapped subprogram. procedure Set_DTC_Entity_Value (Tagged_Type : Entity_Id; Prim : Entity_Id); -- Set the definite value of the DTC_Entity value associated with a given diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb index 86cb702..c139bb4 100644 --- a/gcc/ada/exp_intr.adb +++ b/gcc/ada/exp_intr.adb @@ -325,7 +325,7 @@ package body Exp_Intr is Result_Typ := Class_Wide_Type (Etype (Act_Constr)); -- Check that the accessibility level of the tag is no deeper than that - -- of the constructor function (unless CodePeer_Mode) + -- of the constructor function (unless CodePeer_Mode). if not CodePeer_Mode then Insert_Action (N, @@ -335,7 +335,8 @@ package body Exp_Intr is Left_Opnd => Build_Get_Access_Level (Loc, New_Copy_Tree (Tag_Arg)), Right_Opnd => - Make_Integer_Literal (Loc, Scope_Depth (Act_Constr))), + Make_Integer_Literal + (Loc, Scope_Depth_Default_0 (Act_Constr))), Then_Statements => New_List ( Make_Raise_Statement (Loc, diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb index bbfee62..bce745b 100644 --- a/gcc/ada/exp_spark.adb +++ b/gcc/ada/exp_spark.adb @@ -451,6 +451,7 @@ package body Exp_SPARK is Apply_Universal_Integer_Attribute_Checks (N); if Present (Typ) + and then Known_RM_Size (Typ) and then RM_Size (Typ) = RM_Size (Standard_Long_Long_Integer) then -- ??? This should rather be a range check, but this would diff --git a/gcc/ada/exp_strm.adb b/gcc/ada/exp_strm.adb index c87b881..8983dab1c 100644 --- a/gcc/ada/exp_strm.adb +++ b/gcc/ada/exp_strm.adb @@ -624,7 +624,7 @@ package body Exp_Strm is end if; else pragma Assert (Is_Access_Type (U_Type)); - if P_Size > System_Address_Size then + if Present (P_Size) and then P_Size > System_Address_Size then Lib_RE := RE_I_AD; else Lib_RE := RE_I_AS; @@ -868,7 +868,7 @@ package body Exp_Strm is else pragma Assert (Is_Access_Type (U_Type)); - if P_Size > System_Address_Size then + if Present (P_Size) and then P_Size > System_Address_Size then Lib_RE := RE_W_AD; else Lib_RE := RE_W_AS; diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb index c071a9c..be06580 100644 --- a/gcc/ada/exp_unst.adb +++ b/gcc/ada/exp_unst.adb @@ -270,7 +270,9 @@ package body Exp_Unst is begin pragma Assert (Is_Subprogram (E)); - if Subps_Index (E) = Uint_0 then + if Field_Is_Initial_Zero (E, F_Subps_Index) + or else Subps_Index (E) = Uint_0 + then E := Ultimate_Alias (E); -- The body of a protected operation has a different name and @@ -886,6 +888,7 @@ package body Exp_Unst is if Is_Subprogram (Ent) and then not Is_Generic_Subprogram (Ent) and then not Is_Imported (Ent) + and then not Is_Intrinsic_Subprogram (Ent) and then Scope_Within (Ultimate_Alias (Ent), Subp) then Append_Unique_Call ((N, Current_Subprogram, Ent)); diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 0a6837c..9bc9449 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -4784,7 +4784,8 @@ package body Exp_Util is -- record or bit-packed array, then everything is fine, since the back -- end can handle these cases correctly. - elsif Esize (Comp) <= System_Max_Integer_Size + elsif Known_Esize (Comp) + and then Esize (Comp) <= System_Max_Integer_Size and then (Is_Record_Type (UT) or else Is_Bit_Packed_Array (UT)) then return False; diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 5f81d9e..fac7094 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -865,9 +865,12 @@ package body Freeze is Error_Msg_NE (Size_Too_Small_Message, Size_Clause (T), T); end if; - -- Set size if not set already + -- Set size if not set already. Do not set it to Uint_0, because in + -- some cases (notably array-of-record), the Component_Size is + -- No_Uint, which causes S to be Uint_0. Presumably the RM_Size and + -- Component_Size will eventually be set correctly by the back end. - elsif not Known_RM_Size (T) then + elsif not Known_RM_Size (T) and then S /= Uint_0 then Set_RM_Size (T, S); end if; end Set_Small_Size; @@ -899,8 +902,17 @@ package body Freeze is -- String literals always have known size, and we can set it if Ekind (T) = E_String_Literal_Subtype then - Set_Small_Size - (T, Component_Size (T) * String_Literal_Length (T)); + if Known_Component_Size (T) then + Set_Small_Size + (T, Component_Size (T) * String_Literal_Length (T)); + + else + -- The following is wrong, but does what previous versions + -- did. The Component_Size is unknown for the string in a + -- pragma Warnings. + Set_Small_Size (T, Uint_0); + end if; + return True; -- Unconstrained types never have known at compile time size @@ -932,6 +944,12 @@ package body Freeze is Dim : Uint; begin + -- See comment in Set_Small_Size above + + if No (Size) then + Size := Uint_0; + end if; + Index := First_Index (T); while Present (Index) loop if Nkind (Index) = N_Range then @@ -954,7 +972,7 @@ package body Freeze is else Dim := Expr_Value (High) - Expr_Value (Low) + 1; - if Dim >= 0 then + if Dim > Uint_0 then Size := Size * Dim; else Size := Uint_0; @@ -3703,6 +3721,7 @@ package body Freeze is if Has_Pragma_Pack (Arr) and then not Present (Comp_Size_C) and then (Csiz = 7 or else Csiz = 15 or else Csiz = 31) + and then Known_Esize (Base_Type (Ctyp)) and then Esize (Base_Type (Ctyp)) = Csiz + 1 then Error_Msg_Uint_1 := Csiz; @@ -6646,7 +6665,7 @@ package body Freeze is Dim := Expr_Value (Hi) - Expr_Value (Lo) + 1; - if Dim >= 0 then + if Dim > Uint_0 then Num_Elmts := Num_Elmts * Dim; else Num_Elmts := Uint_0; @@ -6668,9 +6687,12 @@ package body Freeze is if Implicit_Packing then Set_Component_Size (Btyp, Rsiz); - -- Otherwise give an error message + -- Otherwise give an error message, except that if the + -- specified Size is zero, there is no need for pragma + -- Pack. Note that size zero is not considered + -- Addressable. - else + elsif RM_Size (E) /= Uint_0 then Error_Msg_NE ("size given for& too small", SZ, E); Error_Msg_N -- CODEFIX diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 639cf06..98b4aaf 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -3946,7 +3946,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) bool extern_flag = ((Is_Public (gnat_entity) && !definition) || imported_p - || (Convention (gnat_entity) == Convention_Intrinsic + || (Is_Intrinsic_Subprogram (gnat_entity) && Has_Pragma_Inline_Always (gnat_entity))); tree gnu_param_list; @@ -4490,7 +4490,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) /* Likewise for the RM size, if any. */ if (!Known_RM_Size (gnat_entity) && TYPE_SIZE (gnu_type)) Set_RM_Size (gnat_entity, - No_Uint_To_0 (annotate_value (rm_size (gnu_type)))); + annotate_value (rm_size (gnu_type))); /* If we are at global level, GCC applied variable_size to the size but this has done nothing. So, if it's not constant or self-referential, @@ -5366,7 +5366,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, tree gnu_param_type, bool first, /* Builtins are expanded inline and there is no real call sequence involved. So the type expected by the underlying expander is always the type of the argument "as is". */ - if (Convention (gnat_subprog) == Convention_Intrinsic + if (Is_Intrinsic_Subprogram (gnat_subprog) && Present (Interface_Name (gnat_subprog))) mech = By_Copy; @@ -5823,9 +5823,10 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, else { - /* For foreign convention subprograms, return System.Address as void * - or equivalent. Note that this comprises GCC builtins. */ - if (Has_Foreign_Convention (gnat_subprog) + /* For foreign convention/intrinsic subprograms, return System.Address + as void * or equivalent; this comprises GCC builtins. */ + if ((Has_Foreign_Convention (gnat_subprog) + || Is_Intrinsic_Subprogram (gnat_subprog)) && Is_Descendant_Of_Address (Underlying_Type (gnat_return_type))) gnu_return_type = ptr_type_node; else @@ -5995,9 +5996,10 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, { Entity_Id gnat_param_type = Etype (gnat_param); - /* For foreign convention subprograms, pass System.Address as void * - or equivalent. Note that this comprises GCC builtins. */ - if (Has_Foreign_Convention (gnat_subprog) + /* For foreign convention/intrinsic subprograms, pass System.Address + as void * or equivalent; this comprises GCC builtins. */ + if ((Has_Foreign_Convention (gnat_subprog) + || Is_Intrinsic_Subprogram (gnat_subprog)) && Is_Descendant_Of_Address (Underlying_Type (gnat_param_type))) gnu_param_type = ptr_type_node; else @@ -6303,7 +6305,7 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition, /* If this subprogram is expectedly bound to a GCC builtin, fetch the corresponding DECL node and check the parameter association. */ - if (Convention (gnat_subprog) == Convention_Intrinsic + if (Is_Intrinsic_Subprogram (gnat_subprog) && Present (Interface_Name (gnat_subprog))) { tree gnu_ext_name = create_concat_name (gnat_subprog, NULL); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 8a192c7..dc2a03c 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -9079,7 +9079,7 @@ elaborate_all_entities_for_package (Entity_Id gnat_package) continue; /* Skip stuff internal to the compiler. */ - if (Convention (gnat_entity) == Convention_Intrinsic) + if (Is_Intrinsic_Subprogram (gnat_entity)) continue; if (kind == E_Operator) continue; diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb index 1fa7f0b..d91faaa 100644 --- a/gcc/ada/gen_il-gen-gen_entities.adb +++ b/gcc/ada/gen_il-gen-gen_entities.adb @@ -252,7 +252,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Contract, Node_Id), Sm (Is_Elaboration_Warnings_OK_Id, Flag), Sm (Original_Record_Component, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag), Sm (Current_Value, Node_Id), -- setter only @@ -607,7 +607,7 @@ begin -- Gen_IL.Gen.Gen_Entities -- this is the first named subtype). Ab (Decimal_Fixed_Point_Kind, Fixed_Point_Kind, - (Sm (Digits_Value, Uint), + (Sm (Digits_Value, Upos), Sm (Has_Machine_Radix_Clause, Flag), Sm (Machine_Radix_10, Flag), Sm (Scale_Value, Uint))); @@ -623,7 +623,7 @@ begin -- Gen_IL.Gen.Gen_Entities -- first named subtype). Ab (Float_Kind, Real_Kind, - (Sm (Digits_Value, Uint))); + (Sm (Digits_Value, Upos))); Cc (E_Floating_Point_Type, Float_Kind); -- Floating point type, used for the anonymous base type of the @@ -866,23 +866,23 @@ begin -- Gen_IL.Gen.Gen_Entities -- A private type, created by a private type declaration that has -- neither the keyword limited nor the keyword tagged. (Sm (Scalar_Range, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Private_Subtype, Private_Kind, -- A subtype of a private type, created by a subtype declaration used -- to declare a subtype of a private type. - (Sm (Scope_Depth_Value, Uint))); + (Sm (Scope_Depth_Value, Unat))); Cc (E_Limited_Private_Type, Private_Kind, -- A limited private type, created by a private type declaration that -- has the keyword limited, but not the keyword tagged. (Sm (Scalar_Range, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Limited_Private_Subtype, Private_Kind, -- A subtype of a limited private type, created by a subtype declaration -- used to declare a subtype of a limited private type. - (Sm (Scope_Depth_Value, Uint))); + (Sm (Scope_Depth_Value, Unat))); Ab (Incomplete_Kind, Incomplete_Or_Private_Kind, (Sm (Non_Limited_View, Node_Id))); @@ -900,7 +900,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (First_Entity, Node_Id), Sm (First_Private_Entity, Node_Id), Sm (Last_Entity, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (Stored_Constraint, Elist_Id))); Ab (Task_Kind, Concurrent_Kind, @@ -1005,11 +1005,11 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Linker_Section_Pragma, Node_Id), Sm (Overridden_Operation, Node_Id), Sm (Protected_Body_Subprogram, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (Static_Call_Helper, Node_Id), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag), - Sm (Subps_Index, Uint))); + Sm (Subps_Index, Unat))); Cc (E_Function, Subprogram_Kind, -- A function, created by a function declaration or a function body @@ -1137,7 +1137,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Postconditions_Proc, Node_Id), Sm (Protected_Body_Subprogram, Node_Id), Sm (Protection_Object, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1164,7 +1164,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Protected_Body_Subprogram, Node_Id), Sm (Protection_Object, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1178,7 +1178,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), Sm (Return_Applies_To, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Entry_Index_Parameter, Entity_Kind, -- An entry index parameter created by an entry index specification @@ -1209,7 +1209,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Is_Elaboration_Warnings_OK_Id, Flag), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); @@ -1254,7 +1254,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Has_Loop_Entry_Attributes, Flag), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Return_Statement, Entity_Kind, -- A dummy entity created for each return statement. Used to hold @@ -1266,7 +1266,7 @@ begin -- Gen_IL.Gen.Gen_Entities (Sm (First_Entity, Node_Id), Sm (Last_Entity, Node_Id), Sm (Return_Applies_To, Node_Id), - Sm (Scope_Depth_Value, Uint))); + Sm (Scope_Depth_Value, Unat))); Cc (E_Package, Entity_Kind, -- A package, created by a package declaration @@ -1303,7 +1303,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Related_Instance, Node_Id), Sm (Renamed_In_Spec, Flag), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Aux_Pragma, Node_Id), Sm (SPARK_Aux_Pragma_Inherited, Flag), Sm (SPARK_Pragma, Node_Id), @@ -1323,7 +1323,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Last_Entity, Node_Id), Sm (Related_Instance, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Aux_Pragma, Node_Id), Sm (SPARK_Aux_Pragma_Inherited, Flag), Sm (SPARK_Pragma, Node_Id), @@ -1358,7 +1358,7 @@ begin -- Gen_IL.Gen.Gen_Entities Sm (Interface_Name, Node_Id), Sm (Last_Entity, Node_Id), Sm (Renamed_Or_Alias, Node_Id), - Sm (Scope_Depth_Value, Uint), + Sm (Scope_Depth_Value, Unat), Sm (SPARK_Pragma, Node_Id), Sm (SPARK_Pragma_Inherited, Flag))); diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index 20d25ea..3b6bd68 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -984,7 +984,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Cc (N_Case_Statement, N_Statement_Other_Than_Procedure_Call, (Sy (Expression, Node_Id, Default_Empty), Sy (Alternatives, List_Id, Default_No_List), - Sy (End_Span, Uint, Default_Uint_0), + Sy (End_Span, Unat, Default_Uint_0), Sm (From_Conditional_Expression, Flag))); Cc (N_Code_Statement, N_Statement_Other_Than_Procedure_Call, @@ -1094,7 +1094,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Sy (Then_Statements, List_Id), Sy (Elsif_Parts, List_Id, Default_No_List), Sy (Else_Statements, List_Id, Default_No_List), - Sy (End_Span, Uint, Default_Uint_0), + Sy (End_Span, Unat, Default_Uint_0), Sm (From_Conditional_Expression, Flag))); Cc (N_Accept_Alternative, Node_Kind, @@ -1594,7 +1594,7 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Dcheck_Function, Node_Id), Sm (Enclosing_Variant, Node_Id), Sm (Has_SP_Choice, Flag), - Sm (Present_Expr, Uint))); + Sm (Present_Expr, Valid_Uint))); Cc (N_Variant_Part, Node_Kind, (Sy (Name, Node_Id, Default_Empty), diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb index e786251..eed98ee 100644 --- a/gcc/ada/gen_il-gen.adb +++ b/gcc/ada/gen_il-gen.adb @@ -1197,6 +1197,12 @@ package body Gen_IL.Gen is for F in First .. Last loop if Field_Table (F).Field_Type in Node_Or_Entity_Type then Result (Node_Id) := True; + + -- Subtypes of Uint all use the same Cast for Uint + + elsif Field_Table (F).Field_Type in Uint_Subtype then + Result (Uint) := True; + else Result (Field_Table (F).Field_Type) := True; end if; @@ -1767,6 +1773,7 @@ package body Gen_IL.Gen is end if; Put_Get_Set_Incr (S, F, "Set"); + Decrease_Indent (S, 3); Put (S, "end Set_" & Image (F) & ";" & LF & LF); end Put_Setter_Body; diff --git a/gcc/ada/gen_il-internals.adb b/gcc/ada/gen_il-internals.adb index fe1af78..a1a8062 100644 --- a/gcc/ada/gen_il-internals.adb +++ b/gcc/ada/gen_il-internals.adb @@ -370,7 +370,7 @@ package body Gen_IL.Internals is return Image (Default); else - -- Strip off the prefix and capitalize it + -- Strip off the prefix declare Im : constant String := Image (Default); diff --git a/gcc/ada/gen_il-internals.ads b/gcc/ada/gen_il-internals.ads index a811e0b4..7b095c0 100644 --- a/gcc/ada/gen_il-internals.ads +++ b/gcc/ada/gen_il-internals.ads @@ -133,7 +133,7 @@ package Gen_IL.Internals is Default_Uint_0); -- Uint -- Default value for a field in the Nmake functions. No_Default if the -- field parameter has no default value. Otherwise this indicates the - -- default value used, which must matcht the type of the field. + -- default value used, which must match the type of the field. function Image (Default : Field_Default_Value) return String; -- This will be something like "Default_Empty". @@ -191,7 +191,10 @@ package Gen_IL.Internals is function Special_Default (Field_Type : Type_Enum) return String is - (if Field_Type = Elist_Id then "No_Elist" else "Uint_0"); + (case Field_Type is + when Elist_Id => "No_Elist", + when Uint => "No_Uint", + when others => "can't happen"); ---------------- diff --git a/gcc/ada/gen_il-types.ads b/gcc/ada/gen_il-types.ads index 97b9dd2..9395e00 100644 --- a/gcc/ada/gen_il-types.ads +++ b/gcc/ada/gen_il-types.ads @@ -589,5 +589,7 @@ package Gen_IL.Types is subtype Uint_Subtype is Type_Enum with Predicate => Uint_Subtype in Valid_Uint | Unat | Upos | Nonzero_Uint; + -- These are the subtypes of Uint that have predicates restricting their + -- values. end Gen_IL.Types; diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 28f2f19..cae1fad 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -21,7 +21,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Sep 28, 2021 +GNAT User's Guide for Native Platforms , Oct 19, 2021 AdaCore @@ -11800,6 +11800,34 @@ This switch suppresses warnings on cases of suspicious parameter ordering. @end table +@geindex -gnatw_p (gcc) + + +@table @asis + +@item @code{-gnatw_p} + +@emph{Activate warnings for pedantic checks.} + +This switch activates warnings for the failure of certain pedantic checks. +The only case currently supported is a check that the subtype_marks given +for corresponding formal parameter and function results in a subprogram +declaration and its body denote the same subtype declaration. The default +is that such warnings are not given. +@end table + +@geindex -gnatw_P (gcc) + + +@table @asis + +@item @code{-gnatw_P} + +@emph{Suppress warnings for pedantic checks.} + +This switch suppresses warnings on violations of pedantic checks. +@end table + @geindex -gnatwq (gcc) @geindex Parentheses diff --git a/gcc/ada/libgnat/g-io-put__vxworks.adb b/gcc/ada/libgnat/a-nbnbin__ghost.adb index 29307f9..7d22086 100644 --- a/gcc/ada/libgnat/g-io-put__vxworks.adb +++ b/gcc/ada/libgnat/a-nbnbin__ghost.adb @@ -2,11 +2,11 @@ -- -- -- GNAT RUN-TIME COMPONENTS -- -- -- --- G N A T . I O -- +-- ADA.NUMERICS.BIG_NUMBERS.BIG_INTEGERS -- -- -- -- B o d y -- -- -- --- Copyright (C) 1995-2021, AdaCore -- +-- Copyright (C) 2021, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -29,25 +29,48 @@ -- -- ------------------------------------------------------------------------------ --- vxworks zfp version of Put (C : Character) +-- This body is provided as a work-around for a GNAT compiler bug, as GNAT +-- currently does not compile instantiations of the spec with imported ghost +-- generics for packages Signed_Conversions and Unsigned_Conversions. -with Interfaces.C; use Interfaces.C; +package body Ada.Numerics.Big_Numbers.Big_Integers with + SPARK_Mode => Off +is -separate (GNAT.IO) -procedure Put (C : Character) is + package body Signed_Conversions with + SPARK_Mode => Off + is - function ioGlobalStdGet - (File : int) return int; - pragma Import (C, ioGlobalStdGet, "ioGlobalStdGet"); + function To_Big_Integer (Arg : Int) return Valid_Big_Integer is + begin + raise Program_Error; + return (null record); + end To_Big_Integer; - procedure fdprintf - (File : int; - Format : String; - Value : Character); - pragma Import (C, fdprintf, "fdprintf"); + function From_Big_Integer (Arg : Valid_Big_Integer) return Int is + begin + raise Program_Error; + return 0; + end From_Big_Integer; - Stdout_ID : constant int := 1; + end Signed_Conversions; -begin - fdprintf (ioGlobalStdGet (Stdout_ID), "%c" & ASCII.NUL, C); -end Put; + package body Unsigned_Conversions with + SPARK_Mode => Off + is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer is + begin + raise Program_Error; + return (null record); + end To_Big_Integer; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int is + begin + raise Program_Error; + return 0; + end From_Big_Integer; + + end Unsigned_Conversions; + +end Ada.Numerics.Big_Numbers.Big_Integers; diff --git a/gcc/ada/libgnat/a-nbnbin__ghost.ads b/gcc/ada/libgnat/a-nbnbin__ghost.ads new file mode 100644 index 0000000..3663dd7 --- /dev/null +++ b/gcc/ada/libgnat/a-nbnbin__ghost.ads @@ -0,0 +1,202 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT RUN-TIME COMPONENTS -- +-- -- +-- ADA.NUMERICS.BIG_NUMBERS.BIG_INTEGERS -- +-- -- +-- S p e c -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. In accordance with the copyright of that document, you can freely -- +-- copy and modify this specification, provided that if you redistribute a -- +-- modified version, any changes that you have made are clearly indicated. -- +-- -- +------------------------------------------------------------------------------ + +package Ada.Numerics.Big_Numbers.Big_Integers with + SPARK_Mode, + Ghost, + Preelaborate +is + type Big_Integer is private + with Integer_Literal => From_Universal_Image; + + function Is_Valid (Arg : Big_Integer) return Boolean + with + Import, + Global => null; + + subtype Valid_Big_Integer is Big_Integer + with Dynamic_Predicate => Is_Valid (Valid_Big_Integer), + Predicate_Failure => raise Program_Error; + + function "=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function "<" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function "<=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function ">" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function ">=" (L, R : Valid_Big_Integer) return Boolean with + Import, + Global => null; + + function To_Big_Integer (Arg : Integer) return Valid_Big_Integer + with + Import, + Global => null; + + subtype Big_Positive is Big_Integer + with Dynamic_Predicate => + (if Is_Valid (Big_Positive) + then Big_Positive > To_Big_Integer (0)), + Predicate_Failure => (raise Constraint_Error); + + subtype Big_Natural is Big_Integer + with Dynamic_Predicate => + (if Is_Valid (Big_Natural) + then Big_Natural >= To_Big_Integer (0)), + Predicate_Failure => (raise Constraint_Error); + + function In_Range + (Arg : Valid_Big_Integer; Low, High : Big_Integer) return Boolean + is (Low <= Arg and Arg <= High) + with + Import, + Global => null; + + function To_Integer (Arg : Valid_Big_Integer) return Integer + with + Import, + Pre => In_Range (Arg, + Low => To_Big_Integer (Integer'First), + High => To_Big_Integer (Integer'Last)) + or else (raise Constraint_Error), + Global => null; + + generic + type Int is range <>; + package Signed_Conversions is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer + with + Global => null; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int + with + Pre => In_Range (Arg, + Low => To_Big_Integer (Int'First), + High => To_Big_Integer (Int'Last)) + or else (raise Constraint_Error), + Global => null; + end Signed_Conversions; + + generic + type Int is mod <>; + package Unsigned_Conversions is + + function To_Big_Integer (Arg : Int) return Valid_Big_Integer + with + Global => null; + + function From_Big_Integer (Arg : Valid_Big_Integer) return Int + with + Pre => In_Range (Arg, + Low => To_Big_Integer (Int'First), + High => To_Big_Integer (Int'Last)) + or else (raise Constraint_Error), + Global => null; + + end Unsigned_Conversions; + + function From_String (Arg : String) return Valid_Big_Integer + with + Import, + Global => null; + + function From_Universal_Image (Arg : String) return Valid_Big_Integer + renames From_String; + + function "+" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "-" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "abs" (L : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "+" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "-" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "*" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "/" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "mod" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "rem" (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function "**" (L : Valid_Big_Integer; R : Natural) return Valid_Big_Integer + with + Import, + Global => null; + + function Min (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function Max (L, R : Valid_Big_Integer) return Valid_Big_Integer + with + Import, + Global => null; + + function Greatest_Common_Divisor + (L, R : Valid_Big_Integer) return Big_Positive + with + Import, + Pre => (L /= To_Big_Integer (0) and R /= To_Big_Integer (0)) + or else (raise Constraint_Error), + Global => null; + +private + pragma SPARK_Mode (Off); + + type Big_Integer is null record; + +end Ada.Numerics.Big_Numbers.Big_Integers; diff --git a/gcc/ada/libgnat/s-aoinar.adb b/gcc/ada/libgnat/s-aoinar.adb index 2f430ed..41d0cda 100644 --- a/gcc/ada/libgnat/s-aoinar.adb +++ b/gcc/ada/libgnat/s-aoinar.adb @@ -72,22 +72,10 @@ package body System.Atomic_Operations.Integer_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Add_1 + function Atomic_Fetch_Add (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_1, "__atomic_fetch_add_1"); - function Atomic_Fetch_Add_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_2, "__atomic_fetch_add_2"); - function Atomic_Fetch_Add_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_4, "__atomic_fetch_add_4"); - function Atomic_Fetch_Add_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_8, "__atomic_fetch_add_8"); + pragma Import (Intrinsic, Atomic_Fetch_Add, "__atomic_fetch_add"); pragma Warnings (On); begin @@ -96,21 +84,14 @@ package body System.Atomic_Operations.Integer_Arithmetic is if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'Base'First = Atomic_Type'First - and then Atomic_Type'Last - in 2 ** 7 - 1 | 2 ** 15 - 1 | 2 ** 31 - 1 | 2 ** 63 - 1 + and then Atomic_Type'Last = 2**(Atomic_Type'Object_Size - 1) - 1 then - case Long_Long_Integer (Atomic_Type'Last) is - when 2 ** 7 - 1 => - return Atomic_Fetch_Add_1 (Item'Address, Value); - when 2 ** 15 - 1 => - return Atomic_Fetch_Add_2 (Item'Address, Value); - when 2 ** 31 - 1 => - return Atomic_Fetch_Add_4 (Item'Address, Value); - when 2 ** 63 - 1 => - return Atomic_Fetch_Add_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Add (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; @@ -138,22 +119,10 @@ package body System.Atomic_Operations.Integer_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Sub_1 + function Atomic_Fetch_Sub (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_1, "__atomic_fetch_sub_1"); - function Atomic_Fetch_Sub_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_2, "__atomic_fetch_sub_2"); - function Atomic_Fetch_Sub_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_4, "__atomic_fetch_sub_4"); - function Atomic_Fetch_Sub_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_8, "__atomic_fetch_sub_8"); + pragma Import (Intrinsic, Atomic_Fetch_Sub, "__atomic_fetch_sub"); pragma Warnings (On); begin @@ -162,21 +131,14 @@ package body System.Atomic_Operations.Integer_Arithmetic is if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'Base'First = Atomic_Type'First - and then Atomic_Type'Last - in 2 ** 7 - 1 | 2 ** 15 - 1 | 2 ** 31 - 1 | 2 ** 63 - 1 + and then Atomic_Type'Last = 2**(Atomic_Type'Object_Size - 1) - 1 then - case Long_Long_Integer (Atomic_Type'Last) is - when 2 ** 7 - 1 => - return Atomic_Fetch_Sub_1 (Item'Address, Value); - when 2 ** 15 - 1 => - return Atomic_Fetch_Sub_2 (Item'Address, Value); - when 2 ** 31 - 1 => - return Atomic_Fetch_Sub_4 (Item'Address, Value); - when 2 ** 63 - 1 => - return Atomic_Fetch_Sub_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Sub (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; diff --git a/gcc/ada/libgnat/s-aomoar.adb b/gcc/ada/libgnat/s-aomoar.adb index a6f4b0e..617a5b3 100644 --- a/gcc/ada/libgnat/s-aomoar.adb +++ b/gcc/ada/libgnat/s-aomoar.adb @@ -72,48 +72,26 @@ package body System.Atomic_Operations.Modular_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Add_1 + function Atomic_Fetch_Add (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_1, "__atomic_fetch_add_1"); - function Atomic_Fetch_Add_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_2, "__atomic_fetch_add_2"); - function Atomic_Fetch_Add_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_4, "__atomic_fetch_add_4"); - function Atomic_Fetch_Add_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Add_8, "__atomic_fetch_add_8"); + pragma Import (Intrinsic, Atomic_Fetch_Add, "__atomic_fetch_add"); pragma Warnings (On); begin -- Use the direct intrinsics when possible, and fallback to -- compare-and-exchange otherwise. - -- Also suppress spurious warnings. - pragma Warnings (Off); if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'First = 0 - and then Atomic_Type'Last - in 2 ** 8 - 1 | 2 ** 16 - 1 | 2 ** 32 - 1 | 2 ** 64 - 1 + and then Atomic_Type'Last = 2**Atomic_Type'Object_Size - 1 then - pragma Warnings (On); - case Unsigned_64 (Atomic_Type'Last) is - when 2 ** 8 - 1 => - return Atomic_Fetch_Add_1 (Item'Address, Value); - when 2 ** 16 - 1 => - return Atomic_Fetch_Add_2 (Item'Address, Value); - when 2 ** 32 - 1 => - return Atomic_Fetch_Add_4 (Item'Address, Value); - when 2 ** 64 - 1 => - return Atomic_Fetch_Add_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Add (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; @@ -141,48 +119,26 @@ package body System.Atomic_Operations.Modular_Arithmetic is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Fetch_Sub_1 + function Atomic_Fetch_Sub (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_1, "__atomic_fetch_sub_1"); - function Atomic_Fetch_Sub_2 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_2, "__atomic_fetch_sub_2"); - function Atomic_Fetch_Sub_4 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_4, "__atomic_fetch_sub_4"); - function Atomic_Fetch_Sub_8 - (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) - return Atomic_Type; - pragma Import (Intrinsic, Atomic_Fetch_Sub_8, "__atomic_fetch_sub_8"); + pragma Import (Intrinsic, Atomic_Fetch_Sub, "__atomic_fetch_sub"); pragma Warnings (On); begin -- Use the direct intrinsics when possible, and fallback to -- compare-and-exchange otherwise. - -- Also suppress spurious warnings. - pragma Warnings (Off); if Atomic_Type'Base'Last = Atomic_Type'Last and then Atomic_Type'First = 0 - and then Atomic_Type'Last - in 2 ** 8 - 1 | 2 ** 16 - 1 | 2 ** 32 - 1 | 2 ** 64 - 1 + and then Atomic_Type'Last = 2**Atomic_Type'Object_Size - 1 then - pragma Warnings (On); - case Unsigned_64 (Atomic_Type'Last) is - when 2 ** 8 - 1 => - return Atomic_Fetch_Sub_1 (Item'Address, Value); - when 2 ** 16 - 1 => - return Atomic_Fetch_Sub_2 (Item'Address, Value); - when 2 ** 32 - 1 => - return Atomic_Fetch_Sub_4 (Item'Address, Value); - when 2 ** 64 - 1 => - return Atomic_Fetch_Sub_8 (Item'Address, Value); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Fetch_Sub (Item'Address, Value); + else + raise Program_Error; + end if; + else declare Old_Value : aliased Atomic_Type := Item; diff --git a/gcc/ada/libgnat/s-atopex.adb b/gcc/ada/libgnat/s-atopex.adb index b0aa9e5..65e9433 100644 --- a/gcc/ada/libgnat/s-atopex.adb +++ b/gcc/ada/libgnat/s-atopex.adb @@ -43,36 +43,19 @@ package body System.Atomic_Operations.Exchange is Value : Atomic_Type) return Atomic_Type is pragma Warnings (Off); - function Atomic_Exchange_1 + function Atomic_Exchange (Ptr : System.Address; Val : Atomic_Type; Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_1, "__atomic_exchange_1"); - function Atomic_Exchange_2 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_2, "__atomic_exchange_2"); - function Atomic_Exchange_4 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_4, "__atomic_exchange_4"); - function Atomic_Exchange_8 - (Ptr : System.Address; - Val : Atomic_Type; - Model : Mem_Model := Seq_Cst) return Atomic_Type; - pragma Import (Intrinsic, Atomic_Exchange_8, "__atomic_exchange_8"); + pragma Import (Intrinsic, Atomic_Exchange, "__atomic_exchange_n"); pragma Warnings (On); begin - case Atomic_Type'Object_Size is - when 8 => return Atomic_Exchange_1 (Item'Address, Value); - when 16 => return Atomic_Exchange_2 (Item'Address, Value); - when 32 => return Atomic_Exchange_4 (Item'Address, Value); - when 64 => return Atomic_Exchange_8 (Item'Address, Value); - when others => raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Exchange (Item'Address, Value); + else + raise Program_Error; + end if; end Atomic_Exchange; --------------------------------- @@ -85,34 +68,7 @@ package body System.Atomic_Operations.Exchange is Desired : Atomic_Type) return Boolean is pragma Warnings (Off); - function Atomic_Compare_Exchange_1 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_1, "__atomic_compare_exchange_1"); - function Atomic_Compare_Exchange_2 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_2, "__atomic_compare_exchange_2"); - function Atomic_Compare_Exchange_4 - (Ptr : System.Address; - Expected : System.Address; - Desired : Atomic_Type; - Weak : Boolean := False; - Success_Model : Mem_Model := Seq_Cst; - Failure_Model : Mem_Model := Seq_Cst) return Boolean; - pragma Import - (Intrinsic, Atomic_Compare_Exchange_4, "__atomic_compare_exchange_4"); - function Atomic_Compare_Exchange_8 + function Atomic_Compare_Exchange (Ptr : System.Address; Expected : System.Address; Desired : Atomic_Type; @@ -120,26 +76,15 @@ package body System.Atomic_Operations.Exchange is Success_Model : Mem_Model := Seq_Cst; Failure_Model : Mem_Model := Seq_Cst) return Boolean; pragma Import - (Intrinsic, Atomic_Compare_Exchange_8, "__atomic_compare_exchange_8"); + (Intrinsic, Atomic_Compare_Exchange, "__atomic_compare_exchange_n"); pragma Warnings (On); begin - case Atomic_Type'Object_Size is - when 8 => - return - Atomic_Compare_Exchange_1 (Item'Address, Prior'Address, Desired); - when 16 => - return - Atomic_Compare_Exchange_2 (Item'Address, Prior'Address, Desired); - when 32 => - return - Atomic_Compare_Exchange_4 (Item'Address, Prior'Address, Desired); - when 64 => - return - Atomic_Compare_Exchange_8 (Item'Address, Prior'Address, Desired); - when others => - raise Program_Error; - end case; + if Atomic_Type'Object_Size in 8 | 16 | 32 | 64 then + return Atomic_Compare_Exchange (Item'Address, Prior'Address, Desired); + else + raise Program_Error; + end if; end Atomic_Compare_And_Exchange; ------------------ diff --git a/gcc/ada/libgnat/s-atopri.adb b/gcc/ada/libgnat/s-atopri.adb index ba284f0..20aa666 100644 --- a/gcc/ada/libgnat/s-atopri.adb +++ b/gcc/ada/libgnat/s-atopri.adb @@ -31,103 +31,39 @@ package body System.Atomic_Primitives is - ---------------------- - -- Lock_Free_Read_8 -- - ---------------------- + -------------------- + -- Lock_Free_Read -- + -------------------- - function Lock_Free_Read_8 (Ptr : Address) return uint8 is - begin - if uint8'Atomic_Always_Lock_Free then - return Atomic_Load_8 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_8; - - ----------------------- - -- Lock_Free_Read_16 -- - ----------------------- + function Lock_Free_Read (Ptr : Address) return Atomic_Type is + function My_Atomic_Load is new Atomic_Load (Atomic_Type); - function Lock_Free_Read_16 (Ptr : Address) return uint16 is begin - if uint16'Atomic_Always_Lock_Free then - return Atomic_Load_16 (Ptr, Acquire); + if Atomic_Type'Atomic_Always_Lock_Free then + return My_Atomic_Load (Ptr, Acquire); else raise Program_Error; end if; - end Lock_Free_Read_16; + end Lock_Free_Read; - ----------------------- - -- Lock_Free_Read_32 -- - ----------------------- - - function Lock_Free_Read_32 (Ptr : Address) return uint32 is - begin - if uint32'Atomic_Always_Lock_Free then - return Atomic_Load_32 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_32; + ------------------------- + -- Lock_Free_Try_Write -- + ------------------------- - ----------------------- - -- Lock_Free_Read_64 -- - ----------------------- - - function Lock_Free_Read_64 (Ptr : Address) return uint64 is - begin - if uint64'Atomic_Always_Lock_Free then - return Atomic_Load_64 (Ptr, Acquire); - else - raise Program_Error; - end if; - end Lock_Free_Read_64; - - --------------------------- - -- Lock_Free_Try_Write_8 -- - --------------------------- - - function Lock_Free_Try_Write_8 + function Lock_Free_Try_Write (Ptr : Address; - Expected : in out uint8; - Desired : uint8) return Boolean + Expected : in out Atomic_Type; + Desired : Atomic_Type) return Boolean is - Actual : uint8; + function My_Sync_Compare_And_Swap is + new Sync_Compare_And_Swap (Atomic_Type); - begin - if Expected /= Desired then - - if uint8'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_8 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_8; - - ---------------------------- - -- Lock_Free_Try_Write_16 -- - ---------------------------- - - function Lock_Free_Try_Write_16 - (Ptr : Address; - Expected : in out uint16; - Desired : uint16) return Boolean - is - Actual : uint16; + Actual : Atomic_Type; begin if Expected /= Desired then - - if uint16'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_16 (Ptr, Expected, Desired); + if Atomic_Type'Atomic_Always_Lock_Free then + Actual := My_Sync_Compare_And_Swap (Ptr, Expected, Desired); else raise Program_Error; end if; @@ -139,63 +75,6 @@ package body System.Atomic_Primitives is end if; return True; - end Lock_Free_Try_Write_16; - - ---------------------------- - -- Lock_Free_Try_Write_32 -- - ---------------------------- + end Lock_Free_Try_Write; - function Lock_Free_Try_Write_32 - (Ptr : Address; - Expected : in out uint32; - Desired : uint32) return Boolean - is - Actual : uint32; - - begin - if Expected /= Desired then - - if uint32'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_32 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_32; - - ---------------------------- - -- Lock_Free_Try_Write_64 -- - ---------------------------- - - function Lock_Free_Try_Write_64 - (Ptr : Address; - Expected : in out uint64; - Desired : uint64) return Boolean - is - Actual : uint64; - - begin - if Expected /= Desired then - - if uint64'Atomic_Always_Lock_Free then - Actual := Sync_Compare_And_Swap_64 (Ptr, Expected, Desired); - else - raise Program_Error; - end if; - - if Actual /= Expected then - Expected := Actual; - return False; - end if; - end if; - - return True; - end Lock_Free_Try_Write_64; end System.Atomic_Primitives; diff --git a/gcc/ada/libgnat/s-atopri.ads b/gcc/ada/libgnat/s-atopri.ads index 891b2ed..ea03f1a 100644 --- a/gcc/ada/libgnat/s-atopri.ads +++ b/gcc/ada/libgnat/s-atopri.ads @@ -29,7 +29,7 @@ -- -- ------------------------------------------------------------------------------ --- This package contains both atomic primitives defined from gcc built-in +-- This package contains both atomic primitives defined from GCC built-in -- functions and operations used by the compiler to generate the lock-free -- implementation of protected objects. @@ -66,71 +66,31 @@ package System.Atomic_Primitives is -- GCC built-in atomic primitives -- ------------------------------------ - function Atomic_Load_8 + generic + type Atomic_Type is mod <>; + function Atomic_Load (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint8; - pragma Import (Intrinsic, Atomic_Load_8, "__atomic_load_1"); + Model : Mem_Model := Seq_Cst) return Atomic_Type; + pragma Import (Intrinsic, Atomic_Load, "__atomic_load_n"); - function Atomic_Load_16 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint16; - pragma Import (Intrinsic, Atomic_Load_16, "__atomic_load_2"); - - function Atomic_Load_32 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint32; - pragma Import (Intrinsic, Atomic_Load_32, "__atomic_load_4"); - - function Atomic_Load_64 - (Ptr : Address; - Model : Mem_Model := Seq_Cst) return uint64; - pragma Import (Intrinsic, Atomic_Load_64, "__atomic_load_8"); - - function Sync_Compare_And_Swap_8 - (Ptr : Address; - Expected : uint8; - Desired : uint8) return uint8; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_8, - "__sync_val_compare_and_swap_1"); - - function Sync_Compare_And_Swap_16 - (Ptr : Address; - Expected : uint16; - Desired : uint16) return uint16; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_16, - "__sync_val_compare_and_swap_2"); + function Atomic_Load_8 is new Atomic_Load (uint8); + function Atomic_Load_16 is new Atomic_Load (uint16); + function Atomic_Load_32 is new Atomic_Load (uint32); + function Atomic_Load_64 is new Atomic_Load (uint64); - function Sync_Compare_And_Swap_32 + generic + type Atomic_Type is mod <>; + function Sync_Compare_And_Swap (Ptr : Address; - Expected : uint32; - Desired : uint32) return uint32; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_32, - "__sync_val_compare_and_swap_4"); + Expected : Atomic_Type; + Desired : Atomic_Type) return Atomic_Type; + pragma Import + (Intrinsic, Sync_Compare_And_Swap, "__sync_val_compare_and_swap"); - function Sync_Compare_And_Swap_64 - (Ptr : Address; - Expected : uint64; - Desired : uint64) return uint64; - pragma Import (Intrinsic, - Sync_Compare_And_Swap_64, - "__sync_val_compare_and_swap_8"); - - -- ??? We might want to switch to the __atomic series of builtins for - -- compare-and-swap operations at some point. - - -- function Atomic_Compare_Exchange_8 - -- (Ptr : Address; - -- Expected : Address; - -- Desired : uint8; - -- Weak : Boolean := False; - -- Success_Model : Mem_Model := Seq_Cst; - -- Failure_Model : Mem_Model := Seq_Cst) return Boolean; - -- pragma Import (Intrinsic, - -- Atomic_Compare_Exchange_8, - -- "__atomic_compare_exchange_1"); + function Sync_Compare_And_Swap_8 is new Sync_Compare_And_Swap (uint8); + function Sync_Compare_And_Swap_16 is new Sync_Compare_And_Swap (uint16); + function Sync_Compare_And_Swap_32 is new Sync_Compare_And_Swap (uint32); + function Sync_Compare_And_Swap_64 is new Sync_Compare_And_Swap (uint64); function Atomic_Test_And_Set (Ptr : System.Address; @@ -155,46 +115,37 @@ package System.Atomic_Primitives is -- The lock-free implementation uses two atomic instructions for the -- expansion of protected operations: - -- * Lock_Free_Read_N atomically loads the value of the protected component - -- accessed by the current protected operation. - - -- * Lock_Free_Try_Write_N tries to write the Desired value into Ptr only - -- if Expected and Desired mismatch. + -- * Lock_Free_Read atomically loads the value contained in Ptr (with the + -- Acquire synchronization mode). - function Lock_Free_Read_8 (Ptr : Address) return uint8; + -- * Lock_Free_Try_Write atomically tries to write the Desired value into + -- Ptr if Ptr contains the Expected value. It returns true if the value + -- in Ptr was changed, or False if it was not, in which case Expected is + -- updated to the unexpected value in Ptr. Note that it does nothing and + -- returns true if Desired and Expected are equal. - function Lock_Free_Read_16 (Ptr : Address) return uint16; + generic + type Atomic_Type is mod <>; + function Lock_Free_Read (Ptr : Address) return Atomic_Type; - function Lock_Free_Read_32 (Ptr : Address) return uint32; + function Lock_Free_Read_8 is new Lock_Free_Read (uint8); + function Lock_Free_Read_16 is new Lock_Free_Read (uint16); + function Lock_Free_Read_32 is new Lock_Free_Read (uint32); + function Lock_Free_Read_64 is new Lock_Free_Read (uint64); - function Lock_Free_Read_64 (Ptr : Address) return uint64; - - function Lock_Free_Try_Write_8 - (Ptr : Address; - Expected : in out uint8; - Desired : uint8) return Boolean; - - function Lock_Free_Try_Write_16 - (Ptr : Address; - Expected : in out uint16; - Desired : uint16) return Boolean; - - function Lock_Free_Try_Write_32 - (Ptr : Address; - Expected : in out uint32; - Desired : uint32) return Boolean; + generic + type Atomic_Type is mod <>; + function Lock_Free_Try_Write + (Ptr : Address; + Expected : in out Atomic_Type; + Desired : Atomic_Type) return Boolean; - function Lock_Free_Try_Write_64 - (Ptr : Address; - Expected : in out uint64; - Desired : uint64) return Boolean; + function Lock_Free_Try_Write_8 is new Lock_Free_Try_Write (uint8); + function Lock_Free_Try_Write_16 is new Lock_Free_Try_Write (uint16); + function Lock_Free_Try_Write_32 is new Lock_Free_Try_Write (uint32); + function Lock_Free_Try_Write_64 is new Lock_Free_Try_Write (uint64); - pragma Inline (Lock_Free_Read_8); - pragma Inline (Lock_Free_Read_16); - pragma Inline (Lock_Free_Read_32); - pragma Inline (Lock_Free_Read_64); - pragma Inline (Lock_Free_Try_Write_8); - pragma Inline (Lock_Free_Try_Write_16); - pragma Inline (Lock_Free_Try_Write_32); - pragma Inline (Lock_Free_Try_Write_64); +private + pragma Inline (Lock_Free_Read); + pragma Inline (Lock_Free_Try_Write); end System.Atomic_Primitives; diff --git a/gcc/ada/libgnat/s-parame__ae653.ads b/gcc/ada/libgnat/s-parame__ae653.ads deleted file mode 100644 index a3e2351..0000000 --- a/gcc/ada/libgnat/s-parame__ae653.ads +++ /dev/null @@ -1,196 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . P A R A M E T E R S -- --- -- --- S p e c -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- Version is used by VxWorks 653, VxWorks MILS, and VxWorks6 cert Ravenscar - --- This package defines some system dependent parameters for GNAT. These --- are values that are referenced by the runtime library and are therefore --- relevant to the target machine. - --- The parameters whose value is defined in the spec are not generally --- expected to be changed. If they are changed, it will be necessary to --- recompile the run-time library. - --- The parameters which are defined by functions can be changed by modifying --- the body of System.Parameters in file s-parame.adb. A change to this body --- requires only rebinding and relinking of the application. - --- Note: do not introduce any pragma Inline statements into this unit, since --- otherwise the relinking and rebinding capability would be deactivated. - -package System.Parameters is - pragma Pure; - - --------------------------------------- - -- Task And Stack Allocation Control -- - --------------------------------------- - - type Size_Type is range - -(2 ** (Integer'(Standard'Address_Size) - 1)) .. - +(2 ** (Integer'(Standard'Address_Size) - 1)) - 1; - -- Type used to provide task stack sizes to the runtime. Sized to permit - -- stack sizes of up to half the total addressable memory space. This may - -- seem excessively large (even for 32-bit systems), however there are many - -- instances of users requiring large stack sizes (for example string - -- processing). - - Unspecified_Size : constant Size_Type := Size_Type'First; - -- Value used to indicate that no size type is set - - function Default_Stack_Size return Size_Type; - -- Default task stack size used if none is specified - - function Minimum_Stack_Size return Size_Type; - -- Minimum task stack size permitted - - function Adjust_Storage_Size (Size : Size_Type) return Size_Type; - -- Given the storage size stored in the TCB, return the Storage_Size - -- value required by the RM for the Storage_Size attribute. The - -- required adjustment is as follows: - -- - -- when Size = Unspecified_Size, return Default_Stack_Size - -- when Size < Minimum_Stack_Size, return Minimum_Stack_Size - -- otherwise return given Size - - Default_Env_Stack_Size : constant Size_Type := 14_336; - -- Assumed size of the environment task, if no other information - -- is available. This value is used when stack checking is - -- enabled and no GNAT_STACK_LIMIT environment variable is set. - -- This value is chosen as the VxWorks default stack size is 20kB, - -- and a little more than 4kB is necessary for the run time. - - Stack_Grows_Down : constant Boolean := True; - -- This constant indicates whether the stack grows up (False) or - -- down (True) in memory as functions are called. It is used for - -- proper implementation of the stack overflow check. - - Runtime_Default_Sec_Stack_Size : constant Size_Type := 10 * 1024; - -- The run-time chosen default size for secondary stacks that may be - -- overridden by the user with the use of binder -D switch. - - Sec_Stack_Dynamic : constant Boolean := False; - -- Indicates if secondary stacks can grow and shrink at run-time. If False, - -- the size of a secondary stack is fixed at the point of its creation. - - ------------------------------------ - -- Characteristics of time_t type -- - ------------------------------------ - - -- IMPORTANT NOTE: - -- time_t_bits must match the size specified in the VSB. - - time_t_bits : constant := Long_Long_Integer'Size; - -- Number of bits in type time_t for SR0660 and newer, - -- with the default configuration of the VSB. - - ---------------------------------------------- - -- Characteristics of types in Interfaces.C -- - ---------------------------------------------- - - long_bits : constant := Long_Integer'Size; - -- Number of bits in type long and unsigned_long. The normal convention - -- is that this is the same as type Long_Integer, but this may not be true - -- of all targets. - - ptr_bits : constant := Standard'Address_Size; - subtype C_Address is System.Address; - -- Number of bits in Interfaces.C pointers, normally a standard address - - C_Malloc_Linkname : constant String := "__gnat_malloc"; - -- Name of runtime function used to allocate such a pointer - - ---------------------------------------------- - -- Behavior of Pragma Finalize_Storage_Only -- - ---------------------------------------------- - - -- Garbage_Collected is a Boolean constant whose value indicates the - -- effect of the pragma Finalize_Storage_Entry on a controlled type. - - -- Garbage_Collected = False - - -- The system releases all storage on program termination only, - -- but not other garbage collection occurs, so finalization calls - -- are omitted only for outer level objects can be omitted if - -- pragma Finalize_Storage_Only is used. - - -- Garbage_Collected = True - - -- The system provides full garbage collection, so it is never - -- necessary to release storage for controlled objects for which - -- a pragma Finalize_Storage_Only is used. - - Garbage_Collected : constant Boolean := False; - -- The storage mode for this system (release on program exit) - - --------------------- - -- Tasking Profile -- - --------------------- - - -- In the following sections, constant parameters are defined to - -- allow some optimizations and fine tuning within the tasking run time - -- based on restrictions on the tasking features. - - ------------------- - -- Task Abortion -- - ------------------- - - No_Abort : constant Boolean := False; - -- This constant indicates whether abort statements and asynchronous - -- transfer of control (ATC) are disallowed. If set to True, it is - -- assumed that neither construct is used, and the run time does not - -- need to defer/undefer abort and check for pending actions at - -- completion points. A value of True for No_Abort corresponds to: - -- pragma Restrictions (No_Abort_Statements); - -- pragma Restrictions (Max_Asynchronous_Select_Nesting => 0); - - --------------------- - -- Task Attributes -- - --------------------- - - Max_Attribute_Count : constant := 8; - -- Number of task attributes stored in the task control block - - ----------------------- - -- Task Image Length -- - ----------------------- - - Max_Task_Image_Length : constant := 32; - -- This constant specifies the maximum length of a task's image - - ------------------------------ - -- Exception Message Length -- - ------------------------------ - - Default_Exception_Msg_Max_Length : constant := 200; - -- This constant specifies the default number of characters to allow - -- in an exception message (200 is minimum required by RM 11.4.1(18)). - -end System.Parameters; diff --git a/gcc/ada/libgnat/s-thread.ads b/gcc/ada/libgnat/s-thread.ads deleted file mode 100644 index 6508df5..0000000 --- a/gcc/ada/libgnat/s-thread.ads +++ /dev/null @@ -1,92 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . T H R E A D S -- --- -- --- S p e c -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This package provides facilities to register a thread to the runtime, --- and allocate its task specific datas. - --- This package is currently implemented for: - --- VxWorks7r2Cert Light - -with Ada.Unchecked_Conversion; - -with Interfaces.C; - -with System.Secondary_Stack; - -package System.Threads is - - package SST renames System.Secondary_Stack; - - type ATSD is limited private; - -- Type of the Ada thread specific data. It contains datas needed - -- by the GNAT runtime. - - type ATSD_Access is access ATSD; - function From_Address is - new Ada.Unchecked_Conversion (Address, ATSD_Access); - - subtype STATUS is Interfaces.C.int; - -- Equivalent of the C type STATUS - - type t_id is new Interfaces.C.long; - subtype Thread_Id is t_id; - - function Register (T : Thread_Id) return STATUS; - -- Create the task specific data necessary for Ada language support - - -------------------------- - -- Thread Body Handling -- - -------------------------- - - -- The subprograms in this section are called from the process body - -- wrapper in the APEX process registration package. - - procedure Thread_Body_Enter - (Sec_Stack_Ptr : SST.SS_Stack_Ptr; - Process_ATSD_Address : System.Address); - -- Enter thread body, see above for details - - procedure Thread_Body_Leave; - -- Leave thread body (normally), see above for details - - procedure Thread_Body_Exceptional_Exit; - -- Leave thread body (abnormally on exception), see above for details - -private - - type ATSD is record - Sec_Stack_Ptr : SST.SS_Stack_Ptr; - -- Pointer of the allocated secondary stack - - end record; - -end System.Threads; diff --git a/gcc/ada/libgnat/s-thread__ae653.adb b/gcc/ada/libgnat/s-thread__ae653.adb deleted file mode 100644 index 2282a66..0000000 --- a/gcc/ada/libgnat/s-thread__ae653.adb +++ /dev/null @@ -1,163 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- S Y S T E M . T H R E A D S -- --- -- --- B o d y -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This is the VxWorks7r2Cert Light version of this package - -pragma Restrictions (No_Tasking); --- The VxWorks7r2Cert Light version of this package is intended only --- for programs which do not use Ada tasking. This restriction ensures --- that this will be checked by the binder. - -with System.Storage_Elements; use System.Storage_Elements; - -package body System.Threads is - - use Interfaces.C; - - Main_ATSD : aliased ATSD; - -- TSD for environment task - - Current_ATSD : aliased System.Address := System.Null_Address; - pragma Thread_Local_Storage (Current_ATSD); - -- pragma TLS needed since TaskVarAdd no longer available - - -- VxWorks specific API - ERROR : constant STATUS := Interfaces.C.int (-1); - OK : constant STATUS := Interfaces.C.int (0); - - function taskIdVerify (tid : t_id) return STATUS; - pragma Import (C, taskIdVerify, "taskIdVerify"); - - function taskIdSelf return t_id; - pragma Import (C, taskIdSelf, "taskIdSelf"); - - ----------------------- - -- Local Subprograms -- - ----------------------- - - procedure Init_RTS; - -- This procedure performs the initialization of the run-time lib. - -- It installs System.Threads versions of certain operations of the - -- run-time lib. - - function Get_Sec_Stack return SST.SS_Stack_Ptr; - - ----------------------- - -- Thread_Body_Enter -- - ----------------------- - - procedure Thread_Body_Enter - (Sec_Stack_Ptr : SST.SS_Stack_Ptr; - Process_ATSD_Address : System.Address) - is - - ATSD : constant ATSD_Access := From_Address (Process_ATSD_Address); - - begin - - ATSD.Sec_Stack_Ptr := Sec_Stack_Ptr; - SST.SS_Init (ATSD.Sec_Stack_Ptr); - Current_ATSD := Process_ATSD_Address; - - end Thread_Body_Enter; - - ---------------------------------- - -- Thread_Body_Exceptional_Exit -- - ---------------------------------- - - procedure Thread_Body_Exceptional_Exit is - begin - -- No action for this target - - null; - end Thread_Body_Exceptional_Exit; - - ----------------------- - -- Thread_Body_Leave -- - ----------------------- - - procedure Thread_Body_Leave is - begin - -- No action for this target - - null; - end Thread_Body_Leave; - - -------------- - -- Init_RTS -- - -------------- - - procedure Init_RTS is - -- Register environment task - Result : constant Interfaces.C.int := Register (taskIdSelf); - pragma Assert (Result /= ERROR); - - begin - Main_ATSD.Sec_Stack_Ptr := Get_Sec_Stack; - Current_ATSD := Main_ATSD'Address; - end Init_RTS; - - ------------------- - -- Get_Sec_Stack -- - ------------------- - - function Get_Sec_Stack return SST.SS_Stack_Ptr is - CTSD : constant ATSD_Access := From_Address (Current_ATSD); - begin - pragma Assert (CTSD /= null); - return CTSD.Sec_Stack_Ptr; - end Get_Sec_Stack; - - -------------- - -- Register -- - -------------- - - function Register (T : Thread_Id) return STATUS is - begin - -- It cannot be assumed that the caller of this routine has a ATSD; - -- so neither this procedure nor the procedures that it calls should - -- raise or handle exceptions, or make use of a secondary stack. - - if taskIdVerify (T) = ERROR then - return ERROR; - end if; - - Current_ATSD := To_Address (Integer_Address (T)); - - return OK; - end Register; - -begin - -- Initialize run-time library - - Init_RTS; - -end System.Threads; diff --git a/gcc/ada/libgnat/s-widlllu.ads b/gcc/ada/libgnat/s-widlllu.ads index 018e740..10a0c9c 100644 --- a/gcc/ada/libgnat/s-widlllu.ads +++ b/gcc/ada/libgnat/s-widlllu.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_LLLU is - +package System.Wid_LLLU + with SPARK_Mode +is subtype Long_Long_Long_Unsigned is Unsigned_Types.Long_Long_Long_Unsigned; function Width_Long_Long_Long_Unsigned is diff --git a/gcc/ada/libgnat/s-widllu.ads b/gcc/ada/libgnat/s-widllu.ads index ab7ec58..7eaf966 100644 --- a/gcc/ada/libgnat/s-widllu.ads +++ b/gcc/ada/libgnat/s-widllu.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_LLU is - +package System.Wid_LLU + with SPARK_Mode +is subtype Long_Long_Unsigned is Unsigned_Types.Long_Long_Unsigned; function Width_Long_Long_Unsigned is new Width_U (Long_Long_Unsigned); diff --git a/gcc/ada/libgnat/s-widthu.adb b/gcc/ada/libgnat/s-widthu.adb index a91baec..e0e4d17 100644 --- a/gcc/ada/libgnat/s-widthu.adb +++ b/gcc/ada/libgnat/s-widthu.adb @@ -29,10 +29,87 @@ -- -- ------------------------------------------------------------------------------ +with Ada.Numerics.Big_Numbers.Big_Integers; +use Ada.Numerics.Big_Numbers.Big_Integers; + function System.Width_U (Lo, Hi : Uns) return Natural is + + -- Ghost code, loop invariants and assertions in this unit are meant for + -- analysis only, not for run-time checking, as it would be too costly + -- otherwise. This is enforced by setting the assertion policy to Ignore. + + pragma Assertion_Policy (Ghost => Ignore, + Loop_Invariant => Ignore, + Assert => Ignore); + W : Natural; T : Uns; + package Unsigned_Conversion is new Unsigned_Conversions (Int => Uns); + + function Big (Arg : Uns) return Big_Integer is + (Unsigned_Conversion.To_Big_Integer (Arg)) + with Ghost; + + -- Maximum value of exponent for 10 that fits in Uns'Base + function Max_Log10 return Natural is + (case Uns'Base'Size is + when 8 => 2, + when 16 => 4, + when 32 => 9, + when 64 => 19, + when 128 => 38, + when others => raise Program_Error) + with Ghost; + + Max_W : constant Natural := Max_Log10 with Ghost; + Big_10 : constant Big_Integer := Big (10) with Ghost; + + procedure Lemma_Lower_Mult (A, B, C : Big_Natural) + with + Ghost, + Pre => A <= B, + Post => A * C <= B * C; + + procedure Lemma_Div_Commutation (X, Y : Uns) + with + Ghost, + Pre => Y /= 0, + Post => Big (X) / Big (Y) = Big (X / Y); + + procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) + with + Ghost, + Post => X / Y / Z = X / (Y * Z); + + procedure Lemma_Lower_Mult (A, B, C : Big_Natural) is + begin + null; + end Lemma_Lower_Mult; + + procedure Lemma_Div_Commutation (X, Y : Uns) is + begin + null; + end Lemma_Div_Commutation; + + procedure Lemma_Div_Twice (X : Big_Natural; Y, Z : Big_Positive) is + XY : constant Big_Natural := X / Y; + YZ : constant Big_Natural := Y * Z; + XYZ : constant Big_Natural := X / Y / Z; + R : constant Big_Natural := (XY rem Z) * Y + (X rem Y); + begin + pragma Assert (X = XY * Y + (X rem Y)); + pragma Assert (XY = XY / Z * Z + (XY rem Z)); + pragma Assert (X = XYZ * YZ + R); + pragma Assert ((XY rem Z) * Y <= (Z - 1) * Y); + pragma Assert (R <= YZ - 1); + pragma Assert (X / YZ = (XYZ * YZ + R) / YZ); + pragma Assert (X / YZ = XYZ + R / YZ); + end Lemma_Div_Twice; + + Pow : Big_Integer := 1 with Ghost; + T_Init : constant Uns := Uns'Max (Lo, Hi) with Ghost; + begin if Lo > Hi then return 0; @@ -50,10 +127,40 @@ begin -- Increase value if more digits required while T >= 10 loop + Lemma_Div_Commutation (T, 10); + Lemma_Div_Twice (Big (T_Init), Big_10 ** (W - 2), Big_10); + T := T / 10; W := W + 1; + Pow := Pow * 10; + + pragma Loop_Variant (Decreases => T); + pragma Loop_Invariant (W in 3 .. Max_W + 3); + pragma Loop_Invariant (Pow = Big_10 ** (W - 2)); + pragma Loop_Invariant (Big (T) = Big (T_Init) / Pow); end loop; + declare + F : constant Big_Integer := Big_10 ** (W - 2) with Ghost; + Q : constant Big_Integer := Big (T_Init) / F with Ghost; + R : constant Big_Integer := Big (T_Init) rem F with Ghost; + begin + pragma Assert (Q < Big_10); + pragma Assert (Big (T_Init) = Q * F + R); + Lemma_Lower_Mult (Q, Big (9), F); + pragma Assert (Big (T_Init) <= Big (9) * F + F - 1); + pragma Assert (Big (T_Init) < Big_10 * F); + pragma Assert (Big_10 * F = Big_10 ** (W - 1)); + end; + + -- This is an expression of the functional postcondition for Width_U, + -- which cannot be expressed readily as a postcondition as this would + -- require making the instantiation Unsigned_Conversion and function + -- Big available from the spec. + + pragma Assert (Big (Lo) < Big_10 ** (W - 1)); + pragma Assert (Big (Hi) < Big_10 ** (W - 1)); + return W; end if; diff --git a/gcc/ada/libgnat/s-widuns.ads b/gcc/ada/libgnat/s-widuns.ads index 0528456..713532e 100644 --- a/gcc/ada/libgnat/s-widuns.ads +++ b/gcc/ada/libgnat/s-widuns.ads @@ -34,8 +34,9 @@ with System.Width_U; with System.Unsigned_Types; -package System.Wid_Uns is - +package System.Wid_Uns + with SPARK_Mode +is subtype Unsigned is Unsigned_Types.Unsigned; function Width_Unsigned is new Width_U (Unsigned); diff --git a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads b/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads deleted file mode 100644 index b918c18..0000000 --- a/gcc/ada/libgnat/system-vxworks-ppc-ravenscar.ads +++ /dev/null @@ -1,185 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks/HIE Ravenscar Version PPC) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This is a Ravenscar VxWorks version of this package for PowerPC targets - -pragma Restrictions (No_Exception_Propagation); --- Only local exception handling is supported in this profile - -pragma Restrictions (No_Exception_Registration); --- Disable exception name registration. This capability is not used because --- it is only required by exception stream attributes which are not supported --- in this run time. - -pragma Restrictions (No_Implicit_Dynamic_Code); --- Pointers to nested subprograms are not allowed in this run time, in order --- to prevent the compiler from building "trampolines". - -pragma Restrictions (No_Finalization); --- Controlled types are not supported in this run time - -pragma Profile (Ravenscar); --- This is a Ravenscar run time - -pragma Discard_Names; --- Disable explicitly the generation of names associated with entities in --- order to reduce the amount of storage used. These names are not used anyway --- (attributes such as 'Image and 'Value are not supported in this run time). - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := High_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := True; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := True; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := True; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := True; - Suppress_Standard_Library : constant Boolean := True; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/libgnat/system-vxworks-ppc.ads b/gcc/ada/libgnat/system-vxworks-ppc.ads deleted file mode 100644 index 8f384e9..0000000 --- a/gcc/ada/libgnat/system-vxworks-ppc.ads +++ /dev/null @@ -1,163 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks 5 Version PPC) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := High_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - pragma Linker_Options ("--specs=vxworks-ppc-link.spec"); - -- Setup proper set of -L's for this configuration - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := False; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := False; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := False; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := False; - Suppress_Standard_Library : constant Boolean := False; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/libgnat/system-vxworks-x86.ads b/gcc/ada/libgnat/system-vxworks-x86.ads deleted file mode 100644 index 6f952a2..0000000 --- a/gcc/ada/libgnat/system-vxworks-x86.ads +++ /dev/null @@ -1,164 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT RUN-TIME COMPONENTS -- --- -- --- S Y S T E M -- --- -- --- S p e c -- --- (VxWorks 5 Version x86) -- --- -- --- Copyright (C) 1992-2021, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- <http://www.gnu.org/licenses/>. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package System is - pragma Pure; - -- Note that we take advantage of the implementation permission to make - -- this unit Pure instead of Preelaborable; see RM 13.7.1(15). In Ada - -- 2005, this is Pure in any case (AI-362). - - pragma No_Elaboration_Code_All; - -- Allow the use of that restriction in units that WITH this unit - - type Name is (SYSTEM_NAME_GNAT); - System_Name : constant Name := SYSTEM_NAME_GNAT; - - -- System-Dependent Named Numbers - - Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); - Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; - - Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; - Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; - - Max_Base_Digits : constant := Long_Long_Float'Digits; - Max_Digits : constant := Long_Long_Float'Digits; - - Max_Mantissa : constant := Standard'Max_Integer_Size - 1; - Fine_Delta : constant := 2.0 ** (-Max_Mantissa); - - Tick : constant := 1.0 / 60.0; - - -- Storage-related Declarations - - type Address is private; - pragma Preelaborable_Initialization (Address); - Null_Address : constant Address; - - Storage_Unit : constant := 8; - Word_Size : constant := 32; - Memory_Size : constant := 2 ** 32; - - -- Address comparison - - function "<" (Left, Right : Address) return Boolean; - function "<=" (Left, Right : Address) return Boolean; - function ">" (Left, Right : Address) return Boolean; - function ">=" (Left, Right : Address) return Boolean; - function "=" (Left, Right : Address) return Boolean; - - pragma Import (Intrinsic, "<"); - pragma Import (Intrinsic, "<="); - pragma Import (Intrinsic, ">"); - pragma Import (Intrinsic, ">="); - pragma Import (Intrinsic, "="); - - -- Other System-Dependent Declarations - - type Bit_Order is (High_Order_First, Low_Order_First); - Default_Bit_Order : constant Bit_Order := Low_Order_First; - pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning - - -- Priority-related Declarations (RM D.1) - - -- Ada priorities are mapped to VxWorks priorities using the following - -- transformation: 255 - Ada Priority - - -- Ada priorities are used as follows: - - -- 256 is reserved for the VxWorks kernel - -- 248 - 255 correspond to hardware interrupt levels 0 .. 7 - -- 247 is a catchall default "interrupt" priority for signals, - -- allowing higher priority than normal tasks, but lower than - -- hardware priority levels. Protected Object ceilings can - -- override these values. - -- 246 is used by the Interrupt_Manager task - - Max_Priority : constant Positive := 245; - Max_Interrupt_Priority : constant Positive := 255; - - subtype Any_Priority is Integer range 0 .. 255; - subtype Priority is Any_Priority range 0 .. 245; - subtype Interrupt_Priority is Any_Priority range 246 .. 255; - - Default_Priority : constant Priority := 122; - -private - - pragma Linker_Options ("--specs=vxworks-x86-link.spec"); - -- Setup proper set of -L's for this configuration - - type Address is mod Memory_Size; - Null_Address : constant Address := 0; - - -------------------------------------- - -- System Implementation Parameters -- - -------------------------------------- - - -- These parameters provide information about the target that is used - -- by the compiler. They are in the private part of System, where they - -- can be accessed using the special circuitry in the Targparm unit - -- whose source should be consulted for more detailed descriptions - -- of the individual switch values. - - Backend_Divide_Checks : constant Boolean := False; - Backend_Overflow_Checks : constant Boolean := True; - Command_Line_Args : constant Boolean := False; - Configurable_Run_Time : constant Boolean := False; - Denorm : constant Boolean := True; - Duration_32_Bits : constant Boolean := False; - Exit_Status_Supported : constant Boolean := True; - Machine_Overflows : constant Boolean := False; - Machine_Rounds : constant Boolean := True; - Preallocated_Stacks : constant Boolean := False; - Signed_Zeros : constant Boolean := True; - Stack_Check_Default : constant Boolean := False; - Stack_Check_Probes : constant Boolean := False; - Stack_Check_Limits : constant Boolean := True; - Support_Aggregates : constant Boolean := True; - Support_Atomic_Primitives : constant Boolean := True; - Support_Composite_Assign : constant Boolean := True; - Support_Composite_Compare : constant Boolean := True; - Support_Long_Shifts : constant Boolean := True; - Always_Compatible_Rep : constant Boolean := False; - Suppress_Standard_Library : constant Boolean := False; - Use_Ada_Main_Program_Name : constant Boolean := True; - Frontend_Exceptions : constant Boolean := True; - ZCX_By_Default : constant Boolean := False; - - Executable_Extension : constant String := ".out"; - -end System; diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb index 084ca91..83d9681 100644 --- a/gcc/ada/repinfo.adb +++ b/gcc/ada/repinfo.adb @@ -367,46 +367,48 @@ package body Repinfo is null; else - -- If Esize and RM_Size are the same, list as Size. This is a common - -- case, which we may as well list in simple form. + if Known_Esize (Ent) and then Known_RM_Size (Ent) then + -- If Esize and RM_Size are the same, list as Size. This is a + -- common case, which we may as well list in simple form. - if Esize (Ent) = RM_Size (Ent) then - if List_Representation_Info_To_JSON then - Write_Str (" ""Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); - end if; + if Esize (Ent) = RM_Size (Ent) then + if List_Representation_Info_To_JSON then + Write_Str (" ""Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + end if; - -- Otherwise list size values separately + -- Otherwise list size values separately - else - if List_Representation_Info_To_JSON then - Write_Str (" ""Object_Size"": "); - Write_Val (Esize (Ent)); - Write_Line (","); + else + if List_Representation_Info_To_JSON then + Write_Str (" ""Object_Size"": "); + Write_Val (Esize (Ent)); + Write_Line (","); - Write_Str (" ""Value_Size"": "); - Write_Val (RM_Size (Ent)); - Write_Line (","); + Write_Str (" ""Value_Size"": "); + Write_Val (RM_Size (Ent)); + Write_Line (","); - else - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Object_Size use "); - Write_Val (Esize (Ent)); - Write_Line (";"); - - Write_Str ("for "); - List_Name (Ent); - Write_Str ("'Value_Size use "); - Write_Val (RM_Size (Ent)); - Write_Line (";"); + else + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Object_Size use "); + Write_Val (Esize (Ent)); + Write_Line (";"); + + Write_Str ("for "); + List_Name (Ent); + Write_Str ("'Value_Size use "); + Write_Val (RM_Size (Ent)); + Write_Line (";"); + end if; end if; end if; end if; diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb index 3eee2ee..ee5c7cf 100644 --- a/gcc/ada/sem.adb +++ b/gcc/ada/sem.adb @@ -1022,16 +1022,20 @@ package body Sem is Scop : Entity_Id; begin - -- Entity is global if defined outside of current outer_generic_scope: - -- Either the entity has a smaller depth that the outer generic, or it + -- Entity is global if defined outside of current Outer_Generic_Scope: + -- Either the entity has a smaller depth than the outer generic, or it -- is in a different compilation unit, or it is defined within a unit - -- in the same compilation, that is not within the outer_generic. + -- in the same compilation, that is not within the outer generic. if No (Outer_Generic_Scope) then return False; - elsif Scope_Depth (Scope (E)) < Scope_Depth (Outer_Generic_Scope) - or else not In_Same_Source_Unit (E, Outer_Generic_Scope) + -- It makes no sense to compare depths if not in same unit. Scope_Depth + -- is not set for inherited operations. + + elsif not In_Same_Source_Unit (E, Outer_Generic_Scope) + or else not Scope_Depth_Set (Scope (E)) + or else Scope_Depth (Scope (E)) < Scope_Depth (Outer_Generic_Scope) then return True; diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 527342f..42fb610 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -3384,9 +3384,8 @@ package body Sem_Aggr is function Nested_In (V1 : Node_Id; V2 : Node_Id) return Boolean; -- Determine whether variant V1 is within variant V2 - function Variant_Depth (N : Node_Id) return Integer; - -- Determine the distance of a variant to the enclosing type - -- declaration. + function Variant_Depth (N : Node_Id) return Natural; + -- Determine the distance of a variant to the enclosing type declaration -------------------- -- Check_Variant -- @@ -3492,8 +3491,8 @@ package body Sem_Aggr is -- Variant_Depth -- ------------------- - function Variant_Depth (N : Node_Id) return Integer is - Depth : Integer; + function Variant_Depth (N : Node_Id) return Natural is + Depth : Natural; Par : Node_Id; begin @@ -3546,7 +3545,19 @@ package body Sem_Aggr is end loop; pragma Assert (Present (Comp_Type)); - Analyze_And_Resolve (Expression (Assoc), Comp_Type); + + -- A record_component_association in record_delta_aggregate shall not + -- use the box compound delimiter <> rather than an expression; see + -- RM 4.3.1(17.3/5). + + pragma Assert (Present (Expression (Assoc)) xor Box_Present (Assoc)); + + if Box_Present (Assoc) then + Error_Msg_N + ("'<'> in record delta aggregate is not allowed", Assoc); + else + Analyze_And_Resolve (Expression (Assoc), Comp_Type); + end if; Next (Assoc); end loop; end Resolve_Delta_Record_Aggregate; diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index 32c5d37..f2bb12d 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -9251,14 +9251,12 @@ package body Sem_Attr is -- Machine -- ------------- - -- We use the same rounding mode as the one used for RM 4.9(38) + -- We use the same rounding as the one used for RM 4.9(38/2) when Attribute_Machine => Fold_Ureal - (N, - Eval_Fat.Machine - (P_Base_Type, Expr_Value_R (E1), Eval_Fat.Round_Even, N), - Static); + (N, Machine_Number (P_Base_Type, Expr_Value_R (E1), N), Static); + Set_Is_Machine_Number (N); ------------------ -- Machine_Emax -- diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index e4cb7e3..a62eb7c 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -5802,6 +5802,7 @@ package body Sem_Ch12 is if Is_Intrinsic_Subprogram (Gen_Unit) then Set_Is_Intrinsic_Subprogram (Anon_Id); + Set_Interface_Name (Anon_Id, Interface_Name (Gen_Unit)); end if; Analyze_Instance_And_Renamings; @@ -5818,14 +5819,13 @@ package body Sem_Ch12 is end if; -- If the generic is marked Import (Intrinsic), then so is the - -- instance. This indicates that there is no body to instantiate. If - -- generic is marked inline, so it the instance, and the anonymous - -- subprogram it renames. If inlined, or else if inlining is enabled - -- for the compilation, we generate the instance body even if it is - -- not within the main unit. + -- instance; this indicates that there is no body to instantiate. + -- We also copy the interface name in case this is handled by the + -- back-end and deal with an instance of unchecked conversion. if Is_Intrinsic_Subprogram (Gen_Unit) then Set_Is_Intrinsic_Subprogram (Act_Decl_Id); + Set_Interface_Name (Act_Decl_Id, Interface_Name (Gen_Unit)); if Chars (Gen_Unit) = Name_Unchecked_Conversion then Validate_Unchecked_Conversion (N, Act_Decl_Id); @@ -8090,7 +8090,9 @@ package body Sem_Ch12 is (Scope (Ent) = Current_Instantiated_Parent.Gen_Id and then not Is_Child_Unit (Ent)) or else - (Scope_Depth (Scope (Ent)) > + (Scope_Depth_Set (Scope (Ent)) + and then + Scope_Depth (Scope (Ent)) > Scope_Depth (Current_Instantiated_Parent.Gen_Id) and then Get_Source_Unit (Ent) = diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index c60dd97..3374e8b 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -7960,7 +7960,7 @@ package body Sem_Ch13 is ("stream size for elementary type must be 8, 16, 24, " & "32 or 64", N); - elsif RM_Size (U_Ent) > Size then + elsif Known_RM_Size (U_Ent) and then RM_Size (U_Ent) > Size then Error_Msg_Uint_1 := RM_Size (U_Ent); Error_Msg_N ("stream size for elementary type must be 8, 16, 24, " & @@ -17569,7 +17569,9 @@ package body Sem_Ch13 is Source_Siz := RM_Size (Source); Target_Siz := RM_Size (Target); - if Source_Siz /= Target_Siz then + if Present (Source_Siz) and then Present (Target_Siz) + and then Source_Siz /= Target_Siz + then Error_Msg ("?z?types for unchecked conversion have different sizes!", Eloc, Act_Unit); diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb index 57db637..c8d4ec1 100644 --- a/gcc/ada/sem_ch3.adb +++ b/gcc/ada/sem_ch3.adb @@ -6343,7 +6343,7 @@ package body Sem_Ch3 is -- Complete setup of implicit base type - Set_Component_Size (Implicit_Base, Uint_0); + pragma Assert (not Known_Component_Size (Implicit_Base)); Set_Component_Type (Implicit_Base, Element_Type); Set_Finalize_Storage_Only (Implicit_Base, @@ -6372,7 +6372,7 @@ package body Sem_Ch3 is Reinit_Size_Align (T); Set_Etype (T, T); Set_Scope (T, Current_Scope); - Set_Component_Size (T, Uint_0); + pragma Assert (not Known_Component_Size (T)); Set_Is_Constrained (T, False); Set_Is_Fixed_Lower_Bound_Array_Subtype (T, Has_FLB_Index); @@ -17585,7 +17585,7 @@ package body Sem_Ch3 is Set_High_Bound (R_Node, B_Node); -- Initialize various fields of the type. Some of this information - -- may be overwritten later through rep.clauses. + -- may be overwritten later through rep. clauses. Set_Scalar_Range (T, R_Node); Set_RM_Size (T, UI_From_Int (Minimum_Size (T))); @@ -18517,7 +18517,12 @@ package body Sem_Ch3 is Set_Size_Info (T, Implicit_Base); Set_RM_Size (T, RM_Size (Implicit_Base)); Inherit_Rep_Item_Chain (T, Implicit_Base); - Set_Digits_Value (T, Digs_Val); + + if Digs_Val >= Uint_1 then + Set_Digits_Value (T, Digs_Val); + else + pragma Assert (Serious_Errors_Detected > 0); null; + end if; end Floating_Point_Type_Declaration; ---------------------------- @@ -19641,8 +19646,8 @@ package body Sem_Ch3 is return; end if; - -- If the range bounds are "T'Low .. T'High" where T is a name of - -- a discrete type, then use T as the type of the index. + -- If the range bounds are "T'First .. T'Last" where T is a name of a + -- discrete type, then use T as the type of the index. if Nkind (Low_Bound (N)) = N_Attribute_Reference and then Attribute_Name (Low_Bound (N)) = Name_First @@ -21747,141 +21752,130 @@ package body Sem_Ch3 is -- represent the null range the Constraint_Error exception should -- not be raised. - -- ??? The Is_Null_Range (Lo, Hi) test should disappear since it - -- is done in the call to Range_Check (R, T); below. + -- Capture values of bounds and generate temporaries for them + -- if needed, before applying checks, since checks may cause + -- duplication of the expression without forcing evaluation. - if Is_Null_Range (Lo, Hi) then - null; + -- The forced evaluation removes side effects from expressions, + -- which should occur also in GNATprove mode. Otherwise, we end up + -- with unexpected insertions of actions at places where this is + -- not supposed to occur, e.g. on default parameters of a call. - else - -- Capture values of bounds and generate temporaries for them - -- if needed, before applying checks, since checks may cause - -- duplication of the expression without forcing evaluation. - - -- The forced evaluation removes side effects from expressions, - -- which should occur also in GNATprove mode. Otherwise, we end up - -- with unexpected insertions of actions at places where this is - -- not supposed to occur, e.g. on default parameters of a call. - - if Expander_Active or GNATprove_Mode then - - -- Call Force_Evaluation to create declarations as needed - -- to deal with side effects, and also create typ_FIRST/LAST - -- entities for bounds if we have a subtype name. - - -- Note: we do this transformation even if expansion is not - -- active if we are in GNATprove_Mode since the transformation - -- is in general required to ensure that the resulting tree has - -- proper Ada semantics. - - Force_Evaluation - (Lo, Related_Id => Subtyp, Is_Low_Bound => True); - Force_Evaluation - (Hi, Related_Id => Subtyp, Is_High_Bound => True); - end if; + if Expander_Active or GNATprove_Mode then - -- We use a flag here instead of suppressing checks on the type - -- because the type we check against isn't necessarily the place - -- where we put the check. + -- Call Force_Evaluation to create declarations as needed + -- to deal with side effects, and also create typ_FIRST/LAST + -- entities for bounds if we have a subtype name. - R_Checks := Get_Range_Checks (R, T); + -- Note: we do this transformation even if expansion is not + -- active if we are in GNATprove_Mode since the transformation + -- is in general required to ensure that the resulting tree has + -- proper Ada semantics. - -- Look up tree to find an appropriate insertion point. We can't - -- just use insert_actions because later processing depends on - -- the insertion node. Prior to Ada 2012 the insertion point could - -- only be a declaration or a loop, but quantified expressions can - -- appear within any context in an expression, and the insertion - -- point can be any statement, pragma, or declaration. + Force_Evaluation + (Lo, Related_Id => Subtyp, Is_Low_Bound => True); + Force_Evaluation + (Hi, Related_Id => Subtyp, Is_High_Bound => True); + end if; - Insert_Node := Parent (R); - while Present (Insert_Node) loop - exit when - Nkind (Insert_Node) in N_Declaration - and then - Nkind (Insert_Node) not in N_Component_Declaration - | N_Loop_Parameter_Specification - | N_Function_Specification - | N_Procedure_Specification; - - exit when Nkind (Insert_Node) in - N_Later_Decl_Item | - N_Statement_Other_Than_Procedure_Call | - N_Procedure_Call_Statement | - N_Pragma; - - Insert_Node := Parent (Insert_Node); - end loop; + -- We use a flag here instead of suppressing checks on the type + -- because the type we check against isn't necessarily the place + -- where we put the check. - -- Why would Type_Decl not be present??? Without this test, - -- short regression tests fail. + R_Checks := Get_Range_Checks (R, T); - if Present (Insert_Node) then + -- Look up tree to find an appropriate insertion point. We can't + -- just use insert_actions because later processing depends on + -- the insertion node. Prior to Ada 2012 the insertion point could + -- only be a declaration or a loop, but quantified expressions can + -- appear within any context in an expression, and the insertion + -- point can be any statement, pragma, or declaration. - -- Case of loop statement. Verify that the range is part of the - -- subtype indication of the iteration scheme. + Insert_Node := Parent (R); + while Present (Insert_Node) loop + exit when + Nkind (Insert_Node) in N_Declaration + and then + Nkind (Insert_Node) not in N_Component_Declaration + | N_Loop_Parameter_Specification + | N_Function_Specification + | N_Procedure_Specification; + + exit when Nkind (Insert_Node) in + N_Later_Decl_Item | + N_Statement_Other_Than_Procedure_Call | + N_Procedure_Call_Statement | + N_Pragma; + + Insert_Node := Parent (Insert_Node); + end loop; - if Nkind (Insert_Node) = N_Loop_Statement then - declare - Indic : Node_Id; + if Present (Insert_Node) then - begin - Indic := Parent (R); - while Present (Indic) - and then Nkind (Indic) /= N_Subtype_Indication - loop - Indic := Parent (Indic); - end loop; + -- Case of loop statement. Verify that the range is part of the + -- subtype indication of the iteration scheme. - if Present (Indic) then - Def_Id := Etype (Subtype_Mark (Indic)); + if Nkind (Insert_Node) = N_Loop_Statement then + declare + Indic : Node_Id; - Insert_Range_Checks - (R_Checks, - Insert_Node, - Def_Id, - Sloc (Insert_Node), - Do_Before => True); - end if; - end; + begin + Indic := Parent (R); + while Present (Indic) + and then Nkind (Indic) /= N_Subtype_Indication + loop + Indic := Parent (Indic); + end loop; - -- Case of declarations. If the declaration is for a type and - -- involves discriminants, the checks are premature at the - -- declaration point and need to wait for the expansion of the - -- initialization procedure, which will pass in the list to put - -- them on; otherwise, the checks are done at the declaration - -- point and there is no need to do them again in the - -- initialization procedure. + if Present (Indic) then + Def_Id := Etype (Subtype_Mark (Indic)); - elsif Nkind (Insert_Node) in N_Declaration then - Def_Id := Defining_Identifier (Insert_Node); + Insert_Range_Checks + (R_Checks, + Insert_Node, + Def_Id, + Sloc (Insert_Node), + Do_Before => True); + end if; + end; - if (Ekind (Def_Id) = E_Record_Type - and then Depends_On_Discriminant (R)) - or else - (Ekind (Def_Id) = E_Protected_Type - and then Has_Discriminants (Def_Id)) - then - if Present (Check_List) then - Append_Range_Checks - (R_Checks, - Check_List, Def_Id, Sloc (Insert_Node)); - end if; + -- Case of declarations. If the declaration is for a type and + -- involves discriminants, the checks are premature at the + -- declaration point and need to wait for the expansion of the + -- initialization procedure, which will pass in the list to put + -- them on; otherwise, the checks are done at the declaration + -- point and there is no need to do them again in the + -- initialization procedure. - else - if No (Check_List) then - Insert_Range_Checks - (R_Checks, - Insert_Node, Def_Id, Sloc (Insert_Node)); - end if; - end if; + elsif Nkind (Insert_Node) in N_Declaration then + Def_Id := Defining_Identifier (Insert_Node); - -- Case of statements. Drop the checks, as the range appears in - -- the context of a quantified expression. Insertion will take - -- place when expression is expanded. + if (Ekind (Def_Id) = E_Record_Type + and then Depends_On_Discriminant (R)) + or else + (Ekind (Def_Id) = E_Protected_Type + and then Has_Discriminants (Def_Id)) + then + if Present (Check_List) then + Append_Range_Checks + (R_Checks, + Check_List, Def_Id, Sloc (Insert_Node)); + end if; else - null; + if No (Check_List) then + Insert_Range_Checks + (R_Checks, + Insert_Node, Def_Id, Sloc (Insert_Node)); + end if; end if; + + -- Case of statements. Drop the checks, as the range appears in + -- the context of a quantified expression. Insertion will take + -- place when expression is expanded. + + else + null; end if; end if; diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb index 169b01b..fecc060a 100644 --- a/gcc/ada/sem_ch4.adb +++ b/gcc/ada/sem_ch4.adb @@ -4299,21 +4299,67 @@ package body Sem_Ch4 is Loop_Id := Defining_Identifier (Loop_Parameter_Specification (N)); end if; - if Warn_On_Suspicious_Contract - and then not Referenced (Loop_Id, Cond) - and then not Is_Internal_Name (Chars (Loop_Id)) - then - -- Generating C, this check causes spurious warnings on inlined - -- postconditions; we can safely disable it because this check - -- was previously performed when analyzing the internally built - -- postconditions procedure. + declare + type Subexpr_Kind is (Full, Conjunct, Disjunct); - if Modify_Tree_For_C and then In_Inlined_Body then - null; - else - Error_Msg_N ("?T?unused variable &", Loop_Id); + procedure Check_Subexpr (Expr : Node_Id; Kind : Subexpr_Kind); + -- Check that the quantified variable appears in every sub-expression + -- of the quantified expression. If Kind is Full, Expr is the full + -- expression. If Kind is Conjunct (resp. Disjunct), Expr is a + -- conjunct (resp. disjunct) of the full expression. + + ------------------- + -- Check_Subexpr -- + ------------------- + + procedure Check_Subexpr (Expr : Node_Id; Kind : Subexpr_Kind) is + begin + if Nkind (Expr) in N_Op_And | N_And_Then + and then Kind /= Disjunct + then + Check_Subexpr (Left_Opnd (Expr), Conjunct); + Check_Subexpr (Right_Opnd (Expr), Conjunct); + + elsif Nkind (Expr) in N_Op_Or | N_Or_Else + and then Kind /= Conjunct + then + Check_Subexpr (Left_Opnd (Expr), Disjunct); + Check_Subexpr (Right_Opnd (Expr), Disjunct); + + elsif Kind /= Full + and then not Referenced (Loop_Id, Expr) + then + declare + Sub : constant String := + (if Kind = Conjunct then "conjunct" else "disjunct"); + begin + Error_Msg_NE + ("?T?unused variable & in " & Sub, Expr, Loop_Id); + Error_Msg_NE + ("\consider extracting " & Sub & " from quantified " + & "expression", Expr, Loop_Id); + end; + end if; + end Check_Subexpr; + + begin + if Warn_On_Suspicious_Contract + and then not Is_Internal_Name (Chars (Loop_Id)) + + -- Generating C, this check causes spurious warnings on inlined + -- postconditions; we can safely disable it because this check + -- was previously performed when analyzing the internally built + -- postconditions procedure. + + and then not (Modify_Tree_For_C and In_Inlined_Body) + then + if not Referenced (Loop_Id, Cond) then + Error_Msg_N ("?T?unused variable &", Loop_Id); + else + Check_Subexpr (Cond, Kind => Full); + end if; end if; - end if; + end; -- Diagnose a possible misuse of the SOME existential quantifier. When -- we have a quantified expression of the form: diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index e32c4ad..1486918 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -90,6 +90,7 @@ with Tbuild; use Tbuild; with Uintp; use Uintp; with Urealp; use Urealp; with Validsw; use Validsw; +with Warnsw; use Warnsw; package body Sem_Ch6 is @@ -806,6 +807,7 @@ package body Sem_Ch6 is Assoc_Expr : Node_Id; Assoc_Present : Boolean := False; + Check_Cond : Node_Id; Unseen_Disc_Count : Nat := 0; Seen_Discs : Elist_Id; Disc : Entity_Id; @@ -1179,36 +1181,39 @@ package body Sem_Ch6 is and then Present (Disc) and then Ekind (Etype (Disc)) = E_Anonymous_Access_Type then - -- Perform a static check first, if possible + -- Generate a dynamic check based on the extra accessibility of + -- the result or the scope. + + Check_Cond := + Make_Op_Gt (Loc, + Left_Opnd => Accessibility_Level + (Expr => Assoc_Expr, + Level => Dynamic_Level, + In_Return_Context => True), + Right_Opnd => (if Present + (Extra_Accessibility_Of_Result + (Scope_Id)) + then + Extra_Accessibility_Of_Result (Scope_Id) + else + Make_Integer_Literal + (Loc, Scope_Depth (Scope (Scope_Id))))); + + Insert_Before_And_Analyze (Return_Stmt, + Make_Raise_Program_Error (Loc, + Condition => Check_Cond, + Reason => PE_Accessibility_Check_Failed)); + + -- If constant folding has happened on the condition for the + -- generated error, then warn about it being unconditional when + -- we know an error will be raised. - if Static_Accessibility_Level - (Expr => Assoc_Expr, - Level => Zero_On_Dynamic_Level, - In_Return_Context => True) - > Scope_Depth (Scope (Scope_Id)) + if Nkind (Check_Cond) = N_Identifier + and then Entity (Check_Cond) = Standard_True then Error_Msg_N ("access discriminant in return object would be a dangling" & " reference", Return_Stmt); - - exit; - end if; - - -- Otherwise, generate a dynamic check based on the extra - -- accessibility of the result. - - if Present (Extra_Accessibility_Of_Result (Scope_Id)) then - Insert_Before_And_Analyze (Return_Stmt, - Make_Raise_Program_Error (Loc, - Condition => - Make_Op_Gt (Loc, - Left_Opnd => Accessibility_Level - (Expr => Assoc_Expr, - Level => Dynamic_Level, - In_Return_Context => True), - Right_Opnd => Extra_Accessibility_Of_Result - (Scope_Id)), - Reason => PE_Accessibility_Check_Failed)); end if; end if; @@ -5962,6 +5967,17 @@ package body Sem_Ch6 is -- True if the null exclusions of two formals of anonymous access type -- match. + function Subprogram_Subtypes_Have_Same_Declaration + (Subp : Entity_Id; + Decl_Subtype : Entity_Id; + Body_Subtype : Entity_Id) return Boolean; + -- Checks whether corresponding subtypes named within a subprogram + -- declaration and body originate from the same declaration, and returns + -- True when they do. In the case of anonymous access-to-object types, + -- checks the designated types. Also returns True when GNAT_Mode is + -- enabled, or when the subprogram is marked Is_Internal or occurs + -- within a generic instantiation or internal unit (GNAT library unit). + ----------------------- -- Conformance_Error -- ----------------------- @@ -6094,6 +6110,86 @@ package body Sem_Ch6 is end if; end Null_Exclusions_Match; + function Subprogram_Subtypes_Have_Same_Declaration + (Subp : Entity_Id; + Decl_Subtype : Entity_Id; + Body_Subtype : Entity_Id) return Boolean + is + + function Nonlimited_View_Of_Subtype + (Subt : Entity_Id) return Entity_Id; + -- Returns the nonlimited view of a type or subtype that is an + -- incomplete or class-wide type that comes from a limited view of + -- a package (From_Limited_With is True for the entity), or the + -- full view when the subtype is an incomplete type. Otherwise + -- returns the entity passed in. + + function Nonlimited_View_Of_Subtype + (Subt : Entity_Id) return Entity_Id + is + Subt_Temp : Entity_Id := Subt; + begin + if Ekind (Subt) in Incomplete_Kind | E_Class_Wide_Type + and then From_Limited_With (Subt) + then + Subt_Temp := Non_Limited_View (Subt); + end if; + + -- If the subtype is incomplete, return full view if present + -- (and accounts for the case where a type from a limited view + -- is itself an incomplete type). + + if Ekind (Subt_Temp) in Incomplete_Kind + and then Present (Full_View (Subt_Temp)) + then + Subt_Temp := Full_View (Subt_Temp); + end if; + + return Subt_Temp; + end Nonlimited_View_Of_Subtype; + + -- Start of processing for Subprogram_Subtypes_Have_Same_Declaration + + begin + if not In_Instance + and then not In_Internal_Unit (Subp) + and then not Is_Internal (Subp) + and then not GNAT_Mode + and then + Ekind (Etype (Decl_Subtype)) not in Access_Subprogram_Kind + then + if Ekind (Etype (Decl_Subtype)) = E_Anonymous_Access_Type then + if Nonlimited_View_Of_Subtype (Designated_Type (Decl_Subtype)) + /= Nonlimited_View_Of_Subtype (Designated_Type (Body_Subtype)) + then + return False; + end if; + + elsif Nonlimited_View_Of_Subtype (Decl_Subtype) + /= Nonlimited_View_Of_Subtype (Body_Subtype) + then + -- Avoid returning False (and a false-positive warning) for + -- the case of "not null" itypes, which will appear to be + -- different subtypes even when the subtype_marks denote + -- the same subtype. + + if Ekind (Decl_Subtype) = E_Access_Subtype + and then Ekind (Body_Subtype) = E_Access_Subtype + and then Is_Itype (Body_Subtype) + and then Can_Never_Be_Null (Body_Subtype) + and then Etype (Decl_Subtype) = Etype (Body_Subtype) + then + return True; + + else + return False; + end if; + end if; + end if; + + return True; + end Subprogram_Subtypes_Have_Same_Declaration; + -- Local Variables Old_Type : constant Entity_Id := Etype (Old_Id); @@ -6147,6 +6243,18 @@ package body Sem_Ch6 is end if; return; + + -- If the result subtypes conform and pedantic checks are enabled, + -- check to see whether the subtypes originate from different + -- declarations, and issue a warning when they do. + + elsif Ctype = Fully_Conformant + and then Warn_On_Pedantic_Checks + and then not Subprogram_Subtypes_Have_Same_Declaration + (Old_Id, Old_Type, New_Type) + then + Error_Msg_N ("result subtypes conform but come from different " + & "declarations??", New_Id); end if; -- Ada 2005 (AI-231): In case of anonymous access types check the @@ -6343,6 +6451,18 @@ package body Sem_Ch6 is end if; return; + + -- If the formals' subtypes conform and pedantic checks are enabled, + -- check to see whether the subtypes originate from different + -- declarations, and issue a warning when they do. + + elsif Ctype = Fully_Conformant + and then Warn_On_Pedantic_Checks + and then not Subprogram_Subtypes_Have_Same_Declaration + (Old_Id, Old_Formal_Base, New_Formal_Base) + then + Error_Msg_N ("formal subtypes conform but come from " + & "different declarations??", New_Formal); end if; -- For mode conformance, mode must match diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb index 494ec64..7b3dfa6 100644 --- a/gcc/ada/sem_ch8.adb +++ b/gcc/ada/sem_ch8.adb @@ -7279,8 +7279,10 @@ package body Sem_Ch8 is if Within (It.Nam, Inst) then if Within (Old_S, Inst) then declare - It_D : constant Uint := Scope_Depth (It.Nam); - Old_D : constant Uint := Scope_Depth (Old_S); + It_D : constant Uint := + Scope_Depth_Default_0 (It.Nam); + Old_D : constant Uint := + Scope_Depth_Default_0 (Old_S); N_Ent : Entity_Id; begin -- Choose the innermost subprogram, which @@ -9057,10 +9059,12 @@ package body Sem_Ch8 is Set_Scope_Depth_Value (S, Uint_1); elsif not Is_Record_Type (Current_Scope) then - if Ekind (S) = E_Loop then - Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope)); - else - Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1); + if Scope_Depth_Set (Current_Scope) then + if Ekind (S) = E_Loop then + Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope)); + else + Set_Scope_Depth_Value (S, Scope_Depth (Current_Scope) + 1); + end if; end if; end if; end if; diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index 20bc03a..7270172 100644 --- a/gcc/ada/sem_eval.adb +++ b/gcc/ada/sem_eval.adb @@ -523,8 +523,8 @@ package body Sem_Eval is and then Nkind (Parent (N)) in N_Subexpr then Rewrite (N, New_Copy (N)); - Set_Realval - (N, Machine (Base_Type (T), Realval (N), Round_Even, N)); + Set_Realval (N, Machine_Number (Base_Type (T), Realval (N), N)); + Set_Is_Machine_Number (N); end if; end if; @@ -575,18 +575,7 @@ package body Sem_Eval is (N, Corresponding_Integer_Value (N) * Small_Value (T)); elsif not UR_Is_Zero (Realval (N)) then - - -- Note: even though RM 4.9(38) specifies biased rounding, this - -- has been modified by AI-100 in order to prevent confusing - -- differences in rounding between static and non-static - -- expressions. AI-100 specifies that the effect of such rounding - -- is implementation dependent, and in GNAT we round to nearest - -- even to match the run-time behavior. Note that this applies - -- to floating point literals, not fixed points ones, even though - -- their compiler representation is also as a universal real. - - Set_Realval - (N, Machine (Base_Type (T), Realval (N), Round_Even, N)); + Set_Realval (N, Machine_Number (Base_Type (T), Realval (N), N)); Set_Is_Machine_Number (N); end if; @@ -2845,7 +2834,7 @@ package body Sem_Eval is -- the expander that do not correspond to static expressions. procedure Eval_Integer_Literal (N : Node_Id) is - function In_Any_Integer_Context (Context : Node_Id) return Boolean; + function In_Any_Integer_Context (K : Node_Kind) return Boolean; -- If the literal is resolved with a specific type in a context where -- the expected type is Any_Integer, there are no range checks on the -- literal. By the time the literal is evaluated, it carries the type @@ -2856,23 +2845,21 @@ package body Sem_Eval is -- In_Any_Integer_Context -- ---------------------------- - function In_Any_Integer_Context (Context : Node_Id) return Boolean is + function In_Any_Integer_Context (K : Node_Kind) return Boolean is begin -- Any_Integer also appears in digits specifications for real types, -- but those have bounds smaller that those of any integer base type, -- so we can safely ignore these cases. - return - Nkind (Context) in N_Attribute_Definition_Clause - | N_Attribute_Reference - | N_Modular_Type_Definition - | N_Number_Declaration - | N_Signed_Integer_Type_Definition; + return K in N_Attribute_Definition_Clause + | N_Modular_Type_Definition + | N_Number_Declaration + | N_Signed_Integer_Type_Definition; end In_Any_Integer_Context; -- Local variables - Par : constant Node_Id := Parent (N); + PK : constant Node_Kind := Nkind (Parent (N)); Typ : constant Entity_Id := Etype (N); -- Start of processing for Eval_Integer_Literal @@ -2890,12 +2877,11 @@ package body Sem_Eval is -- Check_Non_Static_Context on an expanded literal may lead to spurious -- and misleading warnings. - if (Nkind (Par) in N_Case_Expression_Alternative | N_If_Expression - or else Nkind (Par) not in N_Subexpr) - and then (Nkind (Par) not in N_Case_Expression_Alternative - | N_If_Expression - or else Comes_From_Source (N)) - and then not In_Any_Integer_Context (Par) + if (PK not in N_Subexpr + or else (PK in N_Case_Expression_Alternative | N_If_Expression + and then + Comes_From_Source (N))) + and then not In_Any_Integer_Context (PK) then Check_Non_Static_Context (N); end if; @@ -4366,7 +4352,25 @@ package body Sem_Eval is Fold_Uint (N, Expr_Value (Operand), Stat); end if; - if Is_Out_Of_Range (N, Etype (N), Assume_Valid => True) then + -- If the target is a static floating-point subtype, then its bounds + -- are machine numbers so we must consider the machine-rounded value. + + if Is_Floating_Point_Type (Target_Type) + and then Nkind (N) = N_Real_Literal + and then not Is_Machine_Number (N) + then + declare + Lo : constant Node_Id := Type_Low_Bound (Target_Type); + Hi : constant Node_Id := Type_High_Bound (Target_Type); + Valr : constant Ureal := + Machine_Number (Target_Type, Expr_Value_R (N), N); + begin + if Valr < Expr_Value_R (Lo) or else Valr > Expr_Value_R (Hi) then + Out_Of_Range (N); + end if; + end; + + elsif Is_Out_Of_Range (N, Etype (N), Assume_Valid => True) then Out_Of_Range (N); end if; end Eval_Type_Conversion; @@ -6049,6 +6053,27 @@ package body Sem_Eval is end Is_Statically_Unevaluated; -------------------- + -- Machine_Number -- + -------------------- + + -- Historical note: RM 4.9(38) originally specified biased rounding but + -- this has been modified by AI-268 to prevent confusing differences in + -- rounding between static and nonstatic expressions. This AI specifies + -- that the effect of such rounding is implementation-dependent instead, + -- and in GNAT we round to nearest even to match the run-time behavior. + -- Note that this applies to floating-point literals, not fixed-point + -- ones, even though their representation is also a universal real. + + function Machine_Number + (Typ : Entity_Id; + Val : Ureal; + N : Node_Id) return Ureal + is + begin + return Machine (Typ, Val, Round_Even, N); + end Machine_Number; + + -------------------- -- Not_Null_Range -- -------------------- @@ -7335,19 +7360,12 @@ package body Sem_Eval is elsif Compile_Time_Known_Value (N) then declare - Lo : Node_Id; - Hi : Node_Id; - - LB_Known : Boolean; - HB_Known : Boolean; + Lo : constant Node_Id := Type_Low_Bound (Typ); + Hi : constant Node_Id := Type_High_Bound (Typ); + LB_Known : constant Boolean := Compile_Time_Known_Value (Lo); + HB_Known : constant Boolean := Compile_Time_Known_Value (Hi); begin - Lo := Type_Low_Bound (Typ); - Hi := Type_High_Bound (Typ); - - LB_Known := Compile_Time_Known_Value (Lo); - HB_Known := Compile_Time_Known_Value (Hi); - -- Fixed point types should be considered as such only if flag -- Fixed_Int is set to False. diff --git a/gcc/ada/sem_eval.ads b/gcc/ada/sem_eval.ads index 5e1c2cb..c2e08b6 100644 --- a/gcc/ada/sem_eval.ads +++ b/gcc/ada/sem_eval.ads @@ -149,10 +149,9 @@ package Sem_Eval is -- -- Note: most cases of non-static context checks are handled within -- Sem_Eval itself, including all cases of expressions at the outer level - -- (i.e. those that are not a subexpression). Currently the only outside - -- customer for this procedure is Sem_Attr (because Eval_Attribute is - -- there). There is also one special case arising from ranges (see body of - -- Resolve_Range). + -- (i.e. those that are not a subexpression). The outside customers for + -- this procedure are Sem_Aggr, Sem_Attr (because Eval_Attribute is there) + -- and Sem_Res (for a special case arising from ranges, see Resolve_Range). -- -- Note: this procedure is also called by GNATprove on real literals -- that are not sub-expressions of static expressions, to convert them to @@ -487,6 +486,13 @@ package Sem_Eval is -- it cannot be determined at compile time. Flag Fixed_Int is used as in -- routine Is_In_Range above. + function Machine_Number + (Typ : Entity_Id; + Val : Ureal; + N : Node_Id) return Ureal; + -- Return the machine number of Typ corresponding to the specified Val as + -- per RM 4.9(38/2). N is a node only used to post warnings. + function Not_Null_Range (Lo : Node_Id; Hi : Node_Id) return Boolean; -- Returns True if it can guarantee that Lo .. Hi is not a null range. If -- it cannot (because the value of Lo or Hi is not known at compile time) @@ -575,5 +581,6 @@ private pragma Inline (Eval_Unchecked_Conversion); pragma Inline (Is_OK_Static_Expression); + pragma Inline (Machine_Number); end Sem_Eval; diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb index b3fa32a..1e6397f 100644 --- a/gcc/ada/sem_prag.adb +++ b/gcc/ada/sem_prag.adb @@ -4144,8 +4144,10 @@ package body Sem_Prag is -- than library level instantiations these can appear in contexts which -- would normally be invalid (they only apply to the original template -- and to library level instantiations), and they are simply ignored, - -- which is implemented by rewriting them as null statements and raising - -- exception to terminate analysis. + -- which is implemented by rewriting them as null statements and + -- optionally raising Pragma_Exit to terminate analysis. An exception + -- is not always raised to avoid exception propagation during the + -- bootstrap, so all callers should check whether N has been rewritten. procedure Check_Variant (Variant : Node_Id; UU_Typ : Entity_Id); -- Check an Unchecked_Union variant for lack of nested variants and @@ -6652,8 +6654,14 @@ package body Sem_Prag is Sindex := Source_Index (Current_Sem_Unit); if Loc not in Source_First (Sindex) .. Source_Last (Sindex) then + -- We do not want to raise an exception here since this code + -- is part of the bootstrap path where we cannot rely on + -- exception proapgation working. + -- Instead the caller should check for N being rewritten as + -- a null statement. + -- This code triggers when compiling a-except.adb. + Rewrite (N, Make_Null_Statement (Loc)); - raise Pragma_Exit; -- If before first declaration, the pragma applies to the -- enclosing unit, and the name if present must be this name. @@ -12719,6 +12727,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Lib_Entity := Find_Lib_Unit_Name; -- A pragma that applies to a Ghost entity becomes Ghost for the @@ -15967,6 +15982,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -19650,6 +19672,13 @@ package body Sem_Prag is GNAT_Pragma; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + -- Must appear for a spec or generic spec if Nkind (Unit (Cunit (Current_Sem_Unit))) not in @@ -21436,6 +21465,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Ent := Find_Lib_Unit_Name; -- A pragma that applies to a Ghost entity becomes Ghost for the @@ -22072,8 +22108,15 @@ package body Sem_Prag is if Is_Wrapper_Package (Current_Scope) then return; - else - Check_Valid_Library_Unit_Pragma; + end if; + + Check_Valid_Library_Unit_Pragma; + + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; end if; Ent := Find_Lib_Unit_Name; @@ -22612,6 +22655,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); K := Nkind (Unit (Cunit_Node)); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -22651,6 +22701,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); @@ -22847,6 +22904,13 @@ package body Sem_Prag is Check_Ada_83_Warning; Check_Valid_Library_Unit_Pragma; + -- If N was rewritten as a null statement there is nothing more + -- to do. + + if Nkind (N) = N_Null_Statement then + return; + end if; + Cunit_Node := Cunit (Current_Sem_Unit); Cunit_Ent := Cunit_Entity (Current_Sem_Unit); diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index e79c534..db4d55a 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -315,7 +315,8 @@ package body Sem_Util is -- Ignore transient scopes made during expansion if Comes_From_Source (Node_Par) then - return Scope_Depth (Encl_Scop) + Master_Lvl_Modifier; + return + Scope_Depth_Default_0 (Encl_Scop) + Master_Lvl_Modifier; end if; -- For a return statement within a function, return @@ -627,9 +628,9 @@ package body Sem_Util is -- caller. if Is_Explicitly_Aliased (E) - and then Level /= Dynamic_Level - and then (In_Return_Value (Expr) - or else In_Return_Context) + and then (In_Return_Context + or else (Level /= Dynamic_Level + and then In_Return_Value (Expr))) then return Make_Level_Literal (Scope_Depth (Standard_Standard)); @@ -1137,6 +1138,10 @@ package body Sem_Util is function Addressable (V : Uint) return Boolean is begin + if No (V) then + return False; + end if; + return V = Uint_8 or else V = Uint_16 or else V = Uint_32 or else diff --git a/gcc/ada/sinfo-utils.adb b/gcc/ada/sinfo-utils.adb index cf0ecc1..79269a5 100644 --- a/gcc/ada/sinfo-utils.adb +++ b/gcc/ada/sinfo-utils.adb @@ -242,15 +242,28 @@ package body Sinfo.Utils is use Seinfo; function Is_In_Union_Id (F_Kind : Field_Kind) return Boolean is - (F_Kind in Node_Id_Field - | List_Id_Field - | Elist_Id_Field - | Name_Id_Field - | String_Id_Field - | Uint_Field - | Ureal_Field - | Union_Id_Field); -- True if the field type is one that can be converted to Types.Union_Id + (case F_Kind is + when Node_Id_Field + | List_Id_Field + | Elist_Id_Field + | Name_Id_Field + | String_Id_Field + | Valid_Uint_Field + | Unat_Field + | Upos_Field + | Nonzero_Uint_Field + | Uint_Field + | Ureal_Field + | Union_Id_Field => True, + when Flag_Field + | Node_Kind_Type_Field + | Entity_Kind_Type_Field + | Source_Ptr_Field + | Small_Paren_Count_Type_Field + | Convention_Id_Field + | Component_Alignment_Kind_Field + | Mechanism_Type_Field => False); ----------------------- -- Walk_Sinfo_Fields -- diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb index 9b78ada..69996cb 100644 --- a/gcc/ada/sprint.adb +++ b/gcc/ada/sprint.adb @@ -4394,7 +4394,12 @@ package body Sprint is when E_Modular_Integer_Type => Write_Header; Write_Str ("mod "); - Write_Uint_With_Col_Check (Modulus (Typ), Auto); + + if No (Modulus (Typ)) then + Write_Uint_With_Col_Check (Uint_0, Auto); + else + Write_Uint_With_Col_Check (Modulus (Typ), Auto); + end if; -- Floating-point types and subtypes diff --git a/gcc/ada/treepr.adb b/gcc/ada/treepr.adb index 2e9d2c2..d36042c 100644 --- a/gcc/ada/treepr.adb +++ b/gcc/ada/treepr.adb @@ -885,14 +885,13 @@ package body Treepr is Val : constant Uint := Get_Uint (N, FD.Offset); function Cast is new Unchecked_Conversion (Uint, Int); begin - -- Do this even if Val = No_Uint, because Uint fields default - -- to Uint_0. - - Print_Initial; - UI_Write (Val, Format); - Write_Str (" (Uint = "); - Write_Int (Cast (Val)); - Write_Char (')'); + if Present (Val) then + Print_Initial; + UI_Write (Val, Format); + Write_Str (" (Uint = "); + Write_Int (Cast (Val)); + Write_Char (')'); + end if; end; when Valid_Uint_Field | Unat_Field | Upos_Field diff --git a/gcc/ada/types.h b/gcc/ada/types.h index 2806e50..0938365 100644 --- a/gcc/ada/types.h +++ b/gcc/ada/types.h @@ -261,10 +261,10 @@ typedef Int String_Id; /* Type used for representation of universal integers. */ typedef Int Uint; -typedef Int Valid_Uint; -typedef Int Unat; -typedef Int Upos; -typedef Int Nonzero_Uint; +typedef Uint Valid_Uint; +typedef Uint Unat; +typedef Uint Upos; +typedef Uint Nonzero_Uint; /* Used to indicate missing Uint value. */ #define No_Uint Uint_Low_Bound diff --git a/gcc/ada/uintp.adb b/gcc/ada/uintp.adb index 29d409b..5d1dec1 100644 --- a/gcc/ada/uintp.adb +++ b/gcc/ada/uintp.adb @@ -282,7 +282,10 @@ package body Uintp is -- value is returned from a correctness point of view. procedure Image_Char (C : Character); - -- Internal procedure to output one character + -- Output one character + + procedure Image_String (S : String); + -- Output characters procedure Image_Exponent (N : Natural); -- Output non-zero exponent. Note that we only use the exponent form in @@ -371,6 +374,17 @@ package body Uintp is Character'Val (Character'Pos ('0') + N mod 10); end Image_Exponent; + ------------------ + -- Image_String -- + ------------------ + + procedure Image_String (S : String) is + begin + for X in S'Range loop + Image_Char (S (X)); + end loop; + end Image_String; + ---------------- -- Image_Uint -- ---------------- @@ -401,7 +415,7 @@ package body Uintp is begin if No (Input) then - Image_Char ('?'); + Image_String ("No_Uint"); return; end if; diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb index bca3527..207303b 100644 --- a/gcc/ada/usage.adb +++ b/gcc/ada/usage.adb @@ -557,6 +557,8 @@ begin "order"); Write_Line (" .P* turn off warnings for suspicious parameter " & "order"); + Write_Line (" _p turn on warnings for pedantic checks"); + Write_Line (" _P turn off warnings for pedantic checks"); Write_Line (" q*+ turn on warnings for questionable " & "missing parenthesis"); Write_Line (" Q turn off warnings for questionable " & diff --git a/gcc/ada/vxworks7-cert-rtp-link.spec b/gcc/ada/vxworks7-cert-rtp-link.spec index 0e0440f..4bbf376 100644 --- a/gcc/ada/vxworks7-cert-rtp-link.spec +++ b/gcc/ada/vxworks7-cert-rtp-link.spec @@ -5,5 +5,6 @@ + %{!nostdlib:%{mrtp:%{!shared: \ -l:certRtp.o \ -L%:getenv(VSB_DIR /usr/lib/common/objcert) \ + --defsym=__wrs_rtp_base=0x80000000 \ -T%:getenv(VSB_DIR /usr/ldscripts/rtp.ld) \ }}} diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb index 912ceea..149e2fd 100644 --- a/gcc/ada/warnsw.adb +++ b/gcc/ada/warnsw.adb @@ -76,6 +76,7 @@ package body Warnsw is Warn_On_Overlap := Setting; Warn_On_Overridden_Size := Setting; Warn_On_Parameter_Order := Setting; + Warn_On_Pedantic_Checks := Setting; Warn_On_Questionable_Layout := Setting; Warn_On_Questionable_Missing_Parens := Setting; Warn_On_Record_Holes := Setting; @@ -172,6 +173,8 @@ package body Warnsw is W.Warn_On_Overridden_Size; Warn_On_Parameter_Order := W.Warn_On_Parameter_Order; + Warn_On_Pedantic_Checks := + W.Warn_On_Pedantic_Checks; Warn_On_Questionable_Layout := W.Warn_On_Questionable_Layout; Warn_On_Questionable_Missing_Parens := @@ -284,6 +287,8 @@ package body Warnsw is Warn_On_Overridden_Size; W.Warn_On_Parameter_Order := Warn_On_Parameter_Order; + W.Warn_On_Pedantic_Checks := + Warn_On_Pedantic_Checks; W.Warn_On_Questionable_Layout := Warn_On_Questionable_Layout; W.Warn_On_Questionable_Missing_Parens := @@ -505,6 +510,12 @@ package body Warnsw is when 'C' => Warn_On_Unknown_Compile_Time_Warning := False; + when 'p' => + Warn_On_Pedantic_Checks := True; + + when 'P' => + Warn_On_Pedantic_Checks := False; + when 'r' => Warn_On_Component_Order := True; diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads index 340a752..6113538 100644 --- a/gcc/ada/warnsw.ads +++ b/gcc/ada/warnsw.ads @@ -58,6 +58,13 @@ package Warnsw is -- set with an explicit size clause. Off by default, modified by use of -- -gnatw.s/.S (but not -gnatwa). + Warn_On_Pedantic_Checks : Boolean := False; + -- Warn for violation of miscellaneous pedantic rules (such as when the + -- subtype of a formal parameter given in a subprogram body's specification + -- comes from a different subtype declaration that the subtype of the + -- formal in the subprogram declaration). Off by default, and set by + -- -gnatw_p (but not -gnatwa). + Warn_On_Questionable_Layout : Boolean := False; -- Warn when default layout of a record type is questionable for run-time -- efficiency reasons and would be improved by reordering the components. @@ -128,6 +135,7 @@ package Warnsw is Warn_On_Overlap : Boolean; Warn_On_Overridden_Size : Boolean; Warn_On_Parameter_Order : Boolean; + Warn_On_Pedantic_Checks : Boolean; Warn_On_Questionable_Layout : Boolean; Warn_On_Questionable_Missing_Parens : Boolean; Warn_On_Record_Holes : Boolean; diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index af9eba8..5625be7 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -2860,13 +2860,44 @@ c_omp_predefined_variable (tree decl) { if (VAR_P (decl) && DECL_ARTIFICIAL (decl) - && TREE_READONLY (decl) && TREE_STATIC (decl) - && DECL_NAME (decl) - && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME] - || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME] - || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME])) - return true; + && DECL_NAME (decl)) + { + if (TREE_READONLY (decl) + && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME] + || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME] + || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME])) + return true; + /* For UBSan handle the same also ubsan_create_data created + variables. There is no magic flag for those, but user variables + shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with + such names. */ + if ((flag_sanitize & (SANITIZE_UNDEFINED + | SANITIZE_UNDEFINED_NONDEFAULT)) != 0 + && DECL_IGNORED_P (decl) + && !TREE_READONLY (decl) + && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE + && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE + && TYPE_ARTIFICIAL (TREE_TYPE (decl)) + && TYPE_NAME (TREE_TYPE (decl)) + && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL + && DECL_NAME (TYPE_NAME (TREE_TYPE (decl))) + && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))) + == IDENTIFIER_NODE)) + { + tree id1 = DECL_NAME (decl); + tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl))); + if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1 + && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data") + && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_", + sizeof ("__ubsan_") - 1) + && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2) + - sizeof ("_data") + 1, "_data", + sizeof ("_data") - 1) + && strstr (IDENTIFIER_POINTER (id1), "ubsan_data")) + return true; + } + } return false; } diff --git a/gcc/calls.c b/gcc/calls.c index e50d3fc..27b59f2 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1287,8 +1287,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args_size->constant = 0; args_size->var = 0; - bitmap_obstack_initialize (NULL); - /* In this loop, we consider args in the order they are written. We fill up ARGS from the back. */ @@ -1297,7 +1295,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, int j = i; call_expr_arg_iterator iter; tree arg; - bitmap slots = NULL; if (struct_value_addr_value) { @@ -1324,13 +1321,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, j--; argpos++; } - - if (slots) - BITMAP_FREE (slots); } - bitmap_obstack_release (NULL); - /* I counts args in order (to be) pushed; ARGPOS counts in order written. */ for (argpos = 0; argpos < num_actuals; i--, argpos++) { @@ -1493,9 +1485,6 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, args[i].reg = targetm.calls.function_arg (args_so_far, arg); - if (args[i].reg && CONST_INT_P (args[i].reg)) - args[i].reg = NULL; - /* If this is a sibling call and the machine has register windows, the register window has to be unwinded before calling the routine, so arguments have to go into the incoming registers. */ diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 03260b0..8b067f9 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -6090,7 +6090,7 @@ expand_gimple_basic_block (basic_block bb, bool disable_tail_calls) /* Expand implicit goto and convert goto_locus. */ FOR_EACH_EDGE (e, ei, bb->succs) { - if (e->goto_locus != UNKNOWN_LOCATION || !stmt) + if (e->goto_locus != UNKNOWN_LOCATION || !stmt || is_gimple_debug (stmt)) set_curr_insn_location (e->goto_locus); if ((e->flags & EDGE_FALLTHRU) && e->dest != bb->next_bb) { diff --git a/gcc/config.gcc b/gcc/config.gcc index 3675e06..fb1f06f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -490,6 +490,7 @@ powerpc*-*-*) extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h" extra_headers="${extra_headers} mmintrin.h x86intrin.h" extra_headers="${extra_headers} pmmintrin.h tmmintrin.h smmintrin.h" + extra_headers="${extra_headers} nmmintrin.h" extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h" extra_headers="${extra_headers} amo.h" case x$with_cpu in diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 1a507ea..a815e4c 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -46,6 +46,7 @@ #include "emit-rtl.h" #include "stringpool.h" #include "attribs.h" +#include "gimple-fold.h" #define v8qi_UP E_V8QImode #define v4hi_UP E_V4HImode @@ -2399,11 +2400,65 @@ aarch64_general_fold_builtin (unsigned int fcode, tree type, return NULL_TREE; } +enum aarch64_simd_type +get_mem_type_for_load_store (unsigned int fcode) +{ + switch (fcode) + { + VAR1 (LOAD1, ld1 , 0, LOAD, v8qi) + VAR1 (STORE1, st1 , 0, STORE, v8qi) + return Int8x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v16qi) + VAR1 (STORE1, st1 , 0, STORE, v16qi) + return Int8x16_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4hi) + VAR1 (STORE1, st1 , 0, STORE, v4hi) + return Int16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8hi) + VAR1 (STORE1, st1 , 0, STORE, v8hi) + return Int16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2si) + VAR1 (STORE1, st1 , 0, STORE, v2si) + return Int32x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4si) + VAR1 (STORE1, st1 , 0, STORE, v4si) + return Int32x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2di) + VAR1 (STORE1, st1 , 0, STORE, v2di) + return Int64x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4hf) + VAR1 (STORE1, st1 , 0, STORE, v4hf) + return Float16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8hf) + VAR1 (STORE1, st1 , 0, STORE, v8hf) + return Float16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4bf) + VAR1 (STORE1, st1 , 0, STORE, v4bf) + return Bfloat16x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v8bf) + VAR1 (STORE1, st1 , 0, STORE, v8bf) + return Bfloat16x8_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2sf) + VAR1 (STORE1, st1 , 0, STORE, v2sf) + return Float32x2_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v4sf) + VAR1 (STORE1, st1 , 0, STORE, v4sf) + return Float32x4_t; + VAR1 (LOAD1, ld1 , 0, LOAD, v2df) + VAR1 (STORE1, st1 , 0, STORE, v2df) + return Float64x2_t; + default: + gcc_unreachable (); + break; + } +} + /* Try to fold STMT, given that it's a call to the built-in function with subcode FCODE. Return the new statement on success and null on failure. */ gimple * -aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt) +aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt, + gimple_stmt_iterator *gsi) { gimple *new_stmt = NULL; unsigned nargs = gimple_call_num_args (stmt); @@ -2421,6 +2476,52 @@ aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt) 1, args[0]); gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); break; + + /*lower store and load neon builtins to gimple. */ + BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD) + if (!BYTES_BIG_ENDIAN) + { + enum aarch64_simd_type mem_type + = get_mem_type_for_load_store(fcode); + aarch64_simd_type_info simd_type + = aarch64_simd_types[mem_type]; + tree elt_ptr_type = build_pointer_type (simd_type.eltype); + tree zero = build_zero_cst (elt_ptr_type); + gimple_seq stmts = NULL; + tree base = gimple_convert (&stmts, elt_ptr_type, + args[0]); + if (stmts) + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + new_stmt + = gimple_build_assign (gimple_get_lhs (stmt), + fold_build2 (MEM_REF, + simd_type.itype, + base, zero)); + } + break; + + BUILTIN_VALL_F16 (STORE1, st1, 0, STORE) + if (!BYTES_BIG_ENDIAN) + { + enum aarch64_simd_type mem_type + = get_mem_type_for_load_store(fcode); + aarch64_simd_type_info simd_type + = aarch64_simd_types[mem_type]; + tree elt_ptr_type = build_pointer_type (simd_type.eltype); + tree zero = build_zero_cst (elt_ptr_type); + gimple_seq stmts = NULL; + tree base = gimple_convert (&stmts, elt_ptr_type, + args[0]); + if (stmts) + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + new_stmt + = gimple_build_assign (fold_build2 (MEM_REF, + simd_type.itype, + base, + zero), args[1]); + } + break; + BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10, ALL) BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10, ALL) new_stmt = gimple_build_call_internal (IFN_REDUC_MAX, diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index b91eeeb..768e8fa 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -962,7 +962,8 @@ void aarch64_override_options_internal (struct gcc_options *); const char *aarch64_general_mangle_builtin_type (const_tree); void aarch64_general_init_builtins (void); tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *); -gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *); +gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *, + gimple_stmt_iterator *); rtx aarch64_general_expand_builtin (unsigned int, tree, rtx, int); tree aarch64_general_builtin_decl (unsigned, bool); tree aarch64_general_builtin_rsqrt (unsigned int); diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def index 35dc075..be1c5b5 100644 --- a/gcc/config/aarch64/aarch64-simd-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-builtins.def @@ -506,7 +506,7 @@ BUILTIN_VHSDF (UNOP, nearbyint, 2, FP) BUILTIN_VHSDF (UNOP, rint, 2, FP) BUILTIN_VHSDF (UNOP, round, 2, FP) - BUILTIN_VHSDF_HSDF (UNOP, frintn, 2, FP) + BUILTIN_VHSDF_HSDF (UNOP, roundeven, 2, FP) VAR1 (UNOP, btrunc, 2, FP, hf) VAR1 (UNOP, ceil, 2, FP, hf) diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 48eddf6..29f3817 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -1127,12 +1127,14 @@ ) (define_insn "aarch64_simd_ashr<mode>" - [(set (match_operand:VDQ_I 0 "register_operand" "=w") - (ashiftrt:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w") - (match_operand:VDQ_I 2 "aarch64_simd_rshift_imm" "Dr")))] + [(set (match_operand:VDQ_I 0 "register_operand" "=w,w") + (ashiftrt:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,w") + (match_operand:VDQ_I 2 "aarch64_simd_rshift_imm" "D1,Dr")))] "TARGET_SIMD" - "sshr\t%0.<Vtype>, %1.<Vtype>, %2" - [(set_attr "type" "neon_shift_imm<q>")] + "@ + cmlt\t%0.<Vtype>, %1.<Vtype>, #0 + sshr\t%0.<Vtype>, %1.<Vtype>, %2" + [(set_attr "type" "neon_compare<q>,neon_shift_imm<q>")] ) (define_insn "*aarch64_simd_sra<mode>" @@ -1751,6 +1753,23 @@ } ) +(define_insn "*aarch64_narrow_trunc<mode>" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (match_operand:VQN 1 "register_operand" "w")) + (truncate:<VNARROWQ> + (match_operand:VQN 2 "register_operand" "w"))))] + "TARGET_SIMD" +{ + if (!BYTES_BIG_ENDIAN) + return "uzp1\\t%0.<V2ntype>, %1.<V2ntype>, %2.<V2ntype>"; + else + return "uzp1\\t%0.<V2ntype>, %2.<V2ntype>, %1.<V2ntype>"; +} + [(set_attr "type" "neon_permute<q>")] +) + ;; Packing doubles. (define_expand "vec_pack_trunc_<mode>" @@ -1818,6 +1837,100 @@ [(set_attr "type" "neon_shift_imm_narrow_q")] ) +(define_insn "*aarch64_<srn_op>shrn<mode>_vect" + [(set (match_operand:<VNARROWQ> 0 "register_operand" "=w") + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_<vn_mode>"))))] + "TARGET_SIMD" + "shrn\\t%0.<Vntype>, %1.<Vtype>, %2" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>shrn<mode>2_vect_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (match_operand:<VNARROWQ> 1 "register_operand" "0") + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 2 "register_operand" "w") + (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>")))))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>shrn<mode>2_vect_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 2 "register_operand" "w") + (match_operand:VQN 3 "aarch64_simd_shift_imm_vec_<vn_mode>"))) + (match_operand:<VNARROWQ> 1 "register_operand" "0")))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "shrn2\\t%0.<V2ntype>, %2.<Vtype>, %3" + [(set_attr "type" "neon_shift_imm_narrow_q")] +) + +(define_insn "*aarch64_<srn_op>topbits_shuffle<mode>_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top"))) + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 3 "register_operand" "w") + (match_dup 2)))))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_topbits_shuffle<mode>_le" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (unspec:<VNARROWQ> [ + (match_operand:VQN 1 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top") + ] UNSPEC_RSHRN) + (unspec:<VNARROWQ> [ + (match_operand:VQN 3 "register_operand" "w") + (match_dup 2) + ] UNSPEC_RSHRN)))] + "TARGET_SIMD && !BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_<srn_op>topbits_shuffle<mode>_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 3 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top"))) + (truncate:<VNARROWQ> + (SHIFTRT:VQN (match_operand:VQN 1 "register_operand" "w") + (match_dup 2)))))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + +(define_insn "*aarch64_topbits_shuffle<mode>_be" + [(set (match_operand:<VNARROWQ2> 0 "register_operand" "=w") + (vec_concat:<VNARROWQ2> + (unspec:<VNARROWQ> [ + (match_operand:VQN 3 "register_operand" "w") + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top") + ] UNSPEC_RSHRN) + (unspec:<VNARROWQ> [ + (match_operand:VQN 1 "register_operand" "w") + (match_dup 2) + ] UNSPEC_RSHRN)))] + "TARGET_SIMD && BYTES_BIG_ENDIAN" + "uzp2\\t%0.<V2ntype>, %1.<V2ntype>, %3.<V2ntype>" + [(set_attr "type" "neon_permute<q>")] +) + (define_expand "aarch64_shrn<mode>" [(set (match_operand:<VNARROWQ> 0 "register_operand") (truncate:<VNARROWQ> @@ -6507,6 +6620,23 @@ [(set_attr "type" "neon_tst<q>")] ) +;; One can also get a cmtsts by having to combine a +;; not (neq (eq x 0)) in which case you rewrite it to +;; a comparison against itself + +(define_insn "*aarch64_cmtst_same_<mode>" + [(set (match_operand:<V_INT_EQUIV> 0 "register_operand" "=w") + (plus:<V_INT_EQUIV> + (eq:<V_INT_EQUIV> + (match_operand:VDQ_I 1 "register_operand" "w") + (match_operand:VDQ_I 2 "aarch64_simd_imm_zero")) + (match_operand:<V_INT_EQUIV> 3 "aarch64_simd_imm_minus_one"))) + ] + "TARGET_SIMD" + "cmtst\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>1<Vmtype>" + [(set_attr "type" "neon_tst<q>")] +) + (define_insn_and_split "aarch64_cmtstdi" [(set (match_operand:DI 0 "register_operand" "=w,r") (neg:DI diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 76d99d2..699c105 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -1839,7 +1839,8 @@ static const struct tune_params neoversev1_tunings = tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT + | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ &generic_prefetch_tune }; @@ -1995,7 +1996,7 @@ static const struct tune_params neoversen2_tunings = 2, /* min_div_recip_mul_df. */ 0, /* max_case_values. */ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ &generic_prefetch_tune }; @@ -9499,8 +9500,8 @@ aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) The expansion for a table switch is quite expensive due to the number of instructions, the table lookup and hard to predict indirect jump. When optimizing for speed, and -O3 enabled, use the per-core tuning if - set, otherwise use tables for > 16 cases as a tradeoff between size and - performance. When optimizing for size, use the default setting. */ + set, otherwise use tables for >= 11 cases as a tradeoff between size and + performance. When optimizing for size, use 8 for smallest codesize. */ static unsigned int aarch64_case_values_threshold (void) @@ -9511,7 +9512,7 @@ aarch64_case_values_threshold (void) && selected_cpu->tune->max_case_values != 0) return selected_cpu->tune->max_case_values; else - return optimize_size ? default_case_values_threshold () : 17; + return optimize_size ? 8 : 11; } /* Return true if register REGNO is a valid index register. @@ -14156,7 +14157,7 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi) switch (code & AARCH64_BUILTIN_CLASS) { case AARCH64_BUILTIN_GENERAL: - new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt); + new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt, gsi); break; case AARCH64_BUILTIN_SVE: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 7085cd4..1a39470 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -5920,7 +5920,7 @@ ;; ------------------------------------------------------------------- ;; frint floating-point round to integral standard patterns. -;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn. +;; Expands to btrunc, ceil, floor, nearbyint, rint, round, roundeven. (define_insn "<frint_pattern><mode>2" [(set (match_operand:GPF_F16 0 "register_operand" "=w") diff --git a/gcc/config/aarch64/arm_fp16.h b/gcc/config/aarch64/arm_fp16.h index 2633953..c223546 100644 --- a/gcc/config/aarch64/arm_fp16.h +++ b/gcc/config/aarch64/arm_fp16.h @@ -383,7 +383,7 @@ __extension__ extern __inline float16_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnh_f16 (float16_t __a) { - return __builtin_aarch64_frintnhf (__a); + return __builtin_aarch64_roundevenhf (__a); } __extension__ extern __inline float16_t diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index 24068f8..1768c6b 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -26359,35 +26359,35 @@ __extension__ extern __inline float32_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndns_f32 (float32_t __a) { - return __builtin_aarch64_frintnsf (__a); + return __builtin_aarch64_roundevensf (__a); } __extension__ extern __inline float32x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f32 (float32x2_t __a) { - return __builtin_aarch64_frintnv2sf (__a); + return __builtin_aarch64_roundevenv2sf (__a); } __extension__ extern __inline float64x1_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f64 (float64x1_t __a) { - return (float64x1_t) {__builtin_aarch64_frintndf (__a[0])}; + return (float64x1_t) {__builtin_aarch64_roundevendf (__a[0])}; } __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f32 (float32x4_t __a) { - return __builtin_aarch64_frintnv4sf (__a); + return __builtin_aarch64_roundevenv4sf (__a); } __extension__ extern __inline float64x2_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f64 (float64x2_t __a) { - return __builtin_aarch64_frintnv2df (__a); + return __builtin_aarch64_roundevenv2df (__a); } /* vrndp */ @@ -32792,14 +32792,14 @@ __extension__ extern __inline float16x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndn_f16 (float16x4_t __a) { - return __builtin_aarch64_frintnv4hf (__a); + return __builtin_aarch64_roundevenv4hf (__a); } __extension__ extern __inline float16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) vrndnq_f16 (float16x8_t __a) { - return __builtin_aarch64_frintnv8hf (__a); + return __builtin_aarch64_roundevenv8hf (__a); } __extension__ extern __inline float16x4_t diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 3b49b45..1863081 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -437,6 +437,14 @@ (match_test "aarch64_simd_shift_imm_p (op, GET_MODE (op), true)"))) +(define_constraint "D1" + "@internal + A constraint that matches vector of immediates that is bits(mode)-1." + (and (match_code "const,const_vector") + (match_test "aarch64_const_vec_all_same_in_range_p (op, + GET_MODE_UNIT_BITSIZE (mode) - 1, + GET_MODE_UNIT_BITSIZE (mode) - 1)"))) + (define_constraint "Dr" "@internal A constraint that matches vector of immediates for right shifts." diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index caa42f8..aee32dc 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -2003,6 +2003,9 @@ ;; Op prefix for shift right and accumulate. (define_code_attr sra_op [(ashiftrt "s") (lshiftrt "u")]) +;; op prefix for shift right and narrow. +(define_code_attr srn_op [(ashiftrt "r") (lshiftrt "")]) + ;; Map shift operators onto underlying bit-field instructions (define_code_attr bfshift [(ashift "ubfiz") (ashiftrt "sbfx") (lshiftrt "ubfx") (rotatert "extr")]) @@ -3084,7 +3087,7 @@ (UNSPEC_FRINTI "nearbyint") (UNSPEC_FRINTX "rint") (UNSPEC_FRINTA "round") - (UNSPEC_FRINTN "frintn")]) + (UNSPEC_FRINTN "roundeven")]) ;; frint suffix for floating-point rounding instructions. (define_int_attr frint_suffix [(UNSPEC_FRINTZ "z") (UNSPEC_FRINTP "p") diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 49f02ae..7fd4f9e 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -545,6 +545,12 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 1, 64)"))) +(define_predicate "aarch64_simd_shift_imm_vec_exact_top" + (and (match_code "const_vector") + (match_test "aarch64_const_vec_all_same_in_range_p (op, + GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2, + GET_MODE_UNIT_BITSIZE (GET_MODE (op)) / 2)"))) + (define_predicate "aarch64_simd_shift_imm_vec_qi" (and (match_code "const_vector") (match_test "aarch64_const_vec_all_same_in_range_p (op, 1, 8)"))) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index e51f60a..c4ff06b 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -838,8 +838,6 @@ static char * minipool_startobj; will be conditionalised if possible. */ static int max_insns_skipped = 5; -extern FILE * asm_out_file; - /* True if we are currently building a constant table. */ int making_const_table; @@ -29408,7 +29406,7 @@ arm_dwarf_register_span (rtx rtl) epilogue. */ static void -arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) +arm_unwind_emit_sequence (FILE * out_file, rtx p) { int i; HOST_WIDE_INT offset; @@ -29452,14 +29450,14 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) padlast = offset - 4; gcc_assert (padlast == 0 || padlast == 4); if (padlast == 4) - fprintf (asm_out_file, "\t.pad #4\n"); + fprintf (out_file, "\t.pad #4\n"); reg_size = 4; - fprintf (asm_out_file, "\t.save {"); + fprintf (out_file, "\t.save {"); } else if (IS_VFP_REGNUM (reg)) { reg_size = 8; - fprintf (asm_out_file, "\t.vsave {"); + fprintf (out_file, "\t.vsave {"); } else /* Unknown register type. */ @@ -29485,13 +29483,13 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) gcc_assert (reg >= lastreg); if (i != 1) - fprintf (asm_out_file, ", "); + fprintf (out_file, ", "); /* We can't use %r for vfp because we need to use the double precision register names. */ if (IS_VFP_REGNUM (reg)) - asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); + asm_fprintf (out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2); else - asm_fprintf (asm_out_file, "%r", reg); + asm_fprintf (out_file, "%r", reg); if (flag_checking) { @@ -29509,15 +29507,15 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) offset += reg_size; } } - fprintf (asm_out_file, "}\n"); + fprintf (out_file, "}\n"); if (padfirst) - fprintf (asm_out_file, "\t.pad #%d\n", padfirst); + fprintf (out_file, "\t.pad #%d\n", padfirst); } /* Emit unwind directives for a SET. */ static void -arm_unwind_emit_set (FILE * asm_out_file, rtx p) +arm_unwind_emit_set (FILE * out_file, rtx p) { rtx e0; rtx e1; @@ -29534,12 +29532,12 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM) abort (); - asm_fprintf (asm_out_file, "\t.save "); + asm_fprintf (out_file, "\t.save "); if (IS_VFP_REGNUM (REGNO (e1))) - asm_fprintf(asm_out_file, "{d%d}\n", + asm_fprintf(out_file, "{d%d}\n", (REGNO (e1) - FIRST_VFP_REGNUM) / 2); else - asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1)); + asm_fprintf(out_file, "{%r}\n", REGNO (e1)); break; case REG: @@ -29552,7 +29550,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) || !CONST_INT_P (XEXP (e1, 1))) abort (); - asm_fprintf (asm_out_file, "\t.pad #%wd\n", + asm_fprintf (out_file, "\t.pad #%wd\n", -INTVAL (XEXP (e1, 1))); } else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM) @@ -29566,14 +29564,14 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) abort (); reg = REGNO (XEXP (e1, 0)); offset = INTVAL (XEXP (e1, 1)); - asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%wd\n", + asm_fprintf (out_file, "\t.setfp %r, %r, #%wd\n", HARD_FRAME_POINTER_REGNUM, reg, offset); } else if (REG_P (e1)) { reg = REGNO (e1); - asm_fprintf (asm_out_file, "\t.setfp %r, %r\n", + asm_fprintf (out_file, "\t.setfp %r, %r\n", HARD_FRAME_POINTER_REGNUM, reg); } else @@ -29582,7 +29580,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) else if (REG_P (e1) && REGNO (e1) == SP_REGNUM) { /* Move from sp to reg. */ - asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0)); + asm_fprintf (out_file, "\t.movsp %r\n", REGNO (e0)); } else if (GET_CODE (e1) == PLUS && REG_P (XEXP (e1, 0)) @@ -29590,7 +29588,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) && CONST_INT_P (XEXP (e1, 1))) { /* Set reg to offset from sp. */ - asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n", + asm_fprintf (out_file, "\t.movsp %r, #%d\n", REGNO (e0), (int)INTVAL(XEXP (e1, 1))); } else @@ -29606,7 +29604,7 @@ arm_unwind_emit_set (FILE * asm_out_file, rtx p) /* Emit unwind directives for the given insn. */ static void -arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) +arm_unwind_emit (FILE * out_file, rtx_insn *insn) { rtx note, pat; bool handled_one = false; @@ -29649,7 +29647,7 @@ arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) gcc_assert (src == stack_pointer_rtx); reg = REGNO (dest); - asm_fprintf (asm_out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", + asm_fprintf (out_file, "\t.unwind_raw 0, 0x%x @ vsp = r%d\n", reg + 0x90, reg); } handled_one = true; @@ -29682,12 +29680,12 @@ arm_unwind_emit (FILE * asm_out_file, rtx_insn *insn) switch (GET_CODE (pat)) { case SET: - arm_unwind_emit_set (asm_out_file, pat); + arm_unwind_emit_set (out_file, pat); break; case SEQUENCE: /* Store multiple. */ - arm_unwind_emit_sequence (asm_out_file, pat); + arm_unwind_emit_sequence (out_file, pat); break; default: diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 8b311f3..fd65f4d 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -3018,19 +3018,6 @@ (define_insn "addsubv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI - (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] - "" - "%0 = %1 +|- %2%!" - [(set_attr "type" "dsp32")]) - -(define_insn "subaddv2hi3" - [(set (match_operand:V2HI 0 "register_operand" "=d") - (vec_concat:V2HI (minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") (parallel [(const_int 0)])) (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") @@ -3038,23 +3025,23 @@ (plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" - "%0 = %1 -|+ %2%!" + "%0 = %1 +|- %2%!" [(set_attr "type" "dsp32")]) -(define_insn "ssaddsubv2hi3" +(define_insn "subaddv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI - (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") - (parallel [(const_int 0)])) - (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") - (parallel [(const_int 0)]))) - (ss_minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) - (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] + (plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") + (parallel [(const_int 0)])) + (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") + (parallel [(const_int 0)]))) + (minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) + (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" - "%0 = %1 +|- %2 (S)%!" + "%0 = %1 -|+ %2%!" [(set_attr "type" "dsp32")]) -(define_insn "sssubaddv2hi3" +(define_insn "ssaddsubv2hi3" [(set (match_operand:V2HI 0 "register_operand" "=d") (vec_concat:V2HI (ss_minus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") @@ -3064,6 +3051,19 @@ (ss_plus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] "" + "%0 = %1 +|- %2 (S)%!" + [(set_attr "type" "dsp32")]) + +(define_insn "sssubaddv2hi3" + [(set (match_operand:V2HI 0 "register_operand" "=d") + (vec_concat:V2HI + (ss_plus:HI (vec_select:HI (match_operand:V2HI 1 "register_operand" "d") + (parallel [(const_int 0)])) + (vec_select:HI (match_operand:V2HI 2 "register_operand" "d") + (parallel [(const_int 0)]))) + (ss_minus:HI (vec_select:HI (match_dup 1) (parallel [(const_int 1)])) + (vec_select:HI (match_dup 2) (parallel [(const_int 1)])))))] + "" "%0 = %1 -|+ %2 (S)%!" [(set_attr "type" "dsp32")]) diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 28dc55d..204114c 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -1059,7 +1059,7 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg) int machopic_output_data_section_indirection (machopic_indirection **slot, - FILE *asm_out_file) + FILE *out_file) { machopic_indirection *p = *slot; @@ -1074,7 +1074,7 @@ machopic_output_data_section_indirection (machopic_indirection **slot, switch_to_section (data_section); assemble_align (GET_MODE_ALIGNMENT (Pmode)); - assemble_label (asm_out_file, ptr_name); + assemble_label (out_file, ptr_name); assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name), GET_MODE_SIZE (Pmode), GET_MODE_ALIGNMENT (Pmode), 1); @@ -1084,7 +1084,7 @@ machopic_output_data_section_indirection (machopic_indirection **slot, int machopic_output_stub_indirection (machopic_indirection **slot, - FILE *asm_out_file) + FILE *out_file) { machopic_indirection *p = *slot; @@ -1122,13 +1122,13 @@ machopic_output_stub_indirection (machopic_indirection **slot, else sprintf (stub, "%s%s", user_label_prefix, ptr_name); - machopic_output_stub (asm_out_file, sym, stub); + machopic_output_stub (out_file, sym, stub); return 1; } int -machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) +machopic_output_indirection (machopic_indirection **slot, FILE *out_file) { machopic_indirection *p = *slot; @@ -1160,18 +1160,18 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) storage has been allocated. */ && !TREE_STATIC (decl)) { - fputs ("\t.weak_reference ", asm_out_file); - assemble_name (asm_out_file, sym_name); - fputc ('\n', asm_out_file); + fputs ("\t.weak_reference ", out_file); + assemble_name (out_file, sym_name); + fputc ('\n', out_file); } } - assemble_name (asm_out_file, ptr_name); - fprintf (asm_out_file, ":\n"); + assemble_name (out_file, ptr_name); + fprintf (out_file, ":\n"); - fprintf (asm_out_file, "\t.indirect_symbol "); - assemble_name (asm_out_file, sym_name); - fprintf (asm_out_file, "\n"); + fprintf (out_file, "\t.indirect_symbol "); + assemble_name (out_file, sym_name); + fprintf (out_file, "\n"); /* Variables that are marked with MACHO_SYMBOL_FLAG_STATIC need to have their symbol name instead of 0 in the second entry of @@ -1191,7 +1191,7 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file) } static void -machopic_finish (FILE *asm_out_file) +machopic_finish (FILE *out_file) { if (!machopic_indirections) return; @@ -1199,13 +1199,13 @@ machopic_finish (FILE *asm_out_file) /* First output an symbol indirections that have been placed into .data (we don't expect these now). */ machopic_indirections->traverse_noresize - <FILE *, machopic_output_data_section_indirection> (asm_out_file); + <FILE *, machopic_output_data_section_indirection> (out_file); machopic_indirections->traverse_noresize - <FILE *, machopic_output_stub_indirection> (asm_out_file); + <FILE *, machopic_output_stub_indirection> (out_file); machopic_indirections->traverse_noresize - <FILE *, machopic_output_indirection> (asm_out_file); + <FILE *, machopic_output_indirection> (out_file); } int diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h index 5e49447..44c5e24 100644 --- a/gcc/config/i386/avx512fp16intrin.h +++ b/gcc/config/i386/avx512fp16intrin.h @@ -7149,6 +7149,19 @@ _mm512_permutexvar_ph (__m512i __A, __m512h __B) (__mmask32)-1); } +extern __inline __m512h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm512_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A}; + + return (__m512h) _mm512_set1_ps (u.b); +} + #ifdef __DISABLE_AVX512FP16__ #undef __DISABLE_AVX512FP16__ #pragma GCC pop_options diff --git a/gcc/config/i386/avx512fp16vlintrin.h b/gcc/config/i386/avx512fp16vlintrin.h index 0b1f1cb..11f34bb 100644 --- a/gcc/config/i386/avx512fp16vlintrin.h +++ b/gcc/config/i386/avx512fp16vlintrin.h @@ -3311,6 +3311,32 @@ _mm_permutexvar_ph (__m128i __A, __m128h __B) (__mmask8)-1); } +extern __inline __m256h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm256_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A }; + + return (__m256h) _mm256_set1_ps (u.b); +} + +extern __inline __m128h +__attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) +_mm_set1_pch (_Float16 _Complex __A) +{ + union + { + _Float16 _Complex a; + float b; + } u = { .a = __A }; + + return (__m128h) _mm_set1_ps (u.b); +} + #ifdef __DISABLE_AVX512FP16VL__ #undef __DISABLE_AVX512FP16VL__ #pragma GCC pop_options diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3c3336d..299e1ab 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1567,7 +1567,7 @@ ix86_function_naked (const_tree fn) /* Write the extra assembler code needed to declare a function properly. */ void -ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, +ix86_asm_output_function_label (FILE *out_file, const char *fname, tree decl) { bool is_ms_hook = ix86_function_ms_hook_prologue (decl); @@ -1581,14 +1581,14 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, unsigned int filler_cc = 0xcccccccc; for (i = 0; i < filler_count; i += 4) - fprintf (asm_out_file, ASM_LONG " %#x\n", filler_cc); + fprintf (out_file, ASM_LONG " %#x\n", filler_cc); } #ifdef SUBTARGET_ASM_UNWIND_INIT - SUBTARGET_ASM_UNWIND_INIT (asm_out_file); + SUBTARGET_ASM_UNWIND_INIT (out_file); #endif - ASM_OUTPUT_LABEL (asm_out_file, fname); + ASM_OUTPUT_LABEL (out_file, fname); /* Output magic byte marker, if hot-patch attribute is set. */ if (is_ms_hook) @@ -1597,14 +1597,14 @@ ix86_asm_output_function_label (FILE *asm_out_file, const char *fname, { /* leaq [%rsp + 0], %rsp */ fputs (ASM_BYTE "0x48, 0x8d, 0xa4, 0x24, 0x00, 0x00, 0x00, 0x00\n", - asm_out_file); + out_file); } else { /* movl.s %edi, %edi push %ebp movl.s %esp, %ebp */ - fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", asm_out_file); + fputs (ASM_BYTE "0x8b, 0xff, 0x55, 0x8b, 0xec\n", out_file); } } } @@ -5399,9 +5399,18 @@ ix86_get_ssemov (rtx *operands, unsigned size, switch (scalar_mode) { case E_HFmode: - opcode = (misaligned_p - ? (TARGET_AVX512BW ? "vmovdqu16" : "vmovdqu64") - : "vmovdqa64"); + if (evex_reg_p) + opcode = (misaligned_p + ? (TARGET_AVX512BW + ? "vmovdqu16" + : "vmovdqu64") + : "vmovdqa64"); + else + opcode = (misaligned_p + ? (TARGET_AVX512BW + ? "vmovdqu16" + : "%vmovdqu") + : "%vmovdqa"); break; case E_SFmode: opcode = misaligned_p ? "%vmovups" : "%vmovaps"; @@ -13921,7 +13930,10 @@ ix86_print_operand_address_as (FILE *file, rtx addr, static void ix86_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr) { - ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC, false); + if (this_is_asm_operands && ! address_operand (addr, VOIDmode)) + output_operand_lossage ("invalid constraints for operand"); + else + ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC, false); } /* Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 4158a45..7c0ea4f 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -1231,7 +1231,7 @@ seh_frame_related_expr (FILE *f, struct seh_frame_state *seh, rtx pat) required for unwind of this insn. */ void -i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) +i386_pe_seh_unwind_emit (FILE *out_file, rtx_insn *insn) { rtx note, pat; bool handled_one = false; @@ -1246,8 +1246,8 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) /* See ix86_seh_fixup_eh_fallthru for the rationale. */ rtx_insn *prev = prev_active_insn (insn); if (prev && !insn_nothrow_p (prev)) - fputs ("\tnop\n", asm_out_file); - fputs ("\t.seh_endproc\n", asm_out_file); + fputs ("\tnop\n", out_file); + fputs ("\t.seh_endproc\n", out_file); seh->in_cold_section = true; return; } @@ -1286,7 +1286,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) if (GET_CODE (pat) == PARALLEL) pat = XVECEXP (pat, 0, 0); } - seh_cfa_adjust_cfa (asm_out_file, seh, pat); + seh_cfa_adjust_cfa (out_file, seh, pat); handled_one = true; break; @@ -1294,7 +1294,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = single_set (insn); - seh_cfa_offset (asm_out_file, seh, pat); + seh_cfa_offset (out_file, seh, pat); handled_one = true; break; @@ -1306,7 +1306,7 @@ i386_pe_seh_unwind_emit (FILE *asm_out_file, rtx_insn *insn) return; pat = PATTERN (insn); found: - seh_frame_related_expr (asm_out_file, seh, pat); + seh_frame_related_expr (out_file, seh, pat); } void diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 39a0e07..96c0efb 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -10044,7 +10044,7 @@ static bool need_copy_state; /* The function emits unwind directives for the start of an epilogue. */ static void -process_epilogue (FILE *asm_out_file, rtx insn ATTRIBUTE_UNUSED, +process_epilogue (FILE *out_file, rtx insn ATTRIBUTE_UNUSED, bool unwind, bool frame ATTRIBUTE_UNUSED) { /* If this isn't the last block of the function, then we need to label the @@ -10053,19 +10053,19 @@ process_epilogue (FILE *asm_out_file, rtx insn ATTRIBUTE_UNUSED, if (!last_block) { if (unwind) - fprintf (asm_out_file, "\t.label_state %d\n", + fprintf (out_file, "\t.label_state %d\n", ++cfun->machine->state_num); need_copy_state = true; } if (unwind) - fprintf (asm_out_file, "\t.restore sp\n"); + fprintf (out_file, "\t.restore sp\n"); } /* This function processes a SET pattern for REG_CFA_ADJUST_CFA. */ static void -process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, +process_cfa_adjust_cfa (FILE *out_file, rtx pat, rtx insn, bool unwind, bool frame) { rtx dest = SET_DEST (pat); @@ -10084,17 +10084,17 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, { gcc_assert (!frame_pointer_needed); if (unwind) - fprintf (asm_out_file, + fprintf (out_file, "\t.fframe " HOST_WIDE_INT_PRINT_DEC"\n", -INTVAL (op1)); } else - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); } else { gcc_assert (src == hard_frame_pointer_rtx); - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); } } else if (dest == hard_frame_pointer_rtx) @@ -10103,7 +10103,7 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, gcc_assert (frame_pointer_needed); if (unwind) - fprintf (asm_out_file, "\t.vframe r%d\n", + fprintf (out_file, "\t.vframe r%d\n", ia64_dbx_register_number (REGNO (dest))); } else @@ -10113,7 +10113,7 @@ process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, /* This function processes a SET pattern for REG_CFA_REGISTER. */ static void -process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) +process_cfa_register (FILE *out_file, rtx pat, bool unwind) { rtx dest = SET_DEST (pat); rtx src = SET_SRC (pat); @@ -10124,7 +10124,7 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) { /* Saving return address pointer. */ if (unwind) - fprintf (asm_out_file, "\t.save rp, r%d\n", + fprintf (out_file, "\t.save rp, r%d\n", ia64_dbx_register_number (dest_regno)); return; } @@ -10136,21 +10136,21 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) case PR_REG (0): gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); if (unwind) - fprintf (asm_out_file, "\t.save pr, r%d\n", + fprintf (out_file, "\t.save pr, r%d\n", ia64_dbx_register_number (dest_regno)); break; case AR_UNAT_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); if (unwind) - fprintf (asm_out_file, "\t.save ar.unat, r%d\n", + fprintf (out_file, "\t.save ar.unat, r%d\n", ia64_dbx_register_number (dest_regno)); break; case AR_LC_REGNUM: gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); if (unwind) - fprintf (asm_out_file, "\t.save ar.lc, r%d\n", + fprintf (out_file, "\t.save ar.lc, r%d\n", ia64_dbx_register_number (dest_regno)); break; @@ -10163,7 +10163,7 @@ process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) /* This function processes a SET pattern for REG_CFA_OFFSET. */ static void -process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) +process_cfa_offset (FILE *out_file, rtx pat, bool unwind) { rtx dest = SET_DEST (pat); rtx src = SET_SRC (pat); @@ -10203,35 +10203,35 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case BR_REG (0): gcc_assert (!current_frame_info.r[reg_save_b0]); if (unwind) - fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case PR_REG (0): gcc_assert (!current_frame_info.r[reg_save_pr]); if (unwind) - fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_LC_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_lc]); if (unwind) - fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_PFS_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); if (unwind) - fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; case AR_UNAT_REGNUM: gcc_assert (!current_frame_info.r[reg_save_ar_unat]); if (unwind) - fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", + fprintf (out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", saveop, off); break; @@ -10240,7 +10240,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case GR_REG (6): case GR_REG (7): if (unwind) - fprintf (asm_out_file, "\t.save.g 0x%x\n", + fprintf (out_file, "\t.save.g 0x%x\n", 1 << (src_regno - GR_REG (4))); break; @@ -10250,7 +10250,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case BR_REG (4): case BR_REG (5): if (unwind) - fprintf (asm_out_file, "\t.save.b 0x%x\n", + fprintf (out_file, "\t.save.b 0x%x\n", 1 << (src_regno - BR_REG (1))); break; @@ -10259,7 +10259,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case FR_REG (4): case FR_REG (5): if (unwind) - fprintf (asm_out_file, "\t.save.f 0x%x\n", + fprintf (out_file, "\t.save.f 0x%x\n", 1 << (src_regno - FR_REG (2))); break; @@ -10268,7 +10268,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): if (unwind) - fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", + fprintf (out_file, "\t.save.gf 0x0, 0x%x\n", 1 << (src_regno - FR_REG (12))); break; @@ -10283,7 +10283,7 @@ process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) required to unwind this insn. */ static void -ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) +ia64_asm_unwind_emit (FILE *out_file, rtx_insn *insn) { bool unwind = ia64_except_unwind_info (&global_options) == UI_TARGET; bool frame = dwarf2out_do_frame (); @@ -10303,8 +10303,8 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) { if (unwind) { - fprintf (asm_out_file, "\t.body\n"); - fprintf (asm_out_file, "\t.copy_state %d\n", + fprintf (out_file, "\t.body\n"); + fprintf (out_file, "\t.copy_state %d\n", cfun->machine->state_num); } need_copy_state = false; @@ -10325,7 +10325,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) { if (unwind) - fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", + fprintf (out_file, "\t.save ar.pfs, r%d\n", ia64_dbx_register_number (dest_regno)); } else @@ -10338,9 +10338,9 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) sp" now. */ if (current_frame_info.total_size == 0 && !frame_pointer_needed) /* if haven't done process_epilogue() yet, do it now */ - process_epilogue (asm_out_file, insn, unwind, frame); + process_epilogue (out_file, insn, unwind, frame); if (unwind) - fprintf (asm_out_file, "\t.prologue\n"); + fprintf (out_file, "\t.prologue\n"); } return; } @@ -10353,7 +10353,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame); + process_cfa_adjust_cfa (out_file, pat, insn, unwind, frame); handled_one = true; break; @@ -10361,7 +10361,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_offset (asm_out_file, pat, unwind); + process_cfa_offset (out_file, pat, unwind); handled_one = true; break; @@ -10369,7 +10369,7 @@ ia64_asm_unwind_emit (FILE *asm_out_file, rtx_insn *insn) pat = XEXP (note, 0); if (pat == NULL) pat = PATTERN (insn); - process_cfa_register (asm_out_file, pat, unwind); + process_cfa_register (out_file, pat, unwind); handled_one = true; break; diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 93d23715..51a4760 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -145,8 +145,6 @@ UNSPEC_VUPKHU_V4SF UNSPEC_VUPKLU_V4SF UNSPEC_VGBBD - UNSPEC_VMRGH_DIRECT - UNSPEC_VMRGL_DIRECT UNSPEC_VSPLT_DIRECT UNSPEC_VMRGEW_DIRECT UNSPEC_VMRGOW_DIRECT @@ -1101,19 +1099,17 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (16, GEN_INT (0), GEN_INT (16), GEN_INT (1), GEN_INT (17), - GEN_INT (2), GEN_INT (18), GEN_INT (3), GEN_INT (19), - GEN_INT (4), GEN_INT (20), GEN_INT (5), GEN_INT (21), - GEN_INT (6), GEN_INT (22), GEN_INT (7), GEN_INT (23)); - rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghb_direct + : gen_altivec_vmrglb_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghb_internal" +(define_insn "altivec_vmrghb_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") - (vec_select:V16QI + (vec_select:V16QI (vec_concat:V32QI (match_operand:V16QI 1 "register_operand" "v") (match_operand:V16QI 2 "register_operand" "v")) @@ -1126,20 +1122,6 @@ (const_int 6) (const_int 22) (const_int 7) (const_int 23)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghb %0,%1,%2"; - else - return "vmrglb %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghb_direct" - [(set (match_operand:V16QI 0 "register_operand" "=v") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] - UNSPEC_VMRGH_DIRECT))] - "TARGET_ALTIVEC" "vmrghb %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1149,16 +1131,15 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (8, GEN_INT (0), GEN_INT (8), GEN_INT (1), GEN_INT (9), - GEN_INT (2), GEN_INT (10), GEN_INT (3), GEN_INT (11)); - rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]); - - x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrghh_direct + : gen_altivec_vmrglh_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghh_internal" +(define_insn "altivec_vmrghh_direct" [(set (match_operand:V8HI 0 "register_operand" "=v") (vec_select:V8HI (vec_concat:V16HI @@ -1169,20 +1150,6 @@ (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghh %0,%1,%2"; - else - return "vmrglh %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghh_direct" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] - UNSPEC_VMRGH_DIRECT))] - "TARGET_ALTIVEC" "vmrghh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1192,35 +1159,23 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtvec v = gen_rtvec (4, GEN_INT (0), GEN_INT (4), GEN_INT (1), GEN_INT (5)); - rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_v4si + : gen_altivec_vmrglw_direct_v4si; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrghw_internal" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (vec_select:V4SI - (vec_concat:V8SI - (match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")) +(define_insn "altivec_vmrghw_direct_<mode>" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat:<VS_double> + (match_operand:VSX_W 1 "register_operand" "wa,v") + (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] - "VECTOR_MEM_ALTIVEC_P (V4SImode)" -{ - if (BYTES_BIG_ENDIAN) - return "vmrghw %0,%1,%2"; - else - return "vmrglw %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrghw_direct" - [(set (match_operand:V4SI 0 "register_operand" "=wa,v") - (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "wa,v") - (match_operand:V4SI 2 "register_operand" "wa,v")] - UNSPEC_VMRGH_DIRECT))] "TARGET_ALTIVEC" "@ xxmrghw %x0,%x1,%x2 @@ -1250,19 +1205,17 @@ (use (match_operand:V16QI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (16, GEN_INT (8), GEN_INT (24), GEN_INT (9), GEN_INT (25), - GEN_INT (10), GEN_INT (26), GEN_INT (11), GEN_INT (27), - GEN_INT (12), GEN_INT (28), GEN_INT (13), GEN_INT (29), - GEN_INT (14), GEN_INT (30), GEN_INT (15), GEN_INT (31)); - rtx x = gen_rtx_VEC_CONCAT (V32QImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V16QImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglb_direct + : gen_altivec_vmrghb_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglb_internal" +(define_insn "altivec_vmrglb_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") - (vec_select:V16QI + (vec_select:V16QI (vec_concat:V32QI (match_operand:V16QI 1 "register_operand" "v") (match_operand:V16QI 2 "register_operand" "v")) @@ -1275,20 +1228,6 @@ (const_int 14) (const_int 30) (const_int 15) (const_int 31)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglb %0,%1,%2"; - else - return "vmrghb %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglb_direct" - [(set (match_operand:V16QI 0 "register_operand" "=v") - (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v") - (match_operand:V16QI 2 "register_operand" "v")] - UNSPEC_VMRGL_DIRECT))] - "TARGET_ALTIVEC" "vmrglb %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1298,15 +1237,15 @@ (use (match_operand:V8HI 2 "register_operand"))] "TARGET_ALTIVEC" { - rtvec v = gen_rtvec (8, GEN_INT (4), GEN_INT (12), GEN_INT (5), GEN_INT (13), - GEN_INT (6), GEN_INT (14), GEN_INT (7), GEN_INT (15)); - rtx x = gen_rtx_VEC_CONCAT (V16HImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V8HImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN ? gen_altivec_vmrglh_direct + : gen_altivec_vmrghh_direct; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglh_internal" +(define_insn "altivec_vmrglh_direct" [(set (match_operand:V8HI 0 "register_operand" "=v") (vec_select:V8HI (vec_concat:V16HI @@ -1317,20 +1256,6 @@ (const_int 6) (const_int 14) (const_int 7) (const_int 15)])))] "TARGET_ALTIVEC" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglh %0,%1,%2"; - else - return "vmrghh %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglh_direct" - [(set (match_operand:V8HI 0 "register_operand" "=v") - (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v") - (match_operand:V8HI 2 "register_operand" "v")] - UNSPEC_VMRGL_DIRECT))] - "TARGET_ALTIVEC" "vmrglh %0,%1,%2" [(set_attr "type" "vecperm")]) @@ -1340,35 +1265,23 @@ (use (match_operand:V4SI 2 "register_operand"))] "VECTOR_MEM_ALTIVEC_P (V4SImode)" { - rtvec v = gen_rtvec (4, GEN_INT (2), GEN_INT (6), GEN_INT (3), GEN_INT (7)); - rtx x = gen_rtx_VEC_CONCAT (V8SImode, operands[1], operands[2]); - x = gen_rtx_VEC_SELECT (V4SImode, x, gen_rtx_PARALLEL (VOIDmode, v)); - emit_insn (gen_rtx_SET (operands[0], x)); + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_v4si + : gen_altivec_vmrghw_direct_v4si; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); DONE; }) -(define_insn "*altivec_vmrglw_internal" - [(set (match_operand:V4SI 0 "register_operand" "=v") - (vec_select:V4SI - (vec_concat:V8SI - (match_operand:V4SI 1 "register_operand" "v") - (match_operand:V4SI 2 "register_operand" "v")) +(define_insn "altivec_vmrglw_direct_<mode>" + [(set (match_operand:VSX_W 0 "register_operand" "=wa,v") + (vec_select:VSX_W + (vec_concat:<VS_double> + (match_operand:VSX_W 1 "register_operand" "wa,v") + (match_operand:VSX_W 2 "register_operand" "wa,v")) (parallel [(const_int 2) (const_int 6) (const_int 3) (const_int 7)])))] - "VECTOR_MEM_ALTIVEC_P (V4SImode)" -{ - if (BYTES_BIG_ENDIAN) - return "vmrglw %0,%1,%2"; - else - return "vmrghw %0,%2,%1"; -} - [(set_attr "type" "vecperm")]) - -(define_insn "altivec_vmrglw_direct" - [(set (match_operand:V4SI 0 "register_operand" "=wa,v") - (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "wa,v") - (match_operand:V4SI 2 "register_operand" "wa,v")] - UNSPEC_VMRGL_DIRECT))] "TARGET_ALTIVEC" "@ xxmrglw %x0,%x1,%x2 @@ -3842,13 +3755,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3867,13 +3780,13 @@ { emit_insn (gen_altivec_vmuleuh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulouh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulouh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmuleuh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3892,13 +3805,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrghw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrghw_direct_v4si (operands[0], vo, ve)); } DONE; }) @@ -3917,13 +3830,13 @@ { emit_insn (gen_altivec_vmulesh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulosh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], ve, vo)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], ve, vo)); } else { emit_insn (gen_altivec_vmulosh (ve, operands[1], operands[2])); emit_insn (gen_altivec_vmulesh (vo, operands[1], operands[2])); - emit_insn (gen_altivec_vmrglw_direct (operands[0], vo, ve)); + emit_insn (gen_altivec_vmrglw_direct_v4si (operands[0], vo, ve)); } DONE; }) diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h index ce1287e..32ad72b 100644 --- a/gcc/config/rs6000/emmintrin.h +++ b/gcc/config/rs6000/emmintrin.h @@ -430,20 +430,10 @@ _mm_cmpnge_pd (__m128d __A, __m128d __B) extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_cmpord_pd (__m128d __A, __m128d __B) { -#if _ARCH_PWR8 __v2du c, d; /* Compare against self will return false (0's) if NAN. */ c = (__v2du)vec_cmpeq (__A, __A); d = (__v2du)vec_cmpeq (__B, __B); -#else - __v2du a, b; - __v2du c, d; - const __v2du double_exp_mask = {0x7ff0000000000000, 0x7ff0000000000000}; - a = (__v2du)vec_abs ((__v2df)__A); - b = (__v2du)vec_abs ((__v2df)__B); - c = (__v2du)vec_cmpgt (double_exp_mask, a); - d = (__v2du)vec_cmpgt (double_exp_mask, b); -#endif /* A != NAN and B != NAN. */ return ((__m128d)vec_and(c, d)); } @@ -1472,6 +1462,7 @@ _mm_mul_su32 (__m64 __A, __m64 __B) return ((__m64)a * (__m64)b); } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mul_epu32 (__m128i __A, __m128i __B) { @@ -1498,6 +1489,7 @@ _mm_mul_epu32 (__m128i __A, __m128i __B) return (__m128i) vec_mule ((__v4su)__A, (__v4su)__B); #endif } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_slli_epi16 (__m128i __A, int __B) diff --git a/gcc/config/rs6000/pmmintrin.h b/gcc/config/rs6000/pmmintrin.h index eab712f..83dff1d 100644 --- a/gcc/config/rs6000/pmmintrin.h +++ b/gcc/config/rs6000/pmmintrin.h @@ -123,17 +123,21 @@ _mm_hsub_pd (__m128d __X, __m128d __Y) vec_mergel ((__v2df) __X, (__v2df)__Y)); } +#ifdef _ARCH_PWR8 extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_movehdup_ps (__m128 __X) { return (__m128)vec_mergeo ((__v4su)__X, (__v4su)__X); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_moveldup_ps (__m128 __X) { return (__m128)vec_mergee ((__v4su)__X, (__v4su)__X); } +#endif extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_loaddup_pd (double const *__P) diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 2eceb2c7..6d8727c 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -9959,7 +9959,7 @@ altivec_expand_lxvr_builtin (enum insn_code icode, tree exp, rtx target, bool bl if (sign_extend) { - rtx discratch = gen_reg_rtx (DImode); + rtx discratch = gen_reg_rtx (V2DImode); rtx tiscratch = gen_reg_rtx (TImode); /* Emit the lxvr*x insn. */ @@ -9968,20 +9968,31 @@ altivec_expand_lxvr_builtin (enum insn_code icode, tree exp, rtx target, bool bl return 0; emit_insn (pat); - /* Emit a sign extension from QI,HI,WI to double (DI). */ - rtx scratch = gen_lowpart (smode, tiscratch); + /* Emit a sign extension from V16QI,V8HI,V4SI to V2DI. */ + rtx temp1, temp2; if (icode == CODE_FOR_vsx_lxvrbx) - emit_insn (gen_extendqidi2 (discratch, scratch)); + { + temp1 = simplify_gen_subreg (V16QImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_qi_v2di (discratch, temp1)); + } else if (icode == CODE_FOR_vsx_lxvrhx) - emit_insn (gen_extendhidi2 (discratch, scratch)); + { + temp1 = simplify_gen_subreg (V8HImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_hi_v2di (discratch, temp1)); + } else if (icode == CODE_FOR_vsx_lxvrwx) - emit_insn (gen_extendsidi2 (discratch, scratch)); - /* Assign discratch directly if scratch is already DI. */ - if (icode == CODE_FOR_vsx_lxvrdx) - discratch = scratch; + { + temp1 = simplify_gen_subreg (V4SImode, tiscratch, TImode, 0); + emit_insn (gen_vsx_sign_extend_si_v2di (discratch, temp1)); + } + else if (icode == CODE_FOR_vsx_lxvrdx) + discratch = simplify_gen_subreg (V2DImode, tiscratch, TImode, 0); + else + gcc_unreachable (); - /* Emit the sign extension from DI (double) to TI (quad). */ - emit_insn (gen_extendditi2 (target, discratch)); + /* Emit the sign extension from V2DI (double) to TI (quad). */ + temp2 = simplify_gen_subreg (TImode, discratch, V2DImode, 0); + emit_insn (gen_extendditi2_vector (target, temp2)); return target; } diff --git a/gcc/config/rs6000/rs6000-p8swap.c b/gcc/config/rs6000/rs6000-p8swap.c index 6b559aa..0a84072 100644 --- a/gcc/config/rs6000/rs6000-p8swap.c +++ b/gcc/config/rs6000/rs6000-p8swap.c @@ -766,8 +766,6 @@ rtx_is_swappable_p (rtx op, unsigned int *special) default: break; case UNSPEC_VBPERMQ: - case UNSPEC_VMRGH_DIRECT: - case UNSPEC_VMRGL_DIRECT: case UNSPEC_VPACK_SIGN_SIGN_SAT: case UNSPEC_VPACK_SIGN_UNS_SAT: case UNSPEC_VPACK_UNS_UNS_MOD: diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 01a9559..bac959f 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -21626,17 +21626,17 @@ static void rs6000_xcoff_file_end (void) { switch_to_section (text_section); + if (xcoff_tls_exec_model_detected) + { + /* Add a .ref to __tls_get_addr to force libpthread dependency. */ + fputs ("\t.extern __tls_get_addr\n\t.ref __tls_get_addr\n", asm_out_file); + } fputs ("_section_.text:\n", asm_out_file); switch_to_section (data_section); fputs (TARGET_32BIT ? "\t.long _section_.text\n" : "\t.llong _section_.text\n", asm_out_file); - if (xcoff_tls_exec_model_detected) - { - /* Add a .ref to __tls_get_addr to force libpthread dependency. */ - fputs ("\t.extern __tls_get_addr\n\t.ref __tls_get_addr\n", asm_out_file); - } } struct declare_alias_data @@ -23313,43 +23313,44 @@ altivec_expand_vec_perm_const (rtx target, rtx op0, rtx op1, unsigned char perm[16]; }; static const struct altivec_perm_insn patterns[] = { - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum_direct, - { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum_direct, - { 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct - : CODE_FOR_altivec_vmrglb_direct), - { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct - : CODE_FOR_altivec_vmrglh_direct), - { 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct - : CODE_FOR_altivec_vmrglw_direct), - { 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct - : CODE_FOR_altivec_vmrghb_direct), - { 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct - : CODE_FOR_altivec_vmrghh_direct), - { 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } }, - { OPTION_MASK_ALTIVEC, - (BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct - : CODE_FOR_altivec_vmrghw_direct), - { 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } }, - { OPTION_MASK_P8_VECTOR, - (BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgew_v4sf_direct - : CODE_FOR_p8_vmrgow_v4sf_direct), - { 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27 } }, - { OPTION_MASK_P8_VECTOR, - (BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgow_v4sf_direct - : CODE_FOR_p8_vmrgew_v4sf_direct), - { 4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31 } } - }; + {OPTION_MASK_ALTIVEC, + CODE_FOR_altivec_vpkuhum_direct, + {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}}, + {OPTION_MASK_ALTIVEC, + CODE_FOR_altivec_vpkuwum_direct, + {2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb_direct + : CODE_FOR_altivec_vmrglb_direct, + {0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh_direct + : CODE_FOR_altivec_vmrglh_direct, + {0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw_direct_v4si + : CODE_FOR_altivec_vmrglw_direct_v4si, + {0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb_direct + : CODE_FOR_altivec_vmrghb_direct, + {8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh_direct + : CODE_FOR_altivec_vmrghh_direct, + {8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31}}, + {OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw_direct_v4si + : CODE_FOR_altivec_vmrghw_direct_v4si, + {8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31}}, + {OPTION_MASK_P8_VECTOR, + BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgew_v4sf_direct + : CODE_FOR_p8_vmrgow_v4sf_direct, + {0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27}}, + {OPTION_MASK_P8_VECTOR, + BYTES_BIG_ENDIAN ? CODE_FOR_p8_vmrgow_v4sf_direct + : CODE_FOR_p8_vmrgew_v4sf_direct, + {4, 5, 6, 7, 20, 21, 22, 23, 12, 13, 14, 15, 28, 29, 30, 31}}}; unsigned int i, j, elt, which; unsigned char perm[16]; diff --git a/gcc/config/rs6000/smmintrin.h b/gcc/config/rs6000/smmintrin.h index 90ce03d..b732fbc 100644 --- a/gcc/config/rs6000/smmintrin.h +++ b/gcc/config/rs6000/smmintrin.h @@ -96,6 +96,7 @@ _mm_extract_ps (__m128 __X, const int __N) return ((__v4si)__X)[__N & 3]; } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_blend_epi16 (__m128i __A, __m128i __B, const int __imm8) { @@ -107,6 +108,7 @@ _mm_blend_epi16 (__m128i __A, __m128i __B, const int __imm8) #endif return (__m128i) vec_sel ((__v8hu) __A, (__v8hu) __B, __shortmask); } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_blendv_epi8 (__m128i __A, __m128i __B, __m128i __mask) @@ -167,6 +169,7 @@ _mm_blend_pd (__m128d __A, __m128d __B, const int __imm8) return (__m128d) __r; } +#ifdef _ARCH_PWR8 __inline __m128d __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) _mm_blendv_pd (__m128d __A, __m128d __B, __m128d __mask) @@ -175,6 +178,7 @@ _mm_blendv_pd (__m128d __A, __m128d __B, __m128d __mask) const __vector __bool long long __boolmask = vec_cmplt ((__v2di) __mask, __zero); return (__m128d) vec_sel ((__v2du) __A, (__v2du) __B, (__v2du) __boolmask); } +#endif __inline int __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/rs6000/tmmintrin.h b/gcc/config/rs6000/tmmintrin.h index 9715112..a67d88c 100644 --- a/gcc/config/rs6000/tmmintrin.h +++ b/gcc/config/rs6000/tmmintrin.h @@ -350,6 +350,7 @@ _mm_shuffle_pi8 (__m64 __A, __m64 __B) return (__m64) ((__v2du) (__C))[0]; } +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi8 (__m128i __A, __m128i __B) @@ -361,7 +362,9 @@ _mm_sign_epi8 (__m128i __A, __m128i __B) __v16qi __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v16qi) __A, (__v16qi) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi16 (__m128i __A, __m128i __B) @@ -373,7 +376,9 @@ _mm_sign_epi16 (__m128i __A, __m128i __B) __v8hi __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v8hi) __A, (__v8hi) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_epi32 (__m128i __A, __m128i __B) @@ -385,7 +390,9 @@ _mm_sign_epi32 (__m128i __A, __m128i __B) __v4si __conv = vec_add (__selectneg, __selectpos); return (__m128i) vec_mul ((__v4si) __A, (__v4si) __conv); } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi8 (__m64 __A, __m64 __B) @@ -396,7 +403,9 @@ _mm_sign_pi8 (__m64 __A, __m64 __B) __C = (__v16qi) _mm_sign_epi8 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi16 (__m64 __A, __m64 __B) @@ -407,7 +416,9 @@ _mm_sign_pi16 (__m64 __A, __m64 __B) __C = (__v8hi) _mm_sign_epi16 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif +#ifdef _ARCH_PWR8 extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_sign_pi32 (__m64 __A, __m64 __B) @@ -418,6 +429,7 @@ _mm_sign_pi32 (__m64 __A, __m64 __B) __C = (__v4si) _mm_sign_epi32 ((__m128i) __C, (__m128i) __D); return (__m64) ((__v2du) (__C))[0]; } +#endif extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index bf033e3..346f1a9 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -4688,7 +4688,7 @@ [(set_attr "type" "vecperm")]) ;; V4SF/V4SI interleave -(define_insn "vsx_xxmrghw_<mode>" +(define_expand "vsx_xxmrghw_<mode>" [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa") (vec_select:VSX_W (vec_concat:<VS_double> @@ -4698,14 +4698,17 @@ (const_int 1) (const_int 5)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" { - if (BYTES_BIG_ENDIAN) - return "xxmrghw %x0,%x1,%x2"; - else - return "xxmrglw %x0,%x2,%x1"; + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrghw_direct_<mode> + : gen_altivec_vmrglw_direct_<mode>; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); + DONE; } [(set_attr "type" "vecperm")]) -(define_insn "vsx_xxmrglw_<mode>" +(define_expand "vsx_xxmrglw_<mode>" [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa") (vec_select:VSX_W (vec_concat:<VS_double> @@ -4715,10 +4718,13 @@ (const_int 3) (const_int 7)])))] "VECTOR_MEM_VSX_P (<MODE>mode)" { - if (BYTES_BIG_ENDIAN) - return "xxmrglw %x0,%x1,%x2"; - else - return "xxmrghw %x0,%x2,%x1"; + rtx (*fun) (rtx, rtx, rtx); + fun = BYTES_BIG_ENDIAN ? gen_altivec_vmrglw_direct_<mode> + : gen_altivec_vmrghw_direct_<mode>; + if (!BYTES_BIG_ENDIAN) + std::swap (operands[1], operands[2]); + emit_insn (fun (operands[0], operands[1], operands[2])); + DONE; } [(set_attr "type" "vecperm")]) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 85dd78c..b2f2f64 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -7808,7 +7808,7 @@ s390_asm_declare_function_size (FILE *asm_out_file, /* Write the extra assembler code needed to declare a function properly. */ void -s390_asm_output_function_label (FILE *asm_out_file, const char *fname, +s390_asm_output_function_label (FILE *out_file, const char *fname, tree decl) { int hw_before, hw_after; @@ -7822,11 +7822,11 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname, /* Add a trampoline code area before the function label and initialize it with two-byte nop instructions. This area can be overwritten with code that jumps to a patched version of the function. */ - asm_fprintf (asm_out_file, "\tnopr\t%%r0" + asm_fprintf (out_file, "\tnopr\t%%r0" "\t# pre-label NOPs for hotpatch (%d halfwords)\n", hw_before); for (i = 1; i < hw_before; i++) - fputs ("\tnopr\t%r0\n", asm_out_file); + fputs ("\tnopr\t%r0\n", out_file); /* Note: The function label must be aligned so that (a) the bytes of the following nop do not cross a cacheline boundary, and (b) a jump address @@ -7843,35 +7843,35 @@ s390_asm_output_function_label (FILE *asm_out_file, const char *fname, function_alignment = MAX (function_alignment, (unsigned int) align_functions.levels[0].get_value ()); - fputs ("\t# alignment for hotpatch\n", asm_out_file); - ASM_OUTPUT_ALIGN (asm_out_file, align_functions.levels[0].log); + fputs ("\t# alignment for hotpatch\n", out_file); + ASM_OUTPUT_ALIGN (out_file, align_functions.levels[0].log); } if (S390_USE_TARGET_ATTRIBUTE && TARGET_DEBUG_ARG) { - asm_fprintf (asm_out_file, "\t# fn:%s ar%d\n", fname, s390_arch); - asm_fprintf (asm_out_file, "\t# fn:%s tu%d\n", fname, s390_tune); - asm_fprintf (asm_out_file, "\t# fn:%s sg%d\n", fname, s390_stack_guard); - asm_fprintf (asm_out_file, "\t# fn:%s ss%d\n", fname, s390_stack_size); - asm_fprintf (asm_out_file, "\t# fn:%s bc%d\n", fname, s390_branch_cost); - asm_fprintf (asm_out_file, "\t# fn:%s wf%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s ar%d\n", fname, s390_arch); + asm_fprintf (out_file, "\t# fn:%s tu%d\n", fname, s390_tune); + asm_fprintf (out_file, "\t# fn:%s sg%d\n", fname, s390_stack_guard); + asm_fprintf (out_file, "\t# fn:%s ss%d\n", fname, s390_stack_size); + asm_fprintf (out_file, "\t# fn:%s bc%d\n", fname, s390_branch_cost); + asm_fprintf (out_file, "\t# fn:%s wf%d\n", fname, s390_warn_framesize); - asm_fprintf (asm_out_file, "\t# fn:%s ba%d\n", fname, TARGET_BACKCHAIN); - asm_fprintf (asm_out_file, "\t# fn:%s hd%d\n", fname, TARGET_HARD_DFP); - asm_fprintf (asm_out_file, "\t# fn:%s hf%d\n", fname, !TARGET_SOFT_FLOAT); - asm_fprintf (asm_out_file, "\t# fn:%s ht%d\n", fname, TARGET_OPT_HTM); - asm_fprintf (asm_out_file, "\t# fn:%s vx%d\n", fname, TARGET_OPT_VX); - asm_fprintf (asm_out_file, "\t# fn:%s ps%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s ba%d\n", fname, TARGET_BACKCHAIN); + asm_fprintf (out_file, "\t# fn:%s hd%d\n", fname, TARGET_HARD_DFP); + asm_fprintf (out_file, "\t# fn:%s hf%d\n", fname, !TARGET_SOFT_FLOAT); + asm_fprintf (out_file, "\t# fn:%s ht%d\n", fname, TARGET_OPT_HTM); + asm_fprintf (out_file, "\t# fn:%s vx%d\n", fname, TARGET_OPT_VX); + asm_fprintf (out_file, "\t# fn:%s ps%d\n", fname, TARGET_PACKED_STACK); - asm_fprintf (asm_out_file, "\t# fn:%s se%d\n", fname, TARGET_SMALL_EXEC); - asm_fprintf (asm_out_file, "\t# fn:%s mv%d\n", fname, TARGET_MVCLE); - asm_fprintf (asm_out_file, "\t# fn:%s zv%d\n", fname, TARGET_ZVECTOR); - asm_fprintf (asm_out_file, "\t# fn:%s wd%d\n", fname, + asm_fprintf (out_file, "\t# fn:%s se%d\n", fname, TARGET_SMALL_EXEC); + asm_fprintf (out_file, "\t# fn:%s mv%d\n", fname, TARGET_MVCLE); + asm_fprintf (out_file, "\t# fn:%s zv%d\n", fname, TARGET_ZVECTOR); + asm_fprintf (out_file, "\t# fn:%s wd%d\n", fname, s390_warn_dynamicstack_p); } - ASM_OUTPUT_LABEL (asm_out_file, fname); + ASM_OUTPUT_LABEL (out_file, fname); if (hw_after > 0) - asm_fprintf (asm_out_file, + asm_fprintf (out_file, "\t# post-label NOPs for hotpatch (%d halfwords)\n", hw_after); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ffdb690..08ba25e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2021-10-20 Jason Merrill <jason@redhat.com> + + * parser.c (cp_parser_parse_and_diagnose_invalid_type_name): + Pass true for declarator_p. + (cp_parser_nested_name_specifier_opt): Only look through + TYPENAME_TYPE if check_dependency_p is false. + +2021-10-20 Jakub Jelinek <jakub@redhat.com> + + PR c++/102642 + * name-lookup.c (push_local_extern_decl_alias): Don't call + set_decl_tls_model on error_mark_node. + * decl.c (make_rtl_for_nonlocal_decl): Don't call + set_user_assembler_name on error_mark_node. + * parser.c (cp_parser_oacc_declare): Ignore DECL_LOCAL_DECL_ALIAS + if it is error_mark_node. + (cp_parser_omp_declare_target): Likewise. + +2021-10-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/102786 + * constexpr.c (cxx_eval_constant_expression): Don't reject + INTEGER_CSTs with type POINTER_TYPE to METHOD_TYPE. + 2021-10-15 Jason Merrill <jason@redhat.com> PR c++/51851 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index c5f01b9..6f83d30 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -6191,6 +6191,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (t) == INTEGER_CST && TYPE_PTR_P (TREE_TYPE (t)) + /* INTEGER_CST with pointer-to-method type is only used + for a virtual method in a pointer to member function. + Don't reject those. */ + && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != METHOD_TYPE && !integer_zerop (t)) { if (!ctx->quiet) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 242429d..8a45411 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7373,7 +7373,8 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) This is horrible, as we're affecting a possibly-shared decl. Again, a one-true-decl model breaks down. */ - set_user_assembler_name (ns_decl, asmspec); + if (ns_decl != error_mark_node) + set_user_assembler_name (ns_decl, asmspec); } } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index c414a10..035bcf5 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3474,7 +3474,9 @@ push_local_extern_decl_alias (tree decl) push_nested_namespace (ns); alias = do_pushdecl (alias, /* hiding= */true); pop_nested_namespace (ns); - if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl)) + if (VAR_P (decl) + && CP_DECL_THREAD_LOCAL_P (decl) + && alias != error_mark_node) set_decl_tls_model (alias, DECL_TLS_MODEL (decl)); } } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 865778e..49d951c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3693,7 +3693,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, - /*declarator_p=*/false, + /*declarator_p=*/true, /*optional_p=*/false); /* If the next token is a (, this is a function with no explicit return type, i.e. constructor, destructor or conversion op. */ @@ -6605,6 +6605,8 @@ check_template_keyword_in_nested_name_spec (tree name) it unchanged if there is no nested-name-specifier. Returns the new scope iff there is a nested-name-specifier, or NULL_TREE otherwise. + If CHECK_DEPENDENCY_P is FALSE, names are looked up in dependent scopes. + If IS_DECLARATION is TRUE, the nested-name-specifier is known to be part of a declaration and/or decl-specifier. */ @@ -6645,9 +6647,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /* Grab the nested-name-specifier and continue the loop. */ cp_parser_pre_parsed_nested_name_specifier (parser); /* If we originally encountered this nested-name-specifier - with IS_DECLARATION set to false, we will not have + with CHECK_DEPENDENCY_P set to true, we will not have resolved TYPENAME_TYPEs, so we must do so here. */ if (is_declaration + && !check_dependency_p && TREE_CODE (parser->scope) == TYPENAME_TYPE) { new_scope = resolve_typename_type (parser->scope, @@ -6729,6 +6732,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, a template. So, if we have a typename at this point, we make an effort to look through it. */ if (is_declaration + && !check_dependency_p && !typename_keyword_p && parser->scope && TREE_CODE (parser->scope) == TYPENAME_TYPE) @@ -44437,7 +44441,8 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok) dependent local extern variable decls are as rare as hen's teeth. */ if (auto alias = DECL_LOCAL_DECL_ALIAS (decl)) - decl = alias; + if (alias != error_mark_node) + decl = alias; if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK) id = get_identifier ("omp declare target link"); @@ -45665,7 +45670,8 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) if (VAR_OR_FUNCTION_DECL_P (t) && DECL_LOCAL_DECL_P (t) && DECL_LANG_SPECIFIC (t) - && DECL_LOCAL_DECL_ALIAS (t)) + && DECL_LOCAL_DECL_ALIAS (t) + && DECL_LOCAL_DECL_ALIAS (t) != error_mark_node) handle_omp_declare_target_clause (c, DECL_LOCAL_DECL_ALIAS (t), device_type); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2b18155..171b7a8 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9723,10 +9723,12 @@ A basic @code{asm} statement has the following syntax: asm @var{asm-qualifiers} ( @var{AssemblerInstructions} ) @end example -The @code{asm} keyword is a GNU extension. -When writing code that can be compiled with @option{-ansi} and the -various @option{-std} options, use @code{__asm__} instead of -@code{asm} (@pxref{Alternate Keywords}). +For the C language, the @code{asm} keyword is a GNU extension. +When writing C code that can be compiled with @option{-ansi} and the +@option{-std} options that select C dialects without GNU extensions, use +@code{__asm__} instead of @code{asm} (@pxref{Alternate Keywords}). For +the C++ language, @code{asm} is a standard keyword, but @code{__asm__} +can be used for code compiled with @option{-fno-asm}. @subsubheading Qualifiers @table @code @@ -17693,7 +17695,7 @@ macro @code{__BUILTIN_CPU_SUPPORTS__} if the @code{__builtin_cpu_supports} built-in function is fully supported. If GCC was configured to use a GLIBC before 2.23, the built-in -function @code{__builtin_cpu_suports} always returns a 0 and the +function @code{__builtin_cpu_supports} always returns a 0 and the compiler issues a warning. The following features can be diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index cdfbfdd..4f60e48 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -195,12 +195,6 @@ remove that directory when you do not need that specific version of GCC any longer, and, if shared libraries are installed there as well, no more binaries exist that use them. -@ifhtml -There are also some @uref{old.html,,old installation instructions}, -which are mostly obsolete but still contain some information which has -not yet been merged into the main part of this manual. -@end ifhtml - @html <hr /> <p> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 3663c2b..acfa766 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2448,14 +2448,14 @@ supported for C as this construct is allowed by C++. Do not recognize @code{asm}, @code{inline} or @code{typeof} as a keyword, so that code can use these words as identifiers. You can use the keywords @code{__asm__}, @code{__inline__} and @code{__typeof__} -instead. @option{-ansi} implies @option{-fno-asm}. +instead. In C, @option{-ansi} implies @option{-fno-asm}. -In C++, this switch only affects the @code{typeof} keyword, since -@code{asm} and @code{inline} are standard keywords. You may want to -use the @option{-fno-gnu-keywords} flag instead, which has the same -effect. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), this -switch only affects the @code{asm} and @code{typeof} keywords, since -@code{inline} is a standard keyword in ISO C99. +In C++, @code{inline} is a standard keyword and is not affected by +this switch. You may want to use the @option{-fno-gnu-keywords} flag +instead, which disables @code{typeof} but not @code{asm} and +@code{inline}. In C99 mode (@option{-std=c99} or @option{-std=gnu99}), +this switch only affects the @code{asm} and @code{typeof} keywords, +since @code{inline} is a standard keyword in ISO C99. @item -fno-builtin @itemx -fno-builtin-@var{function} @@ -14431,6 +14431,9 @@ Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit(). Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path. +@item max-fsm-thread-length +Maximum number of basic blocks on a jump thread path. + @item parloops-chunk-size Chunk size of omp schedule for loops parallelized by parloops. diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index b1fffd5..6a16576 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1845,6 +1845,38 @@ Target supports loop vectorization with partial vectors and @item vect_partial_vectors Target supports loop vectorization with partial vectors and @code{vect-partial-vector-usage} is nonzero. + +@item vect_slp_v2qi_store +Target supports vectorization of 2-byte char stores with 2-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4qi_store +Target supports vectorization of 4-byte char stores with 4-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v8qi_store +Target supports vectorization of 8-byte char stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v16qi_store +Target supports vectorization of 16-byte char stores with 16-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v2hi_store +Target supports vectorization of 4-byte short stores with 4-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4hi_store +Target supports vectorization of 8-byte short stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v2si_store +Target supports vectorization of 8-byte int stores with 8-byte aligned +address at plain @option{-O2}. + +@item vect_slp_v4si_store +Target supports vectorization of 16-byte int stores with 16-byte aligned +address at plain @option{-O2}. @end table @subsubsection Thread Local Storage attributes diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9649695..fa66a09 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4230,12 +4230,6 @@ The return value is usually either a @code{reg} RTX for the hard register in which to pass the argument, or zero to pass the argument on the stack. -The return value can be a @code{const_int} which means argument is -passed in a target specific slot with specified number. Target hooks -should be used to store or load argument in such case. See -@code{TARGET_STORE_BOUNDS_FOR_ARG} and @code{TARGET_LOAD_BOUNDS_FOR_ARG} -for more information. - The value of the expression can also be a @code{parallel} RTX@. This is used when an argument is passed in multiple locations. The mode of the @code{parallel} should be the mode of the entire argument. The @@ -5724,45 +5718,6 @@ Otherwise, you should not define this hook. @end deftypefn @c hook-end -@deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no}) -@c hook-start:TARGET_LOAD_BOUNDS_FOR_ARG -This hook is used by expand pass to emit insn to load bounds of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -bounds of @var{arg} are not passed in register. If @var{slot} is a -memory, then bounds are loaded as for regular pointer loaded from -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to obtain bounds. Hook returns RTX holding loaded bounds. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no}) -@c hook-start:TARGET_STORE_BOUNDS_FOR_ARG -This hook is used by expand pass to emit insns to store @var{bounds} of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a -memory, then @var{bounds} are stored as for regular pointer stored in -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to store @var{bounds}. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} rtx TARGET_LOAD_RETURNED_BOUNDS (rtx @var{slot}) -@c hook-start:TARGET_LOAD_RETURNED_BOUNDS -This hook is used by expand pass to emit insn to load bounds -returned by function call in @var{slot}. Hook returns RTX holding -loaded bounds. -@end deftypefn -@c hook-end - -@deftypefn {Target Hook} void TARGET_STORE_RETURNED_BOUNDS (rtx @var{slot}, rtx @var{bounds}) -@c hook-start:TARGET_STORE_RETURNED_BOUNDS -This hook is used by expand pass to emit insn to store @var{bounds} -returned by function call into @var{slot}. -@end deftypefn -@c hook-end - @node Trampolines @section Support for Nested Functions @cindex support for nested functions diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 86352dc..193c9bd 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3780,14 +3780,6 @@ These machine description macros help implement varargs: @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED -@hook TARGET_LOAD_BOUNDS_FOR_ARG - -@hook TARGET_STORE_BOUNDS_FOR_ARG - -@hook TARGET_LOAD_RETURNED_BOUNDS - -@hook TARGET_STORE_RETURNED_BOUNDS - @node Trampolines @section Support for Nested Functions @cindex support for nested functions diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 2d3d33a..f75b880 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,104 @@ +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * openmp.c (gfc_match_omp_clause_reduction): Add 'openmp_target' default + false parameter. Add 'always,tofrom' map for OMP_LIST_IN_REDUCTION case. + (gfc_match_omp_clauses): Add 'openmp_target' default false parameter, + adjust call to gfc_match_omp_clause_reduction. + (match_omp): Adjust call to gfc_match_omp_clauses + * trans-openmp.c (gfc_trans_omp_taskgroup): Add call to + gfc_match_omp_clause, create and return block. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + * trans-types.c (create_fn_spec): For allocatable/pointer + character(len=:), use 'w' not 'R' as fn spec for the length dummy + argument. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/92482 + * trans-expr.c (gfc_conv_procedure_call): Use TREE_OPERAND not + build_fold_indirect_ref_loc to undo an ADDR_EXPR. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * decl.c (gfc_verify_c_interop_param): Remove 'sorry' for + scalar allocatable/pointer and len=*. + * expr.c (is_CFI_desc): Return true for for those. + * gfortran.h (CFI_type_kind_shift, CFI_type_mask, + CFI_type_from_type_kind, CFI_VERSION, CFI_MAX_RANK, + CFI_attribute_pointer, CFI_attribute_allocatable, + CFI_attribute_other, CFI_type_Integer, CFI_type_Logical, + CFI_type_Real, CFI_type_Complex, CFI_type_Character, + CFI_type_ucs4_char, CFI_type_struct, CFI_type_cptr, + CFI_type_cfunptr, CFI_type_other): New #define. + * trans-array.c (CFI_FIELD_BASE_ADDR, CFI_FIELD_ELEM_LEN, + CFI_FIELD_VERSION, CFI_FIELD_RANK, CFI_FIELD_ATTRIBUTE, + CFI_FIELD_TYPE, CFI_FIELD_DIM, CFI_DIM_FIELD_LOWER_BOUND, + CFI_DIM_FIELD_EXTENT, CFI_DIM_FIELD_SM, + gfc_get_cfi_descriptor_field, gfc_get_cfi_desc_base_addr, + gfc_get_cfi_desc_elem_len, gfc_get_cfi_desc_version, + gfc_get_cfi_desc_rank, gfc_get_cfi_desc_type, + gfc_get_cfi_desc_attribute, gfc_get_cfi_dim_item, + gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): + New define/functions to access the CFI array descriptor. + (gfc_conv_descriptor_type): New function for the GFC descriptor. + (gfc_get_array_span): Handle expr of CFI descriptors and + assumed-type descriptors. + (gfc_trans_array_bounds): Remove 'static'. + (gfc_conv_expr_descriptor): For assumed type, use the dtype of + the actual argument. + (structure_alloc_comps): Remove ' ' inside tabs. + * trans-array.h (gfc_trans_array_bounds, gfc_conv_descriptor_type, + gfc_get_cfi_desc_base_addr, gfc_get_cfi_desc_elem_len, + gfc_get_cfi_desc_version, gfc_get_cfi_desc_rank, + gfc_get_cfi_desc_type, gfc_get_cfi_desc_attribute, + gfc_get_cfi_dim_lbound, gfc_get_cfi_dim_extent, gfc_get_cfi_dim_sm): + New prototypes. + * trans-decl.c (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): + Remove global vars. + (gfc_build_builtin_function_decls): Remove their initialization. + (gfc_get_symbol_decl, create_function_arglist, + gfc_trans_deferred_vars): Update for CFI. + (convert_CFI_desc): Remove and replace by ... + (gfc_conv_cfi_to_gfc): ... this function + (gfc_generate_function_code): Call it; create local GFC var for CFI. + * trans-expr.c (gfc_maybe_dereference_var): Handle CFI. + (gfc_conv_subref_array_arg): Handle the if-noncontigous-only copy in + when the result should be a descriptor. + (gfc_conv_gfc_desc_to_cfi_desc): Completely rewritten. + (gfc_conv_procedure_call): CFI fixes. + * trans-openmp.c (gfc_omp_is_optional_argument, + gfc_omp_check_optional_argument): Handle optional + CFI. + * trans-stmt.c (gfc_trans_select_rank_cases): Cleanup, avoid invalid + code for allocatable/pointer dummies, which cannot be assumed size. + * trans-types.c (gfc_cfi_descriptor_base): New global var. + (gfc_get_dtype_rank_type): Skip rank init for rank < 0. + (gfc_sym_type): Handle CFI dummies. + (gfc_get_function_type): Update call. + (gfc_get_cfi_dim_type, gfc_get_cfi_type): New. + * trans-types.h (gfc_sym_type): Update prototype. + (gfc_get_cfi_type): New prototype. + * trans.c (gfc_trans_runtime_check): Make conditions more consistent + to avoid '<logical> AND_THEN <long int>' in conditions. + * trans.h (gfor_fndecl_cfi_to_gfc, gfor_fndecl_gfc_to_cfi): Remove + global-var declaration. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102745 + * intrinsic.c (gfc_convert_type_warn): Fix checks by checking CLASS + and do typcheck in correct order for type extension. + * misc.c (gfc_typename): Print proper not internal CLASS type name. + 2021-10-15 Harald Anlauf <anlauf@gmx.de> Tobias Burnus <tobias@codesourcery.com> diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 6784b07..6043e10 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -8429,6 +8429,7 @@ gfc_match_end (gfc_statement *st) break; case COMP_BLOCK: + case COMP_OMP_STRICTLY_STRUCTURED_BLOCK: *st = ST_END_BLOCK; target = " block"; eos_ok = 0; diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 66f24c6..b19d3a2 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -2205,7 +2205,8 @@ gfc_simplify_expr (gfc_expr *p, int type) (p->value.function.isym->id == GFC_ISYM_LBOUND || p->value.function.isym->id == GFC_ISYM_UBOUND || p->value.function.isym->id == GFC_ISYM_LCOBOUND - || p->value.function.isym->id == GFC_ISYM_UCOBOUND)) + || p->value.function.isym->id == GFC_ISYM_UCOBOUND + || p->value.function.isym->id == GFC_ISYM_SHAPE)) ap = ap->next; for ( ; ap; ap = ap->next) diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 2a161f3..dcf22ac 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -1202,7 +1202,7 @@ failed: static match gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, - bool allow_derived) + bool allow_derived, bool openmp_target = false) { if (pc == 'r' && gfc_match ("reduction ( ") != MATCH_YES) return MATCH_NO; @@ -1349,6 +1349,19 @@ gfc_match_omp_clause_reduction (char pc, gfc_omp_clauses *c, bool openacc, n->u2.udr = gfc_get_omp_namelist_udr (); n->u2.udr->udr = udr; } + if (openmp_target && list_idx == OMP_LIST_IN_REDUCTION) + { + gfc_omp_namelist *p = gfc_get_omp_namelist (), **tl; + p->sym = n->sym; + p->where = p->where; + p->u.map_op = OMP_MAP_ALWAYS_TOFROM; + + tl = &c->lists[OMP_LIST_MAP]; + while (*tl) + tl = &((*tl)->next); + *tl = p; + p->next = NULL; + } } return MATCH_YES; } @@ -1417,7 +1430,8 @@ gfc_match_dupl_atomic (bool not_dupl, const char *name) static match gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, bool first = true, bool needs_space = true, - bool openacc = false, bool context_selector = false) + bool openacc = false, bool context_selector = false, + bool openmp_target = false) { bool error = false; gfc_omp_clauses *c = gfc_get_omp_clauses (); @@ -2121,8 +2135,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, goto error; } if ((mask & OMP_CLAUSE_IN_REDUCTION) - && gfc_match_omp_clause_reduction (pc, c, openacc, - allow_derived) == MATCH_YES) + && gfc_match_omp_clause_reduction (pc, c, openacc, allow_derived, + openmp_target) == MATCH_YES) continue; if ((mask & OMP_CLAUSE_INBRANCH) && (m = gfc_match_dupl_check (!c->inbranch && !c->notinbranch, @@ -3578,7 +3592,8 @@ static match match_omp (gfc_exec_op op, const omp_mask mask) { gfc_omp_clauses *c; - if (gfc_match_omp_clauses (&c, mask) != MATCH_YES) + if (gfc_match_omp_clauses (&c, mask, true, true, false, false, + op == EXEC_OMP_TARGET) != MATCH_YES) return MATCH_ERROR; new_st.op = op; new_st.ext.omp_clauses = c; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 2a454be..b1e73ee 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -5459,7 +5459,7 @@ parse_oacc_loop (gfc_statement acc_st) /* Parse the statements of an OpenMP structured block. */ -static void +static gfc_statement parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) { gfc_statement st, omp_end_st; @@ -5546,6 +5546,32 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gcc_unreachable (); } + bool block_construct = false; + gfc_namespace *my_ns = NULL; + gfc_namespace *my_parent = NULL; + + st = next_statement (); + + if (st == ST_BLOCK) + { + /* Adjust state to a strictly-structured block, now that we found that + the body starts with a BLOCK construct. */ + s.state = COMP_OMP_STRICTLY_STRUCTURED_BLOCK; + + block_construct = true; + gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); + + my_ns = gfc_build_block_ns (gfc_current_ns); + gfc_current_ns = my_ns; + my_parent = my_ns->parent; + + new_st.op = EXEC_BLOCK; + new_st.ext.block.ns = my_ns; + new_st.ext.block.assoc = NULL; + accept_statement (ST_BLOCK); + st = parse_spec (ST_NONE); + } + do { if (workshare_stmts_only) @@ -5562,7 +5588,6 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) restrictions apply recursively. */ bool cycle = true; - st = next_statement (); for (;;) { switch (st) @@ -5588,13 +5613,13 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) case ST_OMP_PARALLEL_MASKED: case ST_OMP_PARALLEL_MASTER: case ST_OMP_PARALLEL_SECTIONS: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_PARALLEL_WORKSHARE: case ST_OMP_CRITICAL: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_PARALLEL_DO: case ST_OMP_PARALLEL_DO_SIMD: @@ -5617,7 +5642,7 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) } } else - st = parse_executable (ST_NONE); + st = parse_executable (st); if (st == ST_NONE) unexpected_eof (); else if (st == ST_OMP_SECTION @@ -5627,9 +5652,27 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) np = new_level (np); np->op = cp->op; np->block = NULL; + st = next_statement (); + } + else if (block_construct && st == ST_END_BLOCK) + { + accept_statement (st); + gfc_current_ns = my_parent; + pop_state (); + + st = next_statement (); + if (st == omp_end_st) + { + accept_statement (st); + st = next_statement (); + } + return st; } else if (st != omp_end_st) - unexpected_statement (st); + { + unexpected_statement (st); + st = next_statement (); + } } while (st != omp_end_st); @@ -5665,6 +5708,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only) gfc_commit_symbols (); gfc_warning_check (); pop_state (); + st = next_statement (); + return st; } @@ -5805,13 +5850,13 @@ parse_executable (gfc_statement st) case ST_OMP_TEAMS: case ST_OMP_TASK: case ST_OMP_TASKGROUP: - parse_omp_structured_block (st, false); - break; + st = parse_omp_structured_block (st, false); + continue; case ST_OMP_WORKSHARE: case ST_OMP_PARALLEL_WORKSHARE: - parse_omp_structured_block (st, true); - break; + st = parse_omp_structured_block (st, true); + continue; case ST_OMP_DISTRIBUTE: case ST_OMP_DISTRIBUTE_PARALLEL_DO: diff --git a/gcc/fortran/parse.h b/gcc/fortran/parse.h index 55f0229..66b275d 100644 --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -31,7 +31,7 @@ enum gfc_compile_state COMP_STRUCTURE, COMP_UNION, COMP_MAP, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, COMP_SELECT_TYPE, COMP_SELECT_RANK, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, - COMP_DO_CONCURRENT + COMP_DO_CONCURRENT, COMP_OMP_STRICTLY_STRUCTURED_BLOCK }; /* Stack element for the current compilation state. These structures diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index f8c087e..bceb8b2 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -4507,6 +4507,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) case GFC_ISYM_UBOUND: case GFC_ISYM_LCOBOUND: case GFC_ISYM_UCOBOUND: + case GFC_ISYM_SHAPE: case GFC_ISYM_THIS_IMAGE: loop->dimen = ss->dimen; goto done; @@ -4558,12 +4559,14 @@ done: /* Fall through to supply start and stride. */ case GFC_ISYM_LBOUND: case GFC_ISYM_UBOUND: + /* This is the variant without DIM=... */ + gcc_assert (expr->value.function.actual->next->expr == NULL); + /* Fall through. */ + + case GFC_ISYM_SHAPE: { gfc_expr *arg; - /* This is the variant without DIM=... */ - gcc_assert (expr->value.function.actual->next->expr == NULL); - arg = expr->value.function.actual->expr; if (arg->rank == -1) { @@ -5350,10 +5353,13 @@ set_loop_bounds (gfc_loopinfo *loop) gfc_expr *expr = loopspec[n]->info->expr; /* The {l,u}bound of an assumed rank. */ - gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND - || expr->value.function.isym->id == GFC_ISYM_UBOUND) - && expr->value.function.actual->next->expr == NULL - && expr->value.function.actual->expr->rank == -1); + if (expr->value.function.isym->id == GFC_ISYM_SHAPE) + gcc_assert (expr->value.function.actual->expr->rank == -1); + else + gcc_assert ((expr->value.function.isym->id == GFC_ISYM_LBOUND + || expr->value.function.isym->id == GFC_ISYM_UBOUND) + && expr->value.function.actual->next->expr == NULL + && expr->value.function.actual->expr->rank == -1); loop->to[n] = info->end[dim]; break; diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 0138937..29697e6 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -6640,7 +6640,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, { tmp = parmse.expr; if (TREE_CODE (tmp) == ADDR_EXPR) - tmp = build_fold_indirect_ref_loc (input_location, tmp); + tmp = TREE_OPERAND (tmp, 0); parmse.expr = gfc_conv_scalar_to_descriptor (&parmse, tmp, fsym->attr); parmse.expr = gfc_build_addr_expr (NULL_TREE, diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 2a2829c..0d91958 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2922,7 +2922,7 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg) /* TODO: bound intrinsic generates way too much unnecessary code. */ static void -gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) +gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, enum gfc_isym_id op) { gfc_actual_arglist *arg; gfc_actual_arglist *arg2; @@ -2930,9 +2930,10 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) tree type; tree bound; tree tmp; - tree cond, cond1, cond3, cond4, size; + tree cond, cond1; tree ubound; tree lbound; + tree size; gfc_se argse; gfc_array_spec * as; bool assumed_rank_lb_one; @@ -2943,7 +2944,7 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) if (se->ss) { /* Create an implicit second parameter from the loop variable. */ - gcc_assert (!arg2->expr); + gcc_assert (!arg2->expr || op == GFC_ISYM_SHAPE); gcc_assert (se->loop->dimen == 1); gcc_assert (se->ss->info->expr == expr); gfc_advance_se_ss_chain (se); @@ -2979,12 +2980,14 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) if (INTEGER_CST_P (bound)) { + gcc_assert (op != GFC_ISYM_SHAPE); if (((!as || as->type != AS_ASSUMED_RANK) && wi::geu_p (wi::to_wide (bound), GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))) || wi::gtu_p (wi::to_wide (bound), GFC_MAX_DIMENSIONS)) gfc_error ("%<dim%> argument of %s intrinsic at %L is not a valid " - "dimension index", upper ? "UBOUND" : "LBOUND", + "dimension index", + (op == GFC_ISYM_UBOUND) ? "UBOUND" : "LBOUND", &expr->where); } @@ -3008,8 +3011,8 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) } } - /* Take care of the lbound shift for assumed-rank arrays, which are - nonallocatable and nonpointers. Those has a lbound of 1. */ + /* Take care of the lbound shift for assumed-rank arrays that are + nonallocatable and nonpointers. Those have a lbound of 1. */ assumed_rank_lb_one = as && as->type == AS_ASSUMED_RANK && ((arg->expr->ts.type != BT_CLASS && !arg->expr->symtree->n.sym->attr.allocatable @@ -3020,6 +3023,10 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) ubound = gfc_conv_descriptor_ubound_get (desc, bound); lbound = gfc_conv_descriptor_lbound_get (desc, bound); + size = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, ubound, lbound); + size = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, size, gfc_index_one_node); /* 13.14.53: Result value for LBOUND @@ -3042,106 +3049,82 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper) not have size zero and has value zero if dimension DIM has size zero. */ - if (!upper && assumed_rank_lb_one) + if (op == GFC_ISYM_LBOUND && assumed_rank_lb_one) se->expr = gfc_index_one_node; else if (as) { - tree stride = gfc_conv_descriptor_stride_get (desc, bound); - - cond1 = fold_build2_loc (input_location, GE_EXPR, logical_type_node, - ubound, lbound); - cond3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node, - stride, gfc_index_zero_node); - cond3 = fold_build2_loc (input_location, TRUTH_AND_EXPR, - logical_type_node, cond3, cond1); - cond4 = fold_build2_loc (input_location, LT_EXPR, logical_type_node, - stride, gfc_index_zero_node); - - if (upper) + if (op == GFC_ISYM_UBOUND) { - tree cond5; - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond3, cond4); - cond5 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, - gfc_index_one_node, lbound); - cond5 = fold_build2_loc (input_location, TRUTH_AND_EXPR, - logical_type_node, cond4, cond5); - - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond, cond5); - - if (assumed_rank_lb_one) + cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, + size, gfc_index_zero_node); + se->expr = fold_build3_loc (input_location, COND_EXPR, + gfc_array_index_type, cond, + (assumed_rank_lb_one ? size : ubound), + gfc_index_zero_node); + } + else if (op == GFC_ISYM_LBOUND) + { + cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node, + size, gfc_index_zero_node); + if (as->type == AS_ASSUMED_SIZE) { - tmp = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, ubound, lbound); - tmp = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, tmp, gfc_index_one_node); + cond1 = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, bound, + build_int_cst (TREE_TYPE (bound), + arg->expr->rank - 1)); + cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, + logical_type_node, cond, cond1); } - else - tmp = ubound; - se->expr = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond, - tmp, gfc_index_zero_node); + lbound, gfc_index_one_node); } + else if (op == GFC_ISYM_SHAPE) + se->expr = size; else - { - if (as->type == AS_ASSUMED_SIZE) - cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, - bound, build_int_cst (TREE_TYPE (bound), - arg->expr->rank - 1)); - else - cond = logical_false_node; + gcc_unreachable (); - cond1 = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond3, cond4); - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, + /* According to F2018 16.9.172, para 5, an assumed rank object, + argument associated with and assumed size array, has the ubound + of the final dimension set to -1 and UBOUND must return this. + Similarly for the SHAPE intrinsic. */ + if (op != GFC_ISYM_LBOUND && assumed_rank_lb_one) + { + tree minus_one = build_int_cst (gfc_array_index_type, -1); + tree rank = fold_convert (gfc_array_index_type, + gfc_conv_descriptor_rank (desc)); + rank = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, rank, minus_one); + + /* Fix the expression to stop it from becoming even more + complicated. */ + se->expr = gfc_evaluate_now (se->expr, &se->pre); + + /* Descriptors for assumed-size arrays have ubound = -1 + in the last dimension. */ + cond1 = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, ubound, minus_one); + cond = fold_build2_loc (input_location, EQ_EXPR, + logical_type_node, bound, rank); + cond = fold_build2_loc (input_location, TRUTH_AND_EXPR, logical_type_node, cond, cond1); - se->expr = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type, cond, - lbound, gfc_index_one_node); + minus_one, se->expr); } } - else + else /* as is null; this is an old-fashioned 1-based array. */ { - if (upper) + if (op != GFC_ISYM_LBOUND) { - size = fold_build2_loc (input_location, MINUS_EXPR, - gfc_array_index_type, ubound, lbound); - se->expr = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, size, - gfc_index_one_node); se->expr = fold_build2_loc (input_location, MAX_EXPR, - gfc_array_index_type, se->expr, + gfc_array_index_type, size, gfc_index_zero_node); } else se->expr = gfc_index_one_node; } - /* According to F2018 16.9.172, para 5, an assumed rank object, argument - associated with and assumed size array, has the ubound of the final - dimension set to -1 and UBOUND must return this. */ - if (upper && as && as->type == AS_ASSUMED_RANK) - { - tree minus_one = build_int_cst (gfc_array_index_type, -1); - tree rank = fold_convert (gfc_array_index_type, - gfc_conv_descriptor_rank (desc)); - rank = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, rank, minus_one); - /* Fix the expression to stop it from becoming even more complicated. */ - se->expr = gfc_evaluate_now (se->expr, &se->pre); - cond = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, bound, rank); - cond1 = fold_build2_loc (input_location, NE_EXPR, - logical_type_node, ubound, minus_one); - cond = fold_build2_loc (input_location, TRUTH_OR_EXPR, - logical_type_node, cond, cond1); - se->expr = fold_build3_loc (input_location, COND_EXPR, - gfc_array_index_type, cond, - se->expr, minus_one); - } type = gfc_typenode_for_spec (&expr->ts); se->expr = convert (type, se->expr); @@ -6691,85 +6674,6 @@ gfc_conv_intrinsic_ibits (gfc_se * se, gfc_expr * expr) } static void -gfc_conv_intrinsic_shape (gfc_se *se, gfc_expr *expr) -{ - gfc_actual_arglist *s, *k; - gfc_expr *e; - gfc_array_spec *as; - gfc_ss *ss; - symbol_attribute attr; - tree result_desc = se->expr; - - /* Remove the KIND argument, if present. */ - s = expr->value.function.actual; - k = s->next; - e = k->expr; - gfc_free_expr (e); - k->expr = NULL; - - gfc_conv_intrinsic_funcall (se, expr); - - /* According to F2018 16.9.172, para 5, an assumed rank entity, argument - associated with an assumed size array, has the ubound of the final - dimension set to -1 and SHAPE must return this. */ - - as = gfc_get_full_arrayspec_from_expr (s->expr); - if (!as || as->type != AS_ASSUMED_RANK) - return; - attr = gfc_expr_attr (s->expr); - ss = gfc_walk_expr (s->expr); - if (attr.pointer || attr.allocatable - || !ss || ss->info->type != GFC_SS_SECTION) - return; - if (se->expr) - result_desc = se->expr; - if (POINTER_TYPE_P (TREE_TYPE (result_desc))) - result_desc = build_fold_indirect_ref_loc (input_location, result_desc); - if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (result_desc))) - { - tree rank, minus_one, cond, ubound, tmp; - stmtblock_t block; - gfc_se ase; - - minus_one = build_int_cst (gfc_array_index_type, -1); - - /* Recover the descriptor for the array. */ - gfc_init_se (&ase, NULL); - ase.descriptor_only = 1; - gfc_conv_expr_lhs (&ase, ss->info->expr); - - /* Obtain rank-1 so that we can address both descriptors. */ - rank = gfc_conv_descriptor_rank (ase.expr); - rank = fold_convert (gfc_array_index_type, rank); - rank = fold_build2_loc (input_location, PLUS_EXPR, - gfc_array_index_type, - rank, minus_one); - rank = gfc_evaluate_now (rank, &se->pre); - - /* The ubound for the final dimension will be tested for being -1. */ - ubound = gfc_conv_descriptor_ubound_get (ase.expr, rank); - ubound = gfc_evaluate_now (ubound, &se->pre); - cond = fold_build2_loc (input_location, EQ_EXPR, - logical_type_node, - ubound, minus_one); - - /* Obtain the last element of the result from the library shape - intrinsic and set it to -1 if that is the value of ubound. */ - tmp = gfc_conv_array_data (result_desc); - tmp = build_fold_indirect_ref_loc (input_location, tmp); - tmp = gfc_build_array_ref (tmp, rank, NULL, NULL); - - gfc_init_block (&block); - gfc_add_modify (&block, tmp, build_int_cst (TREE_TYPE (tmp), -1)); - - cond = build3_v (COND_EXPR, cond, - gfc_finish_block (&block), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&se->pre, cond); - } -} - -static void gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift, bool arithmetic) { @@ -10178,10 +10082,6 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_minmaxloc (se, expr, GT_EXPR); break; - case GFC_ISYM_SHAPE: - gfc_conv_intrinsic_shape (se, expr); - break; - default: gfc_conv_intrinsic_funcall (se, expr); break; @@ -10575,7 +10475,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) break; case GFC_ISYM_LBOUND: - gfc_conv_intrinsic_bound (se, expr, 0); + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_LBOUND); break; case GFC_ISYM_LCOBOUND: @@ -10710,6 +10610,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_scale (se, expr); break; + case GFC_ISYM_SHAPE: + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_SHAPE); + break; + case GFC_ISYM_SIGN: gfc_conv_intrinsic_sign (se, expr); break; @@ -10756,7 +10660,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) break; case GFC_ISYM_UBOUND: - gfc_conv_intrinsic_bound (se, expr, 1); + gfc_conv_intrinsic_bound (se, expr, GFC_ISYM_UBOUND); break; case GFC_ISYM_UCOBOUND: @@ -11030,6 +10934,7 @@ gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss) case GFC_ISYM_UCOBOUND: case GFC_ISYM_LCOBOUND: case GFC_ISYM_THIS_IMAGE: + case GFC_ISYM_SHAPE: break; default: @@ -11038,8 +10943,8 @@ gfc_add_intrinsic_ss_code (gfc_loopinfo * loop ATTRIBUTE_UNUSED, gfc_ss * ss) } -/* The LBOUND, LCOBOUND, UBOUND and UCOBOUND intrinsics with one parameter - are expanded into code inside the scalarization loop. */ +/* The LBOUND, LCOBOUND, UBOUND, UCOBOUND, and SHAPE intrinsics with + one parameter are expanded into code inside the scalarization loop. */ static gfc_ss * gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr) @@ -11048,7 +10953,8 @@ gfc_walk_intrinsic_bound (gfc_ss * ss, gfc_expr * expr) gfc_add_class_array_ref (expr->value.function.actual->expr); /* The two argument version returns a scalar. */ - if (expr->value.function.actual->next->expr) + if (expr->value.function.isym->id != GFC_ISYM_SHAPE + && expr->value.function.actual->next->expr) return ss; return gfc_get_array_ss (ss, expr, 1, GFC_SS_INTRINSIC); @@ -11148,7 +11054,6 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) case GFC_ISYM_PARITY: case GFC_ISYM_PRODUCT: case GFC_ISYM_SUM: - case GFC_ISYM_SHAPE: case GFC_ISYM_SPREAD: case GFC_ISYM_YN2: /* Ignore absent optional parameters. */ @@ -11198,6 +11103,7 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr, case GFC_ISYM_UBOUND: case GFC_ISYM_UCOBOUND: case GFC_ISYM_THIS_IMAGE: + case GFC_ISYM_SHAPE: return gfc_walk_intrinsic_bound (ss, expr); case GFC_ISYM_TRANSFER: diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 4f1b346..e81c558 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -6407,12 +6407,17 @@ gfc_trans_omp_task (gfc_code *code) static tree gfc_trans_omp_taskgroup (gfc_code *code) { + stmtblock_t block; + gfc_start_block (&block); tree body = gfc_trans_code (code->block->next); tree stmt = make_node (OMP_TASKGROUP); TREE_TYPE (stmt) = void_type_node; OMP_TASKGROUP_BODY (stmt) = body; - OMP_TASKGROUP_CLAUSES (stmt) = NULL_TREE; - return stmt; + OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, + code->ext.omp_clauses, + code->loc); + gfc_add_expr_to_block (&block, stmt); + return gfc_finish_block (&block); } static tree @@ -6995,7 +7000,11 @@ gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) res = gfc_trans_omp_directive (code); ompws_flags = saved_ompws_flags; break; - + + case EXEC_BLOCK: + res = gfc_trans_block_construct (code); + break; + default: gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); } diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 50fceeb..4277806 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -3014,7 +3014,11 @@ create_fn_spec (gfc_symbol *sym, tree fntype) } if (sym->ts.type == BT_CHARACTER) { - spec[spec_len++] = 'R'; + if (!sym->ts.u.cl->length + && (sym->attr.allocatable || sym->attr.pointer)) + spec[spec_len++] = 'w'; + else + spec[spec_len++] = 'R'; spec[spec_len++] = ' '; } } diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 85ef974..93d6da6 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -180,9 +180,9 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name) int_range_max edge_range; gcc_checking_assert (irange::supports_type_p (TREE_TYPE (name))); - // Do not process values along abnormal or EH edges. - if (e->flags & (EDGE_ABNORMAL|EDGE_EH)) - return false; + // Do not process values along abnormal edges. + if (e->flags & EDGE_ABNORMAL) + return get_tree_range (r, name, NULL); unsigned idx; if ((idx = tracer.header ("range_on_edge ("))) @@ -203,7 +203,7 @@ gimple_ranger::range_on_edge (irange &r, edge e, tree name) bool res = true; if (!gimple_range_ssa_p (name)) - res = range_of_expr (r, name); + return get_tree_range (r, name, NULL); else { range_on_exit (r, e->src, name); @@ -258,7 +258,7 @@ gimple_ranger::range_of_stmt (irange &r, gimple *s, tree name) if (!name) res = fold_range_internal (r, s, NULL_TREE); else if (!gimple_range_ssa_p (name)) - res = false; + res = get_tree_range (r, name, NULL); // Check if the stmt has already been processed, and is not stale. else if (m_cache.get_non_stale_global_range (r, name)) { diff --git a/gcc/match.pd b/gcc/match.pd index 3ff15bc..5bed2e1 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3606,6 +3606,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) >= inside_prec - !inside_unsignedp) (convert @0))))))) +/* (float_type)(integer_type) x -> trunc (x) if the type of x matches + float_type. Only do the transformation if we do not need to preserve + trapping behaviour, so require !flag_trapping_math. */ +#if GIMPLE +(simplify + (float (fix_trunc @0)) + (if (!flag_trapping_math + && types_match (type, TREE_TYPE (@0)) + && direct_internal_fn_supported_p (IFN_TRUNC, type, + OPTIMIZE_FOR_BOTH)) + (IFN_TRUNC @0))) +#endif + /* If we have a narrowing conversion to an integral type that is fed by a BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely masks off bits outside the final type (and nothing else). */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 057b7ae..15e4424 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -591,7 +591,15 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) tree copy = copy_var_decl (var, name, type); DECL_CONTEXT (copy) = current_function_decl; - DECL_CHAIN (copy) = ctx->block_vars; + + if (ctx) + { + DECL_CHAIN (copy) = ctx->block_vars; + ctx->block_vars = copy; + } + else + record_vars (copy); + /* If VAR is listed in task_shared_vars, it means it wasn't originally addressable and is just because task needs to take it's address. But we don't need to take address of privatizations @@ -602,7 +610,6 @@ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) || (global_nonaddressable_vars && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var))))) TREE_ADDRESSABLE (copy) = 0; - ctx->block_vars = copy; return copy; } @@ -1281,7 +1288,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) tree at = t; if (ctx->outer) scan_omp_op (&at, ctx->outer); - tree nt = omp_copy_decl_1 (at, ctx); + tree nt = omp_copy_decl_1 (at, ctx->outer); splay_tree_insert (ctx->field_map, (splay_tree_key) &DECL_CONTEXT (t), (splay_tree_value) nt); @@ -1322,7 +1329,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) tree at = decl; if (ctx->outer) scan_omp_op (&at, ctx->outer); - tree nt = omp_copy_decl_1 (at, ctx); + tree nt = omp_copy_decl_1 (at, ctx->outer); splay_tree_insert (ctx->field_map, (splay_tree_key) &DECL_CONTEXT (decl), (splay_tree_value) nt); diff --git a/gcc/params.opt b/gcc/params.opt index 06a6fdc..83b3db6 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -533,6 +533,10 @@ The maximum number of nested indirect inlining performed by early inliner. Common Joined UInteger Var(param_max_fields_for_field_sensitive) Param Maximum number of fields in a structure before pointer analysis treats the structure as a single variable. +-param=max-fsm-thread-length= +Common Joined UInteger Var(param_max_fsm_thread_length) Init(10) IntegerRange(1, 999999) Param Optimization +Maximum number of basic blocks on a jump thread path. + -param=max-fsm-thread-path-insns= Common Joined UInteger Var(param_max_fsm_thread_path_insns) Init(100) IntegerRange(1, 999999) Param Optimization Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path. diff --git a/gcc/passes.def b/gcc/passes.def index c11c237..4c54176 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -339,9 +339,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_thread_jumps); NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */); NEXT_PASS (pass_vrp_threader); - /* Threading can leave many const/copy propagations in the IL. - Clean them up. Instead of just copy_prop, we use ccp to - compute alignment and nonzero bits. */ + /* Run CCP to compute alignment and nonzero bits. */ NEXT_PASS (pass_ccp, true /* nonzero_p */); NEXT_PASS (pass_warn_restrict); NEXT_PASS (pass_dse); diff --git a/gcc/target.def b/gcc/target.def index b9bc7fd..927ebfc 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4717,45 +4717,6 @@ not generate any instructions in this case.", default_setup_incoming_varargs) DEFHOOK -(load_bounds_for_arg, - "This hook is used by expand pass to emit insn to load bounds of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -bounds of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then bounds are loaded as for regular pointer loaded from\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to obtain bounds. Hook returns RTX holding loaded bounds.", - rtx, (rtx slot, rtx arg, rtx slot_no), - default_load_bounds_for_arg) - -DEFHOOK -(store_bounds_for_arg, - "This hook is used by expand pass to emit insns to store @var{bounds} of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then @var{bounds} are stored as for regular pointer stored in\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to store @var{bounds}.", - void, (rtx arg, rtx slot, rtx bounds, rtx slot_no), - default_store_bounds_for_arg) - -DEFHOOK -(load_returned_bounds, - "This hook is used by expand pass to emit insn to load bounds\n\ -returned by function call in @var{slot}. Hook returns RTX holding\n\ -loaded bounds.", - rtx, (rtx slot), - default_load_returned_bounds) - -DEFHOOK -(store_returned_bounds, - "This hook is used by expand pass to emit insn to store @var{bounds}\n\ -returned by function call into @var{slot}.", - void, (rtx slot, rtx bounds), - default_store_returned_bounds) - -DEFHOOK (call_args, "While generating RTL for a function call, this target hook is invoked once\n\ for each argument passed to the function, either a register returned by\n\ @@ -4958,12 +4919,6 @@ The return value is usually either a @code{reg} RTX for the hard\n\ register in which to pass the argument, or zero to pass the argument\n\ on the stack.\n\ \n\ -The return value can be a @code{const_int} which means argument is\n\ -passed in a target specific slot with specified number. Target hooks\n\ -should be used to store or load argument in such case. See\n\ -@code{TARGET_STORE_BOUNDS_FOR_ARG} and @code{TARGET_LOAD_BOUNDS_FOR_ARG}\n\ -for more information.\n\ -\n\ The value of the expression can also be a @code{parallel} RTX@. This is\n\ used when an argument is passed in multiple locations. The mode of the\n\ @code{parallel} should be the mode of the entire argument. The\n\ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 812bbe3..0b525bb 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -2253,36 +2253,6 @@ default_member_type_forces_blk (const_tree, machine_mode) return false; } -rtx -default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED, - rtx ptr ATTRIBUTE_UNUSED, - rtx bnd ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -void -default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED, - rtx addr ATTRIBUTE_UNUSED, - rtx bounds ATTRIBUTE_UNUSED, - rtx to ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -rtx -default_load_returned_bounds (rtx slot ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -void -default_store_returned_bounds (rtx slot ATTRIBUTE_UNUSED, - rtx bounds ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - /* Default version of canonicalize_comparison. */ void diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 92d5199..7f7f25a 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -272,10 +272,6 @@ extern bool can_use_doloop_if_innermost (const widest_int &, const widest_int &, unsigned int, bool); -extern rtx default_load_bounds_for_arg (rtx, rtx, rtx); -extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx); -extern rtx default_load_returned_bounds (rtx); -extern void default_store_returned_bounds (rtx,rtx); extern bool default_optab_supported_p (int, machine_mode, machine_mode, optimization_type); extern unsigned int default_max_noce_ifcvt_seq_cost (edge); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2876c7a..602b727 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,341 @@ +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/mvn-cmeq0-1.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/narrow_high_combine.c: Update case. + * gcc.target/aarch64/xtn-combine-1.c: New test. + * gcc.target/aarch64/xtn-combine-2.c: New test. + * gcc.target/aarch64/xtn-combine-3.c: New test. + * gcc.target/aarch64/xtn-combine-4.c: New test. + * gcc.target/aarch64/xtn-combine-5.c: New test. + * gcc.target/aarch64/xtn-combine-6.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shl-combine-2.c: New test. + * gcc.target/aarch64/shl-combine-3.c: New test. + * gcc.target/aarch64/shl-combine-4.c: New test. + * gcc.target/aarch64/shl-combine-5.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shrn-combine-10.c: New test. + * gcc.target/aarch64/shrn-combine-5.c: New test. + * gcc.target/aarch64/shrn-combine-6.c: New test. + * gcc.target/aarch64/shrn-combine-7.c: New test. + * gcc.target/aarch64/shrn-combine-8.c: New test. + * gcc.target/aarch64/shrn-combine-9.c: New test. + +2021-10-20 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/shrn-combine-1.c: New test. + * gcc.target/aarch64/shrn-combine-2.c: New test. + * gcc.target/aarch64/shrn-combine-3.c: New test. + * gcc.target/aarch64/shrn-combine-4.c: New test. + +2021-10-20 Chung-Lin Tang <cltang@codesourcery.com> + + * gfortran.dg/gomp/reduction4.f90: Adjust omp target in_reduction' scan + pattern. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-20 Martin Liska <mliska@suse.cz> + + PR target/102374 + * gcc.target/i386/pr102374.c: New test. + +2021-10-20 Martin Liska <mliska@suse.cz> + + Revert: + 2021-10-20 Martin Liska <mliska@suse.cz> + + PR target/102375 + * gcc.target/aarch64/pr102375.c: New test. + +2021-10-20 Wilco Dijkstra <wdijkstr@arm.com> + + PR target/100966 + * gcc.target/aarch64/frint.x: Add roundeven tests. + * gcc.target/aarch64/frint_double.c: Likewise. + * gcc.target/aarch64/frint_float.c: Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * gcc.target/aarch64/fmla_intrinsic_1.c: prevent over optimization. + * gcc.target/aarch64/fmls_intrinsic_1.c: Likewise. + * gcc.target/aarch64/fmul_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mla_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mls_intrinsic_1.c: Likewise. + * gcc.target/aarch64/mul_intrinsic_1.c: Likewise. + * gcc.target/aarch64/simd/vmul_elem_1.c: Likewise. + * gcc.target/aarch64/vclz.c: Likewise. + * gcc.target/aarch64/vneg_s.c: Likewise. + +2021-10-20 Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com> + + * gcc.target/aarch64/merge_trunc1.c: New test. + +2021-10-20 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/pr102764.c: New test. + +2021-10-20 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102815 + * gfortran.dg/bind-c-contiguous-5.c (do_call, reset_var): Handle + big andian. + +2021-10-20 Jakub Jelinek <jakub@redhat.com> + + PR c++/102642 + * g++.dg/tls/pr102642.C: New test. + +2021-10-20 Aldy Hernandez <aldyh@redhat.com> + Richard Biener <rguenther@suse.de> + + * gcc.dg/Warray-bounds-87.c: Remove xfail. + * gcc.dg/analyzer/pr94851-2.c: Remove xfail. + * gcc.dg/graphite/pr69728.c: Remove xfail. + * gcc.dg/graphite/scop-dsyr2k.c: Remove xfail. + * gcc.dg/graphite/scop-dsyrk.c: Remove xfail. + * gcc.dg/shrink-wrap-loop.c: Remove xfail. + * gcc.dg/loop-8.c: Adjust for new threading restrictions. + * gcc.dg/tree-ssa/ifc-20040816-1.c: Same. + * gcc.dg/tree-ssa/pr21559.c: Same. + * gcc.dg/tree-ssa/pr59597.c: Same. + * gcc.dg/tree-ssa/pr71437.c: Same. + * gcc.dg/tree-ssa/pr77445-2.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-4.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Same. + * gcc.dg/vect/bb-slp-16.c: Same. + * gcc.dg/tree-ssa/ssa-dom-thread-6.c: Remove. + * gcc.dg/tree-ssa/ssa-dom-thread-18.c: Remove. + * gcc.dg/tree-ssa/ssa-dom-thread-2a.c: Remove. + * gcc.dg/tree-ssa/ssa-thread-invalid.c: New test. + +2021-10-20 Jeff Law <jeffreyalaw@gmail.com> + + * gcc.dg/plugin/gil-1.c: Add dg-require-effective-target marker. + +2021-10-20 Hongtao Liu <hongtao.liu@intel.com> + Kewen Lin <linkw@linux.ibm.com> + + PR middle-end/102722 + PR middle-end/102697 + PR middle-end/102462 + PR middle-end/102706 + PR middle-end/102744 + * c-c++-common/Wstringop-overflow-2.c: Adjust testcase with new + xfail/target selector. + * gcc.dg/Warray-bounds-51.c: Ditto. + * gcc.dg/Warray-parameter-3.c: Ditto. + * gcc.dg/Wstringop-overflow-14.c: Ditto. + * gcc.dg/Wstringop-overflow-21.c: Ditto. + * gcc.dg/Wstringop-overflow-68.c: Ditto. + * gcc.dg/Wstringop-overflow-76.c: Ditto. + * gcc.dg/Warray-bounds-48.c: Ditto. + * gcc.dg/Wzero-length-array-bounds-2.c: Ditto. + * lib/target-supports.exp (check_vect_slp_aligned_store_usage): + New function. + (check_effective_target_vect_slp_v2qi_store): Ditto. + (check_effective_target_vect_slp_v4qi_store): Ditto. + (check_effective_target_vect_slp_v8qi_store): Ditto. + (check_effective_target_vect_slp_v16qi_store): Ditto. + (check_effective_target_vect_slp_v2hi_store): Ditto. + (check_effective_target_vect_slp_v4hi_store): Ditto. + (check_effective_target_vect_slp_v2si_store): Ditto. + (check_effective_target_vect_slp_v4si_store): Ditto. + * c-c++-common/Wstringop-overflow-2-novec.c: New test. + * gcc.dg/Warray-bounds-51-novec.c: New test. + * gcc.dg/Warray-bounds-48-novec.c: New test. + * gcc.dg/Warray-parameter-3-novec.c: New test. + * gcc.dg/Wstringop-overflow-14-novec.c: New test. + * gcc.dg/Wstringop-overflow-21-novec.c: New test. + * gcc.dg/Wstringop-overflow-76-novec.c: New test. + * gcc.dg/Wzero-length-array-bounds-2-novec.c: New test. + +2021-10-19 Paul A. Clarke <pc@us.ibm.com> + + * gcc.target/powerpc/sse4_2-pcmpgtq.c: Tighten dg constraints + to minimally Power8. + +2021-10-19 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/92482 + * gfortran.dg/bind-c-char-descr.f90: Remove xfail; extend a bit. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102375 + * gcc.target/aarch64/pr102375.c: New test. + +2021-10-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102827 + * gcc.dg/pr102827.c: New testcase. + +2021-10-19 Xionghu Luo <luoxhu@linux.ibm.com> + + * gcc.target/powerpc/builtins-1.c: Update instruction counts. + +2021-10-19 Haochen Gui <guihaoc@gcc.gnu.org> + + * gcc.target/powerpc/p10_vec_xl_sext.c: New test. + +2021-10-19 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gcc.target/aarch64/sve/pr93183.c: Remove -mcpu=generic+sve from dg-options. + +2021-10-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/102786 + * g++.dg/cpp2a/constexpr-virtual19.C: New test. + +2021-10-19 Martin Liska <mliska@suse.cz> + + PR target/102374 + * gcc.target/i386/pr102374.c: New test. + +2021-10-19 dianhong xu <dianhong.xu@intel.com> + + * gcc.target/i386/avx512fp16-set1-pch-1a.c: New test. + * gcc.target/i386/avx512fp16-set1-pch-1b.c: New test. + * gcc.target/i386/avx512fp16vl-set1-pch-1a.c: New test. + * gcc.target/i386/avx512fp16vl-set1-pch-1b.c: New test. + +2021-10-18 Andrew MacLeod <amacleod@redhat.com> + + PR tree-optimization/102796 + * g++.dg/pr102796.C: New. + +2021-10-18 Kwok Cheung Yeung <kcy@codesourcery.com> + + * gfortran.dg/gomp/declare-variant-15.f90 (variant2, base2, test2): + Add tests. + * gfortran.dg/gomp/declare-variant-16.f90 (base2, variant2, test2): + Add tests. + +2021-10-18 Uroš Bizjak <ubizjak@gmail.com> + + PR target/102761 + * gcc.target/i386/pr102761.c: New test. + +2021-10-18 Jason Merrill <jason@redhat.com> + + * g++.dg/template/crash90.C: Check location of pedwarn. + +2021-10-18 H.J. Lu <hjl.tools@gmail.com> + + * gcc.target/i386/387-12.c (dg-do compile): Require ia32. + (dg-options): Remove -m32. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/i386/387-12.c: Add explicit -m32 option. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/bfin/ones.c: New test case. + * gcc.target/bfin/parity.c: New test case. + * gcc.target/bfin/popcount.c: New test case. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102788 + * g++.dg/vect/pr102788.cc: New testcase. + +2021-10-18 Roger Sayle <roger@nextmovesoftware.com> + + * gcc.target/bfin/ssabs.c: New test case. + * gcc.target/bfin/ssneg.c: New test case. + +2021-10-18 prathamesh.kulkarni <prathamesh.kulkarni@linaro.org> + + PR target/93183 + * gcc.target/aarch64/sve/cond_unary_4.c: Adjust. + * gcc.target/aarch64/sve/pr93183.c: New test. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102086 + PR fortran/92189 + PR fortran/92621 + PR fortran/101308 + PR fortran/101309 + PR fortran/101635 + PR fortran/92482 + * gfortran.dg/ISO_Fortran_binding_4.f90: Extend testcase. + * gfortran.dg/PR100914.f90: Remove xfail. + * gfortran.dg/PR100915.c: Expect CFI_type_cfunptr. + * gfortran.dg/PR100915.f90: Handle CFI_type_cfunptr != CFI_type_cptr. + * gfortran.dg/PR93963.f90: Extend select-rank tests. + * gfortran.dg/bind-c-intent-out.f90: Change to dg-do run, + update scan-dump. + * gfortran.dg/bind_c_array_params_2.f90: Update/extend scan-dump. + * gfortran.dg/bind_c_char_10.f90: Update scan-dump. + * gfortran.dg/bind_c_char_8.f90: Remove dg-error "sorry". + * gfortran.dg/c-interop/allocatable-dummy.f90: Remove xfail. + * gfortran.dg/c-interop/c1255-1.f90: Likewise. + * gfortran.dg/c-interop/c407c-1.f90: Update dg-error. + * gfortran.dg/c-interop/cf-descriptor-5.f90: Remove xfail. + * gfortran.dg/c-interop/cf-out-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/cf-out-descriptor-4.f90: Likewise. + * gfortran.dg/c-interop/cf-out-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/contiguous-2.f90: Likewise. + * gfortran.dg/c-interop/contiguous-3.f90: Likewise. + * gfortran.dg/c-interop/deferred-character-1.f90: Likewise. + * gfortran.dg/c-interop/deferred-character-2.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-3.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-4.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/fc-out-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/ff-descriptor-5.f90: Likewise. + * gfortran.dg/c-interop/ff-descriptor-6.f90: Likewise. + * gfortran.dg/c-interop/fc-descriptor-7.f90: Remove xfail + extend. + * gfortran.dg/c-interop/fc-descriptor-7-c.c: Update for changes. + * gfortran.dg/c-interop/shape.f90: Add implicit none. + * gfortran.dg/c-interop/typecodes-array-char-c.c: Add kind=4 char. + * gfortran.dg/c-interop/typecodes-array-char.f90: Likewise. + * gfortran.dg/c-interop/typecodes-array-float128.f90: Remove xfail. + * gfortran.dg/c-interop/typecodes-scalar-basic.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-float128.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-int128.f90: Likewise. + * gfortran.dg/c-interop/typecodes-scalar-longdouble.f90: Likewise. + * gfortran.dg/iso_c_binding_char_1.f90: Remove dg-error "sorry". + * gfortran.dg/pr93792.f90: Turn XFAIL into PASS. + * gfortran.dg/ISO_Fortran_binding_19.f90: New test. + * gfortran.dg/assumed_type_12.f90: New test. + * gfortran.dg/assumed_type_13.c: New test. + * gfortran.dg/assumed_type_13.f90: New test. + * gfortran.dg/bind-c-char-descr.f90: New test. + * gfortran.dg/bind-c-contiguous-1.c: New test. + * gfortran.dg/bind-c-contiguous-1.f90: New test. + * gfortran.dg/bind-c-contiguous-2.f90: New test. + * gfortran.dg/bind-c-contiguous-3.c: New test. + * gfortran.dg/bind-c-contiguous-3.f90: New test. + * gfortran.dg/bind-c-contiguous-4.c: New test. + * gfortran.dg/bind-c-contiguous-4.f90: New test. + * gfortran.dg/bind-c-contiguous-5.c: New test. + * gfortran.dg/bind-c-contiguous-5.f90: New test. + +2021-10-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/102798 + * gcc.dg/pr102798.c: New testcase. + +2021-10-18 Tobias Burnus <tobias@codesourcery.com> + + PR fortran/102745 + * gfortran.dg/class_72.f90: New. + 2021-10-15 Jason Merrill <jason@redhat.com> PR c++/51851 diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c new file mode 100644 index 0000000..3c34ad3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2-novec.c @@ -0,0 +1,126 @@ +/* PR middle-end/91458 - inconsistent warning for writing past the end + of an array member + { dg-do compile } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds -fno-ipa-icf" } */ + +void sink (void*); + +// Exercise trailing one-element array members. + +struct A1 +{ + char n; + char a[1]; // { dg-message "destination object" "note" } +}; + +// Verify warning for access to a definition with an initializer that doesn't +// initialize the one-element array member. +struct A1 a1__ = { 0 }; + +void ga1__ (void) +{ + a1__.a[0] = 0; + a1__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 1 }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member to empty. +struct A1 a1_0 = { 0, { } }; + +void ga1_0_ (void) +{ + a1_0.a[0] = 0; + a1_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 1, { } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member. +struct A1 a1_1 = { 0, { 1 } }; + +void ga1_1 (void) +{ + a1_1.a[0] = 0; + a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { 1 } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Exercise interior one-element array members (verify they're not +// treated as trailing. + +struct A1i +{ + char n; + char a[1]; // { dg-message "destination object" } + char x; +}; + +// Verify warning for access to a definition with an initializer that doesn't +// initialize the one-element array member. +struct A1i a1i__ = { 0 }; + +void ga1i__ (void) +{ + a1i__.a[0] = 0; + a1i__.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i__.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1i a = { 0 }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member to empty. +struct A1 a1i_0 = { 0, { } }; + +void ga1i_0_ (void) +{ + a1i_0.a[0] = 0; + a1i_0.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i_0.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { } }; + a.a[0] = 0; + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} + +// Verify warning for access to a definition with an initializer that +// initializes the one-element array member. +struct A1 a1i_1 = { 0, { 1 } }; + +void ga1i_1 (void) +{ + a1i_1.a[0] = 0; + a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + + struct A1 a = { 0, { 1 } }; + a.a[0] = 1; + a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" } + sink (&a); +} diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c index 7d29b5f..ca38bda 100644 --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c @@ -190,7 +190,7 @@ void ga1__ (void) struct A1 a = { 1 }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -207,7 +207,7 @@ void ga1_0_ (void) struct A1 a = { 1, { } }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -221,10 +221,10 @@ void ga1_1 (void) a1_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } - struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } a.a[0] = 0; - a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { vect_slp_v4qi_store } } } sink (&a); } @@ -289,7 +289,7 @@ void ga1i__ (void) struct A1i a = { 0 }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -306,7 +306,7 @@ void ga1i_0_ (void) struct A1 a = { 0, { } }; a.a[0] = 0; a.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } - a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v2qi_store } } } sink (&a); } @@ -320,10 +320,10 @@ void ga1i_1 (void) a1i_1.a[1] = 1; // { dg-warning "\\\[-Wstringop-overflow" } a1i_1.a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } - struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + struct A1 a = { 0, { 1 } }; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { target { vect_slp_v4qi_store } } } a.a[0] = 1; - a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } - a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + a.a[1] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v4qi_store } } } + a.a[2] = 3; // { dg-warning "\\\[-Wstringop-overflow" "pr102462" { xfail { vect_slp_v4qi_store } } } sink (&a); } diff --git a/gcc/testsuite/c-c++-common/ubsan/pr64888.c b/gcc/testsuite/c-c++-common/ubsan/pr64888.c new file mode 100644 index 0000000..6319c2f --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr64888.c @@ -0,0 +1,27 @@ +/* PR middle-end/64888 */ +/* { dg-do compile { target fopenmp } } */ +/* { dg-options "-fopenmp -fsanitize=undefined" } */ + +int a, b; + +void +foo () +{ + int c; +#pragma omp parallel default (none) shared (a, b) private (c) + { + c = a / b; /* { dg-bogus "not specified in enclosing" } */ + (void) c; + } +#pragma omp task default (none) shared (a, b) private (c) + { + c = a << b; /* { dg-bogus "not specified in enclosing" } */ + (void) c; + } +#pragma omp teams default (none) shared (a, b) + { + int d[a]; /* { dg-bogus "not specified in enclosing" } */ + d[0] = 0; + (void) d[0]; + } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C new file mode 100644 index 0000000..cb0d1be --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual19.C @@ -0,0 +1,11 @@ +// PR c++/102786 +// { dg-do compile { target c++20 } } + +struct S { + virtual constexpr int foo () const { return 42; } +}; + +constexpr S s; +constexpr auto a = &S::foo; +constexpr auto b = (s.*a) (); +constexpr auto c = (s.*&S::foo) (); diff --git a/gcc/testsuite/g++.dg/pr102796.C b/gcc/testsuite/g++.dg/pr102796.C new file mode 100644 index 0000000..6ad1008 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr102796.C @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-O3 -fno-tree-ccp -fno-tree-fre -fno-tree-forwprop -std=c++17" } + +namespace std { +template <class _E> +struct initializer_list { + const int* __begin_; + decltype(sizeof(int)) __size_; +}; +} // namespace std +struct destroyme1 {}; +struct witharg1 { + witharg1(const destroyme1&); + ~witharg1(); +}; +std::initializer_list globalInitList2 = {witharg1(destroyme1()), + witharg1(destroyme1())}; + diff --git a/gcc/testsuite/g++.dg/template/crash90.C b/gcc/testsuite/g++.dg/template/crash90.C index 125ab0a..fee7dc5 100644 --- a/gcc/testsuite/g++.dg/template/crash90.C +++ b/gcc/testsuite/g++.dg/template/crash90.C @@ -4,5 +4,6 @@ template < unsigned > struct A ; template < typename > struct B ; -template < typename T , A < B < T > {} // { dg-error "parse error|non-type|initializer" } +template < typename T , A < B < T > {} // { dg-error "parse error|non-type" } // { dg-error "39:expected" "" { target *-*-* } .-1 } +// { dg-error "37:initializer list" "" { target c++98_only } .-2 } diff --git a/gcc/testsuite/g++.dg/tls/pr102642.C b/gcc/testsuite/g++.dg/tls/pr102642.C new file mode 100644 index 0000000..e3236d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/tls/pr102642.C @@ -0,0 +1,10 @@ +// PR c++/102642 +// { dg-do compile { target c++11 } } + +thread_local int *z; // { dg-message "previous declaration" } + +void +foo () +{ + extern thread_local int z; // { dg-error "conflicting declaration" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c new file mode 100644 index 0000000..da179a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48-novec.c @@ -0,0 +1,364 @@ +/* PR middle-end/91647 - missing -Warray-bounds accessing a zero-length array + of a declared object + { dg-do "compile" } + { dg-options "-O2 -Wall -fno-tree-vectorize" } + { dg-require-effective-target alloca } */ + +typedef __INT16_TYPE__ int16_t; +typedef __INT32_TYPE__ int32_t; + +void sink (void*); + +/* Exercise a true flexible member. */ + +struct AX +{ + int32_t n; + int16_t ax[]; // { dg-message "while referencing 'ax'" "member" } +}; + +static void warn_ax_local (struct AX *p) +{ + p->ax[0] = 0; // { dg-warning "\\\[-Warray-bounds" } + p->ax[1] = 1; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_ax_extern (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +static void warn_ax_local_buf (struct AX *p) +{ + p->ax[0] = 4; p->ax[1] = 5; + + p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } + p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } + p->ax[4] = 8; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_ax_extern_buf (struct AX *p) +{ + p->ax[0] = 9; p->ax[1] = 10; p->ax[2] = 11; + + p->ax[3] = 12; // { dg-warning "\\\[-Warray-bounds" } + p->ax[4] = 13; // { dg-warning "\\\[-Warray-bounds" } + p->ax[5] = 14; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_ax_extern_bufx (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +static void nowarn_ax_ref (struct AX *p) +{ + p->ax[0] = 0; p->ax[99] = 99; p->ax[999] = 999; p->ax[9999] = 9999; +} + +void test_ax (struct AX *p, unsigned n) +{ + { + struct AX sax; // { dg-message "defined here" "struct definition" } + warn_ax_local (&sax); + sink (&sax); + } + + { + extern + struct AX xsax; + nowarn_ax_extern (&xsax); + sink (&xsax); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char ax_buf_p2[sizeof (struct AX) + 2 * sizeof (int16_t)]; + warn_ax_local_buf ((struct AX*) ax_buf_p2); + sink (ax_buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char ax_buf_p3[sizeof (struct AX) + 3 * sizeof (int16_t)]; + warn_ax_extern_buf ((struct AX*) ax_buf_p3); + sink (ax_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_ax_extern_bufx ((struct AX*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_ax_extern_bufx ((struct AX*) bufn); + sink (bufn); + } + + nowarn_ax_ref (p); +} + + +/* Exercise a zero-length trailing member array. It's the same as above + except that extern declarations with no definitions are considered to + have zero elements (they can't be initialized to have any). */ + +struct A0 +{ + int32_t n; + int16_t a0[0]; // { dg-message "while referencing 'a0'" "member" } +}; + +static void warn_a0_local (struct A0 *p) +{ + p->a0[0] = 0; // { dg-warning "\\\[-Warray-bounds" } + p->a0[1] = 1; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_extern (struct A0 *p) +{ + p->a0[0] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a0[1] = 3; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_local_buf (struct A0 *p) +{ + p->a0[0] = 4; p->a0[1] = 5; + + p->a0[2] = 6; // { dg-warning "\\\[-Warray-bounds" } + p->a0[3] = 7; // { dg-warning "\\\[-Warray-bounds" } + p->a0[4] = 8; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a0_extern_buf (struct A0 *p) +{ + p->a0[0] = 9; p->a0[1] = 10; p->a0[2] = 11; + + p->a0[3] = 12; // { dg-warning "\\\[-Warray-bounds" } + p->a0[4] = 13; // { dg-warning "\\\[-Warray-bounds" } + p->a0[5] = 14; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_a0_extern_bufx (struct A0 *p) +{ + p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999; +} + +static void nowarn_a0_ref (struct A0 *p) +{ + p->a0[0] = 0; p->a0[99] = 99; p->a0[999] = 999; p->a0[9999] = 9999; +} + +void test_a0 (struct A0 *p, unsigned n) +{ + { + struct A0 sa0; // { dg-message "defined here" "struct definition" } + warn_a0_local (&sa0); + sink (&sa0); + } + + { + extern + struct A0 xsa0; // { dg-message "defined here" "struct definition" } + warn_a0_extern (&xsa0); + sink (&xsa0); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char a0_buf_p2[sizeof (struct A0) + 2 * sizeof (int16_t)]; + warn_a0_local_buf ((struct A0*) a0_buf_p2); + sink (a0_buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char a0_buf_p3[sizeof (struct A0) + 3 * sizeof (int16_t)]; + warn_a0_extern_buf ((struct A0*) a0_buf_p3); + sink (a0_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_a0_extern_bufx ((struct A0*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_a0_extern_bufx ((struct A0*) bufn); + sink (bufn); + } + + nowarn_a0_ref (p); +} + + +/* Exercise a one-element trailing member array. It's the same as above + except that it has exactly one element. */ + +struct A1 +{ + int32_t n; + int16_t a1[1]; // { dg-message "while referencing 'a1'" } +}; + +static void warn_a1_local_noinit (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_extern (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_init (struct A1 *p) +{ + p->a1[0] = 0; + p->a1[1] = 1; // { dg-warning "\\\[-Warray-bounds" } + p->a1[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_local_buf (struct A1 *p) +{ + p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; + + p->a1[4] = 4; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a1_extern_buf (struct A1 *p) +{ + p->a1[0] = 0; p->a1[1] = 1; p->a1[2] = 2; p->a1[3] = 3; p->a1[4] = 4; + + p->a1[5] = 5; // { dg-warning "\\\[-Warray-bounds" } +} + +static void nowarn_a1_extern_bufx (struct A1 *p) +{ + p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999; +} + +static void nowarn_a1_ref (struct A1 *p) +{ + p->a1[0] = 0; p->a1[99] = 99; p->a1[999] = 999; p->a1[9999] = 9999; +} + +void test_a1 (struct A1 *p, unsigned n) +{ + { + struct A1 a1; + warn_a1_local_noinit (&a1); + sink (&a1); + } + + { + extern struct A1 a1x; + warn_a1_extern (&a1x); + sink (&a1x); +} + { + struct A1 a1 = { 0, { 1 } }; + warn_a1_init (&a1); + sink (&a1); + } + + { + /* Verify out-of-bounds access to the local BUF is diagnosed. */ + char buf_p2[sizeof (struct A1) + 2 * sizeof (int16_t)]; + warn_a1_local_buf ((struct A1*) buf_p2); + sink (buf_p2); + } + + { + /* Verify out-of-bounds access to the extern BUF with a known + bound is diagnosed. */ + extern char a1_buf_p3[sizeof (struct A1) + 3 * sizeof (int16_t)]; + warn_a1_extern_buf ((struct A1*) a1_buf_p3); + sink (a1_buf_p3); + } + + { + /* Verify that accesses to BUFX with an unknown bound are not + diagnosed. */ + extern char bufx[]; + nowarn_a1_extern_bufx ((struct A1*) bufx); + sink (bufx); + } + + { + /* Verify that accesses to BUFN with a runtime bound are not + diagnosed. */ + char bufn[n]; + nowarn_a1_extern_bufx ((struct A1*) bufn); + sink (bufn); + } + + nowarn_a1_ref (p); +} + + +/* Exercise a two-element trailing member array. It's treated + the same as an interior array member. */ + +struct A2 +{ + int32_t n; + int16_t a2[2]; // { dg-message "while referencing 'a2'" } +}; + +static void warn_a2_noinit (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a2_init (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" } +} + +static void warn_a2_ref (struct A2 *p) +{ + p->a2[0] = 0; p->a2[1] = 1; + + p->a2[2] = 2; // { dg-warning "\\\[-Warray-bounds" } + p->a2[9] = 9; // { dg-warning "\\\[-Warray-bounds" } +} + +void test_a2 (struct A2 *p) +{ + { + struct A2 a2; + warn_a2_noinit (&a2); + sink (&a2); + } + + { + struct A2 a2 = { 0, { 1, 2 } }; + warn_a2_init (&a2); + sink (&a2); + } + + warn_a2_ref (p); +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-48.c b/gcc/testsuite/gcc.dg/Warray-bounds-48.c index 13373d1..19b7634c 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-48.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-48.c @@ -30,7 +30,7 @@ static void nowarn_ax_extern (struct AX *p) static void warn_ax_local_buf (struct AX *p) { - p->ax[0] = 4; p->ax[1] = 5; + p->ax[0] = 4; p->ax[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } } p->ax[2] = 6; // { dg-warning "\\\[-Warray-bounds" } p->ax[3] = 7; // { dg-warning "\\\[-Warray-bounds" } @@ -130,7 +130,7 @@ static void warn_a0_extern (struct A0 *p) static void warn_a0_local_buf (struct A0 *p) { - p->a0[0] = 4; p->a0[1] = 5; + p->a0[0] = 4; p->a0[1] = 5; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2hi_store && { ! vect_slp_v4hi_store } } } } p->a0[2] = 6; // { dg-warning "\\\[-Warray-bounds" } p->a0[3] = 7; // { dg-warning "\\\[-Warray-bounds" } diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c new file mode 100644 index 0000000..ef8056d --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51-novec.c @@ -0,0 +1,21 @@ +/* PR middle-end/92333 - missing variable name referencing VLA in warnings + PR middle-end/82608 - missing -Warray-bounds on an out-of-bounds VLA index + { dg-do compile } + { dg-options "-O2 -Wall -fno-tree-vectorize" } */ + +void sink (void*); + +void test_struct_char_vla_location (void) +{ + unsigned nelts = 7; + + struct { + char cvla[nelts]; // { dg-message "declared here|while referencing" } + } s; + + s.cvla[0] = __LINE__; + s.cvla[nelts - 1] = 0; + s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } + + sink (&s); +} diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-51.c b/gcc/testsuite/gcc.dg/Warray-bounds-51.c index de60d87..8b589f3 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-51.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-51.c @@ -39,7 +39,7 @@ void test_struct_char_vla_location (void) } s; s.cvla[0] = __LINE__; - s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + s.cvla[nelts - 1] = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2qi_store } } } s.cvla[nelts] = 0; // { dg-warning "\\\[-Warray-bounds" } sink (&s); diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-87.c b/gcc/testsuite/gcc.dg/Warray-bounds-87.c index a49874d..a545780 100644 --- a/gcc/testsuite/gcc.dg/Warray-bounds-87.c +++ b/gcc/testsuite/gcc.dg/Warray-bounds-87.c @@ -33,7 +33,7 @@ static unsigned int h (int i, int j) case 9: return j; case 10: - return a[i]; // { dg-bogus "-Warray-bounds" "pr101671" { xfail *-*-* } } + return a[i]; // { dg-bogus "-Warray-bounds" "pr101671" } } return 0; } diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c new file mode 100644 index 0000000..5089d55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3-novec.c @@ -0,0 +1,16 @@ +/* PR c/50584 - No warning for passing small array to C99 static array + declarator + { dg-do compile } + { dg-options "-Wall -Warray-parameter=1" } */ + +/* Also verify that -Warray-bounds doesn't trigger for ordinary array + parameters... */ +#pragma GCC optimize ("2,no-tree-vectorize") + +/* ...but does for static arrays. */ +__attribute__ ((noipa)) void +gcas3 (char a[static 3]) +{ + a[0] = 0; a[1] = 1; a[2] = 2; + a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } +} diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-3.c b/gcc/testsuite/gcc.dg/Warray-parameter-3.c index e8a269c..b6ed8da 100644 --- a/gcc/testsuite/gcc.dg/Warray-parameter-3.c +++ b/gcc/testsuite/gcc.dg/Warray-parameter-3.c @@ -77,7 +77,7 @@ gia3 (int a[3]) __attribute__ ((noipa)) void gcas3 (char a[static 3]) { - a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + a[0] = 0; a[1] = 1; a[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } a[3] = 3; // { dg-warning "\\\[-Warray-bounds" } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c new file mode 100644 index 0000000..de39eaa --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14-novec.c @@ -0,0 +1,16 @@ +/* Test to verify that past-the-end multibyte writes via lvalues of wider + types than char are diagnosed. + { dg-do compile } + { dg-require-effective-target int32plus } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */ + +typedef __INT16_TYPE__ int16_t; + +char a4[4], a8[8], a16[16]; + +void test_int16 (void) +{ + char *p = a4 + 1; + *(int16_t*)p = 0; + *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c index 7683084..c4a3f05 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-14.c @@ -36,8 +36,8 @@ void test_memcpy_cond (int i) void test_int16 (void) { char *p = a4 + 1; - *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } - *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "" { xfail { i?86-*-* x86_64-*-* } } } + *(int16_t*)p = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v2hi_store } } } + *(int16_t*)(p + 2) = 0; // { dg-warning "writing 2 bytes into a region of size 1" "pr102706" { xfail { vect_slp_v2hi_store } } } } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c new file mode 100644 index 0000000..6f83548 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21-novec.c @@ -0,0 +1,34 @@ +/* PR middle-end/92312 - bogus -Wstringop-overflow storing into a trailing + array backed by larger buffer + { dg-do compile } + { dg-options "-O2 -fno-tree-vectorize -Wall -Wno-array-bounds" } */ + +struct S0 { char a, b[0]; }; + +void sink (void*); + +void test_store_zero_length (int i) +{ + char a[3]; + struct S0 *p = (struct S0*)a; + p->a = 0; + p->b[0] = 0; + p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } + p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" } + p->b[i] = 2; + sink (p); +} + +struct Sx { char a, b[]; }; + +void test_store_flexarray (int i) +{ + char a[3]; + struct Sx *p = (struct Sx*)a; + p->a = 0; + p->b[0] = 0; + p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } + p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" } + p->b[i] = 2; + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c index d88bde9..3fccfc9 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-21.c @@ -23,10 +23,10 @@ void test_store_zero_length (int i) { char a[3]; struct S0 *p = (struct S0*)a; - p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } - p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + p->b[2] = 2; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { xfail { vect_slp_v4qi_store } } } p->b[i] = 2; sink (p); } @@ -50,10 +50,10 @@ void test_store_flexarray (int i) { char a[3]; struct Sx *p = (struct Sx*)a; - p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "" { target { i?86-*-* x86_64-*-* } } } + p->a = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v4qi_store } } } p->b[0] = 0; p->b[1] = 1; // { dg-bogus "\\\[-Wstringop-overflow" } - p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "" { xfail { i?86-*-* x86_64-*-* } } } + p->b[2] = 1; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { xfail { vect_slp_v4qi_store } } } p->b[i] = 2; sink (p); } diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c index 09df000..04e91af 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-68.c @@ -58,11 +58,18 @@ void warn_comp_lit_zero (void) void warn_comp_lit (void) { *(AC2*)a1 = Ac2; // { dg-warning "writing 2 bytes into a region of size 1" "pr101475" { xfail *-*-* } } - *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } - *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { i?86-*-* x86_64-*-* } } } } + // After vectorization, below codes are optimized to + // MEM <vector(4) char> [(char *)&a2] = { 0, 1, 2, 3 }; + // MEM <vector(4) char> [(char *)&a3] = { 0, 1, 2, 3 }; + // MEM <vector(8) char> [(char *)&a4] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + // MEM <vector(8) char> [(char *)&a7] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + // MEM <vector(16) char> [(char *)&a15] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + // and warning should be expected, refer to PR102722. + *(AC4*)a2 = Ac4; // { dg-warning "writing 4 bytes into a region of size 2" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } } + *(AC4*)a3 = Ac4; // { dg-warning "writing 4 bytes into a region of size 3" "pr101475" { xfail { ! { vect_slp_v4qi_store } } } } + *(AC8*)a4 = Ac8; // { dg-warning "writing 8 bytes into a region of size 4" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } } + *(AC8*)a7 = Ac8; // { dg-warning "writing 8 bytes into a region of size 7" "pr101475" { xfail { ! { vect_slp_v8qi_store } } } } + *(AC16*)a15 = Ac16; // { dg-warning "writing 16 bytes into a region of size 15" "pr101475" { xfail { ! { vect_slp_v16qi_store } } } } } void warn_aggr_decl (void) diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c new file mode 100644 index 0000000..71c643b --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76-novec.c @@ -0,0 +1,88 @@ +/* Verify warnings and notes for MAX_EXPRs involving either pointers + to distinct objects or one to a known object and the other to + an unknown one. Unlike for the same object, for unrelated objects + the expected warnings and notes are the same as for MIN_EXPR: when + the order of the objects in the address space cannot be determined + the larger of them is assumed to be used. (This is different for + distinct struct members where the order is given.) + The relational expressions are strictly invalid but that should be + diagnosed by a separate warning. + { dg-do compile } + { dg-options "-O2 -Wno-array-bounds -fno-tree-vectorize" } */ + +#define MAX(p, q) ((p) > (q) ? (p) : (q)) + +/* Verify that even for MAX_EXPR and like for MIN_EXPR, the note points + to the larger of the two objects and mentions the offset into it + (although the offset might be better included in the warning). */ +extern char a3[3]; +extern char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" } + +void max_a3_a5 (int i) +{ + char *p = a3 + i; + char *q = a5 + i; + + /* The relational expression below is invalid and should be diagnosed + by its own warning independently of -Wstringop-overflow. */ + char *d = MAX (p, q); + + d[2] = 0; + d[3] = 0; + d[4] = 0; + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + + +// Same as above but with the larger array as the first MAX_EXPR operand. +extern char b4[4]; +extern char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" } + +void max_b6_b4 (int i) +{ + char *p = b6 + i; + char *q = b4 + i; + char *d = MAX (p, q); + + d[3] = 0; + d[4] = 0; + d[5] = 0; + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + +struct A3_5 +{ + char a3[3]; // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } } + char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" } +}; + +void max_A3_A5 (int i, struct A3_5 *pa3_5) +{ + char *p = pa3_5->a3 + i; + char *q = pa3_5->a5 + i; + + char *d = MAX (p, q); + d[2] = 0; + d[3] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } } + d[4] = 0; + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} + + +struct B4_B6 +{ + char b4[4]; + char b6[6]; // { dg-message "at offset 6 into destination object 'b6' of size 6" "note" } +}; + +void max_B6_B4 (int i, struct B4_B6 *pb4_b6) +{ + char *p = pb4_b6->b6 + i; + char *q = pb4_b6->b4 + i; + char *d = MAX (p, q); + + d[3] = 0; + d[4] = 0; + d[5] = 0; + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" } +} diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c index 0c7b53c..5246726 100644 --- a/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c +++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-76.c @@ -27,10 +27,10 @@ void max_a3_a5 (int i) by its own warning independently of -Wstringop-overflow. */ char *d = MAX (p, q); - d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } + d[2] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v4qi_store } } } d[3] = 0; d[4] = 0; - d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102706" { xfail { vect_slp_v4qi_store } } } } @@ -44,10 +44,10 @@ void max_b6_b4 (int i) char *q = b4 + i; char *d = MAX (p, q); - d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "" { target { i?86-*-* x86_64-*-* } } } + d[3] = 0; // { dg-warning "writing 4 bytes into a region of size 3" "pr102706" { target { vect_slp_v4qi_store } } } d[4] = 0; d[5] = 0; - d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102706" { xfail { vect_slp_v4qi_store } } } } @@ -82,7 +82,8 @@ void max_d8_p (char *q, int i) struct A3_5 { char a3[3]; // { dg-message "at offset 3 into destination object 'a3' of size 3" "pr??????" { xfail *-*-* } } - char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { i?86-*-* x86_64-*-* } } } + // refer to pr102697 for xfail + char a5[5]; // { dg-message "at offset 5 into destination object 'a5' of size 5" "note" { xfail { vect_slp_v4qi_store } } } }; void max_A3_A5 (int i, struct A3_5 *pa3_5) @@ -95,14 +96,15 @@ void max_A3_A5 (int i, struct A3_5 *pa3_5) d[2] = 0; d[3] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr??????" { xfail *-*-* } } d[4] = 0; - d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[5] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102697" { xfail { vect_slp_v4qi_store } } } } struct B4_B6 { char b4[4]; - char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" { xfail { i?86-*-* x86_64-*-* } } } + // refer to pr102697 for xfail + char b6[6]; // { dg-message "at offset \[^a-zA-Z\n\r\]*6\[^a-zA-Z0-9\]* into destination object 'b6' of size 6" "note" { xfail { vect_slp_v4qi_store } } } }; void max_B6_B4 (int i, struct B4_B6 *pb4_b6) @@ -114,7 +116,7 @@ void max_B6_B4 (int i, struct B4_B6 *pb4_b6) d[3] = 0; d[4] = 0; d[5] = 0; - d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "" { xfail { i?86-*-* x86_64-*-* } } } + d[6] = 0; // { dg-warning "writing 1 byte into a region of size 0" "pr102697" { xfail { vect_slp_v4qi_store } } } } diff --git a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c new file mode 100644 index 0000000..8e023b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2-novec.c @@ -0,0 +1,45 @@ +/* Test to verify that -Wzero-length-bounds and not -Warray-bounds is + issued for accesses to interior zero-length array members that are + within the bounds of the enclosing struct. + { dg-do compile } + { dg-options "-O2 -Wall -fno-tree-vectorize" } */ + +void sink (void*); + +struct A { int i; }; +struct B { int j; struct A a[0]; }; + +struct C +{ + struct B b1; + struct B b2; +}; + +char cbuf1[1 * sizeof (struct C)]; +char cbuf2[2 * sizeof (struct C)] = { }; + +void test_C_global_buf (void) +{ + struct C *p = (struct C*)&cbuf1; + + p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); + + p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b2.a[ 1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); + + p = (struct C*)&cbuf2; + p->b1.a[-1].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b1.a[ 0].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } + sink (p); + + p->b2.a[ 0].i = 0; + p->b2.a[ 1].i = 0; + p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" } + p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" } + sink (p); +} diff --git a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c index 841b2bf..b232149 100644 --- a/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c +++ b/gcc/testsuite/gcc.dg/Wzero-length-array-bounds-2.c @@ -87,7 +87,7 @@ void test_C_global_buf (void) p->b1.a[ 1].i = 0; // { dg-warning "\\\[-Wzero-length-bounds" } sink (p); - p->b2.a[ 0].i = 0; + p->b2.a[ 0].i = 0; // { dg-warning "\\\[-Wstringop-overflow" "pr102706" { target { vect_slp_v2si_store && { ! vect_slp_v4si_store } } } } p->b2.a[ 1].i = 0; p->b2.a[ 2].i = 0; // { dg-warning "\\\[-Warray-bounds" } p->b2.a[ 3].i = 0; // { dg-warning "\\\[-Warray-bounds" } diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c index 0acf488..62176bd 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr94851-2.c @@ -45,7 +45,7 @@ int pamark(void) { if (curbp->b_amark == (AMARK *)NULL) curbp->b_amark = p; else - last->m_next = p; /* { dg-warning "dereference of NULL 'last'" "deref" { xfail *-*-* } } */ + last->m_next = p; /* { dg-warning "dereference of NULL 'last'" "deref" } */ } p->m_name = (char)c; /* { dg-bogus "leak of 'p'" "bogus leak" } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr69728.c b/gcc/testsuite/gcc.dg/graphite/pr69728.c index 69e2831..a6f3857 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr69728.c +++ b/gcc/testsuite/gcc.dg/graphite/pr69728.c @@ -24,6 +24,4 @@ fn1 () run into scheduling issues before here, not being able to handle empty domains. */ -/* XFAILed by fix for PR86865. */ - -/* { dg-final { scan-tree-dump "loop nest optimized" "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump "loop nest optimized" "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c b/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c index 925ae30..41c91b9 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-dsyr2k.c @@ -17,4 +17,4 @@ void dsyr2k(int N) { #pragma endscop } -/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c b/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c index b748946..e01a517 100644 --- a/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c +++ b/gcc/testsuite/gcc.dg/graphite/scop-dsyrk.c @@ -19,4 +19,4 @@ void dsyrk(int N) #pragma endscop } -/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "number of SCoPs: 1" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/loop-8.c b/gcc/testsuite/gcc.dg/loop-8.c index 90ea1c4..a685fc2 100644 --- a/gcc/testsuite/gcc.dg/loop-8.c +++ b/gcc/testsuite/gcc.dg/loop-8.c @@ -11,18 +11,23 @@ f (int *a, int *b) { int i; - for (i = 0; i < 100; i++) + i = 100; + if (i > 0) { - int d = 42; + do + { + int d = 42; - a[i] = d; - if (i % 2) - d = i; - b[i] = d; + a[i] = d; + if (i % 2) + d = i; + b[i] = d; + ++i; + } + while (i < 100); } } /* Load of 42 is moved out of the loop, introducing a new pseudo register. */ -/* { dg-final { scan-rtl-dump-times "Decided" 1 "loop2_invariant" } } */ /* { dg-final { scan-rtl-dump-not "without introducing a new temporary register" "loop2_invariant" } } */ diff --git a/gcc/testsuite/gcc.dg/plugin/gil-1.c b/gcc/testsuite/gcc.dg/plugin/gil-1.c index 66872f0..6cbc197 100644 --- a/gcc/testsuite/gcc.dg/plugin/gil-1.c +++ b/gcc/testsuite/gcc.dg/plugin/gil-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fanalyzer" } */ +/* { dg-require-effective-target analyzer } */ #include "gil.h" diff --git a/gcc/testsuite/gcc.dg/pr102764.c b/gcc/testsuite/gcc.dg/pr102764.c new file mode 100644 index 0000000..ea1c634 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102764.c @@ -0,0 +1,14 @@ +/* PR middle-end/102764 */ +/* Reported by Chengnian Sun <cnsun@uwaterloo.ca> */ + +/* { dg-do compile } */ +/* { dg-options "-O3 -fcompare-debug" } */ + +volatile int a; + +void main (void) +{ + for (int i = 0; i < 1000; i++) + if (i % 17) + a++; +} diff --git a/gcc/testsuite/gcc.dg/pr102827.c b/gcc/testsuite/gcc.dg/pr102827.c new file mode 100644 index 0000000..eed3eba --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102827.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-vectorize --param ssa-name-def-chain-limit=0" } */ +/* { dg-additional-options "-mavx" { target { x86_64-*-* i?86-*-* } } } */ + +void +test_double_double_nugt_var (double *dest, double *src, int b, int i) +{ + while (i < 1) + { + dest[i] = b ? src[i] : 0.0; + ++i; + } +} diff --git a/gcc/testsuite/gcc.dg/pr36902.c b/gcc/testsuite/gcc.dg/pr36902.c index 7dafc9a..365a26e 100644 --- a/gcc/testsuite/gcc.dg/pr36902.c +++ b/gcc/testsuite/gcc.dg/pr36902.c @@ -24,10 +24,9 @@ struct { unsigned char pcr_select[4]; } sel; +unsigned char buf[64]; int bar(void) { - static unsigned char buf[64]; - sel.size_of_select = 3; foo(buf, sel.pcr_select, sel.size_of_select); @@ -52,8 +51,6 @@ foo2(unsigned char * to, const unsigned char * from, int n) int baz(void) { - static unsigned char buf[64]; - sel.size_of_select = 5; foo2(buf, sel.pcr_select, sel.size_of_select); diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-loop.c b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c index 6e1be893..ddc99e6 100644 --- a/gcc/testsuite/gcc.dg/shrink-wrap-loop.c +++ b/gcc/testsuite/gcc.dg/shrink-wrap-loop.c @@ -1,58 +1,6 @@ /* { dg-do compile { target { { { i?86-*-* x86_64-*-* } && lp64 } || { arm_thumb2 } } } } */ /* { dg-options "-O2 -fdump-rtl-pro_and_epilogue" } */ -/* -Our new threader is threading things a bit too early, and causing the -testcase in gcc.dg/shrink-wrap-loop.c to fail. - - The gist is this BB inside a loop: - - <bb 6> : - # p_2 = PHI <p2_6(D)(2), p_12(5)> - if (p_2 != 0B) - goto <bb 3>; [INV] - else - goto <bb 7>; [INV] - -Our threader can move this check outside of the loop (good). This is -done before branch probabilities are calculated and causes the probs -to be calculated as: - -<bb 2> [local count: 216361238]: - if (p2_6(D) != 0B) - goto <bb 7>; [54.59%] - else - goto <bb 6>; [45.41%] - -Logically this seems correct to me. A simple check outside of a loop -should slightly but not overwhelmingly favor a non-zero value. - -Interestingly however, the old threader couldn't get this, but the IL -ended up identical, albeit with different probabilities. What happens -is that, because the old code could not thread this, the p2 != 0 check -would remain inside the loop and probs would be calculated thusly: - - <bb 6> [local count: 1073741824]: - # p_2 = PHI <p2_6(D)(2), p_12(5)> - if (p_2 != 0B) - goto <bb 3>; [94.50%] - else - goto <bb 7>; [5.50%] - -Then when the loop header copying pass ("ch") shuffled things around, -the IL would end up identical to my early threader code, but with the -probabilities would remain as 94.5/5.5. - -The above discrepancy causes the RTL ifcvt pass to generate different -code, and by the time we get to the shrink wrapping pass, things look -sufficiently different such that the legacy code can actually shrink -wrap, whereas our new code does not. - -IMO, if the loop-ch pass moves conditionals outside of a loop, the -probabilities should be adjusted, but that does mean the shrink wrap -won't happen for this contrived testcase. - */ - int foo (int *p1, int *p2); int @@ -68,4 +16,4 @@ test (int *p1, int *p2) return 1; } -/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail *-*-* } } } */ +/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c index b55a533..f8a6495 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c @@ -39,4 +39,4 @@ int main1 () which is folded by vectorizer. Both outgoing edges must have probability 100% so the resulting profile match after folding. */ /* { dg-final { scan-tree-dump-times "Invalid sum of outgoing probabilities 200.0" 1 "ifcvt" } } */ -/* { dg-final { scan-tree-dump-times "Invalid sum of incoming counts" 1 "ifcvt" } } */ +/* { dg-final { scan-tree-dump-times "Invalid sum of incoming counts" 2 "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index 51b3b7a..43f046e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -35,10 +35,7 @@ void foo (void) /* First, we should simplify the bits < 0 test within the loop. */ /* { dg-final { scan-tree-dump-times "Simplified relational" 1 "evrp" } } */ -/* Second, we should thread the edge out of the loop via the break - statement. We also realize that the final bytes == 0 test is useless, - and thread over it. We also know that toread != 0 is useless when - entering while loop and thread over it. */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp-thread1" } } */ +/* We used to check for 3 threaded jumps here, but they all would + rotate the loop. */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c index 2caa1f5..764b3fe 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr59597.c @@ -56,11 +56,7 @@ main (int argc, char argv[]) return crc; } -/* Previously we had 3 jump threads, but one of them crossed loops. - The reason the old threader was allowing it, was because there was - an ASSERT_EXPR getting in the way. Without the ASSERT_EXPR, we - have an empty pre-header block as the final block in the thread, - which the threader will simply join with the next block which *is* - in a different loop. */ -/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ +/* None of the threads we can get in vrp-thread1 are valid. They all + cross or rotate loops. */ +/* { dg-final { scan-tree-dump-not "Registering jump thread" "vrp-thread1" } } */ /* { dg-final { scan-tree-dump-not "joiner" "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c index a2386ba..eab3a25 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71437.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-ffast-math -O3 -fdump-tree-vrp-thread1-details" } */ +/* { dg-options "-ffast-math -O3 -fdump-tree-dom3-details" } */ int I = 50, J = 50; int S, L; @@ -39,4 +39,8 @@ void foo (int K) bar (LD, SD); } } -/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "vrp-thread1" } } */ + +/* We used to get 1 vrp-thread1 candidates here, but they now get + deferred until after loop opts are done, because they were rotating + loops. */ +/* { dg-final { scan-tree-dump-times "Threaded jump " 2 "dom3" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c index 18f7aab..f2a5e78 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c @@ -123,8 +123,7 @@ enum STATES FMS( u8 **in , u32 *transitions) { aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough to change decisions in switch expansion which in turn can expose new jump threading opportunities. Skip the later tests on aarch64. */ -/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread1" } } */ -/* { dg-final { scan-tree-dump-times "Invalid sum" 1 "thread1" } } */ +/* { dg-final { scan-tree-dump "Jumps threaded: \[7-9\]" "thread2" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread1" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread2" } } */ /* { dg-final { scan-tree-dump-not "optimizing for size" "thread3" { target { ! aarch64*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c deleted file mode 100644 index 0246ebf..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-18.c +++ /dev/null @@ -1,27 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -std=gnu89 --param logical-op-non-short-circuit=0" } */ - -#include "ssa-dom-thread-4.c" - -/* On targets that define LOGICAL_OP_NON_SHORT_CIRCUIT to 0, we split both - "a_elt || b_elt" and "b_elt && kill_elt" into two conditions each, - rather than using "(var1 != 0) op (var2 != 0)". Also, as on other targets, - we duplicate the header of the inner "while" loop. There are then - 4 threading opportunities: - - 1x "!a_elt && b_elt" in the outer "while" loop - -> the start of the inner "while" loop, - skipping the known-true "b_elt" in the first condition. - 1x "!b_elt" in the first condition - -> the outer "while" loop's continuation point, - skipping the known-false "b_elt" in the second condition. - 2x "kill_elt->indx >= b_elt->indx" in the first "while" loop - -> "kill_elt->indx == b_elt->indx" in the second condition, - skipping the known-true "b_elt && kill_elt" in the second - condition. - - All the cases are picked up by VRP1 as jump threads. */ - -/* There used to be 6 jump threads found by thread1, but they all - depended on threading through distinct loops in ethread. */ -/* { dg-final { scan-tree-dump-times "Threaded" 2 "vrp-thread1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c deleted file mode 100644 index 8f0a12c..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2a.c +++ /dev/null @@ -1,21 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-stats -fdump-tree-dom2-stats" } */ - -void bla(); - -/* In the following case, we should be able to thread edge through - the loop header. */ - -void thread_entry_through_header (void) -{ - int i; - - for (i = 0; i < 170; i++) - bla (); -} - -/* There's a single jump thread that should be handled by the VRP - jump threading pass. */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp-thread1"} } */ -/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp-thread1"} } */ -/* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c index 46e464f..9cd4635 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp-thread1-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ +/* { dg-options "-O2 -fdump-tree-vrp-thread2-details -fdump-tree-dom2-details -std=gnu89 --param logical-op-non-short-circuit=1" } */ struct bitmap_head_def; typedef struct bitmap_head_def *bitmap; typedef const struct bitmap_head_def *const_bitmap; @@ -53,10 +53,8 @@ bitmap_ior_and_compl (bitmap dst, const_bitmap a, const_bitmap b, return changed; } -/* The block starting the second conditional has 3 incoming edges, - we should thread all three, but due to a bug in the threading - code we missed the edge when the first conditional is false - (b_elt is zero, which means the second conditional is always - zero. VRP1 catches all three. */ -/* { dg-final { scan-tree-dump-times "Registering jump thread" 2 "vrp-thread1" } } */ -/* { dg-final { scan-tree-dump-times "Path crosses loops" 1 "vrp-thread1" } } */ +/* We used to catch 3 jump threads in vrp-thread1, but they all + rotated the loop, so they were disallowed. This in turn created + other opportunities for the other threaders which result in the the + post-loop threader (vrp-thread2) catching more. */ +/* { dg-final { scan-tree-dump-times "Registering jump thread" 5 "vrp-thread2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c deleted file mode 100644 index b0a7d42..0000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c +++ /dev/null @@ -1,44 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-thread1-details -fdump-tree-thread3-details" } */ - -/* { dg-final { scan-tree-dump-times "Registering jump" 6 "thread1" } } */ -/* { dg-final { scan-tree-dump-times "Registering jump" 1 "thread3" } } */ - -int sum0, sum1, sum2, sum3; -int foo (char *s, char **ret) -{ - int state=0; - char c; - - for (; *s && state != 4; s++) - { - c = *s; - if (c == '*') - { - s++; - break; - } - switch (state) - { - case 0: - if (c == '+') - state = 1; - else if (c != '-') - sum0+=c; - break; - case 1: - if (c == '+') - state = 2; - else if (c == '-') - state = 0; - else - sum1+=c; - break; - default: - break; - } - - } - *ret = s; - return state; -} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c index 16abcde..1da00a6 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c @@ -1,15 +1,14 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-thread1-stats -fdump-tree-thread2-stats -fdump-tree-dom2-stats -fdump-tree-thread3-stats -fdump-tree-dom3-stats -fdump-tree-vrp2-stats -fno-guess-branch-probability" } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread1" } } */ -/* { dg-final { scan-tree-dump "Jumps threaded: 5" "thread3" { target { ! aarch64*-*-* } } } } */ +/* { dg-final { scan-tree-dump "Jumps threaded: 12" "thread3" } } */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom2" } } */ /* aarch64 has the highest CASE_VALUES_THRESHOLD in GCC. It's high enough to change decisions in switch expansion which in turn can expose new jump threading opportunities. Skip the later tests on aarch64. */ /* { dg-final { scan-tree-dump-not "Jumps threaded" "dom3" { target { ! aarch64*-*-* } } } } */ -/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp2" { target { ! aarch64*-*-* } } } } */ +/* { dg-final { scan-tree-dump-not "Jumps threaded" "vrp-thread2" { target { ! aarch64*-*-* } } } } */ enum STATE { S0=0, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c new file mode 100644 index 0000000..bd56a62 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-invalid.c @@ -0,0 +1,102 @@ +// { dg-do compile } +// { dg-options "-O2 -fgimple -fdump-statistics" } +// +// This is a collection of seemingly threadble paths that should not be allowed. + +void foobar (int); + +// Possible thread from 2->4->3, but it would rotate the loop. +void __GIMPLE (ssa) +f1 () +{ + int i; + + // Pre-header. + __BB(2): + goto __BB4; + + // Latch. + __BB(3): + foobar (i_1); + i_5 = i_1 + 1; + goto __BB4; + + __BB(4,loop_header(1)): + i_1 = __PHI (__BB2: 0, __BB3: i_5); + if (i_1 != 101) + goto __BB3; + else + goto __BB5; + + __BB(5): + return; + +} + +// Possible thread from 2->3->5 but threading through the empty latch +// would create a non-empty latch. +void __GIMPLE (ssa) +f2 () +{ + int i; + + // Pre-header. + __BB(2): + goto __BB3; + + __BB(3,loop_header(1)): + i_8 = __PHI (__BB5: i_5, __BB2: 0); + foobar (i_8); + i_5 = i_8 + 1; + if (i_5 != 256) + goto __BB5; + else + goto __BB4; + + // Latch. + __BB(5): + goto __BB3; + + __BB(4): + return; + +} + +// Possible thread from 3->5->6->3 but this would thread through the +// header but not exit the loop. +int __GIMPLE (ssa) +f3 (int a) +{ + int i; + + __BB(2): + goto __BB6; + + __BB(3): + if (i_1 != 0) + goto __BB4; + else + goto __BB5; + + __BB(4): + foobar (5); + goto __BB5; + + // Latch. + __BB(5): + i_7 = i_1 + 1; + goto __BB6; + + __BB(6,loop_header(1)): + i_1 = __PHI (__BB2: 1, __BB5: i_7); + if (i_1 <= 99) + goto __BB3; + else + goto __BB7; + + __BB(7): + return; + +} + +// { dg-final { scan-tree-dump-not "Jumps threaded" "statistics" } } diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c index e68a9b6..82fae06 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c @@ -1,4 +1,6 @@ /* { dg-require-effective-target vect_int } */ +/* The SLP vectorization happens as part of the if-converted loop body. */ +/* { dg-additional-options "-fdump-tree-vect-details" } */ #include <stdarg.h> #include "tree-vect.h" @@ -65,5 +67,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "slp1" } } */ - +/* { dg-final { scan-tree-dump-times "optimized: basic block" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c index 59ad41e..adb787a 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmla_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLA(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vfma##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -104,12 +105,12 @@ main (int argc, char **argv) vfmaq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vfma_lane_f64. */ -/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 1 } } */ +/* vfma_lane_f64. + vfma_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmadd\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 2 } } */ /* vfmaq_lane_f64. - vfma_laneq_f64. vfmaq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmla\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c index 2d5a3d3..865def2 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmls_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLS(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vfms##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -105,12 +106,12 @@ main (int argc, char **argv) vfmsq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vfms_lane_f64. */ -/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 1 } } */ +/* vfms_lane_f64. + vfms_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmsub\\td\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+\, d\[0-9\]+" 2 } } */ /* vfmsq_lane_f64. - vfms_laneq_f64. vfmsq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmls\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c index 8b0880d..d01095e 100644 --- a/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/fmul_intrinsic_1.c @@ -9,6 +9,7 @@ extern double fabs (double); #define TEST_VMUL(q1, q2, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmul##q1##_lane##q2##_f##size (float##size##_t * res, \ const float##size##_t *in1, \ const float##size##_t *in2) \ @@ -104,12 +105,12 @@ main (int argc, char **argv) vmulq_laneq_f32. */ /* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 2 } } */ -/* vmul_lane_f64. */ -/* { dg-final { scan-assembler-times "fmul\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 1 } } */ +/* vmul_lane_f64. + Vmul_laneq_f64. */ +/* { dg-final { scan-assembler-times "fmul\\td\[0-9\]+, d\[0-9\]+, d\[0-9\]+" 2 } } */ -/* vmul_laneq_f64. - vmulq_lane_f64. +/* vmulq_lane_f64. vmulq_laneq_f64. */ -/* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 3 } } */ +/* { dg-final { scan-assembler-times "fmul\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/frint.x b/gcc/testsuite/gcc.target/aarch64/frint.x index 1403740..d598a25 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint.x +++ b/gcc/testsuite/gcc.target/aarch64/frint.x @@ -4,6 +4,7 @@ extern GPF SUFFIX(floor) (GPF); extern GPF SUFFIX(nearbyint) (GPF); extern GPF SUFFIX(rint) (GPF); extern GPF SUFFIX(round) (GPF); +extern GPF SUFFIX(roundeven) (GPF); GPF test1a (GPF x) { @@ -64,3 +65,14 @@ GPF test6b (GPF x) { return SUFFIX(round)(x); } + +GPF test7a (GPF x) +{ + return SUFFIX(__builtin_roundeven)(x); +} + +GPF test7b (GPF x) +{ + return SUFFIX(roundeven)(x); +} + diff --git a/gcc/testsuite/gcc.target/aarch64/frint_double.c b/gcc/testsuite/gcc.target/aarch64/frint_double.c index 9613949..1d28eb0 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint_double.c +++ b/gcc/testsuite/gcc.target/aarch64/frint_double.c @@ -12,3 +12,4 @@ /* { dg-final { scan-assembler-times "frinti\td\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frintx\td\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frinta\td\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "frintn\td\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/frint_float.c b/gcc/testsuite/gcc.target/aarch64/frint_float.c index 493ec37..530cf97 100644 --- a/gcc/testsuite/gcc.target/aarch64/frint_float.c +++ b/gcc/testsuite/gcc.target/aarch64/frint_float.c @@ -12,3 +12,4 @@ /* { dg-final { scan-assembler-times "frinti\ts\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frintx\ts\[0-9\]" 2 } } */ /* { dg-final { scan-assembler-times "frinta\ts\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "frintn\ts\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c new file mode 100644 index 0000000..0721706 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math" } */ + +float +f1 (float x) +{ + int y = x; + + return (float) y; +} + +double +f2 (double x) +{ + long y = x; + + return (double) y; +} + +float +f3 (double x) +{ + int y = x; + + return (float) y; +} + +double +f4 (float x) +{ + int y = x; + + return (double) y; +} + +/* { dg-final { scan-assembler "frintz\\ts\[0-9\]+, s\[0-9\]+" } } */ +/* { dg-final { scan-assembler "frintz\\td\[0-9\]+, d\[0-9\]+" } } */ +/* { dg-final { scan-assembler "fcvtzs\\tw\[0-9\]+, d\[0-9\]+" } } */ +/* { dg-final { scan-assembler "scvtf\\ts\[0-9\]+, w\[0-9\]+" } } */ +/* { dg-final { scan-assembler "fcvtzs\\tw\[0-9\]+, s\[0-9\]+" } } */ +/* { dg-final { scan-assembler "scvtf\\td\[0-9\]+, w\[0-9\]+" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c index 46b3c78..885bfb3 100644 --- a/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mla_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLA(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmlaq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c index e01a4f6..df046ce 100644 --- a/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mls_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMLS(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmlsq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c b/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c index 00ef4f2..517b937 100644 --- a/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c +++ b/gcc/testsuite/gcc.target/aarch64/mul_intrinsic_1.c @@ -11,6 +11,7 @@ extern void abort (void); #define TEST_VMUL(q, su, size, in1_lanes, in2_lanes) \ static void \ +__attribute__((noipa,noinline)) \ test_vmulq_lane##q##_##su##size (MAP##su (size, ) * res, \ const MAP##su(size, ) *in1, \ const MAP##su(size, ) *in2) \ diff --git a/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c b/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c new file mode 100644 index 0000000..27b3909 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/mvn-cmeq0-1.c @@ -0,0 +1,17 @@ +/* { dg-do assemble } */ +/* { dg-options "-O --save-temps" } */ + +#include <arm_neon.h> + +uint8x8_t bar(int16x8_t abs_row0, int16x8_t row0) { + uint16x8_t row0_diff = + vreinterpretq_u16_s16(veorq_s16(abs_row0, vshrq_n_s16(row0, 15))); + uint8x8_t abs_row0_gt0 = + vmovn_u16(vcgtq_u16(vreinterpretq_u16_s16(abs_row0), vdupq_n_u16(0))); + return abs_row0_gt0; +} + + +/* { dg-final { scan-assembler-times {\tcmtst\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tcmeq\t} } } */ +/* { dg-final { scan-assembler-not {\tnot\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c b/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c index 50ecab0..fa61196 100644 --- a/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c +++ b/gcc/testsuite/gcc.target/aarch64/narrow_high_combine.c @@ -225,7 +225,8 @@ TEST_2_UNARY (vqmovun, uint32x4_t, int64x2_t, s64, u32) /* { dg-final { scan-assembler-times "\\tuqshrn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqrshrn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tuqrshrn2\\tv" 6} } */ -/* { dg-final { scan-assembler-times "\\txtn2\\tv" 12} } */ +/* { dg-final { scan-assembler-times "\\txtn2\\tv" 6} } */ +/* { dg-final { scan-assembler-times "\\tuzp1\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tuqxtn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqxtn2\\tv" 6} } */ /* { dg-final { scan-assembler-times "\\tsqxtun2\\tv" 6} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c new file mode 100644 index 0000000..6a0331f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-2.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE char + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c new file mode 100644 index 0000000..2086b24a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-3.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE short + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c new file mode 100644 index 0000000..0831810 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-4.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE int + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c new file mode 100644 index 0000000..6b2a6bd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shl-combine-5.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE long + +void e (signed TYPE * restrict a, signed TYPE *b, int n) +{ + for (int i = 0; i < n; i++) + b[i] = a[i] >> (sizeof(TYPE)*8)-1; +} + +/* { dg-final { scan-assembler-times {\tcmlt\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tsshr\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c new file mode 100644 index 0000000..a285246 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-1.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE char + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c new file mode 100644 index 0000000..3a1cfce --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint32x4_t foo (uint64x2_t a, uint64x2_t b) +{ + return vrshrn_high_n_u64 (vrshrn_n_u64 (a, 32), b, 32); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c new file mode 100644 index 0000000..012135b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-2.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE short + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c new file mode 100644 index 0000000..8b5b360 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-3.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE int + +void foo (unsigned long long * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> 3; +} + +/* { dg-final { scan-assembler-times {\tshrn\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tshrn2\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c new file mode 100644 index 0000000..fedca76 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-4.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE long long + +void foo (unsigned TYPE * restrict a, TYPE * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = (a[i] * a[i]) >> 2; +} + +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c new file mode 100644 index 0000000..408e8553 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-5.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 char +#define TYPE2 short +#define SHIFT 8 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c new file mode 100644 index 0000000..6211ba3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-6.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 short +#define TYPE2 int +#define SHIFT 16 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c new file mode 100644 index 0000000..56cbeac --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-7.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define TYPE1 int +#define TYPE2 long long +#define SHIFT 32 + +void foo (TYPE2 * restrict a, TYPE1 * restrict d, int n) +{ + for( int i = 0; i < n; i++ ) + d[i] = a[i] >> SHIFT; +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c new file mode 100644 index 0000000..6a47f3c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-8.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint8x16_t foo (uint16x8_t a, uint16x8_t b) +{ + return vrshrn_high_n_u16 (vrshrn_n_u16 (a, 8), b, 8); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c new file mode 100644 index 0000000..929a55c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-9.c @@ -0,0 +1,14 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + + +#include <arm_neon.h> + +uint16x8_t foo (uint32x4_t a, uint32x4_t b) +{ + return vrshrn_high_n_u32 (vrshrn_n_u32 (a, 16), b, 16); +} + +/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tshrn\t} } } */ +/* { dg-final { scan-assembler-not {\tshrn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c index a1faefd..ffa391a 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c +++ b/gcc/testsuite/gcc.target/aarch64/simd/vmul_elem_1.c @@ -146,12 +146,14 @@ check_v2sf (float32_t elemA, float32_t elemB) vst1_f32 (vec32x2_res, vmul_n_f32 (vec32x2_src, elemA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint32_t *) &vec32x2_res[indx] != * (uint32_t *) &expected2_1[indx]) abort (); vst1_f32 (vec32x2_res, vmul_n_f32 (vec32x2_src, elemB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint32_t *) &vec32x2_res[indx] != * (uint32_t *) &expected2_2[indx]) abort (); @@ -169,24 +171,28 @@ check_v4sf (float32_t elemA, float32_t elemB, float32_t elemC, float32_t elemD) vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_1[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_2[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_3[indx]) abort (); vst1q_f32 (vec32x4_res, vmulq_n_f32 (vec32x4_src, elemD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (* (uint32_t *) &vec32x4_res[indx] != * (uint32_t *) &expected4_4[indx]) abort (); @@ -204,12 +210,14 @@ check_v2df (float64_t elemdC, float64_t elemdD) vst1q_f64 (vec64x2_res, vmulq_n_f64 (vec64x2_src, elemdC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint64_t *) &vec64x2_res[indx] != * (uint64_t *) &expectedd2_1[indx]) abort (); vst1q_f64 (vec64x2_res, vmulq_n_f64 (vec64x2_src, elemdD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (* (uint64_t *) &vec64x2_res[indx] != * (uint64_t *) &expectedd2_2[indx]) abort (); @@ -227,12 +235,14 @@ check_v2si (int32_t elemsA, int32_t elemsB) vst1_s32 (vecs32x2_res, vmul_n_s32 (vecs32x2_src, elemsA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecs32x2_res[indx] != expecteds2_1[indx]) abort (); vst1_s32 (vecs32x2_res, vmul_n_s32 (vecs32x2_src, elemsB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecs32x2_res[indx] != expecteds2_2[indx]) abort (); @@ -248,12 +258,14 @@ check_v2si_unsigned (uint32_t elemusA, uint32_t elemusB) vst1_u32 (vecus32x2_res, vmul_n_u32 (vecus32x2_src, elemusA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecus32x2_res[indx] != expectedus2_1[indx]) abort (); vst1_u32 (vecus32x2_res, vmul_n_u32 (vecus32x2_src, elemusB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 2; indx++) if (vecus32x2_res[indx] != expectedus2_2[indx]) abort (); @@ -271,24 +283,28 @@ check_v4si (int32_t elemsA, int32_t elemsB, int32_t elemsC, int32_t elemsD) vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_1[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_2[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_3[indx]) abort (); vst1q_s32 (vecs32x4_res, vmulq_n_s32 (vecs32x4_src, elemsD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecs32x4_res[indx] != expecteds4_4[indx]) abort (); @@ -305,24 +321,28 @@ check_v4si_unsigned (uint32_t elemusA, uint32_t elemusB, uint32_t elemusC, vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_1[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_2[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_3[indx]) abort (); vst1q_u32 (vecus32x4_res, vmulq_n_u32 (vecus32x4_src, elemusD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecus32x4_res[indx] != expectedus4_4[indx]) abort (); @@ -341,24 +361,28 @@ check_v4hi (int16_t elemhA, int16_t elemhB, int16_t elemhC, int16_t elemhD) vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_1[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_2[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_3[indx]) abort (); vst1_s16 (vech16x4_res, vmul_n_s16 (vech16x4_src, elemhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vech16x4_res[indx] != expectedh4_4[indx]) abort (); @@ -375,24 +399,28 @@ check_v4hi_unsigned (uint16_t elemuhA, uint16_t elemuhB, uint16_t elemuhC, vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_1[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_2[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_3[indx]) abort (); vst1_u16 (vecuh16x4_res, vmul_n_u16 (vecuh16x4_src, elemuhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 4; indx++) if (vecuh16x4_res[indx] != expecteduh4_4[indx]) abort (); @@ -411,48 +439,56 @@ check_v8hi (int16_t elemhA, int16_t elemhB, int16_t elemhC, int16_t elemhD, vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_1[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_2[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_3[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_4[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhE)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_5[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhF)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_6[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhG)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_7[indx]) abort (); vst1q_s16 (vech16x8_res, vmulq_n_s16 (vech16x8_src, elemhH)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vech16x8_res[indx] != expectedh8_8[indx]) abort (); @@ -470,48 +506,56 @@ check_v8hi_unsigned (uint16_t elemuhA, uint16_t elemuhB, uint16_t elemuhC, vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhA)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_1[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhB)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_2[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhC)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_3[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhD)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_4[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhE)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_5[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhF)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_6[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhG)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_7[indx]) abort (); vst1q_u16 (vecuh16x8_res, vmulq_n_u16 (vecuh16x8_src, elemuhH)); + asm volatile ("" : : : "memory"); for (indx = 0; indx < 8; indx++) if (vecuh16x8_res[indx] != expecteduh8_8[indx]) abort (); diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c index 2f92224..8d1ee41 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr93183.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -mcpu=generic+sve" } */ +/* { dg-options "-O3" } */ typedef unsigned char uint8_t; diff --git a/gcc/testsuite/gcc.target/aarch64/vclz.c b/gcc/testsuite/gcc.target/aarch64/vclz.c index a36ee44..ca4d174 100644 --- a/gcc/testsuite/gcc.target/aarch64/vclz.c +++ b/gcc/testsuite/gcc.target/aarch64/vclz.c @@ -66,22 +66,62 @@ extern void abort (void); #define CLZ_INST(reg_len, data_len, is_signed) \ CONCAT1 (vclz, POSTFIX (reg_len, data_len, is_signed)) -#define RUN_TEST(test_set, answ_set, reg_len, data_len, is_signed, n) \ - INHIB_OPTIMIZATION; \ - a = LOAD_INST (reg_len, data_len, is_signed) (test_set); \ - b = LOAD_INST (reg_len, data_len, is_signed) (answ_set); \ - a = CLZ_INST (reg_len, data_len, is_signed) (a); \ - for (i = 0; i < n; i++) \ - if (a [i] != b [i]) \ - return 1; +#define BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (int##size##_t* test_set, \ + int##size##_t* answ_set, \ + int reg_len, int data_len, \ + int n) \ +{ \ + int i; \ + INHIB_OPTIMIZATION; \ + int##size##x##lanes##_t a = vld1##type##size (test_set); \ + int##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vclz##type##size (a); \ + for (i = 0; i < n; i++){ \ + if (a [i] != b [i]) \ + return 1; \ + } \ + return 0; \ +} + +/* unsigned inputs */ +#define U_BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (uint##size##_t* test_set, \ + uint##size##_t* answ_set, \ + int reg_len, int data_len, \ + int n) \ +{ \ + int i; \ + INHIB_OPTIMIZATION; \ + uint##size##x##lanes##_t a = vld1##type##size (test_set); \ + uint##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vclz##type##size (a); \ + for (i = 0; i < n; i++){ \ + if (a [i] != b [i]) \ + return 1; \ + } \ + return 0; \ +} + +BUILD_TEST (_s, 8, 8) +BUILD_TEST (_s, 16, 4) +BUILD_TEST (_s, 32, 2) +BUILD_TEST (q_s, 8, 16) +BUILD_TEST (q_s, 16, 8) +BUILD_TEST (q_s, 32, 4) + +U_BUILD_TEST (_u, 8, 8) +U_BUILD_TEST (_u, 16, 4) +U_BUILD_TEST (_u, 32, 2) +U_BUILD_TEST (q_u, 8, 16) +U_BUILD_TEST (q_u, 16, 8) +U_BUILD_TEST (q_u, 32, 4) int __attribute__ ((noinline)) test_vclz_s8 () { - int i; - int8x8_t a; - int8x8_t b; - int8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 @@ -98,22 +138,18 @@ test_vclz_s8 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 8, 1, 8); - RUN_TEST (test_set1, answ_set1, 64, 8, 1, 1); + int o1 = run_test_s8x8 (test_set0, answ_set0, 64, 8, 8); + int o2 = run_test_s8x8 (test_set1, answ_set1, 64, 8, 1); - return 0; + return o1||o2; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 4 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 2 } } */ int __attribute__ ((noinline)) test_vclz_s16 () { - int i; - int16x4_t a; - int16x4_t b; - int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; int16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -126,25 +162,21 @@ test_vclz_s16 () int16_t answ_set3[4] = { 4, 3, 2, 1 }; int16_t answ_set4[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 16, 1, 4); - RUN_TEST (test_set1, answ_set1, 64, 16, 1, 4); - RUN_TEST (test_set2, answ_set2, 64, 16, 1, 4); - RUN_TEST (test_set3, answ_set3, 64, 16, 1, 4); - RUN_TEST (test_set4, answ_set4, 64, 16, 1, 1); + int o1 = run_test_s16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_s16x4 (test_set1, answ_set1, 64, 16, 4); + int o3 = run_test_s16x4 (test_set2, answ_set2, 64, 16, 4); + int o4 = run_test_s16x4 (test_set3, answ_set3, 64, 16, 4); + int o5 = run_test_s16x4 (test_set4, answ_set4, 64, 16, 1); - return 0; + return o1||o2||o3||o4||o5; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 10} } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 2} } */ int __attribute__ ((noinline)) test_vclz_s32 () { - int i; - int32x2_t a; - int32x2_t b; - int32_t test_set0[2] = { TEST0, TEST1 }; int32_t test_set1[2] = { TEST2, TEST3 }; int32_t test_set2[2] = { TEST4, TEST5 }; @@ -181,37 +213,34 @@ test_vclz_s32 () int32_t answ_set15[2] = { 2, 1 }; int32_t answ_set16[2] = { 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 32, 1, 2); - RUN_TEST (test_set1, answ_set1, 64, 32, 1, 2); - RUN_TEST (test_set2, answ_set2, 64, 32, 1, 2); - RUN_TEST (test_set3, answ_set3, 64, 32, 1, 2); - RUN_TEST (test_set4, answ_set4, 64, 32, 1, 2); - RUN_TEST (test_set5, answ_set5, 64, 32, 1, 2); - RUN_TEST (test_set6, answ_set6, 64, 32, 1, 2); - RUN_TEST (test_set7, answ_set7, 64, 32, 1, 2); - RUN_TEST (test_set8, answ_set8, 64, 32, 1, 2); - RUN_TEST (test_set9, answ_set9, 64, 32, 1, 2); - RUN_TEST (test_set10, answ_set10, 64, 32, 1, 2); - RUN_TEST (test_set11, answ_set11, 64, 32, 1, 2); - RUN_TEST (test_set12, answ_set12, 64, 32, 1, 2); - RUN_TEST (test_set13, answ_set13, 64, 32, 1, 2); - RUN_TEST (test_set14, answ_set14, 64, 32, 1, 2); - RUN_TEST (test_set15, answ_set15, 64, 32, 1, 2); - RUN_TEST (test_set16, answ_set16, 64, 32, 1, 1); - - return 0; + int o1 = run_test_s32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_s32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_s32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_s32x2 (test_set3, answ_set3, 64, 32, 2); + int o5 = run_test_s32x2 (test_set4, answ_set4, 64, 32, 2); + int o6 = run_test_s32x2 (test_set5, answ_set5, 64, 32, 2); + int o7 = run_test_s32x2 (test_set6, answ_set6, 64, 32, 2); + int o8 = run_test_s32x2 (test_set7, answ_set7, 64, 32, 2); + int o9 = run_test_s32x2 (test_set8, answ_set8, 64, 32, 2); + int o10 = run_test_s32x2 (test_set9, answ_set9, 64, 32, 2); + int o11 = run_test_s32x2 (test_set10, answ_set10, 64, 32, 2); + int o12 = run_test_s32x2 (test_set11, answ_set11, 64, 32, 2); + int o13 = run_test_s32x2 (test_set12, answ_set12, 64, 32, 2); + int o14 = run_test_s32x2 (test_set13, answ_set13, 64, 32, 2); + int o15 = run_test_s32x2 (test_set14, answ_set14, 64, 32, 2); + int o16 = run_test_s32x2 (test_set15, answ_set15, 64, 32, 2); + int o17 = run_test_s32x2 (test_set16, answ_set16, 64, 32, 1); + + return o1||o2||o3||o4||o5||o6||o7||o8||o9||o10||o11||o12||o13||o14 + ||o15||o16||o17; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 34 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 2 } } */ int __attribute__ ((noinline)) test_vclzq_s8 () { - int i; - int8x16_t a; - int8x16_t b; - int8_t test_set0[16] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8, TEST8 @@ -219,8 +248,8 @@ test_vclzq_s8 () int8_t answ_set0[16] = { 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 1, 9); - return 0; + int o1 = run_testq_s8x16 (test_set0, answ_set0, 128, 8, 9); + return o1; } /* Double scan-assembler-times to take account of unsigned functions. */ @@ -229,10 +258,6 @@ test_vclzq_s8 () int __attribute__ ((noinline)) test_vclzq_s16 () { - int i; - int16x8_t a; - int16x8_t b; - int16_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 }; @@ -252,23 +277,19 @@ test_vclzq_s16 () int16_t answ_set2[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 16, 1, 8); - RUN_TEST (test_set1, answ_set1, 128, 16, 1, 8); - RUN_TEST (test_set2, answ_set2, 128, 16, 1, 1); + int o1 = run_testq_s16x8 (test_set0, answ_set0, 128, 16, 8); + int o2 = run_testq_s16x8 (test_set1, answ_set1, 128, 16, 8); + int o3 = run_testq_s16x8 (test_set2, answ_set2, 128, 16, 1); - return 0; + return o1||o2||o3; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 6 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 2 } } */ int __attribute__ ((noinline)) test_vclzq_s32 () { - int i; - int32x4_t a; - int32x4_t b; - int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; int32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -289,27 +310,23 @@ test_vclzq_s32 () int32_t answ_set7[4] = { 4, 3, 2, 1 }; int32_t answ_set8[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 32, 1, 4); - RUN_TEST (test_set1, answ_set1, 128, 32, 1, 4); - RUN_TEST (test_set2, answ_set2, 128, 32, 1, 4); - RUN_TEST (test_set3, answ_set3, 128, 32, 1, 4); - RUN_TEST (test_set4, answ_set4, 128, 32, 1, 1); + int o1 = run_testq_s32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_s32x4 (test_set1, answ_set1, 128, 32, 4); + int o3 = run_testq_s32x4 (test_set2, answ_set2, 128, 32, 4); + int o4 = run_testq_s32x4 (test_set3, answ_set3, 128, 32, 4); + int o5 = run_testq_s32x4 (test_set4, answ_set4, 128, 32, 1); - return 0; + return o1||o2||o3||o4||o5; } /* Double scan-assembler-times to take account of unsigned functions. */ -/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 10 } } */ +/* { dg-final { scan-assembler-times "clz\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */ /* Unsigned versions. */ int __attribute__ ((noinline)) test_vclz_u8 () { - int i; - uint8x8_t a; - uint8x8_t b; - uint8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7 }; @@ -323,10 +340,10 @@ test_vclz_u8 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 8, 0, 8); - RUN_TEST (test_set1, answ_set1, 64, 8, 0, 1); + int o1 = run_test_u8x8 (test_set0, answ_set0, 64, 8, 8); + int o2 = run_test_u8x8 (test_set1, answ_set1, 64, 8, 1); - return 0; + return o1||o2; } /* ASM scan near test for signed version. */ @@ -334,10 +351,6 @@ test_vclz_u8 () int __attribute__ ((noinline)) test_vclz_u16 () { - int i; - uint16x4_t a; - uint16x4_t b; - uint16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; uint16_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; uint16_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -350,13 +363,13 @@ test_vclz_u16 () uint16_t answ_set3[4] = { 4, 3, 2, 1 }; uint16_t answ_set4[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 16, 0, 4); - RUN_TEST (test_set1, answ_set1, 64, 16, 0, 4); - RUN_TEST (test_set2, answ_set2, 64, 16, 0, 4); - RUN_TEST (test_set3, answ_set3, 64, 16, 0, 4); - RUN_TEST (test_set4, answ_set4, 64, 16, 0, 1); + int o1 = run_test_u16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_u16x4 (test_set1, answ_set1, 64, 16, 4); + int o3 = run_test_u16x4 (test_set2, answ_set2, 64, 16, 4); + int o4 = run_test_u16x4 (test_set3, answ_set3, 64, 16, 4); + int o5 = run_test_u16x4 (test_set4, answ_set4, 64, 16, 1); - return 0; + return o1||o2||o3||o4||o5; } /* ASM scan near test for signed version. */ @@ -364,10 +377,6 @@ test_vclz_u16 () int __attribute__ ((noinline)) test_vclz_u32 () { - int i; - uint32x2_t a; - uint32x2_t b; - uint32_t test_set0[2] = { TEST0, TEST1 }; uint32_t test_set1[2] = { TEST2, TEST3 }; uint32_t test_set2[2] = { TEST4, TEST5 }; @@ -404,25 +413,26 @@ test_vclz_u32 () uint32_t answ_set15[2] = { 2, 1 }; uint32_t answ_set16[2] = { 0, 0 }; - RUN_TEST (test_set0, answ_set0, 64, 32, 0, 2); - RUN_TEST (test_set1, answ_set1, 64, 32, 0, 2); - RUN_TEST (test_set2, answ_set2, 64, 32, 0, 2); - RUN_TEST (test_set3, answ_set3, 64, 32, 0, 2); - RUN_TEST (test_set4, answ_set4, 64, 32, 0, 2); - RUN_TEST (test_set5, answ_set5, 64, 32, 0, 2); - RUN_TEST (test_set6, answ_set6, 64, 32, 0, 2); - RUN_TEST (test_set7, answ_set7, 64, 32, 0, 2); - RUN_TEST (test_set8, answ_set8, 64, 32, 0, 2); - RUN_TEST (test_set9, answ_set9, 64, 32, 0, 2); - RUN_TEST (test_set10, answ_set10, 64, 32, 0, 2); - RUN_TEST (test_set11, answ_set11, 64, 32, 0, 2); - RUN_TEST (test_set12, answ_set12, 64, 32, 0, 2); - RUN_TEST (test_set13, answ_set13, 64, 32, 0, 2); - RUN_TEST (test_set14, answ_set14, 64, 32, 0, 2); - RUN_TEST (test_set15, answ_set15, 64, 32, 0, 2); - RUN_TEST (test_set16, answ_set16, 64, 32, 0, 1); - - return 0; + int o1 = run_test_u32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_u32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_u32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_u32x2 (test_set3, answ_set3, 64, 32, 2); + int o5 = run_test_u32x2 (test_set4, answ_set4, 64, 32, 2); + int o6 = run_test_u32x2 (test_set5, answ_set5, 64, 32, 2); + int o7 = run_test_u32x2 (test_set6, answ_set6, 64, 32, 2); + int o8 = run_test_u32x2 (test_set7, answ_set7, 64, 32, 2); + int o9 = run_test_u32x2 (test_set8, answ_set8, 64, 32, 2); + int o10 = run_test_u32x2 (test_set9, answ_set9, 64, 32, 2); + int o11 = run_test_u32x2 (test_set10, answ_set10, 64, 32, 2); + int o12 = run_test_u32x2 (test_set11, answ_set11, 64, 32, 2); + int o13 = run_test_u32x2 (test_set12, answ_set12, 64, 32, 2); + int o14 = run_test_u32x2 (test_set13, answ_set13, 64, 32, 2); + int o15 = run_test_u32x2 (test_set14, answ_set14, 64, 32, 2); + int o16 = run_test_u32x2 (test_set15, answ_set15, 64, 32, 2); + int o17 = run_test_u32x2 (test_set16, answ_set16, 64, 32, 1); + + return o1||o2||o3||o4||o5||o6||o7||o8||o9||o10||o11||o12||o13||o14 + ||o15||o16||o17; } /* ASM scan near test for signed version. */ @@ -441,9 +451,9 @@ test_vclzq_u8 () uint8_t answ_set0[16] = { 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 0, 9); + int o1 = run_testq_u8x16 (test_set0, answ_set0, 128, 8, 9); - return 0; + return o1; } /* ASM scan near test for signed version. */ @@ -476,11 +486,11 @@ test_vclzq_u16 () 0, 0, 0, 0, 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 16, 0, 8); - RUN_TEST (test_set1, answ_set1, 128, 16, 0, 8); - RUN_TEST (test_set2, answ_set2, 128, 16, 0, 1); + int o1 = run_testq_u16x8 (test_set0, answ_set0, 128, 16, 8); + int o2 = run_testq_u16x8 (test_set1, answ_set1, 128, 16, 8); + int o3 = run_testq_u16x8 (test_set2, answ_set2, 128, 16, 1); - return 0; + return o1||o2||o3; } /* ASM scan near test for signed version. */ @@ -488,10 +498,6 @@ test_vclzq_u16 () int __attribute__ ((noinline)) test_vclzq_u32 () { - int i; - uint32x4_t a; - uint32x4_t b; - uint32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; uint32_t test_set1[4] = { TEST4, TEST5, TEST6, TEST7 }; uint32_t test_set2[4] = { TEST8, TEST9, TEST10, TEST11 }; @@ -512,13 +518,13 @@ test_vclzq_u32 () uint32_t answ_set7[4] = { 4, 3, 2, 1 }; uint32_t answ_set8[4] = { 0, 0, 0, 0 }; - RUN_TEST (test_set0, answ_set0, 128, 32, 0, 4); - RUN_TEST (test_set1, answ_set1, 128, 32, 0, 4); - RUN_TEST (test_set2, answ_set2, 128, 32, 0, 4); - RUN_TEST (test_set3, answ_set3, 128, 32, 0, 4); - RUN_TEST (test_set4, answ_set4, 128, 32, 0, 1); + int o1 = run_testq_u32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_u32x4 (test_set1, answ_set1, 128, 32, 4); + int o3 = run_testq_u32x4 (test_set2, answ_set2, 128, 32, 4); + int o4 = run_testq_u32x4 (test_set3, answ_set3, 128, 32, 4); + int o5 = run_testq_u32x4 (test_set4, answ_set4, 128, 32, 1); - return 0; + return o1||o2||o3||o4||o5; } /* ASM scan near test for signed version. */ diff --git a/gcc/testsuite/gcc.target/aarch64/vneg_s.c b/gcc/testsuite/gcc.target/aarch64/vneg_s.c index 6947526..8ddc4d2 100644 --- a/gcc/testsuite/gcc.target/aarch64/vneg_s.c +++ b/gcc/testsuite/gcc.target/aarch64/vneg_s.c @@ -31,49 +31,24 @@ extern void abort (void); -#define CONCAT(a, b) a##b -#define CONCAT1(a, b) CONCAT (a, b) -#define REG_INFEX64 _ -#define REG_INFEX128 q_ -#define REG_INFEX(reg_len) REG_INFEX##reg_len -#define POSTFIX(reg_len, data_len) \ - CONCAT1 (REG_INFEX (reg_len), s##data_len) -#define DATA_TYPE_32 float -#define DATA_TYPE_64 double -#define DATA_TYPE(data_len) DATA_TYPE_##data_len - -#define FORCE_SIMD_INST64_8(data) -#define FORCE_SIMD_INST64_16(data) -#define FORCE_SIMD_INST64_32(data) -#define FORCE_SIMD_INST64_64(data) force_simd (data) -#define FORCE_SIMD_INST128_8(data) -#define FORCE_SIMD_INST128_16(data) -#define FORCE_SIMD_INST128_32(data) -#define FORCE_SIMD_INST128_64(data) - -#define FORCE_SIMD_INST(reg_len, data_len, data) \ - CONCAT1 (FORCE_SIMD_INST, reg_len##_##data_len) (data) -#define LOAD_INST(reg_len, data_len) \ - CONCAT1 (vld1, POSTFIX (reg_len, data_len)) -#define NEG_INST(reg_len, data_len) \ - CONCAT1 (vneg, POSTFIX (reg_len, data_len)) - -#define RUN_TEST(test_set, answ_set, reg_len, data_len, n, a, b) \ - { \ - int i; \ - INHIB_OPTIMIZATION; \ - (a) = LOAD_INST (reg_len, data_len) (test_set); \ - (b) = LOAD_INST (reg_len, data_len) (answ_set); \ - FORCE_SIMD_INST (reg_len, data_len, a) \ - a = NEG_INST (reg_len, data_len) (a); \ - FORCE_SIMD_INST (reg_len, data_len, a) \ - for (i = 0; i < n; i++) \ - { \ - INHIB_OPTIMIZATION; \ - if (a[i] != b[i]) \ - return 1; \ - } \ - } +#define BUILD_TEST(type, size, lanes) \ +int __attribute__((noipa,noinline)) \ +run_test##type##size##x##lanes (int##size##_t* test_set, \ + int##size##_t* answ_set, \ + int reg_len, int data_len, int n) \ +{ \ + int i; \ + int##size##x##lanes##_t a = vld1##type##size (test_set); \ + int##size##x##lanes##_t b = vld1##type##size (answ_set); \ + a = vneg##type##size (a); \ + for (i = 0; i < n; i++) \ + { \ + INHIB_OPTIMIZATION; \ + if (a[i] != b[i]) \ + return 1; \ + } \ + return 0; \ +} \ #define RUN_TEST_SCALAR(test_val, answ_val, a, b) \ { \ @@ -87,12 +62,19 @@ extern void abort (void); force_simd (res); \ } +BUILD_TEST (_s, 8, 8) +BUILD_TEST (_s, 16, 4) +BUILD_TEST (_s, 32, 2) +BUILD_TEST (_s, 64, 1) + +BUILD_TEST (q_s, 8, 16) +BUILD_TEST (q_s, 16, 8) +BUILD_TEST (q_s, 32, 4) +BUILD_TEST (q_s, 64, 2) + int __attribute__ ((noinline)) test_vneg_s8 () { - int8x8_t a; - int8x8_t b; - int8_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN }; @@ -100,9 +82,9 @@ test_vneg_s8 () ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SCHAR_MIN + 1, SCHAR_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 8, 8, a, b); + int o1 = run_test_s8x8 (test_set0, answ_set0, 64, 8, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8b, v\[0-9\]+\.8b" 1 } } */ @@ -110,29 +92,23 @@ test_vneg_s8 () int __attribute__ ((noinline)) test_vneg_s16 () { - int16x4_t a; - int16x4_t b; - int16_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int16_t test_set1[4] = { TEST4, TEST5, SHRT_MAX, SHRT_MIN }; int16_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 }; int16_t answ_set1[4] = { ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 16, 4, a, b); - RUN_TEST (test_set1, answ_set1, 64, 16, 4, a, b); + int o1 = run_test_s16x4 (test_set0, answ_set0, 64, 16, 4); + int o2 = run_test_s16x4 (test_set1, answ_set1, 64, 16, 4); - return 0; + return o1||o2; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 2 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4h, v\[0-9\]+\.4h" 1 } } */ int __attribute__ ((noinline)) test_vneg_s32 () { - int32x2_t a; - int32x2_t b; - int32_t test_set0[2] = { TEST0, TEST1 }; int32_t test_set1[2] = { TEST2, TEST3 }; int32_t test_set2[2] = { TEST4, TEST5 }; @@ -143,22 +119,19 @@ test_vneg_s32 () int32_t answ_set2[2] = { ANSW4, ANSW5 }; int32_t answ_set3[2] = { INT_MIN + 1, INT_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 32, 2, a, b); - RUN_TEST (test_set1, answ_set1, 64, 32, 2, a, b); - RUN_TEST (test_set2, answ_set2, 64, 32, 2, a, b); - RUN_TEST (test_set3, answ_set3, 64, 32, 2, a, b); + int o1 = run_test_s32x2 (test_set0, answ_set0, 64, 32, 2); + int o2 = run_test_s32x2 (test_set1, answ_set1, 64, 32, 2); + int o3 = run_test_s32x2 (test_set2, answ_set2, 64, 32, 2); + int o4 = run_test_s32x2 (test_set3, answ_set3, 64, 32, 2); - return 0; + return o1||o2||o3||o4; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 4 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2s, v\[0-9\]+\.2s" 1 } } */ int __attribute__ ((noinline)) test_vneg_s64 () { - int64x1_t a; - int64x1_t b; - int64_t test_set0[1] = { TEST0 }; int64_t test_set1[1] = { TEST1 }; int64_t test_set2[1] = { TEST2 }; @@ -177,16 +150,16 @@ test_vneg_s64 () int64_t answ_set6[1] = { LLONG_MIN + 1 }; int64_t answ_set7[1] = { LLONG_MIN }; - RUN_TEST (test_set0, answ_set0, 64, 64, 1, a, b); - RUN_TEST (test_set1, answ_set1, 64, 64, 1, a, b); - RUN_TEST (test_set2, answ_set2, 64, 64, 1, a, b); - RUN_TEST (test_set3, answ_set3, 64, 64, 1, a, b); - RUN_TEST (test_set4, answ_set4, 64, 64, 1, a, b); - RUN_TEST (test_set5, answ_set5, 64, 64, 1, a, b); - RUN_TEST (test_set6, answ_set6, 64, 64, 1, a, b); - RUN_TEST (test_set7, answ_set7, 64, 64, 1, a, b); + int o1 = run_test_s64x1 (test_set0, answ_set0, 64, 64, 1); + int o2 = run_test_s64x1 (test_set1, answ_set1, 64, 64, 1); + int o3 = run_test_s64x1 (test_set2, answ_set2, 64, 64, 1); + int o4 = run_test_s64x1 (test_set3, answ_set3, 64, 64, 1); + int o5 = run_test_s64x1 (test_set4, answ_set4, 64, 64, 1); + int o6 = run_test_s64x1 (test_set5, answ_set5, 64, 64, 1); + int o7 = run_test_s64x1 (test_set6, answ_set6, 64, 64, 1); + int o8 = run_test_s64x1 (test_set7, answ_set7, 64, 64, 1); - return 0; + return o1||o2||o3||o4||o5||o6||o7||o8; } int __attribute__ ((noinline)) @@ -206,14 +179,11 @@ test_vnegd_s64 () return 0; } -/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 16 } } */ +/* { dg-final { scan-assembler-times "neg\\td\[0-9\]+, d\[0-9\]+" 8 } } */ int __attribute__ ((noinline)) test_vnegq_s8 () { - int8x16_t a; - int8x16_t b; - int8_t test_set0[16] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SCHAR_MAX, SCHAR_MIN, 4, 8, 15, 16, 23, 42, -1, -2 @@ -224,9 +194,9 @@ test_vnegq_s8 () -4, -8, -15, -16, -23, -42, 1, 2 }; - RUN_TEST (test_set0, answ_set0, 128, 8, 8, a, b); + int o1 = run_testq_s8x16 (test_set0, answ_set0, 128, 8, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.16b, v\[0-9\]+\.16b" 1 } } */ @@ -234,9 +204,6 @@ test_vnegq_s8 () int __attribute__ ((noinline)) test_vnegq_s16 () { - int16x8_t a; - int16x8_t b; - int16_t test_set0[8] = { TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, SHRT_MAX, SHRT_MIN }; @@ -244,9 +211,9 @@ test_vnegq_s16 () ANSW0, ANSW1, ANSW2, ANSW3, ANSW4, ANSW5, SHRT_MIN + 1, SHRT_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 16, 8, a, b); + int o1 = run_testq_s16x8 (test_set0, answ_set0, 128, 16, 8); - return 0; + return o1; } /* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.8h, v\[0-9\]+\.8h" 1 } } */ @@ -254,29 +221,23 @@ test_vnegq_s16 () int __attribute__ ((noinline)) test_vnegq_s32 () { - int32x4_t a; - int32x4_t b; - int32_t test_set0[4] = { TEST0, TEST1, TEST2, TEST3 }; int32_t test_set1[4] = { TEST4, TEST5, INT_MAX, INT_MIN }; int32_t answ_set0[4] = { ANSW0, ANSW1, ANSW2, ANSW3 }; int32_t answ_set1[4] = { ANSW4, ANSW5, INT_MIN + 1, INT_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 32, 4, a, b); - RUN_TEST (test_set1, answ_set1, 128, 32, 4, a, b); + int o1 = run_testq_s32x4 (test_set0, answ_set0, 128, 32, 4); + int o2 = run_testq_s32x4 (test_set1, answ_set1, 128, 32, 4); - return 0; + return o1||o2; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 2 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.4s, v\[0-9\]+\.4s" 1 } } */ int __attribute__ ((noinline)) test_vnegq_s64 () { - int64x2_t a; - int64x2_t b; - int64_t test_set0[2] = { TEST0, TEST1 }; int64_t test_set1[2] = { TEST2, TEST3 }; int64_t test_set2[2] = { TEST4, TEST5 }; @@ -287,15 +248,15 @@ test_vnegq_s64 () int64_t answ_set2[2] = { ANSW4, ANSW5 }; int64_t answ_set3[2] = { LLONG_MIN + 1, LLONG_MIN }; - RUN_TEST (test_set0, answ_set0, 128, 64, 2, a, b); - RUN_TEST (test_set1, answ_set1, 128, 64, 2, a, b); - RUN_TEST (test_set2, answ_set2, 128, 64, 2, a, b); - RUN_TEST (test_set3, answ_set3, 128, 64, 2, a, b); + int o1 = run_testq_s64x2 (test_set0, answ_set0, 128, 64, 2); + int o2 = run_testq_s64x2 (test_set1, answ_set1, 128, 64, 2); + int o3 = run_testq_s64x2 (test_set2, answ_set2, 128, 64, 2); + int o4 = run_testq_s64x2 (test_set3, answ_set3, 128, 64, 2); - return 0; + return o1||o2||o2||o4; } -/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 4 } } */ +/* { dg-final { scan-assembler-times "neg\\tv\[0-9\]+\.2d, v\[0-9\]+\.2d" 1 } } */ int main (int argc, char **argv) diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c new file mode 100644 index 0000000..14e0414 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-1.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c new file mode 100644 index 0000000..c259010 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-2.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c new file mode 100644 index 0000000..9a2065f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-3.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN signed +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c new file mode 100644 index 0000000..77c3dce --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-4.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c new file mode 100644 index 0000000..ae30e86 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-5.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c new file mode 100644 index 0000000..882f3d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/xtn-combine-6.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#define SIGN unsigned +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE1 * restrict a, SIGN TYPE2 *b, int n) +{ + for (int i = 0; i < n; i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tuzp1\t} 1 } } */ +/* { dg-final { scan-assembler-not {\txtn\t} } } */ +/* { dg-final { scan-assembler-not {\txtn2\t} } } */ diff --git a/gcc/testsuite/gcc.target/i386/387-12.c b/gcc/testsuite/gcc.target/i386/387-12.c index 7fe50a2..ba86536 100644 --- a/gcc/testsuite/gcc.target/i386/387-12.c +++ b/gcc/testsuite/gcc.target/i386/387-12.c @@ -1,6 +1,6 @@ /* PR target/26915 */ -/* { dg-do compile } */ -/* { dg-options "-O -m32 -mfpmath=387 -mfancy-math-387" } */ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O -mfpmath=387 -mfancy-math-387" } */ double testm0(void) { diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c new file mode 100644 index 0000000..0055193 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1a.c @@ -0,0 +1,13 @@ +/* { dg-do compile} */ +/* { dg-options "-O2 -mavx512fp16" } */ + +#include <immintrin.h> + +__m512h +__attribute__ ((noinline, noclone)) +test_mm512_set1_pch (_Float16 _Complex A) +{ + return _mm512_set1_pch(A); +} + +/* { dg-final { scan-assembler "vbroadcastss\[ \\t\]+\[^\n\r\]*%zmm\[01\]" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c new file mode 100644 index 0000000..450d7e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16-set1-pch-1b.c @@ -0,0 +1,42 @@ +/* { dg-do run { target avx512fp16 } } */ +/* { dg-options "-O2 -mavx512fp16" } */ + +#include<stdio.h> +#include <math.h> +#include <complex.h> + +static void do_test (void); + +#define DO_TEST do_test +#define AVX512FP16 + +#include <immintrin.h> +#include "avx512-check.h" + +static void +do_test (void) +{ + _Float16 _Complex fc = 1.0 + 1.0*I; + union + { + _Float16 _Complex a; + float b; + } u = { .a = fc }; + float ff= u.b; + + typedef union + { + float fp[16]; + __m512h m512h; + } u1; + + __m512h test512 = _mm512_set1_pch(fc); + + u1 test; + test.m512h = test512; + for (int i = 0; i<16; i++) + { + if (test.fp[i] != ff) abort(); + } + +} diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c new file mode 100644 index 0000000..4c5624f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1a.c @@ -0,0 +1,20 @@ +/* { dg-do compile} */ +/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */ + +#include <immintrin.h> + +__m256h +__attribute__ ((noinline, noclone)) +test_mm256_set1_pch (_Float16 _Complex A) +{ + return _mm256_set1_pch(A); +} + +__m128h +__attribute__ ((noinline, noclone)) +test_mm_set1_pch (_Float16 _Complex A) +{ + return _mm_set1_pch(A); +} + +/* { dg-final { scan-assembler-times "vbroadcastss" 2 } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c new file mode 100644 index 0000000..aebff14 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-set1-pch-1b.c @@ -0,0 +1,57 @@ +/* { dg-do run { target avx512fp16 } } */ +/* { dg-options "-O2 -mavx512fp16 -mavx512vl" } */ + +#include<stdio.h> +#include <math.h> +#include <complex.h> + +static void do_test (void); + +#define DO_TEST do_test +#define AVX512FP16 + +#include <immintrin.h> +#include "avx512-check.h" + +static void +do_test (void) +{ + _Float16 _Complex fc = 1.0 + 1.0*I; + union + { + _Float16 _Complex a; + float b; + } u = { .a = fc }; + float ff= u.b; + + typedef union + { + float fp[8]; + __m256h m256h; + } u1; + + __m256h test256 = _mm256_set1_pch(fc); + + u1 test1; + test1.m256h = test256; + for (int i = 0; i<8; i++) + { + if (test1.fp[i] != ff) abort(); + } + + typedef union + { + float fp[4]; + __m128h m128h; + } u2; + + __m128h test128 = _mm_set1_pch(fc); + + u2 test2; + test2.m128h = test128; + for (int i = 0; i<4; i++) + { + if (test2.fp[i] != ff) abort(); + } + +} diff --git a/gcc/testsuite/gcc.target/i386/pr102761.c b/gcc/testsuite/gcc.target/i386/pr102761.c new file mode 100644 index 0000000..58ff27e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102761.c @@ -0,0 +1,11 @@ +/* PR target/102761 */ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +int foo (void); + +void +bar (void) +{ + asm volatile ("%a0" : : "X"(foo () ? 2 : 1)); /* { dg-error "invalid constraints for operand" } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr102812.c b/gcc/testsuite/gcc.target/i386/pr102812.c new file mode 100644 index 0000000..bad4fa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr102812.c @@ -0,0 +1,12 @@ +/* PR target/102812 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse4 -mno-avx" } */ +/* { dg-final { scan-assembler-not "vmovdqa64\t" } } */ +/* { dg-final { scan-assembler "movdqa\t" } } */ + +typedef _Float16 v8hf __attribute__((__vector_size__ (16))); + +v8hf t (_Float16 a) +{ + return (v8hf) {a, 0, 0, 0, 0, 0, 0, 0}; +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1.c b/gcc/testsuite/gcc.target/powerpc/builtins-1.c index 83aed5a..2dafa90 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtins-1.c +++ b/gcc/testsuite/gcc.target/powerpc/builtins-1.c @@ -317,10 +317,10 @@ int main () /* { dg-final { scan-assembler-times "vctuxs" 2 } } */ /* { dg-final { scan-assembler-times "vmrghb" 4 { target be } } } */ -/* { dg-final { scan-assembler-times "vmrghb" 5 { target le } } } */ +/* { dg-final { scan-assembler-times "vmrghb" 6 { target le } } } */ /* { dg-final { scan-assembler-times "vmrghh" 8 } } */ -/* { dg-final { scan-assembler-times "xxmrghw" 8 } } */ -/* { dg-final { scan-assembler-times "xxmrglw" 8 } } */ +/* { dg-final { scan-assembler-times "xxmrghw" 4 } } */ +/* { dg-final { scan-assembler-times "xxmrglw" 4 } } */ /* { dg-final { scan-assembler-times "vmrglh" 8 } } */ /* { dg-final { scan-assembler-times "xxlnor" 6 } } */ /* { dg-final { scan-assembler-times {\mvpkudus\M} 1 } } */ @@ -347,7 +347,7 @@ int main () /* { dg-final { scan-assembler-times "vspltb" 6 } } */ /* { dg-final { scan-assembler-times "vspltw" 0 } } */ /* { dg-final { scan-assembler-times "vmrgow" 8 } } */ -/* { dg-final { scan-assembler-times "vmrglb" 5 { target le } } } */ +/* { dg-final { scan-assembler-times "vmrglb" 4 { target le } } } */ /* { dg-final { scan-assembler-times "vmrglb" 6 { target be } } } */ /* { dg-final { scan-assembler-times "vmrgew" 8 } } */ /* { dg-final { scan-assembler-times "vsplth" 8 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c b/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c new file mode 100644 index 0000000..78e72ac --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/p10_vec_xl_sext.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target int128 } */ +/* { dg-require-effective-target power10_ok } */ +/* { dg-options "-mdejagnu-cpu=power10 -O2" } */ + +#include <altivec.h> + +vector signed __int128 +foo1 (signed long a, signed char *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo2 (signed long a, signed short *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo3 (signed long a, signed int *b) +{ + return vec_xl_sext (a, b); +} + +vector signed __int128 +foo4 (signed long a, signed long *b) +{ + return vec_xl_sext (a, b); +} + +/* { dg-final { scan-assembler-times {\mvextsd2q\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mvextsb2d\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvextsh2d\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mvextsw2d\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c index e8ecd9c..36b9bd7 100644 --- a/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c +++ b/gcc/testsuite/gcc.target/powerpc/sse4_2-pcmpgtq.c @@ -1,6 +1,6 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mvsx" } */ -/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-O2 -mpower8-vector" } */ +/* { dg-require-effective-target p8vector_hw } */ #ifndef CHECK_H #define CHECK_H "sse4_2-check.h" diff --git a/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 index 3b01ad3..8829fd1 100644 --- a/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 +++ b/gcc/testsuite/gfortran.dg/bind-c-char-descr.f90 @@ -2,7 +2,6 @@ ! ! Contributed by José Rui Faustino de Sousa ! -! Note the xfail issue below for 'strg_print_2("abc") program strp_p @@ -24,13 +23,18 @@ program strp_p if (len(str) /= 3 .or. str /= "abc") stop 1 if (len(strp_1) /= 3 .or. strp_1 /= "abc") stop 2 if (len(strp_2) /= 3 .or. strp_2 /= "abc") stop 3 - call strg_print_0("abc") ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(str) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(strp_1) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_0(strp_2) ! Error (10.0.0) or segmentation fault (9.1.0) - call strg_print_1(strp_1) ! Not yet supported + call strg_print_0("abc") + call strg_print_0(str) + call strg_print_0(strp_1) + call strg_print_0(strp_2) + call strg_print_0_c("abc") + call strg_print_0_c(str) + call strg_print_0_c(strp_1) + call strg_print_0_c(strp_2) + call strg_print_1(strp_1) + call strg_print_1_c(strp_1) - call strg_print_2("abc", xfail=.true.) + call strg_print_2("abc") call strg_print_2(str) call strg_print_2(strp_1) call strg_print_2(strp_2) @@ -42,14 +46,21 @@ program strp_p contains - subroutine strg_print_0(this) bind(c) ! Error (10.0.0 20191106) or warning (9.1.0) issued with bind(c) + subroutine strg_print_0 (this) character(len=*, kind=c_char), target, intent(in) :: this if (len (this) /= 3) stop 10 if (this /= "abc") stop 11 end subroutine strg_print_0 + + subroutine strg_print_0_c (this) bind(c) + character(len=*, kind=c_char), target, intent(in) :: this + + if (len (this) /= 3) stop 10 + if (this /= "abc") stop 11 + end subroutine strg_print_0_c - subroutine strg_print_1(this) bind(c) ! Not yet supported with bind(c) + subroutine strg_print_1 (this) bind(c) character(len=:, kind=c_char), pointer, intent(in) :: this character(len=:), pointer :: strn @@ -63,26 +74,34 @@ contains if (this /= "abc") stop 25 end if end subroutine strg_print_1 + + subroutine strg_print_1_c (this) bind(c) + character(len=:, kind=c_char), pointer, intent(in) :: this + character(len=:), pointer :: strn + + if (.not. associated (this)) stop 20 + if (len (this) /= 3) stop 21 + if (this /= "abc") stop 22 + strn => this + if (.not. associated (strn)) stop 23 + if(associated(strn))then + if (len (this) /= 3) stop 24 + if (this /= "abc") stop 25 + end if + end subroutine strg_print_1_c - subroutine strg_print_2(this, xfail) + subroutine strg_print_2(this) use, intrinsic :: iso_c_binding, only: & c_loc, c_f_pointer type(*), target, intent(in) :: this(..) - logical, optional, value :: xfail character(len=l), pointer :: strn call c_f_pointer(c_loc(this), strn) if (.not. associated (strn)) stop 30 - if(associated(strn))then + if (associated(strn)) then if (len (strn) /= 3) stop 31 - if (strn /= "abc") then - if (present (xfail)) then - print *, 'INVALID STRING - EXPECTED "abc" / PR47225' - else - stop 32 - end if - end if + if (strn /= "abc") stop 32 end if end subroutine strg_print_2 diff --git a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c index 48c03d4..0b7bae8 100644 --- a/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c +++ b/gcc/testsuite/gfortran.dg/bind-c-contiguous-5.c @@ -88,6 +88,7 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, basic_check (z, is_cont || num == 2); if (!is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); @@ -97,24 +98,55 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + check_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (y, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (y, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (y, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (z, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (z, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (z, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#else +#error "Unsupported __BYTE_ORDER__" +#endif } else if (num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); +#endif } else if (num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9*4) != 0) + __builtin_abort (); +#endif } else __builtin_abort (); @@ -144,6 +176,7 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, // intent_in if (intent_in && !is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); @@ -153,24 +186,53 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); check_str (z, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); check_str (z, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#else + check_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (y, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (y, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (y, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); + check_str (z, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + check_str (z, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + check_str (z, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#endif } else if (intent_in && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0a\0\0\0b\0\0\0c\0\0\0g\0\0\0h\0\0\0i\0\0\0n\0\0\0o\0\0\0p", 9*4) != 0) + __builtin_abort (); +#endif } else if (intent_in && num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m\0\0\0", 9) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0d\0\0\0e\0\0\0f\0\0\0g\0\0\0h\0\0\0i\0\0\0j\0\0\0l\0\0\0m", 9) != 0) + __builtin_abort (); +#endif } else if (intent_in) __builtin_abort (); @@ -179,15 +241,22 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, if (is_cont && num == 1) { /* Copy in - set the value to check that no copy out is done. */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy ((char*) x->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); memcpy ((char*) y->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); memcpy ((char*) z->base_addr, "1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9\0\0\0", 9*4); +#else + memcpy ((char*) x->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); + memcpy ((char*) y->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); + memcpy ((char*) z->base_addr, "\0\0\0""1\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""6\0\0\0""7\0\0\0""8\0\0\0""9", 9*4); +#endif } return addr1; } // !intent_in if (!is_cont && num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ check_str (x, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero); check_str (x, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one); check_str (x, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two); @@ -197,15 +266,35 @@ do_call (CFI_cdesc_t *x, CFI_cdesc_t *y, CFI_cdesc_t *z, check_str (z, "A\0\0\0B\0\0\0C\0\0\0", 3*4, zero); check_str (z, "D\0\0\0E\0\0\0F\0\0\0", 3*4, one); check_str (z, "G\0\0\0H\0\0\0I\0\0\0", 3*4, two); +#else + check_str (x, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (x, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (x, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); + check_str (y, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (y, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (y, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); + check_str (z, "\0\0\0A\0\0\0B\0\0\0C", 3*4, zero); + check_str (z, "\0\0\0D\0\0\0E\0\0\0F", 3*4, one); + check_str (z, "\0\0\0G\0\0\0H\0\0\0I", 3*4, two); +#endif } else { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ if (memcmp ((const char*) x->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) y->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); if (memcmp ((const char*) z->base_addr, "A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I\0\0\0", 9*4) != 0) __builtin_abort (); +#else + if (memcmp ((const char*) x->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) y->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); + if (memcmp ((const char*) z->base_addr, "\0\0\0A\0\0\0B\0\0\0C\0\0\0D\0\0\0E\0\0\0F\0\0\0G\0\0\0H\0\0\0I", 9*4) != 0) + __builtin_abort (); +#endif } return addr1; } @@ -275,15 +364,27 @@ reset_var (CFI_cdesc_t *x, int num) if (num == 1) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ set_str (x, "a\0\0\0b\0\0\0c\0\0\0", 3*4, zero); set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); set_str (x, "n\0\0\0o\0\0\0p\0\0\0", 3*4, two); +#else + set_str (x, "\0\0\0a\0\0\0b\0\0\0c", 3*4, zero); + set_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + set_str (x, "\0\0\0n\0\0\0o\0\0\0p", 3*4, two); +#endif } else if (num == 2) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ set_str (x, "d\0\0\0e\0\0\0f\0\0\0", 3*4, zero); set_str (x, "g\0\0\0h\0\0\0i\0\0\0", 3*4, one); set_str (x, "j\0\0\0l\0\0\0m\0\0\0", 3*4, two); +#else + set_str (x, "\0\0\0d\0\0\0e\0\0\0f", 3*4, zero); + set_str (x, "\0\0\0g\0\0\0h\0\0\0i", 3*4, one); + set_str (x, "\0\0\0j\0\0\0l\0\0\0m", 3*4, two); +#endif } else __builtin_abort (); diff --git a/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 new file mode 100644 index 0000000..d9e193a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/shape-bindc.f90 @@ -0,0 +1,77 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.1 SHAPE +! +! The description of the intrinsic function SHAPE in ISO/IEC 1539-1:2010 +! is changed for an assumed-rank array that is associated with an +! assumed-size array; an assumed-size array has no shape, but in this +! case the result has a value equal to +! [ (SIZE (ARRAY, I, KIND), I=1,RANK (ARRAY)) ] +! with KIND omitted from SIZE if it was omitted from SHAPE. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + +contains + + subroutine testit (a) bind(c) + integer :: a(..) + + integer :: r + r = rank(a) + + block + integer :: s(r) + s = shape(a) + do i = 1, r + if (s(i) .ne. size(a,i)) stop 101 + end do + end block + + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 new file mode 100644 index 0000000..e17ca88 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/shape-poly.f90 @@ -0,0 +1,89 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.1 SHAPE +! +! The description of the intrinsic function SHAPE in ISO/IEC 1539-1:2010 +! is changed for an assumed-rank array that is associated with an +! assumed-size array; an assumed-size array has no shape, but in this +! case the result has a value equal to +! [ (SIZE (ARRAY, I, KIND), I=1,RANK (ARRAY)) ] +! with KIND omitted from SIZE if it was omitted from SHAPE. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is the polymorphic version of shape.f90. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + +contains + + subroutine testit (a) + use m + class(t) :: a(..) + + integer :: r + r = rank(a) + + block + integer :: s(r) + s = shape(a) + do i = 1, r + if (s(i) .ne. size(a,i)) stop 101 + end do + end block + + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 new file mode 100644 index 0000000..132ca50 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/size-bindc.f90 @@ -0,0 +1,106 @@ +! Reported as pr94070. +! { dg-do run } +! +! TS 29113 +! 6.4.2 SIZE +! +! The description of the intrinsic function SIZE in ISO/IEC 1539-1:2010 +! is changed in the following cases: +! +! (1) for an assumed-rank object that is associated with an assumed-size +! array, the result has the value −1 if DIM is present and equal to the +! rank of ARRAY, and a negative value that is equal to +! PRODUCT ( [ (SIZE (ARRAY, I, KIND), I=1, RANK (ARRAY)) ] ) +! if DIM is not present; +! +! (2) for an assumed-rank object that is associated with a scalar, the +! result has the value 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + integer :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test scalars. + call test0 (x) + call test0 (-1) + call test0 (x1(1)) + +contains + + subroutine testit (a, r, sizes) bind(c) + integer :: a(..) + integer :: r + integer :: sizes(r) + + integer :: totalsize, thissize + totalsize = 1 + + if (r .ne. rank(a)) stop 101 + + do i = 1, r + thissize = size (a, i) + print *, 'got size ', thissize, ' expected ', sizes(i) + if (thissize .ne. sizes(i)) stop 102 + totalsize = totalsize * thissize + end do + + if (size(a) .ne. totalsize) stop 103 + end subroutine + + subroutine test0 (a) bind(c) + integer :: a(..) + + if (size (a) .ne. 1) stop 103 + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + integer :: sizes(1) + sizes(1) = -1 + call testit (a, 1, sizes) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + integer :: sizes(3) + sizes(1) = u1 - l1 + 1 + sizes(2) = u2 - l2 + 1 + sizes(3) = -1 + + call testit (a, 3, sizes) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 new file mode 100644 index 0000000..2241ab8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/size-poly.f90 @@ -0,0 +1,118 @@ +! Reported as pr94070. +! { dg-do run } +! +! TS 29113 +! 6.4.2 SIZE +! +! The description of the intrinsic function SIZE in ISO/IEC 1539-1:2010 +! is changed in the following cases: +! +! (1) for an assumed-rank object that is associated with an assumed-size +! array, the result has the value −1 if DIM is present and equal to the +! rank of ARRAY, and a negative value that is equal to +! PRODUCT ( [ (SIZE (ARRAY, I, KIND), I=1, RANK (ARRAY)) ] ) +! if DIM is not present; +! +! (2) for an assumed-rank object that is associated with a scalar, the +! result has the value 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is the polymorphic version of size.f90. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + type(t) :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call test1 (y1) + p1 => x1 + call test1 (p1) + allocate (a1(5)) + call test1 (a1) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test scalars. + call test0 (x) + call test0 (x1(1)) + +contains + + subroutine testit (a, r, sizes) + use m + class(t) :: a(..) + integer :: r + integer :: sizes(r) + + integer :: totalsize, thissize + totalsize = 1 + + if (r .ne. rank(a)) stop 101 + + do i = 1, r + thissize = size (a, i) + print *, 'got size ', thissize, ' expected ', sizes(i) + if (thissize .ne. sizes(i)) stop 102 + totalsize = totalsize * thissize + end do + + if (size(a) .ne. totalsize) stop 103 + end subroutine + + subroutine test0 (a) + use m + class(t) :: a(..) + + if (size (a) .ne. 1) stop 103 + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + integer :: sizes(1) + sizes(1) = -1 + call testit (a, 1, sizes) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + integer :: sizes(3) + sizes(1) = u1 - l1 + 1 + sizes(2) = u2 - l2 + 1 + sizes(3) = -1 + + call testit (a, 3, sizes) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 b/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 new file mode 100644 index 0000000..e771836 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/ubound-bindc.f90 @@ -0,0 +1,129 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.3 UBOUND +! +! The description of the intrinsic function UBOUND in ISO/IEC +! 1539-1:2010 is changed for an assumed-rank object that is associated +! with an assumed-size array; the result of UBOUND (ARRAY, RANK(ARRAY), +! KIND) has a value equal to LBOUND (ARRAY, RANK (ARRAY), KIND) −2 with +! KIND omitted from LBOUND if it was omitted from UBOUND. +! +! NOTE 6.2 +! If LBOUND or UBOUND is invoked for an assumed-rank object that is +! associated with a scalar and DIM is absent, the result is a zero-sized +! array. LBOUND or UBOUND cannot be invoked for an assumed-rank object +! that is associated with a scalar if DIM is present because the rank of +! a scalar is zero and DIM must be ≥ 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. + +program test + + ! Define some arrays for testing. + integer, target :: x1(5) + integer :: y1(0:9) + integer, pointer :: p1(:) + integer, allocatable :: a1(:) + integer, target :: x3(2,3,4) + integer :: y3(0:1,-3:-1,4) + integer, pointer :: p3(:,:,:) + integer, allocatable :: a3(:,:,:) + integer :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call testit2(x1, shape(x1)) + call test1 (y1) + call testit2(y1, shape(y1)) + p1 => x1 + call testit2(p1, shape(p1)) + call testit2p(p1, lbound(p1), shape(p1)) + call test1 (p1) + p1(77:) => x1 + call testit2p(p1, [77], shape(p1)) + allocate (a1(5)) + call testit2(a1, shape(a1)) + call testit2a(a1, lbound(a1), shape(a1)) + call test1 (a1) + deallocate(a1) + allocate (a1(-38:5)) + call test1 (a1) + call testit2(a1, shape(a1)) + call testit2a(a1, [-38], shape(a1)) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test some scalars. + call test0 (x) + call test0 (-1) + call test0 (x1(1)) + +contains + + subroutine testit (a) bind(c) + integer :: a(..) + integer :: r + r = rank(a) + if (any (lbound (a) .ne. 1)) stop 101 + if (ubound (a, r) .ne. -1) stop 102 + end subroutine + + subroutine testit2(a, shape) bind(c) + integer :: a(..) + integer :: shape(:) + if (rank(a) /= size(shape)) stop 111 + if (any (lbound(a) /= 1)) stop 112 + if (any (ubound(a) /= shape)) stop 113 + end subroutine + + subroutine testit2a(a,lbound2, shape2) bind(c) + integer, allocatable :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 121 + if (any (lbound(a) /= lbound2)) stop 122 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 123 + if (any (shape(a) /= shape2)) stop 124 + if (sum (shape(a)) /= size(a)) stop 125 + end subroutine + + subroutine testit2p(a, lbound2, shape2) bind(c) + integer, pointer :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 131 + if (any (lbound(a) /= lbound2)) stop 132 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 133 + if (any (shape(a) /= shape2)) stop 134 + if (sum (shape(a)) /= size(a)) stop 135 + end subroutine + + subroutine test0 (a) bind(c) + integer :: a(..) + if (rank (a) .ne. 0) stop 141 + if (size (lbound (a)) .ne. 0) stop 142 + if (size (ubound (a)) .ne. 0) stop 143 + end subroutine + + subroutine test1 (a) bind(c) + integer :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) bind(c) + implicit none + integer :: l1, u1, l2, u2 + integer :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 b/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 new file mode 100644 index 0000000..333a253 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c-interop/ubound-poly.f90 @@ -0,0 +1,145 @@ +! { dg-do run } +! +! TS 29113 +! 6.4.3 UBOUND +! +! The description of the intrinsic function UBOUND in ISO/IEC +! 1539-1:2010 is changed for an assumed-rank object that is associated +! with an assumed-size array; the result of UBOUND (ARRAY, RANK(ARRAY), +! KIND) has a value equal to LBOUND (ARRAY, RANK (ARRAY), KIND) −2 with +! KIND omitted from LBOUND if it was omitted from UBOUND. +! +! NOTE 6.2 +! If LBOUND or UBOUND is invoked for an assumed-rank object that is +! associated with a scalar and DIM is absent, the result is a zero-sized +! array. LBOUND or UBOUND cannot be invoked for an assumed-rank object +! that is associated with a scalar if DIM is present because the rank of +! a scalar is zero and DIM must be ≥ 1. +! +! The idea here is that the main program passes some arrays to a test +! subroutine with an assumed-size dummy, which in turn passes that to a +! subroutine with an assumed-rank dummy. +! +! This is like ubound.f90, but using polymorphic arrays instead of integer +! arrays. + +module m + type :: t + integer :: id + real :: xyz(3) + end type +end module + +program test + use m + + ! Define some arrays for testing. + type(t), target :: x1(5) + type(t) :: y1(0:9) + class(t), pointer :: p1(:) + class(t), allocatable :: a1(:) + type(t), target :: x3(2,3,4) + type(t) :: y3(0:1,-3:-1,4) + class(t), pointer :: p3(:,:,:) + type(t), allocatable :: a3(:,:,:) + type(t) :: x + + ! Test the 1-dimensional arrays. + call test1 (x1) + call testit2(x1, shape(x1)) + call test1 (y1) + call testit2(y1, shape(y1)) + p1 => x1 + call testit2(p1, shape(p1)) + call testit2p(p1, lbound(p1), shape(p1)) + call test1 (p1) + p1(77:) => x1 + call testit2p(p1, [77], shape(p1)) + allocate (a1(5)) + call testit2(a1, shape(a1)) + call testit2a(a1, lbound(a1), shape(a1)) + call test1 (a1) + deallocate(a1) + allocate (a1(-38:5)) + call test1 (a1) + call testit2(a1, shape(a1)) + call testit2a(a1, [-38], shape(a1)) + + ! Test the multi-dimensional arrays. + call test3 (x3, 1, 2, 1, 3) + call test3 (y3, 0, 1, -3, -1) + p3 => x3 + call test3 (p3, 1, 2, 1, 3) + allocate (a3(2,3,4)) + call test3 (a3, 1, 2, 1, 3) + + ! Test some scalars. + call test0 (x) + call test0 (x1(1)) + +contains + + subroutine testit (a) + use m + class(t) :: a(..) + integer :: r + r = rank(a) + if (any (lbound (a) .ne. 1)) stop 101 + if (ubound (a, r) .ne. -1) stop 102 + end subroutine + + subroutine testit2(a, shape) + use m + class(t) :: a(..) + integer :: shape(:) + if (rank(a) /= size(shape)) stop 111 + if (any (lbound(a) /= 1)) stop 112 + if (any (ubound(a) /= shape)) stop 113 + end subroutine + + subroutine testit2a(a,lbound2, shape2) + use m + class(t), allocatable :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 121 + if (any (lbound(a) /= lbound2)) stop 122 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 123 + if (any (shape(a) /= shape2)) stop 124 + if (sum (shape(a)) /= size(a)) stop 125 + end subroutine + + subroutine testit2p(a, lbound2, shape2) + use m + class(t), pointer :: a(..) + integer :: lbound2(:), shape2(:) + if (rank(a) /= size(shape2)) stop 131 + if (any (lbound(a) /= lbound2)) stop 132 + if (any (ubound(a) /= lbound2 + shape2 - 1)) stop 133 + if (any (shape(a) /= shape2)) stop 134 + if (sum (shape(a)) /= size(a)) stop 135 + end subroutine + + subroutine test0 (a) + use m + class(t) :: a(..) + if (rank (a) .ne. 0) stop 141 + if (size (lbound (a)) .ne. 0) stop 142 + if (size (ubound (a)) .ne. 0) stop 143 + end subroutine + + subroutine test1 (a) + use m + class(t) :: a(*) + + call testit (a) + end subroutine + + subroutine test3 (a, l1, u1, l2, u2) + use m + integer :: l1, u1, l2, u2 + class(t) :: a(l1:u1, l2:u2, *) + + call testit (a) + end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 index d60dd72..1bfddc7 100644 --- a/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/cancel-1.f90 @@ -265,6 +265,7 @@ subroutine f2 end do !$omp end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -417,6 +418,7 @@ subroutine f2 !$omp end ordered end do !$omp sections + !$omp section block !$omp cancel parallel ! { dg-error "not closely nested inside" } !$omp cancel do ! { dg-error "not closely nested inside" } @@ -515,6 +517,7 @@ subroutine f3 end do !$omp end do nowait !$omp sections + !$omp section block !$omp cancel sections ! { dg-warning "nowait" } end block diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 index b2ad96a..4a88e3e 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-15.f90 @@ -14,6 +14,13 @@ contains subroutine base () end subroutine + subroutine variant2 () + end subroutine + + subroutine base2 () + !$omp declare variant (base2: variant2) match (construct={parallel}) + end subroutine + subroutine test1 () !$omp target !$omp parallel @@ -21,4 +28,10 @@ contains !$omp end parallel !$omp end target end subroutine + + subroutine test2 () + !$omp parallel + call base2 () ! { dg-final { scan-tree-dump-times "variant2 \\\(\\\);" 1 "gimple" } } + !$omp end parallel + end subroutine end module diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 index fc97322..5e34d47 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-16.f90 @@ -10,15 +10,27 @@ module main subroutine base () !$omp declare variant (variant) match (construct={parallel}) end subroutine + + subroutine base2 () + !$omp declare variant (base2: variant2) match (construct={target}) + end subroutine end interface - contains subroutine variant () end subroutine + subroutine variant2 () + end subroutine + subroutine test () !$omp parallel call base () ! { dg-final { scan-tree-dump-times "variant \\\(\\\);" 1 "gimple" } } !$omp end parallel end subroutine + + subroutine test2 () + !$omp target + call base2 () ! { dg-final { scan-tree-dump-times "variant2 \\\(\\\);" 1 "gimple" } } + !$omp end target + end subroutine end module diff --git a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 index cd2e39a..5d0d200 100644 --- a/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/nesting-3.f90 @@ -7,7 +7,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -33,7 +33,7 @@ subroutine f1 !$omp end sections !$omp sections !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -72,7 +72,7 @@ subroutine f1 !$omp sections !$omp section !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -105,7 +105,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -129,7 +129,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -150,7 +150,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -171,7 +171,7 @@ subroutine f1 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -195,7 +195,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -224,7 +224,7 @@ subroutine f1 block; end block end do !$omp sections - block; end block + call do_work !$omp section block; end block !$omp end sections @@ -257,7 +257,7 @@ subroutine f2 block; end block end do !$omp sections ! { dg-error "may not be closely nested" } - block; end block + call do_work !$omp section block; end block !$omp end sections diff --git a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 index 52d504b..71b4231 100644 --- a/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/reduction4.f90 @@ -137,7 +137,7 @@ end ! { dg-final { scan-tree-dump-times "#pragma omp sections reduction\\(task,\\\+:a\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(\\\+:a\\)" 2 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(i:1\\) reduction\\(task,\\\+:a\\)" 1 "original" } } -! { dg-final { scan-tree-dump-times "#pragma omp target in_reduction\\(\\\+:b\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp target map\\(always,tofrom:b\\) in_reduction\\(\\\+:b\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp task in_reduction\\(\\\+:a\\)" 1 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp teams reduction\\(\\\+:b\\)" 2 "original" } } ! { dg-final { scan-tree-dump-times "#pragma omp taskloop reduction\\(\\\+:a\\) in_reduction\\(\\\+:b\\)" 2 "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 new file mode 100644 index 0000000..ef8507e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-1.f90 @@ -0,0 +1,214 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + call do_work + end block + + !$omp parallel + block + call do_work + end block + !$omp end parallel + + !$omp teams + block + call do_work + end block + + !$omp teams + block + call do_work + end block + !$omp end teams + + !$omp masked + block + x = x + 1 + end block + + !$omp masked + block + x = x + 1 + end block + !$omp end masked + + !$omp scope + block + call do_work + end block + + !$omp scope + block + call do_work + end block + !$omp end scope + + !$omp single + block + x = x + 1 + end block + + !$omp single + block + x = x + 1 + end block + !$omp end single + + !$omp workshare + block + x = x + 1 + end block + + !$omp workshare + block + x = x + 1 + end block + !$omp end workshare + + !$omp task + block + call do_work + end block + + !$omp task + block + call do_work + end block + !$omp end task + + !$omp target data map(x) + block + x = x + 1 + end block + + !$omp target data map(x) + block + x = x + 1 + end block + !$omp end target data + + !$omp target + block + x = x + 1 + end block + + !$omp target + block + x = x + 1 + end block + !$omp end target + + !$omp parallel workshare + block + x = x + 1 + end block + + !$omp parallel workshare + block + x = x + 1 + end block + !$omp end parallel workshare + + !$omp parallel masked + block + x = x + 1 + end block + + !$omp parallel masked + block + x = x + 1 + end block + !$omp end parallel masked + + !$omp target parallel + block + call do_work + end block + + !$omp target parallel + block + call do_work + end block + !$omp end target parallel + + !$omp target teams + block + call do_work + end block + + !$omp target teams + block + call do_work + end block + !$omp end target teams + + !$omp critical + block + x = x + 1 + end block + + !$omp critical + block + x = x + 1 + end block + !$omp end critical + + !$omp taskgroup + block + x = x + 1 + end block + + !$omp taskgroup + block + x = x + 1 + end block + !$omp end taskgroup + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + end do + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + !$omp end ordered + end do + + !$omp master + block + x = x + 1 + end block + + !$omp master + block + x = x + 1 + end block + !$omp end master + + !$omp parallel master + block + x = x + 1 + end block + + !$omp parallel master + block + x = x + 1 + end block + !$omp end parallel master + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 new file mode 100644 index 0000000..ad4d08a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-2.f90 @@ -0,0 +1,139 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, i, n + + x = 0 + n = 10 + + !$omp parallel + block + call do_work + end block + call do_work + !$omp end parallel ! { dg-error "Unexpected !.OMP END PARALLEL statement" } + + !$omp teams + block + call do_work + end block + call do_work + !$omp end teams ! { dg-error "Unexpected !.OMP END TEAMS statement" } + + !$omp masked + block + x = x + 1 + end block + x = x + 1 + !$omp end masked ! { dg-error "Unexpected !.OMP END MASKED statement" } + + !$omp scope + block + call do_work + end block + call do_work + !$omp end scope ! { dg-error "Unexpected !.OMP END SCOPE statement" } + + !$omp single + block + x = x + 1 + end block + x = x + 1 + !$omp end single ! { dg-error "Unexpected !.OMP END SINGLE statement" } + + !$omp workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end workshare ! { dg-error "Unexpected !.OMP END WORKSHARE statement" } + + !$omp task + block + call do_work + end block + call do_work + !$omp end task ! { dg-error "Unexpected !.OMP END TASK statement" } + + !$omp target data map(x) + block + x = x + 1 + end block + x = x + 1 + !$omp end target data ! { dg-error "Unexpected !.OMP END TARGET DATA statement" } + + !$omp target + block + x = x + 1 + end block + x = x + 1 + !$omp end target ! { dg-error "Unexpected !.OMP END TARGET statement" } + + !$omp parallel workshare + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel workshare ! { dg-error "Unexpected !.OMP END PARALLEL WORKSHARE statement" } + + !$omp parallel masked + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel masked ! { dg-error "Unexpected !.OMP END PARALLEL MASKED statement" } + + !$omp target parallel + block + call do_work + end block + call do_work + !$omp end target parallel ! { dg-error "Unexpected !.OMP END TARGET PARALLEL statement" } + + !$omp target teams + block + call do_work + end block + call do_work + !$omp end target teams ! { dg-error "Unexpected !.OMP END TARGET TEAMS statement" } + + !$omp critical + block + x = x + 1 + end block + x = x + 1 + !$omp end critical ! { dg-error "Unexpected !.OMP END CRITICAL statement" } + + !$omp taskgroup + block + x = x + 1 + end block + x = x + 1 + !$omp end taskgroup ! { dg-error "Unexpected !.OMP END TASKGROUP statement" } + + !$omp do ordered + do i = 1, n + !$omp ordered + block + call do_work + end block + call do_work + !$omp end ordered ! { dg-error "Unexpected !.OMP END ORDERED statement" } + end do + + !$omp master + block + x = x + 1 + end block + x = x + 1 + !$omp end master ! { dg-error "Unexpected !.OMP END MASTER statement" } + + !$omp parallel master + block + x = x + 1 + end block + x = x + 1 + !$omp end parallel master ! { dg-error "Unexpected !.OMP END PARALLEL MASTER statement" } + +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 new file mode 100644 index 0000000..ae85fa0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/strictly-structured-block-3.f90 @@ -0,0 +1,52 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program main + integer :: x, y + + x = 0 + y = 0 + + !$omp parallel + !$omp parallel + block + call do_work + end block + !$omp end parallel + !$omp end parallel + + !$omp workshare + block + x = 1 + !$omp critical + block + y = 3 + end block + end block + + !$omp sections + block + !$omp section + block + x = 1 + end block + x = x + 2 + !$omp section + call do_work + end block + + !$omp sections + !$omp section + block + end block + x = 1 + !$omp end sections + + !$omp sections + block + block + end block + x = 1 + end block + +end program main diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 9ebca7a..1c8b1eb 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -7580,6 +7580,188 @@ proc check_effective_target_vect_element_align_preferred { } { && [check_effective_target_vect_variable_length] }] } +# Return true if vectorization of v2qi/v4qi/v8qi/v16qi/v2hi store is enabed. +# Return zero if the desirable pattern isn't found. +# It's used by Warray-bounds/Wstringop-overflow testcases which are +# regressed by O2 vectorization, refer to PR102697/PR102462/PR102706 +proc check_vect_slp_aligned_store_usage { pattern macro } { + global tool + + set result [check_compile slp_aligned_store_usage assembly { + char a[16] __attribute__ ((aligned (16))); + short b[4] __attribute__((aligned(8))); + int c[4] __attribute__((aligned(16))); + #ifdef TEST_V8QI + void + foo () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + a[4] = 4; + a[5] = 5; + a[6] = 6; + a[7] = 7; + } + #elif TEST_V16QI + void + foo1 () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + a[4] = 4; + a[5] = 5; + a[6] = 6; + a[7] = 7; + a[8] = 8; + a[9] = 9; + a[10] = 10; + a[11] = 11; + a[12] = 12; + a[13] = 13; + a[14] = 14; + a[15] = 15; + } + #elif TEST_V4QI + void + foo2 () + { + a[0] = 0; + a[1] = 1; + a[2] = 2; + a[3] = 3; + } + #elif TEST_V2QI + void + foo3 () + { + a[0] = 0; + a[1] = 1; + } + #elif TEST_V2HI + void + foo4 () + { + b[0] = 0; + b[1] = 1; + } + #elif TEST_V4HI + void + foo5 () + { + b[0] = 0; + b[1] = 1; + b[2] = 2; + b[3] = 3; + } + #elif TEST_V2SI + void + foo6 () + { + c[0] = 0; + c[1] = 1; + } + #elif TEST_V4SI + void + foo7 () + { + c[0] = 0; + c[1] = 1; + c[2] = 2; + c[3] = 3; + } + #endif + } "-O2 -fopt-info-all -D$macro" ] + + # Get compiler emitted messages and delete generated file. + set lines [lindex $result 0] + set output [lindex $result 1] + remote_file build delete $output + + # Check pattern exits in lines, set it to zero if not found. + if { [regexp $pattern $lines] } then { + return 1 + } + + return 0 +} + +# Return the true if target support vectorization of 2-byte char stores +# with 2-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2qi_store { } { + set pattern {add new stmt: MEM <vector\(2\) char>} + set macro "TEST_V2QI" + return [check_cached_effective_target vect_slp_v2qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro] }] + +} + +# Return the true if target support vectorization of 4-byte char stores +# with 4-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4qi_store { } { + set pattern {add new stmt: MEM <vector\(4\) char>} + set macro "TEST_V4QI" + return [check_cached_effective_target vect_slp_v4qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte char stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v8qi_store { } { + set pattern {add new stmt: MEM <vector\(8\) char>} + set macro "TEST_V8QI" + return [check_cached_effective_target vect_slp_v8qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 16-byte char stores +# with 16-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v16qi_store { } { + set pattern {add new stmt: MEM <vector\(16\) char>} + set macro "TEST_V16QI" + return [check_cached_effective_target vect_slp_v16qi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 4-byte short stores +# with 4-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2hi_store { } { + set pattern {add new stmt: MEM <vector\(2\) short int>} + set macro "TEST_V2HI" + return [check_cached_effective_target vect_slp_v2hi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte short stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4hi_store { } { + set pattern {add new stmt: MEM <vector\(4\) short int>} + set macro "TEST_V4HI" + return [check_cached_effective_target vect_slp_v4hi_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 8-byte int stores +# with 8-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v2si_store { } { + set pattern {add new stmt: MEM <vector\(2\) int>} + set macro "TEST_V2SI" + return [check_cached_effective_target vect_slp_v2si_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + +# Return the true if target support vectorization of 16-byte int stores +# with 16-byte aligned address at plain O2. +proc check_effective_target_vect_slp_v4si_store { } { + set pattern {add new stmt: MEM <vector\(4\) int>} + set macro "TEST_V4SI" + return [check_cached_effective_target vect_slp_v4si_store { + expr [check_vect_slp_aligned_store_usage $pattern $macro ] }] +} + # Return 1 if we can align stack data to the preferred vector alignment. proc check_effective_target_vect_align_stack_vars { } { diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 4b4b0b5..b3a27bc 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "value-prof.h" #include "tree-inline.h" #include "tree-ssa-live.h" +#include "tree-ssa-dce.h" #include "omp-general.h" #include "omp-expand.h" #include "tree-cfgcleanup.h" @@ -9666,13 +9667,52 @@ make_pass_warn_unused_result (gcc::context *ctxt) return new pass_warn_unused_result (ctxt); } +/* Maybe Remove stores to variables we marked write-only. + Return true if a store was removed. */ +static bool +maybe_remove_writeonly_store (gimple_stmt_iterator &gsi, gimple *stmt, + bitmap dce_ssa_names) +{ + /* Keep access when store has side effect, i.e. in case when source + is volatile. */ + if (!gimple_store_p (stmt) + || gimple_has_side_effects (stmt) + || optimize_debug) + return false; + + tree lhs = get_base_address (gimple_get_lhs (stmt)); + + if (!VAR_P (lhs) + || (!TREE_STATIC (lhs) && !DECL_EXTERNAL (lhs)) + || !varpool_node::get (lhs)->writeonly) + return false; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Removing statement, writes" + " to write only var:\n"); + print_gimple_stmt (dump_file, stmt, 0, + TDF_VOPS|TDF_MEMSYMS); + } + + /* Mark ssa name defining to be checked for simple dce. */ + if (gimple_assign_single_p (stmt)) + { + tree rhs = gimple_assign_rhs1 (stmt); + if (TREE_CODE (rhs) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (rhs)) + bitmap_set_bit (dce_ssa_names, SSA_NAME_VERSION (rhs)); + } + unlink_stmt_vdef (stmt); + gsi_remove (&gsi, true); + release_defs (stmt); + return true; +} + /* IPA passes, compilation of earlier functions or inlining might have changed some properties, such as marked functions nothrow, pure, const or noreturn. - Remove redundant edges and basic blocks, and create new ones if necessary. - - This pass can't be executed as stand alone pass from pass manager, because - in between inlining and this fixup the verify_flow_info would fail. */ + Remove redundant edges and basic blocks, and create new ones if necessary. */ unsigned int execute_fixup_cfg (void) @@ -9685,6 +9725,7 @@ execute_fixup_cfg (void) profile_count num = node->count; profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; bool scale = num.initialized_p () && !(num == den); + auto_bitmap dce_ssa_names; if (scale) { @@ -9724,26 +9765,13 @@ execute_fixup_cfg (void) todo |= TODO_cleanup_cfg; } - /* Remove stores to variables we marked write-only. - Keep access when store has side effect, i.e. in case when source - is volatile. */ - if (gimple_store_p (stmt) - && !gimple_has_side_effects (stmt) - && !optimize_debug) + /* Remove stores to variables we marked write-only. */ + if (maybe_remove_writeonly_store (gsi, stmt, dce_ssa_names)) { - tree lhs = get_base_address (gimple_get_lhs (stmt)); - - if (VAR_P (lhs) - && (TREE_STATIC (lhs) || DECL_EXTERNAL (lhs)) - && varpool_node::get (lhs)->writeonly) - { - unlink_stmt_vdef (stmt); - gsi_remove (&gsi, true); - release_defs (stmt); - todo |= TODO_update_ssa | TODO_cleanup_cfg; - continue; - } + todo |= TODO_update_ssa | TODO_cleanup_cfg; + continue; } + /* For calls we can simply remove LHS when it is known to be write-only. */ if (is_gimple_call (stmt) @@ -9804,6 +9832,8 @@ execute_fixup_cfg (void) && (todo & TODO_cleanup_cfg)) loops_state_set (LOOPS_NEED_FIXUP); + simple_dce_from_worklist (dce_ssa_names); + return todo; } diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 57bac06..46f4ffe 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -757,6 +757,9 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1, *var = NULL_TREE; *off = NULL_TREE; + if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type)) + return false; + switch (code) { case INTEGER_CST: diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 15dcc1e..b165dc0 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -2490,7 +2490,7 @@ predicate_rhs_code (gassign *stmt, tree mask, tree cond, */ static void -predicate_statements (loop_p loop) +predicate_statements (loop_p loop, edge pe) { unsigned int i, orig_loop_num_nodes = loop->num_nodes; auto_vec<int, 1> vect_sizes; @@ -2596,8 +2596,7 @@ predicate_statements (loop_p loop) if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2)) && expr_invariant_in_loop_p (loop, gimple_assign_rhs1 (stmt2))) - gsi_insert_on_edge_immediate (loop_preheader_edge (loop), - stmt2); + gsi_insert_on_edge_immediate (pe, stmt2); else if (first) { gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT); @@ -2679,7 +2678,7 @@ remove_conditions_and_labels (loop_p loop) blocks. Replace PHI nodes with conditional modify expressions. */ static void -combine_blocks (class loop *loop) +combine_blocks (class loop *loop, edge pe) { basic_block bb, exit_bb, merge_target_bb; unsigned int orig_loop_num_nodes = loop->num_nodes; @@ -2692,7 +2691,7 @@ combine_blocks (class loop *loop) predicate_all_scalar_phis (loop); if (need_to_predicate || need_to_rewrite_undefined) - predicate_statements (loop); + predicate_statements (loop, pe); /* Merge basic blocks. */ exit_bb = NULL; @@ -3187,6 +3186,7 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) bool aggressive_if_conv; class loop *rloop; bitmap exit_bbs; + edge pe; again: rloop = NULL; @@ -3218,6 +3218,9 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) || loop->dont_vectorize)) goto cleanup; + /* The edge to insert invariant stmts on. */ + pe = loop_preheader_edge (loop); + /* Since we have no cost model, always version loops unless the user specified -ftree-loop-if-convert or unless versioning is required. Either version this loop, or if the pattern is right for outer-loop @@ -3255,12 +3258,18 @@ tree_if_conversion (class loop *loop, vec<gimple *> *preds) gcc_assert (nloop->inner && nloop->inner->next == NULL); rloop = nloop->inner; } + else + /* If we versioned loop then make sure to insert invariant + stmts before the .LOOP_VECTORIZED check since the vectorizer + will re-use that for things like runtime alias versioning + whose condition can end up using those invariants. */ + pe = single_pred_edge (gimple_bb (preds->last ())); } /* Now all statements are if-convertible. Combine all the basic blocks into one huge basic block doing the if-conversion on-the-fly. */ - combine_blocks (loop); + combine_blocks (loop, pe); /* Perform local CSE, this esp. helps the vectorizer analysis if loads and stores are involved. CSE only the loop body, not the entry diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 6a4dc72..4334e05 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -45,13 +45,6 @@ struct object_size_info unsigned int *stack, *tos; }; -static const unsigned HOST_WIDE_INT unknown[4] = { - HOST_WIDE_INT_M1U, - HOST_WIDE_INT_M1U, - 0, - 0 -}; - static tree compute_object_offset (const_tree, const_tree); static bool addr_object_size (struct object_size_info *, const_tree, int, unsigned HOST_WIDE_INT *); @@ -82,6 +75,11 @@ static bitmap computed[4]; /* Maximum value of offset we consider to be addition. */ static unsigned HOST_WIDE_INT offset_limit; +static inline unsigned HOST_WIDE_INT +unknown (int object_size_type) +{ + return ((unsigned HOST_WIDE_INT) -((object_size_type >> 1) ^ 1)); +} /* Initialize OFFSET_LIMIT variable. */ static void @@ -204,7 +202,7 @@ decl_init_size (tree decl, bool min) /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown[object_size_type]. */ + If unknown, return unknown (object_size_type). */ static bool addr_object_size (struct object_size_info *osi, const_tree ptr, @@ -216,7 +214,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown[object_size_type]; + *psize = unknown (object_size_type); pt_var = TREE_OPERAND (ptr, 0); while (handled_component_p (pt_var)) @@ -244,9 +242,9 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, SSA_NAME_VERSION (var))) sz = object_sizes[object_size_type][SSA_NAME_VERSION (var)]; else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } - if (sz != unknown[object_size_type]) + if (sz != unknown (object_size_type)) { offset_int mem_offset; if (mem_ref_offset (pt_var).is_constant (&mem_offset)) @@ -257,13 +255,13 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, else if (wi::fits_uhwi_p (dsz)) sz = dsz.to_uhwi (); else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } else - sz = unknown[object_size_type]; + sz = unknown (object_size_type); } - if (sz != unknown[object_size_type] && sz < offset_limit) + if (sz != unknown (object_size_type) && sz < offset_limit) pt_var_size = size_int (sz); } else if (DECL_P (pt_var)) @@ -445,7 +443,7 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL. Handles calls to functions declared with attribute alloc_size. OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. - If unknown, return unknown[object_size_type]. */ + If unknown, return unknown (object_size_type). */ static unsigned HOST_WIDE_INT alloc_object_size (const gcall *call, int object_size_type) @@ -459,7 +457,7 @@ alloc_object_size (const gcall *call, int object_size_type) calltype = gimple_call_fntype (call); if (!calltype) - return unknown[object_size_type]; + return unknown (object_size_type); /* Set to positions of alloc_size arguments. */ int arg1 = -1, arg2 = -1; @@ -479,7 +477,7 @@ alloc_object_size (const gcall *call, int object_size_type) || (arg2 >= 0 && (arg2 >= (int)gimple_call_num_args (call) || TREE_CODE (gimple_call_arg (call, arg2)) != INTEGER_CST))) - return unknown[object_size_type]; + return unknown (object_size_type); tree bytes = NULL_TREE; if (arg2 >= 0) @@ -492,7 +490,7 @@ alloc_object_size (const gcall *call, int object_size_type) if (bytes && tree_fits_uhwi_p (bytes)) return tree_to_uhwi (bytes); - return unknown[object_size_type]; + return unknown (object_size_type); } @@ -534,7 +532,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, /* Set to unknown and overwrite just before returning if the size could be determined. */ - *psize = unknown[object_size_type]; + *psize = unknown (object_size_type); if (! offset_limit) init_offset_limit (); @@ -674,7 +672,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, { EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi) if (object_sizes[object_size_type][i] - != unknown[object_size_type]) + != unknown (object_size_type)) { print_generic_expr (dump_file, ssa_name (i), dump_flags); @@ -692,7 +690,7 @@ compute_builtin_object_size (tree ptr, int object_size_type, } *psize = object_sizes[object_size_type][SSA_NAME_VERSION (ptr)]; - return *psize != unknown[object_size_type]; + return *psize != unknown (object_size_type); } /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */ @@ -705,7 +703,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) unsigned HOST_WIDE_INT bytes; gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); + != unknown (object_size_type)); gcc_assert (osi->pass == 0); if (TREE_CODE (value) == WITH_SIZE_EXPR) @@ -718,7 +716,7 @@ expr_object_size (struct object_size_info *osi, tree ptr, tree value) if (TREE_CODE (value) == ADDR_EXPR) addr_object_size (osi, value, object_size_type, &bytes); else - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); if ((object_size_type & 2) == 0) { @@ -745,7 +743,7 @@ call_object_size (struct object_size_info *osi, tree ptr, gcall *call) gcc_assert (is_gimple_call (call)); gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); + != unknown (object_size_type)); gcc_assert (osi->pass == 0); bytes = alloc_object_size (call, object_size_type); @@ -770,24 +768,12 @@ unknown_object_size (struct object_size_info *osi, tree ptr) { int object_size_type = osi->object_size_type; unsigned int varno = SSA_NAME_VERSION (ptr); - unsigned HOST_WIDE_INT bytes; + unsigned HOST_WIDE_INT bytes = unknown (object_size_type); - gcc_assert (object_sizes[object_size_type][varno] - != unknown[object_size_type]); - gcc_assert (osi->pass == 0); + gcc_checking_assert (object_sizes[object_size_type][varno] != bytes); + gcc_checking_assert (osi->pass == 0); - bytes = unknown[object_size_type]; - - if ((object_size_type & 2) == 0) - { - if (object_sizes[object_size_type][varno] < bytes) - object_sizes[object_size_type][varno] = bytes; - } - else - { - if (object_sizes[object_size_type][varno] > bytes) - object_sizes[object_size_type][varno] = bytes; - } + object_sizes[object_size_type][varno] = bytes; } @@ -802,11 +788,11 @@ merge_object_sizes (struct object_size_info *osi, tree dest, tree orig, unsigned int varno = SSA_NAME_VERSION (dest); unsigned HOST_WIDE_INT orig_bytes; - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; if (offset >= offset_limit) { - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); return false; } @@ -814,7 +800,7 @@ merge_object_sizes (struct object_size_info *osi, tree dest, tree orig, collect_object_sizes_for (osi, orig); orig_bytes = object_sizes[object_size_type][SSA_NAME_VERSION (orig)]; - if (orig_bytes != unknown[object_size_type]) + if (orig_bytes != unknown (object_size_type)) orig_bytes = (offset > orig_bytes) ? HOST_WIDE_INT_0U : orig_bytes - offset; @@ -865,7 +851,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) else gcc_unreachable (); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; /* Handle PTR + OFFSET here. */ @@ -874,7 +860,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) || TREE_CODE (op0) == ADDR_EXPR)) { if (! tree_fits_uhwi_p (op1)) - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); else if (TREE_CODE (op0) == SSA_NAME) return merge_object_sizes (osi, var, op0, tree_to_uhwi (op1)); else @@ -883,10 +869,10 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) /* op0 will be ADDR_EXPR here. */ addr_object_size (osi, op0, object_size_type, &bytes); - if (bytes == unknown[object_size_type]) + if (bytes == unknown (object_size_type)) ; else if (off > offset_limit) - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); else if (off > bytes) bytes = 0; else @@ -894,7 +880,7 @@ plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) } } else - bytes = unknown[object_size_type]; + bytes = unknown (object_size_type); if ((object_size_type & 2) == 0) { @@ -924,7 +910,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return false; then_ = gimple_assign_rhs2 (stmt); @@ -935,7 +921,7 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) else expr_object_size (osi, var, then_); - if (object_sizes[object_size_type][varno] == unknown[object_size_type]) + if (object_sizes[object_size_type][varno] == unknown (object_size_type)) return reexamine; if (TREE_CODE (else_) == SSA_NAME) @@ -956,9 +942,9 @@ cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) object size is object size of the first operand minus the constant. If the constant is bigger than the number of remaining bytes until the end of the object, object size is 0, but if it is instead a pointer - subtraction, object size is unknown[object_size_type]. + subtraction, object size is unknown (object_size_type). To differentiate addition from subtraction, ADDR_EXPR returns - unknown[object_size_type] for all objects bigger than half of the address + unknown (object_size_type) for all objects bigger than half of the address space, and constants less than half of the address space are considered addition, while bigger constants subtraction. For a memcpy like GIMPLE_CALL that always returns one of its arguments, the @@ -1030,7 +1016,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) expr_object_size (osi, var, rhs); } else - unknown_object_size (osi, var); + unknown_object_size (osi, var); break; } @@ -1053,7 +1039,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) case GIMPLE_ASM: /* Pointers defined by __asm__ statements can point anywhere. */ - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); break; case GIMPLE_NOP: @@ -1062,7 +1048,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) expr_object_size (osi, var, SSA_NAME_VAR (var)); else /* Uninitialized SSA names point nowhere. */ - object_sizes[object_size_type][varno] = unknown[object_size_type]; + object_sizes[object_size_type][varno] = unknown (object_size_type); break; case GIMPLE_PHI: @@ -1074,7 +1060,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) tree rhs = gimple_phi_arg (stmt, i)->def; if (object_sizes[object_size_type][varno] - == unknown[object_size_type]) + == unknown (object_size_type)) break; if (TREE_CODE (rhs) == SSA_NAME) @@ -1090,7 +1076,7 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) } if (! reexamine - || object_sizes[object_size_type][varno] == unknown[object_size_type]) + || object_sizes[object_size_type][varno] == unknown (object_size_type)) { bitmap_set_bit (computed[object_size_type], varno); bitmap_clear_bit (osi->reexamine, varno); @@ -1298,6 +1284,10 @@ object_sizes_execute (function *fun, bool insert_min_max_p) if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE)) continue; + tree lhs = gimple_call_lhs (call); + if (!lhs) + continue; + init_object_sizes (); /* If insert_min_max_p, only attempt to fold @@ -1312,11 +1302,9 @@ object_sizes_execute (function *fun, bool insert_min_max_p) { unsigned HOST_WIDE_INT object_size_type = tree_to_uhwi (ost); tree ptr = gimple_call_arg (call, 0); - tree lhs = gimple_call_lhs (call); if ((object_size_type == 1 || object_size_type == 3) && (TREE_CODE (ptr) == ADDR_EXPR - || TREE_CODE (ptr) == SSA_NAME) - && lhs) + || TREE_CODE (ptr) == SSA_NAME)) { tree type = TREE_TYPE (lhs); unsigned HOST_WIDE_INT bytes; @@ -1339,10 +1327,6 @@ object_sizes_execute (function *fun, bool insert_min_max_p) continue; } - tree lhs = gimple_call_lhs (call); - if (!lhs) - continue; - result = gimple_fold_stmt_to_constant (call, do_valueize); if (!result) { diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c index 62f936a..38913b0 100644 --- a/gcc/tree-ssa-threadbackward.c +++ b/gcc/tree-ssa-threadbackward.c @@ -52,12 +52,10 @@ along with GCC; see the file COPYING3. If not see class back_threader_registry { public: - back_threader_registry (); bool register_path (const vec<basic_block> &, edge taken); bool thread_through_all_blocks (bool may_peel_loop_headers); private: back_jt_path_registry m_lowlevel_registry; - int m_threaded_paths; }; // Class to abstract the profitability code for the backwards threader. @@ -78,7 +76,6 @@ class back_threader { public: back_threader (bool speed_p, bool resolve); - ~back_threader (); void maybe_thread_block (basic_block bb); bool thread_through_all_blocks (bool may_peel_loop_headers); private: @@ -130,10 +127,6 @@ back_threader::back_threader (bool speed_p, bool resolve) m_resolve = resolve; } -back_threader::~back_threader () -{ -} - // Register the current path for jump threading if it's profitable to // do so. // @@ -147,6 +140,10 @@ back_threader::maybe_register_path () if (taken_edge && taken_edge != UNREACHABLE_EDGE) { + // Avoid circular paths. + if (m_visited_bbs.contains (taken_edge->dest)) + return UNREACHABLE_EDGE; + bool irreducible = false; bool profitable = m_profit.profitable_path_p (m_path, m_name, taken_edge, &irreducible); @@ -574,11 +571,6 @@ back_threader::debug () dump (stderr); } -back_threader_registry::back_threader_registry () -{ - m_threaded_paths = 0; -} - bool back_threader_registry::thread_through_all_blocks (bool may_peel_loop_headers) { @@ -620,6 +612,15 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path, if (m_path.length () <= 1) return false; + if (m_path.length () > (unsigned) param_max_fsm_thread_length) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " FAIL: Jump-thread path not considered: " + "the number of basic blocks on the path " + "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n"); + return false; + } + int n_insns = 0; gimple_stmt_iterator gsi; loop_p loop = m_path[0]->loop_father; @@ -919,9 +920,7 @@ back_threader_registry::register_path (const vec<basic_block> &m_path, m_lowlevel_registry.push_edge (jump_thread_path, taken_edge, EDGE_NO_COPY_SRC_BLOCK); - - if (m_lowlevel_registry.register_jump_thread (jump_thread_path)) - ++m_threaded_paths; + m_lowlevel_registry.register_jump_thread (jump_thread_path); return true; } @@ -1059,7 +1058,7 @@ public: {} opt_pass * clone (void) override { - return new pass_thread_jumps (m_ctxt); + return new pass_thread_jumps_full (m_ctxt); } bool gate (function *) override { diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 32ce1e3..8e6f043 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -278,7 +278,7 @@ cancel_thread (vec<jump_thread_edge *> *path, const char *reason = NULL) if (dump_file && (dump_flags & TDF_DETAILS)) { if (reason) - fprintf (dump_file, "%s:\n", reason); + fprintf (dump_file, "%s: ", reason); dump_jump_thread_path (dump_file, *path, false); fprintf (dump_file, "\n"); @@ -2295,12 +2295,6 @@ back_jt_path_registry::adjust_paths_after_duplication (unsigned curr_path_num) { vec<jump_thread_edge *> *curr_path = m_paths[curr_path_num]; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "just threaded: "); - debug_path (dump_file, curr_path_num); - } - /* Iterate through all the other paths and adjust them. */ for (unsigned cand_path_num = 0; cand_path_num < m_paths.length (); ) { @@ -2409,12 +2403,6 @@ back_jt_path_registry::duplicate_thread_path (edge entry, if (!can_copy_bbs_p (region, n_region)) return false; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "\nabout to thread: "); - debug_path (dump_file, current_path_no); - } - /* Some sanity checking. Note that we do not check for all possible missuses of the functions. I.e. if you ask to copy something weird, it will work, but the state of structures probably will not be @@ -2771,6 +2759,7 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) bool seen_latch = false; int loops_crossed = 0; bool crossed_latch = false; + bool crossed_loop_header = false; // Use ->dest here instead of ->src to ignore the first block. The // first block is allowed to be in a different loop, since it'll be // redirected. See similar comment in profitable_path_p: "we don't @@ -2804,6 +2793,14 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) ++loops_crossed; } + // ?? Avoid threading through loop headers that remain in the + // loop, as such threadings tend to create sub-loops which + // _might_ be OK ??. + if (e->dest->loop_father->header == e->dest + && !flow_loop_nested_p (exit->dest->loop_father, + e->dest->loop_father)) + crossed_loop_header = true; + if (flag_checking && !m_backedge_threads) gcc_assert ((path[i]->e->flags & EDGE_DFS_BACK) == 0); } @@ -2829,6 +2826,21 @@ jt_path_registry::cancel_invalid_paths (vec<jump_thread_edge *> &path) cancel_thread (&path, "Path crosses loops"); return true; } + // The path should either start and end in the same loop or exit the + // loop it starts in but never enter a loop. This also catches + // creating irreducible loops, not only rotation. + if (entry->src->loop_father != exit->dest->loop_father + && !flow_loop_nested_p (exit->src->loop_father, + entry->dest->loop_father)) + { + cancel_thread (&path, "Path rotates loop"); + return true; + } + if (crossed_loop_header) + { + cancel_thread (&path, "Path crosses loop header but does not exit it"); + return true; + } return false; } diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index a19045f..556ae97 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -1396,7 +1396,9 @@ vector_alignment_reachable_p (dr_vec_info *dr_info) static void vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info, - unsigned int *inside_cost, + dr_alignment_support alignment_support_scheme, + int misalignment, + unsigned int *inside_cost, unsigned int *outside_cost, stmt_vector_for_cost *body_cost_vec, stmt_vector_for_cost *prologue_cost_vec) @@ -1411,10 +1413,12 @@ vect_get_data_access_cost (vec_info *vinfo, dr_vec_info *dr_info, ncopies = vect_get_num_copies (loop_vinfo, STMT_VINFO_VECTYPE (stmt_info)); if (DR_IS_READ (dr_info->dr)) - vect_get_load_cost (vinfo, stmt_info, ncopies, true, inside_cost, + vect_get_load_cost (vinfo, stmt_info, ncopies, alignment_support_scheme, + misalignment, true, inside_cost, outside_cost, prologue_cost_vec, body_cost_vec, false); else - vect_get_store_cost (vinfo,stmt_info, ncopies, inside_cost, body_cost_vec); + vect_get_store_cost (vinfo,stmt_info, ncopies, alignment_support_scheme, + misalignment, inside_cost, body_cost_vec); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -1465,13 +1469,10 @@ peel_info_hasher::equal (const _vect_peel_info *a, const _vect_peel_info *b) static void vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab, loop_vec_info loop_vinfo, dr_vec_info *dr_info, - int npeel) + int npeel, bool supportable_if_not_aligned) { struct _vect_peel_info elem, *slot; _vect_peel_info **new_slot; - tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); - bool supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true); elem.npeel = npeel; slot = peeling_htab->find (&elem); @@ -1487,7 +1488,9 @@ vect_peeling_hash_insert (hash_table<peel_info_hasher> *peeling_htab, *new_slot = slot; } - if (!supportable_dr_alignment + /* If this DR is not supported with unknown misalignment then bias + this slot when the cost model is disabled. */ + if (!supportable_if_not_aligned && unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) slot->count += VECT_MAX_COST; } @@ -1526,29 +1529,49 @@ vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo, unsigned int *outside_cost, stmt_vector_for_cost *body_cost_vec, stmt_vector_for_cost *prologue_cost_vec, - unsigned int npeel, - bool unknown_misalignment) + unsigned int npeel) { vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); + bool dr0_alignment_known_p + = (dr0_info + && known_alignment_for_access_p (dr0_info, + STMT_VINFO_VECTYPE (dr0_info->stmt))); + for (data_reference *dr : datarefs) { dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); if (!vect_relevant_for_alignment_p (dr_info)) continue; - int save_misalignment; - save_misalignment = dr_info->misalignment; + tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); + dr_alignment_support alignment_support_scheme; + int misalignment; + unsigned HOST_WIDE_INT alignment; + if (npeel == 0) - ; - else if (unknown_misalignment && dr_info == dr0_info) - SET_DR_MISALIGNMENT (dr_info, - vect_dr_misalign_for_aligned_access (dr0_info)); + misalignment = dr_misalignment (dr_info, vectype); + else if (dr_info == dr0_info + || vect_dr_aligned_if_peeled_dr_is (dr_info, dr0_info)) + misalignment = 0; + else if (!dr0_alignment_known_p + || !known_alignment_for_access_p (dr_info, vectype) + || !DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)) + misalignment = DR_MISALIGNMENT_UNKNOWN; else - vect_update_misalignment_for_peel (dr_info, dr0_info, npeel); - vect_get_data_access_cost (loop_vinfo, dr_info, inside_cost, outside_cost, + { + misalignment = dr_misalignment (dr_info, vectype); + misalignment += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr)); + misalignment &= alignment - 1; + } + alignment_support_scheme + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + misalignment); + + vect_get_data_access_cost (loop_vinfo, dr_info, + alignment_support_scheme, misalignment, + inside_cost, outside_cost, body_cost_vec, prologue_cost_vec); - SET_DR_MISALIGNMENT (dr_info, save_misalignment); } } @@ -1572,7 +1595,7 @@ vect_peeling_hash_get_lowest_cost (_vect_peel_info **slot, vect_get_peeling_costs_all_drs (loop_vinfo, elem->dr_info, &inside_cost, &outside_cost, &body_cost_vec, - &prologue_cost_vec, elem->npeel, false); + &prologue_cost_vec, elem->npeel); body_cost_vec.release (); @@ -1644,26 +1667,38 @@ vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info, vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); enum dr_alignment_support supportable_dr_alignment; + bool dr0_alignment_known_p + = known_alignment_for_access_p (dr0_info, + STMT_VINFO_VECTYPE (dr0_info->stmt)); + /* Ensure that all data refs can be vectorized after the peel. */ for (data_reference *dr : datarefs) { - int save_misalignment; - if (dr == dr0_info->dr) continue; dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); - if (!vect_relevant_for_alignment_p (dr_info)) + if (!vect_relevant_for_alignment_p (dr_info) + || vect_dr_aligned_if_peeled_dr_is (dr_info, dr0_info)) continue; - save_misalignment = dr_info->misalignment; - vect_update_misalignment_for_peel (dr_info, dr0_info, npeel); tree vectype = STMT_VINFO_VECTYPE (dr_info->stmt); + int misalignment; + unsigned HOST_WIDE_INT alignment; + if (!dr0_alignment_known_p + || !known_alignment_for_access_p (dr_info, vectype) + || !DR_TARGET_ALIGNMENT (dr_info).is_constant (&alignment)) + misalignment = DR_MISALIGNMENT_UNKNOWN; + else + { + misalignment = dr_misalignment (dr_info, vectype); + misalignment += npeel * TREE_INT_CST_LOW (DR_STEP (dr_info->dr)); + misalignment &= alignment - 1; + } supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, false); - SET_DR_MISALIGNMENT (dr_info, save_misalignment); - - if (!supportable_dr_alignment) + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + misalignment); + if (supportable_dr_alignment == dr_unaligned_unsupported) return false; } @@ -1802,7 +1837,6 @@ opt_result vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) { class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - enum dr_alignment_support supportable_dr_alignment; dr_vec_info *first_store = NULL; dr_vec_info *dr0_info = NULL; struct data_reference *dr; @@ -1911,8 +1945,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) stmt_vec_info stmt_info = dr_info->stmt; tree vectype = STMT_VINFO_VECTYPE (stmt_info); - supportable_dr_alignment - = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, true); do_peeling = vector_alignment_reachable_p (dr_info); if (do_peeling) { @@ -1956,11 +1988,20 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) } /* Save info about DR in the hash table. Also include peeling - amounts according to the explanation above. */ + amounts according to the explanation above. Indicate + the alignment status when the ref is not aligned. + ??? Rather than using unknown alignment here we should + prune all entries from the peeling hashtable which cause + DRs to be not supported. */ + bool supportable_if_not_aligned + = targetm.vectorize.support_vector_misalignment + (TYPE_MODE (vectype), TREE_TYPE (DR_REF (dr_info->dr)), + DR_MISALIGNMENT_UNKNOWN, false); while (known_le (npeel_tmp, nscalars)) { vect_peeling_hash_insert (&peeling_htab, loop_vinfo, - dr_info, npeel_tmp); + dr_info, npeel_tmp, + supportable_if_not_aligned); npeel_tmp += MAX (1, target_align / dr_size); } @@ -1999,11 +2040,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) /* Check for data refs with unsupportable alignment that can be peeled. */ - if (!supportable_dr_alignment) - { - one_dr_unsupportable = true; - unsupportable_dr_info = dr_info; - } + enum dr_alignment_support supportable_dr_alignment + = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, + DR_MISALIGNMENT_UNKNOWN); + if (supportable_dr_alignment == dr_unaligned_unsupported) + { + one_dr_unsupportable = true; + unsupportable_dr_info = dr_info; + } if (!first_store && DR_IS_WRITE (dr)) { @@ -2055,7 +2099,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) vect_get_peeling_costs_all_drs (loop_vinfo, dr0_info, &load_inside_cost, &load_outside_cost, - &dummy, &dummy, estimated_npeels, true); + &dummy, &dummy, estimated_npeels); dummy.release (); if (first_store) @@ -2065,7 +2109,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) &store_inside_cost, &store_outside_cost, &dummy, &dummy, - estimated_npeels, true); + estimated_npeels); dummy.release (); } else @@ -2153,8 +2197,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) stmt_vector_for_cost dummy; dummy.create (2); vect_get_peeling_costs_all_drs (loop_vinfo, NULL, &nopeel_inside_cost, - &nopeel_outside_cost, &dummy, &dummy, - 0, false); + &nopeel_outside_cost, &dummy, &dummy, 0); dummy.release (); /* Add epilogue costs. As we do not peel for alignment here, no prologue @@ -2343,7 +2386,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr); stmt_vec_info stmt_info = dr_info->stmt; tree vectype = STMT_VINFO_VECTYPE (stmt_info); - if (aligned_access_p (dr_info, vectype) + int misalignment; + if ((misalignment = dr_misalignment (dr_info, vectype)) == 0 || !vect_relevant_for_alignment_p (dr_info)) continue; @@ -2353,14 +2397,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) break; } - supportable_dr_alignment + enum dr_alignment_support supportable_dr_alignment = vect_supportable_dr_alignment (loop_vinfo, dr_info, vectype, - false); - if (!supportable_dr_alignment) + misalignment); + if (supportable_dr_alignment == dr_unaligned_unsupported) { - if (known_alignment_for_access_p (dr_info, vectype) - || LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length () - >= (unsigned) param_vect_max_version_for_alignment_checks) + if (misalignment != DR_MISALIGNMENT_UNKNOWN + || (LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo).length () + >= (unsigned) param_vect_max_version_for_alignment_checks)) { do_versioning = false; break; @@ -3303,8 +3347,10 @@ vect_vfa_access_size (vec_info *vinfo, dr_vec_info *dr_info) access_size *= DR_GROUP_SIZE (stmt_vinfo) - DR_GROUP_GAP (stmt_vinfo); } tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo); + int misalignment; if (STMT_VINFO_VEC_STMTS (stmt_vinfo).exists () - && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, false) + && ((misalignment = dr_misalignment (dr_info, vectype)), true) + && (vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment) == dr_explicit_realign_optimized)) { /* We might access a full vector's worth. */ @@ -6620,7 +6666,6 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment) return (known_le (alignment, (unsigned HOST_WIDE_INT) MAX_STACK_ALIGNMENT)); } - /* Return whether the data reference DR_INFO is supported with respect to its alignment. If CHECK_ALIGNED_ACCESSES is TRUE, check if the access is supported even @@ -6629,7 +6674,7 @@ vect_can_force_dr_alignment_p (const_tree decl, poly_uint64 alignment) enum dr_alignment_support vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, - tree vectype, bool check_aligned_accesses) + tree vectype, int misalignment) { data_reference *dr = dr_info->dr; stmt_vec_info stmt_info = dr_info->stmt; @@ -6638,7 +6683,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, class loop *vect_loop = NULL; bool nested_in_vect_loop = false; - if (aligned_access_p (dr_info, vectype) && !check_aligned_accesses) + if (misalignment == 0) return dr_aligned; /* For now assume all conditional loads/stores support unaligned @@ -6720,9 +6765,6 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, if (DR_IS_READ (dr)) { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (optab_handler (vec_realign_load_optab, mode) != CODE_FOR_nothing && (!targetm.vectorize.builtin_mask_for_load || targetm.vectorize.builtin_mask_for_load ())) @@ -6744,26 +6786,15 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info, else return dr_explicit_realign_optimized; } - if (!known_alignment_for_access_p (dr_info, vectype)) - is_packed = not_size_aligned (DR_REF (dr)); - - if (targetm.vectorize.support_vector_misalignment - (mode, type, dr_misalignment (dr_info, vectype), is_packed)) - /* Can't software pipeline the loads, but can at least do them. */ - return dr_unaligned_supported; } - else - { - bool is_packed = false; - tree type = (TREE_TYPE (DR_REF (dr))); - if (!known_alignment_for_access_p (dr_info, vectype)) - is_packed = not_size_aligned (DR_REF (dr)); - - if (targetm.vectorize.support_vector_misalignment - (mode, type, dr_misalignment (dr_info, vectype), is_packed)) - return dr_unaligned_supported; - } + bool is_packed = false; + tree type = TREE_TYPE (DR_REF (dr)); + if (misalignment == DR_MISALIGNMENT_UNKNOWN) + is_packed = not_size_aligned (DR_REF (dr)); + if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment, + is_packed)) + return dr_unaligned_supported; /* Unsupported. */ return dr_unaligned_unsupported; diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 709bcb6..eff4640 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -975,7 +975,6 @@ vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap, (gimple_call_internal_fn (call_stmt)))) || gimple_call_tail_p (call_stmt) || gimple_call_noreturn_p (call_stmt) - || !gimple_call_nothrow_p (call_stmt) || gimple_call_chain (call_stmt)) { if (dump_enabled_p ()) diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index f5e1941..8f52745 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -909,6 +909,8 @@ cfun_returns (tree decl) static void vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, vect_memory_access_type memory_access_type, + dr_alignment_support alignment_support_scheme, + int misalignment, vec_load_store_type vls_type, slp_tree slp_node, stmt_vector_for_cost *cost_vec) { @@ -969,7 +971,8 @@ vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, scalar_store, stmt_info, 0, vect_body); } else - vect_get_store_cost (vinfo, stmt_info, ncopies, &inside_cost, cost_vec); + vect_get_store_cost (vinfo, stmt_info, ncopies, alignment_support_scheme, + misalignment, &inside_cost, cost_vec); if (memory_access_type == VMAT_ELEMENTWISE || memory_access_type == VMAT_STRIDED_SLP) @@ -1021,15 +1024,12 @@ vect_model_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Calculate cost of DR's memory access. */ void -vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, +vect_get_store_cost (vec_info *, stmt_vec_info stmt_info, int ncopies, + dr_alignment_support alignment_support_scheme, + int misalignment, unsigned int *inside_cost, stmt_vector_for_cost *body_cost_vec) { - dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); - int alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false); - switch (alignment_support_scheme) { case dr_aligned: @@ -1049,8 +1049,7 @@ vect_get_store_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Here, we assign an additional cost for the unaligned store. */ *inside_cost += record_stmt_cost (body_cost_vec, ncopies, unaligned_store, stmt_info, - dr_misalignment (dr_info, vectype), - vect_body); + misalignment, vect_body); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "vect_model_store_cost: unaligned supported by " @@ -1085,6 +1084,8 @@ static void vect_model_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, unsigned ncopies, poly_uint64 vf, vect_memory_access_type memory_access_type, + dr_alignment_support alignment_support_scheme, + int misalignment, gather_scatter_info *gs_info, slp_tree slp_node, stmt_vector_for_cost *cost_vec) @@ -1144,7 +1145,8 @@ vect_model_load_cost (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "vect_model_load_cost: %d unused vectors.\n", gaps); - vect_get_load_cost (vinfo, stmt_info, ncopies * gaps, false, + vect_get_load_cost (vinfo, stmt_info, ncopies * gaps, + alignment_support_scheme, misalignment, false, &inside_cost, &prologue_cost, cost_vec, cost_vec, true); } @@ -1189,8 +1191,16 @@ vect_model_load_cost (vec_info *vinfo, ncopies * assumed_nunits, scalar_load, stmt_info, 0, vect_body); } + else if (memory_access_type == VMAT_INVARIANT) + { + /* Invariant loads will ideally be hoisted and splat to a vector. */ + prologue_cost += record_stmt_cost (cost_vec, 1, + scalar_to_vec, stmt_info, 0, + vect_prologue); + } else - vect_get_load_cost (vinfo, stmt_info, ncopies, first_stmt_p, + vect_get_load_cost (vinfo, stmt_info, ncopies, + alignment_support_scheme, misalignment, first_stmt_p, &inside_cost, &prologue_cost, cost_vec, cost_vec, true); if (memory_access_type == VMAT_ELEMENTWISE @@ -1209,18 +1219,15 @@ vect_model_load_cost (vec_info *vinfo, /* Calculate cost of DR's memory access. */ void -vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, +vect_get_load_cost (vec_info *, stmt_vec_info stmt_info, int ncopies, + dr_alignment_support alignment_support_scheme, + int misalignment, bool add_realign_cost, unsigned int *inside_cost, unsigned int *prologue_cost, stmt_vector_for_cost *prologue_cost_vec, stmt_vector_for_cost *body_cost_vec, bool record_prologue_costs) { - dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); - int alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, dr_info, vectype, false); - switch (alignment_support_scheme) { case dr_aligned: @@ -1239,8 +1246,7 @@ vect_get_load_cost (vec_info *vinfo, stmt_vec_info stmt_info, int ncopies, /* Here, we assign an additional cost for the unaligned load. */ *inside_cost += record_stmt_cost (body_cost_vec, ncopies, unaligned_load, stmt_info, - dr_misalignment (dr_info, vectype), - vect_body); + misalignment, vect_body); if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, @@ -1967,13 +1973,14 @@ perm_mask_for_reverse (tree vectype) /* A subroutine of get_load_store_type, with a subset of the same arguments. Handle the case where STMT_INFO is a load or store that - accesses consecutive elements with a negative step. */ + accesses consecutive elements with a negative step. Sets *POFFSET + to the offset to be applied to the DR for the first access. */ static vect_memory_access_type get_negative_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, tree vectype, vec_load_store_type vls_type, - unsigned int ncopies) + unsigned int ncopies, poly_int64 *poffset) { dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info); dr_alignment_support alignment_support_scheme; @@ -1986,8 +1993,9 @@ get_negative_load_store_type (vec_info *vinfo, return VMAT_ELEMENTWISE; } - alignment_support_scheme = vect_supportable_dr_alignment (vinfo, dr_info, - vectype, false); + int misalignment = dr_misalignment (dr_info, vectype); + alignment_support_scheme + = vect_supportable_dr_alignment (vinfo, dr_info, vectype, misalignment); if (alignment_support_scheme != dr_aligned && alignment_support_scheme != dr_unaligned_supported) { @@ -2003,6 +2011,7 @@ get_negative_load_store_type (vec_info *vinfo, dump_printf_loc (MSG_NOTE, vect_location, "negative step with invariant source;" " no permute needed.\n"); + *poffset = -TYPE_VECTOR_SUBPARTS (vectype) + 1; return VMAT_CONTIGUOUS_DOWN; } @@ -2014,6 +2023,7 @@ get_negative_load_store_type (vec_info *vinfo, return VMAT_ELEMENTWISE; } + *poffset = -TYPE_VECTOR_SUBPARTS (vectype) + 1; return VMAT_CONTIGUOUS_REVERSE; } @@ -2108,7 +2118,9 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, tree vectype, slp_tree slp_node, bool masked_p, vec_load_store_type vls_type, vect_memory_access_type *memory_access_type, + poly_int64 *poffset, dr_alignment_support *alignment_support_scheme, + int *misalignment, gather_scatter_info *gs_info) { loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); @@ -2180,15 +2192,15 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, can do half-vector operations avoid the epilogue peeling by simply loading half of the vector only. Usually the construction with an upper zero half will be elided. */ - dr_alignment_support alignment_support_scheme; + dr_alignment_support alss; + int misalign = dr_misalignment (first_dr_info, vectype); tree half_vtype; if (overrun_p && !masked_p - && (((alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, - vectype, false))) + && (((alss = vect_supportable_dr_alignment (vinfo, first_dr_info, + vectype, misalign))) == dr_aligned - || alignment_support_scheme == dr_unaligned_supported) + || alss == dr_unaligned_supported) && known_eq (nunits, (group_size - gap) * 2) && known_eq (nunits, group_size) && (vector_vector_composition_type (vectype, 2, &half_vtype) @@ -2209,7 +2221,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, /* ??? The VMAT_CONTIGUOUS_REVERSE code generation is only correct for single element "interleaving" SLP. */ *memory_access_type = get_negative_load_store_type - (vinfo, stmt_info, vectype, vls_type, 1); + (vinfo, stmt_info, vectype, vls_type, 1, poffset); else { /* Try to use consecutive accesses of DR_GROUP_SIZE elements, @@ -2294,10 +2306,17 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, if (*memory_access_type == VMAT_GATHER_SCATTER || *memory_access_type == VMAT_ELEMENTWISE) - *alignment_support_scheme = dr_unaligned_supported; + { + *alignment_support_scheme = dr_unaligned_supported; + *misalignment = DR_MISALIGNMENT_UNKNOWN; + } else - *alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false); + { + *misalignment = dr_misalignment (first_dr_info, vectype); + *alignment_support_scheme + = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, + *misalignment); + } if (vls_type != VLS_LOAD && first_stmt_info == stmt_info) { @@ -2337,7 +2356,9 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, storing it in *MEMORY_ACCESS_TYPE if so. If we decide to use gathers or scatters, fill in GS_INFO accordingly. In addition *ALIGNMENT_SUPPORT_SCHEME is filled out and false is returned if - the target does not support the alignment scheme. + the target does not support the alignment scheme. *MISALIGNMENT + is set according to the alignment of the access (including + DR_MISALIGNMENT_UNKNOWN when it is unknown). SLP says whether we're performing SLP rather than loop vectorization. MASKED_P is true if the statement is conditional on a vectorized mask. @@ -2350,11 +2371,15 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, bool masked_p, vec_load_store_type vls_type, unsigned int ncopies, vect_memory_access_type *memory_access_type, + poly_int64 *poffset, dr_alignment_support *alignment_support_scheme, + int *misalignment, gather_scatter_info *gs_info) { loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo); poly_uint64 nunits = TYPE_VECTOR_SUBPARTS (vectype); + *misalignment = DR_MISALIGNMENT_UNKNOWN; + *poffset = 0; if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) { *memory_access_type = VMAT_GATHER_SCATTER; @@ -2401,8 +2426,9 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, { if (!get_group_load_store_type (vinfo, stmt_info, vectype, slp_node, masked_p, - vls_type, memory_access_type, - alignment_support_scheme, gs_info)) + vls_type, memory_access_type, poffset, + alignment_support_scheme, + misalignment, gs_info)) return false; } else if (STMT_VINFO_STRIDED_P (stmt_info)) @@ -2432,13 +2458,15 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, { if (cmp < 0) *memory_access_type = get_negative_load_store_type - (vinfo, stmt_info, vectype, vls_type, ncopies); + (vinfo, stmt_info, vectype, vls_type, ncopies, poffset); else *memory_access_type = VMAT_CONTIGUOUS; + *misalignment = dr_misalignment (STMT_VINFO_DR_INFO (stmt_info), + vectype); *alignment_support_scheme = vect_supportable_dr_alignment (vinfo, STMT_VINFO_DR_INFO (stmt_info), - vectype, false); + vectype, *misalignment); } } @@ -7228,7 +7256,6 @@ vectorizable_store (vec_info *vinfo, unsigned int group_size, i; vec<tree> oprnds = vNULL; vec<tree> result_chain = vNULL; - tree offset = NULL_TREE; vec<tree> vec_oprnds = vNULL; bool slp = (slp_node != NULL); unsigned int vec_num; @@ -7337,9 +7364,11 @@ vectorizable_store (vec_info *vinfo, vect_memory_access_type memory_access_type; enum dr_alignment_support alignment_support_scheme; + int misalignment; + poly_int64 poffset; if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, vls_type, - ncopies, &memory_access_type, - &alignment_support_scheme, &gs_info)) + ncopies, &memory_access_type, &poffset, + &alignment_support_scheme, &misalignment, &gs_info)) return false; if (mask) @@ -7422,7 +7451,8 @@ vectorizable_store (vec_info *vinfo, STMT_VINFO_TYPE (stmt_info) = store_vec_info_type; vect_model_store_cost (vinfo, stmt_info, ncopies, - memory_access_type, vls_type, slp_node, cost_vec); + memory_access_type, alignment_support_scheme, + misalignment, vls_type, slp_node, cost_vec); return true; } gcc_assert (memory_access_type == STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info)); @@ -7904,14 +7934,6 @@ vectorizable_store (vec_info *vinfo, auto_vec<tree> dr_chain (group_size); oprnds.create (group_size); - /* Gather-scatter accesses perform only component accesses, alignment - is irrelevant for them. */ - if (memory_access_type == VMAT_GATHER_SCATTER) - alignment_support_scheme = dr_unaligned_supported; - else - alignment_support_scheme - = vect_supportable_dr_alignment (vinfo, first_dr_info, vectype, false); - gcc_assert (alignment_support_scheme); vec_loop_masks *loop_masks = (loop_vinfo && LOOP_VINFO_FULLY_MASKED_P (loop_vinfo) @@ -7934,9 +7956,9 @@ vectorizable_store (vec_info *vinfo, || alignment_support_scheme == dr_aligned || alignment_support_scheme == dr_unaligned_supported); - if (memory_access_type == VMAT_CONTIGUOUS_DOWN - || memory_access_type == VMAT_CONTIGUOUS_REVERSE) - offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1); + tree offset = NULL_TREE; + if (!known_eq (poffset, 0)) + offset = size_int (poffset); tree bump; tree vec_offset = NULL_TREE; @@ -8221,16 +8243,18 @@ vectorizable_store (vec_info *vinfo, vec_oprnd = result_chain[i]; align = known_alignment (DR_TARGET_ALIGNMENT (first_dr_info)); - if (aligned_access_p (first_dr_info, vectype)) - misalign = 0; - else if (dr_misalignment (first_dr_info, vectype) - == DR_MISALIGNMENT_UNKNOWN) + if (alignment_support_scheme == dr_aligned) + { + gcc_assert (aligned_access_p (first_dr_info, vectype)); + misalign = 0; + } + else if (misalignment == DR_MISALIGNMENT_UNKNOWN) { align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info)); misalign = 0; } else - misalign = dr_misalignment (first_dr_info, vectype); + misalign = misalignment; if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME) set_ptr_info_alignment (get_ptr_info (dataref_ptr), align, @@ -8307,8 +8331,8 @@ vectorizable_store (vec_info *vinfo, dataref_offset ? dataref_offset : build_int_cst (ref_type, 0)); - if (aligned_access_p (first_dr_info, vectype)) - ; + if (alignment_support_scheme == dr_aligned) + gcc_assert (aligned_access_p (first_dr_info, vectype)); else TREE_TYPE (data_ref) = build_aligned_type (TREE_TYPE (data_ref), @@ -8489,7 +8513,6 @@ vectorizable_load (vec_info *vinfo, unsigned int group_size; poly_uint64 group_gap_adj; tree msq = NULL_TREE, lsq; - tree offset = NULL_TREE; tree byte_offset = NULL_TREE; tree realignment_token = NULL_TREE; gphi *phi = NULL; @@ -8698,9 +8721,11 @@ vectorizable_load (vec_info *vinfo, vect_memory_access_type memory_access_type; enum dr_alignment_support alignment_support_scheme; + int misalignment; + poly_int64 poffset; if (!get_load_store_type (vinfo, stmt_info, vectype, slp_node, mask, VLS_LOAD, - ncopies, &memory_access_type, - &alignment_support_scheme, &gs_info)) + ncopies, &memory_access_type, &poffset, + &alignment_support_scheme, &misalignment, &gs_info)) return false; if (mask) @@ -8763,6 +8788,7 @@ vectorizable_load (vec_info *vinfo, STMT_VINFO_TYPE (stmt_info) = load_vec_info_type; vect_model_load_cost (vinfo, stmt_info, ncopies, vf, memory_access_type, + alignment_support_scheme, misalignment, &gs_info, slp_node, cost_vec); return true; } @@ -9283,6 +9309,9 @@ vectorizable_load (vec_info *vinfo, else at_loop = loop; + tree offset = NULL_TREE; + if (!known_eq (poffset, 0)) + offset = size_int (poffset); if (memory_access_type == VMAT_CONTIGUOUS_REVERSE) offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1); @@ -9558,14 +9587,14 @@ vectorizable_load (vec_info *vinfo, gcc_assert (aligned_access_p (first_dr_info, vectype)); misalign = 0; } - else if (dr_misalignment (first_dr_info, vectype) == -1) + else if (misalignment == DR_MISALIGNMENT_UNKNOWN) { align = dr_alignment (vect_dr_behavior (vinfo, first_dr_info)); misalign = 0; } else - misalign = dr_misalignment (first_dr_info, vectype); + misalign = misalignment; if (dataref_offset == NULL_TREE && TREE_CODE (dataref_ptr) == SSA_NAME) set_ptr_info_alignment (get_ptr_info (dataref_ptr), diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 4aa84ac..866d813 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -1957,11 +1957,13 @@ extern bool vect_nop_conversion_p (stmt_vec_info); extern opt_result vect_analyze_stmt (vec_info *, stmt_vec_info, bool *, slp_tree, slp_instance, stmt_vector_for_cost *); -extern void vect_get_load_cost (vec_info *, stmt_vec_info, int, bool, +extern void vect_get_load_cost (vec_info *, stmt_vec_info, int, + dr_alignment_support, int, bool, unsigned int *, unsigned int *, stmt_vector_for_cost *, stmt_vector_for_cost *, bool); extern void vect_get_store_cost (vec_info *, stmt_vec_info, int, + dr_alignment_support, int, unsigned int *, stmt_vector_for_cost *); extern bool vect_supportable_shift (vec_info *, enum tree_code, tree); extern tree vect_gen_perm_mask_any (tree, const vec_perm_indices &); @@ -1978,7 +1980,7 @@ extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, unsigned int = 0); /* In tree-vect-data-refs.c. */ extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64); extern enum dr_alignment_support vect_supportable_dr_alignment - (vec_info *, dr_vec_info *, tree, bool); + (vec_info *, dr_vec_info *, tree, int); extern tree vect_get_smallest_scalar_type (stmt_vec_info, tree); extern opt_result vect_analyze_data_ref_dependences (loop_vec_info, unsigned int *); extern bool vect_slp_analyze_instance_dependence (vec_info *, slp_instance); |