diff options
author | Thomas Schwinge <tschwinge@baylibre.com> | 2024-03-19 16:37:35 +0100 |
---|---|---|
committer | Thomas Schwinge <tschwinge@baylibre.com> | 2024-03-19 16:37:35 +0100 |
commit | e8c161211f0c5bfac915979aebcd6a16b0bc49ab (patch) | |
tree | 5c6bfeac90f189d4f07b82337cea932083751727 | |
parent | f0fdff9b6da1a17d8e1c2d83347e84c5218b1b29 (diff) | |
parent | 061a82fa2b751b42d0d8ddfcd45367c848d3ee64 (diff) | |
download | gcc-e8c161211f0c5bfac915979aebcd6a16b0bc49ab.zip gcc-e8c161211f0c5bfac915979aebcd6a16b0bc49ab.tar.gz gcc-e8c161211f0c5bfac915979aebcd6a16b0bc49ab.tar.bz2 |
Merge commit 'f7884f7673444b8a2c10ea0981d480f2e82dd16a^' into HEAD
1412 files changed, 37261 insertions, 10414 deletions
@@ -1,3 +1,16 @@ +2023-11-23 Nathaniel Shead <nathanieloshead@gmail.com> + + * MAINTAINERS: Add myself to write after approval and DCO + +2023-11-22 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * libtool.m4: Fix stray call + +2023-11-19 Lewis Hyatt <lhyatt@gmail.com> + + * Makefile.in: Regenerate. + * Makefile.tpl: Add dependency on site.exp to check-gcc-* targets + 2023-11-18 Petter Tomner <tomner@bahnhof.se> * MAINTAINERS: Update my email address. diff --git a/MAINTAINERS b/MAINTAINERS index 2e26db8..e1e66b5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -654,6 +654,7 @@ Svein Seldal <svein@dev.seldal.com> Senthil Kumar Selvaraj <saaadhu@gcc.gnu.org> Thiemo Seufer <ths@networkno.de> Bill Seurer <seurer@linux.vnet.ibm.com> +Nathaniel Shead <nathanieloshead@gmail.com> Tim Shen <timshen@google.com> David Sherwood <david.sherwood@arm.com> Sharad Singhai <singhai@google.com> @@ -768,6 +769,7 @@ Navid Rahimi <navidrahimi@microsoft.com> Rishi Raj <rishiraj45035@gmail.com> Trevor Saunders <tbsaunde+gcc@tbsaunde.org> Bill Schmidt <bill.schmidt@fastmail.com> +Nathaniel Shead <nathanieloshead@gmail.org> Nathan Sidwell <nathan@acm.org> Edward Smith-Rowland <esmithrowland@gmail.com> Petter Tomner <tomner@bahnhof.se> diff --git a/contrib/regression/ChangeLog b/contrib/regression/ChangeLog index 27dccac..82abb1f 100644 --- a/contrib/regression/ChangeLog +++ b/contrib/regression/ChangeLog @@ -1,3 +1,16 @@ +2023-11-23 Hans-Peter Nilsson <hp@axis.com> + + * btest-gcc.sh (--handle-xpass-as-fail): New option. + +2023-11-23 Hans-Peter Nilsson <hp@axis.com> + + * btest-gcc.sh (Option handling): Break out shifts from each + option alternative. + +2023-11-23 Hans-Peter Nilsson <hp@axis.com> + + * btest-gcc.sh (Option handling): Handle multiple options. + 2023-02-16 Hans-Peter Nilsson <hp@axis.com> * objs-gcc.sh: Only bootstrap if source-directory contains gcc. diff --git a/contrib/regression/btest-gcc.sh b/contrib/regression/btest-gcc.sh index 1808fcc..684019f 100755 --- a/contrib/regression/btest-gcc.sh +++ b/contrib/regression/btest-gcc.sh @@ -22,20 +22,29 @@ add_passes_despite_regression=0 dashj='' +handle_xpass_as_fail=false # <options> can be # --add-passes-despite-regression: # Add new "PASSes" despite there being some regressions. # -j<n>: # Pass '-j<n>' to make. - -case "$1" in - --add-passes-despite-regression) - add_passes_despite_regression=1; shift;; - -j*) - dashj=$1; shift;; - -*) echo "Invalid option: $1"; exit 2;; -esac +# --handle-xpass-as-fail: +# Count XPASS as a FAIL (default ignored). + +while : ; do + case "$1" in + --add-passes-despite-regression) + add_passes_despite_regression=1;; + --handle-xpass-as-fail) + handle_xpass_as_fail=true;; + -j*) + dashj=$1;; + -*) echo "Invalid option: $1"; exit 2;; + *) break;; + esac + shift +done # TARGET is the target triplet. It should be the same one as used in # constructing PREFIX. Or it can be the keyword 'native', indicating @@ -199,7 +208,11 @@ done # Work out what failed for LOG in $TESTLOGS ; do L=`basename $LOG` - awk '/^FAIL: / { print "'$L'",$2; }' $LOG || exit 1 + if $handle_xpass_as_fail ; then + awk '/^(FAIL|XPASS): / { print "'$L'",$2; }' $LOG || exit 1 + else + awk '/^FAIL: / { print "'$L'",$2; }' $LOG || exit 1 + fi done | sort | uniq > $FAILED || exit 1 comm -12 $FAILED $PASSES >> $REGRESS || exit 1 NUMREGRESS=`wc -l < $REGRESS | tr -d ' '` diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog index 3d5b2d2..7fbb611 100644 --- a/fixincludes/ChangeLog +++ b/fixincludes/ChangeLog @@ -1,3 +1,7 @@ +2023-11-22 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * configure: Regenerated. + 2023-10-30 Iain Sandoe <iain@sandoe.co.uk> * configure: Regenerate. diff --git a/fixincludes/configure b/fixincludes/configure index 1bb547a..662c94d 100755 --- a/fixincludes/configure +++ b/fixincludes/configure @@ -3027,7 +3027,6 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # --------------------------- # _LT_COMPILER_PIC -enable_darwin_at_rpath_$1=no # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 67906ac..aad4c29 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,1250 @@ +2023-11-26 Alexander Monakov <amonakov@ispras.ru> + + * sort.cc: Use 'sorting networks' in comments. + +2023-11-26 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + * config/riscv/riscv-avlprop.cc (avl_can_be_propagated_p): Add slidedown. + (vlmax_ta_p): Ditto. + (pass_avlprop::get_vlmax_ta_preferred_avl): Ditto. + +2023-11-26 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-avlprop.cc (alv_can_be_propagated_p): Fix typo. + (avl_can_be_propagated_p): Ditto. + (vlmax_ta_p): Ditto. + +2023-11-25 Gerald Pfeifer <gerald@pfeifer.com> + + PR other/69374 + * doc/install.texi (Downloading the source): Sort the list of + front ends and add D, Go, and Modula-2. + +2023-11-25 Gerald Pfeifer <gerald@pfeifer.com> + + PR target/69374 + * doc/install.texi (Specific) <*-*-freebsd*>: Remove older + contents referencing GCC 4.x. + +2023-11-25 Gerald Pfeifer <gerald@pfeifer.com> + + * doc/standards.texi (Standards): Update ISO C++ reference. + +2023-11-25 Jakub Jelinek <jakub@redhat.com> + + PR target/111408 + * config/i386/i386.md (*jcc_bt<mode>_mask, + *jcc_bt<SWI48:mode>_mask_1): Add (const_int 0) as expected + second operand of bt_comparison_operator. + +2023-11-25 Andrew Pinski <pinskia@gmail.com> + Jakub Jelinek <jakub@redhat.com> + + PR target/109977 + * config/aarch64/aarch64-simd.md (aarch64_simd_stp<mode>): Use <vwcore> + rather than %<vw> for alternative with r constraint on input operand. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * doc/install.texi (amdgcn-*-amdhsa): Fix URL to ROCm; + change 'in the future' to 'in LLVM 18'. + +2023-11-24 John David Anglin <danglin@gcc.gnu.org> + + * config/pa/pa.cc (pa_emit_move_sequence): Use INT14_OK_STRICT + in a couple of places. + +2023-11-24 Martin Jambor <mjambor@suse.cz> + + PR middle-end/109849 + * tree-sra.cc (passed_by_ref_in_call): New. + (sra_initialize): Allocate passed_by_ref_in_call. + (sra_deinitialize): Free passed_by_ref_in_call. + (create_access): Add decl pool candidates only if they are not + already candidates. + (build_access_from_expr_1): Bail out on ADDR_EXPRs. + (build_access_from_call_arg): New function. + (asm_visit_addr): Rename to scan_visit_addr, change the + disqualification dump message. + (scan_function): Check taken addresses for all non-call statements, + including phi nodes. Process all call arguments, including the static + chain, build_access_from_call_arg. + (maybe_add_sra_candidate): Relax need_to_live_in_memory check to allow + non-escaped local variables. + (sort_and_splice_var_accesses): Disallow smaller-than-precision + replacements for aggregates passed by reference to functions. + (sra_modify_expr): Use a separate stmt iterator for adding satements + before the processed statement and after it. + (enum out_edge_check): New type. + (abnormal_edge_after_stmt_p): New function. + (sra_modify_call_arg): New function. + (sra_modify_assign): Adjust calls to sra_modify_expr. + (sra_modify_function_body): Likewise, use sra_modify_call_arg to + process call arguments, including the static chain. + +2023-11-24 Uros Bizjak <ubizjak@gmail.com> + + PR target/112686 + * config/i386/i386.cc (ix86_expand_split_stack_prologue): Load + function address to a register for ix86_cmodel == CM_LARGE. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * doc/invoke.texi (-Wopenmp): Add. + * gimplify.cc (gimplify_omp_for): Add OPT_Wopenmp to warning_at. + * omp-expand.cc (expand_omp_ordered_sink): Likewise. + * omp-general.cc (omp_check_context_selector): Likewise. + * omp-low.cc (scan_omp_for, check_omp_nesting_restrictions, + lower_omp_ordered_clauses): Likewise. + * omp-simd-clone.cc (simd_clone_clauses_extract): Likewise. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112694 + * config/riscv/riscv-v.cc (preferred_simd_mode): Allow poly_int (1,1) vectors. + +2023-11-24 Alexander Monakov <amonakov@ispras.ru> + + * config.in: Regenerate. + * configure: Regenerate. + * configure.ac: Delete manual checks for old Valgrind headers. + * system.h (VALGRIND_MAKE_MEM_NOACCESS): Delete. + (VALGRIND_MAKE_MEM_DEFINED): Delete. + (VALGRIND_MAKE_MEM_UNDEFINED): Delete. + (VALGRIND_MALLOCLIKE_BLOCK): Delete. + (VALGRIND_FREELIKE_BLOCK): Delete. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR target/112681 + * config/i386/i386-expand.cc (ix86_expand_branch): Use + ix86_expand_vector_logical_operator to expand vector XOR rather than + gen_rtx_SET on gen_rtx_XOR. + +2023-11-24 Alex Coplan <alex.coplan@arm.com> + + * rtl-ssa/access-utils.h (filter_accesses): New. + (remove_regno_access): New. + (check_remove_regno_access): New. + * rtl-ssa/accesses.cc (rtl_ssa::remove_note_accesses_base): Use + new filter_accesses helper. + +2023-11-24 Alex Coplan <alex.coplan@arm.com> + + * rtl-ssa/accesses.cc (function_info::create_set): New. + * rtl-ssa/accesses.h (access_info::is_temporary): New. + * rtl-ssa/changes.cc (move_insn): Handle new (temporary) insns. + (function_info::finalize_new_accesses): Handle new/temporary + user-created accesses. + (function_info::apply_changes_to_insn): Ensure m_is_temp flag + on new insns gets cleared. + (function_info::change_insns): Handle new/temporary insns. + (function_info::create_insn): New. + * rtl-ssa/changes.h (class insn_change): Make function_info a + friend class. + * rtl-ssa/functions.h (function_info): Declare new entry points: + create_set, create_insn. Declare new change_alloc helper. + * rtl-ssa/insns.cc (insn_info::print_full): Identify temporary insns in + dump. + * rtl-ssa/insns.h (insn_info): Add new m_is_temp flag and accompanying + is_temporary accessor. + * rtl-ssa/internals.inl (insn_info::insn_info): Initialize m_is_temp to + false. + * rtl-ssa/member-fns.inl (function_info::change_alloc): New. + * rtl-ssa/movement.h (restrict_movement_for_defs_ignoring): Add + handling for temporary defs. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/112673 + * match.pd (bit_field_ref (vce @0) -> bit_field_ref @0): Only simplify + if either @0 doesn't have scalar integral type or if it has mode + precision. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112679 + * gimple-lower-bitint.cc (gimple_lower_bitint): Also stop first loop on + floating point SSA_NAME set in FLOAT_EXPR assignment from BITINT_TYPE + INTEGER_CST. Set has_large_huge for those if that BITINT_TYPE is large + or huge. Set kind to such FLOAT_EXPR assignment rhs1 BITINT_TYPE's kind. + +2023-11-24 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112677 + * tree-vect-loop.cc (vectorizable_reduction): Use alloca + to allocate vectype_op. + +2023-11-24 Haochen Gui <guihaoc@gcc.gnu.org> + + * expr.cc (by_pieces_ninsns): Include by pieces compare when + do the adjustment for overlap operations. Replace mov_optab + checks with gcc assertion. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112668 + * gimple-iterator.h (gsi_end, gsi_end_bb): New inline functions. + * gimple-lower-bitint.cc (bitint_large_huge::handle_cast): After + temporarily adding statements after m_init_gsi, update m_init_gsi + such that later additions after it will be after the added statements. + (bitint_large_huge::handle_load): Likewise. When splitting + gsi_bb (m_init_gsi) basic block, update m_preheader_bb if needed + and update saved m_gsi as well if needed. + (bitint_large_huge::lower_mergeable_stmt, + bitint_large_huge::lower_comparison_stmt, + bitint_large_huge::lower_mul_overflow, + bitint_large_huge::lower_bit_query): Use gsi_end_bb. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR c++/112619 + * tree.cc (try_catch_may_fallthru): If second operand of + TRY_CATCH_EXPR is not a STATEMENT_LIST, handle it as if it was a + STATEMENT_LIST containing a single statement. + +2023-11-24 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112344 + * tree-chrec.cc (chrec_apply): Only use an unsigned add + when the overall increment doesn't fit the signed type. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + * config/riscv/riscv-v.cc (shuffle_extract_and_slide1up_patterns): New function. + (expand_vec_perm_const_1): Add new optimization. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-v.cc (shuffle_bswap_pattern): Disable for NUNIT < 4. + +2023-11-24 Haochen Jiang <haochen.jiang@intel.com> + + PR target/112643 + * config/i386/driver-i386.cc (check_avx10_avx512_features): + Renamed to ... + (check_avx512_features): this and remove avx10 check. + (host_detect_local_cpu): Never append -mno-avx10.1-{256,512} to + avoid emitting warnings when building GCC with native arch. + * config/i386/i386-builtin.def (BDESC): Add missing AVX512VL for + 128/256 bit builtin for AVX512VP2INTERSECT. + * config/i386/i386-options.cc (ix86_option_override_internal): + Also check whether the AVX512 flags is set when trying to reset. + * config/i386/i386.h + (PTA_SKYLAKE_AVX512): Add missing PTA_EVEX512. + (PTA_ZNVER4): Ditto. + +2023-11-23 Georg-Johann Lay <avr@gjlay.de> + + PR target/86776 + * config/avr/avr.cc (TARGET_HAVE_SPECULATION_SAFE_VALUE): Define + to speculation_safe_value_not_needed. + +2023-11-23 Marek Polacek <polacek@redhat.com> + + * common.opt (Whardened, fhardened): New options. + * config.in: Regenerate. + * config/bpf/bpf.cc: Include "opts.h". + (bpf_option_override): If flag_stack_protector_set_by_fhardened_p, do + not inform that -fstack-protector does not work. + * config/i386/i386-options.cc (ix86_option_override_internal): When + -fhardened, maybe enable -fcf-protection=full. + * config/linux-protos.h (linux_fortify_source_default_level): Declare. + * config/linux.cc (linux_fortify_source_default_level): New. + * config/linux.h (TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL): Redefine. + * configure: Regenerate. + * configure.ac: Check if the linker supports '-z now' and '-z relro'. + Check if -fhardened is supported on $target_os. + * doc/invoke.texi: Document -fhardened and -Whardened. + * doc/tm.texi: Regenerate. + * doc/tm.texi.in (TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL): Add. + * gcc.cc (driver_handle_option): Remember if any link options or -static + were specified on the command line. + (process_command): When -fhardened, maybe enable -pie and + -Wl,-z,relro,-z,now. + * opts.cc (flag_stack_protector_set_by_fhardened_p): New global. + (finish_options): When -fhardened, enable + -ftrivial-auto-var-init=zero and -fstack-protector-strong. + (print_help_hardened): New. + (print_help): Call it. + * opts.h (flag_stack_protector_set_by_fhardened_p): Declare. + * target.def (fortify_source_default_level): New target hook. + * targhooks.cc (default_fortify_source_default_level): New. + * targhooks.h (default_fortify_source_default_level): Declare. + * toplev.cc (process_options): When -fhardened, enable + -fstack-clash-protection. If flag_stack_protector_set_by_fhardened_p, + do not warn that -fstack-protector not supported for this target. + Don't enable -fhardened when !HAVE_FHARDENED_SUPPORT. + +2023-11-23 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins-functions.h + (full_width_access::memory_vector_mode): Add default clause. + +2023-11-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/112672 + * config/i386/i386.md (parityhi2): + Use temporary register in the call to gen_parityhi2_cmp. + +2023-11-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/89316 + * config/i386/i386.cc (ix86_expand_split_stack_prologue): Obtain + scratch regno when flag_force_indirect_call is set. On 64-bit + targets, call __morestack_large_model when flag_force_indirect_call + is set and on 32-bit targets with -fpic, manually expand PIC sequence + to call __morestack. Move the function address to an indirect + call scratch register. + +2023-11-23 Sebastian Huber <sebastian.huber@embedded-brains.de> + + PR tree-optimization/112678 + * tree-profile.cc (tree_profiling): Do not use atomic operations + for -fprofile-update=single. + +2023-11-23 Juergen Christ <jchrist@linux.ibm.com> + + * config/s390/s390-c.cc (s390_cpu_cpp_builtins): Define + __GCC_ASM_FLAG_OUTPUTS__. + * config/s390/s390.cc (s390_canonicalize_comparison): More + UNSPEC_CC_TO_INT cases. + (s390_md_asm_adjust): Implement flags output. + * config/s390/s390.md (ccstore4): Allow mask operands. + * doc/extend.texi: Document flags output. + +2023-11-23 Juergen Christ <jchrist@linux.ibm.com> + + * config/s390/s390.md: Split TImode loads. + +2023-11-23 Juergen Christ <jchrist@linux.ibm.com> + + * config/s390/vector.md: (*vec_extract) Fix. + +2023-11-23 Di Zhao <dizhao@os.amperecomputing.com> + + * tree-ssa-reassoc.cc (get_reassociation_width): check + for loop dependent FMAs. + (reassociate_bb): For 3 ops, refine the condition to call + swap_ops_for_binary_stmt. + +2023-11-23 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-protos.h (emit_vec_extract): New function. + * config/riscv/riscv-v.cc (emit_vec_extract): Ditto. + * config/riscv/riscv.cc (riscv_legitimize_move): Refine codes. + +2023-11-23 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + PR target/112670 + * config/riscv/riscv-avlprop.cc (alv_can_be_propagated_p): New function. + (vlmax_ta_p): Disable vrgather AVL propagation. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112336 + * expr.cc (EXTEND_BITINT): Don't call reduce_to_bit_field_precision + if modifier is EXPAND_INITIALIZER. + +2023-11-23 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-v.cc (emit_vlmax_gather_insn): Refine codes. + (emit_vlmax_masked_gather_mu_insn): Ditto. + (modulo_sel_indices): Ditto. + (expand_vec_perm): Ditto. + (shuffle_generic_patterns): Ditto. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + * doc/extend.texi (__builtin_stdc_bit_ceil, __builtin_stdc_bit_floor, + __builtin_stdc_bit_width, __builtin_stdc_count_ones, + __builtin_stdc_count_zeros, __builtin_stdc_first_leading_one, + __builtin_stdc_first_leading_zero, __builtin_stdc_first_trailing_one, + __builtin_stdc_first_trailing_zero, __builtin_stdc_has_single_bit, + __builtin_stdc_leading_ones, __builtin_stdc_leading_zeros, + __builtin_stdc_trailing_ones, __builtin_stdc_trailing_zeros): Document. + +2023-11-23 Richard Biener <rguenther@suse.de> + + PR middle-end/32667 + * doc/md.texi (cpymem): Document that exact overlap of source + and destination needs to work. + * doc/standards.texi (ffreestanding): Mention memcpy is required + to handle the exact overlap case. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR c++/110348 + * doc/invoke.texi (-Wno-c++26-extensions): Document. + +2023-11-23 Manolis Tsamis <manolis.tsamis@vrull.eu> + + * ifcvt.cc (noce_convert_multiple_sets_1): Remove old code. + +2023-11-23 Pan Li <pan2.li@intel.com> + + PR target/111720 + * dse.cc (get_stored_val): Allow vector mode if read size is + less than or equal to stored size. + +2023-11-23 Costas Argyris <costas.argyris@gmail.com> + + * configure.ac: Handle new --enable-win32-utf8-manifest + option. + * config.host: allow win32 utf8 manifest to be disabled + by user. + * configure: Regenerate. + +2023-11-22 John David Anglin <danglin@gcc.gnu.org> + + PR target/112592 + * config/pa/pa.h (MAX_FIXED_MODE_SIZE): Define. + +2023-11-22 John David Anglin <danglin@gcc.gnu.org> + + PR target/112617 + * config/pa/predicates.md (integer_store_memory_operand): Return + true for REG+D addresses when reload_in_progress is true. + +2023-11-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112344 + * tree-chrec.cc (chrec_apply): Perform the overall increment + calculation and increment in an unsigned type. + +2023-11-22 Andrew Stubbs <ams@codesourcery.com> + + * config/gcn/gcn-valu.md (*mov<mode>_4reg): Disparage AVGPR use when a + reload is required. + +2023-11-22 Vladimir N. Makarov <vmakarov@redhat.com> + + PR rtl-optimization/112610 + * ira-costs.cc: (find_costs_and_classes): Remove arg. + Use ira_dump_file for printing. + (print_allocno_costs, print_pseudo_costs): Ditto. + (ira_costs): Adjust call of find_costs_and_classes. + (ira_set_pseudo_classes): Set up and restore ira_dump_file. + +2023-11-22 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * config/riscv/riscv-v.cc (shuffle_compress_patterns): Fix vcompress bug. + +2023-11-22 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md + (aarch64_uaddw<mode>_<PERM_EXTEND:perm_hilo>_zip, + aarch64_usubw<mode>_<PERM_EXTEND:perm_hilo>_zip): Split into... + (aarch64_uaddw<mode>_lo_zip, aarch64_uaddw<mode>_hi_zip, + "aarch64_usubw<mode>_lo_zip, "aarch64_usubw<mode>_hi_zip): ... This. + * config/aarch64/iterators.md (PERM_EXTEND, perm_index): Remove. + (perm_hilo): Remove UNSPEC_ZIP1, UNSPEC_ZIP2. + +2023-11-22 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins.cc + (function_resolver::infer_pointer_type): Remove spurious line. + +2023-11-22 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/lsx.md (vec_perm<mode:LSX>): Make the + selector VIMODE. + * config/loongarch/loongarch.cc (loongarch_expand_vec_perm): + Use the mode of the selector (instead of the shuffled vector) + for truncating it. Operate on subregs in the selector mode if + the shuffled vector has a different mode (i. e. it's a + floating-point vector). + +2023-11-22 Hongyu Wang <hongyu.wang@intel.com> + + * config/i386/i386.md (push2_di): Adjust operand order for AT&T + syntax. + (pop2_di): Likewise. + (push2p_di): Likewise. + (pop2p_di): Likewise. + +2023-11-22 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * config/riscv/riscv-v.cc (emit_vlmax_gather_insn): Adapt the priority. + (shuffle_generic_patterns): Fix permutation indice bug. + * config/riscv/vector-iterators.md: Fix VEI16 bug. + +2023-11-22 liuhongt <hongtao.liu@intel.com> + + * config/i386/sse.md (cbranch<mode>4): Extend to Vector + HI/QImode. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + PR target/111815 + * config/vax/vax.cc (index_term_p): Only accept the index scaler + as the RHS operand to ASHIFT. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/predicates.md (order_operator): Remove predicate. + * config/riscv/riscv.cc (riscv_rtx_costs): Update accordingly. + * config/riscv/riscv.md (*branch<mode>, *mov<GPR:mode><X:mode>cc) + (cstore<mode>4): Likewise. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv-protos.h (riscv_expand_float_scc): Add + `invert_ptr' parameter. + * config/riscv/riscv.cc (riscv_emit_float_compare): Add NE + inversion handling. + (riscv_expand_float_scc): Pass `invert_ptr' through to + `riscv_emit_float_compare'. + (riscv_expand_conditional_move): Pass `&invert' to + `riscv_expand_float_scc'. + * config/riscv/riscv.md (add<mode>cc): Likewise. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_emit_float_compare) <NE>: Handle + separately. + <EQ, LE, LT, GE, GT>: Return operands supplied as is. + (riscv_emit_binary): Call `riscv_emit_binary' directly rather + than going through a temporary register for word-mode targets. + (riscv_expand_conditional_branch): Canonicalize the comparison + if not against constant zero. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/predicates.md (ne_operator): New predicate. + * config/riscv/riscv.cc (riscv_insn_cost): Handle branches on a + floating-point condition. + * config/riscv/riscv.md (@cbranch<mode>4): Rename expander to... + (@cbranch<ANYF:mode>4): ... this. Only expand the RTX via + `riscv_expand_conditional_branch' for `!signed_order_operator' + operators, otherwise let it through. + (*cbranch<ANYF:mode>4, *cbranch<ANYF:mode>4): New insns and + splitters. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Don't + bail out in floating-point conditions. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_float_scc): Suppress the + use of SUBREG if the conditional-set target is word-mode. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.md (add<mode>cc): New expander. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/predicates.md (movcc_operand): New predicate. + * config/riscv/riscv.cc (riscv_expand_conditional_move): Handle + generic targets. + * config/riscv/riscv.md (mov<mode>cc): Likewise. + * config/riscv/riscv.opt (mmovcc): New option. + * doc/invoke.texi (Option Summary): Document it. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv-protos.h (riscv_emit_unary): New prototype. + * config/riscv/riscv.cc (riscv_emit_unary): New function. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Unify + conditional-move handling across all the relevant targets. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Also + accept constants for T-Head data input operands. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Also + accept constants for T-Head comparison operands. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Remove + the check for operand 1 being constant 0 in the Ventana/Zicond + case for equality comparisons. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Also + invert the condition for GEU and LEU. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_insn_cost): New function. + (riscv_max_noce_ifcvt_seq_cost): Likewise. + (riscv_noce_conversion_profitable_p): Likewise. + (TARGET_INSN_COST): New macro. + (TARGET_MAX_NOCE_IFCVT_SEQ_COST): New macro. + (TARGET_NOCE_CONVERSION_PROFITABLE_P): New macro. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Remove + extraneous variable for EQ vs NE operation selection. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Use + `nullptr' rather than 0 to initialize a pointer. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Use + `mode0' and `mode1' for `GET_MODE (op0)' and `GET_MODE (op1)'. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_expand_conditional_move): Use + `mode' for `GET_MODE (dest)' throughout. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.cc (riscv_emit_int_compare): Bail out if + NEED_EQ_NE_P but the comparison is neither EQ nor NE. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * config/riscv/riscv.md (mov<mode>cc): Move comment on SFB + patterns over to... + (*mov<GPR:mode><X:mode>cc): ... here. + +2023-11-21 Robin Dapp <rdapp@ventanamicro.com> + + PR middle-end/112406 + * tree-vect-loop.cc (vectorize_fold_left_reduction): Allow + reduction index != 1. + (vect_transform_reduction): Handle reduction index != 1. + +2023-11-21 Richard Sandiford <richard.sandiford@arm.com> + + * common.md (aligned_register_operand): New predicate. + +2023-11-21 Richard Sandiford <richard.sandiford@arm.com> + + * ira-int.h (ira_allocno): Add a register_filters field. + (ALLOCNO_REGISTER_FILTERS): New macro. + (ALLOCNO_SET_REGISTER_FILTERS): Likewise. + * ira-build.cc (ira_create_allocno): Initialize register_filters. + (create_cap_allocno): Propagate register_filters. + (propagate_allocno_info): Likewise. + (propagate_some_info_from_allocno): Likewise. + * ira-lives.cc (process_register_constraint_filters): New function. + (process_bb_node_lives): Use it to record register filter + information. + * ira-color.cc (assign_hard_reg): Check register filters. + (improve_allocation, fast_allocation): Likewise. + +2023-11-21 Richard Sandiford <richard.sandiford@arm.com> + + * lra-constraints.cc (process_alt_operands): Check register filters. + +2023-11-21 Richard Sandiford <richard.sandiford@arm.com> + + * recog.h (operand_alternative): Add a register_filters field. + (alternative_register_filters): New function. + * recog.cc (preprocess_constraints): Calculate the filters field. + (constrain_operands): Check register filters. + +2023-11-21 Richard Sandiford <richard.sandiford@arm.com> + + * rtl.def (DEFINE_REGISTER_CONSTRAINT): Add an optional filter + operand. + * doc/md.texi (define_register_constraint): Document it. + * doc/tm.texi.in: Reference it in discussion about aligned registers. + * doc/tm.texi: Regenerate. + * gensupport.h (register_filters, get_register_filter_id): Declare. + * gensupport.cc (register_filter_map, register_filters): New variables. + (get_register_filter_id): New function. + (process_define_register_constraint): Likewise. + (process_rtx): Pass define_register_constraints to + process_define_register_constraint. + * genconfig.cc (main): Emit a definition of NUM_REGISTER_FILTERS. + * genpreds.cc (constraint_data): Add a filter field. + (add_constraint): Update accordingly. + (process_define_register_constraint): Pass the filter operand. + (write_init_reg_class_start_regs): New function. + (write_get_register_filter): Likewise. + (write_get_register_filter_id): Likewise. + (write_tm_preds_h): Write a definition of target_constraints, + plus helpers to test its contents. Write the get_register_filter* + functions. + (write_insn_preds_c): Write init_reg_class_start_regs. + * reginfo.cc (init_reg_class_start_regs): Declare. + (init_reg_sets): Call it. + * target-globals.h (this_target_constraints): Declare. + (target_globals): Add a constraints field. + (restore_target_globals): Update accordingly. + * target-globals.cc: Include tm_p.h. + (default_target_globals): Initialize the constraints field. + (save_target_globals): Handle the constraints field. + (target_globals::~target_globals): Likewise. + +2023-11-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112623 + * tree-ssa-forwprop.cc (simplify_vector_constructor): + Check the source mode of the insn for vector pack/unpacks. + +2023-11-21 Richard Biener <rguenther@suse.de> + + * tree-vect-loop.cc (vect_analyze_loop_2): Move check + of VF against max_vf until VF is final. + +2023-11-21 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * config/riscv/riscv.cc (riscv_const_insns): Disallow DI CONST_VECTOR on RV32. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64.cc (aarch64_override_options): Rework warnings. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + PR target/111370 + * config/aarch64/aarch64-arches.def (armv9-a, armv9.1-a, armv9.2-a, + armv9.3-a): Update to generic-armv9-a. + * config/aarch64/aarch64-cores.def (generic-armv9-a): New. + * config/aarch64/aarch64-tune.md: Regenerate. + * config/aarch64/aarch64.cc: Include generic_armv9_a.h. + * config/aarch64/tuning_models/generic_armv9_a.h: New file. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + PR target/111370 + * config/aarch64/aarch64-arches.def (armv8-9, armv8-a, armv8.1-a, + armv8.2-a, armv8.3-a, armv8.4-a, armv8.5-a, armv8.6-a, armv8.7-a, + armv8.8-a): Update to generic_armv8_a. + * config/aarch64/aarch64-cores.def (generic-armv8-a): New. + * config/aarch64/aarch64-tune.md: Regenerate. + * config/aarch64/aarch64.cc: Include generic_armv8_a.h + * config/aarch64/aarch64.h (TARGET_CPU_DEFAULT): Change to + TARGET_CPU_generic_armv8_a. + * config/aarch64/tuning_models/generic_armv8_a.h: New file. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + PR target/111370 + * config/aarch64/aarch64-cores.def: Add generic. + * config/aarch64/aarch64-opts.h (enum aarch64_proc): Remove generic. + * config/aarch64/aarch64-tune.md: Regenerate + * config/aarch64/aarch64.cc (all_cores): Remove generic + * config/aarch64/aarch64.h (enum target_cpus): Remove + TARGET_CPU_generic. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + PR target/111370 + * config/aarch64/aarch64.cc (generic_addrcost_table, + exynosm1_addrcost_table, + xgene1_addrcost_table, + thunderx2t99_addrcost_table, + thunderx3t110_addrcost_table, + tsv110_addrcost_table, + qdf24xx_addrcost_table, + a64fx_addrcost_table, + neoversev1_addrcost_table, + neoversen2_addrcost_table, + neoversev2_addrcost_table, + generic_regmove_cost, + cortexa57_regmove_cost, + cortexa53_regmove_cost, + exynosm1_regmove_cost, + thunderx_regmove_cost, + xgene1_regmove_cost, + qdf24xx_regmove_cost, + thunderx2t99_regmove_cost, + thunderx3t110_regmove_cost, + tsv110_regmove_cost, + a64fx_regmove_cost, + neoversen2_regmove_cost, + neoversev1_regmove_cost, + neoversev2_regmove_cost, + generic_vector_cost, + a64fx_vector_cost, + qdf24xx_vector_cost, + thunderx_vector_cost, + tsv110_vector_cost, + cortexa57_vector_cost, + exynosm1_vector_cost, + xgene1_vector_cost, + thunderx2t99_vector_cost, + thunderx3t110_vector_cost, + ampere1_vector_cost, + generic_branch_cost, + generic_tunings, + cortexa35_tunings, + cortexa53_tunings, + cortexa57_tunings, + cortexa72_tunings, + cortexa73_tunings, + exynosm1_tunings, + thunderxt88_tunings, + thunderx_tunings, + tsv110_tunings, + xgene1_tunings, + emag_tunings, + qdf24xx_tunings, + saphira_tunings, + thunderx2t99_tunings, + thunderx3t110_tunings, + neoversen1_tunings, + ampere1_tunings, + ampere1a_tunings, + neoversev1_vector_cost, + neoversev1_tunings, + neoverse512tvb_vector_cost, + neoverse512tvb_tunings, + neoversen2_vector_cost, + neoversen2_tunings, + neoversev2_vector_cost, + neoversev2_tunings + a64fx_tunings): Split into own files. + * config/aarch64/tuning_models/a64fx.h: New file. + * config/aarch64/tuning_models/ampere1.h: New file. + * config/aarch64/tuning_models/ampere1a.h: New file. + * config/aarch64/tuning_models/cortexa35.h: New file. + * config/aarch64/tuning_models/cortexa53.h: New file. + * config/aarch64/tuning_models/cortexa57.h: New file. + * config/aarch64/tuning_models/cortexa72.h: New file. + * config/aarch64/tuning_models/cortexa73.h: New file. + * config/aarch64/tuning_models/emag.h: New file. + * config/aarch64/tuning_models/exynosm1.h: New file. + * config/aarch64/tuning_models/generic.h: New file. + * config/aarch64/tuning_models/neoverse512tvb.h: New file. + * config/aarch64/tuning_models/neoversen1.h: New file. + * config/aarch64/tuning_models/neoversen2.h: New file. + * config/aarch64/tuning_models/neoversev1.h: New file. + * config/aarch64/tuning_models/neoversev2.h: New file. + * config/aarch64/tuning_models/qdf24xx.h: New file. + * config/aarch64/tuning_models/saphira.h: New file. + * config/aarch64/tuning_models/thunderx.h: New file. + * config/aarch64/tuning_models/thunderx2t99.h: New file. + * config/aarch64/tuning_models/thunderx3t110.h: New file. + * config/aarch64/tuning_models/thunderxt88.h: New file. + * config/aarch64/tuning_models/tsv110.h: New file. + * config/aarch64/tuning_models/xgene1.h: New file. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64-simd.md (vec_unpack<su>_lo_<mode, + vec_unpack<su>_lo_<mode): Split into... + (vec_unpacku_lo_<mode, vec_unpacks_lo_<mode, + vec_unpacku_lo_<mode, vec_unpacks_lo_<mode): ...These. + (aarch64_usubw<mode>_<PERM_EXTEND:perm_hilo>_zip): New. + (aarch64_uaddw<mode>_<PERM_EXTEND:perm_hilo>_zip): New. + * config/aarch64/iterators.md (PERM_EXTEND, perm_index): New. + (perm_hilo): Add UNSPEC_ZIP1, UNSPEC_ZIP2. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + * config/aarch64/aarch64.cc (aarch64_adjust_stmt_cost): Guard mla. + (aarch64_vector_costs::count_ops): Likewise. + +2023-11-21 Sebastian Huber <sebastian.huber@embedded-brains.de> + + PR middle-end/112634 + * tree-profile.cc (gen_assign_counter_update): Cast the unsigned result type of + __atomic_add_fetch() to the signed counter type. + (gen_counter_update): Fix formatting. + +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + * tree-profile.cc (gen_counter_update, tree_profiling): Formatting + fixes. + +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112639 + * builtins.cc (fold_builtin_bit_query): If arg0 has side-effects, arg1 + is specified but cleared, call save_expr on arg0. + +2023-11-21 Hongyu Wang <hongyu.wang@intel.com> + + * config/i386/i386-expand.h (gen_push): Add default bool + parameter. + (gen_pop): Likewise. + * config/i386/i386-opts.h (enum apx_features): Add apx_ppx, add + it to apx_all. + * config/i386/i386.cc (ix86_emit_restore_reg_using_pop): Add + ppx_p parameter for function declaration. + (gen_push2): Add ppx_p parameter, emit push2p if ppx_p is true. + (gen_push): Likewise. + (ix86_emit_restore_reg_using_pop2): Likewise for pop2p. + (ix86_emit_save_regs): Emit pushp/push2p under TARGET_APX_PPX. + (ix86_emit_restore_reg_using_pop): Add ppx_p, emit popp insn + and adjust cfi when ppx_p is ture. + (ix86_emit_restore_reg_using_pop2): Add ppx_p and parse to its + callee. + (ix86_emit_restore_regs_using_pop2): Likewise. + (ix86_expand_epilogue): Parse TARGET_APX_PPX to + ix86_emit_restore_reg_using_pop. + * config/i386/i386.h (TARGET_APX_PPX): New. + * config/i386/i386.md (UNSPEC_APX_PPX): New unspec. + (pushp_di): New define_insn. + (popp_di): Likewise. + (push2p_di): Likewise. + (pop2p_di): Likewise. + * config/i386/i386.opt: Add apx_ppx enum. + +2023-11-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/111970 + * tree-vect-stmts.cc (vectorizable_load): Fix offset calculation + for SLP gather load. + (vectorizable_store): Likewise for SLP scatter store. + +2023-11-21 Xi Ruoyao <xry111@xry111.site> + + * config/loongarch/loongarch-def.h (stdint.h): Guard with #if to + exclude it for target libraries. + (loongarch_isa_base_features): Likewise. + (loongarch_isa): Likewise. + (loongarch_abi): Likewise. + (loongarch_target): Likewise. + (loongarch_cpu_default_isa): Likewise. + +2023-11-21 liuhongt <hongtao.liu@intel.com> + + PR target/112325 + * config/i386/i386-expand.cc (emit_reduc_half): Hanlde + V8QImode. + * config/i386/mmx.md (reduc_<code>_scal_<mode>): New expander. + (reduc_<code>_scal_v4qi): Ditto. + +2023-11-20 Marc Poulhiès <dkm@kataplop.net> + + * config/nvptx/nvptx.h (struct machine_function): Fix typo in variadic. + * config/nvptx/nvptx.cc (nvptx_function_arg_advance): Adjust to use fixed name. + (nvptx_declare_function_name): Likewise. + (nvptx_call_args): Likewise. + (nvptx_expand_call): Likewise. + +2023-11-20 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * tree-profile.cc (gen_counter_update): Use unshare_expr() for the + counter expression in the second gimple_build_assign(). + +2023-11-20 Jan Hubicka <jh@suse.cz> + + * cgraph.cc (add_detected_attribute_1): New function. + (cgraph_node::add_detected_attribute): Likewise. + * cgraph.h (cgraph_node::add_detected_attribute): Declare. + * common.opt: Add -Wsuggest-attribute=returns_nonnull. + * doc/invoke.texi: Document new flag. + * gimple-range-fold.cc (fold_using_range::range_of_call): + Use known reutrn value ranges. + * ipa-prop.cc (struct ipa_return_value_summary): New type. + (class ipa_return_value_sum_t): New type. + (ipa_return_value_sum): New summary. + (ipa_record_return_value_range): New function. + (ipa_return_value_range): New function. + * ipa-prop.h (ipa_return_value_range): Declare. + (ipa_record_return_value_range): Declare. + * ipa-pure-const.cc (warn_function_returns_nonnull): New funcion. + * ipa-utils.h (warn_function_returns_nonnull): Declare. + * symbol-summary.h: Fix comment. + * tree-vrp.cc (execute_ranger_vrp): Record return values. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112618 + * tree-vect-loop.cc (vect_transform_loop_stmt): For not + relevant and unused .MASK_CALL make sure we remove the + scalar stmt. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112281 + * tree-loop-distribution.cc + (loop_distribution::pg_add_dependence_edges): For = in the + innermost common loop record a partition conflict. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR middle-end/112622 + * convert.cc (convert_to_real_1): Use element_precision + where a vector type might appear. Provide specific + diagnostic for unexpected vector argument. + +2023-11-20 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112597 + * config/riscv/vector-iterators.md: Remove VDEMOTE and VMDEMOTE. + * config/riscv/vector.md: Fix slide1 intermediate mode bug. + +2023-11-20 Robin Dapp <rdapp@ventanamicro.com> + + * config/riscv/riscv-v.cc (gather_scatter_valid_offset_mode_p): + Add check for XLEN == 32. + * config/riscv/vector-iterators.md: Change VLS part of the + demote iterator to 2x elements modes + * config/riscv/vector.md: Adjust iterators and insn conditions. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins-base.cc (vld1_impl, vld1q) + (vst1_impl, vst1q): New. + * config/arm/arm-mve-builtins-base.def (vld1q, vst1q): New. + * config/arm/arm-mve-builtins-base.h (vld1q, vst1q): New. + * config/arm/arm_mve.h + (vld1q): Delete. + (vst1q): Delete. + (vld1q_s8): Delete. + (vld1q_s32): Delete. + (vld1q_s16): Delete. + (vld1q_u8): Delete. + (vld1q_u32): Delete. + (vld1q_u16): Delete. + (vld1q_f32): Delete. + (vld1q_f16): Delete. + (vst1q_f32): Delete. + (vst1q_f16): Delete. + (vst1q_s8): Delete. + (vst1q_s32): Delete. + (vst1q_s16): Delete. + (vst1q_u8): Delete. + (vst1q_u32): Delete. + (vst1q_u16): Delete. + (__arm_vld1q_s8): Delete. + (__arm_vld1q_s32): Delete. + (__arm_vld1q_s16): Delete. + (__arm_vld1q_u8): Delete. + (__arm_vld1q_u32): Delete. + (__arm_vld1q_u16): Delete. + (__arm_vst1q_s8): Delete. + (__arm_vst1q_s32): Delete. + (__arm_vst1q_s16): Delete. + (__arm_vst1q_u8): Delete. + (__arm_vst1q_u32): Delete. + (__arm_vst1q_u16): Delete. + (__arm_vld1q_f32): Delete. + (__arm_vld1q_f16): Delete. + (__arm_vst1q_f32): Delete. + (__arm_vst1q_f16): Delete. + (__arm_vld1q): Delete. + (__arm_vst1q): Delete. + * config/arm/mve.md (mve_vld1q_f<mode>): Rename into ... + (@mve_vld1q_f<mode>): ... this. + (mve_vld1q_<supf><mode>): Rename into ... + (@mve_vld1q_<supf><mode>) ... this. + (mve_vst1q_f<mode>): Rename into ... + (@mve_vst1q_f<mode>): ... this. + (mve_vst1q_<supf><mode>): Rename into ... + (@mve_vst1q_<supf><mode>) ... this. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins-shapes.cc (load, store): New. + * config/arm/arm-mve-builtins-shapes.h (load, store): New. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins-functions.h (multi_vector_function) + (full_width_access): New classes. + * config/arm/arm-mve-builtins.cc + (find_type_suffix_for_scalar_type, infer_pointer_type) + (require_pointer_type, get_contiguous_base, add_mem_operand) + (add_fixed_operand, use_contiguous_load_insn) + (use_contiguous_store_insn): New. + * config/arm/arm-mve-builtins.h (memory_vector_mode) + (infer_pointer_type, require_pointer_type, get_contiguous_base) + (add_mem_operand) + (add_fixed_operand, use_contiguous_load_insn) + (use_contiguous_store_insn): New. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-mve-builtins-shapes.cc (build_const_pointer): + New. + (parse_type): Add support for '_', 'al' and 'as'. + * config/arm/arm-mve-builtins.h (function_instance): Add + memory_scalar_type. + (function_base): Likewise. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * config/arm/arm-builtins.cc (arm_init_simd_builtin_types): Fix + initialization of arm_simd_types[].eltype. + * config/arm/arm-mve-builtins.def (DEF_MVE_TYPE): Fix scalar + types. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + * typeclass.h (enum type_class): Add vector_type_class. + * builtins.cc (type_to_class): Return vector_type_class for + VECTOR_TYPE. + * doc/extend.texi (__builtin_classify_type): Mention bit-precise + integer types and vector types. + +2023-11-20 Robin Dapp <rdapp@ventanamicro.com> + + PR middle-end/112406 + * tree-vect-patterns.cc (vect_recog_mask_conversion_pattern): + Convert masks for conditional operations as well. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/90693 + * tree-ssa-math-opts.cc (match_single_bit_test): Mark POPCOUNT with + result only used in equality comparison against 1 with direct optab + support as .POPCOUNT call with 2 arguments. + * internal-fn.h (expand_POPCOUNT): Declare. + * internal-fn.def (DEF_INTERNAL_INT_EXT_FN): New macro, document it, + undefine at the end. + (POPCOUNT): Use it instead of DEF_INTERNAL_INT_FN. + * internal-fn.cc (DEF_INTERNAL_INT_EXT_FN): Define to nothing before + inclusion to define expanders. + (expand_POPCOUNT): New function. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/90693 + * tree-ssa-math-opts.cc (match_single_bit_test): New function. + (math_opts_dom_walker::after_dom_children): Call it for EQ_EXPR + and NE_EXPR assignments and GIMPLE_CONDs. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + * internal-fn.def: Document missing DEF_INTERNAL* macros and make sure + they are all undefined at the end. + * internal-fn.cc (lookup_hilo_internal_fn, lookup_evenodd_internal_fn, + widening_fn_p, get_len_internal_fn): Don't undef DEF_INTERNAL_*FN + macros after inclusion of internal-fn.def. + +2023-11-20 Haochen Jiang <haochen.jiang@intel.com> + + * common/config/i386/cpuinfo.h (get_available_features): + Add avx10_set and version and detect avx10.1. + (cpu_indicator_init): Handle avx10.1-512. + * common/config/i386/i386-common.cc + (OPTION_MASK_ISA2_AVX10_1_256_SET): New. + (OPTION_MASK_ISA2_AVX10_1_256_SET): Ditto. + (OPTION_MASK_ISA2_AVX10_1_512_UNSET): Ditto. + (OPTION_MASK_ISA2_AVX10_1_512_UNSET): Ditto. + (OPTION_MASK_ISA2_AVX2_UNSET): Modify for AVX10.1. + (ix86_handle_option): Handle -mavx10.1-256 and -mavx10.1-512. + Add indicator for explicit no-avx512 and no-avx10.1 options. + * common/config/i386/i386-cpuinfo.h (enum processor_features): + Add FEATURE_AVX10_1_256 and FEATURE_AVX10_1_512. + * common/config/i386/i386-isas.h: Add ISA_NAME_TABLE_ENTRY for + AVX10_1_256 and AVX10_1_512. + * config/i386/cpuid.h (bit_AVX10): New. + (bit_AVX10_256): Ditto. + (bit_AVX10_512): Ditto. + * config/i386/driver-i386.cc (check_avx10_avx512_features): New. + (host_detect_local_cpu): Do not append "-mno-" options under + specific scenarios to avoid emitting a warning. + * config/i386/i386-isa.def + (EVEX512): Add DEF_PTA(EVEX512). + (AVX10_1_256): Add DEF_PTA(AVX10_1_256). + (AVX10_1_512): Add DEF_PTA(AVX10_1_512). + * config/i386/i386-options.cc (isa2_opts): Add -mavx10.1-256 and + -mavx10.1-512. + (ix86_function_specific_save): Save explicit no indicator. + (ix86_function_specific_restore): Restore explicit no indicator. + (ix86_valid_target_attribute_inner_p): Handle avx10.1, avx10.1-256 and + avx10.1-512. + (ix86_valid_target_attribute_tree): Handle avx512 function + attributes with avx10.1 command line option. + (ix86_option_override_internal): Handle AVX10.1 options. + * config/i386/i386.h: Add PTA_EVEX512 for AVX512 target + machines. + * config/i386/i386.opt: Add variable ix86_no_avx512_explicit and + ix86_no_avx10_1_explicit, option -mavx10.1, -mavx10.1-256 and + -mavx10.1-512. + * doc/extend.texi: Document avx10.1, avx10.1-256 and avx10.1-512. + * doc/invoke.texi: Document -mavx10.1, -mavx10.1-256 and -mavx10.1-512. + * doc/sourcebuild.texi: Document target avx10.1, avx10.1-256 + and avx10.1-512. + +2023-11-20 liuhongt <hongtao.liu@intel.com> + + PR target/112325 + * config/i386/sse.md (reduc_<code>_scal_<mode>): New expander. + (REDUC_ANY_LOGIC_MODE): New iterator. + (REDUC_PLUS_MODE): Extend to VxHI/SI/DImode. + (REDUC_SSE_PLUS_MODE): Ditto. + +2023-11-20 xuli <xuli1@eswincomputing.com> + + PR target/112537 + * config/riscv/riscv-opts.h (enum riscv_stringop_strategy_enum): Strategy enum. + * config/riscv/riscv-string.cc (riscv_expand_block_move): Disabled based on options. + (expand_block_move): Ditto. + * config/riscv/riscv.opt: Add -mmemcpy-strategy=. + +2023-11-20 Lulu Cheng <chenglulu@loongson.cn> + + * config/loongarch/gnu-user.h (MUSL_ABI_SPEC): Modify suffix. + +2023-11-19 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-v.cc (emit_vlmax_insn_lra): Optimize constant AVL. + +2023-11-19 Philipp Tomsich <philipp.tomsich@vrull.eu> + + * config/riscv/riscv-protos.h (extract_base_offset_in_addr): Prototype. + * config/riscv/riscv.cc (riscv_fusion_pairs): New enum. + (riscv_tune_param): Add fusible_ops field. + (riscv_tune_param_rocket_tune_info): Initialize new field. + (riscv_tune_param_sifive_7_tune_info): Likewise. + (thead_c906_tune_info): Likewise. + (generic_oo_tune_info): Likewise. + (optimize_size_tune_info): Likewise. + (riscv_macro_fusion_p): New function. + (riscv_fusion_enabled_p): Likewise. + (riscv_macro_fusion_pair_p): Likewise. + (TARGET_SCHED_MACRO_FUSION_P): Define. + (TARGET_SCHED_MACRO_FUSION_PAIR_P): Likewise. + (extract_base_offset_in_addr): Moved into riscv.cc from... + * config/riscv/thead.cc: Here. + Co-authored-by: Raphael Zinsly <rzinsly@ventanamicro.com> + Co-authored-by: Jeff Law <jlaw@ventanamicro.com> + +2023-11-19 Jeff Law <jlaw@ventanamicro.com> + + * config/c6x/c6x.md (mvilc): Add mode to UNSPEC source. + * config/mips/mips.md (rdhwr_synci_step_<mode>): Likewise. + * config/riscv/riscv.md (riscv_frcsr, riscv_frflags): Likewise. + * config/s390/s390.md (@split_stack_call<mode>): Likewise. + (@split_stack_cond_call<mode>): Likewise. + * config/sh/sh.md (sp_switch_1): Likewise. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * diagnostic.h: Include "rich-location.h". + * edit-context.h (class fixit_hint): New forward decl. + * gcc-rich-location.h: Include "rich-location.h". + * genmatch.cc: Likewise. + * pretty-print.h: Likewise. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * Makefile.in (CPPLIB_H): Add libcpp/include/rich-location.h. + * coretypes.h (class rich_location): New forward decl. + +2023-11-19 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * config/riscv/riscv-v.cc (expand_tuple_move): Fix bug. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107573 + * doc/invoke.texi: Add -Wanalyzer-undefined-behavior-strtok. + 2023-11-18 Xi Ruoyao <xry111@xry111.site> * config/loongarch/predicates.md (const_call_insn_operand): diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6ce2b65..2d1ad39 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20231119 +20231127 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 45c3f37..6fb7510 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,190 @@ +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/trans.cc (Loop_Statement_to_gnu): Always use the + simpler form for a loop with a boolean iteration variable. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Array_Subtype>: Put + the alignment directly on the type in the constrained case too. + * gcc-interface/utils.cc (maybe_pad_type): For an array type, take + the alignment of the element type as the original alignment. + +2023-11-21 Gary Dismukes <dismukes@adacore.com> + + * sem_aggr.adb (Resolve_Container_Aggregate): In the case where Comp + is an N_Iterated_Component_Association, pick up Discrete_Choices rather + than Choices. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * exp_ch7.adb (Build_Finalizer): For package specs and bodies, push + and pop the specs onto the scope stack only once. + * inline.adb (Cleanup_Scopes): Call Pop_Scope instead of End_Scope. + +2023-11-21 Steve Baird <baird@adacore.com> + + * sem_aggr.adb (Resolve_Delta_Array_Aggregate): In the case of a + deep delta choice, the expected type for the expression will + typically not be the component type of the array type, so a call + to Analyze_And_Resolve that assumes otherwise would be an error. + It turns out that such a call, while wrong, is usually harmless + because the expression has already been marked as analyzed. This + doesn't work if the aggregate occurs in a postcondition and, in + any case, we don't want to rely on this. So do not perform the + call in the deep case. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * sem_warn.adb (Check_References.Type_OK_For_No_Value_Assigned): + New predicate. + (Check_References): For Warn_On_No_Value_Assigned, use the same test + on the type in the address-not-taken and default cases. + +2023-11-21 Gary Dismukes <dismukes@adacore.com> + + * exp_ch5.adb (Expand_Iterator_Loop_Over_Container): Retrieve the + iteration type's iteration interface progenitor via + Iterator_Interface_Ancestor, in the case of both "in" and "of" + iterators. Narrow the scope of Pack, so it's declared and + initialized only within the code related to "of" iterators, and + change its name to Cont_Type_Pack. Adjust comments. + * sem_ch5.adb (Get_Cursor_Type): In the case of a derived type, + retrieve the iteration type's iterator interface progenitor (if it + exists) via Iterator_Interface_Ancestor rather than assuming that + the parent type is the interface progenitor. + * sem_util.ads (Iterator_Interface_Ancestor): New function. + * sem_util.adb (Iterator_Interface_Ancestor): New function + returning a type's associated iterator interface type, if any, by + collecting and traversing the type's interfaces. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * sem_attr.adb (Resolve_Attribute) <Attribute_Address>: Remove the + bypass for prefixes with task type. + +2023-11-21 Viljar Indus <indus@adacore.com> + + * par.adb: Restore Style_Checks after parsing each unit. + +2023-11-21 Yannick Moy <moy@adacore.com> + + * exp_spark.adb (Expand_SPARK_Delta_Or_Aggregate): Fix type. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * sem_ch12.adb (Analyze_Package_Instantiation): Test Expander_Active + to detect generic contexts for the generation of cleanup actions. + +2023-11-21 Justin Squirek <squirek@adacore.com> + + * libgnat/g-catiio.adb (Value): Modify conditionals to use 'Last + instead of 'Length + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * sem_util.adb (Null_Status): Deal with unchecked type conversions. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * exp_aggr.adb (Convert_To_Assignments): Do not treat initialization + procedures specially when it comes to creating a transient scope. + * exp_ch7.adb (Build_Finalizer.Process_Declarations): Likewise. + * exp_util.adb (Requires_Cleanup_Actions): Likewise. + +2023-11-21 Doug Rupp <rupp@adacore.com> + + * s-oscons-tmplt.c: #define CLOCK_RT_Ada "CLOCK_MONOTONIC" for + __vxworks + +2023-11-21 Steve Baird <baird@adacore.com> + + * sem_aggr.adb: Replace "not Present (...)" call with "No (...)" call. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * gen_il-fields.ads (Opt_Field_Enum): Remove Is_Finalization_Wrapper + * gen_il-gen-gen_nodes.adb (N_Block_Statement): Likewise. + * sinfo.ads (Is_Finalization_Wrapper): Delete. + * exp_ch7.adb (Build_Finalizer.Process_Declarations): Adjust comment + and remove obsolete code testing the Is_Finalization_Wrapper flag. + * exp_util.adb (Requires_Cleanup_Actions): Likewise. + +2023-11-21 Doug Rupp <rupp@adacore.com> + + * libgnat/libada.gpr: Revise section 1 + +2023-11-21 Steve Baird <baird@adacore.com> + + * par.adb: Add new Boolean variable Inside_Delta_Aggregate. + * par-ch4.adb (P_Simple_Expression): Add support for a deep delta + aggregate choice. We turn a sequence of selectors into a peculiar + tree. We build a component (Indexed or Selected) whose prefix is + another such component, etc. The leftmost prefix at the bottom of + the tree has a "name" which is the first selector, without any + further prefix. For something like "with delta (1)(2) => 3" where + the type of the aggregate is an array of arrays of integers, we'll + build an N_Indexed_Component whose prefix is an integer literal 1. + This is consistent with the trees built for "regular" + (Ada-defined) delta aggregates. + * sem_aggr.adb (Is_Deep_Choice, Is_Root_Prefix_Of_Deep_Choice): + New queries. + (Resolve_Deep_Delta_Assoc): new procedure. + (Resolve_Delta_Array_Aggregate): call Resolve_Deep_Delta_Assoc in + deep case. + (Resolve_Delta_Record_Aggregate): call Resolve_Deep_Delta_Assoc in + deep case. + (Get_Component_Type): new function replaces old Get_Component + function. + * sem_aggr.ads (Is_Deep_Choice, Is_Root_Prefix_Of_Deep_Choice): + New queries. + * exp_aggr.adb (Expand_Delta_Array_Aggregate): add nested function + Make_Array_Delta_Assignment_LHS; call it instead of + Make_Indexed_Component. + (Expand_Delta_Record_Aggregate): add nested function + Make_Record_Delta_Assignment_LHS; call it instead of + Make_Selected_Component. + * exp_spark.adb (Expand_SPARK_Delta_Or_Update): Insert range + checks for indexes in deep delta aggregates. + +2023-11-21 Ronan Desplanques <desplanques@adacore.com> + + * adaint.c (__gnat_unlink): Add new parameter and fix text + conversion on Windows. Remove unnecessary curly braces. + * adaint.h (__gnat_unlink): Add new parameter. + * libgnat/i-cstrea.ads (unlink): Adapt to __gnat_unlink signature + change. + * libgnat/i-cstrea.adb (unlink): New Subprogram definition. + * libgnat/s-crtl.ads (unlink): Adapt to __gnat_unlink signature + change. + * libgnat/s-fileio.adb (Delete): Pass encoding argument to unlink. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * sem_ch12.adb (Save_Global_References.Set_Global_Type): Beef up + comment about the setting of the full view. + * sem_res.adb (Resolve_Actuals.Insert_Default): Add another bypass + for the case of a generic context. + +2023-11-21 Marc Poulhiès <poulhies@adacore.com> + + * doc/gnat_ugn/the_gnat_compilation_model.rst: Move index + directives. + * gnat_ugn.texi: Regenerate. + +2023-11-21 Pierre-Marie de Rodat <derodat@adacore.com> + + * par_sco.adb (Process_Decisions)<Process_Node>: Skip aspect + specifications. + +2023-11-21 Ronan Desplanques <desplanques@adacore.com> + + * libgnat/libgnat_common.gpr: Unconditionally pass -gnatg. + +2023-11-21 Marc Poulhiès <poulhies@adacore.com> + + * exp_util.ads: Typo fix. + 2023-11-16 Eric Botcazou <ebotcazou@adacore.com> * gcc-interface/decl.cc (gnat_to_gnu_subprog_type): Also create a diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c index bb4ed26..4ab9565 100644 --- a/gcc/ada/adaint.c +++ b/gcc/ada/adaint.c @@ -747,15 +747,19 @@ __gnat_os_filename (char *filename ATTRIBUTE_UNUSED, /* Delete a file. */ int -__gnat_unlink (char *path) +__gnat_unlink (char *path, int encoding ATTRIBUTE_UNUSED) { #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS) - { - TCHAR wpath[GNAT_MAX_PATH_LEN]; + TCHAR wpath[GNAT_MAX_PATH_LEN]; + if (encoding == Encoding_Unspecified) S2WSC (wpath, path, GNAT_MAX_PATH_LEN); - return _tunlink (wpath); - } + else if (encoding == Encoding_UTF8) + S2WSU (wpath, path, GNAT_MAX_PATH_LEN); + else + S2WS (wpath, path, GNAT_MAX_PATH_LEN); + + return _tunlink (wpath); #else return unlink (path); #endif diff --git a/gcc/ada/adaint.h b/gcc/ada/adaint.h index 987432c..298ea9e 100644 --- a/gcc/ada/adaint.h +++ b/gcc/ada/adaint.h @@ -172,7 +172,7 @@ extern int __gnat_open_new_temp (char *, int); extern int __gnat_mkdir (char *, int); extern int __gnat_stat (char *, GNAT_STRUCT_STAT *); -extern int __gnat_unlink (char *); +extern int __gnat_unlink (char *, int encoding); extern int __gnat_rename (char *, char *); extern int __gnat_chdir (char *); extern int __gnat_rmdir (char *); diff --git a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst index ed24fed..fd15459 100644 --- a/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst +++ b/gcc/ada/doc/gnat_ugn/the_gnat_compilation_model.rst @@ -226,9 +226,9 @@ possible encoding schemes: ``16#A345#``. This scheme is compatible with use of the full Wide_Character set. -*Upper-Half Coding* - .. index:: Upper-Half Coding +.. index:: Upper-Half Coding +*Upper-Half Coding* The wide character with encoding ``16#abcd#`` where the upper bit is on (in other words, 'a' is in the range 8-F) is represented as two bytes, ``16#ab#`` and ``16#cd#``. The second byte cannot be a format control @@ -236,9 +236,9 @@ possible encoding schemes: be also used for shift-JIS or EUC, where the internal coding matches the external coding. -*Shift JIS Coding* - .. index:: Shift JIS Coding +.. index:: Shift JIS Coding +*Shift JIS Coding* A wide character is represented by a two-character sequence, ``16#ab#`` and ``16#cd#``, with the restrictions described for upper-half encoding as @@ -247,10 +247,9 @@ possible encoding schemes: conversion. Only characters defined in the JIS code set table can be used with this encoding method. +.. index:: EUC Coding *EUC Coding* - .. index:: EUC Coding - A wide character is represented by a two-character sequence ``16#ab#`` and ``16#cd#``, with both characters being in the upper half. The internal diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb index 319254d..691430a 100644 --- a/gcc/ada/exp_aggr.adb +++ b/gcc/ada/exp_aggr.adb @@ -4294,15 +4294,9 @@ package body Exp_Aggr is return; end if; - -- Otherwise, if a transient scope is required, create it now. If we - -- are within an initialization procedure do not create such, because - -- the target of the assignment must not be declared within a local - -- block, and because cleanup will take place on return from the - -- initialization procedure. + -- Otherwise, if a transient scope is required, create it now - -- Should the condition be more restrictive ??? - - if Requires_Transient_Scope (Typ) and then not Inside_Init_Proc then + if Requires_Transient_Scope (Typ) then Establish_Transient_Scope (N, Manage_Sec_Stack => False); end if; @@ -5243,7 +5237,7 @@ package body Exp_Aggr is -- The bounds of the aggregate for this dimension Ind_Typ : constant Entity_Id := Aggr_Index_Typ (Dim); - -- The index type for this dimension.xxx + -- The index type for this dimension. Cond : Node_Id; Assoc : Node_Id; @@ -7344,6 +7338,12 @@ package body Exp_Aggr is -- choices that are ranges, subtype indications, subtype names, and -- iterated component associations. + function Make_Array_Delta_Assignment_LHS + (Choice : Node_Id; Temp : Entity_Id) return Node_Id; + -- Generate the LHS for the assignment associated with one + -- component association. This can be more complex than just an + -- indexed component in the case of a deep delta aggregate. + ------------------- -- Generate_Loop -- ------------------- @@ -7380,6 +7380,60 @@ package body Exp_Aggr is End_Label => Empty); end Generate_Loop; + function Make_Array_Delta_Assignment_LHS + (Choice : Node_Id; Temp : Entity_Id) return Node_Id + is + function Make_Delta_Choice_LHS + (Choice : Node_Id; + Deep_Choice : Boolean) return Node_Id; + -- Recursively (but recursion only in deep delta aggregate case) + -- build up the LHS by successively applying selectors. + + --------------------------- + -- Make_Delta_Choice_LHS -- + --------------------------- + + function Make_Delta_Choice_LHS + (Choice : Node_Id; + Deep_Choice : Boolean) return Node_Id + is + begin + if not Deep_Choice + or else Is_Root_Prefix_Of_Deep_Choice (Choice) + then + return Make_Indexed_Component (Sloc (Choice), + Prefix => New_Occurrence_Of (Temp, Loc), + Expressions => New_List (New_Copy_Tree (Choice))); + + else + -- a deep delta aggregate choice + pragma Assert (All_Extensions_Allowed); + + declare + -- recursively get name for prefix + LHS_Prefix : constant Node_Id + := Make_Delta_Choice_LHS (Prefix (Choice), Deep_Choice); + begin + if Nkind (Choice) = N_Indexed_Component then + return Make_Indexed_Component (Sloc (Choice), + Prefix => LHS_Prefix, + Expressions => New_Copy_List (Expressions (Choice))); + else + return Make_Selected_Component (Sloc (Choice), + Prefix => LHS_Prefix, + Selector_Name => + Make_Identifier + (Sloc (Choice), + Chars (Selector_Name (Choice)))); + end if; + end; + end if; + end Make_Delta_Choice_LHS; + begin + return Make_Delta_Choice_LHS + (Choice, Is_Deep_Choice (Choice, Etype (N))); + end Make_Array_Delta_Assignment_LHS; + -- Local variables Choice : Node_Id; @@ -7416,9 +7470,7 @@ package body Exp_Aggr is Append_To (Deltas, Make_Assignment_Statement (Sloc (Choice), Name => - Make_Indexed_Component (Sloc (Choice), - Prefix => New_Occurrence_Of (Temp, Loc), - Expressions => New_List (New_Copy_Tree (Choice))), + Make_Array_Delta_Assignment_LHS (Choice, Temp), Expression => New_Copy_Tree (Expression (Assoc)))); end if; @@ -7443,6 +7495,43 @@ package body Exp_Aggr is Assoc : Node_Id; Choice : Node_Id; + function Make_Record_Delta_Assignment_LHS + (Selector : Node_Id) return Node_Id; + -- Generate the LHS for an assignment to a component (or subcomponent + -- if -gnatX specified) of the result object. + + -------------------------------------- + -- Make_Record_Delta_Assignment_LHS -- + -------------------------------------- + + function Make_Record_Delta_Assignment_LHS + (Selector : Node_Id) return Node_Id + is + begin + if Nkind (Selector) = N_Selected_Component then + -- a deep delta aggregate, requires -gnatX0 + return + Make_Selected_Component + (Sloc (Choice), + Prefix => Make_Record_Delta_Assignment_LHS + (Prefix (Selector)), + Selector_Name => + Make_Identifier (Loc, Chars (Selector_Name (Selector)))); + elsif Nkind (Selector) = N_Indexed_Component then + -- a deep delta aggregate, requires -gnatX0 + return + Make_Indexed_Component + (Sloc (Choice), + Prefix => Make_Record_Delta_Assignment_LHS + (Prefix (Selector)), + Expressions => Expressions (Selector)); + else + return Make_Selected_Component + (Sloc (Choice), + Prefix => New_Occurrence_Of (Temp, Loc), + Selector_Name => Make_Identifier (Loc, Chars (Selector))); + end if; + end Make_Record_Delta_Assignment_LHS; begin Assoc := First (Component_Associations (N)); @@ -7451,10 +7540,7 @@ package body Exp_Aggr is while Present (Choice) loop Append_To (Deltas, Make_Assignment_Statement (Sloc (Choice), - Name => - Make_Selected_Component (Sloc (Choice), - Prefix => New_Occurrence_Of (Temp, Loc), - Selector_Name => Make_Identifier (Loc, Chars (Choice))), + Name => Make_Record_Delta_Assignment_LHS (Choice), Expression => New_Copy_Tree (Expression (Assoc)))); Next (Choice); end loop; diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index cd3b02b..d946f6d 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -5158,9 +5158,6 @@ package body Exp_Ch5 is -- The package in which the iterator interface is instantiated. This is -- typically an instance within the container package. - Pack : Entity_Id; - -- The package in which the container type is declared - begin if Present (Iterator_Filter (I_Spec)) then pragma Assert (Ada_Version >= Ada_2022); @@ -5195,15 +5192,6 @@ package body Exp_Ch5 is -- package Vector_Iterator_Interfaces is new -- Ada.Iterator_Interfaces (Cursor, Has_Element); - -- If the container type is a derived type, the cursor type is found in - -- the package of the ultimate ancestor type. - - if Is_Derived_Type (Container_Typ) then - Pack := Scope (Root_Type (Container_Typ)); - else - Pack := Scope (Container_Typ); - end if; - if Of_Present (I_Spec) then Handle_Of : declare Container_Arg : Node_Id; @@ -5289,6 +5277,9 @@ package body Exp_Ch5 is Default_Iter : Entity_Id; Ent : Entity_Id; + Cont_Type_Pack : Entity_Id; + -- The package in which the container type is declared + Reference_Control_Type : Entity_Id := Empty; Pseudo_Reference : Entity_Id := Empty; @@ -5312,11 +5303,14 @@ package body Exp_Ch5 is Iter_Type := Etype (Default_Iter); - -- The iterator type, which is a class-wide type, may itself be - -- derived locally, so the desired instantiation is the scope of - -- the root type of the iterator type. + -- If the container type is a derived type, the cursor type is + -- found in the package of the ultimate ancestor type. - Iter_Pack := Scope (Root_Type (Etype (Iter_Type))); + if Is_Derived_Type (Container_Typ) then + Cont_Type_Pack := Scope (Root_Type (Container_Typ)); + else + Cont_Type_Pack := Scope (Container_Typ); + end if; -- Find declarations needed for "for ... of" optimization. -- These declarations come from GNAT sources or sources @@ -5326,7 +5320,7 @@ package body Exp_Ch5 is -- Note that we use _Next or _Previous to avoid picking up -- some arbitrary user-defined Next or Previous. - Ent := First_Entity (Pack); + Ent := First_Entity (Cont_Type_Pack); while Present (Ent) loop -- Get_Element_Access function with one parameter called -- Position. @@ -5400,6 +5394,11 @@ package body Exp_Ch5 is Analyze_And_Resolve (Name (I_Spec)); + -- The desired instantiation is the scope of an iterator interface + -- type that is an ancestor of the iterator type. + + Iter_Pack := Scope (Iterator_Interface_Ancestor (Iter_Type)); + -- Find cursor type in proper iterator package, which is an -- instantiation of Iterator_Interfaces. @@ -5469,11 +5468,12 @@ package body Exp_Ch5 is else Iter_Type := Etype (Name (I_Spec)); - -- The iterator type, which is a class-wide type, may itself be - -- derived locally, so the desired instantiation is the scope of - -- the root type of the iterator type, as in the "of" case. + -- The instantiation in which to locate the Has_Element function + -- is the scope containing an iterator interface type that is + -- an ancestor of the iterator type. + + Iter_Pack := Scope (Iterator_Interface_Ancestor (Iter_Type)); - Iter_Pack := Scope (Root_Type (Etype (Iter_Type))); Cursor := Id; end if; diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 369f0b0..f8c12b7 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -1575,19 +1575,10 @@ package body Exp_Ch7 is Prepend_To (Decls, Counter_Typ_Decl); -- The counter and its associated type must be manually analyzed - -- since N has already been analyzed. Use the scope of the spec - -- when inserting in a package. + -- since N has already been analyzed. - if For_Package then - Push_Scope (Spec_Id); - Analyze (Counter_Typ_Decl); - Analyze (Counter_Decl); - Pop_Scope; - - else - Analyze (Counter_Typ_Decl); - Analyze (Counter_Decl); - end if; + Analyze (Counter_Typ_Decl); + Analyze (Counter_Decl); Jump_Alts := New_List; end if; @@ -1933,12 +1924,8 @@ package body Exp_Ch7 is Append_To (Decls, Fin_Body); end if; - -- Push the name of the package - - Push_Scope (Spec_Id); Analyze (Fin_Spec); Analyze (Fin_Body); - Pop_Scope; -- Non-package case @@ -2248,8 +2235,8 @@ package body Exp_Ch7 is -- Finalization of transient objects are treated separately in -- order to handle sensitive cases. These include: - -- * Aggregate expansion - -- * If, case, and expression with actions expansion + -- * Conditional expressions + -- * Expressions with actions -- * Transient scopes -- If one of those contexts has marked the transient object as @@ -2479,51 +2466,6 @@ package body Exp_Ch7 is and then Present (Library_Unit (Decl)) then Process_Package_Body (Proper_Body (Unit (Library_Unit (Decl)))); - - -- Handle a rare case caused by a controlled transient object - -- created as part of a record init proc. The variable is wrapped - -- in a block, but the block is not associated with a transient - -- scope. - - elsif Nkind (Decl) = N_Block_Statement - and then Inside_Init_Proc - then - Old_Counter_Val := Counter_Val; - - if Present (Handled_Statement_Sequence (Decl)) then - Process_Declarations - (Statements (Handled_Statement_Sequence (Decl)), - Preprocess); - end if; - - Process_Declarations (Declarations (Decl), Preprocess); - - -- Either the declaration or statement list of the block has a - -- controlled object. - - if Preprocess - and then Top_Level - and then No (Last_Top_Level_Ctrl_Construct) - and then Counter_Val > Old_Counter_Val - then - Last_Top_Level_Ctrl_Construct := Decl; - end if; - - -- Handle the case where the original context has been wrapped in - -- a block to avoid interference between exception handlers and - -- At_End handlers. Treat the block as transparent and process its - -- contents. - - elsif Nkind (Decl) = N_Block_Statement - and then Is_Finalization_Wrapper (Decl) - then - if Present (Handled_Statement_Sequence (Decl)) then - Process_Declarations - (Statements (Handled_Statement_Sequence (Decl)), - Preprocess); - end if; - - Process_Declarations (Declarations (Decl), Preprocess); end if; Prev_Non_Pragma (Decl); @@ -3464,6 +3406,10 @@ package body Exp_Ch7 is -- Step 2: Object [pre]processing if For_Package then + -- For package specs and bodies, we are invoked from the Standard + -- scope, so we need to push the specs onto the scope stack first. + + Push_Scope (Spec_Id); -- Preprocess the visible declarations now in order to obtain the -- correct number of controlled object by the time the private @@ -3541,6 +3487,12 @@ package body Exp_Ch7 is if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then Create_Finalizer; end if; + + -- Pop the scope that was pushed above for package specs and bodies + + if For_Package then + Pop_Scope; + end if; end Build_Finalizer; -------------------------- diff --git a/gcc/ada/exp_spark.adb b/gcc/ada/exp_spark.adb index c344dc1..ae0e616 100644 --- a/gcc/ada/exp_spark.adb +++ b/gcc/ada/exp_spark.adb @@ -43,6 +43,7 @@ with Restrict; use Restrict; with Rident; use Rident; with Rtsfind; use Rtsfind; with Sem; use Sem; +with Sem_Aggr; use Sem_Aggr; with Sem_Aux; use Sem_Aux; with Sem_Ch7; use Sem_Ch7; with Sem_Ch8; use Sem_Ch8; @@ -186,15 +187,47 @@ package body Exp_SPARK is (Typ : Entity_Id; Aggr : Node_Id) is + procedure Apply_Range_Checks (Choice : Node_Id); + -- Apply range checks on indexes from a deep choice + + ------------------------ + -- Apply_Range_Checks -- + ------------------------ + + procedure Apply_Range_Checks (Choice : Node_Id) is + Pref : Node_Id := Choice; + Index : N_Subexpr_Id; + begin + loop + if Nkind (Pref) = N_Indexed_Component then + Index := First (Expressions (Pref)); + Apply_Scalar_Range_Check (Index, Etype (Index)); + + elsif Is_Array_Type (Typ) + and then Is_Root_Prefix_Of_Deep_Choice (Pref) + then + Index := Pref; + Apply_Scalar_Range_Check (Index, Etype (Index)); + end if; + + exit when Is_Root_Prefix_Of_Deep_Choice (Pref); + + Pref := Prefix (Pref); + end loop; + end Apply_Range_Checks; + + -- Local variables + Assoc : Node_Id; Comp : Node_Id; - Comp_Id : Entity_Id; Comp_Type : Entity_Id; Expr : Node_Id; Index : Node_Id; Index_Typ : Entity_Id; New_Assoc : Node_Id; + -- Start of processing for Expand_SPARK_Delta_Or_Update + begin -- Apply scalar range checks on the updated components, if needed @@ -277,6 +310,9 @@ package body Exp_SPARK is if Nkind (Index) in N_Range | N_Subtype_Indication then null; + elsif Is_Deep_Choice (Index, Typ) then + Apply_Range_Checks (Index); + -- Otherwise the index denotes a single expression where -- range checks need to be applied or a subtype name -- (without range constraints) where applying checks is @@ -346,15 +382,16 @@ package body Exp_SPARK is Comp := First (Choices (Assoc)); while Present (Comp) loop - Comp_Id := Entity (Comp); - Comp_Type := Etype (Comp_Id); + if Is_Deep_Choice (Comp, Typ) then + Comp_Type := Etype (Comp); + else + Comp_Type := Etype (Entity (Comp)); + end if; New_Assoc := Make_Component_Association (Sloc => Sloc (Assoc), - Choices => - New_List - (New_Occurrence_Of (Comp_Id, Sloc (Comp))), + Choices => New_List (New_Copy_Tree (Comp)), Expression => New_Copy_Tree (Expr)); -- New association must be attached to the aggregate before we @@ -364,6 +401,10 @@ package body Exp_SPARK is Analyze_And_Resolve (Expression (New_Assoc), Comp_Type); + if Is_Deep_Choice (Comp, Typ) then + Apply_Range_Checks (First (Choices (New_Assoc))); + end if; + if Is_Scalar_Type (Comp_Type) then Apply_Scalar_Range_Check (Expression (New_Assoc), Comp_Type); diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 730889c..3952a16 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -13023,8 +13023,8 @@ package body Exp_Util is -- Finalization of transient objects are treated separately in -- order to handle sensitive cases. These include: - -- * Aggregate expansion - -- * If, case, and expression with actions expansion + -- * Conditional expressions + -- * Expressions with actions -- * Transient scopes -- If one of those contexts has marked the transient object as @@ -13233,27 +13233,6 @@ package body Exp_Util is then return True; end if; - - elsif Nkind (Decl) = N_Block_Statement - and then - - -- Handle a rare case caused by a controlled transient object - -- created as part of a record init proc. The variable is wrapped - -- in a block, but the block is not associated with a transient - -- scope. - - (Inside_Init_Proc - - -- Handle the case where the original context has been wrapped in - -- a block to avoid interference between exception handlers and - -- At_End handlers. Treat the block as transparent and process its - -- contents. - - or else Is_Finalization_Wrapper (Decl)) - then - if Requires_Cleanup_Actions (Decl, Lib_Level) then - return True; - end if; end if; Next (Decl); diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads index 95ea440..932bf3f 100644 --- a/gcc/ada/exp_util.ads +++ b/gcc/ada/exp_util.ads @@ -1070,7 +1070,7 @@ package Exp_Util is -- call and is analyzed and resolved on return. Name_Req may only be set to -- True if Exp has the form of a name, and the effect is to guarantee that -- any replacement maintains the form of name. If Renaming_Req is set to - -- True, the routine produces an object renaming reclaration capturing the + -- True, the routine produces an object renaming declaration capturing the -- expression. If Variable_Ref is set to True, a variable is considered as -- side effect (used in implementing Force_Evaluation). Note: after call to -- Remove_Side_Effects, it is safe to call New_Copy_Tree to obtain a copy diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index 9c7f684..c446b14 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -3010,6 +3010,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) TREE_TYPE (TYPE_FIELDS (gnu_type)) = gnu_inner; } } + + /* Otherwise, if an alignment is specified, use it if valid and, if + the alignment was requested with an explicit clause, state so. */ + else if (Known_Alignment (gnat_entity)) + { + SET_TYPE_ALIGN (gnu_type, + validate_alignment (Alignment (gnat_entity), + gnat_entity, + TYPE_ALIGN (gnu_type))); + if (Present (Alignment_Clause (gnat_entity))) + TYPE_USER_ALIGN (gnu_type) = 1; + } } break; diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc index c7d9162..9c418be 100644 --- a/gcc/ada/gcc-interface/trans.cc +++ b/gcc/ada/gcc-interface/trans.cc @@ -3021,7 +3021,9 @@ Loop_Statement_to_gnu (Node_Id gnat_node) } /* We use two different strategies to translate the loop, depending on - whether optimization is enabled. + whether optimization is enabled, except for the very peculiar case + of a loop running over a boolean type where we use the simpler form + in order to avoid manipulating negative values in a boolean context. If it is, we generate the canonical loop form expected by the loop optimizer and the loop vectorizer, which is the do-while form: @@ -3067,7 +3069,9 @@ Loop_Statement_to_gnu (Node_Id gnat_node) which works in all cases. */ - if (optimize && !optimize_debug) + if (optimize + && !optimize_debug + && TREE_CODE (gnu_base_type) != BOOLEAN_TYPE) { /* We can use the do-while form directly if GNU_FIRST-1 doesn't overflow. */ diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index 8b2c7f9..e7b5c77 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -1485,7 +1485,14 @@ canonicalize_pad_type (tree type) IS_COMPONENT_TYPE is true if this is being done for the component type of an array. DEFINITION is true if this type is being defined. SET_RM_SIZE is true if the RM size of the resulting type is to be set to SIZE too; in - this case, the padded type is canonicalized before being returned. */ + this case, the padded type is canonicalized before being returned. + + Note that, if TYPE is an array, then we pad it even if it has already got + an alignment of ALIGN, provided that it's larger than the alignment of the + element type. This ensures that the size of the type is a multiple of its + alignment as required by the GCC type system, and alleviates the oddity of + the larger alignment, which is used to implement alignment clauses present + on unconstrained array types. */ tree maybe_pad_type (tree type, tree size, unsigned int align, @@ -1493,7 +1500,10 @@ maybe_pad_type (tree type, tree size, unsigned int align, bool definition, bool set_rm_size) { tree orig_size = TYPE_SIZE (type); - unsigned int orig_align = TYPE_ALIGN (type); + unsigned int orig_align + = TREE_CODE (type) == ARRAY_TYPE + ? TYPE_ALIGN (TREE_TYPE (type)) + : TYPE_ALIGN (type); tree record, field; /* If TYPE is a padded type, see if it agrees with any size and alignment @@ -1515,7 +1525,10 @@ maybe_pad_type (tree type, tree size, unsigned int align, type = TREE_TYPE (TYPE_FIELDS (type)); orig_size = TYPE_SIZE (type); - orig_align = TYPE_ALIGN (type); + orig_align + = TREE_CODE (type) == ARRAY_TYPE + ? TYPE_ALIGN (TREE_TYPE (type)) + : TYPE_ALIGN (type); } /* If the size is either not being changed or is being made smaller (which diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads index a0bfb39..c565e19 100644 --- a/gcc/ada/gen_il-fields.ads +++ b/gcc/ada/gen_il-fields.ads @@ -255,7 +255,6 @@ package Gen_IL.Fields is Is_Entry_Barrier_Function, Is_Expanded_Build_In_Place_Call, Is_Expanded_Contract, - Is_Finalization_Wrapper, Is_Folded_In_Parser, Is_Generic_Contract_Pragma, Is_Homogeneous_Aggregate, diff --git a/gcc/ada/gen_il-gen-gen_nodes.adb b/gcc/ada/gen_il-gen-gen_nodes.adb index 996d8d7..087f785 100644 --- a/gcc/ada/gen_il-gen-gen_nodes.adb +++ b/gcc/ada/gen_il-gen-gen_nodes.adb @@ -1029,7 +1029,6 @@ begin -- Gen_IL.Gen.Gen_Nodes Sm (Cleanup_Actions, List_Id), Sm (Exception_Junk, Flag), Sm (Is_Abort_Block, Flag), - Sm (Is_Finalization_Wrapper, Flag), Sm (Is_Initialization_Block, Flag), Sm (Is_Task_Master, Flag))); diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 78f8849..3859709 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -19,7 +19,7 @@ @copying @quotation -GNAT User's Guide for Native Platforms , Oct 26, 2023 +GNAT User's Guide for Native Platforms , Nov 10, 2023 AdaCore @@ -1363,22 +1363,30 @@ characters (using uppercase letters) of the wide character code. For example, ESC A345 is used to represent the wide character with code @code{16#A345#}. This scheme is compatible with use of the full Wide_Character set. - -@item `Upper-Half Coding' +@end table @geindex Upper-Half Coding + +@table @asis + +@item `Upper-Half Coding' + The wide character with encoding @code{16#abcd#} where the upper bit is on (in other words, ‘a’ is in the range 8-F) is represented as two bytes, @code{16#ab#} and @code{16#cd#}. The second byte cannot be a format control character, but is not required to be in the upper half. This method can be also used for shift-JIS or EUC, where the internal coding matches the external coding. - -@item `Shift JIS Coding' +@end table @geindex Shift JIS Coding + +@table @asis + +@item `Shift JIS Coding' + A wide character is represented by a two-character sequence, @code{16#ab#} and @code{16#cd#}, with the restrictions described for upper-half encoding as @@ -1386,11 +1394,15 @@ described above. The internal character code is the corresponding JIS character according to the standard algorithm for Shift-JIS conversion. Only characters defined in the JIS code set table can be used with this encoding method. - -@item `EUC Coding' +@end table @geindex EUC Coding + +@table @asis + +@item `EUC Coding' + A wide character is represented by a two-character sequence @code{16#ab#} and @code{16#cd#}, with both characters being in the upper half. The internal @@ -29568,8 +29580,8 @@ to permit their use in free software. @printindex ge -@anchor{d1}@w{ } @anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } +@anchor{d1}@w{ } @c %**end of body @bye diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb index 5fff881..1fbbe6d 100644 --- a/gcc/ada/inline.adb +++ b/gcc/ada/inline.adb @@ -2908,7 +2908,7 @@ package body Inline is else Push_Scope (Scop); Expand_Cleanup_Actions (Decl); - End_Scope; + Pop_Scope; end if; Next_Elmt (Elmt); diff --git a/gcc/ada/libgnat/g-catiio.adb b/gcc/ada/libgnat/g-catiio.adb index 42b86cc..d80e6fc 100644 --- a/gcc/ada/libgnat/g-catiio.adb +++ b/gcc/ada/libgnat/g-catiio.adb @@ -849,7 +849,7 @@ package body GNAT.Calendar.Time_IO is begin Advance_Digits (Num_Digits => 1); - while Index <= Date'Length and then Symbol in '0' .. '9' loop + while Index <= Date'Last and then Symbol in '0' .. '9' loop Advance; end loop; @@ -1005,7 +1005,7 @@ package body GNAT.Calendar.Time_IO is -- Check for trailing characters - if Index /= Date'Length + 1 then + if Index /= Date'Last + 1 then raise Wrong_Syntax; end if; diff --git a/gcc/ada/libgnat/i-cstrea.adb b/gcc/ada/libgnat/i-cstrea.adb index f761f3f..fe668e1 100644 --- a/gcc/ada/libgnat/i-cstrea.adb +++ b/gcc/ada/libgnat/i-cstrea.adb @@ -130,4 +130,13 @@ package body Interfaces.C_Streams is return C_setvbuf (stream, buffer, mode, size); end setvbuf; + ------------ + -- unlink -- + ------------ + + function unlink (filename : chars) return int is + begin + return System.CRTL.unlink (filename); + end unlink; + end Interfaces.C_Streams; diff --git a/gcc/ada/libgnat/i-cstrea.ads b/gcc/ada/libgnat/i-cstrea.ads index 3911122..67f10cf 100644 --- a/gcc/ada/libgnat/i-cstrea.ads +++ b/gcc/ada/libgnat/i-cstrea.ads @@ -197,8 +197,7 @@ package Interfaces.C_Streams is function ungetc (c : int; stream : FILEs) return int renames System.CRTL.ungetc; - function unlink (filename : chars) return int - renames System.CRTL.unlink; + function unlink (filename : chars) return int; --------------------- -- Extra functions -- diff --git a/gcc/ada/libgnat/libada.gpr b/gcc/ada/libgnat/libada.gpr index 9453cae..2848c56 100644 --- a/gcc/ada/libgnat/libada.gpr +++ b/gcc/ada/libgnat/libada.gpr @@ -6,13 +6,14 @@ -- 1. Create a new directory (e.g. "rts-debug"), then copy the adainclude -- directory from the reference runtime that you want to rebuild. -- You can find the relevant adainclude directory by running the command --- gprls [--target=<target>] [--RTS=<runtime>] and using the adainclude +-- gprls -v [--target=<target>] [--RTS=<runtime>] and using the adainclude -- directory listed. For example: --- $ cd <reference directory> --- $ mkdir rts-debug --- $ cd rts-debug --- $ cp -a `gprls -v | grep adainclude` . --- $ cd adainclude +-- $ cd <reference directory> +-- $ mkdir rts-debug +-- $ cd rts-debug +-- $ cp -a `gprls -v \ +-- [--target=<target>] --RTS=native | grep adainclude` . +-- $ cd adainclude -- -- or under Windows: -- diff --git a/gcc/ada/libgnat/libgnat_common.gpr b/gcc/ada/libgnat/libgnat_common.gpr index 6303928..a634033 100644 --- a/gcc/ada/libgnat/libgnat_common.gpr +++ b/gcc/ada/libgnat/libgnat_common.gpr @@ -5,7 +5,7 @@ abstract project Libgnat_Common is ("-I../include", "-DIN_RTS=1", "-fexceptions", "-DSTANDALONE") & External_As_List ("EXTRALIBFLAGS", " "); - Ada_Flags := Common_Flags & ("-nostdinc", "-I../adainclude") + Ada_Flags := Common_Flags & ("-nostdinc", "-I../adainclude", "-gnatg") & Split (External ("ADAFLAGS", "-gnatpg"), " "); Library_Kind := External ("LIBRARY_KIND", "static"); diff --git a/gcc/ada/libgnat/s-crtl.ads b/gcc/ada/libgnat/s-crtl.ads index c3a3b64..56900a8 100644 --- a/gcc/ada/libgnat/s-crtl.ads +++ b/gcc/ada/libgnat/s-crtl.ads @@ -220,7 +220,8 @@ package System.CRTL is function ungetc (c : int; stream : FILEs) return int; pragma Import (C, ungetc, "ungetc"); - function unlink (filename : chars) return int; + function unlink (filename : chars; + encoding : Filename_Encoding := Unspecified) return int; pragma Import (C, unlink, "__gnat_unlink"); function open (filename : chars; oflag : int) return int; diff --git a/gcc/ada/libgnat/s-fileio.adb b/gcc/ada/libgnat/s-fileio.adb index 931b68a..f55cdc7 100644 --- a/gcc/ada/libgnat/s-fileio.adb +++ b/gcc/ada/libgnat/s-fileio.adb @@ -350,6 +350,7 @@ package body System.File_IO is declare Filename : aliased constant String := File.Name.all; Is_Temporary_File : constant Boolean := File.Is_Temporary_File; + Encoding : constant CRTL.Filename_Encoding := File.Encoding; begin Close (File_Ptr); @@ -360,7 +361,7 @@ package body System.File_IO is -- it's a temporary file, then closing it already unlinked it. if not Is_Temporary_File then - if unlink (Filename'Address) = -1 then + if System.CRTL.unlink (Filename'Address, Encoding) = -1 then raise Use_Error with OS_Lib.Errno_Message; end if; end if; diff --git a/gcc/ada/par-ch4.adb b/gcc/ada/par-ch4.adb index 52f2b02..2ff6e00 100644 --- a/gcc/ada/par-ch4.adb +++ b/gcc/ada/par-ch4.adb @@ -1393,6 +1393,8 @@ package body Ch4 is Start_Token : constant Token_Type := Token; -- Used to prevent mismatches (...] and [...) + Saved_Delta_Aggregate_Flag : constant Boolean := Inside_Delta_Aggregate; + -- Start of processing for P_Aggregate_Or_Paren_Expr begin @@ -1497,6 +1499,7 @@ package body Ch4 is Scan; -- past WITH if Token = Tok_Delta then Scan; -- past DELTA + Inside_Delta_Aggregate := True; Aggregate_Node := New_Node (N_Delta_Aggregate, Lparen_Sloc); Set_Expression (Aggregate_Node, Expr_Node); Expr_Node := Empty; @@ -1707,6 +1710,16 @@ package body Ch4 is end if; Set_Component_Associations (Aggregate_Node, Assoc_List); + + -- Inside_Delta_Aggregate is only tested if Serious_Errors = 0, so + -- it is ok if we fail to restore the saved I_D_A value in an error + -- path. In particular, it is ok that we do not restore it if + -- Error_Resync is propagated. Earlier return statements (which return + -- without restoring the saved I_D_A value) should either be in error + -- paths or in paths where I_D_A could not have been modified. + + Inside_Delta_Aggregate := Saved_Delta_Aggregate_Flag; + return Aggregate_Node; end P_Aggregate_Or_Paren_Expr; @@ -2519,6 +2532,109 @@ package body Ch4 is Expr_Form := EF_Simple; end if; + -- If all extensions are enabled and we have a deep delta aggregate + -- whose type is an array type with an element type that is a + -- record type, then we can encounter legal things like + -- with delta (Some_Index_Expression).Some_Component + -- where a parenthesized expression precedes a dot. + -- Similarly, if the element type is an array type then we can see + -- with delta (Some_Index_Expression)(Another_Index_Expression) + -- where a parenthesized expression precedes a left parenthesis. + + if Token in Tok_Dot | Tok_Left_Paren + and then Prev_Token = Tok_Right_Paren + and then Serious_Errors_Detected = 0 + and then Inside_Delta_Aggregate + and then All_Extensions_Allowed + then + if Token = Tok_Dot then + Node2 := New_Node (N_Selected_Component, Token_Ptr); + Scan; -- past dot + declare + Tail : constant Node_Id := P_Simple_Expression; + -- remaining selectors occurring after the dot + + Rover : Node_Id := Tail; + Prev : Node_Id := Empty; + begin + -- If Tail already has a prefix, then we want to prepend + -- Node1 onto that prefix and then return Tail. + -- Otherwise, Tail should simply be an identifier so + -- we want to build a Selected_Component with Tail as the + -- selector name and return that. + + Set_Prefix (Node2, Node1); + + while Nkind (Rover) + in N_Indexed_Component | N_Selected_Component loop + Prev := Rover; + Rover := Prefix (Rover); + end loop; + + case Nkind (Prev) is + when N_Selected_Component | N_Indexed_Component => + -- We've scanned a dot, so an identifier should follow + if Nkind (Prefix (Prev)) = N_Identifier then + Set_Selector_Name (Node2, Prefix (Prev)); + Set_Prefix (Prev, Node2); + return Tail; + end if; + + when N_Empty => + -- We've scanned a dot, so an identifier should follow + if Nkind (Tail) = N_Identifier then + Set_Selector_Name (Node2, Tail); + return Node2; + end if; + + when others => + null; + end case; + + -- fall through to error case + end; + else + Node2 := New_Node (N_Indexed_Component, Token_Ptr); + declare + Tail : constant Node_Id := P_Simple_Expression; + -- remaining selectors + + Rover : Node_Id := Tail; + Prev : Node_Id := Empty; + begin + -- If Tail already has a prefix, then we want to prepend + -- Node1 onto that prefix and then return Tail. + -- Otherwise, Tail should be an index expression and + -- we want to build an Indexed_Component with Tail as the + -- index value and return that. + + Set_Prefix (Node2, Node1); + + while Nkind (Rover) + in N_Indexed_Component | N_Selected_Component loop + Prev := Rover; + Rover := Prefix (Rover); + end loop; + + case Nkind (Prev) is + when N_Selected_Component | N_Indexed_Component => + Set_Expressions (Node2, New_List (Prefix (Prev))); + Set_Prefix (Prev, Node2); + return Tail; + + when N_Empty => + Set_Expressions (Node2, New_List (Tail)); + return Node2; + + when others => + null; + end case; + + -- fall through to error case + end; + end if; + end if; + -- Come here at end of simple expression, where we do a couple of -- special checks to improve error recovery. @@ -2529,8 +2645,8 @@ package body Ch4 is if Token = Tok_Dot then Error_Msg_SC ("prefix for selection is not a name"); - -- If qualified expression, comment and continue, otherwise something - -- is pretty nasty so do an Error_Resync call. + -- If qualified expression, comment and continue, otherwise + -- something is pretty nasty so do an Error_Resync call. if Ada_Version < Ada_2012 and then Nkind (Node1) = N_Qualified_Expression diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb index 5206899..4e10dd9 100644 --- a/gcc/ada/par.adb +++ b/gcc/ada/par.adb @@ -76,6 +76,15 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is -- Variable used to save values of config switches while we parse the -- new unit, to be restored on exit for proper recursive behavior. + Inside_Delta_Aggregate : Boolean := False; + -- True within a delta aggregate (but only after the "delta" token has + -- been scanned). Used to distinguish syntax errors from syntactically + -- correct "deep" delta aggregates (enabled via -gnatX0). + Save_Style_Checks : Style_Check_Options; + Save_Style_Check : Boolean; + -- Variables for storing the original state of whether style checks should + -- be active in general and which particular ones should be checked. + -------------------- -- Error Recovery -- -------------------- @@ -1596,6 +1605,11 @@ begin else Save_Config_Attrs := Save_Config_Switches; + -- Store the state of Style_Checks pragamas + + Save_Style_Check := Style_Check; + Save_Style_Check_Options (Save_Style_Checks); + -- The following loop runs more than once in syntax check mode -- where we allow multiple compilation units in the same file -- and in Multiple_Unit_Per_file mode where we skip units till @@ -1653,6 +1667,7 @@ begin -- syntax mode we are interested in all units in the file. else + declare Comp_Unit_Node : constant Node_Id := P_Compilation_Unit; @@ -1739,6 +1754,13 @@ begin Restore_Config_Switches (Save_Config_Attrs); end loop; + -- Restore the state of Style_Checks after parsing the unit to + -- avoid parsed pragmas affecting other units. + + Reset_Style_Check_Options; + Set_Style_Check_Options (Save_Style_Checks); + Style_Check := Save_Style_Check; + -- Now that we have completely parsed the source file, we can complete -- the source file table entry. diff --git a/gcc/ada/par_sco.adb b/gcc/ada/par_sco.adb index 0639ca6..84af8bf 100644 --- a/gcc/ada/par_sco.adb +++ b/gcc/ada/par_sco.adb @@ -751,6 +751,13 @@ package body Par_SCO is begin case Nkind (N) is + -- Aspect specifications have dedicated processings (see + -- Traverse_Aspects) so ignore them here, so that they are + -- processed only once. + + when N_Aspect_Specification => + return Skip; + -- Logical operators, output table entries and then process -- operands recursively to deal with nested conditions. diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index fb6bb0f..f1140d5 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -1975,7 +1975,8 @@ CND(CLOCK_THREAD_CPUTIME_ID, "Thread CPU clock") #if defined(__linux__) || defined(__FreeBSD__) \ || (defined(_AIX) && defined(_AIXVERSION_530)) \ - || defined(__DragonFly__) || defined(__QNX__) + || defined(__DragonFly__) || defined(__QNX__) \ + || defined (__vxworks) /** On these platforms use system provided monotonic clock instead of ** the default CLOCK_REALTIME. We then need to set up cond var attributes ** appropriately (see thread.c). diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb index 36db798..bc03a07 100644 --- a/gcc/ada/sem_aggr.adb +++ b/gcc/ada/sem_aggr.adb @@ -27,7 +27,6 @@ with Aspects; use Aspects; with Atree; use Atree; with Checks; use Checks; with Einfo; use Einfo; -with Einfo.Entities; use Einfo.Entities; with Einfo.Utils; use Einfo.Utils; with Elists; use Elists; with Errout; use Errout; @@ -423,6 +422,9 @@ package body Sem_Aggr is procedure Resolve_Delta_Array_Aggregate (N : Node_Id; Typ : Entity_Id); procedure Resolve_Delta_Record_Aggregate (N : Node_Id; Typ : Entity_Id); + procedure Resolve_Deep_Delta_Assoc (N : Node_Id; Typ : Entity_Id); + -- Resolve the names/expressions in a component association for + -- a deep delta aggregate. Typ is the type of the enclosing object. ------------------------ -- Array_Aggr_Subtype -- @@ -759,6 +761,28 @@ package body Sem_Aggr is end if; end Check_Expr_OK_In_Limited_Aggregate; + -------------------- + -- Is_Deep_Choice -- + -------------------- + + function Is_Deep_Choice + (Choice : Node_Id; + Aggr_Type : Type_Kind_Id) return Boolean + is + Pref : Node_Id := Choice; + begin + while not Is_Root_Prefix_Of_Deep_Choice (Pref) loop + Pref := Prefix (Pref); + end loop; + + if Is_Array_Type (Aggr_Type) then + return Paren_Count (Pref) > 0 + and then Pref /= Choice; + else + return Pref /= Choice; + end if; + end Is_Deep_Choice; + ------------------------- -- Is_Others_Aggregate -- ------------------------- @@ -771,6 +795,17 @@ package body Sem_Aggr is and then Nkind (First (Choice_List (First (Assoc)))) = N_Others_Choice; end Is_Others_Aggregate; + ----------------------------------- + -- Is_Root_Prefix_Of_Deep_Choice -- + ----------------------------------- + + function Is_Root_Prefix_Of_Deep_Choice (Pref : Node_Id) return Boolean is + begin + return Paren_Count (Pref) > 0 + or else Nkind (Pref) not in N_Indexed_Component + | N_Selected_Component; + end Is_Root_Prefix_Of_Deep_Choice; + ------------------------- -- Is_Single_Aggregate -- ------------------------- @@ -3540,7 +3575,23 @@ package body Sem_Aggr is end if; end if; else - Choice := First (Choices (Comp)); + + -- If Nkind is N_Iterated_Component_Association, + -- this corresponds to an iterator_specification + -- with a loop_parameter_specification, and we + -- have to pick up Discrete_Choices. In this case + -- there will be just one "choice", which will + -- typically be a range. + + if Nkind (Comp) = N_Iterated_Component_Association + then + Choice := First (Discrete_Choices (Comp)); + + -- Case where there's a list of choices + + else + Choice := First (Choices (Comp)); + end if; while Present (Choice) loop Get_Index_Bounds (Choice, Lo, Hi); @@ -3661,6 +3712,8 @@ package body Sem_Aggr is Choice : Node_Id; Expr : Node_Id; + Deep_Choice_Seen : Boolean := False; + begin Assoc := First (Deltas); while Present (Assoc) loop @@ -3713,31 +3766,39 @@ package body Sem_Aggr is else Choice := First (Choice_List (Assoc)); while Present (Choice) loop - Analyze (Choice); + if Is_Deep_Choice (Choice, Typ) then + pragma Assert (All_Extensions_Allowed); + Deep_Choice_Seen := True; - if Nkind (Choice) = N_Others_Choice then - Error_Msg_N - ("OTHERS not allowed in delta aggregate", Choice); + -- a deep delta aggregate + Resolve_Deep_Delta_Assoc (Assoc, Typ); + else + Analyze (Choice); - elsif Is_Entity_Name (Choice) - and then Is_Type (Entity (Choice)) - then - -- Choice covers a range of values + if Nkind (Choice) = N_Others_Choice then + Error_Msg_N + ("OTHERS not allowed in delta aggregate", Choice); - if Base_Type (Entity (Choice)) /= - Base_Type (Index_Type) + elsif Is_Entity_Name (Choice) + and then Is_Type (Entity (Choice)) then - Error_Msg_NE - ("choice does not match index type of &", - Choice, Typ); - end if; + -- Choice covers a range of values - elsif Nkind (Choice) = N_Subtype_Indication then - Resolve_Discrete_Subtype_Indication - (Choice, Base_Type (Index_Type)); + if Base_Type (Entity (Choice)) /= + Base_Type (Index_Type) + then + Error_Msg_NE + ("choice does not match index type of &", + Choice, Typ); + end if; - else - Resolve (Choice, Index_Type); + elsif Nkind (Choice) = N_Subtype_Indication then + Resolve_Discrete_Subtype_Indication + (Choice, Base_Type (Index_Type)); + + else + Resolve (Choice, Index_Type); + end if; end if; Next (Choice); @@ -3752,7 +3813,7 @@ package body Sem_Aggr is if Box_Present (Assoc) then Error_Msg_N ("'<'> in array delta aggregate is not allowed", Assoc); - else + elsif not Deep_Choice_Seen then Analyze_And_Resolve (Expression (Assoc), Component_Type (Typ)); end if; end if; @@ -3773,14 +3834,15 @@ package body Sem_Aggr is Comp_Ref : Entity_Id := Empty; -- init to avoid warning Variant : Node_Id; - procedure Check_Variant (Id : Entity_Id); + procedure Check_Variant (Id : Node_Id); -- If a given component of the delta aggregate appears in a variant -- part, verify that it is within the same variant as that of previous -- specified variant components of the delta. - function Get_Component (Nam : Node_Id) return Entity_Id; - -- Locate component with a given name and return it. If none found then - -- report error and return Empty. + function Get_Component_Type + (Selector : Node_Id; Enclosing_Type : Entity_Id) return Entity_Id; + -- Locate component with a given name and return its type. + -- If none found then report error and return Empty. function Nested_In (V1 : Node_Id; V2 : Node_Id) return Boolean; -- Determine whether variant V1 is within variant V2 @@ -3792,7 +3854,7 @@ package body Sem_Aggr is -- Check_Variant -- -------------------- - procedure Check_Variant (Id : Entity_Id) is + procedure Check_Variant (Id : Node_Id) is Comp : Entity_Id; Comp_Variant : Node_Id; @@ -3843,30 +3905,80 @@ package body Sem_Aggr is end if; end Check_Variant; - ------------------- - -- Get_Component -- - ------------------- + ------------------------ + -- Get_Component_Type -- + ------------------------ - function Get_Component (Nam : Node_Id) return Entity_Id is + function Get_Component_Type + (Selector : Node_Id; Enclosing_Type : Entity_Id) return Entity_Id + is Comp : Entity_Id; - begin - Comp := First_Entity (Typ); + case Nkind (Selector) is + when N_Selected_Component | N_Indexed_Component => + -- a deep delta aggregate choice + + declare + Prefix_Type : constant Entity_Id := + Get_Component_Type (Prefix (Selector), Enclosing_Type); + begin + if No (Prefix_Type) then + pragma Assert (Serious_Errors_Detected > 0); + return Empty; + end if; + + -- Set the type of the prefix for GNATprove + + Set_Etype (Prefix (Selector), Prefix_Type); + + if Nkind (Selector) = N_Selected_Component then + return Get_Component_Type + (Selector_Name (Selector), + Enclosing_Type => Prefix_Type); + elsif not Is_Array_Type (Prefix_Type) then + Error_Msg_NE + ("type& is not an array type", + Selector, Prefix_Type); + elsif Number_Dimensions (Prefix_Type) /= 1 then + Error_Msg_NE + ("array type& not one-dimensional", + Selector, Prefix_Type); + elsif List_Length (Expressions (Selector)) /= 1 then + Error_Msg_NE + ("wrong number of indices for array type&", + Selector, Prefix_Type); + else + Analyze_And_Resolve + (First (Expressions (Selector)), + Etype (First_Index (Prefix_Type))); + return Component_Type (Prefix_Type); + end if; + end; + + when others => + null; + end case; + + Comp := First_Entity (Enclosing_Type); while Present (Comp) loop - if Chars (Comp) = Chars (Nam) then + if Chars (Comp) = Chars (Selector) then if Ekind (Comp) = E_Discriminant then - Error_Msg_N ("delta cannot apply to discriminant", Nam); + Error_Msg_N ("delta cannot apply to discriminant", Selector); end if; - return Comp; + Set_Entity (Selector, Comp); + Set_Etype (Selector, Etype (Comp)); + + return Etype (Comp); end if; Next_Entity (Comp); end loop; - Error_Msg_NE ("type& has no component with this name", Nam, Typ); + Error_Msg_NE + ("type& has no component with this name", Selector, Enclosing_Type); return Empty; - end Get_Component; + end Get_Component_Type; --------------- -- Nested_In -- @@ -3911,10 +4023,10 @@ package body Sem_Aggr is Deltas : constant List_Id := Component_Associations (N); - Assoc : Node_Id; - Choice : Node_Id; - Comp : Entity_Id; - Comp_Type : Entity_Id := Empty; -- init to avoid warning + Assoc : Node_Id; + Choice : Node_Id; + Comp_Type : Entity_Id := Empty; -- init to avoid warning + Deep_Choice : Boolean; -- Start of processing for Resolve_Delta_Record_Aggregate @@ -3925,19 +4037,27 @@ package body Sem_Aggr is while Present (Assoc) loop Choice := First (Choice_List (Assoc)); while Present (Choice) loop - Comp := Get_Component (Choice); + Deep_Choice := Nkind (Choice) /= N_Identifier; + if Deep_Choice then + Error_Msg_GNAT_Extension + ("deep delta aggregate", Sloc (Choice)); + end if; - if Present (Comp) then - Check_Variant (Choice); + Comp_Type := Get_Component_Type + (Selector => Choice, Enclosing_Type => Typ); - Comp_Type := Etype (Comp); + -- Set the type of the choice for GNATprove - -- Decorate the component reference by setting its entity and - -- type, as otherwise backends like GNATprove would have to - -- rediscover this information by themselves. + if Deep_Choice then + Set_Etype (Choice, Comp_Type); + end if; - Set_Entity (Choice, Comp); - Set_Etype (Choice, Comp_Type); + if Present (Comp_Type) then + if not Deep_Choice then + -- ??? Not clear yet how RM 4.3.1(17.7) applies to a + -- deep delta aggregate. + Check_Variant (Choice); + end if; else Comp_Type := Any_Type; end if; @@ -3973,6 +4093,95 @@ package body Sem_Aggr is end loop; end Resolve_Delta_Record_Aggregate; + ------------------------------ + -- Resolve_Deep_Delta_Assoc -- + ------------------------------ + + procedure Resolve_Deep_Delta_Assoc (N : Node_Id; Typ : Entity_Id) is + Choice : constant Node_Id := First (Choice_List (N)); + Enclosing_Type : Entity_Id := Typ; + + procedure Resolve_Choice_Prefix + (Choice_Prefix : Node_Id; Enclosing_Type : in out Entity_Id); + -- Recursively analyze selectors. Enclosing_Type is set to + -- type of the last component. + + --------------------------- + -- Resolve_Choice_Prefix -- + --------------------------- + + procedure Resolve_Choice_Prefix + (Choice_Prefix : Node_Id; Enclosing_Type : in out Entity_Id) + is + Selector : Node_Id := Choice_Prefix; + begin + if not Is_Root_Prefix_Of_Deep_Choice (Choice_Prefix) then + Resolve_Choice_Prefix (Prefix (Choice_Prefix), Enclosing_Type); + + if Nkind (Choice_Prefix) = N_Selected_Component then + Selector := Selector_Name (Choice_Prefix); + else + pragma Assert (Nkind (Choice_Prefix) = N_Indexed_Component); + Selector := First (Expressions (Choice_Prefix)); + end if; + end if; + + if Is_Array_Type (Enclosing_Type) then + Analyze_And_Resolve (Selector, + Etype (First_Index (Enclosing_Type))); + Enclosing_Type := Component_Type (Enclosing_Type); + else + declare + Comp : Entity_Id := First_Entity (Enclosing_Type); + Found : Boolean := False; + begin + while Present (Comp) and not Found loop + if Chars (Comp) = Chars (Selector) then + if Ekind (Comp) = E_Discriminant then + Error_Msg_N ("delta cannot apply to discriminant", + Selector); + end if; + Found := True; + Set_Entity (Selector, Comp); + Set_Etype (Selector, Etype (Comp)); + Set_Analyzed (Selector); + Enclosing_Type := Etype (Comp); + else + Next_Entity (Comp); + end if; + end loop; + if not Found then + Error_Msg_NE + ("type& has no component with this name", + Selector, Enclosing_Type); + end if; + end; + end if; + + -- Set the type of the prefix for GNATprove, except for the root + -- prefix, whose type is already the expected one for a record + -- delta aggregate, or the type of the array index for an + -- array delta aggregate (the only case here really since + -- Resolve_Deep_Delta_Assoc is only called for array delta + -- aggregates). + + if Selector /= Choice_Prefix then + Set_Etype (Choice_Prefix, Enclosing_Type); + end if; + end Resolve_Choice_Prefix; + begin + declare + Unimplemented : exception; -- TEMPORARY + begin + if Present (Next (Choice)) then + raise Unimplemented; + end if; + end; + + Resolve_Choice_Prefix (Choice, Enclosing_Type); + Analyze_And_Resolve (Expression (N), Enclosing_Type); + end Resolve_Deep_Delta_Assoc; + --------------------------------- -- Resolve_Extension_Aggregate -- --------------------------------- diff --git a/gcc/ada/sem_aggr.ads b/gcc/ada/sem_aggr.ads index 46d28ae..386a161 100644 --- a/gcc/ada/sem_aggr.ads +++ b/gcc/ada/sem_aggr.ads @@ -26,7 +26,8 @@ -- This package contains the resolution code for aggregates. It is logically -- part of Sem_Res, but is split off since the aggregate code is so complex. -with Types; use Types; +with Einfo.Entities; use Einfo.Entities; +with Types; use Types; package Sem_Aggr is @@ -50,4 +51,15 @@ package Sem_Aggr is function Is_Null_Array_Aggregate_High_Bound (N : Node_Id) return Boolean; -- Returns True for the high bound of a null array aggregate. + function Is_Deep_Choice + (Choice : Node_Id; + Aggr_Type : Type_Kind_Id) return Boolean; + -- Returns whether Choice from a delta aggregate of type Aggr_Type is a + -- deep choice. + + function Is_Root_Prefix_Of_Deep_Choice (Pref : Node_Id) return Boolean; + -- Returns whether prefix Pref of a deep choice is its root prefix. Except + -- for its use in Is_Deep_Choice, this function should only be called on + -- prefixes of a deep choice as identified by Is_Deep_Choice. + end Sem_Aggr; diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb index 531bc11..000253e 100644 --- a/gcc/ada/sem_attr.adb +++ b/gcc/ada/sem_attr.adb @@ -12119,9 +12119,7 @@ package body Sem_Attr is Note_Possible_Modification (P, Sure => False); end if; - if Nkind (P) in N_Subexpr - and then Is_Overloaded (P) - then + if Nkind (P) in N_Subexpr and then Is_Overloaded (P) then Get_First_Interp (P, Index, It); Get_Next_Interp (Index, It); @@ -12135,11 +12133,7 @@ package body Sem_Attr is if not Is_Entity_Name (P) or else not Is_Overloadable (Entity (P)) then - if not Is_Task_Type (Etype (P)) - or else Nkind (P) = N_Explicit_Dereference - then - Resolve (P); - end if; + Resolve (P); end if; -- If this is the name of a derived subprogram, or that of a diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index f73e1b5..7c645c4 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -4824,10 +4824,7 @@ package body Sem_Ch12 is -- Cleanup actions are not generated within generic units -- or in the formal part of generic units. - if Inside_A_Generic - or else Is_Generic_Unit (S) - or else Ekind (S) = E_Void - then + if not Expander_Active then exit; -- For package scopes, cleanup actions are generated only @@ -16938,8 +16935,11 @@ package body Sem_Ch12 is elsif No (Full_View (Typ)) and then Typ /= Etype (Typ) then null; - -- Otherwise mark the type for flipping and use the full view when - -- available. + -- Otherwise mark the type for flipping and set the full view on N2 + -- when available, which is necessary for Check_Private_View to swap + -- back the views in case the full declaration of Typ is visible in + -- the instantiation context. Note that this will be problematic if + -- N2 is re-analyzed later, e.g. if it's a default value in a call. else Set_Has_Private_View (N); diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb index 72e7d18..de38ddf 100644 --- a/gcc/ada/sem_ch5.adb +++ b/gcc/ada/sem_ch5.adb @@ -2113,11 +2113,28 @@ package body Sem_Ch5 is Ent : Entity_Id; begin - -- If iterator type is derived, the cursor is declared in the scope - -- of the parent type. + -- If the iterator type is derived and it has an iterator interface + -- type as an ancestor, then the cursor type is declared in the scope + -- of that interface type. if Is_Derived_Type (Typ) then - Ent := First_Entity (Scope (Etype (Typ))); + declare + Iter_Iface : constant Entity_Id := + Iterator_Interface_Ancestor (Typ); + + begin + if Present (Iter_Iface) then + Ent := First_Entity (Scope (Iter_Iface)); + + -- If there's not an iterator interface, then retrieve the + -- scope associated with the parent type and start from its + -- first entity. + + else + Ent := First_Entity (Scope (Etype (Typ))); + end if; + end; + else Ent := First_Entity (Scope (Typ)); end if; diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb index 42f7c10..70a8417 100644 --- a/gcc/ada/sem_res.adb +++ b/gcc/ada/sem_res.adb @@ -4017,13 +4017,21 @@ package body Sem_Res is Analyze_And_Resolve (Actval, Base_Type (Etype (Actval))); -- Resolve entities with their own type, which may differ from - -- the type of a reference in a generic context (the view - -- swapping mechanism did not anticipate the re-analysis of - -- default values in calls). + -- the type of a reference in a generic context because of the + -- trick used in Save_Global_References.Set_Global_Type to set + -- full views forcefully, which did not anticipate the need to + -- re-analyze default values in calls. elsif Is_Entity_Name (Actval) then Analyze_And_Resolve (Actval, Etype (Entity (Actval))); + -- Ditto for calls whose name is an entity, for the same reason + + elsif Nkind (Actval) = N_Function_Call + and then Is_Entity_Name (Name (Actval)) + then + Analyze_And_Resolve (Actval, Etype (Entity (Name (Actval)))); + else Analyze_And_Resolve (Actval, Etype (Actval)); end if; diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 3d870b1..423b8d3 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -21496,6 +21496,40 @@ package body Sem_Util is pragma Assert (No (Actual)); end Iterate_Call_Parameters; + -------------------------------- + -- Iterate_Interface_Ancestor -- + -------------------------------- + + function Iterator_Interface_Ancestor (Typ : Entity_Id) return Entity_Id is + begin + if Has_Interfaces (Typ) then + declare + Iface_Elmt : Elmt_Id; + Ifaces : Elist_Id; + Root_Iface : Entity_Id; + + begin + Collect_Interfaces (Typ, Ifaces); + + Iface_Elmt := First_Elmt (Ifaces); + while Present (Iface_Elmt) loop + Root_Iface := Root_Type (Node (Iface_Elmt)); + + if Chars (Root_Iface) + in Name_Forward_Iterator | Name_Reversible_Iterator + and then In_Predefined_Unit (Root_Iface) + then + return Root_Iface; + end if; + + Next_Elmt (Iface_Elmt); + end loop; + end; + end if; + + return Empty; + end Iterator_Interface_Ancestor; + ------------------------- -- Kill_Current_Values -- ------------------------- @@ -25429,7 +25463,7 @@ package body Sem_Util is -- Check the status of the operand of a type conversion - elsif Nkind (N) = N_Type_Conversion then + elsif Nkind (N) in N_Type_Conversion | N_Unchecked_Type_Conversion then return Null_Status (Expression (N)); -- The input denotes a reference to an entity. Determine whether the diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads index caf6a66..96b4730 100644 --- a/gcc/ada/sem_util.ads +++ b/gcc/ada/sem_util.ads @@ -2480,6 +2480,13 @@ package Sem_Util is -- Calls Handle_Parameter for each pair of formal and actual parameters of -- a function, procedure, or entry call. + function Iterator_Interface_Ancestor (Typ : Entity_Id) return Entity_Id; + -- If Typ has an ancestor that is an iterator interface type declared in + -- an instance of Ada.Iterator_Interfaces, then returns that interface + -- type. Otherwise returns Empty. (It's not clear what it means if there + -- is more than one such ancestor, perhaps coming from multiple instances, + -- but this function returns the first such ancestor it finds. ???) + procedure Kill_Current_Values (Last_Assignment_Only : Boolean := False); -- This procedure is called to clear all constant indications from all -- entities in the current scope and in any parent scopes if the current diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb index 7ecb4d9..125f5c7 100644 --- a/gcc/ada/sem_warn.adb +++ b/gcc/ada/sem_warn.adb @@ -857,6 +857,10 @@ package body Sem_Warn is -- from another unit. This is true for entities in packages that are at -- the library level. + function Type_OK_For_No_Value_Assigned (T : Entity_Id) return Boolean; + -- Return True if it is OK for an object of type T to be referenced + -- without having been assigned a value in the source. + function Warnings_Off_E1 return Boolean; -- Return True if Warnings_Off is set for E1, or for its Etype (E1T), -- or for the base type of E1T. @@ -1121,6 +1125,37 @@ package body Sem_Warn is end loop; end Publicly_Referenceable; + ----------------------------------- + -- Type_OK_For_No_Value_Assigned -- + ----------------------------------- + + function Type_OK_For_No_Value_Assigned (T : Entity_Id) return Boolean is + begin + -- No information for generic types, so be conservative + + if Is_Generic_Type (T) then + return False; + end if; + + -- Even if objects of access types are implicitly initialized to null + + if Is_Access_Type (T) then + return False; + end if; + + -- The criterion is whether the type is (partially) initialized in + -- the source, in other words we disregard implicit default values. + -- But we do not require full initialization for by-reference types + -- because they are complex and it may not be possible to have it. + + if Is_By_Reference_Type (T) then + return + Is_Partially_Initialized_Type (T, Include_Implicit => False); + else + return Is_Fully_Initialized_Type (T); + end if; + end Type_OK_For_No_Value_Assigned; + --------------------- -- Warnings_Off_E1 -- --------------------- @@ -1414,10 +1449,7 @@ package body Sem_Warn is and then not Warnings_Off_E1 and then not Has_Junk_Name (E1) then - if Is_Access_Type (E1T) - or else - not Is_Partially_Initialized_Type (E1T, False) - then + if not Type_OK_For_No_Value_Assigned (E1T) then Output_Reference_Error ("?v?variable& is read but never assigned!"); end if; @@ -1456,14 +1488,12 @@ package body Sem_Warn is goto Continue; end if; - -- Check for unset reference. If type of object has - -- preelaborable initialization, warning is misleading. + -- Check for unset reference if Warn_On_No_Value_Assigned and then Present (UR) - and then not Known_To_Have_Preelab_Init (Etype (E1)) + and then not Type_OK_For_No_Value_Assigned (E1T) then - -- Don't issue warning if appearing inside Initial_Condition -- pragma or aspect, since that expression is not evaluated -- at the point where it occurs in the source. diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index 8f96260..1a63170 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -1723,12 +1723,6 @@ package Sinfo is -- Present in N_Contract nodes. Set if the contract has already undergone -- expansion activities. - -- Is_Finalization_Wrapper - -- This flag is present in N_Block_Statement nodes. It is set when the - -- block acts as a wrapper of a handled construct which has controlled - -- objects. The wrapper prevents interference between exception handlers - -- and At_End handlers. - -- Is_Generic_Contract_Pragma -- This flag is present in N_Pragma nodes. It is set when the pragma is -- a source construct, applies to a generic unit or its body, and denotes @@ -5238,7 +5232,6 @@ package Sinfo is -- Is_Task_Allocation_Block -- Exception_Junk -- Is_Abort_Block - -- Is_Finalization_Wrapper -- Is_Initialization_Block -- Is_Task_Master -- At_End_Proc (set to Empty if no clean up procedure) diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index e92c518..bab9e54 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,46 @@ +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * analyzer.h: Include "rich-location.h". + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107573 + * analyzer.h (register_known_functions): Add region_model_manager + param. + * analyzer.opt (Wanalyzer-undefined-behavior-strtok): New. + * call-summary.cc + (call_summary_replay::convert_region_from_summary_1): Handle + RK_PRIVATE. + * engine.cc (impl_run_checkers): Pass model manager to + register_known_functions. + * kf.cc (class undefined_function_behavior): New. + (class kf_strtok): New. + (register_known_functions): Add region_model_manager param. + Use it to register "strtok". + * region-model-manager.cc + (region_model_manager::get_or_create_conjured_svalue): Add "idx" + param. + * region-model-manager.h + (region_model_manager::get_or_create_conjured_svalue): Add "idx" + param. + (region_model_manager::get_root_region): New accessor. + * region-model.cc (region_model::scan_for_null_terminator): Handle + "expr" being null. + (region_model::get_representative_path_var_1): Handle RK_PRIVATE. + * region-model.h (region_model::called_from_main_p): Make public. + * region.cc (region::get_memory_space): Handle RK_PRIVATE. + (region::can_have_initial_svalue_p): Handle MEMSPACE_PRIVATE. + (private_region::dump_to_pp): New. + * region.h (MEMSPACE_PRIVATE): New. + (RK_PRIVATE): New. + (class private_region): New. + (is_a_helper <const private_region *>::test): New. + * store.cc (store::replay_call_summary_cluster): Handle + RK_PRIVATE. + * svalue.h (struct conjured_svalue::key_t): Add "idx" param to + ctor and "m_idx" field. + (class conjured_svalue::conjured_svalue): Likewise. + 2023-11-18 David Malcolm <dmalcolm@redhat.com> PR analyzer/106147 diff --git a/gcc/attribs.cc b/gcc/attribs.cc index f9fd258..c7209c2 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -2649,47 +2649,6 @@ namespace selftest typedef std::pair<const char *, const char *> excl_pair; -struct excl_hash_traits: typed_noop_remove<excl_pair> -{ - typedef excl_pair value_type; - typedef value_type compare_type; - - static hashval_t hash (const value_type &x) - { - hashval_t h1 = htab_hash_string (x.first); - hashval_t h2 = htab_hash_string (x.second); - return h1 ^ h2; - } - - static bool equal (const value_type &x, const value_type &y) - { - return !strcmp (x.first, y.first) && !strcmp (x.second, y.second); - } - - static void mark_deleted (value_type &x) - { - x = value_type (NULL, NULL); - } - - static const bool empty_zero_p = false; - - static void mark_empty (value_type &x) - { - x = value_type ("", ""); - } - - static bool is_deleted (const value_type &x) - { - return !x.first && !x.second; - } - - static bool is_empty (const value_type &x) - { - return !*x.first && !*x.second; - } -}; - - /* Self-test to verify that each attribute exclusion is symmetric, meaning that if attribute A is encoded as incompatible with attribute B then the opposite relationship is also encoded. @@ -2699,13 +2658,15 @@ struct excl_hash_traits: typed_noop_remove<excl_pair> static void test_attribute_exclusions () { + using excl_hash_traits = pair_hash<nofree_string_hash, nofree_string_hash>; + /* Iterate over the array of attribute tables first (with TI0 as the index) and over the array of attribute_spec in each table (with SI0 as the index). */ const size_t ntables = ARRAY_SIZE (attribute_tables); /* Set of pairs of mutually exclusive attributes. */ - typedef hash_set<excl_pair, false, excl_hash_traits> exclusion_set; + typedef hash_set<excl_hash_traits> exclusion_set; exclusion_set excl_set; for (size_t ti0 = 0; ti0 != ntables; ++ti0) diff --git a/gcc/builtins.cc b/gcc/builtins.cc index 5ece0d2..6af2a0b 100644 --- a/gcc/builtins.cc +++ b/gcc/builtins.cc @@ -1859,6 +1859,7 @@ type_to_class (tree type) case LANG_TYPE: return lang_type_class; case OPAQUE_TYPE: return opaque_type_class; case BITINT_TYPE: return bitint_type_class; + case VECTOR_TYPE: return vector_type_class; default: return no_type_class; } } @@ -9818,6 +9819,8 @@ fold_builtin_bit_query (location_t loc, enum built_in_function fcode, if (!direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH)) arg2 = NULL_TREE; + if (arg2 == NULL_TREE) + arg0 = save_expr (arg0); } if (fcodei == END_BUILTINS || arg2) call = build_call_expr_internal_loc (loc, ifn, integer_type_node, diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ed26f97..25ab676 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,47 @@ +2023-11-24 Lewis Hyatt <lhyatt@gmail.com> + + PR pch/112319 + * c-ppoutput.cc (cb_read_pch): Reinitialize the frontend parser + after loading a PCH. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * c.opt (-Wopenmp): Add missing tailing '.'. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * c.opt (Wopenmp): Add, enable by default. + +2023-11-23 Marek Polacek <polacek@redhat.com> + + * c-opts.cc: Include "target.h". + (c_finish_options): Maybe cpp_define _FORTIFY_SOURCE + and _GLIBCXX_ASSERTIONS. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (enum rid): Add RID_BUILTIN_STDC: New. + * c-common.cc (c_common_reswords): Add __builtin_stdc_bit_ceil, + __builtin_stdc_bit_floor, __builtin_stdc_bit_width, + __builtin_stdc_count_ones, __builtin_stdc_count_zeros, + __builtin_stdc_first_leading_one, __builtin_stdc_first_leading_zero, + __builtin_stdc_first_trailing_one, __builtin_stdc_first_trailing_zero, + __builtin_stdc_has_single_bit, __builtin_stdc_leading_ones, + __builtin_stdc_leading_zeros, __builtin_stdc_trailing_ones and + __builtin_stdc_trailing_zeros. Move __builtin_assoc_barrier + alphabetically earlier. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR c++/110348 + * c.opt (Wc++26-extensions): New option. + * c-cppbuiltin.cc (c_cpp_builtins): For C++26 predefine + __cpp_static_assert to 202306L rather than 201411L. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * c-lex.cc: Include "rich-location.h". + 2023-11-18 Sebastian Huber <sebastian.huber@embedded-brains.de> * c-cppbuiltin.cc (c_cpp_builtins): Define diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 0ea0c4f..ca7557c 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -311,6 +311,44 @@ const struct fname_var_t fname_vars[] = {NULL, 0, 0}, }; +/* Flags to restrict availability of generic features that + are known to __has_{feature,extension}. */ + +enum +{ + HF_FLAG_NONE = 0, + HF_FLAG_EXT = 1, /* Available only as an extension. */ + HF_FLAG_SANITIZE = 2, /* Availability depends on sanitizer flags. */ +}; + +/* Info for generic features which can be queried through + __has_{feature,extension}. */ + +struct hf_feature_info +{ + const char *ident; + unsigned flags; + unsigned mask; +}; + +/* Table of generic features which can be queried through + __has_{feature,extension}. */ + +static constexpr hf_feature_info has_feature_table[] = +{ + { "address_sanitizer", HF_FLAG_SANITIZE, SANITIZE_ADDRESS }, + { "thread_sanitizer", HF_FLAG_SANITIZE, SANITIZE_THREAD }, + { "leak_sanitizer", HF_FLAG_SANITIZE, SANITIZE_LEAK }, + { "hwaddress_sanitizer", HF_FLAG_SANITIZE, SANITIZE_HWADDRESS }, + { "undefined_behavior_sanitizer", HF_FLAG_SANITIZE, SANITIZE_UNDEFINED }, + { "attribute_deprecated_with_message", HF_FLAG_NONE, 0 }, + { "attribute_unavailable_with_message", HF_FLAG_NONE, 0 }, + { "enumerator_attributes", HF_FLAG_NONE, 0 }, + { "tls", HF_FLAG_NONE, 0 }, + { "gnu_asm_goto_with_outputs", HF_FLAG_EXT, 0 }, + { "gnu_asm_goto_with_outputs_full", HF_FLAG_EXT, 0 } +}; + /* Global visibility options. */ struct visibility_flags visibility_options; @@ -380,6 +418,7 @@ const struct c_common_resword c_common_reswords[] = { "__attribute__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY }, + { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY }, { "__builtin_call_with_static_chain", RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, @@ -388,9 +427,22 @@ const struct c_common_resword c_common_reswords[] = { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 }, { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, - { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, + { "__builtin_stdc_bit_ceil", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_bit_floor", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_bit_width", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_count_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_count_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_first_leading_one", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_first_leading_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_first_trailing_one", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_first_trailing_zero", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_has_single_bit", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_leading_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_leading_zeros", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_trailing_ones", RID_BUILTIN_STDC, D_CONLY }, + { "__builtin_stdc_trailing_zeros", RID_BUILTIN_STDC, D_CONLY }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, @@ -9877,4 +9929,63 @@ c_strict_flex_array_level_of (tree array_field) return strict_flex_array_level; } +/* Map from identifiers to booleans. Value is true for features, and + false for extensions. Used to implement __has_{feature,extension}. */ + +using feature_map_t = hash_map <tree, bool>; +static feature_map_t *feature_map; + +/* Register a feature for __has_{feature,extension}. FEATURE_P is true + if the feature identified by NAME is a feature (as opposed to an + extension). */ + +void +c_common_register_feature (const char *name, bool feature_p) +{ + bool dup = feature_map->put (get_identifier (name), feature_p); + gcc_checking_assert (!dup); +} + +/* Lazily initialize hash table for __has_{feature,extension}, + dispatching to the appropriate front end to register language-specific + features. */ + +static void +init_has_feature () +{ + gcc_checking_assert (!feature_map); + feature_map = new feature_map_t; + + for (unsigned i = 0; i < ARRAY_SIZE (has_feature_table); i++) + { + const hf_feature_info *info = has_feature_table + i; + + if ((info->flags & HF_FLAG_SANITIZE) && !(flag_sanitize & info->mask)) + continue; + + const bool feature_p = !(info->flags & HF_FLAG_EXT); + c_common_register_feature (info->ident, feature_p); + } + + /* Register language-specific features. */ + c_family_register_lang_features (); +} + +/* If STRICT_P is true, evaluate __has_feature (IDENT). + Otherwise, evaluate __has_extension (IDENT). */ + +bool +has_feature_p (const char *ident, bool strict_p) +{ + if (!feature_map) + init_has_feature (); + + tree name = canonicalize_attr_name (get_identifier (ident)); + bool *feat_p = feature_map->get (name); + if (!feat_p) + return false; + + return !strict_p || *feat_p; +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index b57e83d..dd4fe3a 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -106,10 +106,10 @@ enum rid /* C extensions */ RID_ASM, RID_TYPEOF, RID_TYPEOF_UNQUAL, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, - RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, - RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, - RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, - RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, + RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, + RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, + RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, + RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, RID_BUILTIN_STDC, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ @@ -1126,6 +1126,14 @@ extern bool c_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level, ATTRIBUTE_GCC_DIAG(5,0); extern int c_common_has_attribute (cpp_reader *, bool); extern int c_common_has_builtin (cpp_reader *); +extern int c_common_has_feature (cpp_reader *, bool); + +/* Implemented by each front end in *-lang.cc. */ +extern void c_family_register_lang_features (); + +/* Implemented in c-family/c-common.cc. */ +extern void c_common_register_feature (const char *, bool); +extern bool has_feature_p (const char *, bool); extern bool parse_optimize_options (tree, bool); diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 8d2f07a..56c4d63 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -1023,7 +1023,8 @@ c_cpp_builtins (cpp_reader *pfile) { /* Set feature test macros for C++17. */ cpp_define (pfile, "__cpp_unicode_characters=201411L"); - cpp_define (pfile, "__cpp_static_assert=201411L"); + if (cxx_dialect <= cxx23) + cpp_define (pfile, "__cpp_static_assert=201411L"); cpp_define (pfile, "__cpp_namespace_attributes=201411L"); cpp_define (pfile, "__cpp_enumerator_attributes=201411L"); cpp_define (pfile, "__cpp_nested_namespace_definitions=201411L"); @@ -1086,6 +1087,7 @@ c_cpp_builtins (cpp_reader *pfile) { /* Set feature test macros for C++26. */ cpp_define (pfile, "__cpp_constexpr=202306L"); + cpp_define (pfile, "__cpp_static_assert=202306L"); } if (flag_concepts) { diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc index 86ec679..cc0af7e 100644 --- a/gcc/c-family/c-lex.cc +++ b/gcc/c-family/c-lex.cc @@ -83,6 +83,7 @@ init_c_lex (void) cb->read_pch = c_common_read_pch; cb->has_attribute = c_common_has_attribute; cb->has_builtin = c_common_has_builtin; + cb->has_feature = c_common_has_feature; cb->get_source_date_epoch = cb_get_source_date_epoch; cb->get_suggestion = cb_get_suggestion; cb->remap_filename = remap_macro_filename; @@ -452,16 +453,16 @@ c_common_has_attribute (cpp_reader *pfile, bool std_syntax) return result; } -/* Callback for has_builtin. */ +/* Helper for __has_{builtin,feature,extension}. */ -int -c_common_has_builtin (cpp_reader *pfile) +static const char * +c_common_lex_availability_macro (cpp_reader *pfile, const char *builtin) { const cpp_token *token = get_token_no_padding (pfile); if (token->type != CPP_OPEN_PAREN) { cpp_error (pfile, CPP_DL_ERROR, - "missing '(' after \"__has_builtin\""); + "missing '(' after \"__has_%s\"", builtin); return 0; } @@ -481,7 +482,7 @@ c_common_has_builtin (cpp_reader *pfile) else { cpp_error (pfile, CPP_DL_ERROR, - "macro \"__has_builtin\" requires an identifier"); + "macro \"__has_%s\" requires an identifier", builtin); if (token->type == CPP_CLOSE_PAREN) return 0; } @@ -500,9 +501,38 @@ c_common_has_builtin (cpp_reader *pfile) break; } + return name; +} + +/* Callback for has_builtin. */ + +int +c_common_has_builtin (cpp_reader *pfile) +{ + const char *name = c_common_lex_availability_macro (pfile, "builtin"); + if (!name) + return 0; + return names_builtin_p (name); } +/* Callback for has_feature. STRICT_P is true for has_feature and false + for has_extension. */ + +int +c_common_has_feature (cpp_reader *pfile, bool strict_p) +{ + const char *builtin = strict_p ? "feature" : "extension"; + const char *name = c_common_lex_availability_macro (pfile, builtin); + if (!name) + return 0; + + /* If -pedantic-errors is given, __has_extension is equivalent to + __has_feature. */ + strict_p |= flag_pedantic_errors; + return has_feature_p (name, strict_p); +} + /* Read a token and return its type. Fill *VALUE with its value, if applicable. Fill *CPP_FLAGS with the token's flags, if it is diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index 10403c0..d7faff1 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "target.h" #include "c-target.h" #include "c-common.h" #include "memmodel.h" @@ -1573,6 +1574,9 @@ c_finish_options (void) cb_file_change (parse_in, cmd_map); linemap_line_start (line_table, 0, 1); + bool fortify_seen_p = false; + bool cxx_assert_seen_p = false; + /* All command line defines must have the same location. */ cpp_force_token_locations (parse_in, line_table->highest_line); for (size_t i = 0; i < deferred_count; i++) @@ -1590,6 +1594,41 @@ c_finish_options (void) else cpp_assert (parse_in, opt->arg); } + + if (UNLIKELY (flag_hardened) + && (opt->code == OPT_D || opt->code == OPT_U)) + { + if (!fortify_seen_p) + fortify_seen_p + = (!strncmp (opt->arg, "_FORTIFY_SOURCE", 15) + && (opt->arg[15] == '\0' || opt->arg[15] == '=')); + if (!cxx_assert_seen_p) + cxx_assert_seen_p + = (!strncmp (opt->arg, "_GLIBCXX_ASSERTIONS", 19) + && (opt->arg[19] == '\0' || opt->arg[19] == '=')); + } + } + + if (flag_hardened) + { + if (!fortify_seen_p && optimize > 0) + cpp_define_formatted (parse_in, "_FORTIFY_SOURCE=%u", + targetm.fortify_source_default_level ()); + else if (optimize == 0) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_FORTIFY_SOURCE%> is not enabled by %<-fhardened%> " + "because optimizations are turned off"); + else + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_FORTIFY_SOURCE%> is not enabled by %<-fhardened%> " + "because it was specified in %<-D%> or %<-U%>"); + if (!cxx_assert_seen_p) + cpp_define (parse_in, "_GLIBCXX_ASSERTIONS"); + else + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<_GLIBCXX_ASSERTIONS%> is not enabled by " + "%<-fhardened%> because it was specified in %<-D%> " + "or %<-U%>"); } cpp_stop_forcing_token_locations (parse_in); diff --git a/gcc/c-family/c-ppoutput.cc b/gcc/c-family/c-ppoutput.cc index 4aa2bef..4805085b 100644 --- a/gcc/c-family/c-ppoutput.cc +++ b/gcc/c-family/c-ppoutput.cc @@ -162,6 +162,7 @@ init_pp_output (FILE *out_stream) cb->has_attribute = c_common_has_attribute; cb->has_builtin = c_common_has_builtin; + cb->has_feature = c_common_has_feature; cb->get_source_date_epoch = cb_get_source_date_epoch; cb->remap_filename = remap_macro_filename; @@ -862,4 +863,9 @@ cb_read_pch (cpp_reader *pfile, const char *name, fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name); print.src_line++; + + /* The process of reading the PCH has destroyed the frontend parser, + so ask the frontend to reinitialize it, in case we need it to + process any #pragma directives encountered while preprocessing. */ + c_init_preprocess (); } diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index b10c605..a2c8cef 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -498,6 +498,10 @@ Wc++23-extensions C++ ObjC++ Var(warn_cxx23_extensions) Warning Init(1) Warn about C++23 constructs in code compiled with an older standard. +Wc++26-extensions +C++ ObjC++ Var(warn_cxx26_extensions) Warning Init(1) +Warn about C++26 constructs in code compiled with an older standard. + Wcast-function-type C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra) Warn about casts between incompatible function types. @@ -1171,6 +1175,10 @@ Wopenacc-parallelism C C++ Var(warn_openacc_parallelism) Warning Warn about potentially suboptimal choices related to OpenACC parallelism. +Wopenmp +C ObjC C++ ObjC++ Warning Var(warn_openmp) Init(1) +Warn about suspicious OpenMP code. + Wopenmp-simd C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall) Warn if a simd directive is overridden by the vectorizer cost model. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 64fd993..46d8c59 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,23 @@ +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * c-parser.cc (c_parser_omp_clause_num_threads, + c_parser_omp_clause_num_tasks, c_parser_omp_clause_grainsize, + c_parser_omp_clause_priority, c_parser_omp_clause_schedule, + c_parser_omp_clause_num_teams, c_parser_omp_clause_thread_limit, + c_parser_omp_clause_dist_schedule, c_parser_omp_depobj, + c_parser_omp_scan_loop_body, c_parser_omp_assumption_clauses): + Add OPT_Wopenmp to warning_at. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * c-parser.cc (c_parser_omp_depobj): Accept optionally an argument + to the destroy clause. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + * c-parser.cc (c_parser_postfix_expression): Handle RID_BUILTIN_STDC. + * c-decl.cc (names_builtin_p): Likewise. + 2023-11-14 Jakub Jelinek <jakub@redhat.com> PR c/111309 diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 64d3a94..439a312 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -11370,11 +11370,12 @@ names_builtin_p (const char *name) functions. */ switch (C_RID_CODE (id)) { + case RID_BUILTIN_ASSOC_BARRIER: case RID_BUILTIN_CONVERTVECTOR: case RID_BUILTIN_HAS_ATTRIBUTE: case RID_BUILTIN_SHUFFLE: case RID_BUILTIN_SHUFFLEVECTOR: - case RID_BUILTIN_ASSOC_BARRIER: + case RID_BUILTIN_STDC: case RID_CHOOSE_EXPR: case RID_OFFSETOF: case RID_TYPES_COMPATIBLE_P: diff --git a/gcc/c/c-lang.cc b/gcc/c/c-lang.cc index ddfd3e8..ff6633e 100644 --- a/gcc/c/c-lang.cc +++ b/gcc/c/c-lang.cc @@ -63,6 +63,15 @@ c_get_sarif_source_language (const char *) return "c"; } +/* Implement c-family hook to register language-specific features for + __has_{feature,extension}. */ + +void +c_family_register_lang_features () +{ + c_register_features (); +} + #if CHECKING_P namespace selftest { diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index c8f49aa..53eda7f 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -34,6 +34,39 @@ along with GCC; see the file COPYING3. If not see static bool c_tree_printer (pretty_printer *, text_info *, const char *, int, bool, bool, bool, bool *, const char **); +/* Info for C language features which can be queried through + __has_{feature,extension}. */ + +struct c_feature_info +{ + const char *ident; + const int *enable_flag; +}; + +static const c_feature_info c_feature_table[] = +{ + { "c_alignas", &flag_isoc11 }, + { "c_alignof", &flag_isoc11 }, + { "c_atomic", &flag_isoc11 }, + { "c_generic_selections", &flag_isoc11 }, + { "c_static_assert", &flag_isoc11 }, + { "c_thread_local", &flag_isoc11 }, + { "cxx_binary_literals", &flag_isoc23 } +}; + +/* Register features specific to the C language. */ + +void +c_register_features () +{ + for (unsigned i = 0; i < ARRAY_SIZE (c_feature_table); i++) + { + const c_feature_info *info = c_feature_table + i; + const bool feat_p = !info->enable_flag || *info->enable_flag; + c_common_register_feature (info->ident, feat_p); + } +} + bool c_missing_noreturn_ok_p (tree decl) { diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index ede451c..63aff70 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -21,6 +21,9 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_C_OBJC_COMMON #define GCC_C_OBJC_COMMON +/* Implemented in c-objc-common.cc. */ +extern void c_register_features (); + /* Lang hooks that are shared between C and ObjC are defined here. Hooks specific to C or ObjC go in c-lang.cc and objc/objc-lang.cc, respectively. */ diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 703f957..df9a079 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -11743,6 +11743,297 @@ c_parser_postfix_expression (c_parser *parser) set_c_expr_source_range (&expr, start_loc, end_loc); } break; + case RID_BUILTIN_STDC: + { + vec<c_expr_t, va_gc> *cexpr_list; + c_expr_t *arg_p; + location_t close_paren_loc; + enum c_builtin_stdc { + C_BUILTIN_STDC_BIT_CEIL, + C_BUILTIN_STDC_BIT_FLOOR, + C_BUILTIN_STDC_BIT_WIDTH, + C_BUILTIN_STDC_COUNT_ONES, + C_BUILTIN_STDC_COUNT_ZEROS, + C_BUILTIN_STDC_FIRST_LEADING_ONE, + C_BUILTIN_STDC_FIRST_LEADING_ZERO, + C_BUILTIN_STDC_FIRST_TRAILING_ONE, + C_BUILTIN_STDC_FIRST_TRAILING_ZERO, + C_BUILTIN_STDC_HAS_SINGLE_BIT, + C_BUILTIN_STDC_LEADING_ONES, + C_BUILTIN_STDC_LEADING_ZEROS, + C_BUILTIN_STDC_TRAILING_ONES, + C_BUILTIN_STDC_TRAILING_ZEROS, + C_BUILTIN_STDC_MAX + } stdc_rid = C_BUILTIN_STDC_MAX; + const char *name + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + switch (name[sizeof ("__builtin_stdc_") - 1]) + { + case 'b': + switch (name[sizeof ("__builtin_stdc_bit_") - 1]) + { + case 'c': + stdc_rid = C_BUILTIN_STDC_BIT_CEIL; + break; + case 'f': + stdc_rid = C_BUILTIN_STDC_BIT_FLOOR; + break; + default: + stdc_rid = C_BUILTIN_STDC_BIT_WIDTH; + break; + } + break; + case 'c': + if (name[sizeof ("__builtin_stdc_count_") - 1] == 'o') + stdc_rid = C_BUILTIN_STDC_COUNT_ONES; + else + stdc_rid = C_BUILTIN_STDC_COUNT_ZEROS; + break; + case 'f': + switch (name[sizeof ("__builtin_stdc_first_trailing_") - 1]) + { + case 'n': + stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ONE; + break; + case 'e': + stdc_rid = C_BUILTIN_STDC_FIRST_LEADING_ZERO; + break; + case 'o': + stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ONE; + break; + default: + stdc_rid = C_BUILTIN_STDC_FIRST_TRAILING_ZERO; + break; + } + break; + case 'h': + stdc_rid = C_BUILTIN_STDC_HAS_SINGLE_BIT; + break; + case 'l': + if (name[sizeof ("__builtin_stdc_leading_") - 1] == 'o') + stdc_rid = C_BUILTIN_STDC_LEADING_ONES; + else + stdc_rid = C_BUILTIN_STDC_LEADING_ZEROS; + break; + case 't': + if (name[sizeof ("__builtin_stdc_trailing_") - 1] == 'o') + stdc_rid = C_BUILTIN_STDC_TRAILING_ONES; + else + stdc_rid = C_BUILTIN_STDC_TRAILING_ZEROS; + break; + } + gcc_checking_assert (stdc_rid != C_BUILTIN_STDC_MAX); + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, name, + &cexpr_list, false, + &close_paren_loc)) + { + expr.set_error (); + break; + } + + if (vec_safe_length (cexpr_list) != 1) + { + error_at (loc, "wrong number of arguments to %qs", name); + expr.set_error (); + break; + } + + arg_p = &(*cexpr_list)[0]; + *arg_p = convert_lvalue_to_rvalue (loc, *arg_p, true, true); + if (!INTEGRAL_TYPE_P (TREE_TYPE (arg_p->value))) + { + error_at (loc, "%qs operand not an integral type", name); + expr.set_error (); + break; + } + tree arg = arg_p->value; + tree type = TYPE_MAIN_VARIANT (TREE_TYPE (arg)); + /* Expand: + __builtin_stdc_leading_zeros (arg) as + (unsigned int) __builtin_clzg (arg, prec) + __builtin_stdc_leading_ones (arg) as + (unsigned int) __builtin_clzg ((type) ~arg, prec) + __builtin_stdc_trailing_zeros (arg) as + (unsigned int) __builtin_ctzg (arg, prec) + __builtin_stdc_trailing_ones (arg) as + (unsigned int) __builtin_ctzg ((type) ~arg, prec) + __builtin_stdc_first_leading_zero (arg) as + __builtin_clzg ((type) ~arg, -1) + 1U + __builtin_stdc_first_leading_one (arg) as + __builtin_clzg (arg, -1) + 1U + __builtin_stdc_first_trailing_zero (arg) as + __builtin_ctzg ((type) ~arg, -1) + 1U + __builtin_stdc_first_trailing_one (arg) as + __builtin_ctzg (arg, -1) + 1U + __builtin_stdc_count_zeros (arg) as + (unsigned int) __builtin_popcountg ((type) ~arg) + __builtin_stdc_count_ones (arg) as + (unsigned int) __builtin_popcountg (arg) + __builtin_stdc_has_single_bit (arg) as + (_Bool) (__builtin_popcountg (arg) == 1) + __builtin_stdc_bit_width (arg) as + (unsigned int) (prec - __builtin_clzg (arg, prec)) + __builtin_stdc_bit_floor (arg) as + arg == 0 ? (type) 0 + : (type) 1 << (prec - 1 - __builtin_clzg (arg)) + __builtin_stdc_bit_ceil (arg) as + arg <= 1 ? (type) 1 + : (type) 2 << (prec - 1 - __builtin_clzg (arg - 1)) + without evaluating arg multiple times, type being + __typeof (arg) and prec __builtin_popcountg ((type) ~0)). */ + int prec = TYPE_PRECISION (type); + tree barg1 = arg; + switch (stdc_rid) + { + case C_BUILTIN_STDC_BIT_CEIL: + arg = save_expr (arg); + barg1 = build2_loc (loc, PLUS_EXPR, type, arg, + build_int_cst (type, -1)); + break; + case C_BUILTIN_STDC_BIT_FLOOR: + barg1 = arg = save_expr (arg); + break; + case C_BUILTIN_STDC_COUNT_ZEROS: + case C_BUILTIN_STDC_FIRST_LEADING_ZERO: + case C_BUILTIN_STDC_FIRST_TRAILING_ZERO: + case C_BUILTIN_STDC_LEADING_ONES: + case C_BUILTIN_STDC_TRAILING_ONES: + barg1 = build1_loc (loc, BIT_NOT_EXPR, type, arg); + break; + default: + break; + } + tree barg2 = NULL_TREE; + switch (stdc_rid) + { + case C_BUILTIN_STDC_BIT_WIDTH: + case C_BUILTIN_STDC_LEADING_ONES: + case C_BUILTIN_STDC_LEADING_ZEROS: + case C_BUILTIN_STDC_TRAILING_ONES: + case C_BUILTIN_STDC_TRAILING_ZEROS: + barg2 = build_int_cst (integer_type_node, prec); + break; + case C_BUILTIN_STDC_FIRST_LEADING_ONE: + case C_BUILTIN_STDC_FIRST_LEADING_ZERO: + case C_BUILTIN_STDC_FIRST_TRAILING_ONE: + case C_BUILTIN_STDC_FIRST_TRAILING_ZERO: + barg2 = integer_minus_one_node; + break; + default: + break; + } + tree fndecl = NULL_TREE; + switch (stdc_rid) + { + case C_BUILTIN_STDC_BIT_CEIL: + case C_BUILTIN_STDC_BIT_FLOOR: + case C_BUILTIN_STDC_BIT_WIDTH: + case C_BUILTIN_STDC_FIRST_LEADING_ONE: + case C_BUILTIN_STDC_FIRST_LEADING_ZERO: + case C_BUILTIN_STDC_LEADING_ONES: + case C_BUILTIN_STDC_LEADING_ZEROS: + fndecl = builtin_decl_explicit (BUILT_IN_CLZG); + break; + case C_BUILTIN_STDC_FIRST_TRAILING_ONE: + case C_BUILTIN_STDC_FIRST_TRAILING_ZERO: + case C_BUILTIN_STDC_TRAILING_ONES: + case C_BUILTIN_STDC_TRAILING_ZEROS: + fndecl = builtin_decl_explicit (BUILT_IN_CTZG); + break; + case C_BUILTIN_STDC_COUNT_ONES: + case C_BUILTIN_STDC_COUNT_ZEROS: + case C_BUILTIN_STDC_HAS_SINGLE_BIT: + fndecl = builtin_decl_explicit (BUILT_IN_POPCOUNTG); + break; + default: + gcc_unreachable (); + } + /* Construct a call to __builtin_{clz,ctz,popcount}g. */ + int nargs = barg2 != NULL_TREE ? 2 : 1; + vec<tree, va_gc> *args; + vec_alloc (args, nargs); + vec<tree, va_gc> *origtypes; + vec_alloc (origtypes, nargs); + auto_vec<location_t> arg_loc (nargs); + args->quick_push (barg1); + arg_loc.quick_push (arg_p->get_location ()); + origtypes->quick_push (arg_p->original_type); + if (nargs == 2) + { + args->quick_push (barg2); + arg_loc.quick_push (loc); + origtypes->quick_push (integer_type_node); + } + expr.value = c_build_function_call_vec (loc, arg_loc, fndecl, + args, origtypes); + set_c_expr_source_range (&expr, loc, close_paren_loc); + if (expr.value == error_mark_node) + break; + switch (stdc_rid) + { + case C_BUILTIN_STDC_BIT_CEIL: + case C_BUILTIN_STDC_BIT_FLOOR: + --prec; + /* FALLTHRU */ + case C_BUILTIN_STDC_BIT_WIDTH: + expr.value = build2_loc (loc, MINUS_EXPR, integer_type_node, + build_int_cst (integer_type_node, + prec), expr.value); + break; + case C_BUILTIN_STDC_FIRST_LEADING_ONE: + case C_BUILTIN_STDC_FIRST_LEADING_ZERO: + case C_BUILTIN_STDC_FIRST_TRAILING_ONE: + case C_BUILTIN_STDC_FIRST_TRAILING_ZERO: + expr.value = build2_loc (loc, PLUS_EXPR, integer_type_node, + expr.value, integer_one_node); + break; + case C_BUILTIN_STDC_HAS_SINGLE_BIT: + expr.value = build2_loc (loc, EQ_EXPR, boolean_type_node, + expr.value, integer_one_node); + break; + default: + break; + } + + if (stdc_rid != C_BUILTIN_STDC_BIT_CEIL + && stdc_rid != C_BUILTIN_STDC_BIT_FLOOR) + { + if (stdc_rid != C_BUILTIN_STDC_HAS_SINGLE_BIT) + expr.value = fold_convert_loc (loc, unsigned_type_node, + expr.value); + break; + } + /* For __builtin_stdc_bit_ceil (0U) or __builtin_stdc_bit_ceil (1U) + or __builtin_stdc_bit_floor (0U) avoid bogus -Wshift-count-* + warnings. The LSHIFT_EXPR is in dead code in that case. */ + if (integer_zerop (arg) + || (stdc_rid == C_BUILTIN_STDC_BIT_CEIL && integer_onep (arg))) + expr.value = build_int_cst (type, 0); + else + expr.value + = build2_loc (loc, LSHIFT_EXPR, type, + build_int_cst (type, + (stdc_rid + == C_BUILTIN_STDC_BIT_CEIL + ? 2 : 1)), expr.value); + if (stdc_rid == C_BUILTIN_STDC_BIT_CEIL) + expr.value = build3_loc (loc, COND_EXPR, type, + build2_loc (loc, LE_EXPR, + boolean_type_node, arg, + build_int_cst (type, 1)), + build_int_cst (type, 1), + expr.value); + else + expr.value = build3_loc (loc, COND_EXPR, type, + build2_loc (loc, EQ_EXPR, + boolean_type_node, arg, + build_int_cst (type, 0)), + build_int_cst (type, 0), + expr.value); + break; + } case RID_AT_SELECTOR: { gcc_assert (c_dialect_objc ()); @@ -15780,7 +16071,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) protected_set_expr_location (c, expr_loc); if (c == boolean_true_node) { - warning_at (expr_loc, 0, + warning_at (expr_loc, OPT_Wopenmp, "%<num_threads%> value must be positive"); t = integer_one_node; } @@ -15841,7 +16132,8 @@ c_parser_omp_clause_num_tasks (c_parser *parser, tree list) SET_EXPR_LOCATION (c, expr_loc); if (c == boolean_true_node) { - warning_at (expr_loc, 0, "%<num_tasks%> value must be positive"); + warning_at (expr_loc, OPT_Wopenmp, + "%<num_tasks%> value must be positive"); t = integer_one_node; } @@ -15902,7 +16194,8 @@ c_parser_omp_clause_grainsize (c_parser *parser, tree list) SET_EXPR_LOCATION (c, expr_loc); if (c == boolean_true_node) { - warning_at (expr_loc, 0, "%<grainsize%> value must be positive"); + warning_at (expr_loc, OPT_Wopenmp, + "%<grainsize%> value must be positive"); t = integer_one_node; } @@ -15950,7 +16243,8 @@ c_parser_omp_clause_priority (c_parser *parser, tree list) SET_EXPR_LOCATION (c, expr_loc); if (c == boolean_true_node) { - warning_at (expr_loc, 0, "%<priority%> value must be non-negative"); + warning_at (expr_loc, OPT_Wopenmp, + "%<priority%> value must be non-negative"); t = integer_one_node; } @@ -17092,7 +17386,7 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) protected_set_expr_location (s, loc); if (s == boolean_true_node) { - warning_at (loc, 0, + warning_at (loc, OPT_Wopenmp, "chunk size value must be positive"); t = integer_one_node; } @@ -17254,7 +17548,8 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list) protected_set_expr_location (c, upper_loc); if (c == boolean_true_node) { - warning_at (upper_loc, 0, "%<num_teams%> value must be positive"); + warning_at (upper_loc, OPT_Wopenmp, + "%<num_teams%> value must be positive"); upper = integer_one_node; } if (lower) @@ -17264,15 +17559,17 @@ c_parser_omp_clause_num_teams (c_parser *parser, tree list) protected_set_expr_location (c, lower_loc); if (c == boolean_true_node) { - warning_at (lower_loc, 0, "%<num_teams%> value must be positive"); + warning_at (lower_loc, OPT_Wopenmp, + "%<num_teams%> value must be positive"); lower = NULL_TREE; } else if (TREE_CODE (lower) == INTEGER_CST && TREE_CODE (upper) == INTEGER_CST && tree_int_cst_lt (upper, lower)) { - warning_at (lower_loc, 0, "%<num_teams%> lower bound %qE bigger " - "than upper bound %qE", lower, upper); + warning_at (lower_loc, OPT_Wopenmp, + "%<num_teams%> lower bound %qE bigger than upper " + "bound %qE", lower, upper); lower = NULL_TREE; } } @@ -17319,7 +17616,8 @@ c_parser_omp_clause_thread_limit (c_parser *parser, tree list) protected_set_expr_location (c, expr_loc); if (c == boolean_true_node) { - warning_at (expr_loc, 0, "%<thread_limit%> value must be positive"); + warning_at (expr_loc, OPT_Wopenmp, + "%<thread_limit%> value must be positive"); t = integer_one_node; } @@ -18549,7 +18847,7 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list) /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule"); */ if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE)) - warning_at (loc, 0, "too many %qs clauses", "dist_schedule"); + warning_at (loc, OPT_Wopenmp, "too many %qs clauses", "dist_schedule"); if (t == error_mark_node) return list; @@ -21314,6 +21612,9 @@ c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p) destroy update (dependence-type) + OpenMP 5.2 additionally: + destroy ( depobj ) + dependence-type: in out @@ -21372,7 +21673,26 @@ c_parser_omp_depobj (c_parser *parser) clause = error_mark_node; } else if (!strcmp ("destroy", p)) - kind = OMP_CLAUSE_DEPEND_LAST; + { + matching_parens c_parens; + kind = OMP_CLAUSE_DEPEND_LAST; + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) + && c_parens.require_open (parser)) + { + tree destobj = c_parser_expr_no_commas (parser, NULL).value; + if (!lvalue_p (destobj)) + error_at (EXPR_LOC_OR_LOC (destobj, c_loc), + "%<destroy%> expression is not lvalue expression"); + else if (depobj != error_mark_node + && !operand_equal_p (destobj, depobj, + OEP_MATCH_SIDE_EFFECTS + | OEP_LEXICOGRAPHIC)) + warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp, + "the %<destroy%> expression %qE should be the same " + "as the %<depobj%> argument %qE", destobj, depobj); + c_parens.skip_until_found_close (parser); + } + } else if (!strcmp ("update", p)) { matching_parens c_parens; @@ -21602,7 +21922,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); else { - warning_at (c_parser_peek_token (parser)->location, 0, + warning_at (c_parser_peek_token (parser)->location, OPT_Wopenmp, "%<#pragma omp scan%> with zero preceding executable " "statements"); substmt = build_empty_stmt (loc); @@ -21650,8 +21970,9 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) else { if (found_scan) - warning_at (loc, 0, "%<#pragma omp scan%> with zero succeeding " - "executable statements"); + warning_at (loc, OPT_Wopenmp, + "%<#pragma omp scan%> with zero succeeding executable " + "statements"); substmt = build_empty_stmt (loc); } substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses); @@ -25957,7 +26278,7 @@ c_parser_omp_assumption_clauses (c_parser *parser, bool is_assume) } else if (startswith (p, "ext_")) { - warning_at (cloc, 0, "unknown assumption clause %qs", p); + warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index e41e5ad..f93259a 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -2629,6 +2629,54 @@ cgraph_node::set_malloc_flag (bool malloc_p) return changed; } +/* Worker to set malloc flag. */ +static void +add_detected_attribute_1 (cgraph_node *node, const char *attr, bool *changed) +{ + if (!lookup_attribute (attr, DECL_ATTRIBUTES (node->decl))) + { + DECL_ATTRIBUTES (node->decl) = tree_cons (get_identifier (attr), + NULL_TREE, DECL_ATTRIBUTES (node->decl)); + *changed = true; + } + + ipa_ref *ref; + FOR_EACH_ALIAS (node, ref) + { + cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring); + if (alias->get_availability () > AVAIL_INTERPOSABLE) + add_detected_attribute_1 (alias, attr, changed); + } + + for (cgraph_edge *e = node->callers; e; e = e->next_caller) + if (e->caller->thunk + && (e->caller->get_availability () > AVAIL_INTERPOSABLE)) + add_detected_attribute_1 (e->caller, attr, changed); +} + +/* Add attribyte ATTR to function and its aliases. */ + +bool +cgraph_node::add_detected_attribute (const char *attr) +{ + bool changed = false; + + if (get_availability () > AVAIL_INTERPOSABLE) + add_detected_attribute_1 (this, attr, &changed); + else + { + ipa_ref *ref; + + FOR_EACH_ALIAS (this, ref) + { + cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring); + if (alias->get_availability () > AVAIL_INTERPOSABLE) + add_detected_attribute_1 (alias, attr, &changed); + } + } + return changed; +} + /* Worker to set noreturng flag. */ static void set_noreturn_flag_1 (cgraph_node *node, bool noreturn_p, bool *changed) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index cedaaac..cfdd9f6 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1190,6 +1190,10 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node bool set_pure_flag (bool pure, bool looping); + /* Add attribute ATTR to cgraph_node's decl and on aliases of the node + if any. */ + bool add_detected_attribute (const char *attr); + /* Call callback on function and aliases associated to the function. When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are skipped. */ diff --git a/gcc/common.md b/gcc/common.md index 51ecd79..91a72bd 100644 --- a/gcc/common.md +++ b/gcc/common.md @@ -17,6 +17,34 @@ ;; along with GCC; see the file COPYING3. If not see ;; <http://www.gnu.org/licenses/>. */ +;; This predicate is intended to be paired with register constraints that use +;; register filters to impose an alignment. Operands that are aligned via +;; TARGET_HARD_REGNO_MODE_OK should use normal register_operands instead. +(define_predicate "aligned_register_operand" + (match_code "reg,subreg") +{ + /* Require the offset in a non-paradoxical subreg to be naturally aligned. + For example, if we have a subreg of something that is double the size of + this operand, the offset must select the first or second half of it. */ + if (SUBREG_P (op) + && multiple_p (SUBREG_BYTE (op), GET_MODE_SIZE (GET_MODE (op)))) + op = SUBREG_REG (op); + if (!REG_P (op)) + return false; + + if (HARD_REGISTER_P (op)) + { + if (!in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op))) + return false; + + /* Reject hard registers that would need reloading, so that the reload + is visible to IRA and to pre-RA optimizers. */ + if (REGNO (op) % REG_NREGS (op) != 0) + return false; + } + return true; +}) + (define_register_constraint "r" "GENERAL_REGS" "Matches any general register.") diff --git a/gcc/common.opt b/gcc/common.opt index d21db5d..736a465 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -634,6 +634,10 @@ Wfree-nonheap-object Common Var(warn_free_nonheap_object) Init(1) Warning Warn when attempting to free a non-heap object. +Whardened +Common Var(warn_hardened) Init(1) Warning +Warn when -fhardened did not enable an option from its set. + Whsa Common Ignore Warning Does nothing. Preserved for backward compatibility. @@ -781,6 +785,10 @@ Wsuggest-attribute=malloc Common Var(warn_suggest_attribute_malloc) Warning Warn about functions which might be candidates for __attribute__((malloc)). +Wsuggest-attribute=returns_nonnull +Common Var(warn_suggest_attribute_returns_nonnull) Warning +Warn about functions which might be candidates for __attribute__((returns_nonnull)). + Wsuggest-final-types Common Var(warn_suggest_final_types) Warning Warn about C++ polymorphic types where adding final keyword would improve code quality. @@ -1819,6 +1827,10 @@ fguess-branch-probability Common Var(flag_guess_branch_prob) Optimization Enable guessing of branch probabilities. +fhardened +Common Driver Var(flag_hardened) +Enable various security-relevant flags. + fharden-compares Common Var(flag_harden_compares) Optimization Harden conditionals not used in branches, checking reversed conditions. diff --git a/gcc/common/config/i386/cpuinfo.h b/gcc/common/config/i386/cpuinfo.h index 7d25479..f90fb4d 100644 --- a/gcc/common/config/i386/cpuinfo.h +++ b/gcc/common/config/i386/cpuinfo.h @@ -715,6 +715,9 @@ get_available_features (struct __processor_model *cpu_model, int apx_usable = 0; /* Check if KL is usable. */ int has_kl = 0; + /* Record AVX10 version. */ + int avx10_set = 0; + int version = 0; if ((ecx & bit_OSXSAVE)) { /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and @@ -941,6 +944,9 @@ get_available_features (struct __processor_model *cpu_model, { if (eax & bit_AVX512BF16) set_feature (FEATURE_AVX512BF16); + /* AVX10 has the same XSTATE with AVX512. */ + if (edx & bit_AVX10) + avx10_set = 1; } if (amx_usable) { @@ -992,6 +998,33 @@ get_available_features (struct __processor_model *cpu_model, } } + /* Get Advanced Features at level 0x24 (eax = 0x24). */ + if (avx10_set && max_cpuid_level >= 0x24) + { + __cpuid (0x24, eax, ebx, ecx, edx); + version = ebx & 0xff; + if (ebx & bit_AVX10_256) + switch (version) + { + case 1: + set_feature (FEATURE_AVX10_1_256); + break; + default: + set_feature (FEATURE_AVX10_1_256); + break; + } + if (ebx & bit_AVX10_512) + switch (version) + { + case 1: + set_feature (FEATURE_AVX10_1_512); + break; + default: + set_feature (FEATURE_AVX10_1_512); + break; + } + } + /* Check cpuid level of extended features. */ __cpuid (0x80000000, ext_level, ebx, ecx, edx); diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc index 1b09499..f101e4d 100644 --- a/gcc/common/config/i386/i386-common.cc +++ b/gcc/common/config/i386/i386-common.cc @@ -126,6 +126,9 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_APX_F_SET OPTION_MASK_ISA2_APX_F #define OPTION_MASK_ISA2_EVEX512_SET OPTION_MASK_ISA2_EVEX512 #define OPTION_MASK_ISA2_USER_MSR_SET OPTION_MASK_ISA2_USER_MSR +#define OPTION_MASK_ISA2_AVX10_1_256_SET OPTION_MASK_ISA2_AVX10_1_256 +#define OPTION_MASK_ISA2_AVX10_1_512_SET \ + (OPTION_MASK_ISA2_AVX10_1_256_SET | OPTION_MASK_ISA2_AVX10_1_512) /* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same as -msse4.2. */ @@ -235,7 +238,8 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_AVX2_UNSET \ (OPTION_MASK_ISA2_AVXIFMA_UNSET | OPTION_MASK_ISA2_AVXVNNI_UNSET \ | OPTION_MASK_ISA2_AVXVNNIINT8_UNSET | OPTION_MASK_ISA2_AVXNECONVERT_UNSET \ - | OPTION_MASK_ISA2_AVXVNNIINT16_UNSET | OPTION_MASK_ISA2_AVX512F_UNSET) + | OPTION_MASK_ISA2_AVXVNNIINT16_UNSET | OPTION_MASK_ISA2_AVX512F_UNSET \ + | OPTION_MASK_ISA2_AVX10_1_256_UNSET) #define OPTION_MASK_ISA_AVX512F_UNSET \ (OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD_UNSET \ | OPTION_MASK_ISA_AVX512PF_UNSET | OPTION_MASK_ISA_AVX512ER_UNSET \ @@ -315,6 +319,9 @@ along with GCC; see the file COPYING3. If not see #define OPTION_MASK_ISA2_APX_F_UNSET OPTION_MASK_ISA2_APX_F #define OPTION_MASK_ISA2_EVEX512_UNSET OPTION_MASK_ISA2_EVEX512 #define OPTION_MASK_ISA2_USER_MSR_UNSET OPTION_MASK_ISA2_USER_MSR +#define OPTION_MASK_ISA2_AVX10_1_256_UNSET \ + (OPTION_MASK_ISA2_AVX10_1_256 | OPTION_MASK_ISA2_AVX10_1_512_UNSET) +#define OPTION_MASK_ISA2_AVX10_1_512_UNSET OPTION_MASK_ISA2_AVX10_1_512 /* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same as -mno-sse4.1. */ @@ -616,6 +623,7 @@ ix86_handle_option (struct gcc_options *opts, opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512F_UNSET; opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512F_UNSET; opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512F_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -629,6 +637,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512CD_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512CD_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -903,6 +912,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512VBMI2_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512VBMI2_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -918,6 +928,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512FP16_UNSET; opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512FP16_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -931,6 +942,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512VNNI_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512VNNI_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -946,6 +958,7 @@ ix86_handle_option (struct gcc_options *opts, opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512VPOPCNTDQ_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512VPOPCNTDQ_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -960,6 +973,7 @@ ix86_handle_option (struct gcc_options *opts, opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512BITALG_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512BITALG_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -975,6 +989,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512BF16_UNSET; opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512BF16_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1042,6 +1057,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512DQ_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512DQ_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1057,6 +1073,7 @@ ix86_handle_option (struct gcc_options *opts, opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512BW_UNSET; opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX512BW_UNSET; opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX512BW_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1070,6 +1087,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512VL_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512VL_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1083,6 +1101,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512IFMA_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512IFMA_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1096,6 +1115,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags &= ~OPTION_MASK_ISA_AVX512VBMI_UNSET; opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512VBMI_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1372,6 +1392,7 @@ ix86_handle_option (struct gcc_options *opts, { opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_EVEX512_UNSET; opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_EVEX512_UNSET; + opts->x_ix86_no_avx512_explicit = 1; } return true; @@ -1388,6 +1409,38 @@ ix86_handle_option (struct gcc_options *opts, } return true; + case OPT_mavx10_1_256: + if (value) + { + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVX10_1_256_SET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX10_1_256_SET; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2_SET; + opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_SET; + } + else + { + opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX10_1_256_UNSET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX10_1_256_UNSET; + opts->x_ix86_no_avx10_1_explicit = 1; + } + return true; + + case OPT_mavx10_1_512: + if (value) + { + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_AVX10_1_512_SET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX10_1_512_SET; + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX2_SET; + opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX2_SET; + } + else + { + opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_AVX10_1_512_UNSET; + opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA2_AVX10_1_512_UNSET; + opts->x_ix86_no_avx10_1_explicit = 1; + } + return true; + case OPT_mfma: if (value) { diff --git a/gcc/common/config/i386/i386-cpuinfo.h b/gcc/common/config/i386/i386-cpuinfo.h index a0552ef..38fa765 100644 --- a/gcc/common/config/i386/i386-cpuinfo.h +++ b/gcc/common/config/i386/i386-cpuinfo.h @@ -266,6 +266,8 @@ enum processor_features FEATURE_SM4, FEATURE_APX_F, FEATURE_USER_MSR, + FEATURE_AVX10_1_256, + FEATURE_AVX10_1_512, CPU_FEATURE_MAX }; diff --git a/gcc/common/config/i386/i386-isas.h b/gcc/common/config/i386/i386-isas.h index 6875924..a7b7c52 100644 --- a/gcc/common/config/i386/i386-isas.h +++ b/gcc/common/config/i386/i386-isas.h @@ -193,4 +193,7 @@ ISA_NAMES_TABLE_START ISA_NAMES_TABLE_ENTRY("sm4", FEATURE_SM4, P_NONE, "-msm4") ISA_NAMES_TABLE_ENTRY("apxf", FEATURE_APX_F, P_NONE, "-mapxf") ISA_NAMES_TABLE_ENTRY("usermsr", FEATURE_USER_MSR, P_NONE, "-musermsr") + ISA_NAMES_TABLE_ENTRY("avx10.1", FEATURE_AVX10_1_256, P_NONE, "-mavx10.1") + ISA_NAMES_TABLE_ENTRY("avx10.1-256", FEATURE_AVX10_1_256, P_NONE, "-mavx10.1-256") + ISA_NAMES_TABLE_ENTRY("avx10.1-512", FEATURE_AVX10_1_512, P_NONE, "-mavx10.1-512") ISA_NAMES_TABLE_END diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 5111626..ded85b4 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -169,9 +169,9 @@ struct riscv_ext_version static const struct riscv_ext_version riscv_ext_version_table[] = { /* name, ISA spec, major version, minor_version. */ - {"e", ISA_SPEC_CLASS_20191213, 1, 9}, - {"e", ISA_SPEC_CLASS_20190608, 1, 9}, - {"e", ISA_SPEC_CLASS_2P2, 1, 9}, + {"e", ISA_SPEC_CLASS_20191213, 2, 0}, + {"e", ISA_SPEC_CLASS_20190608, 2, 0}, + {"e", ISA_SPEC_CLASS_2P2, 2, 0}, {"i", ISA_SPEC_CLASS_20191213, 2, 1}, {"i", ISA_SPEC_CLASS_20190608, 2, 1}, @@ -963,7 +963,7 @@ riscv_subset_list::parse_std_ext (const char *p) add ("e", major_version, minor_version, explicit_version_p, false); - if (m_xlen > 32) + if (m_xlen > 64) { error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA", m_arch, m_xlen); diff --git a/gcc/config.gcc b/gcc/config.gcc index b88591b..3000379 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1651,7 +1651,6 @@ bpf-*-*) tm_file="elfos.h ${tm_file}" tmake_file="${tmake_file} bpf/t-bpf" use_collect2=no - extra_headers="bpf-helpers.h" use_gcc_stdint=provide extra_objs="coreout.o core-builtins.o" target_gtfiles="$target_gtfiles \$(srcdir)/config/bpf/coreout.cc \$(srcdir)/config/bpf/core-builtins.cc" @@ -2682,22 +2681,22 @@ mips*-sde-elf*) esac case ${target} in mipsisa32r6*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32" ;; mipsisa32r2*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32" ;; mipsisa32*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32 MIPS_ABI_DEFAULT=ABI_32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32 MIPS_ABI_DEFAULT=ABI_32" ;; mipsisa64r6*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6 MIPS_ABI_DEFAULT=ABI_N32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6 MIPS_ABI_DEFAULT=ABI_N32" ;; mipsisa64r2*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2 MIPS_ABI_DEFAULT=ABI_N32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2 MIPS_ABI_DEFAULT=ABI_N32" ;; mipsisa64*) - tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_ABI_DEFAULT=ABI_N32" + tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_ABI_DEFAULT=ABI_N32" ;; esac ;; @@ -4704,7 +4703,7 @@ case "${target}" in # Infer arch from --with-arch, --target, and --with-abi. case "${with_arch}" in - rv32e* | rv32i* | rv32g* | rv64i* | rv64g*) + rv32e* | rv32i* | rv32g* | rv64e* | rv64i* | rv64g*) # OK. ;; "") @@ -4713,11 +4712,12 @@ case "${target}" in ilp32e) with_arch="rv32e" ;; ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;; lp64 | lp64f | lp64d) with_arch="rv64gc" ;; + lp64e) with_arch="rv64e" ;; *) with_arch="rv${xlen}gc" ;; esac ;; *) - echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32e, rv32i, rv32g, rv64i, or rv64g." 1>&2 + echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32e, rv32i, rv32g, rv64e, rv64i, or rv64g." 1>&2 exit 1 ;; esac @@ -4731,7 +4731,7 @@ case "${target}" in # pick a default based on the ISA, preferring soft-float # unless the D extension is present. case "${with_abi}" in - ilp32 | ilp32e | ilp32f | ilp32d | lp64 | lp64f | lp64d) + ilp32 | ilp32e | ilp32f | ilp32d | lp64 | lp64e | lp64f | lp64d) ;; "") case "${with_arch}" in @@ -4739,6 +4739,7 @@ case "${target}" in rv32e*) with_abi=ilp32e ;; rv32*) with_abi=ilp32 ;; rv64*d* | rv64g*) with_abi=lp64d ;; + rv64e*) with_abi=lp64e ;; rv64*) with_abi=lp64 ;; esac ;; @@ -4754,7 +4755,7 @@ case "${target}" in ilp32,rv32* | ilp32e,rv32e* \ | ilp32f,rv32*f* | ilp32f,rv32g* \ | ilp32d,rv32*d* | ilp32d,rv32g* \ - | lp64,rv64* \ + | lp64,rv64* | lp64e,rv64e* \ | lp64f,rv64*f* | lp64f,rv64g* \ | lp64d,rv64*d* | lp64d,rv64g*) ;; diff --git a/gcc/config.host b/gcc/config.host index 5df8575..21a988e 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -230,24 +230,19 @@ case ${host} in host_exeext=.exe host_lto_plugin_soname=cyglto_plugin.dll ;; - i[34567]86-*-mingw32*) + i[34567]86-*-mingw32* | x86_64-*-mingw*) host_xm_file=i386/xm-mingw32.h - host_xmake_file="${host_xmake_file} i386/x-mingw32 i386/x-mingw32-utf8" + host_xmake_file="${host_xmake_file} ${host_xmake_mingw} i386/x-mingw32" + host_extra_gcc_objs="${host_extra_gcc_objs} ${host_extra_gcc_objs_mingw} driver-mingw32.o" + host_extra_objs="${host_extra_objs} ${host_extra_objs_mingw}" host_exeext=.exe out_host_hook_obj=host-mingw32.o - host_extra_objs="${host_extra_objs} utf8-mingw32.o" - host_extra_gcc_objs="${host_extra_gcc_objs} driver-mingw32.o utf8rc-mingw32.o" - host_lto_plugin_soname=liblto_plugin.dll - ;; - x86_64-*-mingw*) - use_long_long_for_widest_fast_int=yes - host_xm_file=i386/xm-mingw32.h - host_xmake_file="${host_xmake_file} i386/x-mingw32 i386/x-mingw32-utf8" - host_exeext=.exe - out_host_hook_obj=host-mingw32.o - host_extra_objs="${host_extra_objs} utf8-mingw32.o" - host_extra_gcc_objs="${host_extra_gcc_objs} driver-mingw32.o utf8rc-mingw32.o" host_lto_plugin_soname=liblto_plugin.dll + case ${host} in + x86_64-*-*) + use_long_long_for_widest_fast_int=yes + ;; + esac ;; aarch64*-*-darwin*) out_host_hook_obj="${out_host_hook_obj} host-aarch64-darwin.o" diff --git a/gcc/config.in b/gcc/config.in index e100c20..fa40825 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1332,6 +1332,12 @@ #endif +/* Define 0/1 if -fhardened is supported */ +#ifndef USED_FOR_TARGET +#undef HAVE_FHARDENED_SUPPORT +#endif + + /* Define to 1 if you have the `fileno_unlocked' function. */ #ifndef USED_FOR_TARGET #undef HAVE_FILENO_UNLOCKED @@ -1740,6 +1746,12 @@ #endif +/* Define 0/1 if your linker supports -z now */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_NOW_SUPPORT +#endif + + /* Define if your PowerPC64 linker only needs function descriptor syms. */ #ifndef USED_FOR_TARGET #undef HAVE_LD_NO_DOT_SYMS @@ -1783,6 +1795,12 @@ #endif +/* Define 0/1 if your linker supports -z relro */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_RELRO_SUPPORT +#endif + + /* Define if your linker links a mix of read-only and read-write sections into a read-write section. */ #ifndef USED_FOR_TARGET @@ -1868,12 +1886,6 @@ #endif -/* Define if valgrind's memcheck.h header is installed. */ -#ifndef USED_FOR_TARGET -#undef HAVE_MEMCHECK_H -#endif - - /* Define to 1 if you have the <memory.h> header file. */ #ifndef USED_FOR_TARGET #undef HAVE_MEMORY_H @@ -2136,12 +2148,6 @@ #endif -/* Define if valgrind's valgrind/memcheck.h header is installed. */ -#ifndef USED_FOR_TARGET -#undef HAVE_VALGRIND_MEMCHECK_H -#endif - - /* Define to 1 if you have the `vfork' function. */ #ifndef USED_FOR_TARGET #undef HAVE_VFORK diff --git a/gcc/config/aarch64/aarch64-arches.def b/gcc/config/aarch64/aarch64-arches.def index 7ae92aa..6b9a19c 100644 --- a/gcc/config/aarch64/aarch64-arches.def +++ b/gcc/config/aarch64/aarch64-arches.def @@ -30,19 +30,19 @@ Due to the assumptions about the positions of these fields in config.gcc, NAME should be kept as the first argument. */ -AARCH64_ARCH("armv8-a", generic, V8A, 8, (SIMD)) -AARCH64_ARCH("armv8.1-a", generic, V8_1A, 8, (V8A, LSE, CRC, RDMA)) -AARCH64_ARCH("armv8.2-a", generic, V8_2A, 8, (V8_1A)) -AARCH64_ARCH("armv8.3-a", generic, V8_3A, 8, (V8_2A, PAUTH, RCPC)) -AARCH64_ARCH("armv8.4-a", generic, V8_4A, 8, (V8_3A, F16FML, DOTPROD, FLAGM)) -AARCH64_ARCH("armv8.5-a", generic, V8_5A, 8, (V8_4A, SB, SSBS, PREDRES)) -AARCH64_ARCH("armv8.6-a", generic, V8_6A, 8, (V8_5A, I8MM, BF16)) -AARCH64_ARCH("armv8.7-a", generic, V8_7A, 8, (V8_6A, LS64)) -AARCH64_ARCH("armv8.8-a", generic, V8_8A, 8, (V8_7A, MOPS)) -AARCH64_ARCH("armv8-r", generic, V8R , 8, (V8_4A)) -AARCH64_ARCH("armv9-a", generic, V9A , 9, (V8_5A, SVE2)) -AARCH64_ARCH("armv9.1-a", generic, V9_1A, 9, (V8_6A, V9A)) -AARCH64_ARCH("armv9.2-a", generic, V9_2A, 9, (V8_7A, V9_1A)) -AARCH64_ARCH("armv9.3-a", generic, V9_3A, 9, (V8_8A, V9_2A)) +AARCH64_ARCH("armv8-a", generic_armv8_a, V8A, 8, (SIMD)) +AARCH64_ARCH("armv8.1-a", generic_armv8_a, V8_1A, 8, (V8A, LSE, CRC, RDMA)) +AARCH64_ARCH("armv8.2-a", generic_armv8_a, V8_2A, 8, (V8_1A)) +AARCH64_ARCH("armv8.3-a", generic_armv8_a, V8_3A, 8, (V8_2A, PAUTH, RCPC)) +AARCH64_ARCH("armv8.4-a", generic_armv8_a, V8_4A, 8, (V8_3A, F16FML, DOTPROD, FLAGM)) +AARCH64_ARCH("armv8.5-a", generic_armv8_a, V8_5A, 8, (V8_4A, SB, SSBS, PREDRES)) +AARCH64_ARCH("armv8.6-a", generic_armv8_a, V8_6A, 8, (V8_5A, I8MM, BF16)) +AARCH64_ARCH("armv8.7-a", generic_armv8_a, V8_7A, 8, (V8_6A, LS64)) +AARCH64_ARCH("armv8.8-a", generic_armv8_a, V8_8A, 8, (V8_7A, MOPS)) +AARCH64_ARCH("armv8-r", generic_armv8_a, V8R , 8, (V8_4A)) +AARCH64_ARCH("armv9-a", generic_armv9_a, V9A , 9, (V8_5A, SVE2)) +AARCH64_ARCH("armv9.1-a", generic_armv9_a, V9_1A, 9, (V8_6A, V9A)) +AARCH64_ARCH("armv9.2-a", generic_armv9_a, V9_2A, 9, (V8_7A, V9_1A)) +AARCH64_ARCH("armv9.3-a", generic_armv9_a, V9_3A, 9, (V8_8A, V9_2A)) #undef AARCH64_ARCH diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index eae40b2..16752b7 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -189,4 +189,9 @@ AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPER AARCH64_CORE("neoverse-v2", neoversev2, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1) AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1) +/* Generic Architecture Processors. */ +AARCH64_CORE("generic", generic, cortexa53, V8A, (), generic, 0x0, 0x0, -1) +AARCH64_CORE("generic-armv8-a", generic_armv8_a, cortexa53, V8A, (), generic_armv8_a, 0x0, 0x0, -1) +AARCH64_CORE("generic-armv9-a", generic_armv9_a, cortexa53, V9A, (), generic_armv9_a, 0x0, 0x0, -1) + #undef AARCH64_CORE diff --git a/gcc/config/aarch64/aarch64-opts.h b/gcc/config/aarch64/aarch64-opts.h index 831e28a..01151e9 100644 --- a/gcc/config/aarch64/aarch64-opts.h +++ b/gcc/config/aarch64/aarch64-opts.h @@ -32,8 +32,6 @@ enum aarch64_processor #define AARCH64_CORE(NAME, INTERNAL_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \ INTERNAL_IDENT, #include "aarch64-cores.def" - /* Used to indicate that no processor has been specified. */ - generic, /* Used to mark the end of the processor table. */ aarch64_none }; diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index c6f2d58..ad79a81 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -269,7 +269,7 @@ "TARGET_SIMD" {@ [ cons: =0 , 1 ; attrs: type ] [ Umn , w ; neon_stp ] stp\t%<Vetype>1, %<Vetype>1, %y0 - [ Umn , r ; store_<ldpstp_vel_sz> ] stp\t%<vw>1, %<vw>1, %y0 + [ Umn , r ; store_<ldpstp_vel_sz> ] stp\t%<vwcore>1, %<vwcore>1, %y0 } ) @@ -2029,26 +2029,60 @@ [(set_attr "type" "neon_shift_imm_long")] ) -(define_expand "vec_unpack<su>_hi_<mode>" +(define_expand "vec_unpacku_hi_<mode>" [(match_operand:<VWIDE> 0 "register_operand") - (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))] + (match_operand:VQW 1 "register_operand")] + "TARGET_SIMD" + { + rtx res = gen_reg_rtx (<MODE>mode); + rtx tmp = aarch64_gen_shareable_zero (<MODE>mode); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_aarch64_zip2<mode> (res, tmp, operands[1])); + else + emit_insn (gen_aarch64_zip2<mode> (res, operands[1], tmp)); + emit_move_insn (operands[0], + simplify_gen_subreg (<VWIDE>mode, res, <MODE>mode, 0)); + DONE; + } +) + +(define_expand "vec_unpacks_hi_<mode>" + [(match_operand:<VWIDE> 0 "register_operand") + (match_operand:VQW 1 "register_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true); - emit_insn (gen_aarch64_simd_vec_unpack<su>_hi_<mode> (operands[0], - operands[1], p)); + emit_insn (gen_aarch64_simd_vec_unpacks_hi_<mode> (operands[0], + operands[1], p)); DONE; } ) -(define_expand "vec_unpack<su>_lo_<mode>" +(define_expand "vec_unpacku_lo_<mode>" [(match_operand:<VWIDE> 0 "register_operand") - (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))] + (match_operand:VQW 1 "register_operand")] + "TARGET_SIMD" + { + rtx res = gen_reg_rtx (<MODE>mode); + rtx tmp = aarch64_gen_shareable_zero (<MODE>mode); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_aarch64_zip1<mode> (res, tmp, operands[1])); + else + emit_insn (gen_aarch64_zip1<mode> (res, operands[1], tmp)); + emit_move_insn (operands[0], + simplify_gen_subreg (<VWIDE>mode, res, <MODE>mode, 0)); + DONE; + } +) + +(define_expand "vec_unpacks_lo_<mode>" + [(match_operand:<VWIDE> 0 "register_operand") + (match_operand:VQW 1 "register_operand")] "TARGET_SIMD" { rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false); - emit_insn (gen_aarch64_simd_vec_unpack<su>_lo_<mode> (operands[0], - operands[1], p)); + emit_insn (gen_aarch64_simd_vec_unpacks_lo_<mode> (operands[0], + operands[1], p)); DONE; } ) @@ -4776,6 +4810,62 @@ [(set_attr "type" "neon_sub_widen")] ) +(define_insn "aarch64_usubw<mode>_lo_zip" + [(set (match_operand:<VWIDE> 0 "register_operand" "=w") + (minus:<VWIDE> + (match_operand:<VWIDE> 1 "register_operand" "w") + (subreg:<VWIDE> + (unspec:<MODE> [ + (match_operand:VQW 2 "register_operand" "w") + (match_operand:VQW 3 "aarch64_simd_imm_zero") + ] UNSPEC_ZIP1) 0)))] + "TARGET_SIMD" + "usubw\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vhalftype>" + [(set_attr "type" "neon_sub_widen")] +) + +(define_insn "aarch64_uaddw<mode>_lo_zip" + [(set (match_operand:<VWIDE> 0 "register_operand" "=w") + (plus:<VWIDE> + (subreg:<VWIDE> + (unspec:<MODE> [ + (match_operand:VQW 2 "register_operand" "w") + (match_operand:VQW 3 "aarch64_simd_imm_zero") + ] UNSPEC_ZIP1) 0) + (match_operand:<VWIDE> 1 "register_operand" "w")))] + "TARGET_SIMD" + "uaddw\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vhalftype>" + [(set_attr "type" "neon_add_widen")] +) + +(define_insn "aarch64_usubw<mode>_hi_zip" + [(set (match_operand:<VWIDE> 0 "register_operand" "=w") + (minus:<VWIDE> + (match_operand:<VWIDE> 1 "register_operand" "w") + (subreg:<VWIDE> + (unspec:<MODE> [ + (match_operand:VQW 2 "register_operand" "w") + (match_operand:VQW 3 "aarch64_simd_imm_zero") + ] UNSPEC_ZIP2) 0)))] + "TARGET_SIMD" + "usubw2\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>" + [(set_attr "type" "neon_sub_widen")] +) + +(define_insn "aarch64_uaddw<mode>_hi_zip" + [(set (match_operand:<VWIDE> 0 "register_operand" "=w") + (plus:<VWIDE> + (subreg:<VWIDE> + (unspec:<MODE> [ + (match_operand:VQW 2 "register_operand" "w") + (match_operand:VQW 3 "aarch64_simd_imm_zero") + ] UNSPEC_ZIP2) 0) + (match_operand:<VWIDE> 1 "register_operand" "w")))] + "TARGET_SIMD" + "uaddw2\\t%0.<Vwtype>, %1.<Vwtype>, %2.<Vtype>" + [(set_attr "type" "neon_add_widen")] +) + (define_insn "aarch64_<ANY_EXTEND:su>addw<mode>" [(set (match_operand:<VWIDE> 0 "register_operand" "=w") (plus:<VWIDE> diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md index c969277..61bb852 100644 --- a/gcc/config/aarch64/aarch64-tune.md +++ b/gcc/config/aarch64/aarch64-tune.md @@ -1,5 +1,5 @@ ;; -*- buffer-read-only: t -*- ;; Generated automatically by gentune.sh from aarch64-cores.def (define_attr "tune" - "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexx2,cortexx3,cortexx4,neoversen2,neoversev2,demeter" + "cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexx2,cortexx3,cortexx4,neoversen2,neoversev2,demeter,generic,generic_armv8_a,generic_armv9_a" (const (symbol_ref "((enum attr_tune) aarch64_tune)"))) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 800a8b0..f6f6f94 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -354,2405 +354,32 @@ static const struct aarch64_flag_desc aarch64_tuning_flags[] = }; /* Tuning parameters. */ - -static const struct cpu_addrcost_table generic_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 0, /* register_sextend */ - 0, /* register_zextend */ - 0 /* imm_offset */ -}; - -static const struct cpu_addrcost_table exynosm1_addrcost_table = -{ - { - 0, /* hi */ - 0, /* si */ - 0, /* di */ - 2, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 1, /* register_offset */ - 1, /* register_sextend */ - 2, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table xgene1_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 1, /* pre_modify */ - 1, /* post_modify */ - 1, /* post_modify_ld3_st3 */ - 1, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 1, /* register_sextend */ - 1, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table thunderx2t99_addrcost_table = -{ - { - 1, /* hi */ - 1, /* si */ - 1, /* di */ - 2, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 2, /* register_offset */ - 3, /* register_sextend */ - 3, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table thunderx3t110_addrcost_table = -{ - { - 1, /* hi */ - 1, /* si */ - 1, /* di */ - 2, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 2, /* register_offset */ - 3, /* register_sextend */ - 3, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table tsv110_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 1, /* register_sextend */ - 1, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table qdf24xx_addrcost_table = -{ - { - 1, /* hi */ - 1, /* si */ - 1, /* di */ - 2, /* ti */ - }, - 1, /* pre_modify */ - 1, /* post_modify */ - 1, /* post_modify_ld3_st3 */ - 1, /* post_modify_ld4_st4 */ - 3, /* register_offset */ - 3, /* register_sextend */ - 3, /* register_zextend */ - 2, /* imm_offset */ -}; - -static const struct cpu_addrcost_table a64fx_addrcost_table = -{ - { - 1, /* hi */ - 1, /* si */ - 1, /* di */ - 2, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 0, /* post_modify_ld3_st3 */ - 0, /* post_modify_ld4_st4 */ - 2, /* register_offset */ - 3, /* register_sextend */ - 3, /* register_zextend */ - 0, /* imm_offset */ -}; - -static const struct cpu_addrcost_table neoversev1_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 3, /* post_modify_ld3_st3 */ - 3, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 0, /* register_sextend */ - 0, /* register_zextend */ - 0 /* imm_offset */ -}; - -static const struct cpu_addrcost_table neoversen2_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 2, /* post_modify_ld3_st3 */ - 2, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 0, /* register_sextend */ - 0, /* register_zextend */ - 0 /* imm_offset */ -}; - -static const struct cpu_addrcost_table neoversev2_addrcost_table = -{ - { - 1, /* hi */ - 0, /* si */ - 0, /* di */ - 1, /* ti */ - }, - 0, /* pre_modify */ - 0, /* post_modify */ - 2, /* post_modify_ld3_st3 */ - 2, /* post_modify_ld4_st4 */ - 0, /* register_offset */ - 0, /* register_sextend */ - 0, /* register_zextend */ - 0 /* imm_offset */ -}; - -static const struct cpu_regmove_cost generic_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 5, /* GP2FP */ - 5, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost cortexa57_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 5, /* GP2FP */ - 5, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost cortexa53_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 5, /* GP2FP */ - 5, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost exynosm1_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost (actual, 4 and 9). */ - 9, /* GP2FP */ - 9, /* FP2GP */ - 1 /* FP2FP */ -}; - -static const struct cpu_regmove_cost thunderx_regmove_cost = -{ - 2, /* GP2GP */ - 2, /* GP2FP */ - 6, /* FP2GP */ - 4 /* FP2FP */ -}; - -static const struct cpu_regmove_cost xgene1_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 8, /* GP2FP */ - 8, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost qdf24xx_regmove_cost = -{ - 2, /* GP2GP */ - /* Avoid the use of int<->fp moves for spilling. */ - 6, /* GP2FP */ - 6, /* FP2GP */ - 4 /* FP2FP */ -}; - -static const struct cpu_regmove_cost thunderx2t99_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of int<->fp moves for spilling. */ - 5, /* GP2FP */ - 6, /* FP2GP */ - 3, /* FP2FP */ -}; - -static const struct cpu_regmove_cost thunderx3t110_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of int<->fp moves for spilling. */ - 4, /* GP2FP */ - 5, /* FP2GP */ - 4 /* FP2FP */ -}; - -static const struct cpu_regmove_cost tsv110_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 2, /* GP2FP */ - 3, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost a64fx_regmove_cost = -{ - 1, /* GP2GP */ - /* Avoid the use of slow int<->fp moves for spilling by setting - their cost higher than memmov_cost. */ - 5, /* GP2FP */ - 7, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost neoversen2_regmove_cost = -{ - 1, /* GP2GP */ - /* Spilling to int<->fp instead of memory is recommended so set - realistic costs compared to memmov_cost. */ - 3, /* GP2FP */ - 2, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost neoversev1_regmove_cost = -{ - 1, /* GP2GP */ - /* Spilling to int<->fp instead of memory is recommended so set - realistic costs compared to memmov_cost. */ - 3, /* GP2FP */ - 2, /* FP2GP */ - 2 /* FP2FP */ -}; - -static const struct cpu_regmove_cost neoversev2_regmove_cost = -{ - 1, /* GP2GP */ - /* Spilling to int<->fp instead of memory is recommended so set - realistic costs compared to memmov_cost. */ - 3, /* GP2FP */ - 2, /* FP2GP */ - 2 /* FP2FP */ -}; - -/* Generic costs for Advanced SIMD vector operations. */ -static const advsimd_vec_cost generic_advsimd_vector_cost = -{ - 1, /* int_stmt_cost */ - 1, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 2, /* reduc_i8_cost */ - 2, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 2, /* reduc_f16_cost */ - 2, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - 2, /* vec_to_scalar_cost */ - 1, /* scalar_to_vec_cost */ - 1, /* align_load_cost */ - 1, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* Generic costs for SVE vector operations. */ -static const sve_vec_cost generic_sve_vector_cost = -{ - { - 1, /* int_stmt_cost */ - 1, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 2, /* reduc_i8_cost */ - 2, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 2, /* reduc_f16_cost */ - 2, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - 2, /* vec_to_scalar_cost */ - 1, /* scalar_to_vec_cost */ - 1, /* align_load_cost */ - 1, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 2, /* clast_cost */ - 2, /* fadda_f16_cost */ - 2, /* fadda_f32_cost */ - 2, /* fadda_f64_cost */ - 4, /* gather_load_x32_cost */ - 2, /* gather_load_x64_cost */ - 1 /* scatter_store_elt_cost */ -}; - -/* Generic costs for vector insn classes. */ -static const struct cpu_vector_cost generic_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 1, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 3, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &generic_advsimd_vector_cost, /* advsimd */ - &generic_sve_vector_cost, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost a64fx_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 5, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 13, /* reduc_i8_cost */ - 13, /* reduc_i16_cost */ - 13, /* reduc_i32_cost */ - 13, /* reduc_i64_cost */ - 13, /* reduc_f16_cost */ - 13, /* reduc_f32_cost */ - 13, /* reduc_f64_cost */ - 13, /* store_elt_extra_cost */ - 13, /* vec_to_scalar_cost */ - 4, /* scalar_to_vec_cost */ - 6, /* align_load_cost */ - 6, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const sve_vec_cost a64fx_sve_vector_cost = -{ - { - 2, /* int_stmt_cost */ - 5, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 13, /* reduc_i8_cost */ - 13, /* reduc_i16_cost */ - 13, /* reduc_i32_cost */ - 13, /* reduc_i64_cost */ - 13, /* reduc_f16_cost */ - 13, /* reduc_f32_cost */ - 13, /* reduc_f64_cost */ - 13, /* store_elt_extra_cost */ - 13, /* vec_to_scalar_cost */ - 4, /* scalar_to_vec_cost */ - 6, /* align_load_cost */ - 6, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 13, /* clast_cost */ - 13, /* fadda_f16_cost */ - 13, /* fadda_f32_cost */ - 13, /* fadda_f64_cost */ - 64, /* gather_load_x32_cost */ - 32, /* gather_load_x64_cost */ - 1 /* scatter_store_elt_cost */ -}; - -static const struct cpu_vector_cost a64fx_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 5, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 3, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &a64fx_advsimd_vector_cost, /* advsimd */ - &a64fx_sve_vector_cost, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost qdf24xx_advsimd_vector_cost = -{ - 1, /* int_stmt_cost */ - 3, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 1, /* reduc_i8_cost */ - 1, /* reduc_i16_cost */ - 1, /* reduc_i32_cost */ - 1, /* reduc_i64_cost */ - 1, /* reduc_f16_cost */ - 1, /* reduc_f32_cost */ - 1, /* reduc_f64_cost */ - 1, /* store_elt_extra_cost */ - 1, /* vec_to_scalar_cost */ - 1, /* scalar_to_vec_cost */ - 1, /* align_load_cost */ - 1, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* QDF24XX costs for vector insn classes. */ -static const struct cpu_vector_cost qdf24xx_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 1, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 3, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &qdf24xx_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - - -static const advsimd_vec_cost thunderx_advsimd_vector_cost = -{ - 4, /* int_stmt_cost */ - 1, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 4, /* permute_cost */ - 2, /* reduc_i8_cost */ - 2, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 2, /* reduc_f16_cost */ - 2, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - 2, /* vec_to_scalar_cost */ - 2, /* scalar_to_vec_cost */ - 3, /* align_load_cost */ - 5, /* unalign_load_cost */ - 5, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* ThunderX costs for vector insn classes. */ -static const struct cpu_vector_cost thunderx_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 3, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 3, /* cond_taken_branch_cost */ - 3, /* cond_not_taken_branch_cost */ - &thunderx_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost tsv110_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 3, /* reduc_i8_cost */ - 3, /* reduc_i16_cost */ - 3, /* reduc_i32_cost */ - 3, /* reduc_i64_cost */ - 3, /* reduc_f16_cost */ - 3, /* reduc_f32_cost */ - 3, /* reduc_f64_cost */ - 3, /* store_elt_extra_cost */ - 3, /* vec_to_scalar_cost */ - 2, /* scalar_to_vec_cost */ - 5, /* align_load_cost */ - 5, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const struct cpu_vector_cost tsv110_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 5, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &tsv110_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost cortexa57_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 8, /* reduc_i8_cost */ - 8, /* reduc_i16_cost */ - 8, /* reduc_i32_cost */ - 8, /* reduc_i64_cost */ - 8, /* reduc_f16_cost */ - 8, /* reduc_f32_cost */ - 8, /* reduc_f64_cost */ - 8, /* store_elt_extra_cost */ - 8, /* vec_to_scalar_cost */ - 8, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* Cortex-A57 costs for vector insn classes. */ -static const struct cpu_vector_cost cortexa57_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &cortexa57_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost exynosm1_advsimd_vector_cost = -{ - 3, /* int_stmt_cost */ - 3, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 3, /* reduc_i8_cost */ - 3, /* reduc_i16_cost */ - 3, /* reduc_i32_cost */ - 3, /* reduc_i64_cost */ - 3, /* reduc_f16_cost */ - 3, /* reduc_f32_cost */ - 3, /* reduc_f64_cost */ - 3, /* store_elt_extra_cost */ - 3, /* vec_to_scalar_cost */ - 3, /* scalar_to_vec_cost */ - 5, /* align_load_cost */ - 5, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const struct cpu_vector_cost exynosm1_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 5, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &exynosm1_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost xgene1_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 4, /* reduc_i8_cost */ - 4, /* reduc_i16_cost */ - 4, /* reduc_i32_cost */ - 4, /* reduc_i64_cost */ - 4, /* reduc_f16_cost */ - 4, /* reduc_f32_cost */ - 4, /* reduc_f64_cost */ - 4, /* store_elt_extra_cost */ - 4, /* vec_to_scalar_cost */ - 4, /* scalar_to_vec_cost */ - 10, /* align_load_cost */ - 10, /* unalign_load_cost */ - 2, /* unalign_store_cost */ - 2 /* store_cost */ -}; - -/* Generic costs for vector insn classes. */ -static const struct cpu_vector_cost xgene1_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 1, /* scalar_fp_stmt_cost */ - 5, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 2, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &xgene1_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost thunderx2t99_advsimd_vector_cost = -{ - 4, /* int_stmt_cost */ - 5, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 10, /* permute_cost */ - 6, /* reduc_i8_cost */ - 6, /* reduc_i16_cost */ - 6, /* reduc_i32_cost */ - 6, /* reduc_i64_cost */ - 6, /* reduc_f16_cost */ - 6, /* reduc_f32_cost */ - 6, /* reduc_f64_cost */ - 6, /* store_elt_extra_cost */ - 6, /* vec_to_scalar_cost */ - 5, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* Costs for vector insn classes for Vulcan. */ -static const struct cpu_vector_cost thunderx2t99_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 6, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 2, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &thunderx2t99_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost thunderx3t110_advsimd_vector_cost = -{ - 5, /* int_stmt_cost */ - 5, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 10, /* permute_cost */ - 5, /* reduc_i8_cost */ - 5, /* reduc_i16_cost */ - 5, /* reduc_i32_cost */ - 5, /* reduc_i64_cost */ - 5, /* reduc_f16_cost */ - 5, /* reduc_f32_cost */ - 5, /* reduc_f64_cost */ - 5, /* store_elt_extra_cost */ - 5, /* vec_to_scalar_cost */ - 5, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - 4, /* unalign_store_cost */ - 4 /* store_cost */ -}; - -static const struct cpu_vector_cost thunderx3t110_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 5, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 2, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &thunderx3t110_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -static const advsimd_vec_cost ampere1_advsimd_vector_cost = -{ - 1, /* int_stmt_cost */ - 3, /* fp_stmt_cost */ - 0, /* ld2_st2_permute_cost */ - 0, /* ld3_st3_permute_cost */ - 0, /* ld4_st4_permute_cost */ - 2, /* permute_cost */ - 12, /* reduc_i8_cost */ - 9, /* reduc_i16_cost */ - 6, /* reduc_i32_cost */ - 5, /* reduc_i64_cost */ - 9, /* reduc_f16_cost */ - 6, /* reduc_f32_cost */ - 5, /* reduc_f64_cost */ - 8, /* store_elt_extra_cost */ - 6, /* vec_to_scalar_cost */ - 7, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -/* Ampere-1 costs for vector insn classes. */ -static const struct cpu_vector_cost ampere1_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 3, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &ere1_advsimd_vector_cost, /* advsimd */ - nullptr, /* sve */ - nullptr /* issue_info */ -}; - -/* Generic costs for branch instructions. */ -static const struct cpu_branch_cost generic_branch_cost = -{ - 1, /* Predictable. */ - 3 /* Unpredictable. */ -}; - -/* Generic approximation modes. */ -static const cpu_approx_modes generic_approx_modes = -{ - AARCH64_APPROX_NONE, /* division */ - AARCH64_APPROX_NONE, /* sqrt */ - AARCH64_APPROX_NONE /* recip_sqrt */ -}; - -/* Approximation modes for Exynos M1. */ -static const cpu_approx_modes exynosm1_approx_modes = -{ - AARCH64_APPROX_NONE, /* division */ - AARCH64_APPROX_ALL, /* sqrt */ - AARCH64_APPROX_ALL /* recip_sqrt */ -}; - -/* Approximation modes for X-Gene 1. */ -static const cpu_approx_modes xgene1_approx_modes = -{ - AARCH64_APPROX_NONE, /* division */ - AARCH64_APPROX_NONE, /* sqrt */ - AARCH64_APPROX_ALL /* recip_sqrt */ -}; - -/* Generic prefetch settings (which disable prefetch). */ -static const cpu_prefetch_tune generic_prefetch_tune = -{ - 0, /* num_slots */ - -1, /* l1_cache_size */ - -1, /* l1_cache_line_size */ - -1, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune exynosm1_prefetch_tune = -{ - 0, /* num_slots */ - -1, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - -1, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune qdf24xx_prefetch_tune = -{ - 4, /* num_slots */ - 32, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 512, /* l2_cache_size */ - false, /* prefetch_dynamic_strides */ - 2048, /* minimum_stride */ - 3 /* default_opt_level */ -}; - -static const cpu_prefetch_tune thunderxt88_prefetch_tune = -{ - 8, /* num_slots */ - 32, /* l1_cache_size */ - 128, /* l1_cache_line_size */ - 16*1024, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - 3 /* default_opt_level */ -}; - -static const cpu_prefetch_tune thunderx_prefetch_tune = -{ - 8, /* num_slots */ - 32, /* l1_cache_size */ - 128, /* l1_cache_line_size */ - -1, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune thunderx2t99_prefetch_tune = -{ - 8, /* num_slots */ - 32, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 256, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune thunderx3t110_prefetch_tune = -{ - 8, /* num_slots */ - 32, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 256, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune tsv110_prefetch_tune = -{ - 0, /* num_slots */ - 64, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 512, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune xgene1_prefetch_tune = -{ - 8, /* num_slots */ - 32, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 256, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune a64fx_prefetch_tune = -{ - 8, /* num_slots */ - 64, /* l1_cache_size */ - 256, /* l1_cache_line_size */ - 32768, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const cpu_prefetch_tune ampere1_prefetch_tune = -{ - 0, /* num_slots */ - 64, /* l1_cache_size */ - 64, /* l1_cache_line_size */ - 2048, /* l2_cache_size */ - true, /* prefetch_dynamic_strides */ - -1, /* minimum_stride */ - -1 /* default_opt_level */ -}; - -static const struct tune_params generic_tunings = -{ - &cortexa57_extra_costs, - &generic_addrcost_table, - &generic_regmove_cost, - &generic_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 2, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "16:12", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - /* Enabling AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS significantly benefits - Neoverse V1. It does not have a noticeable effect on A64FX and should - have at most a very minor effect on SVE2 cores. */ - (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params cortexa35_tunings = -{ - &cortexa53_extra_costs, - &generic_addrcost_table, - &cortexa53_regmove_cost, - &generic_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 1, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params cortexa53_tunings = -{ - &cortexa53_extra_costs, - &generic_addrcost_table, - &cortexa53_regmove_cost, - &generic_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 2, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params cortexa57_tunings = -{ - &cortexa57_extra_costs, - &generic_addrcost_table, - &cortexa57_regmove_cost, - &cortexa57_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params cortexa72_tunings = -{ - &cortexa57_extra_costs, - &generic_addrcost_table, - &cortexa57_regmove_cost, - &cortexa57_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params cortexa73_tunings = -{ - &cortexa57_extra_costs, - &generic_addrcost_table, - &cortexa57_regmove_cost, - &cortexa57_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 2, /* issue_rate. */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params exynosm1_tunings = -{ - &exynosm1_extra_costs, - &exynosm1_addrcost_table, - &exynosm1_regmove_cost, - &exynosm1_vector_cost, - &generic_branch_cost, - &exynosm1_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC), /* fusible_ops */ - "4", /* function_align. */ - "4", /* jump_align. */ - "4", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 48, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &exynosm1_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params thunderxt88_tunings = -{ - &thunderx_extra_costs, - &generic_addrcost_table, - &thunderx_regmove_cost, - &thunderx_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 6, /* load_int. */ - 6, /* store_int. */ - 6, /* load_fp. */ - 6, /* store_fp. */ - 6, /* load_pred. */ - 6 /* store_pred. */ - }, /* memmov_cost. */ - 2, /* issue_rate */ - AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ - "8", /* function_align. */ - "8", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &thunderxt88_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ -}; - -static const struct tune_params thunderx_tunings = -{ - &thunderx_extra_costs, - &generic_addrcost_table, - &thunderx_regmove_cost, - &thunderx_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 6, /* load_int. */ - 6, /* store_int. */ - 6, /* load_fp. */ - 6, /* store_fp. */ - 6, /* load_pred. */ - 6 /* store_pred. */ - }, /* memmov_cost. */ - 2, /* issue_rate */ - AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ - "8", /* function_align. */ - "8", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ - &thunderx_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ -}; - -static const struct tune_params tsv110_tunings = -{ - &tsv110_extra_costs, - &tsv110_addrcost_table, - &tsv110_regmove_cost, - &tsv110_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH - | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ - "16", /* function_align. */ - "4", /* jump_align. */ - "8", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &tsv110_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params xgene1_tunings = -{ - &xgene1_extra_costs, - &xgene1_addrcost_table, - &xgene1_regmove_cost, - &xgene1_vector_cost, - &generic_branch_cost, - &xgene1_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 6, /* load_int. */ - 6, /* store_int. */ - 6, /* load_fp. */ - 6, /* store_fp. */ - 6, /* load_pred. */ - 6 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - AARCH64_FUSE_NOTHING, /* fusible_ops */ - "16", /* function_align. */ - "16", /* jump_align. */ - "16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 17, /* max_case_values. */ - tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ - &xgene1_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params emag_tunings = -{ - &xgene1_extra_costs, - &xgene1_addrcost_table, - &xgene1_regmove_cost, - &xgene1_vector_cost, - &generic_branch_cost, - &xgene1_approx_modes, - SVE_NOT_IMPLEMENTED, - { 6, /* load_int. */ - 6, /* store_int. */ - 6, /* load_fp. */ - 6, /* store_fp. */ - 6, /* load_pred. */ - 6 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - AARCH64_FUSE_NOTHING, /* fusible_ops */ - "16", /* function_align. */ - "16", /* jump_align. */ - "16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 17, /* max_case_values. */ - tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ - &xgene1_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params qdf24xx_tunings = -{ - &qdf24xx_extra_costs, - &qdf24xx_addrcost_table, - &qdf24xx_regmove_cost, - &qdf24xx_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ - "16", /* function_align. */ - "8", /* jump_align. */ - "16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS, /* tune_flags. */ - &qdf24xx_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -/* Tuning structure for the Qualcomm Saphira core. Default to falkor values - for now. */ -static const struct tune_params saphira_tunings = -{ - &generic_extra_costs, - &generic_addrcost_table, - &generic_regmove_cost, - &generic_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD - | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ - "16", /* function_align. */ - "8", /* jump_align. */ - "16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 1, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params thunderx2t99_tunings = -{ - &thunderx2t99_extra_costs, - &thunderx2t99_addrcost_table, - &thunderx2t99_regmove_cost, - &thunderx2t99_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate. */ - (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC - | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ - "16", /* function_align. */ - "8", /* jump_align. */ - "16", /* loop_align. */ - 3, /* int_reassoc_width. */ - 2, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &thunderx2t99_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params thunderx3t110_tunings = -{ - &thunderx3t110_extra_costs, - &thunderx3t110_addrcost_table, - &thunderx3t110_regmove_cost, - &thunderx3t110_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 6, /* issue_rate. */ - (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC - | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ - "16", /* function_align. */ - "8", /* jump_align. */ - "16", /* loop_align. */ - 3, /* int_reassoc_width. */ - 2, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &thunderx3t110_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params neoversen1_tunings = -{ - &cortexa76_extra_costs, - &generic_addrcost_table, - &generic_regmove_cost, - &cortexa57_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 2, /* store_int. */ - 5, /* load_fp. */ - 2, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32:16", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params ampere1_tunings = -{ - &ere1_extra_costs, - &generic_addrcost_table, - &generic_regmove_cost, - &ere1_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | - AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | - AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | - AARCH64_FUSE_CMP_BRANCH), - /* fusible_ops */ - "32", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 4, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &ere1_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ -}; - -static const struct tune_params ampere1a_tunings = -{ - &ere1a_extra_costs, - &generic_addrcost_table, - &generic_regmove_cost, - &ere1_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_NOT_IMPLEMENTED, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 4, /* issue_rate */ - (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | - AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | - AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | - AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_ALU_CBZ | - AARCH64_FUSE_ADDSUB_2REG_CONST1), - /* fusible_ops */ - "32", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &ere1_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ -}; - -static const advsimd_vec_cost neoversev1_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 4, /* ld2_st2_permute_cost */ - 4, /* ld3_st3_permute_cost */ - 5, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 4, /* reduc_i8_cost */ - 4, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 6, /* reduc_f16_cost */ - 3, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* This depends very much on what the scalar value is and - where it comes from. E.g. some constants take two dependent - instructions or a load, while others might be moved from a GPR. - 4 seems to be a reasonable compromise in practice. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const sve_vec_cost neoversev1_sve_vector_cost = -{ - { - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 4, /* ld2_st2_permute_cost */ - 7, /* ld3_st3_permute_cost */ - 8, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - /* Theoretically, a reduction involving 31 scalar ADDs could - complete in ~9 cycles and would have a cost of 31. [SU]ADDV - completes in 14 cycles, so give it a cost of 31 + 5. */ - 36, /* reduc_i8_cost */ - /* Likewise for 15 scalar ADDs (~5 cycles) vs. 12: 15 + 7. */ - 22, /* reduc_i16_cost */ - /* Likewise for 7 scalar ADDs (~3 cycles) vs. 10: 7 + 7. */ - 14, /* reduc_i32_cost */ - /* Likewise for 3 scalar ADDs (~2 cycles) vs. 10: 3 + 8. */ - 11, /* reduc_i64_cost */ - /* Theoretically, a reduction involving 15 scalar FADDs could - complete in ~9 cycles and would have a cost of 30. FADDV - completes in 13 cycles, so give it a cost of 30 + 4. */ - 34, /* reduc_f16_cost */ - /* Likewise for 7 scalar FADDs (~6 cycles) vs. 11: 14 + 5. */ - 19, /* reduc_f32_cost */ - /* Likewise for 3 scalar FADDs (~4 cycles) vs. 9: 6 + 5. */ - 11, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* See the comment above the Advanced SIMD versions. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 3, /* clast_cost */ - 19, /* fadda_f16_cost */ - 11, /* fadda_f32_cost */ - 8, /* fadda_f64_cost */ - 32, /* gather_load_x32_cost */ - 16, /* gather_load_x64_cost */ - 3 /* scatter_store_elt_cost */ -}; - -static const aarch64_scalar_vec_issue_info neoversev1_scalar_issue_info = -{ - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ -}; - -static const aarch64_advsimd_vec_issue_info neoversev1_advsimd_issue_info = -{ - { - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 2, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ -}; - -static const aarch64_sve_vec_issue_info neoversev1_sve_issue_info = -{ - { - { - 2, /* loads_per_cycle */ - 2, /* stores_per_cycle */ - 2, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 2, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ - }, - 1, /* pred_ops_per_cycle */ - 2, /* while_pred_ops */ - 2, /* int_cmp_pred_ops */ - 1, /* fp_cmp_pred_ops */ - 1, /* gather_scatter_pair_general_ops */ - 1 /* gather_scatter_pair_pred_ops */ -}; - -static const aarch64_vec_issue_info neoversev1_vec_issue_info = -{ - &neoversev1_scalar_issue_info, - &neoversev1_advsimd_issue_info, - &neoversev1_sve_issue_info -}; - -/* Neoverse V1 costs for vector insn classes. */ -static const struct cpu_vector_cost neoversev1_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 2, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &neoversev1_advsimd_vector_cost, /* advsimd */ - &neoversev1_sve_vector_cost, /* sve */ - &neoversev1_vec_issue_info /* issue_info */ -}; - -static const struct tune_params neoversev1_tunings = -{ - &cortexa76_extra_costs, - &neoversev1_addrcost_table, - &neoversev1_regmove_cost, - &neoversev1_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_256, /* sve_width */ - { 4, /* load_int. */ - 2, /* store_int. */ - 6, /* load_fp. */ - 2, /* store_fp. */ - 6, /* load_pred. */ - 1 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32:16", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 4, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - 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 - | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const sve_vec_cost neoverse512tvb_sve_vector_cost = -{ - { - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 4, /* ld2_st2_permute_cost */ - 5, /* ld3_st3_permute_cost */ - 5, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - /* Theoretically, a reduction involving 15 scalar ADDs could - complete in ~5 cycles and would have a cost of 15. Assume that - [SU]ADDV completes in 11 cycles and so give it a cost of 15 + 6. */ - 21, /* reduc_i8_cost */ - /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ - 13, /* reduc_i16_cost */ - /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ - 9, /* reduc_i32_cost */ - /* Likewise for 1 scalar ADD (1 cycle) vs. 8: 1 + 7. */ - 8, /* reduc_i64_cost */ - /* Theoretically, a reduction involving 7 scalar FADDs could - complete in ~6 cycles and would have a cost of 14. Assume that - FADDV completes in 8 cycles and so give it a cost of 14 + 2. */ - 16, /* reduc_f16_cost */ - /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ - 8, /* reduc_f32_cost */ - /* Likewise for 1 scalar FADD (2 cycles) vs. 4: 2 + 2. */ - 4, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* This depends very much on what the scalar value is and - where it comes from. E.g. some constants take two dependent - instructions or a load, while others might be moved from a GPR. - 4 seems to be a reasonable compromise in practice. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores generally have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 3, /* clast_cost */ - 10, /* fadda_f16_cost */ - 6, /* fadda_f32_cost */ - 4, /* fadda_f64_cost */ - /* A strided Advanced SIMD x64 load would take two parallel FP loads - (6 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather - is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads - (cost 8) and a vec_construct (cost 2). Add a full vector operation - (cost 2) to that, to avoid the difference being lost in rounding. - - There is no easy comparison between a strided Advanced SIMD x32 load - and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector - operation more than a 64-bit gather. */ - 14, /* gather_load_x32_cost */ - 12, /* gather_load_x64_cost */ - 3 /* scatter_store_elt_cost */ -}; - -static const aarch64_sve_vec_issue_info neoverse512tvb_sve_issue_info = -{ - { - { - 3, /* loads_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 2, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ - }, - 2, /* pred_ops_per_cycle */ - 2, /* while_pred_ops */ - 2, /* int_cmp_pred_ops */ - 1, /* fp_cmp_pred_ops */ - 1, /* gather_scatter_pair_general_ops */ - 1 /* gather_scatter_pair_pred_ops */ -}; - -static const aarch64_vec_issue_info neoverse512tvb_vec_issue_info = -{ - &neoversev1_scalar_issue_info, - &neoversev1_advsimd_issue_info, - &neoverse512tvb_sve_issue_info -}; - -static const struct cpu_vector_cost neoverse512tvb_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 2, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &neoversev1_advsimd_vector_cost, /* advsimd */ - &neoverse512tvb_sve_vector_cost, /* sve */ - &neoverse512tvb_vec_issue_info /* issue_info */ -}; - -static const struct tune_params neoverse512tvb_tunings = -{ - &cortexa76_extra_costs, - &neoversev1_addrcost_table, - &neoversev1_regmove_cost, - &neoverse512tvb_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_128 | SVE_256, /* sve_width */ - { 4, /* load_int. */ - 2, /* store_int. */ - 6, /* load_fp. */ - 2, /* store_fp. */ - 6, /* load_pred. */ - 1 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32:16", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 4, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - 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. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const advsimd_vec_cost neoversen2_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 2, /* ld2_st2_permute_cost */ - 2, /* ld3_st3_permute_cost */ - 3, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 4, /* reduc_i8_cost */ - 4, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 6, /* reduc_f16_cost */ - 4, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* This depends very much on what the scalar value is and - where it comes from. E.g. some constants take two dependent - instructions or a load, while others might be moved from a GPR. - 4 seems to be a reasonable compromise in practice. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const sve_vec_cost neoversen2_sve_vector_cost = -{ - { - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 3, /* ld2_st2_permute_cost */ - 4, /* ld3_st3_permute_cost */ - 4, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - /* Theoretically, a reduction involving 15 scalar ADDs could - complete in ~5 cycles and would have a cost of 15. [SU]ADDV - completes in 11 cycles, so give it a cost of 15 + 6. */ - 21, /* reduc_i8_cost */ - /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ - 13, /* reduc_i16_cost */ - /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ - 9, /* reduc_i32_cost */ - /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ - 2, /* reduc_i64_cost */ - /* Theoretically, a reduction involving 7 scalar FADDs could - complete in ~8 cycles and would have a cost of 14. FADDV - completes in 6 cycles, so give it a cost of 14 - 2. */ - 12, /* reduc_f16_cost */ - /* Likewise for 3 scalar FADDs (~4 cycles) vs. 4: 6 - 0. */ - 6, /* reduc_f32_cost */ - /* Likewise for 1 scalar FADD (~2 cycles) vs. 2: 2 - 0. */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* See the comment above the Advanced SIMD versions. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 3, /* clast_cost */ - 10, /* fadda_f16_cost */ - 6, /* fadda_f32_cost */ - 4, /* fadda_f64_cost */ - /* A strided Advanced SIMD x64 load would take two parallel FP loads - (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather - is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads - (cost 8) and a vec_construct (cost 2). Add a full vector operation - (cost 2) to that, to avoid the difference being lost in rounding. - - There is no easy comparison between a strided Advanced SIMD x32 load - and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector - operation more than a 64-bit gather. */ - 14, /* gather_load_x32_cost */ - 12, /* gather_load_x64_cost */ - 3 /* scatter_store_elt_cost */ -}; - -static const aarch64_scalar_vec_issue_info neoversen2_scalar_issue_info = -{ - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ -}; - -static const aarch64_advsimd_vec_issue_info neoversen2_advsimd_issue_info = -{ - { - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 2, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 2, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ -}; - -static const aarch64_sve_vec_issue_info neoversen2_sve_issue_info = -{ - { - { - 3, /* loads_per_cycle */ - 2, /* stores_per_cycle */ - 2, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 3, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ - }, - 2, /* pred_ops_per_cycle */ - 2, /* while_pred_ops */ - 2, /* int_cmp_pred_ops */ - 1, /* fp_cmp_pred_ops */ - 1, /* gather_scatter_pair_general_ops */ - 1 /* gather_scatter_pair_pred_ops */ -}; - -static const aarch64_vec_issue_info neoversen2_vec_issue_info = -{ - &neoversen2_scalar_issue_info, - &neoversen2_advsimd_issue_info, - &neoversen2_sve_issue_info -}; - -/* Neoverse N2 costs for vector insn classes. */ -static const struct cpu_vector_cost neoversen2_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 2, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &neoversen2_advsimd_vector_cost, /* advsimd */ - &neoversen2_sve_vector_cost, /* sve */ - &neoversen2_vec_issue_info /* issue_info */ -}; - -static const struct tune_params neoversen2_tunings = -{ - &cortexa76_extra_costs, - &neoversen2_addrcost_table, - &neoversen2_regmove_cost, - &neoversen2_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_128, /* sve_width */ - { 4, /* load_int. */ - 1, /* store_int. */ - 6, /* load_fp. */ - 2, /* store_fp. */ - 6, /* load_pred. */ - 1 /* store_pred. */ - }, /* memmov_cost. */ - 3, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32:16", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 2, /* int_reassoc_width. */ - 4, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND - | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS - | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const advsimd_vec_cost neoversev2_advsimd_vector_cost = -{ - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 2, /* ld2_st2_permute_cost */ - 2, /* ld3_st3_permute_cost */ - 3, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - 4, /* reduc_i8_cost */ - 4, /* reduc_i16_cost */ - 2, /* reduc_i32_cost */ - 2, /* reduc_i64_cost */ - 6, /* reduc_f16_cost */ - 3, /* reduc_f32_cost */ - 2, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* This depends very much on what the scalar value is and - where it comes from. E.g. some constants take two dependent - instructions or a load, while others might be moved from a GPR. - 4 seems to be a reasonable compromise in practice. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ -}; - -static const sve_vec_cost neoversev2_sve_vector_cost = -{ - { - 2, /* int_stmt_cost */ - 2, /* fp_stmt_cost */ - 3, /* ld2_st2_permute_cost */ - 3, /* ld3_st3_permute_cost */ - 4, /* ld4_st4_permute_cost */ - 3, /* permute_cost */ - /* Theoretically, a reduction involving 15 scalar ADDs could - complete in ~3 cycles and would have a cost of 15. [SU]ADDV - completes in 11 cycles, so give it a cost of 15 + 8. */ - 21, /* reduc_i8_cost */ - /* Likewise for 7 scalar ADDs (~2 cycles) vs. 9: 7 + 7. */ - 14, /* reduc_i16_cost */ - /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 4. */ - 7, /* reduc_i32_cost */ - /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ - 2, /* reduc_i64_cost */ - /* Theoretically, a reduction involving 7 scalar FADDs could - complete in ~6 cycles and would have a cost of 14. FADDV - completes in 8 cycles, so give it a cost of 14 + 2. */ - 16, /* reduc_f16_cost */ - /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ - 8, /* reduc_f32_cost */ - /* Likewise for 1 scalar FADD (~2 cycles) vs. 4: 2 + 2. */ - 4, /* reduc_f64_cost */ - 2, /* store_elt_extra_cost */ - /* This value is just inherited from the Cortex-A57 table. */ - 8, /* vec_to_scalar_cost */ - /* See the comment above the Advanced SIMD versions. */ - 4, /* scalar_to_vec_cost */ - 4, /* align_load_cost */ - 4, /* unalign_load_cost */ - /* Although stores have a latency of 2 and compete for the - vector pipes, in practice it's better not to model that. */ - 1, /* unalign_store_cost */ - 1 /* store_cost */ - }, - 3, /* clast_cost */ - 10, /* fadda_f16_cost */ - 6, /* fadda_f32_cost */ - 4, /* fadda_f64_cost */ - /* A strided Advanced SIMD x64 load would take two parallel FP loads - (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather - is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads - (cost 8) and a vec_construct (cost 2). Add a full vector operation - (cost 2) to that, to avoid the difference being lost in rounding. - - There is no easy comparison between a strided Advanced SIMD x32 load - and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector - operation more than a 64-bit gather. */ - 14, /* gather_load_x32_cost */ - 12, /* gather_load_x64_cost */ - 3 /* scatter_store_elt_cost */ -}; - -static const aarch64_scalar_vec_issue_info neoversev2_scalar_issue_info = -{ - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 6, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ -}; - -static const aarch64_advsimd_vec_issue_info neoversev2_advsimd_issue_info = -{ - { - 3, /* loads_stores_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 2, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ -}; - -static const aarch64_sve_vec_issue_info neoversev2_sve_issue_info = -{ - { - { - 3, /* loads_per_cycle */ - 2, /* stores_per_cycle */ - 4, /* general_ops_per_cycle */ - 0, /* fp_simd_load_general_ops */ - 1 /* fp_simd_store_general_ops */ - }, - 2, /* ld2_st2_general_ops */ - 3, /* ld3_st3_general_ops */ - 3 /* ld4_st4_general_ops */ - }, - 2, /* pred_ops_per_cycle */ - 2, /* while_pred_ops */ - 2, /* int_cmp_pred_ops */ - 1, /* fp_cmp_pred_ops */ - 1, /* gather_scatter_pair_general_ops */ - 1 /* gather_scatter_pair_pred_ops */ -}; - -static const aarch64_vec_issue_info neoversev2_vec_issue_info = -{ - &neoversev2_scalar_issue_info, - &neoversev2_advsimd_issue_info, - &neoversev2_sve_issue_info -}; - -/* Demeter costs for vector insn classes. */ -static const struct cpu_vector_cost neoversev2_vector_cost = -{ - 1, /* scalar_int_stmt_cost */ - 2, /* scalar_fp_stmt_cost */ - 4, /* scalar_load_cost */ - 1, /* scalar_store_cost */ - 1, /* cond_taken_branch_cost */ - 1, /* cond_not_taken_branch_cost */ - &neoversev2_advsimd_vector_cost, /* advsimd */ - &neoversev2_sve_vector_cost, /* sve */ - &neoversev2_vec_issue_info /* issue_info */ -}; - -static const struct tune_params neoversev2_tunings = -{ - &cortexa76_extra_costs, - &neoversev2_addrcost_table, - &neoversev2_regmove_cost, - &neoversev2_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_128, /* sve_width */ - { 4, /* load_int. */ - 2, /* store_int. */ - 6, /* load_fp. */ - 1, /* store_fp. */ - 6, /* load_pred. */ - 2 /* store_pred. */ - }, /* memmov_cost. */ - 5, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32:16", /* function_align. */ - "4", /* jump_align. */ - "32:16", /* loop_align. */ - 3, /* int_reassoc_width. */ - 6, /* fp_reassoc_width. */ - 4, /* fma_reassoc_width. */ - 3, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND - | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS - | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS - | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ - &generic_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; - -static const struct tune_params a64fx_tunings = -{ - &a64fx_extra_costs, - &a64fx_addrcost_table, - &a64fx_regmove_cost, - &a64fx_vector_cost, - &generic_branch_cost, - &generic_approx_modes, - SVE_512, /* sve_width */ - { 4, /* load_int. */ - 4, /* store_int. */ - 4, /* load_fp. */ - 4, /* store_fp. */ - 4, /* load_pred. */ - 4 /* store_pred. */ - }, /* memmov_cost. */ - 7, /* issue_rate */ - (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ - "32", /* function_align. */ - "16", /* jump_align. */ - "32", /* loop_align. */ - 4, /* int_reassoc_width. */ - 2, /* fp_reassoc_width. */ - 1, /* fma_reassoc_width. */ - 2, /* vec_reassoc_width. */ - 2, /* min_div_recip_mul_sf. */ - 2, /* min_div_recip_mul_df. */ - 0, /* max_case_values. */ - tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ - (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ - &a64fx_prefetch_tune, - AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ - AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ -}; +#include "tuning_models/generic.h" +#include "tuning_models/generic_armv8_a.h" +#include "tuning_models/generic_armv9_a.h" +#include "tuning_models/cortexa35.h" +#include "tuning_models/cortexa53.h" +#include "tuning_models/cortexa57.h" +#include "tuning_models/cortexa72.h" +#include "tuning_models/cortexa73.h" +#include "tuning_models/exynosm1.h" +#include "tuning_models/thunderxt88.h" +#include "tuning_models/thunderx.h" +#include "tuning_models/tsv110.h" +#include "tuning_models/xgene1.h" +#include "tuning_models/emag.h" +#include "tuning_models/qdf24xx.h" +#include "tuning_models/saphira.h" +#include "tuning_models/thunderx2t99.h" +#include "tuning_models/thunderx3t110.h" +#include "tuning_models/neoversen1.h" +#include "tuning_models/ampere1.h" +#include "tuning_models/ampere1a.h" +#include "tuning_models/neoversev1.h" +#include "tuning_models/neoverse512tvb.h" +#include "tuning_models/neoversen2.h" +#include "tuning_models/neoversev2.h" +#include "tuning_models/a64fx.h" /* Support for fine-grained override of the tuning structures. */ struct aarch64_tuning_override_function @@ -2802,8 +429,6 @@ static const struct processor all_cores[] = {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH, \ feature_deps::cpu_##IDENT, &COSTS##_tunings}, #include "aarch64-cores.def" - {"generic", generic, cortexa53, AARCH64_ARCH_V8A, - feature_deps::V8A ().enable, &generic_tunings}, {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, NULL} }; @@ -17007,7 +14632,7 @@ aarch64_adjust_stmt_cost (vec_info *vinfo, vect_cost_for_stmt kind, } gassign *assign = dyn_cast<gassign *> (STMT_VINFO_STMT (stmt_info)); - if (assign) + if ((kind == scalar_stmt || kind == vector_stmt) && assign) { /* For MLA we need to reduce the cost since MLA is 1 instruction. */ if (!vect_is_reduction (stmt_info) @@ -17088,15 +14713,18 @@ aarch64_vector_costs::count_ops (unsigned int count, vect_cost_for_stmt kind, ops->reduction_latency = MAX (ops->reduction_latency, base); } - /* Assume that multiply-adds will become a single operation. */ - if (stmt_info && aarch64_multiply_add_p (m_vinfo, stmt_info, m_vec_flags)) - return; + if (stmt_info && (kind == scalar_stmt || kind == vector_stmt)) + { + /* Assume that multiply-adds will become a single operation. */ + if (aarch64_multiply_add_p (m_vinfo, stmt_info, m_vec_flags)) + return; + + /* Assume that bool AND with compare operands will become a single + operation. */ + if (aarch64_bool_compound_p (m_vinfo, stmt_info, m_vec_flags)) + return; + } - /* Assume that bool AND with compare operands will become a single - operation. */ - if (stmt_info - && aarch64_bool_compound_p (m_vinfo, stmt_info, m_vec_flags)) - return; /* Count the basic operation cost associated with KIND. */ switch (kind) @@ -18808,12 +16436,22 @@ aarch64_override_options (void) if (cpu && arch) { /* If both -mcpu and -march are specified, warn if they are not - architecturally compatible and prefer the -march ISA flags. */ - if (arch->arch != cpu->arch) - { - warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch", + feature compatible. feature compatible means that the inclusion of the + cpu features would end up disabling an achitecture feature. In + otherwords the cpu features need to be a strict superset of the arch + features and if so prefer the -march ISA flags. */ + auto full_arch_flags = arch->flags | arch_isa; + auto full_cpu_flags = cpu->flags | cpu_isa; + if (~full_cpu_flags & full_arch_flags) + { + std::string ext_diff + = aarch64_get_extension_string_for_isa_flags (full_arch_flags, + full_cpu_flags); + warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch " + "and resulted in options %<%s%> being added", aarch64_cpu_string, - aarch64_arch_string); + aarch64_arch_string, + ext_diff.c_str ()); } selected_arch = arch->arch; diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 2f0777a..1ac2989 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -720,12 +720,11 @@ enum target_cpus #define AARCH64_CORE(NAME, INTERNAL_IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \ TARGET_CPU_##INTERNAL_IDENT, #include "aarch64-cores.def" - TARGET_CPU_generic }; /* If there is no CPU defined at configure, use generic as default. */ #ifndef TARGET_CPU_DEFAULT -# define TARGET_CPU_DEFAULT TARGET_CPU_generic +# define TARGET_CPU_DEFAULT TARGET_CPU_generic_armv8_a #endif /* If inserting NOP before a mult-accumulate insn remember to adjust the diff --git a/gcc/config/aarch64/tuning_models/a64fx.h b/gcc/config/aarch64/tuning_models/a64fx.h new file mode 100644 index 0000000..7b06c27 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/a64fx.h @@ -0,0 +1,169 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_A64FX +#define GCC_AARCH64_H_A64FX + +#include "generic.h" + +static const struct cpu_addrcost_table a64fx_addrcost_table = +{ + { + 1, /* hi */ + 1, /* si */ + 1, /* di */ + 2, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 2, /* register_offset */ + 3, /* register_sextend */ + 3, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost a64fx_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 5, /* GP2FP */ + 7, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost a64fx_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 5, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 13, /* reduc_i8_cost */ + 13, /* reduc_i16_cost */ + 13, /* reduc_i32_cost */ + 13, /* reduc_i64_cost */ + 13, /* reduc_f16_cost */ + 13, /* reduc_f32_cost */ + 13, /* reduc_f64_cost */ + 13, /* store_elt_extra_cost */ + 13, /* vec_to_scalar_cost */ + 4, /* scalar_to_vec_cost */ + 6, /* align_load_cost */ + 6, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const sve_vec_cost a64fx_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 5, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 13, /* reduc_i8_cost */ + 13, /* reduc_i16_cost */ + 13, /* reduc_i32_cost */ + 13, /* reduc_i64_cost */ + 13, /* reduc_f16_cost */ + 13, /* reduc_f32_cost */ + 13, /* reduc_f64_cost */ + 13, /* store_elt_extra_cost */ + 13, /* vec_to_scalar_cost */ + 4, /* scalar_to_vec_cost */ + 6, /* align_load_cost */ + 6, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 13, /* clast_cost */ + 13, /* fadda_f16_cost */ + 13, /* fadda_f32_cost */ + 13, /* fadda_f64_cost */ + 64, /* gather_load_x32_cost */ + 32, /* gather_load_x64_cost */ + 1 /* scatter_store_elt_cost */ +}; + +static const struct cpu_vector_cost a64fx_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 5, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 3, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &a64fx_advsimd_vector_cost, /* advsimd */ + &a64fx_sve_vector_cost, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune a64fx_prefetch_tune = +{ + 8, /* num_slots */ + 64, /* l1_cache_size */ + 256, /* l1_cache_line_size */ + 32768, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params a64fx_tunings = +{ + &a64fx_extra_costs, + &a64fx_addrcost_table, + &a64fx_regmove_cost, + &a64fx_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_512, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 7, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32", /* function_align. */ + "16", /* jump_align. */ + "32", /* loop_align. */ + 4, /* int_reassoc_width. */ + 2, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &a64fx_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_A64FX. */ diff --git a/gcc/config/aarch64/tuning_models/ampere1.h b/gcc/config/aarch64/tuning_models/ampere1.h new file mode 100644 index 0000000..8d2a1c6 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/ampere1.h @@ -0,0 +1,113 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_AMPERE1 +#define GCC_AARCH64_H_AMPERE1 + +#include "generic.h" + +static const advsimd_vec_cost ampere1_advsimd_vector_cost = +{ + 1, /* int_stmt_cost */ + 3, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 12, /* reduc_i8_cost */ + 9, /* reduc_i16_cost */ + 6, /* reduc_i32_cost */ + 5, /* reduc_i64_cost */ + 9, /* reduc_f16_cost */ + 6, /* reduc_f32_cost */ + 5, /* reduc_f64_cost */ + 8, /* store_elt_extra_cost */ + 6, /* vec_to_scalar_cost */ + 7, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* Ampere-1 costs for vector insn classes. */ +static const struct cpu_vector_cost ampere1_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 3, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &ere1_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune ampere1_prefetch_tune = +{ + 0, /* num_slots */ + 64, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 2048, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params ampere1_tunings = +{ + &ere1_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &ere1_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | + AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | + AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | + AARCH64_FUSE_CMP_BRANCH), + /* fusible_ops */ + "32", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 4, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &ere1_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_AMPERE1. */ diff --git a/gcc/config/aarch64/tuning_models/ampere1a.h b/gcc/config/aarch64/tuning_models/ampere1a.h new file mode 100644 index 0000000..c419ffb --- /dev/null +++ b/gcc/config/aarch64/tuning_models/ampere1a.h @@ -0,0 +1,65 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_AMPERE1A +#define GCC_AARCH64_H_AMPERE1A + +#include "generic.h" + +static const struct tune_params ampere1a_tunings = +{ + &ere1a_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &ere1_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | + AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | + AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | + AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_ALU_CBZ | + AARCH64_FUSE_ADDSUB_2REG_CONST1), + /* fusible_ops */ + "32", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &ere1_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_AMPERE1A. */ diff --git a/gcc/config/aarch64/tuning_models/cortexa35.h b/gcc/config/aarch64/tuning_models/cortexa35.h new file mode 100644 index 0000000..5534335 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/cortexa35.h @@ -0,0 +1,62 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_CORTEXA35 +#define GCC_AARCH64_H_CORTEXA35 + +#include "generic.h" +#include "cortexa53.h" + +static const struct tune_params cortexa35_tunings = +{ + &cortexa53_extra_costs, + &generic_addrcost_table, + &cortexa53_regmove_cost, + &generic_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 1, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_CORTEXA35. */ diff --git a/gcc/config/aarch64/tuning_models/cortexa53.h b/gcc/config/aarch64/tuning_models/cortexa53.h new file mode 100644 index 0000000..9dfdccc --- /dev/null +++ b/gcc/config/aarch64/tuning_models/cortexa53.h @@ -0,0 +1,71 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_CORTEXA53 +#define GCC_AARCH64_H_CORTEXA53 + +#include "generic.h" + +static const struct cpu_regmove_cost cortexa53_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 5, /* GP2FP */ + 5, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const struct tune_params cortexa53_tunings = +{ + &cortexa53_extra_costs, + &generic_addrcost_table, + &cortexa53_regmove_cost, + &generic_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 2, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_CORTEXA53. */ diff --git a/gcc/config/aarch64/tuning_models/cortexa57.h b/gcc/config/aarch64/tuning_models/cortexa57.h new file mode 100644 index 0000000..9c4789d --- /dev/null +++ b/gcc/config/aarch64/tuning_models/cortexa57.h @@ -0,0 +1,109 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_CORTEXA57 +#define GCC_AARCH64_H_CORTEXA57 + +#include "generic.h" + +static const struct cpu_regmove_cost cortexa57_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 5, /* GP2FP */ + 5, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost cortexa57_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 8, /* reduc_i8_cost */ + 8, /* reduc_i16_cost */ + 8, /* reduc_i32_cost */ + 8, /* reduc_i64_cost */ + 8, /* reduc_f16_cost */ + 8, /* reduc_f32_cost */ + 8, /* reduc_f64_cost */ + 8, /* store_elt_extra_cost */ + 8, /* vec_to_scalar_cost */ + 8, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* Cortex-A57 costs for vector insn classes. */ +static const struct cpu_vector_cost cortexa57_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &cortexa57_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const struct tune_params cortexa57_tunings = +{ + &cortexa57_extra_costs, + &generic_addrcost_table, + &cortexa57_regmove_cost, + &cortexa57_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_CORTEXA57. */ diff --git a/gcc/config/aarch64/tuning_models/cortexa72.h b/gcc/config/aarch64/tuning_models/cortexa72.h new file mode 100644 index 0000000..968171c --- /dev/null +++ b/gcc/config/aarch64/tuning_models/cortexa72.h @@ -0,0 +1,61 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_CORTEXA72 +#define GCC_AARCH64_H_CORTEXA72 + +#include "generic.h" + +static const struct tune_params cortexa72_tunings = +{ + &cortexa57_extra_costs, + &generic_addrcost_table, + &cortexa57_regmove_cost, + &cortexa57_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_CORTEXA72. */ diff --git a/gcc/config/aarch64/tuning_models/cortexa73.h b/gcc/config/aarch64/tuning_models/cortexa73.h new file mode 100644 index 0000000..8d1a504 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/cortexa73.h @@ -0,0 +1,62 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_CORTEXA73 +#define GCC_AARCH64_H_CORTEXA73 + +#include "generic.h" + +static const struct tune_params cortexa73_tunings = +{ + &cortexa57_extra_costs, + &generic_addrcost_table, + &cortexa57_regmove_cost, + &cortexa57_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 2, /* issue_rate. */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + + +#endif /* GCC_AARCH64_H_CORTEXA73. */ diff --git a/gcc/config/aarch64/tuning_models/emag.h b/gcc/config/aarch64/tuning_models/emag.h new file mode 100644 index 0000000..3f3402c --- /dev/null +++ b/gcc/config/aarch64/tuning_models/emag.h @@ -0,0 +1,60 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_EMAG +#define GCC_AARCH64_H_EMAG + +#include "generic.h" + +static const struct tune_params emag_tunings = +{ + &xgene1_extra_costs, + &xgene1_addrcost_table, + &xgene1_regmove_cost, + &xgene1_vector_cost, + &generic_branch_cost, + &xgene1_approx_modes, + SVE_NOT_IMPLEMENTED, + { 6, /* load_int. */ + 6, /* store_int. */ + 6, /* load_fp. */ + 6, /* store_fp. */ + 6, /* load_pred. */ + 6 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + AARCH64_FUSE_NOTHING, /* fusible_ops */ + "16", /* function_align. */ + "16", /* jump_align. */ + "16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 17, /* max_case_values. */ + tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ + &xgene1_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_EMAG. */ diff --git a/gcc/config/aarch64/tuning_models/exynosm1.h b/gcc/config/aarch64/tuning_models/exynosm1.h new file mode 100644 index 0000000..a42ea4d --- /dev/null +++ b/gcc/config/aarch64/tuning_models/exynosm1.h @@ -0,0 +1,144 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_EXYNOSM1 +#define GCC_AARCH64_H_EXYNOSM1 + +#include "generic.h" + +static const struct cpu_addrcost_table exynosm1_addrcost_table = +{ + { + 0, /* hi */ + 0, /* si */ + 0, /* di */ + 2, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 1, /* register_offset */ + 1, /* register_sextend */ + 2, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost exynosm1_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost (actual, 4 and 9). */ + 9, /* GP2FP */ + 9, /* FP2GP */ + 1 /* FP2FP */ +}; + +static const advsimd_vec_cost exynosm1_advsimd_vector_cost = +{ + 3, /* int_stmt_cost */ + 3, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 3, /* reduc_i8_cost */ + 3, /* reduc_i16_cost */ + 3, /* reduc_i32_cost */ + 3, /* reduc_i64_cost */ + 3, /* reduc_f16_cost */ + 3, /* reduc_f32_cost */ + 3, /* reduc_f64_cost */ + 3, /* store_elt_extra_cost */ + 3, /* vec_to_scalar_cost */ + 3, /* scalar_to_vec_cost */ + 5, /* align_load_cost */ + 5, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const struct cpu_vector_cost exynosm1_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 5, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &exynosm1_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +/* Approximation modes for Exynos M1. */ +static const cpu_approx_modes exynosm1_approx_modes = +{ + AARCH64_APPROX_NONE, /* division */ + AARCH64_APPROX_ALL, /* sqrt */ + AARCH64_APPROX_ALL /* recip_sqrt */ +}; + +static const cpu_prefetch_tune exynosm1_prefetch_tune = +{ + 0, /* num_slots */ + -1, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + -1, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params exynosm1_tunings = +{ + &exynosm1_extra_costs, + &exynosm1_addrcost_table, + &exynosm1_regmove_cost, + &exynosm1_vector_cost, + &generic_branch_cost, + &exynosm1_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC), /* fusible_ops */ + "4", /* function_align. */ + "4", /* jump_align. */ + "4", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 48, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &exynosm1_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_EXYNOSM1. */ diff --git a/gcc/config/aarch64/tuning_models/generic.h b/gcc/config/aarch64/tuning_models/generic.h new file mode 100644 index 0000000..deb2c1c --- /dev/null +++ b/gcc/config/aarch64/tuning_models/generic.h @@ -0,0 +1,190 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + Contributed by ARM Ltd. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_GENERIC +#define GCC_AARCH64_H_GENERIC + +static const struct cpu_addrcost_table generic_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost generic_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 5, /* GP2FP */ + 5, /* FP2GP */ + 2 /* FP2FP */ +}; + +/* Generic costs for Advanced SIMD vector operations. */ +static const advsimd_vec_cost generic_advsimd_vector_cost = +{ + 1, /* int_stmt_cost */ + 1, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 2, /* reduc_i8_cost */ + 2, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 2, /* reduc_f16_cost */ + 2, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + 2, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* align_load_cost */ + 1, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* Generic costs for SVE vector operations. */ +static const sve_vec_cost generic_sve_vector_cost = +{ + { + 1, /* int_stmt_cost */ + 1, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 2, /* reduc_i8_cost */ + 2, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 2, /* reduc_f16_cost */ + 2, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + 2, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* align_load_cost */ + 1, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 2, /* clast_cost */ + 2, /* fadda_f16_cost */ + 2, /* fadda_f32_cost */ + 2, /* fadda_f64_cost */ + 4, /* gather_load_x32_cost */ + 2, /* gather_load_x64_cost */ + 1 /* scatter_store_elt_cost */ +}; + +/* Generic costs for vector insn classes. */ +static const struct cpu_vector_cost generic_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 1, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 3, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &generic_advsimd_vector_cost, /* advsimd */ + &generic_sve_vector_cost, /* sve */ + nullptr /* issue_info */ +}; + +/* Generic costs for branch instructions. */ +static const struct cpu_branch_cost generic_branch_cost = +{ + 1, /* Predictable. */ + 3 /* Unpredictable. */ +}; + +/* Generic approximation modes. */ +static const cpu_approx_modes generic_approx_modes = +{ + AARCH64_APPROX_NONE, /* division */ + AARCH64_APPROX_NONE, /* sqrt */ + AARCH64_APPROX_NONE /* recip_sqrt */ +}; + +/* Generic prefetch settings (which disable prefetch). */ +static const cpu_prefetch_tune generic_prefetch_tune = +{ + 0, /* num_slots */ + -1, /* l1_cache_size */ + -1, /* l1_cache_line_size */ + -1, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params generic_tunings = +{ + &cortexa57_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &generic_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 2, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "16:12", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + /* Enabling AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS significantly benefits + Neoverse V1. It does not have a noticeable effect on A64FX and should + have at most a very minor effect on SVE2 cores. */ + (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_GENERIC. */ diff --git a/gcc/config/aarch64/tuning_models/generic_armv8_a.h b/gcc/config/aarch64/tuning_models/generic_armv8_a.h new file mode 100644 index 0000000..82abe17 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/generic_armv8_a.h @@ -0,0 +1,191 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_GENERIC_ARMV8_A +#define GCC_AARCH64_H_GENERIC_ARMV8_A + +#include "generic.h" + +static const struct cpu_addrcost_table generic_armv8_a_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost generic_armv8_a_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 5, /* GP2FP */ + 5, /* FP2GP */ + 2 /* FP2FP */ +}; + +/* Generic costs for Advanced SIMD vector operations. */ +static const advsimd_vec_cost generic_armv8_a_advsimd_vector_cost = +{ + 1, /* int_stmt_cost */ + 1, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 2, /* reduc_i8_cost */ + 2, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 2, /* reduc_f16_cost */ + 2, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + 2, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* align_load_cost */ + 1, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* Generic costs for SVE vector operations. */ +static const sve_vec_cost generic_armv8_a_sve_vector_cost = +{ + { + 1, /* int_stmt_cost */ + 1, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 2, /* reduc_i8_cost */ + 2, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 2, /* reduc_f16_cost */ + 2, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + 2, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* align_load_cost */ + 1, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 2, /* clast_cost */ + 2, /* fadda_f16_cost */ + 2, /* fadda_f32_cost */ + 2, /* fadda_f64_cost */ + 4, /* gather_load_x32_cost */ + 2, /* gather_load_x64_cost */ + 1 /* scatter_store_elt_cost */ +}; + +/* Generic costs for vector insn classes. */ +static const struct cpu_vector_cost generic_armv8_a_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 1, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 3, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &generic_armv8_a_advsimd_vector_cost, /* advsimd */ + &generic_armv8_a_sve_vector_cost, /* sve */ + nullptr /* issue_info */ +}; + +/* Generic costs for branch instructions. */ +static const struct cpu_branch_cost generic_armv8_a_branch_cost = +{ + 1, /* Predictable. */ + 3 /* Unpredictable. */ +}; + +/* Generic approximation modes. */ +static const cpu_approx_modes generic_armv8_a_approx_modes = +{ + AARCH64_APPROX_NONE, /* division */ + AARCH64_APPROX_NONE, /* sqrt */ + AARCH64_APPROX_NONE /* recip_sqrt */ +}; + +/* Generic prefetch settings (which disable prefetch). */ +static const cpu_prefetch_tune generic_armv8_a_prefetch_tune = +{ + 0, /* num_slots */ + -1, /* l1_cache_size */ + -1, /* l1_cache_line_size */ + -1, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params generic_armv8_a_tunings = +{ + &cortexa76_extra_costs, + &generic_armv8_a_addrcost_table, + &generic_armv8_a_regmove_cost, + &generic_armv8_a_vector_cost, + &generic_armv8_a_branch_cost, + &generic_armv8_a_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 2, /* store_int. */ + 5, /* load_fp. */ + 2, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND + | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS + | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_GENERIC_ARMV8_A. */ diff --git a/gcc/config/aarch64/tuning_models/generic_armv9_a.h b/gcc/config/aarch64/tuning_models/generic_armv9_a.h new file mode 100644 index 0000000..c017468 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/generic_armv9_a.h @@ -0,0 +1,245 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_GENERIC_ARMV9_A +#define GCC_AARCH64_H_GENERIC_ARMV9_A + +#include "generic.h" +#include "generic_armv8_a.h" + +static const struct cpu_addrcost_table generic_armv9_a_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 2, /* post_modify_ld3_st3 */ + 2, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost generic_armv9_a_regmove_cost = +{ + 1, /* GP2GP */ + /* Spilling to int<->fp instead of memory is recommended so set + realistic costs compared to memmov_cost. */ + 3, /* GP2FP */ + 2, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost generic_armv9_a_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 2, /* ld2_st2_permute_cost */ + 2, /* ld3_st3_permute_cost */ + 3, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 4, /* reduc_i8_cost */ + 4, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 6, /* reduc_f16_cost */ + 4, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* This depends very much on what the scalar value is and + where it comes from. E.g. some constants take two dependent + instructions or a load, while others might be moved from a GPR. + 4 seems to be a reasonable compromise in practice. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const sve_vec_cost generic_armv9_a_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 3, /* ld2_st2_permute_cost */ + 4, /* ld3_st3_permute_cost */ + 4, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + /* Theoretically, a reduction involving 15 scalar ADDs could + complete in ~5 cycles and would have a cost of 15. [SU]ADDV + completes in 11 cycles, so give it a cost of 15 + 6. */ + 21, /* reduc_i8_cost */ + /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ + 13, /* reduc_i16_cost */ + /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ + 9, /* reduc_i32_cost */ + /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ + 2, /* reduc_i64_cost */ + /* Theoretically, a reduction involving 7 scalar FADDs could + complete in ~8 cycles and would have a cost of 14. FADDV + completes in 6 cycles, so give it a cost of 14 - 2. */ + 12, /* reduc_f16_cost */ + /* Likewise for 3 scalar FADDs (~4 cycles) vs. 4: 6 - 0. */ + 6, /* reduc_f32_cost */ + /* Likewise for 1 scalar FADD (~2 cycles) vs. 2: 2 - 0. */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* See the comment above the Advanced SIMD versions. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 3, /* clast_cost */ + 10, /* fadda_f16_cost */ + 6, /* fadda_f32_cost */ + 4, /* fadda_f64_cost */ + /* A strided Advanced SIMD x64 load would take two parallel FP loads + (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather + is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads + (cost 8) and a vec_construct (cost 2). Add a full vector operation + (cost 2) to that, to avoid the difference being lost in rounding. + + There is no easy comparison between a strided Advanced SIMD x32 load + and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector + operation more than a 64-bit gather. */ + 14, /* gather_load_x32_cost */ + 12, /* gather_load_x64_cost */ + 3 /* scatter_store_elt_cost */ +}; + +static const aarch64_scalar_vec_issue_info generic_armv9_a_scalar_issue_info = +{ + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ +}; + +static const aarch64_advsimd_vec_issue_info generic_armv9_a_advsimd_issue_info = +{ + { + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 2, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ +}; + +static const aarch64_sve_vec_issue_info generic_armv9_a_sve_issue_info = +{ + { + { + 3, /* loads_per_cycle */ + 2, /* stores_per_cycle */ + 2, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 3, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ + }, + 2, /* pred_ops_per_cycle */ + 2, /* while_pred_ops */ + 2, /* int_cmp_pred_ops */ + 1, /* fp_cmp_pred_ops */ + 1, /* gather_scatter_pair_general_ops */ + 1 /* gather_scatter_pair_pred_ops */ +}; + +static const aarch64_vec_issue_info generic_armv9_a_vec_issue_info = +{ + &generic_armv9_a_scalar_issue_info, + &generic_armv9_a_advsimd_issue_info, + &generic_armv9_a_sve_issue_info +}; + +/* Neoverse N2 costs for vector insn classes. */ +static const struct cpu_vector_cost generic_armv9_a_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 2, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &generic_armv9_a_advsimd_vector_cost, /* advsimd */ + &generic_armv9_a_sve_vector_cost, /* sve */ + &generic_armv9_a_vec_issue_info /* issue_info */ +}; + +static const struct tune_params generic_armv9_a_tunings = +{ + &cortexa76_extra_costs, + &generic_armv9_a_addrcost_table, + &generic_armv9_a_regmove_cost, + &generic_armv9_a_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_SCALABLE, /* sve_width */ + { 4, /* load_int. */ + 1, /* store_int. */ + 6, /* load_fp. */ + 2, /* store_fp. */ + 6, /* load_pred. */ + 1 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND + | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_GENERIC_ARMV9_A. */ diff --git a/gcc/config/aarch64/tuning_models/neoverse512tvb.h b/gcc/config/aarch64/tuning_models/neoverse512tvb.h new file mode 100644 index 0000000..50d7b23 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/neoverse512tvb.h @@ -0,0 +1,164 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_NEOVERSE512TVB +#define GCC_AARCH64_H_NEOVERSE512TVB + +#include "generic.h" + +static const sve_vec_cost neoverse512tvb_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 4, /* ld2_st2_permute_cost */ + 5, /* ld3_st3_permute_cost */ + 5, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + /* Theoretically, a reduction involving 15 scalar ADDs could + complete in ~5 cycles and would have a cost of 15. Assume that + [SU]ADDV completes in 11 cycles and so give it a cost of 15 + 6. */ + 21, /* reduc_i8_cost */ + /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ + 13, /* reduc_i16_cost */ + /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ + 9, /* reduc_i32_cost */ + /* Likewise for 1 scalar ADD (1 cycle) vs. 8: 1 + 7. */ + 8, /* reduc_i64_cost */ + /* Theoretically, a reduction involving 7 scalar FADDs could + complete in ~6 cycles and would have a cost of 14. Assume that + FADDV completes in 8 cycles and so give it a cost of 14 + 2. */ + 16, /* reduc_f16_cost */ + /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ + 8, /* reduc_f32_cost */ + /* Likewise for 1 scalar FADD (2 cycles) vs. 4: 2 + 2. */ + 4, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* This depends very much on what the scalar value is and + where it comes from. E.g. some constants take two dependent + instructions or a load, while others might be moved from a GPR. + 4 seems to be a reasonable compromise in practice. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores generally have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 3, /* clast_cost */ + 10, /* fadda_f16_cost */ + 6, /* fadda_f32_cost */ + 4, /* fadda_f64_cost */ + /* A strided Advanced SIMD x64 load would take two parallel FP loads + (6 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather + is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads + (cost 8) and a vec_construct (cost 2). Add a full vector operation + (cost 2) to that, to avoid the difference being lost in rounding. + + There is no easy comparison between a strided Advanced SIMD x32 load + and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector + operation more than a 64-bit gather. */ + 14, /* gather_load_x32_cost */ + 12, /* gather_load_x64_cost */ + 3 /* scatter_store_elt_cost */ +}; + +static const aarch64_sve_vec_issue_info neoverse512tvb_sve_issue_info = +{ + { + { + 3, /* loads_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ + }, + 2, /* pred_ops_per_cycle */ + 2, /* while_pred_ops */ + 2, /* int_cmp_pred_ops */ + 1, /* fp_cmp_pred_ops */ + 1, /* gather_scatter_pair_general_ops */ + 1 /* gather_scatter_pair_pred_ops */ +}; + +static const aarch64_vec_issue_info neoverse512tvb_vec_issue_info = +{ + &neoversev1_scalar_issue_info, + &neoversev1_advsimd_issue_info, + &neoverse512tvb_sve_issue_info +}; + +static const struct cpu_vector_cost neoverse512tvb_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 2, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &neoversev1_advsimd_vector_cost, /* advsimd */ + &neoverse512tvb_sve_vector_cost, /* sve */ + &neoverse512tvb_vec_issue_info /* issue_info */ +}; + +static const struct tune_params neoverse512tvb_tunings = +{ + &cortexa76_extra_costs, + &neoversev1_addrcost_table, + &neoversev1_regmove_cost, + &neoverse512tvb_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_128 | SVE_256, /* sve_width */ + { 4, /* load_int. */ + 2, /* store_int. */ + 6, /* load_fp. */ + 2, /* store_fp. */ + 6, /* load_pred. */ + 1 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 4, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + 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. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_NEOVERSE512TVB. */ diff --git a/gcc/config/aarch64/tuning_models/neoversen1.h b/gcc/config/aarch64/tuning_models/neoversen1.h new file mode 100644 index 0000000..132166d --- /dev/null +++ b/gcc/config/aarch64/tuning_models/neoversen1.h @@ -0,0 +1,60 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_NEOVERSEN1 +#define GCC_AARCH64_H_NEOVERSEN1 + +#include "generic.h" + +static const struct tune_params neoversen1_tunings = +{ + &cortexa76_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &cortexa57_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 2, /* store_int. */ + 5, /* load_fp. */ + 2, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_NEOVERSEN1. */ diff --git a/gcc/config/aarch64/tuning_models/neoversen2.h b/gcc/config/aarch64/tuning_models/neoversen2.h new file mode 100644 index 0000000..395a6d8 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/neoversen2.h @@ -0,0 +1,245 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_NEOVERSEN2 +#define GCC_AARCH64_H_NEOVERSEN2 + +#include "generic.h" + +static const struct cpu_addrcost_table neoversen2_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 2, /* post_modify_ld3_st3 */ + 2, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost neoversen2_regmove_cost = +{ + 1, /* GP2GP */ + /* Spilling to int<->fp instead of memory is recommended so set + realistic costs compared to memmov_cost. */ + 3, /* GP2FP */ + 2, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost neoversen2_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 2, /* ld2_st2_permute_cost */ + 2, /* ld3_st3_permute_cost */ + 3, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 4, /* reduc_i8_cost */ + 4, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 6, /* reduc_f16_cost */ + 4, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* This depends very much on what the scalar value is and + where it comes from. E.g. some constants take two dependent + instructions or a load, while others might be moved from a GPR. + 4 seems to be a reasonable compromise in practice. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const sve_vec_cost neoversen2_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 3, /* ld2_st2_permute_cost */ + 4, /* ld3_st3_permute_cost */ + 4, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + /* Theoretically, a reduction involving 15 scalar ADDs could + complete in ~5 cycles and would have a cost of 15. [SU]ADDV + completes in 11 cycles, so give it a cost of 15 + 6. */ + 21, /* reduc_i8_cost */ + /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ + 13, /* reduc_i16_cost */ + /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ + 9, /* reduc_i32_cost */ + /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ + 2, /* reduc_i64_cost */ + /* Theoretically, a reduction involving 7 scalar FADDs could + complete in ~8 cycles and would have a cost of 14. FADDV + completes in 6 cycles, so give it a cost of 14 - 2. */ + 12, /* reduc_f16_cost */ + /* Likewise for 3 scalar FADDs (~4 cycles) vs. 4: 6 - 0. */ + 6, /* reduc_f32_cost */ + /* Likewise for 1 scalar FADD (~2 cycles) vs. 2: 2 - 0. */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* See the comment above the Advanced SIMD versions. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 3, /* clast_cost */ + 10, /* fadda_f16_cost */ + 6, /* fadda_f32_cost */ + 4, /* fadda_f64_cost */ + /* A strided Advanced SIMD x64 load would take two parallel FP loads + (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather + is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads + (cost 8) and a vec_construct (cost 2). Add a full vector operation + (cost 2) to that, to avoid the difference being lost in rounding. + + There is no easy comparison between a strided Advanced SIMD x32 load + and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector + operation more than a 64-bit gather. */ + 14, /* gather_load_x32_cost */ + 12, /* gather_load_x64_cost */ + 3 /* scatter_store_elt_cost */ +}; + +static const aarch64_scalar_vec_issue_info neoversen2_scalar_issue_info = +{ + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ +}; + +static const aarch64_advsimd_vec_issue_info neoversen2_advsimd_issue_info = +{ + { + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 2, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ +}; + +static const aarch64_sve_vec_issue_info neoversen2_sve_issue_info = +{ + { + { + 3, /* loads_per_cycle */ + 2, /* stores_per_cycle */ + 2, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 3, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ + }, + 2, /* pred_ops_per_cycle */ + 2, /* while_pred_ops */ + 2, /* int_cmp_pred_ops */ + 1, /* fp_cmp_pred_ops */ + 1, /* gather_scatter_pair_general_ops */ + 1 /* gather_scatter_pair_pred_ops */ +}; + +static const aarch64_vec_issue_info neoversen2_vec_issue_info = +{ + &neoversen2_scalar_issue_info, + &neoversen2_advsimd_issue_info, + &neoversen2_sve_issue_info +}; + +/* Neoverse N2 costs for vector insn classes. */ +static const struct cpu_vector_cost neoversen2_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 2, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &neoversen2_advsimd_vector_cost, /* advsimd */ + &neoversen2_sve_vector_cost, /* sve */ + &neoversen2_vec_issue_info /* issue_info */ +}; + +static const struct tune_params neoversen2_tunings = +{ + &cortexa76_extra_costs, + &neoversen2_addrcost_table, + &neoversen2_regmove_cost, + &neoversen2_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_128, /* sve_width */ + { 4, /* load_int. */ + 1, /* store_int. */ + 6, /* load_fp. */ + 2, /* store_fp. */ + 6, /* load_pred. */ + 1 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND + | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS + | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_NEOVERSEN2. */ diff --git a/gcc/config/aarch64/tuning_models/neoversev1.h b/gcc/config/aarch64/tuning_models/neoversev1.h new file mode 100644 index 0000000..584a500 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/neoversev1.h @@ -0,0 +1,237 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_NEOVERSEV1 +#define GCC_AARCH64_H_NEOVERSEV1 + +#include "generic.h" + +static const struct cpu_addrcost_table neoversev1_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 3, /* post_modify_ld3_st3 */ + 3, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost neoversev1_regmove_cost = +{ + 1, /* GP2GP */ + /* Spilling to int<->fp instead of memory is recommended so set + realistic costs compared to memmov_cost. */ + 3, /* GP2FP */ + 2, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost neoversev1_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 4, /* ld2_st2_permute_cost */ + 4, /* ld3_st3_permute_cost */ + 5, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 4, /* reduc_i8_cost */ + 4, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 6, /* reduc_f16_cost */ + 3, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* This depends very much on what the scalar value is and + where it comes from. E.g. some constants take two dependent + instructions or a load, while others might be moved from a GPR. + 4 seems to be a reasonable compromise in practice. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const sve_vec_cost neoversev1_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 4, /* ld2_st2_permute_cost */ + 7, /* ld3_st3_permute_cost */ + 8, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + /* Theoretically, a reduction involving 31 scalar ADDs could + complete in ~9 cycles and would have a cost of 31. [SU]ADDV + completes in 14 cycles, so give it a cost of 31 + 5. */ + 36, /* reduc_i8_cost */ + /* Likewise for 15 scalar ADDs (~5 cycles) vs. 12: 15 + 7. */ + 22, /* reduc_i16_cost */ + /* Likewise for 7 scalar ADDs (~3 cycles) vs. 10: 7 + 7. */ + 14, /* reduc_i32_cost */ + /* Likewise for 3 scalar ADDs (~2 cycles) vs. 10: 3 + 8. */ + 11, /* reduc_i64_cost */ + /* Theoretically, a reduction involving 15 scalar FADDs could + complete in ~9 cycles and would have a cost of 30. FADDV + completes in 13 cycles, so give it a cost of 30 + 4. */ + 34, /* reduc_f16_cost */ + /* Likewise for 7 scalar FADDs (~6 cycles) vs. 11: 14 + 5. */ + 19, /* reduc_f32_cost */ + /* Likewise for 3 scalar FADDs (~4 cycles) vs. 9: 6 + 5. */ + 11, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* See the comment above the Advanced SIMD versions. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 3, /* clast_cost */ + 19, /* fadda_f16_cost */ + 11, /* fadda_f32_cost */ + 8, /* fadda_f64_cost */ + 32, /* gather_load_x32_cost */ + 16, /* gather_load_x64_cost */ + 3 /* scatter_store_elt_cost */ +}; + +static const aarch64_scalar_vec_issue_info neoversev1_scalar_issue_info = +{ + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ +}; + +static const aarch64_advsimd_vec_issue_info neoversev1_advsimd_issue_info = +{ + { + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ +}; + +static const aarch64_sve_vec_issue_info neoversev1_sve_issue_info = +{ + { + { + 2, /* loads_per_cycle */ + 2, /* stores_per_cycle */ + 2, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ + }, + 1, /* pred_ops_per_cycle */ + 2, /* while_pred_ops */ + 2, /* int_cmp_pred_ops */ + 1, /* fp_cmp_pred_ops */ + 1, /* gather_scatter_pair_general_ops */ + 1 /* gather_scatter_pair_pred_ops */ +}; + +static const aarch64_vec_issue_info neoversev1_vec_issue_info = +{ + &neoversev1_scalar_issue_info, + &neoversev1_advsimd_issue_info, + &neoversev1_sve_issue_info +}; + +/* Neoverse V1 costs for vector insn classes. */ +static const struct cpu_vector_cost neoversev1_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 2, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &neoversev1_advsimd_vector_cost, /* advsimd */ + &neoversev1_sve_vector_cost, /* sve */ + &neoversev1_vec_issue_info /* issue_info */ +}; + +static const struct tune_params neoversev1_tunings = +{ + &cortexa76_extra_costs, + &neoversev1_addrcost_table, + &neoversev1_regmove_cost, + &neoversev1_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_256, /* sve_width */ + { 4, /* load_int. */ + 2, /* store_int. */ + 6, /* load_fp. */ + 2, /* store_fp. */ + 6, /* load_pred. */ + 1 /* store_pred. */ + }, /* memmov_cost. */ + 3, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 4, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + 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 + | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + + +#endif /* GCC_AARCH64_H_NEOVERSEV1. */ diff --git a/gcc/config/aarch64/tuning_models/neoversev2.h b/gcc/config/aarch64/tuning_models/neoversev2.h new file mode 100644 index 0000000..28d4244 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/neoversev2.h @@ -0,0 +1,245 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_NEOVERSEV2 +#define GCC_AARCH64_H_NEOVERSEV2 + +#include "generic.h" + +static const struct cpu_addrcost_table neoversev2_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 2, /* post_modify_ld3_st3 */ + 2, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 0, /* register_sextend */ + 0, /* register_zextend */ + 0 /* imm_offset */ +}; + +static const struct cpu_regmove_cost neoversev2_regmove_cost = +{ + 1, /* GP2GP */ + /* Spilling to int<->fp instead of memory is recommended so set + realistic costs compared to memmov_cost. */ + 3, /* GP2FP */ + 2, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost neoversev2_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 2, /* ld2_st2_permute_cost */ + 2, /* ld3_st3_permute_cost */ + 3, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + 4, /* reduc_i8_cost */ + 4, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 6, /* reduc_f16_cost */ + 3, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* This depends very much on what the scalar value is and + where it comes from. E.g. some constants take two dependent + instructions or a load, while others might be moved from a GPR. + 4 seems to be a reasonable compromise in practice. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const sve_vec_cost neoversev2_sve_vector_cost = +{ + { + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 3, /* ld2_st2_permute_cost */ + 3, /* ld3_st3_permute_cost */ + 4, /* ld4_st4_permute_cost */ + 3, /* permute_cost */ + /* Theoretically, a reduction involving 15 scalar ADDs could + complete in ~3 cycles and would have a cost of 15. [SU]ADDV + completes in 11 cycles, so give it a cost of 15 + 8. */ + 21, /* reduc_i8_cost */ + /* Likewise for 7 scalar ADDs (~2 cycles) vs. 9: 7 + 7. */ + 14, /* reduc_i16_cost */ + /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 4. */ + 7, /* reduc_i32_cost */ + /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ + 2, /* reduc_i64_cost */ + /* Theoretically, a reduction involving 7 scalar FADDs could + complete in ~6 cycles and would have a cost of 14. FADDV + completes in 8 cycles, so give it a cost of 14 + 2. */ + 16, /* reduc_f16_cost */ + /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ + 8, /* reduc_f32_cost */ + /* Likewise for 1 scalar FADD (~2 cycles) vs. 4: 2 + 2. */ + 4, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + /* This value is just inherited from the Cortex-A57 table. */ + 8, /* vec_to_scalar_cost */ + /* See the comment above the Advanced SIMD versions. */ + 4, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + /* Although stores have a latency of 2 and compete for the + vector pipes, in practice it's better not to model that. */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ + }, + 3, /* clast_cost */ + 10, /* fadda_f16_cost */ + 6, /* fadda_f32_cost */ + 4, /* fadda_f64_cost */ + /* A strided Advanced SIMD x64 load would take two parallel FP loads + (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather + is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads + (cost 8) and a vec_construct (cost 2). Add a full vector operation + (cost 2) to that, to avoid the difference being lost in rounding. + + There is no easy comparison between a strided Advanced SIMD x32 load + and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector + operation more than a 64-bit gather. */ + 14, /* gather_load_x32_cost */ + 12, /* gather_load_x64_cost */ + 3 /* scatter_store_elt_cost */ +}; + +static const aarch64_scalar_vec_issue_info neoversev2_scalar_issue_info = +{ + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 6, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ +}; + +static const aarch64_advsimd_vec_issue_info neoversev2_advsimd_issue_info = +{ + { + 3, /* loads_stores_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 2, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ +}; + +static const aarch64_sve_vec_issue_info neoversev2_sve_issue_info = +{ + { + { + 3, /* loads_per_cycle */ + 2, /* stores_per_cycle */ + 4, /* general_ops_per_cycle */ + 0, /* fp_simd_load_general_ops */ + 1 /* fp_simd_store_general_ops */ + }, + 2, /* ld2_st2_general_ops */ + 3, /* ld3_st3_general_ops */ + 3 /* ld4_st4_general_ops */ + }, + 2, /* pred_ops_per_cycle */ + 2, /* while_pred_ops */ + 2, /* int_cmp_pred_ops */ + 1, /* fp_cmp_pred_ops */ + 1, /* gather_scatter_pair_general_ops */ + 1 /* gather_scatter_pair_pred_ops */ +}; + +static const aarch64_vec_issue_info neoversev2_vec_issue_info = +{ + &neoversev2_scalar_issue_info, + &neoversev2_advsimd_issue_info, + &neoversev2_sve_issue_info +}; + +/* Demeter costs for vector insn classes. */ +static const struct cpu_vector_cost neoversev2_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 2, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &neoversev2_advsimd_vector_cost, /* advsimd */ + &neoversev2_sve_vector_cost, /* sve */ + &neoversev2_vec_issue_info /* issue_info */ +}; + +static const struct tune_params neoversev2_tunings = +{ + &cortexa76_extra_costs, + &neoversev2_addrcost_table, + &neoversev2_regmove_cost, + &neoversev2_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_128, /* sve_width */ + { 4, /* load_int. */ + 2, /* store_int. */ + 6, /* load_fp. */ + 1, /* store_fp. */ + 6, /* load_pred. */ + 2 /* store_pred. */ + }, /* memmov_cost. */ + 5, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ + "32:16", /* function_align. */ + "4", /* jump_align. */ + "32:16", /* loop_align. */ + 3, /* int_reassoc_width. */ + 6, /* fp_reassoc_width. */ + 4, /* fma_reassoc_width. */ + 3, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND + | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS + | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS + | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_NEOVERSEV2. */ diff --git a/gcc/config/aarch64/tuning_models/qdf24xx.h b/gcc/config/aarch64/tuning_models/qdf24xx.h new file mode 100644 index 0000000..29c9b9f --- /dev/null +++ b/gcc/config/aarch64/tuning_models/qdf24xx.h @@ -0,0 +1,137 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_QDF24XX +#define GCC_AARCH64_H_QDF24XX + +#include "generic.h" + +static const struct cpu_addrcost_table qdf24xx_addrcost_table = +{ + { + 1, /* hi */ + 1, /* si */ + 1, /* di */ + 2, /* ti */ + }, + 1, /* pre_modify */ + 1, /* post_modify */ + 1, /* post_modify_ld3_st3 */ + 1, /* post_modify_ld4_st4 */ + 3, /* register_offset */ + 3, /* register_sextend */ + 3, /* register_zextend */ + 2, /* imm_offset */ +}; + +static const struct cpu_regmove_cost qdf24xx_regmove_cost = +{ + 2, /* GP2GP */ + /* Avoid the use of int<->fp moves for spilling. */ + 6, /* GP2FP */ + 6, /* FP2GP */ + 4 /* FP2FP */ +}; + +static const advsimd_vec_cost qdf24xx_advsimd_vector_cost = +{ + 1, /* int_stmt_cost */ + 3, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 1, /* reduc_i8_cost */ + 1, /* reduc_i16_cost */ + 1, /* reduc_i32_cost */ + 1, /* reduc_i64_cost */ + 1, /* reduc_f16_cost */ + 1, /* reduc_f32_cost */ + 1, /* reduc_f64_cost */ + 1, /* store_elt_extra_cost */ + 1, /* vec_to_scalar_cost */ + 1, /* scalar_to_vec_cost */ + 1, /* align_load_cost */ + 1, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* QDF24XX costs for vector insn classes. */ +static const struct cpu_vector_cost qdf24xx_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 1, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 3, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &qdf24xx_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune qdf24xx_prefetch_tune = +{ + 4, /* num_slots */ + 32, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 512, /* l2_cache_size */ + false, /* prefetch_dynamic_strides */ + 2048, /* minimum_stride */ + 3 /* default_opt_level */ +}; + +static const struct tune_params qdf24xx_tunings = +{ + &qdf24xx_extra_costs, + &qdf24xx_addrcost_table, + &qdf24xx_regmove_cost, + &qdf24xx_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS, /* tune_flags. */ + &qdf24xx_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_QDF24XX. */ diff --git a/gcc/config/aarch64/tuning_models/saphira.h b/gcc/config/aarch64/tuning_models/saphira.h new file mode 100644 index 0000000..e584d31 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/saphira.h @@ -0,0 +1,63 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_SAPHIRA +#define GCC_AARCH64_H_SAPHIRA + +#include "generic.h" + +/* Tuning structure for the Qualcomm Saphira core. Default to falkor values + for now. */ +static const struct tune_params saphira_tunings = +{ + &generic_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &generic_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD + | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &generic_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_SAPHIRA. */ diff --git a/gcc/config/aarch64/tuning_models/thunderx.h b/gcc/config/aarch64/tuning_models/thunderx.h new file mode 100644 index 0000000..dd4b9d5 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/thunderx.h @@ -0,0 +1,117 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_THUNDERX +#define GCC_AARCH64_H_THUNDERX + +#include "generic.h" + +static const struct cpu_regmove_cost thunderx_regmove_cost = +{ + 2, /* GP2GP */ + 2, /* GP2FP */ + 6, /* FP2GP */ + 4 /* FP2FP */ +}; + +static const advsimd_vec_cost thunderx_advsimd_vector_cost = +{ + 4, /* int_stmt_cost */ + 1, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 4, /* permute_cost */ + 2, /* reduc_i8_cost */ + 2, /* reduc_i16_cost */ + 2, /* reduc_i32_cost */ + 2, /* reduc_i64_cost */ + 2, /* reduc_f16_cost */ + 2, /* reduc_f32_cost */ + 2, /* reduc_f64_cost */ + 2, /* store_elt_extra_cost */ + 2, /* vec_to_scalar_cost */ + 2, /* scalar_to_vec_cost */ + 3, /* align_load_cost */ + 5, /* unalign_load_cost */ + 5, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* ThunderX costs for vector insn classes. */ +static const struct cpu_vector_cost thunderx_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 3, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 3, /* cond_taken_branch_cost */ + 3, /* cond_not_taken_branch_cost */ + &thunderx_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune thunderx_prefetch_tune = +{ + 8, /* num_slots */ + 32, /* l1_cache_size */ + 128, /* l1_cache_line_size */ + -1, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params thunderx_tunings = +{ + &thunderx_extra_costs, + &generic_addrcost_table, + &thunderx_regmove_cost, + &thunderx_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 6, /* load_int. */ + 6, /* store_int. */ + 6, /* load_fp. */ + 6, /* store_fp. */ + 6, /* load_pred. */ + 6 /* store_pred. */ + }, /* memmov_cost. */ + 2, /* issue_rate */ + AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ + "8", /* function_align. */ + "8", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ + &thunderx_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_THUNDERX. */ diff --git a/gcc/config/aarch64/tuning_models/thunderx2t99.h b/gcc/config/aarch64/tuning_models/thunderx2t99.h new file mode 100644 index 0000000..0a376e0 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/thunderx2t99.h @@ -0,0 +1,137 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_THUNDERX2T99 +#define GCC_AARCH64_H_THUNDERX2T99 + +#include "generic.h" + +static const struct cpu_addrcost_table thunderx2t99_addrcost_table = +{ + { + 1, /* hi */ + 1, /* si */ + 1, /* di */ + 2, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 2, /* register_offset */ + 3, /* register_sextend */ + 3, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost thunderx2t99_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of int<->fp moves for spilling. */ + 5, /* GP2FP */ + 6, /* FP2GP */ + 3, /* FP2FP */ +}; + +static const advsimd_vec_cost thunderx2t99_advsimd_vector_cost = +{ + 4, /* int_stmt_cost */ + 5, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 10, /* permute_cost */ + 6, /* reduc_i8_cost */ + 6, /* reduc_i16_cost */ + 6, /* reduc_i32_cost */ + 6, /* reduc_i64_cost */ + 6, /* reduc_f16_cost */ + 6, /* reduc_f32_cost */ + 6, /* reduc_f64_cost */ + 6, /* store_elt_extra_cost */ + 6, /* vec_to_scalar_cost */ + 5, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +/* Costs for vector insn classes for Vulcan. */ +static const struct cpu_vector_cost thunderx2t99_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 6, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 2, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &thunderx2t99_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune thunderx2t99_prefetch_tune = +{ + 8, /* num_slots */ + 32, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 256, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params thunderx2t99_tunings = +{ + &thunderx2t99_extra_costs, + &thunderx2t99_addrcost_table, + &thunderx2t99_regmove_cost, + &thunderx2t99_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate. */ + (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC + | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ + 3, /* int_reassoc_width. */ + 2, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &thunderx2t99_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_THUNDERX2T99. */ diff --git a/gcc/config/aarch64/tuning_models/thunderx3t110.h b/gcc/config/aarch64/tuning_models/thunderx3t110.h new file mode 100644 index 0000000..65203b4 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/thunderx3t110.h @@ -0,0 +1,136 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_THUNDERX3T110 +#define GCC_AARCH64_H_THUNDERX3T110 + +#include "generic.h" + +static const struct cpu_addrcost_table thunderx3t110_addrcost_table = +{ + { + 1, /* hi */ + 1, /* si */ + 1, /* di */ + 2, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 2, /* register_offset */ + 3, /* register_sextend */ + 3, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost thunderx3t110_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of int<->fp moves for spilling. */ + 4, /* GP2FP */ + 5, /* FP2GP */ + 4 /* FP2FP */ +}; + +static const advsimd_vec_cost thunderx3t110_advsimd_vector_cost = +{ + 5, /* int_stmt_cost */ + 5, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 10, /* permute_cost */ + 5, /* reduc_i8_cost */ + 5, /* reduc_i16_cost */ + 5, /* reduc_i32_cost */ + 5, /* reduc_i64_cost */ + 5, /* reduc_f16_cost */ + 5, /* reduc_f32_cost */ + 5, /* reduc_f64_cost */ + 5, /* store_elt_extra_cost */ + 5, /* vec_to_scalar_cost */ + 5, /* scalar_to_vec_cost */ + 4, /* align_load_cost */ + 4, /* unalign_load_cost */ + 4, /* unalign_store_cost */ + 4 /* store_cost */ +}; + +static const struct cpu_vector_cost thunderx3t110_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 5, /* scalar_fp_stmt_cost */ + 4, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 2, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &thunderx3t110_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune thunderx3t110_prefetch_tune = +{ + 8, /* num_slots */ + 32, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 256, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params thunderx3t110_tunings = +{ + &thunderx3t110_extra_costs, + &thunderx3t110_addrcost_table, + &thunderx3t110_regmove_cost, + &thunderx3t110_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 6, /* issue_rate. */ + (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC + | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ + "16", /* function_align. */ + "8", /* jump_align. */ + "16", /* loop_align. */ + 3, /* int_reassoc_width. */ + 2, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 2, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &thunderx3t110_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_THUNDERX3T110. */ diff --git a/gcc/config/aarch64/tuning_models/thunderxt88.h b/gcc/config/aarch64/tuning_models/thunderxt88.h new file mode 100644 index 0000000..dcc74d3 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/thunderxt88.h @@ -0,0 +1,72 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_THUNDERXT88 +#define GCC_AARCH64_H_THUNDERXT88 + +#include "generic.h" +#include "thunderx.h" + +static const cpu_prefetch_tune thunderxt88_prefetch_tune = +{ + 8, /* num_slots */ + 32, /* l1_cache_size */ + 128, /* l1_cache_line_size */ + 16*1024, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + 3 /* default_opt_level */ +}; + +static const struct tune_params thunderxt88_tunings = +{ + &thunderx_extra_costs, + &generic_addrcost_table, + &thunderx_regmove_cost, + &thunderx_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 6, /* load_int. */ + 6, /* store_int. */ + 6, /* load_fp. */ + 6, /* store_fp. */ + 6, /* load_pred. */ + 6 /* store_pred. */ + }, /* memmov_cost. */ + 2, /* issue_rate */ + AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ + "8", /* function_align. */ + "8", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &thunderxt88_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALIGNED, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALIGNED /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_THUNDERXT88. */ diff --git a/gcc/config/aarch64/tuning_models/tsv110.h b/gcc/config/aarch64/tuning_models/tsv110.h new file mode 100644 index 0000000..42aeafc --- /dev/null +++ b/gcc/config/aarch64/tuning_models/tsv110.h @@ -0,0 +1,137 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_TSV110 +#define GCC_AARCH64_H_TSV110 + +#include "generic.h" + +static const struct cpu_addrcost_table tsv110_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 0, /* pre_modify */ + 0, /* post_modify */ + 0, /* post_modify_ld3_st3 */ + 0, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 1, /* register_sextend */ + 1, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost tsv110_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 2, /* GP2FP */ + 3, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost tsv110_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 3, /* reduc_i8_cost */ + 3, /* reduc_i16_cost */ + 3, /* reduc_i32_cost */ + 3, /* reduc_i64_cost */ + 3, /* reduc_f16_cost */ + 3, /* reduc_f32_cost */ + 3, /* reduc_f64_cost */ + 3, /* store_elt_extra_cost */ + 3, /* vec_to_scalar_cost */ + 2, /* scalar_to_vec_cost */ + 5, /* align_load_cost */ + 5, /* unalign_load_cost */ + 1, /* unalign_store_cost */ + 1 /* store_cost */ +}; + +static const struct cpu_vector_cost tsv110_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 5, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 1, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &tsv110_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +static const cpu_prefetch_tune tsv110_prefetch_tune = +{ + 0, /* num_slots */ + 64, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 512, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params tsv110_tunings = +{ + &tsv110_extra_costs, + &tsv110_addrcost_table, + &tsv110_regmove_cost, + &tsv110_vector_cost, + &generic_branch_cost, + &generic_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 4, /* load_int. */ + 4, /* store_int. */ + 4, /* load_fp. */ + 4, /* store_fp. */ + 4, /* load_pred. */ + 4 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH + | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ + "16", /* function_align. */ + "4", /* jump_align. */ + "8", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 0, /* max_case_values. */ + tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ + &tsv110_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_TSV110. */ diff --git a/gcc/config/aarch64/tuning_models/xgene1.h b/gcc/config/aarch64/tuning_models/xgene1.h new file mode 100644 index 0000000..53a3eb0 --- /dev/null +++ b/gcc/config/aarch64/tuning_models/xgene1.h @@ -0,0 +1,145 @@ +/* Tuning model description for AArch64 architecture. + Copyright (C) 2009-2023 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_AARCH64_H_XGENE1 +#define GCC_AARCH64_H_XGENE1 + +#include "generic.h" + +static const struct cpu_addrcost_table xgene1_addrcost_table = +{ + { + 1, /* hi */ + 0, /* si */ + 0, /* di */ + 1, /* ti */ + }, + 1, /* pre_modify */ + 1, /* post_modify */ + 1, /* post_modify_ld3_st3 */ + 1, /* post_modify_ld4_st4 */ + 0, /* register_offset */ + 1, /* register_sextend */ + 1, /* register_zextend */ + 0, /* imm_offset */ +}; + +static const struct cpu_regmove_cost xgene1_regmove_cost = +{ + 1, /* GP2GP */ + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + 8, /* GP2FP */ + 8, /* FP2GP */ + 2 /* FP2FP */ +}; + +static const advsimd_vec_cost xgene1_advsimd_vector_cost = +{ + 2, /* int_stmt_cost */ + 2, /* fp_stmt_cost */ + 0, /* ld2_st2_permute_cost */ + 0, /* ld3_st3_permute_cost */ + 0, /* ld4_st4_permute_cost */ + 2, /* permute_cost */ + 4, /* reduc_i8_cost */ + 4, /* reduc_i16_cost */ + 4, /* reduc_i32_cost */ + 4, /* reduc_i64_cost */ + 4, /* reduc_f16_cost */ + 4, /* reduc_f32_cost */ + 4, /* reduc_f64_cost */ + 4, /* store_elt_extra_cost */ + 4, /* vec_to_scalar_cost */ + 4, /* scalar_to_vec_cost */ + 10, /* align_load_cost */ + 10, /* unalign_load_cost */ + 2, /* unalign_store_cost */ + 2 /* store_cost */ +}; + +/* Generic costs for vector insn classes. */ +static const struct cpu_vector_cost xgene1_vector_cost = +{ + 1, /* scalar_int_stmt_cost */ + 1, /* scalar_fp_stmt_cost */ + 5, /* scalar_load_cost */ + 1, /* scalar_store_cost */ + 2, /* cond_taken_branch_cost */ + 1, /* cond_not_taken_branch_cost */ + &xgene1_advsimd_vector_cost, /* advsimd */ + nullptr, /* sve */ + nullptr /* issue_info */ +}; + +/* Approximation modes for X-Gene 1. */ +static const cpu_approx_modes xgene1_approx_modes = +{ + AARCH64_APPROX_NONE, /* division */ + AARCH64_APPROX_NONE, /* sqrt */ + AARCH64_APPROX_ALL /* recip_sqrt */ +}; + +static const cpu_prefetch_tune xgene1_prefetch_tune = +{ + 8, /* num_slots */ + 32, /* l1_cache_size */ + 64, /* l1_cache_line_size */ + 256, /* l2_cache_size */ + true, /* prefetch_dynamic_strides */ + -1, /* minimum_stride */ + -1 /* default_opt_level */ +}; + +static const struct tune_params xgene1_tunings = +{ + &xgene1_extra_costs, + &xgene1_addrcost_table, + &xgene1_regmove_cost, + &xgene1_vector_cost, + &generic_branch_cost, + &xgene1_approx_modes, + SVE_NOT_IMPLEMENTED, /* sve_width */ + { 6, /* load_int. */ + 6, /* store_int. */ + 6, /* load_fp. */ + 6, /* store_fp. */ + 6, /* load_pred. */ + 6 /* store_pred. */ + }, /* memmov_cost. */ + 4, /* issue_rate */ + AARCH64_FUSE_NOTHING, /* fusible_ops */ + "16", /* function_align. */ + "16", /* jump_align. */ + "16", /* loop_align. */ + 2, /* int_reassoc_width. */ + 4, /* fp_reassoc_width. */ + 1, /* fma_reassoc_width. */ + 1, /* vec_reassoc_width. */ + 2, /* min_div_recip_mul_sf. */ + 2, /* min_div_recip_mul_df. */ + 17, /* max_case_values. */ + tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ + (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ + &xgene1_prefetch_tune, + AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */ + AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */ +}; + +#endif /* GCC_AARCH64_H_XGENE1. */ diff --git a/gcc/config/arm/arm-builtins.cc b/gcc/config/arm/arm-builtins.cc index fca7dca..dd9c581 100644 --- a/gcc/config/arm/arm-builtins.cc +++ b/gcc/config/arm/arm-builtins.cc @@ -1580,20 +1580,20 @@ arm_init_simd_builtin_types (void) TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false; } /* Init all the element types built by the front-end. */ - arm_simd_types[Int8x8_t].eltype = intQI_type_node; - arm_simd_types[Int8x16_t].eltype = intQI_type_node; - arm_simd_types[Int16x4_t].eltype = intHI_type_node; - arm_simd_types[Int16x8_t].eltype = intHI_type_node; - arm_simd_types[Int32x2_t].eltype = intSI_type_node; - arm_simd_types[Int32x4_t].eltype = intSI_type_node; - arm_simd_types[Int64x2_t].eltype = intDI_type_node; - arm_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node; - arm_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node; - arm_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node; - arm_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node; - arm_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node; - arm_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node; - arm_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node; + arm_simd_types[Int8x8_t].eltype = get_typenode_from_name (INT8_TYPE); + arm_simd_types[Int8x16_t].eltype = get_typenode_from_name (INT8_TYPE); + arm_simd_types[Int16x4_t].eltype = get_typenode_from_name (INT16_TYPE); + arm_simd_types[Int16x8_t].eltype = get_typenode_from_name (INT16_TYPE); + arm_simd_types[Int32x2_t].eltype = get_typenode_from_name (INT32_TYPE); + arm_simd_types[Int32x4_t].eltype = get_typenode_from_name (INT32_TYPE); + arm_simd_types[Int64x2_t].eltype = get_typenode_from_name (INT64_TYPE); + arm_simd_types[Uint8x8_t].eltype = get_typenode_from_name (UINT8_TYPE); + arm_simd_types[Uint8x16_t].eltype = get_typenode_from_name (UINT8_TYPE); + arm_simd_types[Uint16x4_t].eltype = get_typenode_from_name (UINT16_TYPE); + arm_simd_types[Uint16x8_t].eltype = get_typenode_from_name (UINT16_TYPE); + arm_simd_types[Uint32x2_t].eltype = get_typenode_from_name (UINT32_TYPE); + arm_simd_types[Uint32x4_t].eltype = get_typenode_from_name (UINT32_TYPE); + arm_simd_types[Uint64x2_t].eltype = get_typenode_from_name (UINT64_TYPE); /* Note: poly64x2_t is defined in arm_neon.h, to ensure it gets default mangling. */ diff --git a/gcc/config/arm/arm-mve-builtins-base.cc b/gcc/config/arm/arm-mve-builtins-base.cc index 5478cac..cfe1b95 100644 --- a/gcc/config/arm/arm-mve-builtins-base.cc +++ b/gcc/config/arm/arm-mve-builtins-base.cc @@ -83,6 +83,62 @@ class vuninitializedq_impl : public quiet<function_base> } }; +class vld1_impl : public full_width_access +{ +public: + unsigned int + call_properties (const function_instance &) const override + { + return CP_READ_MEMORY; + } + + rtx + expand (function_expander &e) const override + { + insn_code icode; + if (e.type_suffix (0).float_p) + icode = code_for_mve_vld1q_f(e.vector_mode (0)); + else + { + if (e.type_suffix (0).unsigned_p) + icode = code_for_mve_vld1q(VLD1Q_U, + e.vector_mode (0)); + else + icode = code_for_mve_vld1q(VLD1Q_S, + e.vector_mode (0)); + } + return e.use_contiguous_load_insn (icode); + } +}; + +class vst1_impl : public full_width_access +{ +public: + unsigned int + call_properties (const function_instance &) const override + { + return CP_WRITE_MEMORY; + } + + rtx + expand (function_expander &e) const override + { + insn_code icode; + if (e.type_suffix (0).float_p) + icode = code_for_mve_vst1q_f(e.vector_mode (0)); + else + { + if (e.type_suffix (0).unsigned_p) + icode = code_for_mve_vst1q(VST1Q_U, + e.vector_mode (0)); + else + icode = code_for_mve_vst1q(VST1Q_S, + e.vector_mode (0)); + } + return e.use_contiguous_store_insn (icode); + } +}; + } /* end anonymous namespace */ namespace arm_mve { @@ -290,6 +346,7 @@ FUNCTION (vfmasq, unspec_mve_function_exact_insn, (-1, -1, -1, -1, -1, VFMASQ_N_ FUNCTION (vfmsq, unspec_mve_function_exact_insn, (-1, -1, VFMSQ_F, -1, -1, -1, -1, -1, VFMSQ_M_F, -1, -1, -1)) FUNCTION_WITH_M_N_NO_F (vhaddq, VHADDQ) FUNCTION_WITH_M_N_NO_F (vhsubq, VHSUBQ) +FUNCTION (vld1q, vld1_impl,) FUNCTION_PRED_P_S (vmaxavq, VMAXAVQ) FUNCTION_WITHOUT_N_NO_U_F (vmaxaq, VMAXAQ) FUNCTION_ONLY_F (vmaxnmaq, VMAXNMAQ) @@ -405,6 +462,7 @@ FUNCTION_ONLY_N_NO_F (vshrntq, VSHRNTQ) FUNCTION_ONLY_N_NO_F (vshrq, VSHRQ) FUNCTION_ONLY_N_NO_F (vsliq, VSLIQ) FUNCTION_ONLY_N_NO_F (vsriq, VSRIQ) +FUNCTION (vst1q, vst1_impl,) FUNCTION_WITH_RTX_M_N (vsubq, MINUS, VSUBQ) FUNCTION (vuninitializedq, vuninitializedq_impl,) diff --git a/gcc/config/arm/arm-mve-builtins-base.def b/gcc/config/arm/arm-mve-builtins-base.def index 01dfbde..1687924 100644 --- a/gcc/config/arm/arm-mve-builtins-base.def +++ b/gcc/config/arm/arm-mve-builtins-base.def @@ -47,6 +47,7 @@ DEF_MVE_FUNCTION (vhaddq, binary_opt_n, all_integer, mx_or_none) DEF_MVE_FUNCTION (vhcaddq_rot90, binary, all_signed, mx_or_none) DEF_MVE_FUNCTION (vhcaddq_rot270, binary, all_signed, mx_or_none) DEF_MVE_FUNCTION (vhsubq, binary_opt_n, all_integer, mx_or_none) +DEF_MVE_FUNCTION (vld1q, load, all_integer, none) DEF_MVE_FUNCTION (vmaxaq, binary_maxamina, all_signed, m_or_none) DEF_MVE_FUNCTION (vmaxavq, binary_maxavminav, all_signed, p_or_none) DEF_MVE_FUNCTION (vmaxq, binary, all_integer, mx_or_none) @@ -150,6 +151,7 @@ DEF_MVE_FUNCTION (vshrntq, binary_rshift_narrow, integer_16_32, m_or_none) DEF_MVE_FUNCTION (vshrq, binary_rshift, all_integer, mx_or_none) DEF_MVE_FUNCTION (vsliq, ternary_lshift, all_integer, m_or_none) DEF_MVE_FUNCTION (vsriq, ternary_rshift, all_integer, m_or_none) +DEF_MVE_FUNCTION (vst1q, store, all_integer, none) DEF_MVE_FUNCTION (vsubq, binary_opt_n, all_integer, mx_or_none) DEF_MVE_FUNCTION (vuninitializedq, inherent, all_integer_with_64, none) #undef REQUIRES_FLOAT @@ -182,6 +184,7 @@ DEF_MVE_FUNCTION (veorq, binary, all_float, mx_or_none) DEF_MVE_FUNCTION (vfmaq, ternary_opt_n, all_float, m_or_none) DEF_MVE_FUNCTION (vfmasq, ternary_n, all_float, m_or_none) DEF_MVE_FUNCTION (vfmsq, ternary, all_float, m_or_none) +DEF_MVE_FUNCTION (vld1q, load, all_float, none) DEF_MVE_FUNCTION (vmaxnmaq, binary, all_float, m_or_none) DEF_MVE_FUNCTION (vmaxnmavq, binary_maxvminv, all_float, p_or_none) DEF_MVE_FUNCTION (vmaxnmq, binary, all_float, mx_or_none) @@ -203,6 +206,7 @@ DEF_MVE_FUNCTION (vrndnq, unary, all_float, mx_or_none) DEF_MVE_FUNCTION (vrndpq, unary, all_float, mx_or_none) DEF_MVE_FUNCTION (vrndq, unary, all_float, mx_or_none) DEF_MVE_FUNCTION (vrndxq, unary, all_float, mx_or_none) +DEF_MVE_FUNCTION (vst1q, store, all_float, none) DEF_MVE_FUNCTION (vsubq, binary_opt_n, all_float, mx_or_none) DEF_MVE_FUNCTION (vuninitializedq, inherent, all_float, none) #undef REQUIRES_FLOAT diff --git a/gcc/config/arm/arm-mve-builtins-base.h b/gcc/config/arm/arm-mve-builtins-base.h index c574c32..8c7e5fe 100644 --- a/gcc/config/arm/arm-mve-builtins-base.h +++ b/gcc/config/arm/arm-mve-builtins-base.h @@ -63,6 +63,7 @@ extern const function_base *const vhaddq; extern const function_base *const vhcaddq_rot270; extern const function_base *const vhcaddq_rot90; extern const function_base *const vhsubq; +extern const function_base *const vld1q; extern const function_base *const vmaxaq; extern const function_base *const vmaxavq; extern const function_base *const vmaxnmaq; @@ -103,8 +104,8 @@ extern const function_base *const vmovnbq; extern const function_base *const vmovntq; extern const function_base *const vmulhq; extern const function_base *const vmullbq_int; -extern const function_base *const vmulltq_int; extern const function_base *const vmullbq_poly; +extern const function_base *const vmulltq_int; extern const function_base *const vmulltq_poly; extern const function_base *const vmulq; extern const function_base *const vmvnq; @@ -178,6 +179,7 @@ extern const function_base *const vshrntq; extern const function_base *const vshrq; extern const function_base *const vsliq; extern const function_base *const vsriq; +extern const function_base *const vst1q; extern const function_base *const vsubq; extern const function_base *const vuninitializedq; diff --git a/gcc/config/arm/arm-mve-builtins-functions.h b/gcc/config/arm/arm-mve-builtins-functions.h index eba1f07..1c93e64 100644 --- a/gcc/config/arm/arm-mve-builtins-functions.h +++ b/gcc/config/arm/arm-mve-builtins-functions.h @@ -966,6 +966,64 @@ public: } }; +/* A function_base that sometimes or always operates on tuples of + vectors. */ +class multi_vector_function : public function_base +{ +public: + CONSTEXPR multi_vector_function (unsigned int vectors_per_tuple) + : m_vectors_per_tuple (vectors_per_tuple) {} + + unsigned int + vectors_per_tuple () const override + { + return m_vectors_per_tuple; + } + + /* The number of vectors in a tuple, or 1 if the function only operates + on single vectors. */ + unsigned int m_vectors_per_tuple; +}; + +/* A function_base that loads or stores contiguous memory elements + without extending or truncating them. */ +class full_width_access : public multi_vector_function +{ +public: + CONSTEXPR full_width_access (unsigned int vectors_per_tuple = 1) + : multi_vector_function (vectors_per_tuple) {} + + tree + memory_scalar_type (const function_instance &fi) const override + { + return fi.scalar_type (0); + } + + machine_mode + memory_vector_mode (const function_instance &fi) const override + { + machine_mode mode = fi.vector_mode (0); + /* Vectors of floating-point are managed in memory as vectors of + integers. */ + switch (mode) + { + case E_V4SFmode: + mode = E_V4SImode; + break; + case E_V8HFmode: + mode = E_V8HImode; + break; + default: + break; + } + + if (m_vectors_per_tuple != 1) + mode = targetm.array_mode (mode, m_vectors_per_tuple).require (); + + return mode; + } +}; + } /* end namespace arm_mve */ /* Declare the global function base NAME, creating it from an instance diff --git a/gcc/config/arm/arm-mve-builtins-shapes.cc b/gcc/config/arm/arm-mve-builtins-shapes.cc index 23eb9d0..fe983e7 100644 --- a/gcc/config/arm/arm-mve-builtins-shapes.cc +++ b/gcc/config/arm/arm-mve-builtins-shapes.cc @@ -39,6 +39,13 @@ namespace arm_mve { +/* Return a representation of "const T *". */ +static tree +build_const_pointer (tree t) +{ + return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST)); +} + /* If INSTANCE has a predicate, add it to the list of argument types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the function. */ @@ -140,6 +147,9 @@ parse_element_type (const function_instance &instance, const char *&format) /* Read and return a type from FORMAT for function INSTANCE. Advance FORMAT beyond the type string. The format is: + _ - void + al - array pointer for loads + as - array pointer for stores p - predicates with type mve_pred16_t s<elt> - a scalar type with the given element suffix t<elt> - a vector or tuple type with given element suffix [*1] @@ -156,6 +166,21 @@ parse_type (const function_instance &instance, const char *&format) { int ch = *format++; + + if (ch == '_') + return void_type_node; + + if (ch == 'a') + { + ch = *format++; + if (ch == 'l') + return build_const_pointer (instance.memory_scalar_type ()); + if (ch == 's') { + return build_pointer_type (instance.memory_scalar_type ()); + } + gcc_unreachable (); + } + if (ch == 'p') return get_mve_pred16_t (); @@ -1403,6 +1428,38 @@ struct inherent_def : public nonoverloaded_base }; SHAPE (inherent) +/* sv<t0>_t svfoo[_t0](const <t0>_t *) + + Example: vld1q. + int8x16_t [__arm_]vld1q[_s8](int8_t const *base) + int8x16_t [__arm_]vld1q_z[_s8](int8_t const *base, mve_pred16_t p) */ +struct load_def : public overloaded_base<0> +{ + void + build (function_builder &b, const function_group_info &group, + bool preserve_user_namespace) const override + { + b.add_overloaded_functions (group, MODE_none, preserve_user_namespace); + build_all (b, "t0,al", group, MODE_none, preserve_user_namespace); + } + + /* Resolve a call based purely on a pointer argument. */ + tree + resolve (function_resolver &r) const override + { + gcc_assert (r.mode_suffix_id == MODE_none); + + unsigned int i, nargs; + type_suffix_index type; + if (!r.check_gp_argument (1, i, nargs) + || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES) + return error_mark_node; + + return r.resolve_to (r.mode_suffix_id, type); + } +}; +SHAPE (load) + /* <T0>_t vfoo[_t0](<T0>_t) <T0>_t vfoo_n_t0(<sT0>_t) @@ -1452,6 +1509,41 @@ struct mvn_def : public overloaded_base<0> }; SHAPE (mvn) +/* void vfoo[_t0](<X>_t *, v<t0>[xN]_t) + + where <X> might be tied to <t0> (for non-truncating stores) or might + depend on the function base name (for truncating stores). + + Example: vst1q. + void [__arm_]vst1q[_s8](int8_t *base, int8x16_t value) + void [__arm_]vst1q_p[_s8](int8_t *base, int8x16_t value, mve_pred16_t p) */ +struct store_def : public overloaded_base<0> +{ + void + build (function_builder &b, const function_group_info &group, + bool preserve_user_namespace) const override + { + b.add_overloaded_functions (group, MODE_none, preserve_user_namespace); + build_all (b, "_,as,v0", group, MODE_none, preserve_user_namespace); + } + + tree + resolve (function_resolver &r) const override + { + gcc_assert (r.mode_suffix_id == MODE_none); + + unsigned int i, nargs; + type_suffix_index type; + if (!r.check_gp_argument (2, i, nargs) + || !r.require_pointer_type (0) + || (type = r.infer_vector_type (1)) == NUM_TYPE_SUFFIXES) + return error_mark_node; + + return r.resolve_to (r.mode_suffix_id, type); + } +}; +SHAPE (store) + /* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, <T0>_t) i.e. the standard shape for ternary operations that operate on diff --git a/gcc/config/arm/arm-mve-builtins-shapes.h b/gcc/config/arm/arm-mve-builtins-shapes.h index a932453..aa9309d 100644 --- a/gcc/config/arm/arm-mve-builtins-shapes.h +++ b/gcc/config/arm/arm-mve-builtins-shapes.h @@ -61,7 +61,9 @@ namespace arm_mve extern const function_shape *const cmp; extern const function_shape *const create; extern const function_shape *const inherent; + extern const function_shape *const load; extern const function_shape *const mvn; + extern const function_shape *const store; extern const function_shape *const ternary; extern const function_shape *const ternary_lshift; extern const function_shape *const ternary_n; diff --git a/gcc/config/arm/arm-mve-builtins.cc b/gcc/config/arm/arm-mve-builtins.cc index 02dc8fa..dec163d 100644 --- a/gcc/config/arm/arm-mve-builtins.cc +++ b/gcc/config/arm/arm-mve-builtins.cc @@ -36,6 +36,7 @@ #include "fold-const.h" #include "gimple.h" #include "gimple-iterator.h" +#include "explow.h" #include "emit-rtl.h" #include "langhooks.h" #include "stringpool.h" @@ -529,6 +530,22 @@ matches_type_p (const_tree model_type, const_tree candidate) && TYPE_MAIN_VARIANT (model_type) == TYPE_MAIN_VARIANT (candidate)); } +/* If TYPE is a valid MVE element type, return the corresponding type + suffix, otherwise return NUM_TYPE_SUFFIXES. */ +static type_suffix_index +find_type_suffix_for_scalar_type (const_tree type) +{ + /* A linear search should be OK here, since the code isn't hot and + the number of types is only small. */ + for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i) + { + vector_type_index vector_i = type_suffixes[suffix_i].vector_type; + if (matches_type_p (scalar_types[vector_i], type)) + return type_suffix_index (suffix_i); + } + return NUM_TYPE_SUFFIXES; +} + /* Report an error against LOCATION that the user has tried to use a floating point function when the mve.fp extension is disabled. */ static void @@ -1125,6 +1142,36 @@ function_resolver::resolve_to (mode_suffix_index mode, return res; } +/* Require argument ARGNO to be a pointer to a scalar type that has a + corresponding type suffix. Return that type suffix on success, + otherwise report an error and return NUM_TYPE_SUFFIXES. */ +type_suffix_index +function_resolver::infer_pointer_type (unsigned int argno) +{ + tree actual = get_argument_type (argno); + if (actual == error_mark_node) + return NUM_TYPE_SUFFIXES; + + if (TREE_CODE (actual) != POINTER_TYPE) + { + error_at (location, "passing %qT to argument %d of %qE, which" + " expects a pointer type", actual, argno + 1, fndecl); + return NUM_TYPE_SUFFIXES; + } + + tree target = TREE_TYPE (actual); + type_suffix_index type = find_type_suffix_for_scalar_type (target); + if (type == NUM_TYPE_SUFFIXES) + { + error_at (location, "passing %qT to argument %d of %qE, but %qT is not" + " a valid MVE element type", actual, argno + 1, fndecl, + build_qualified_type (target, 0)); + return NUM_TYPE_SUFFIXES; + } + + return type; +} + /* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS vectors; NUM_VECTORS is 1 for the former. Return the associated type suffix on success, using TYPE_SUFFIX_b for predicates. Report an error @@ -1498,6 +1545,22 @@ function_resolver::require_scalar_type (unsigned int argno, return true; } +/* Require argument ARGNO to be some form of pointer, without being specific + about its target type. Return true if the argument has the right form, + otherwise report an appropriate error. */ +bool +function_resolver::require_pointer_type (unsigned int argno) +{ + if (!scalar_argument_p (argno)) + { + error_at (location, "passing %qT to argument %d of %qE, which" + " expects a scalar pointer", get_argument_type (argno), + argno + 1, fndecl); + return false; + } + return true; +} + /* Require the function to have exactly EXPECTED arguments. Return true if it does, otherwise report an appropriate error. */ bool @@ -1955,6 +2018,14 @@ function_expander::direct_optab_handler (optab op, unsigned int suffix_i) return ::direct_optab_handler (op, vector_mode (suffix_i)); } +/* Return the base address for a contiguous load or store + function. */ +rtx +function_expander::get_contiguous_base () +{ + return args[0]; +} + /* For a function that does the equivalent of: OUTPUT = COND ? FN (INPUTS) : FALLBACK; @@ -2043,6 +2114,26 @@ function_expander::add_integer_operand (HOST_WIDE_INT x) create_integer_operand (&m_ops.last (), x); } +/* Add a memory operand with mode MODE and address ADDR. */ +void +function_expander::add_mem_operand (machine_mode mode, rtx addr) +{ + gcc_assert (VECTOR_MODE_P (mode)); + rtx mem = gen_rtx_MEM (mode, memory_address (mode, addr)); + /* The memory is only guaranteed to be element-aligned. */ + set_mem_align (mem, GET_MODE_ALIGNMENT (GET_MODE_INNER (mode))); + add_fixed_operand (mem); +} + +/* Add an operand that must be X. The only way of legitimizing an + invalid X is to reload the address of a MEM. */ +void +function_expander::add_fixed_operand (rtx x) +{ + m_ops.safe_grow (m_ops.length () + 1, true); + create_fixed_operand (&m_ops.last (), x); +} + /* Generate instruction ICODE, given that its operands have already been added to M_OPS. Return the value of the first operand. */ rtx @@ -2137,6 +2228,30 @@ function_expander::use_cond_insn (insn_code icode, unsigned int merge_argno) return generate_insn (icode); } +/* Implement the call using instruction ICODE, which loads memory operand 1 + into register operand 0. */ +rtx +function_expander::use_contiguous_load_insn (insn_code icode) +{ + machine_mode mem_mode = memory_vector_mode (); + + add_output_operand (icode); + add_mem_operand (mem_mode, get_contiguous_base ()); + return generate_insn (icode); +} + +/* Implement the call using instruction ICODE, which stores register operand 1 + into memory operand 0. */ +rtx +function_expander::use_contiguous_store_insn (insn_code icode) +{ + machine_mode mem_mode = memory_vector_mode (); + + add_mem_operand (mem_mode, get_contiguous_base ()); + add_input_operand (icode, args[1]); + return generate_insn (icode); +} + /* Implement the call using a normal unpredicated optab for PRED_none. <optab> corresponds to: diff --git a/gcc/config/arm/arm-mve-builtins.def b/gcc/config/arm/arm-mve-builtins.def index e2cf1ba..a901d82 100644 --- a/gcc/config/arm/arm-mve-builtins.def +++ b/gcc/config/arm/arm-mve-builtins.def @@ -39,14 +39,14 @@ DEF_MVE_MODE (r, none, none, none) #define REQUIRES_FLOAT false DEF_MVE_TYPE (mve_pred16_t, boolean_type_node) -DEF_MVE_TYPE (uint8x16_t, unsigned_intQI_type_node) -DEF_MVE_TYPE (uint16x8_t, unsigned_intHI_type_node) -DEF_MVE_TYPE (uint32x4_t, unsigned_intSI_type_node) -DEF_MVE_TYPE (uint64x2_t, unsigned_intDI_type_node) -DEF_MVE_TYPE (int8x16_t, intQI_type_node) -DEF_MVE_TYPE (int16x8_t, intHI_type_node) -DEF_MVE_TYPE (int32x4_t, intSI_type_node) -DEF_MVE_TYPE (int64x2_t, intDI_type_node) +DEF_MVE_TYPE (uint8x16_t, get_typenode_from_name (UINT8_TYPE)) +DEF_MVE_TYPE (uint16x8_t, get_typenode_from_name (UINT16_TYPE)) +DEF_MVE_TYPE (uint32x4_t, get_typenode_from_name (UINT32_TYPE)) +DEF_MVE_TYPE (uint64x2_t, get_typenode_from_name (UINT64_TYPE)) +DEF_MVE_TYPE (int8x16_t, get_typenode_from_name (INT8_TYPE)) +DEF_MVE_TYPE (int16x8_t, get_typenode_from_name (INT16_TYPE)) +DEF_MVE_TYPE (int32x4_t, get_typenode_from_name (INT32_TYPE)) +DEF_MVE_TYPE (int64x2_t, get_typenode_from_name (INT64_TYPE)) #undef REQUIRES_FLOAT #define REQUIRES_FLOAT true diff --git a/gcc/config/arm/arm-mve-builtins.h b/gcc/config/arm/arm-mve-builtins.h index 37b8223..9c219fa 100644 --- a/gcc/config/arm/arm-mve-builtins.h +++ b/gcc/config/arm/arm-mve-builtins.h @@ -277,6 +277,8 @@ public: bool could_trap_p () const; unsigned int vectors_per_tuple () const; + tree memory_scalar_type () const; + machine_mode memory_vector_mode () const; const mode_suffix_info &mode_suffix () const; @@ -382,6 +384,7 @@ public: type_suffix_index = NUM_TYPE_SUFFIXES, type_suffix_index = NUM_TYPE_SUFFIXES); + type_suffix_index infer_pointer_type (unsigned int); type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int); type_suffix_index infer_vector_type (unsigned int); @@ -393,8 +396,9 @@ public: type_suffix_index, type_class_index = SAME_TYPE_CLASS, unsigned int = SAME_SIZE); - bool require_integer_immediate (unsigned int); bool require_scalar_type (unsigned int, const char *); + bool require_pointer_type (unsigned int); + bool require_integer_immediate (unsigned int); bool require_derived_scalar_type (unsigned int, type_class_index, unsigned int = SAME_SIZE); @@ -475,18 +479,23 @@ public: insn_code direct_optab_handler (optab, unsigned int = 0); + rtx get_contiguous_base (); rtx get_fallback_value (machine_mode, unsigned int, unsigned int &); rtx get_reg_target (); void add_output_operand (insn_code); void add_input_operand (insn_code, rtx); void add_integer_operand (HOST_WIDE_INT); + void add_mem_operand (machine_mode, rtx); + void add_fixed_operand (rtx); rtx generate_insn (insn_code); rtx use_exact_insn (insn_code); rtx use_unpred_insn (insn_code); rtx use_pred_x_insn (insn_code); rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO); + rtx use_contiguous_load_insn (insn_code); + rtx use_contiguous_store_insn (insn_code); rtx map_to_rtx_codes (rtx_code, rtx_code, rtx_code); @@ -519,6 +528,23 @@ public: of vectors in the tuples, otherwise return 1. */ virtual unsigned int vectors_per_tuple () const { return 1; } + /* If the function addresses memory, return the type of a single + scalar memory element. */ + virtual tree + memory_scalar_type (const function_instance &) const + { + gcc_unreachable (); + } + + /* If the function addresses memory, return a vector mode whose + GET_MODE_NUNITS is the number of elements addressed and whose + GET_MODE_INNER is the mode of a single scalar memory element. */ + virtual machine_mode + memory_vector_mode (const function_instance &) const + { + gcc_unreachable (); + } + /* Try to fold the given gimple call. Return the new gimple statement on success, otherwise return null. */ virtual gimple *fold (gimple_folder &) const { return NULL; } @@ -644,6 +670,23 @@ function_instance::vectors_per_tuple () const return base->vectors_per_tuple (); } +/* If the function addresses memory, return the type of a single + scalar memory element. */ +inline tree +function_instance::memory_scalar_type () const +{ + return base->memory_scalar_type (*this); +} + +/* If the function addresses memory, return a vector mode whose + GET_MODE_NUNITS is the number of elements addressed and whose + GET_MODE_INNER is the mode of a single scalar memory element. */ +inline machine_mode +function_instance::memory_vector_mode () const +{ + return base->memory_vector_mode (*this); +} + /* Return information about the function's mode suffix. */ inline const mode_suffix_info & function_instance::mode_suffix () const diff --git a/gcc/config/arm/arm_mve.h b/gcc/config/arm/arm_mve.h index b82d94e..cc027f9 100644 --- a/gcc/config/arm/arm_mve.h +++ b/gcc/config/arm/arm_mve.h @@ -56,7 +56,6 @@ #define vstrbq_scatter_offset_p(__base, __offset, __value, __p) __arm_vstrbq_scatter_offset_p(__base, __offset, __value, __p) #define vstrwq_scatter_base_p(__addr, __offset, __value, __p) __arm_vstrwq_scatter_base_p(__addr, __offset, __value, __p) #define vldrbq_gather_offset_z(__base, __offset, __p) __arm_vldrbq_gather_offset_z(__base, __offset, __p) -#define vld1q(__base) __arm_vld1q(__base) #define vldrhq_gather_offset(__base, __offset) __arm_vldrhq_gather_offset(__base, __offset) #define vldrhq_gather_offset_z(__base, __offset, __p) __arm_vldrhq_gather_offset_z(__base, __offset, __p) #define vldrhq_gather_shifted_offset(__base, __offset) __arm_vldrhq_gather_shifted_offset(__base, __offset) @@ -69,7 +68,6 @@ #define vldrwq_gather_offset_z(__base, __offset, __p) __arm_vldrwq_gather_offset_z(__base, __offset, __p) #define vldrwq_gather_shifted_offset(__base, __offset) __arm_vldrwq_gather_shifted_offset(__base, __offset) #define vldrwq_gather_shifted_offset_z(__base, __offset, __p) __arm_vldrwq_gather_shifted_offset_z(__base, __offset, __p) -#define vst1q(__addr, __value) __arm_vst1q(__addr, __value) #define vstrhq_scatter_offset(__base, __offset, __value) __arm_vstrhq_scatter_offset(__base, __offset, __value) #define vstrhq_scatter_offset_p(__base, __offset, __value, __p) __arm_vstrhq_scatter_offset_p(__base, __offset, __value, __p) #define vstrhq_scatter_shifted_offset(__base, __offset, __value) __arm_vstrhq_scatter_shifted_offset(__base, __offset, __value) @@ -346,12 +344,6 @@ #define vldrbq_z_u32(__base, __p) __arm_vldrbq_z_u32(__base, __p) #define vldrwq_gather_base_z_u32(__addr, __offset, __p) __arm_vldrwq_gather_base_z_u32(__addr, __offset, __p) #define vldrwq_gather_base_z_s32(__addr, __offset, __p) __arm_vldrwq_gather_base_z_s32(__addr, __offset, __p) -#define vld1q_s8(__base) __arm_vld1q_s8(__base) -#define vld1q_s32(__base) __arm_vld1q_s32(__base) -#define vld1q_s16(__base) __arm_vld1q_s16(__base) -#define vld1q_u8(__base) __arm_vld1q_u8(__base) -#define vld1q_u32(__base) __arm_vld1q_u32(__base) -#define vld1q_u16(__base) __arm_vld1q_u16(__base) #define vldrhq_gather_offset_s32(__base, __offset) __arm_vldrhq_gather_offset_s32(__base, __offset) #define vldrhq_gather_offset_s16(__base, __offset) __arm_vldrhq_gather_offset_s16(__base, __offset) #define vldrhq_gather_offset_u32(__base, __offset) __arm_vldrhq_gather_offset_u32(__base, __offset) @@ -380,8 +372,6 @@ #define vldrwq_u32(__base) __arm_vldrwq_u32(__base) #define vldrwq_z_s32(__base, __p) __arm_vldrwq_z_s32(__base, __p) #define vldrwq_z_u32(__base, __p) __arm_vldrwq_z_u32(__base, __p) -#define vld1q_f32(__base) __arm_vld1q_f32(__base) -#define vld1q_f16(__base) __arm_vld1q_f16(__base) #define vldrhq_f16(__base) __arm_vldrhq_f16(__base) #define vldrhq_z_f16(__base, __p) __arm_vldrhq_z_f16(__base, __p) #define vldrwq_f32(__base) __arm_vldrwq_f32(__base) @@ -416,14 +406,6 @@ #define vldrwq_gather_shifted_offset_z_f32(__base, __offset, __p) __arm_vldrwq_gather_shifted_offset_z_f32(__base, __offset, __p) #define vldrwq_gather_shifted_offset_z_s32(__base, __offset, __p) __arm_vldrwq_gather_shifted_offset_z_s32(__base, __offset, __p) #define vldrwq_gather_shifted_offset_z_u32(__base, __offset, __p) __arm_vldrwq_gather_shifted_offset_z_u32(__base, __offset, __p) -#define vst1q_f32(__addr, __value) __arm_vst1q_f32(__addr, __value) -#define vst1q_f16(__addr, __value) __arm_vst1q_f16(__addr, __value) -#define vst1q_s8(__addr, __value) __arm_vst1q_s8(__addr, __value) -#define vst1q_s32(__addr, __value) __arm_vst1q_s32(__addr, __value) -#define vst1q_s16(__addr, __value) __arm_vst1q_s16(__addr, __value) -#define vst1q_u8(__addr, __value) __arm_vst1q_u8(__addr, __value) -#define vst1q_u32(__addr, __value) __arm_vst1q_u32(__addr, __value) -#define vst1q_u16(__addr, __value) __arm_vst1q_u16(__addr, __value) #define vstrhq_f16(__addr, __value) __arm_vstrhq_f16(__addr, __value) #define vstrhq_scatter_offset_s32( __base, __offset, __value) __arm_vstrhq_scatter_offset_s32( __base, __offset, __value) #define vstrhq_scatter_offset_s16( __base, __offset, __value) __arm_vstrhq_scatter_offset_s16( __base, __offset, __value) @@ -1537,48 +1519,6 @@ __arm_vldrwq_gather_base_z_u32 (uint32x4_t __addr, const int __offset, mve_pred1 return __builtin_mve_vldrwq_gather_base_z_uv4si (__addr, __offset, __p); } -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_s8 (int8_t const * __base) -{ - return __builtin_mve_vld1q_sv16qi ((__builtin_neon_qi *) __base); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_s32 (int32_t const * __base) -{ - return __builtin_mve_vld1q_sv4si ((__builtin_neon_si *) __base); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_s16 (int16_t const * __base) -{ - return __builtin_mve_vld1q_sv8hi ((__builtin_neon_hi *) __base); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_u8 (uint8_t const * __base) -{ - return __builtin_mve_vld1q_uv16qi ((__builtin_neon_qi *) __base); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_u32 (uint32_t const * __base) -{ - return __builtin_mve_vld1q_uv4si ((__builtin_neon_si *) __base); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_u16 (uint16_t const * __base) -{ - return __builtin_mve_vld1q_uv8hi ((__builtin_neon_hi *) __base); -} - __extension__ extern __inline int32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrhq_gather_offset_s32 (int16_t const * __base, uint32x4_t __offset) @@ -1919,48 +1859,6 @@ __arm_vldrwq_gather_shifted_offset_z_u32 (uint32_t const * __base, uint32x4_t __ __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_s8 (int8_t * __addr, int8x16_t __value) -{ - __builtin_mve_vst1q_sv16qi ((__builtin_neon_qi *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_s32 (int32_t * __addr, int32x4_t __value) -{ - __builtin_mve_vst1q_sv4si ((__builtin_neon_si *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_s16 (int16_t * __addr, int16x8_t __value) -{ - __builtin_mve_vst1q_sv8hi ((__builtin_neon_hi *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_u8 (uint8_t * __addr, uint8x16_t __value) -{ - __builtin_mve_vst1q_uv16qi ((__builtin_neon_qi *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_u32 (uint32_t * __addr, uint32x4_t __value) -{ - __builtin_mve_vst1q_uv4si ((__builtin_neon_si *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_u16 (uint16_t * __addr, uint16x8_t __value) -{ - __builtin_mve_vst1q_uv8hi ((__builtin_neon_hi *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrhq_scatter_offset_s32 (int16_t * __base, uint32x4_t __offset, int32x4_t __value) { __builtin_mve_vstrhq_scatter_offset_sv4si ((__builtin_neon_hi *) __base, __offset, __value); @@ -4423,20 +4321,6 @@ __arm_vornq_m_f16 (float16x8_t __inactive, float16x8_t __a, float16x8_t __b, mve __extension__ extern __inline float32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_f32 (float32_t const * __base) -{ - return __builtin_mve_vld1q_fv4sf((__builtin_neon_si *) __base); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q_f16 (float16_t const * __base) -{ - return __builtin_mve_vld1q_fv8hf((__builtin_neon_hi *) __base); -} - -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrwq_f32 (float32_t const * __base) { return __builtin_mve_vldrwq_fv4sf((__builtin_neon_si *) __base); @@ -4549,20 +4433,6 @@ __arm_vstrwq_f32 (float32_t * __addr, float32x4_t __value) __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_f32 (float32_t * __addr, float32x4_t __value) -{ - __builtin_mve_vst1q_fv4sf ((__builtin_neon_si *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q_f16 (float16_t * __addr, float16x8_t __value) -{ - __builtin_mve_vst1q_fv8hf ((__builtin_neon_hi *) __addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrhq_f16 (float16_t * __addr, float16x8_t __value) { __builtin_mve_vstrhq_fv8hf ((__builtin_neon_hi *) __addr, __value); @@ -5651,48 +5521,6 @@ __arm_vldrbq_gather_offset_z (uint8_t const * __base, uint16x8_t __offset, mve_p return __arm_vldrbq_gather_offset_z_u16 (__base, __offset, __p); } -__extension__ extern __inline int8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (int8_t const * __base) -{ - return __arm_vld1q_s8 (__base); -} - -__extension__ extern __inline int32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (int32_t const * __base) -{ - return __arm_vld1q_s32 (__base); -} - -__extension__ extern __inline int16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (int16_t const * __base) -{ - return __arm_vld1q_s16 (__base); -} - -__extension__ extern __inline uint8x16_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (uint8_t const * __base) -{ - return __arm_vld1q_u8 (__base); -} - -__extension__ extern __inline uint32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (uint32_t const * __base) -{ - return __arm_vld1q_u32 (__base); -} - -__extension__ extern __inline uint16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (uint16_t const * __base) -{ - return __arm_vld1q_u16 (__base); -} - __extension__ extern __inline int32x4_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrhq_gather_offset (int16_t const * __base, uint32x4_t __offset) @@ -5919,48 +5747,6 @@ __arm_vldrwq_gather_shifted_offset_z (uint32_t const * __base, uint32x4_t __offs __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (int8_t * __addr, int8x16_t __value) -{ - __arm_vst1q_s8 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (int32_t * __addr, int32x4_t __value) -{ - __arm_vst1q_s32 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (int16_t * __addr, int16x8_t __value) -{ - __arm_vst1q_s16 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (uint8_t * __addr, uint8x16_t __value) -{ - __arm_vst1q_u8 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (uint32_t * __addr, uint32x4_t __value) -{ - __arm_vst1q_u32 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (uint16_t * __addr, uint16x8_t __value) -{ - __arm_vst1q_u16 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrhq_scatter_offset (int16_t * __base, uint32x4_t __offset, int32x4_t __value) { __arm_vstrhq_scatter_offset_s32 (__base, __offset, __value); @@ -7809,20 +7595,6 @@ __arm_vornq_m (float16x8_t __inactive, float16x8_t __a, float16x8_t __b, mve_pre return __arm_vornq_m_f16 (__inactive, __a, __b, __p); } -__extension__ extern __inline float32x4_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (float32_t const * __base) -{ - return __arm_vld1q_f32 (__base); -} - -__extension__ extern __inline float16x8_t -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vld1q (float16_t const * __base) -{ - return __arm_vld1q_f16 (__base); -} - __extension__ extern __inline float16x8_t __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vldrhq_gather_offset (float16_t const * __base, uint16x8_t __offset) @@ -7895,20 +7667,6 @@ __arm_vstrwq (float32_t * __addr, float32x4_t __value) __extension__ extern __inline void __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (float32_t * __addr, float32x4_t __value) -{ - __arm_vst1q_f32 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) -__arm_vst1q (float16_t * __addr, float16x8_t __value) -{ - __arm_vst1q_f16 (__addr, __value); -} - -__extension__ extern __inline void -__attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) __arm_vstrhq (float16_t * __addr, float16x8_t __value) { __arm_vstrhq_f16 (__addr, __value); @@ -8670,17 +8428,6 @@ extern void *__ARM_undef; int (*)[__ARM_mve_type_float16x8_t][__ARM_mve_type_float16x8_t][__ARM_mve_type_float16x8_t]: __arm_vornq_m_f16 (__ARM_mve_coerce(__p0, float16x8_t), __ARM_mve_coerce(__p1, float16x8_t), __ARM_mve_coerce(__p2, float16x8_t), p3), \ int (*)[__ARM_mve_type_float32x4_t][__ARM_mve_type_float32x4_t][__ARM_mve_type_float32x4_t]: __arm_vornq_m_f32 (__ARM_mve_coerce(__p0, float32x4_t), __ARM_mve_coerce(__p1, float32x4_t), __ARM_mve_coerce(__p2, float32x4_t), p3));}) -#define __arm_vld1q(p0) (\ - _Generic( (int (*)[__ARM_mve_typeid(p0)])0, \ - int (*)[__ARM_mve_type_int8_t_ptr]: __arm_vld1q_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *)), \ - int (*)[__ARM_mve_type_int16_t_ptr]: __arm_vld1q_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *)), \ - int (*)[__ARM_mve_type_int32_t_ptr]: __arm_vld1q_s32 (__ARM_mve_coerce_s32_ptr(p0, int32_t *)), \ - int (*)[__ARM_mve_type_uint8_t_ptr]: __arm_vld1q_u8 (__ARM_mve_coerce_u8_ptr(p0, uint8_t *)), \ - int (*)[__ARM_mve_type_uint16_t_ptr]: __arm_vld1q_u16 (__ARM_mve_coerce_u16_ptr(p0, uint16_t *)), \ - int (*)[__ARM_mve_type_uint32_t_ptr]: __arm_vld1q_u32 (__ARM_mve_coerce_u32_ptr(p0, uint32_t *)), \ - int (*)[__ARM_mve_type_float16_t_ptr]: __arm_vld1q_f16 (__ARM_mve_coerce_f16_ptr(p0, float16_t *)), \ - int (*)[__ARM_mve_type_float32_t_ptr]: __arm_vld1q_f32 (__ARM_mve_coerce_f32_ptr(p0, float32_t *)))) - #define __arm_vld1q_z(p0,p1) ( \ _Generic( (int (*)[__ARM_mve_typeid(p0)])0, \ int (*)[__ARM_mve_type_int8_t_ptr]: __arm_vld1q_z_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *), p1), \ @@ -8792,17 +8539,6 @@ extern void *__ARM_undef; int (*)[__ARM_mve_type_float16_t_ptr][__ARM_mve_type_float16x8x2_t]: __arm_vst2q_f16 (__ARM_mve_coerce_f16_ptr(p0, float16_t *), __ARM_mve_coerce(__p1, float16x8x2_t)), \ int (*)[__ARM_mve_type_float32_t_ptr][__ARM_mve_type_float32x4x2_t]: __arm_vst2q_f32 (__ARM_mve_coerce_f32_ptr(p0, float32_t *), __ARM_mve_coerce(__p1, float32x4x2_t)));}) -#define __arm_vst1q(p0,p1) ({ __typeof(p1) __p1 = (p1); \ - _Generic( (int (*)[__ARM_mve_typeid(p0)][__ARM_mve_typeid(__p1)])0, \ - int (*)[__ARM_mve_type_int8_t_ptr][__ARM_mve_type_int8x16_t]: __arm_vst1q_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *), __ARM_mve_coerce(__p1, int8x16_t)), \ - int (*)[__ARM_mve_type_int16_t_ptr][__ARM_mve_type_int16x8_t]: __arm_vst1q_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *), __ARM_mve_coerce(__p1, int16x8_t)), \ - int (*)[__ARM_mve_type_int32_t_ptr][__ARM_mve_type_int32x4_t]: __arm_vst1q_s32 (__ARM_mve_coerce_s32_ptr(p0, int32_t *), __ARM_mve_coerce(__p1, int32x4_t)), \ - int (*)[__ARM_mve_type_uint8_t_ptr][__ARM_mve_type_uint8x16_t]: __arm_vst1q_u8 (__ARM_mve_coerce_u8_ptr(p0, uint8_t *), __ARM_mve_coerce(__p1, uint8x16_t)), \ - int (*)[__ARM_mve_type_uint16_t_ptr][__ARM_mve_type_uint16x8_t]: __arm_vst1q_u16 (__ARM_mve_coerce_u16_ptr(p0, uint16_t *), __ARM_mve_coerce(__p1, uint16x8_t)), \ - int (*)[__ARM_mve_type_uint32_t_ptr][__ARM_mve_type_uint32x4_t]: __arm_vst1q_u32 (__ARM_mve_coerce_u32_ptr(p0, uint32_t *), __ARM_mve_coerce(__p1, uint32x4_t)), \ - int (*)[__ARM_mve_type_float16_t_ptr][__ARM_mve_type_float16x8_t]: __arm_vst1q_f16 (__ARM_mve_coerce_f16_ptr(p0, float16_t *), __ARM_mve_coerce(__p1, float16x8_t)), \ - int (*)[__ARM_mve_type_float32_t_ptr][__ARM_mve_type_float32x4_t]: __arm_vst1q_f32 (__ARM_mve_coerce_f32_ptr(p0, float32_t *), __ARM_mve_coerce(__p1, float32x4_t)));}) - #define __arm_vstrhq(p0,p1) ({ __typeof(p1) __p1 = (p1); \ _Generic( (int (*)[__ARM_mve_typeid(p0)][__ARM_mve_typeid(__p1)])0, \ int (*)[__ARM_mve_type_int16_t_ptr][__ARM_mve_type_int16x8_t]: __arm_vstrhq_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *), __ARM_mve_coerce(__p1, int16x8_t)), \ @@ -9149,15 +8885,6 @@ extern void *__ARM_undef; int (*)[__ARM_mve_type_int32x4_t]: __arm_vstrwq_scatter_base_p_s32 (p0, p1, __ARM_mve_coerce(__p2, int32x4_t), p3), \ int (*)[__ARM_mve_type_uint32x4_t]: __arm_vstrwq_scatter_base_p_u32 (p0, p1, __ARM_mve_coerce(__p2, uint32x4_t), p3));}) -#define __arm_vld1q(p0) (\ - _Generic( (int (*)[__ARM_mve_typeid(p0)])0, \ - int (*)[__ARM_mve_type_int8_t_ptr]: __arm_vld1q_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *)), \ - int (*)[__ARM_mve_type_int16_t_ptr]: __arm_vld1q_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *)), \ - int (*)[__ARM_mve_type_int32_t_ptr]: __arm_vld1q_s32 (__ARM_mve_coerce_s32_ptr(p0, int32_t *)), \ - int (*)[__ARM_mve_type_uint8_t_ptr]: __arm_vld1q_u8 (__ARM_mve_coerce_u8_ptr(p0, uint8_t *)), \ - int (*)[__ARM_mve_type_uint16_t_ptr]: __arm_vld1q_u16 (__ARM_mve_coerce_u16_ptr(p0, uint16_t *)), \ - int (*)[__ARM_mve_type_uint32_t_ptr]: __arm_vld1q_u32 (__ARM_mve_coerce_u32_ptr(p0, uint32_t *)))) - #define __arm_vldrhq_gather_offset(p0,p1) ({ __typeof(p1) __p1 = (p1); \ _Generic( (int (*)[__ARM_mve_typeid(p0)][__ARM_mve_typeid(__p1)])0, \ int (*)[__ARM_mve_type_int16_t_ptr][__ARM_mve_type_uint16x8_t]: __arm_vldrhq_gather_offset_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *), __ARM_mve_coerce(__p1, uint16x8_t)), \ @@ -9206,15 +8933,6 @@ extern void *__ARM_undef; int (*)[__ARM_mve_type_int32_t_ptr]: __arm_vldrwq_gather_shifted_offset_z_s32 (__ARM_mve_coerce_s32_ptr(__p0, int32_t *), p1, p2), \ int (*)[__ARM_mve_type_uint32_t_ptr]: __arm_vldrwq_gather_shifted_offset_z_u32 (__ARM_mve_coerce_u32_ptr(__p0, uint32_t *), p1, p2));}) -#define __arm_vst1q(p0,p1) ({ __typeof(p1) __p1 = (p1); \ - _Generic( (int (*)[__ARM_mve_typeid(p0)][__ARM_mve_typeid(__p1)])0, \ - int (*)[__ARM_mve_type_int8_t_ptr][__ARM_mve_type_int8x16_t]: __arm_vst1q_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *), __ARM_mve_coerce(__p1, int8x16_t)), \ - int (*)[__ARM_mve_type_int16_t_ptr][__ARM_mve_type_int16x8_t]: __arm_vst1q_s16 (__ARM_mve_coerce_s16_ptr(p0, int16_t *), __ARM_mve_coerce(__p1, int16x8_t)), \ - int (*)[__ARM_mve_type_int32_t_ptr][__ARM_mve_type_int32x4_t]: __arm_vst1q_s32 (__ARM_mve_coerce_s32_ptr(p0, int32_t *), __ARM_mve_coerce(__p1, int32x4_t)), \ - int (*)[__ARM_mve_type_uint8_t_ptr][__ARM_mve_type_uint8x16_t]: __arm_vst1q_u8 (__ARM_mve_coerce_u8_ptr(p0, uint8_t *), __ARM_mve_coerce(__p1, uint8x16_t)), \ - int (*)[__ARM_mve_type_uint16_t_ptr][__ARM_mve_type_uint16x8_t]: __arm_vst1q_u16 (__ARM_mve_coerce_u16_ptr(p0, uint16_t *), __ARM_mve_coerce(__p1, uint16x8_t)), \ - int (*)[__ARM_mve_type_uint32_t_ptr][__ARM_mve_type_uint32x4_t]: __arm_vst1q_u32 (__ARM_mve_coerce_u32_ptr(p0, uint32_t *), __ARM_mve_coerce(__p1, uint32x4_t)));}) - #define __arm_vst1q_p(p0,p1,p2) ({ __typeof(p1) __p1 = (p1); \ _Generic( (int (*)[__ARM_mve_typeid(p0)][__ARM_mve_typeid(__p1)])0, \ int (*)[__ARM_mve_type_int8_t_ptr][__ARM_mve_type_int8x16_t]: __arm_vst1q_p_s8 (__ARM_mve_coerce_s8_ptr(p0, int8_t *), __ARM_mve_coerce(__p1, int8x16_t), p2), \ diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 366cec0..b0d3443 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -3690,7 +3690,7 @@ } [(set_attr "length" "8")]) -(define_expand "mve_vld1q_f<mode>" +(define_expand "@mve_vld1q_f<mode>" [(match_operand:MVE_0 0 "s_register_operand") (unspec:MVE_0 [(match_operand:<MVE_CNVT> 1 "mve_memory_operand")] VLD1Q_F) ] @@ -3700,7 +3700,7 @@ DONE; }) -(define_expand "mve_vld1q_<supf><mode>" +(define_expand "@mve_vld1q_<supf><mode>" [(match_operand:MVE_2 0 "s_register_operand") (unspec:MVE_2 [(match_operand:MVE_2 1 "mve_memory_operand")] VLD1Q) ] @@ -4408,7 +4408,7 @@ } [(set_attr "length" "4")]) -(define_expand "mve_vst1q_f<mode>" +(define_expand "@mve_vst1q_f<mode>" [(match_operand:<MVE_CNVT> 0 "mve_memory_operand") (unspec:<MVE_CNVT> [(match_operand:MVE_0 1 "s_register_operand")] VST1Q_F) ] @@ -4418,7 +4418,7 @@ DONE; }) -(define_expand "mve_vst1q_<supf><mode>" +(define_expand "@mve_vst1q_<supf><mode>" [(match_operand:MVE_2 0 "mve_memory_operand") (unspec:MVE_2 [(match_operand:MVE_2 1 "s_register_operand")] VST1Q) ] diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index c3e0995..a297f4e 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -15309,6 +15309,12 @@ avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code) #undef TARGET_CANONICALIZE_COMPARISON #define TARGET_CANONICALIZE_COMPARISON avr_canonicalize_comparison +/* According to the opening comment in PR86772, the following applies: + "If the port does not (and never will in the future) need to mitigate + against unsafe speculation." */ +#undef TARGET_HAVE_SPECULATION_SAFE_VALUE +#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed + struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/bpf/bpf-helpers.h b/gcc/config/bpf/bpf-helpers.h deleted file mode 100644 index 4a6825c..0000000 --- a/gcc/config/bpf/bpf-helpers.h +++ /dev/null @@ -1,427 +0,0 @@ -/* Copyright (C) 2019-2023 Free Software Foundation, Inc. - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - GCC is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - 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/>. */ - -/* The purpose of this file is to provide a compatiblity layer with - the Linux kernel bpf_helpers.h header that is located in - linux/tools/testing/selftests/bpf/bpf_helpers.h. That file is - currently llvm-specific. */ - -#ifndef __BPF_HELPERS_H -#define __BPF_HELPERS_H - -#define SEC(NAME) __attribute__((section(NAME), used)) -#define KERNEL_HELPER(NUM) __attribute__((kernel_helper(NUM))) - -/* Flags used in some kernel helpers. */ - -#define BPF_ANY 0 -#define BPF_NOEXIST 1 -#define BPF_EXIST 2 - -#define BPF_F_LOCK 4 -#define BPF_F_NO_COMMON_LRU (1U << 1) -#define BPF_F_NUMA_NODE (1U << 2) - -/* Prototypes of functions to call kernel helpers. - Please keep these protoypes sorted by helper number. */ - -void *bpf_map_lookup_elem (void *map, const void *key) - KERNEL_HELPER (1); - -int bpf_map_update_elem (void *map, const void *key, const void *value, - unsigned long long flags) - KERNEL_HELPER (2); - -int bpf_map_delete_elem (void *map, const void *key) - KERNEL_HELPER (3); - -int bpf_probe_read (void *dst, int size, const void *unsafe_ptr) - KERNEL_HELPER (4); - -unsigned long long bpf_ktime_get_ns (void) - KERNEL_HELPER (5); - -int bpf_trace_printk (const char *fmt, int fmt_size, ...) - KERNEL_HELPER (6); - -unsigned long long bpf_get_prandom_u32 (void) - KERNEL_HELPER (7); - -unsigned long long bpf_get_smp_processor_id (void) - KERNEL_HELPER (8); - -int bpf_skb_store_bytes (void *ctx, int off, void *from, int len, - unsigned int start_header) - KERNEL_HELPER (9); - -int bpf_l3_csum_replace (void *ctx, int off, int from, int to, int flags) - KERNEL_HELPER (10); - -int bpf_l4_csum_replace (void *ctx, int off, int from, int to, int flags) - KERNEL_HELPER (11); - -int bpf_tail_call (void *ctx, void *map, unsigned int index) - KERNEL_HELPER (12); - -int bpf_clone_redirect (void *ctx, int ifindex, int flags) - KERNEL_HELPER (13); - -unsigned long long bpf_get_current_pid_tgid (void) - KERNEL_HELPER (14); - -unsigned long long bpf_get_current_uid_gid (void) - KERNEL_HELPER (15); - -int bpf_get_current_comm (void *buf, int buf_size) - KERNEL_HELPER (16); - -unsigned int bpf_get_cgroup_classid (void *ctx) - KERNEL_HELPER (17); - -int bpf_skb_vlan_push (void *ctx, short vlan_proto, - unsigned short vlan_tci) - KERNEL_HELPER (18); - -int bpf_skb_vlan_pop (void *ctx) - KERNEL_HELPER (19); - -int bpf_skb_get_tunnel_key (void *ctx, void *key, int size, int flags) - KERNEL_HELPER (20); - -int bpf_skb_set_tunnel_key (void *ctx, void *key, int size, int flags) - KERNEL_HELPER (21); - -unsigned long long bpf_perf_event_read (void *map, unsigned long long flags) - KERNEL_HELPER (22); - -int bpf_redirect (int ifindex, int flags) - KERNEL_HELPER (23); - -unsigned int bpf_get_route_realm (void *ctx) - KERNEL_HELPER (24); - -int bpf_perf_event_output (void *ctx, void *map, unsigned long long flags, - void *data, int size) - KERNEL_HELPER (25); - -int bpf_skb_load_bytes (void *ctx, int off, void *to, int len) - KERNEL_HELPER (26); - -int bpf_get_stackid (void *ctx, void *map, int flags) - KERNEL_HELPER (27); - -int bpf_csum_diff (void *from, int from_size, void *to, int to_size, int seed) - KERNEL_HELPER (28); - -int bpf_skb_get_tunnel_opt (void *ctx, void *md, int size) - KERNEL_HELPER (29); - -int bpf_skb_set_tunnel_opt (void *ctx, void *md, int size) - KERNEL_HELPER (30); - -int bpf_skb_change_proto (void *ctx, short proto, unsigned long flags) - KERNEL_HELPER (31); - -int bpf_skb_change_type (void *ctx, unsigned int type) - KERNEL_HELPER (32); - -int bpf_skb_under_cgroup (void *ctx, void *map, int index) - KERNEL_HELPER (33); - -unsigned int bpf_get_hash_recalc (void *ctx) - KERNEL_HELPER (34); - -unsigned long long bpf_get_current_task (void) - KERNEL_HELPER (35); - -int bpf_probe_write_user (void *dst, const void *src, int size) - KERNEL_HELPER (36); - -int bpf_current_task_under_cgroup (void *map, int index) - KERNEL_HELPER (37); - -int bpf_skb_change_tail (void *ctx, unsigned int len, unsigned long flags) - KERNEL_HELPER (38); - -int bpf_skb_pull_data (void *, int len) - KERNEL_HELPER (39); - -long long bpf_csum_update (void *ctx, unsigned int csum) - KERNEL_HELPER (40); - -void bpf_set_hash_invalid (void *ctx) - KERNEL_HELPER (41); - -int bpf_get_numa_node_id (void) - KERNEL_HELPER (42); - -int bpf_skb_change_head (void *, int len, int flags) - KERNEL_HELPER (43); - -int bpf_xdp_adjust_head (void *ctx, int offset) - KERNEL_HELPER (44); - -int bpf_probe_read_str (void *ctx, unsigned int size, const void *unsafe_ptr) - KERNEL_HELPER (45); - -int bpf_get_socket_cookie (void *ctx) - KERNEL_HELPER (46); - -unsigned int bpf_get_socket_uid (void *ctx) - KERNEL_HELPER (47); - -unsigned int bpf_set_hash (void *ctx, unsigned int hash) - KERNEL_HELPER (48); - -int bpf_setsockopt (void *ctx, int level, int optname, void *optval, int optlen) - KERNEL_HELPER (49); - -int bpf_skb_adjust_room (void *ctx, int len_diff, unsigned int mode, - unsigned long long flags) - KERNEL_HELPER (50); - -int bpf_redirect_map (void *map, int key, int flags) - KERNEL_HELPER (51); - -int bpf_sk_redirect_map (void *ctx, void *map, int key, int flags) - KERNEL_HELPER (52); - -int bpf_sock_map_update (void *map, void *key, void *value, - unsigned long long flags) - KERNEL_HELPER (53); - -int bpf_xdp_adjust_meta (void *ctx, int offset) - KERNEL_HELPER (54); - -int bpf_perf_event_read_value (void *map, unsigned long long flags, - void *buf, unsigned int buf_size) - KERNEL_HELPER (55); - -int bpf_perf_prog_read_value (void *ctx, void *buf, unsigned int buf_size) - KERNEL_HELPER (56); - -int bpf_getsockopt (void *ctx, int level, int optname, void *optval, - int optlen) - KERNEL_HELPER (57); - -int bpf_override_return (void *ctx, unsigned long rc) - KERNEL_HELPER (58); - -int bpf_sock_ops_cb_flags_set (void *ctx, int flags) - KERNEL_HELPER (59); - -int bpf_msg_redirect_map (void *ctx, void *map, int key, int flags) - KERNEL_HELPER (60); - -int bpf_msg_apply_bytes (void *ctx, int len) - KERNEL_HELPER (61); - -int bpf_msg_cork_bytes (void *ctx, int len) - KERNEL_HELPER (62); - -int bpf_msg_pull_data (void *, int len) - KERNEL_HELPER (63); - -int bpf_bind (void *ctx, void *addr, int addr_len) - KERNEL_HELPER (64); - -int bpf_xdp_adjust_tail (struct xdp_md *xdp_md, int delta) - KERNEL_HELPER (65); - -int bpf_skb_get_xfrm_state (void *ctx, int index, void *state, - int size, int flags) - KERNEL_HELPER (66); - -int bpf_get_stack (void *ctx, void *buf, int size, int flags) - KERNEL_HELPER (67); - -int bpf_skb_load_bytes_relative (void *ctx, int off, void *to, int len, - unsigned int start_header) - KERNEL_HELPER (68); - -int bpf_fib_lookup (void *ctx, struct bpf_fib_lookup *params, - int plen, unsigned int flags) - KERNEL_HELPER (69); - -int bpf_sock_hash_update (void *map, void *key, void *value, - unsigned long long flags) - KERNEL_HELPER (70); - -int bpf_msg_redirect_hash (void *ctx, void *map, void *key, int flags) - KERNEL_HELPER (71); - -int bpf_sk_redirect_hash (void *ctx, void *map, void *key, int flags) - KERNEL_HELPER (72); - -int bpf_lwt_push_encap (void *ctx, unsigned int type, void *hdr, - unsigned int len) - KERNEL_HELPER (73); - -int bpf_lwt_seg6_store_bytes (void *ctx, unsigned int offset, - void *from, unsigned int len) - KERNEL_HELPER (74); - -int bpf_lwt_seg6_adjust_srh (void *ctx, unsigned int offset, - unsigned int len) - KERNEL_HELPER (75); - -int bpf_lwt_seg6_action (void *ctx, unsigned int action, void *param, - unsigned int param_len) - KERNEL_HELPER (76); - -int bpf_rc_repeat (void *ctx) - KERNEL_HELPER (77); - -int bpf_rc_keydown (void *ctx, unsigned int protocol, - unsigned long long scancode, unsigned int toggle) - KERNEL_HELPER (78); - -unsigned bpf_skb_cgroup_id (void *ctx) - KERNEL_HELPER (79); - -unsigned long long bpf_get_current_cgroup_id (void) - KERNEL_HELPER (80); - -void *bpf_get_local_storage (void *map, unsigned long long flags) - KERNEL_HELPER (81); - -int bpf_sk_select_reuseport (void *ctx, void *map, void *key, unsigned int flags) - KERNEL_HELPER (82); - -unsigned long long bpf_skb_ancestor_cgroup_id (void *ctx, int level) - KERNEL_HELPER (83); - -struct bpf_sock *bpf_sk_lookup_tcp (void *ctx, struct bpf_sock_tuple *tuple, - int size, unsigned long long netns_id, - unsigned long long flags) - KERNEL_HELPER (84); - -struct bpf_sock *bpf_sk_lookup_udp (void *ctx, struct bpf_sock_tuple *tuple, - int size, unsigned long long netns_id, - unsigned long long flags) - KERNEL_HELPER (85); - -int bpf_sk_release (struct bpf_sock *sk) - KERNEL_HELPER (86); - -int bpf_map_push_elem (void *map, const void *value, unsigned long long flags) - KERNEL_HELPER (87); - -int bpf_map_pop_elem (void *map, void *value) - KERNEL_HELPER (88); - -int bpf_map_peek_elem (void *map, void *value) - KERNEL_HELPER (89); - -int bpf_msg_push_data (void *ctx, int start, int cut, int flags) - KERNEL_HELPER (90); - -int bpf_msg_pop_data (void *ctx, int start, int cut, int flags) - KERNEL_HELPER (91); - -int bpf_rc_pointer_rel (void *ctx, int rel_x, int rel_y) - KERNEL_HELPER (92); - -void bpf_spin_lock (struct bpf_spin_lock *lock) - KERNEL_HELPER (93); - -void bpf_spin_unlock (struct bpf_spin_lock *lock) - KERNEL_HELPER (94); - -struct bpf_sock *bpf_sk_fullsock (struct bpf_sock *sk) - KERNEL_HELPER (95); - -struct bpf_sock *bpf_tcp_sock (struct bpf_sock *sk) - KERNEL_HELPER (96); - -int bpf_skb_ecn_set_ce (void *ctx) - KERNEL_HELPER (97); - -struct bpf_sock *bpf_get_listener_sock (struct bpf_sock *sk) - KERNEL_HELPER (98); - -struct bpf_sock *bpf_skc_lookup_tcp (void *ctx, - struct bpf_sock_tuple *tuple, - unsigned int tuple_size, - unsigned long netns, - unsigned long flags) - KERNEL_HELPER (99); - -int bpf_tcp_check_syncookie (struct bpf_sock *sk, void *iph, - unsigned int iph_len, - struct tcp_hdr *th, - unsigned int th_len) - KERNEL_HELPER (100); - -int bpf_sysctl_get_name (struct bpf_sysctl *ctx, - char *buf, unsigned long buf_len, - unsigned long flags) - KERNEL_HELPER (101); - -int bpf_sysctl_get_current_value (struct bpf_sysctl *ctx, - char *buf, unsigned long buf_len) - KERNEL_HELPER (102); - -int bpf_sysctl_get_new_value (struct bpf_sysctl *ctx, char *buf, - unsigned long buf_len) - KERNEL_HELPER (103); - -int bpf_sysctl_set_new_value (struct bpf_sysctl *ctx, const char *buf, - unsigned long buf_len) - KERNEL_HELPER (104); - -int bpf_strtol (const char *buf, unsigned long buf_len, - unsigned long flags, long *res) - KERNEL_HELPER (105); - -int bpf_strtoul (const char *buf, unsigned long buf_len, - unsigned long flags, unsigned long *res) - KERNEL_HELPER (106); - -void *bpf_sk_storage_get (void *map, struct bpf_sock *sk, - void *value, long flags) - KERNEL_HELPER (107); - -int bpf_sk_storage_delete (void *map, struct bpf_sock *sk) - KERNEL_HELPER (108); - -/* Functions to emit BPF_LD_ABS and BPF_LD_IND instructions. We - provide the "standard" names as synonyms of the corresponding GCC - builtins. Note how the SKB argument is ignored. */ - -#define load_byte(SKB,OFF) __builtin_bpf_load_byte ((OFF)) -#define load_half(SKB,OFF) __builtin_bpf_load_half ((OFF)) -#define load_word(SKB,OFF) __builtin_bpf_load_word ((OFF)) - -struct bpf_map_def -{ - unsigned int type; - unsigned int key_size; - unsigned int value_size; - unsigned int max_entries; - unsigned int map_flags; - unsigned int inner_map_idx; - unsigned int numa_node; -}; - -#endif /* ! __BPF_HELPERS_H */ diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc index a0956a0..223a43c 100644 --- a/gcc/config/bpf/bpf.cc +++ b/gcc/config/bpf/bpf.cc @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify-me.h" #include "core-builtins.h" +#include "opts.h" /* Per-function machine data. */ struct GTY(()) machine_function @@ -250,9 +251,10 @@ bpf_option_override (void) /* Disable -fstack-protector as it is not supported in BPF. */ if (flag_stack_protect) { - inform (input_location, - "%<-fstack-protector%> does not work " - "on this architecture"); + if (!flag_stack_protector_set_by_fhardened_p) + inform (input_location, + "%<-fstack-protector%> does not work " + "on this architecture"); flag_stack_protect = 0; } diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md index 88b9291..906fdb3 100644 --- a/gcc/config/c6x/c6x.md +++ b/gcc/config/c6x/c6x.md @@ -1440,7 +1440,7 @@ (define_insn "mvilc" [(set (reg:SI REG_ILC) - (unspec [(match_operand:SI 0 "register_operand" "a,b")] UNSPEC_MVILC))] + (unspec:SI [(match_operand:SI 0 "register_operand" "a,b")] UNSPEC_MVILC))] "TARGET_INSNS_64PLUS" "%|%.\\tmvc\\t%$\\t%0, ILC" [(set_attr "predicable" "no") diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md index 23f2bbe..a928dec 100644 --- a/gcc/config/gcn/gcn-valu.md +++ b/gcc/config/gcn/gcn-valu.md @@ -566,10 +566,10 @@ (match_operand:V_4REG 1 "general_operand"))] "" {@ [cons: =0, 1; attrs: type, length, gcn_version] - [v,vDB;vmult,16,* ] v_mov_b32\t%L0, %L1\; v_mov_b32\t%H0, %H1\; v_mov_b32\t%J0, %J1\; v_mov_b32\t%K0, %K1 - [v,a ;vmult,32,* ] v_accvgpr_read_b32\t%L0, %L1\; v_accvgpr_read_b32\t%H0, %H1\; v_accvgpr_read_b32\t%J0, %J1\; v_accvgpr_read_b32\t%K0, %K1 - [a,v ;vmult,32,* ] v_accvgpr_write_b32\t%L0, %L1\;v_accvgpr_write_b32\t%H0, %H1\;v_accvgpr_write_b32\t%J0, %J1\;v_accvgpr_write_b32\t%K0, %K1 - [a,a ;vmult,32,cdna2] v_accvgpr_mov_b32\t%L0, %L1\; v_accvgpr_mov_b32\t%H0, %H1\; v_accvgpr_mov_b32\t%J0, %J1\; v_accvgpr_mov_b32\t%K0, %K1 + [v ,vDB;vmult,16,* ] v_mov_b32\t%L0, %L1\; v_mov_b32\t%H0, %H1\; v_mov_b32\t%J0, %J1\; v_mov_b32\t%K0, %K1 + [v ,a ;vmult,32,* ] v_accvgpr_read_b32\t%L0, %L1\; v_accvgpr_read_b32\t%H0, %H1\; v_accvgpr_read_b32\t%J0, %J1\; v_accvgpr_read_b32\t%K0, %K1 + [$a,v ;vmult,32,* ] v_accvgpr_write_b32\t%L0, %L1\;v_accvgpr_write_b32\t%H0, %H1\;v_accvgpr_write_b32\t%J0, %J1\;v_accvgpr_write_b32\t%K0, %K1 + [a ,a ;vmult,32,cdna2] v_accvgpr_mov_b32\t%L0, %L1\; v_accvgpr_mov_b32\t%H0, %H1\; v_accvgpr_mov_b32\t%J0, %J1\; v_accvgpr_mov_b32\t%K0, %K1 }) (define_insn "mov<mode>_exec" diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc index 52c8a0e..22d2b6e 100644 --- a/gcc/config/gcn/gcn.cc +++ b/gcc/config/gcn/gcn.cc @@ -5050,7 +5050,9 @@ gcn_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode, rtx dst, rtx src0, rtx src1, const vec_perm_indices & sel) { - if (vmode != op_mode) + if (vmode != op_mode + || !VECTOR_MODE_P (vmode) + || GET_MODE_INNER (vmode) == TImode) return false; unsigned int nelt = GET_MODE_NUNITS (vmode); diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h index 75ef271..d1fc93e 100644 --- a/gcc/config/i386/cpuid.h +++ b/gcc/config/i386/cpuid.h @@ -150,6 +150,7 @@ #define bit_AVXVNNIINT16 (1 << 10) #define bit_PREFETCHI (1 << 14) #define bit_USER_MSR (1 << 15) +#define bit_AVX10 (1 << 19) #define bit_APX_F (1 << 21) /* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */ @@ -166,6 +167,10 @@ #define bit_AESKLE ( 1<<0 ) #define bit_WIDEKL ( 1<<2 ) +/* AVX10 sub leaf (%eax == 0x24) */ +/* %ebx */ +#define bit_AVX10_256 (1 << 17) +#define bit_AVX10_512 (1 << 18) /* Signatures for different CPU implementations as returned in uses of cpuid with level 0. */ diff --git a/gcc/config/i386/driver-i386.cc b/gcc/config/i386/driver-i386.cc index 55d4045..204600e 100644 --- a/gcc/config/i386/driver-i386.cc +++ b/gcc/config/i386/driver-i386.cc @@ -369,6 +369,37 @@ detect_caches_intel (bool xeon_mp, unsigned max_level, return describe_cache (level1, level2); } +/* Extended features */ +#define has_feature(f) \ + has_cpu_feature (&cpu_model, cpu_features2, f) + +/* We will emit a warning when using AVX10.1 and AVX512 options with one + enabled and the other disabled. Add this function to avoid push "-mno-" + options under this scenario for -march=native. */ + +bool check_avx512_features (__processor_model &cpu_model, + unsigned int (&cpu_features2)[SIZE_OF_CPU_FEATURES], + const enum processor_features feature) +{ + if (has_feature (FEATURE_AVX10_1_256) + && ((feature == FEATURE_AVX512F) + || (feature == FEATURE_AVX512CD) + || (feature == FEATURE_AVX512DQ) + || (feature == FEATURE_AVX512BW) + || (feature == FEATURE_AVX512VL) + || (feature == FEATURE_AVX512IFMA) + || (feature == FEATURE_AVX512VBMI) + || (feature == FEATURE_AVX512VBMI2) + || (feature == FEATURE_AVX512VNNI) + || (feature == FEATURE_AVX512VPOPCNTDQ) + || (feature == FEATURE_AVX512BITALG) + || (feature == FEATURE_AVX512FP16) + || (feature == FEATURE_AVX512BF16))) + return false; + + return true; +} + /* This will be called by the spec parser in gcc.cc when it sees a %:local_cpu_detect(args) construct. Currently it will be called with either "arch [32|64]" or "tune [32|64]" as argument @@ -447,10 +478,6 @@ const char *host_detect_local_cpu (int argc, const char **argv) } } - /* Extended features */ -#define has_feature(f) \ - has_cpu_feature (&cpu_model, cpu_features2, f) - if (vendor == VENDOR_AMD) { unsigned int name; @@ -868,7 +895,12 @@ const char *host_detect_local_cpu (int argc, const char **argv) options = concat (options, " ", isa_names_table[i].option, NULL); } - else + /* Never push -mno-avx10.1-{256,512} under -march=native to + avoid unnecessary warnings when building librarys. */ + else if ((isa_names_table[i].feature != FEATURE_AVX10_1_256) + && (isa_names_table[i].feature != FEATURE_AVX10_1_512) + && check_avx512_features (cpu_model, cpu_features2, + isa_names_table[i].feature)) options = concat (options, neg_option, isa_names_table[i].option + 2, NULL); } diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def index 19fa5c1..7a5f267 100644 --- a/gcc/config/i386/i386-builtin.def +++ b/gcc/config/i386/i386-builtin.def @@ -301,10 +301,10 @@ BDESC (OPTION_MASK_ISA_AVX512BW, OPTION_MASK_ISA2_EVEX512, CODE_FOR_avx512bw_sto /* AVX512VP2INTERSECT */ BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT | OPTION_MASK_ISA2_EVEX512, CODE_FOR_nothing, "__builtin_ia32_2intersectd512", IX86_BUILTIN_2INTERSECTD512, UNKNOWN, (int) VOID_FTYPE_PUHI_PUHI_V16SI_V16SI) BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT | OPTION_MASK_ISA2_EVEX512, CODE_FOR_nothing, "__builtin_ia32_2intersectq512", IX86_BUILTIN_2INTERSECTQ512, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V8DI_V8DI) -BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd256", IX86_BUILTIN_2INTERSECTD256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V8SI_V8SI) -BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq256", IX86_BUILTIN_2INTERSECTQ256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4DI_V4DI) -BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd128", IX86_BUILTIN_2INTERSECTD128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4SI_V4SI) -BDESC (0, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq128", IX86_BUILTIN_2INTERSECTQ128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V2DI_V2DI) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd256", IX86_BUILTIN_2INTERSECTD256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V8SI_V8SI) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq256", IX86_BUILTIN_2INTERSECTQ256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4DI_V4DI) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd128", IX86_BUILTIN_2INTERSECTD128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4SI_V4SI) +BDESC (OPTION_MASK_ISA_AVX512VL, OPTION_MASK_ISA2_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq128", IX86_BUILTIN_2INTERSECTQ128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V2DI_V2DI) /* AVX512VL */ BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_loadv16hi_mask, "__builtin_ia32_loaddquhi256_mask", IX86_BUILTIN_LOADDQUHI256_MASK, UNKNOWN, (int) V16HI_FTYPE_PCSHORT_V16HI_UHI) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index a8d871d..4bd7d4f 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -2453,7 +2453,8 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) /* Generate XOR since we can't check that one operand is zero vector. */ tmp = gen_reg_rtx (mode); - emit_insn (gen_rtx_SET (tmp, gen_rtx_XOR (mode, op0, op1))); + rtx ops[3] = { tmp, op0, op1 }; + ix86_expand_vector_logical_operator (XOR, mode, ops); tmp = gen_lowpart (p_mode, tmp); emit_insn (gen_rtx_SET (gen_rtx_REG (CCZmode, FLAGS_REG), gen_rtx_UNSPEC (CCZmode, @@ -17748,6 +17749,7 @@ emit_reduc_half (rtx dest, rtx src, int i) tem = gen_mmx_lshrv1si3 (d, gen_lowpart (V1SImode, src), GEN_INT (i / 2)); break; + case E_V8QImode: case E_V4HImode: d = gen_reg_rtx (V1DImode); tem = gen_mmx_lshrv1di3 (d, gen_lowpart (V1DImode, src), diff --git a/gcc/config/i386/i386-expand.h b/gcc/config/i386/i386-expand.h index 1ea789c..997cb7d 100644 --- a/gcc/config/i386/i386-expand.h +++ b/gcc/config/i386/i386-expand.h @@ -44,9 +44,9 @@ void ix86_emit_binop (enum rtx_code code, machine_mode mode, rtx dst, rtx src); enum calling_abi ix86_function_abi (const_tree fndecl); bool ix86_function_ms_hook_prologue (const_tree fn); void warn_once_call_ms2sysv_xlogues (const char *feature); -rtx gen_push (rtx arg); +rtx gen_push (rtx arg, bool = false); rtx gen_pushfl (void); -rtx gen_pop (rtx arg); +rtx gen_pop (rtx arg, bool = false); rtx gen_popfl (void); rtx ix86_expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, int ignore); diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def index 991df5e..f730aa2 100644 --- a/gcc/config/i386/i386-isa.def +++ b/gcc/config/i386/i386-isa.def @@ -123,3 +123,6 @@ DEF_PTA(SHA512) DEF_PTA(SM4) DEF_PTA(APX_F) DEF_PTA(USER_MSR) +DEF_PTA(EVEX512) +DEF_PTA(AVX10_1_256) +DEF_PTA(AVX10_1_512) diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index df7d243..fb8638a 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -258,7 +258,9 @@ static struct ix86_target_opts isa2_opts[] = { "-msha512", OPTION_MASK_ISA2_SHA512 }, { "-msm4", OPTION_MASK_ISA2_SM4 }, { "-mevex512", OPTION_MASK_ISA2_EVEX512 }, - { "-musermsr", OPTION_MASK_ISA2_USER_MSR } + { "-musermsr", OPTION_MASK_ISA2_USER_MSR }, + { "-mavx10.1-256", OPTION_MASK_ISA2_AVX10_1_256 }, + { "-mavx10.1-512", OPTION_MASK_ISA2_AVX10_1_512 } }; static struct ix86_target_opts isa_opts[] = { @@ -705,6 +707,8 @@ ix86_function_specific_save (struct cl_target_option *ptr, ptr->x_ix86_apx_features = opts->x_ix86_apx_features; ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit; ptr->x_ix86_isa_flags2_explicit = opts->x_ix86_isa_flags2_explicit; + ptr->x_ix86_no_avx512_explicit = opts->x_ix86_no_avx512_explicit; + ptr->x_ix86_no_avx10_1_explicit = opts->x_ix86_no_avx10_1_explicit; ptr->x_recip_mask_explicit = opts->x_recip_mask_explicit; ptr->x_ix86_arch_string = opts->x_ix86_arch_string; ptr->x_ix86_tune_string = opts->x_ix86_tune_string; @@ -847,6 +851,8 @@ ix86_function_specific_restore (struct gcc_options *opts, opts->x_ix86_apx_features = ptr->x_ix86_apx_features; opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit; opts->x_ix86_isa_flags2_explicit = ptr->x_ix86_isa_flags2_explicit; + opts->x_ix86_no_avx512_explicit = ptr->x_ix86_no_avx512_explicit; + opts->x_ix86_no_avx10_1_explicit = ptr->x_ix86_no_avx10_1_explicit; opts->x_recip_mask_explicit = ptr->x_recip_mask_explicit; opts->x_ix86_arch_string = ptr->x_ix86_arch_string; opts->x_ix86_tune_string = ptr->x_ix86_tune_string; @@ -1125,6 +1131,9 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[], IX86_ATTR_ISA ("apxf", OPT_mapxf), IX86_ATTR_ISA ("evex512", OPT_mevex512), IX86_ATTR_ISA ("usermsr", OPT_musermsr), + IX86_ATTR_ISA ("avx10.1", OPT_mavx10_1_256), + IX86_ATTR_ISA ("avx10.1-256", OPT_mavx10_1_256), + IX86_ATTR_ISA ("avx10.1-512", OPT_mavx10_1_512), /* enum options */ IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_), @@ -1411,6 +1420,17 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, target_clone_attr)) return error_mark_node; + /* AVX10.1-256 will enable only 256 bit AVX512F features by setting all + AVX512 related ISA flags and not setting EVEX512. When it is used + with avx512 related function attribute, we need to enable 512 bit to + align with the command line behavior. Manually set EVEX512 for this + scenario. */ + if ((def->x_ix86_isa_flags2 & OPTION_MASK_ISA2_AVX10_1_256) + && (opts->x_ix86_isa_flags & OPTION_MASK_ISA_AVX512F) + && !(def->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512) + && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512)) + opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_EVEX512; + /* If the changed options are different from the default, rerun ix86_option_override_internal, and then save the options away. The string options are attribute options, and will be undone @@ -1421,7 +1441,10 @@ ix86_valid_target_attribute_tree (tree fndecl, tree args, || option_strings[IX86_FUNCTION_SPECIFIC_ARCH] || option_strings[IX86_FUNCTION_SPECIFIC_TUNE] || enum_opts_set.x_ix86_fpmath - || enum_opts_set.x_prefer_vector_width_type) + || enum_opts_set.x_prefer_vector_width_type + || (!(def->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_AVX10_1_256) + && (opts->x_ix86_isa_flags2_explicit + & OPTION_MASK_ISA2_AVX10_1_256))) { /* If we are using the default tune= or arch=, undo the string assigned, and use the default. */ @@ -1963,7 +1986,7 @@ ix86_option_override_internal (bool main_args_p, struct gcc_options *opts_set) { unsigned int i; - unsigned HOST_WIDE_INT ix86_arch_mask; + unsigned HOST_WIDE_INT ix86_arch_mask, avx512_isa_flags, avx512_isa_flags2; const bool ix86_tune_specified = (opts->x_ix86_tune_string != NULL); /* -mrecip options. */ @@ -1982,6 +2005,14 @@ ix86_option_override_internal (bool main_args_p, { "vec-sqrt", RECIP_MASK_VEC_SQRT }, }; + avx512_isa_flags = OPTION_MASK_ISA_AVX512F | OPTION_MASK_ISA_AVX512CD + | OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512BW + | OPTION_MASK_ISA_AVX512VL | OPTION_MASK_ISA_AVX512IFMA + | OPTION_MASK_ISA_AVX512VBMI | OPTION_MASK_ISA_AVX512VBMI2 + | OPTION_MASK_ISA_AVX512VNNI | OPTION_MASK_ISA_AVX512VPOPCNTDQ + | OPTION_MASK_ISA_AVX512BITALG; + avx512_isa_flags2 = OPTION_MASK_ISA2_AVX512FP16 + | OPTION_MASK_ISA2_AVX512BF16; /* Turn off both OPTION_MASK_ABI_64 and OPTION_MASK_ABI_X32 if TARGET_64BIT_DEFAULT is true and TARGET_64BIT is false. */ @@ -2590,12 +2621,101 @@ ix86_option_override_internal (bool main_args_p, &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM) & ~opts->x_ix86_isa_flags_explicit); - /* Set EVEX512 target if it is not explicitly set - when AVX512 is enabled. */ - if (TARGET_AVX512F_P(opts->x_ix86_isa_flags) - && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512)) + /* Emit a warning if AVX10.1 options is used with AVX512/EVEX512 options except + for the following option combinations: + 1. Both AVX10.1-512 and AVX512 with 512 bit vector width are enabled with no + explicit disable on other AVX512 features. + 2. Both AVX10.1-256 and AVX512 w/o 512 bit vector width are enabled with no + explicit disable on other AVX512 features. + 3. Both AVX10.1 and AVX512 are disabled. */ + if (TARGET_AVX10_1_512_P (opts->x_ix86_isa_flags2)) + { + if (opts->x_ix86_no_avx512_explicit + && (((~(avx512_isa_flags & opts->x_ix86_isa_flags) + & (avx512_isa_flags & opts->x_ix86_isa_flags_explicit))) + || ((~((avx512_isa_flags2 | OPTION_MASK_ISA2_EVEX512) + & opts->x_ix86_isa_flags2) + & ((avx512_isa_flags2 | OPTION_MASK_ISA2_EVEX512) + & opts->x_ix86_isa_flags2_explicit))))) + warning (0, "%<-mno-evex512%> or %<-mno-avx512XXX%> cannot disable " + "AVX10 instructions when AVX10.1-512 is available"); + } + else if (TARGET_AVX10_1_256_P (opts->x_ix86_isa_flags2)) + { + if (TARGET_EVEX512_P (opts->x_ix86_isa_flags2) + && (OPTION_MASK_ISA2_EVEX512 & opts->x_ix86_isa_flags2_explicit)) + { + if (!TARGET_AVX512F_P (opts->x_ix86_isa_flags) + || !(OPTION_MASK_ISA_AVX512F & opts->x_ix86_isa_flags_explicit)) + { + /* We should not emit 512 bit instructions under AVX10.1-256 + when EVEX512 is enabled w/o any AVX512 features enabled. + Disable EVEX512 bit for this. */ + warning (0, "Using %<-mevex512%> without any AVX512 features " + "enabled together with AVX10.1 only will not enable " + "any AVX512 or AVX10.1-512 features, using 256 as " + "max vector size"); + opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA2_EVEX512; + } + else + warning (0, "Vector size conflicts between AVX10.1 and AVX512, " + "using 512 as max vector size"); + } + else if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) + && !(OPTION_MASK_ISA2_EVEX512 + & opts->x_ix86_isa_flags2_explicit)) + warning (0, "Vector size conflicts between AVX10.1 and AVX512, using " + "512 as max vector size"); + else if (opts->x_ix86_no_avx512_explicit + && (((~(avx512_isa_flags & opts->x_ix86_isa_flags) + & (avx512_isa_flags & opts->x_ix86_isa_flags_explicit))) + || ((~(avx512_isa_flags2 & opts->x_ix86_isa_flags2) + & (avx512_isa_flags2 + & opts->x_ix86_isa_flags2_explicit))))) + warning (0, "%<-mno-avx512XXX%> cannot disable AVX10 instructions " + "when AVX10 is available"); + } + else if (TARGET_AVX512F_P (opts->x_ix86_isa_flags) + && (OPTION_MASK_ISA_AVX512F & opts->x_ix86_isa_flags_explicit)) + { + if (opts->x_ix86_no_avx10_1_explicit + && ((OPTION_MASK_ISA2_AVX10_1_256 | OPTION_MASK_ISA2_AVX10_1_512) + & opts->x_ix86_isa_flags2_explicit)) + { + warning (0, "%<-mno-avx10.1, -mno-avx10.1-256, -mno-avx10.1-512%> " + "cannot disable AVX512 instructions when " + "%<-mavx512XXX%>"); + /* Reset those unset AVX512 flags set by AVX10 options when AVX10 is + disabled. */ + if (OPTION_MASK_ISA2_AVX10_1_256 & opts->x_ix86_isa_flags2_explicit) + { + opts->x_ix86_isa_flags = (~avx512_isa_flags + & opts->x_ix86_isa_flags) + | (avx512_isa_flags & opts->x_ix86_isa_flags + & opts->x_ix86_isa_flags_explicit); + opts->x_ix86_isa_flags2 = (~avx512_isa_flags2 + & opts->x_ix86_isa_flags2) + | (avx512_isa_flags2 & opts->x_ix86_isa_flags2 + & opts->x_ix86_isa_flags2_explicit); + } + } + } + + /* Set EVEX512 if one of the following conditions meets: + 1. AVX512 is enabled while EVEX512 is not explicitly set/unset. + 2. AVX10.1-512 is enabled. */ + if (TARGET_AVX10_1_512_P (opts->x_ix86_isa_flags2) + || (TARGET_AVX512F_P (opts->x_ix86_isa_flags) + && !(opts->x_ix86_isa_flags2_explicit & OPTION_MASK_ISA2_EVEX512))) opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA2_EVEX512; + /* Enable all AVX512 related ISAs when AVX10.1 is enabled. */ + if (TARGET_AVX10_1_256_P (opts->x_ix86_isa_flags2)) + { + opts->x_ix86_isa_flags |= avx512_isa_flags; + opts->x_ix86_isa_flags2 |= avx512_isa_flags2; + } + /* Disable AVX512{PF,ER,4VNNIW,4FAMPS} for -mno-evex512. */ if (!TARGET_EVEX512_P(opts->x_ix86_isa_flags2)) { @@ -3072,10 +3192,25 @@ ix86_option_override_internal (bool main_args_p, = build_target_option_node (opts, opts_set); } + const bool cf_okay_p = (TARGET_64BIT || TARGET_CMOV); + /* When -fhardened, enable -fcf-protection=full, but only when it's + compatible with this target, and when it wasn't already specified + on the command line. */ + if (opts->x_flag_hardened && cf_okay_p) + { + if (opts->x_flag_cf_protection == CF_NONE) + opts->x_flag_cf_protection = CF_FULL; + else if (opts->x_flag_cf_protection != CF_FULL) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fcf-protection=full%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); + } + if (opts->x_flag_cf_protection != CF_NONE) { if ((opts->x_flag_cf_protection & CF_BRANCH) == CF_BRANCH - && !TARGET_64BIT && !TARGET_CMOV) + && !cf_okay_p) error ("%<-fcf-protection%> is not compatible with this target"); opts->x_flag_cf_protection diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h index 2ec76a1..4d293ed 100644 --- a/gcc/config/i386/i386-opts.h +++ b/gcc/config/i386/i386-opts.h @@ -139,7 +139,8 @@ enum apx_features { apx_egpr = 1 << 0, apx_push2pop2 = 1 << 1, apx_ndd = 1 << 2, - apx_all = apx_egpr | apx_push2pop2 | apx_ndd, + apx_ppx = 1 << 3, + apx_all = apx_egpr | apx_push2pop2 | apx_ndd | apx_ppx, }; #endif diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 683ac64..9390f52 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -105,7 +105,7 @@ along with GCC; see the file COPYING3. If not see static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); static void ix86_print_operand_address_as (FILE *, rtx, addr_space_t, bool); -static void ix86_emit_restore_reg_using_pop (rtx); +static void ix86_emit_restore_reg_using_pop (rtx, bool = false); #ifndef CHECK_STACK_LIMIT @@ -6448,7 +6448,7 @@ output_set_got (rtx dest, rtx label) /* Generate an "push" pattern for input ARG. */ rtx -gen_push (rtx arg) +gen_push (rtx arg, bool ppx_p) { struct machine_function *m = cfun->machine; @@ -6459,10 +6459,10 @@ gen_push (rtx arg) if (REG_P (arg) && GET_MODE (arg) != word_mode) arg = gen_rtx_REG (word_mode, REGNO (arg)); - return gen_rtx_SET (gen_rtx_MEM (word_mode, - gen_rtx_PRE_DEC (Pmode, - stack_pointer_rtx)), - arg); + rtx stack = gen_rtx_MEM (word_mode, + gen_rtx_PRE_DEC (Pmode, + stack_pointer_rtx)); + return ppx_p ? gen_pushp_di (stack, arg) : gen_rtx_SET (stack, arg); } rtx @@ -6486,15 +6486,16 @@ gen_pushfl (void) /* Generate an "pop" pattern for input ARG. */ rtx -gen_pop (rtx arg) +gen_pop (rtx arg, bool ppx_p) { if (REG_P (arg) && GET_MODE (arg) != word_mode) arg = gen_rtx_REG (word_mode, REGNO (arg)); - return gen_rtx_SET (arg, - gen_rtx_MEM (word_mode, - gen_rtx_POST_INC (Pmode, - stack_pointer_rtx))); + rtx stack = gen_rtx_MEM (word_mode, + gen_rtx_POST_INC (Pmode, + stack_pointer_rtx)); + + return ppx_p ? gen_popp_di (arg, stack) : gen_rtx_SET (arg, stack); } rtx @@ -6512,7 +6513,7 @@ gen_popfl (void) /* Generate a "push2" pattern for input ARG. */ rtx -gen_push2 (rtx mem, rtx reg1, rtx reg2) +gen_push2 (rtx mem, rtx reg1, rtx reg2, bool ppx_p = false) { struct machine_function *m = cfun->machine; const int offset = UNITS_PER_WORD * 2; @@ -6527,7 +6528,8 @@ gen_push2 (rtx mem, rtx reg1, rtx reg2) if (REG_P (reg2) && GET_MODE (reg2) != word_mode) reg2 = gen_rtx_REG (word_mode, REGNO (reg2)); - return gen_push2_di (mem, reg1, reg2); + return ppx_p ? gen_push2p_di (mem, reg1, reg2): + gen_push2_di (mem, reg1, reg2); } /* Return >= 0 if there is an unused call-clobbered register available @@ -7369,7 +7371,8 @@ ix86_emit_save_regs (void) for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true)) { - insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno))); + insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno), + TARGET_APX_PPX)); RTX_FRAME_RELATED_P (insn) = 1; } } @@ -7399,7 +7402,8 @@ ix86_emit_save_regs (void) gen_rtx_REG (word_mode, regno_list[0]), gen_rtx_REG (word_mode, - regno_list[1]))); + regno_list[1]), + TARGET_APX_PPX)); RTX_FRAME_RELATED_P (insn) = 1; rtx dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (3)); @@ -7431,7 +7435,8 @@ ix86_emit_save_regs (void) } else { - insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno))); + insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno), + TARGET_APX_PPX)); RTX_FRAME_RELATED_P (insn) = 1; aligned = true; } @@ -7439,7 +7444,8 @@ ix86_emit_save_regs (void) if (loaded_regnum == 1) { insn = emit_insn (gen_push (gen_rtx_REG (word_mode, - regno_list[0]))); + regno_list[0]), + TARGET_APX_PPX)); RTX_FRAME_RELATED_P (insn) = 1; } } @@ -9268,13 +9274,13 @@ ix86_expand_prologue (void) emit_insn (gen_prologue_use (stack_pointer_rtx)); } -/* Emit code to restore REG using a POP insn. */ +/* Emit code to restore REG using a POP or POPP insn. */ static void -ix86_emit_restore_reg_using_pop (rtx reg) +ix86_emit_restore_reg_using_pop (rtx reg, bool ppx_p) { struct machine_function *m = cfun->machine; - rtx_insn *insn = emit_insn (gen_pop (reg)); + rtx_insn *insn = emit_insn (gen_pop (reg, ppx_p)); ix86_add_cfa_restore_note (insn, reg, m->fs.sp_offset); m->fs.sp_offset -= UNITS_PER_WORD; @@ -9328,14 +9334,19 @@ ix86_emit_restore_reg_using_pop (rtx reg) /* Emit code to restore REG using a POP2 insn. */ static void -ix86_emit_restore_reg_using_pop2 (rtx reg1, rtx reg2) +ix86_emit_restore_reg_using_pop2 (rtx reg1, rtx reg2, bool ppx_p = false) { struct machine_function *m = cfun->machine; const int offset = UNITS_PER_WORD * 2; + rtx_insn *insn; rtx mem = gen_rtx_MEM (TImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx)); - rtx_insn *insn = emit_insn (gen_pop2_di (reg1, mem, reg2)); + + if (ppx_p) + insn = emit_insn (gen_pop2p_di (reg1, mem, reg2)); + else + insn = emit_insn (gen_pop2_di (reg1, mem, reg2)); RTX_FRAME_RELATED_P (insn) = 1; @@ -9397,13 +9408,13 @@ ix86_emit_restore_reg_using_pop2 (rtx reg1, rtx reg2) /* Emit code to restore saved registers using POP insns. */ static void -ix86_emit_restore_regs_using_pop (void) +ix86_emit_restore_regs_using_pop (bool ppx_p) { unsigned int regno; for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, false, true)) - ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno)); + ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno), ppx_p); } /* Emit code to restore saved registers using POP2 insns. */ @@ -9432,20 +9443,23 @@ ix86_emit_restore_regs_using_pop2 (void) ix86_emit_restore_reg_using_pop2 (gen_rtx_REG (word_mode, regno_list[0]), gen_rtx_REG (word_mode, - regno_list[1])); + regno_list[1]), + TARGET_APX_PPX); loaded_regnum = 0; regno_list[0] = regno_list[1] = -1; } } else { - ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno)); + ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno), + TARGET_APX_PPX); aligned = true; } } if (loaded_regnum == 1) - ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno_list[0])); + ix86_emit_restore_reg_using_pop (gen_rtx_REG (word_mode, regno_list[0]), + TARGET_APX_PPX); } /* Emit code and notes for the LEAVE instruction. If insn is non-null, @@ -9990,7 +10004,7 @@ ix86_expand_epilogue (int style) if (TARGET_APX_PUSH2POP2 && m->func_type == TYPE_NORMAL) ix86_emit_restore_regs_using_pop2 (); else - ix86_emit_restore_regs_using_pop (); + ix86_emit_restore_regs_using_pop (TARGET_APX_PPX); } /* If we used a stack pointer and haven't already got rid of it, @@ -10353,6 +10367,7 @@ ix86_expand_split_stack_prologue (void) rtx_code_label *label; rtx limit, current, allocate_rtx, call_fusage; rtx_insn *call_insn; + unsigned int scratch_regno = INVALID_REGNUM; rtx scratch_reg = NULL_RTX; rtx_code_label *varargs_label = NULL; rtx fn; @@ -10375,11 +10390,16 @@ ix86_expand_split_stack_prologue (void) limit = ix86_split_stack_guard (); - if (allocate < SPLIT_STACK_AVAILABLE) - current = stack_pointer_rtx; - else + if (allocate >= SPLIT_STACK_AVAILABLE + || flag_force_indirect_call) + { + scratch_regno = split_stack_prologue_scratch_regno (); + if (scratch_regno == INVALID_REGNUM) + return; + } + + if (allocate >= SPLIT_STACK_AVAILABLE) { - unsigned int scratch_regno; rtx offset; /* We need a scratch register to hold the stack pointer minus @@ -10387,9 +10407,7 @@ ix86_expand_split_stack_prologue (void) function, the scratch register can be any caller-saved register which is not used for parameters. */ offset = GEN_INT (- allocate); - scratch_regno = split_stack_prologue_scratch_regno (); - if (scratch_regno == INVALID_REGNUM) - return; + scratch_reg = gen_rtx_REG (Pmode, scratch_regno); if (!TARGET_64BIT || x86_64_immediate_operand (offset, Pmode)) { @@ -10407,6 +10425,8 @@ ix86_expand_split_stack_prologue (void) } current = scratch_reg; } + else + current = stack_pointer_rtx; ix86_expand_branch (GEU, current, limit, label); rtx_insn *jump_insn = get_last_insn (); @@ -10435,8 +10455,8 @@ ix86_expand_split_stack_prologue (void) { rtx reg10, reg11; - reg10 = gen_rtx_REG (Pmode, R10_REG); - reg11 = gen_rtx_REG (Pmode, R11_REG); + reg10 = gen_rtx_REG (DImode, R10_REG); + reg11 = gen_rtx_REG (DImode, R11_REG); /* If this function uses a static chain, it will be in %r10. Preserve it across the call to __morestack. */ @@ -10449,50 +10469,51 @@ ix86_expand_split_stack_prologue (void) use_reg (&call_fusage, rax); } - if ((ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) - && !TARGET_PECOFF) + if (flag_force_indirect_call + || ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC) { HOST_WIDE_INT argval; - gcc_assert (Pmode == DImode); - /* When using the large model we need to load the address - into a register, and we've run out of registers. So we - switch to a different calling convention, and we call a - different function: __morestack_large. We pass the - argument size in the upper 32 bits of r10 and pass the - frame size in the lower 32 bits. */ - gcc_assert ((allocate & HOST_WIDE_INT_C (0xffffffff)) == allocate); - gcc_assert ((args_size & 0xffffffff) == args_size); - if (split_stack_fn_large == NULL_RTX) { split_stack_fn_large = gen_rtx_SYMBOL_REF (Pmode, "__morestack_large_model"); SYMBOL_REF_FLAGS (split_stack_fn_large) |= SYMBOL_FLAG_LOCAL; } + + fn = split_stack_fn_large; + if (ix86_cmodel == CM_LARGE_PIC) { rtx_code_label *label; rtx x; + gcc_assert (Pmode == DImode); + label = gen_label_rtx (); emit_label (label); LABEL_PRESERVE_P (label) = 1; emit_insn (gen_set_rip_rex64 (reg10, label)); emit_insn (gen_set_got_offset_rex64 (reg11, label)); emit_insn (gen_add2_insn (reg10, reg11)); - x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, split_stack_fn_large), - UNSPEC_GOT); + x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, fn), UNSPEC_GOT); x = gen_rtx_CONST (Pmode, x); emit_move_insn (reg11, x); x = gen_rtx_PLUS (Pmode, reg10, reg11); x = gen_const_mem (Pmode, x); - emit_move_insn (reg11, x); + fn = copy_to_suggested_reg (x, reg11, Pmode); } - else - emit_move_insn (reg11, split_stack_fn_large); + else if (ix86_cmodel == CM_LARGE) + fn = copy_to_suggested_reg (fn, reg11, Pmode); - fn = reg11; + /* When using the large model we need to load the address + into a register, and we've run out of registers. So we + switch to a different calling convention, and we call a + different function: __morestack_large. We pass the + argument size in the upper 32 bits of r10 and pass the + frame size in the lower 32 bits. */ + gcc_assert ((allocate & HOST_WIDE_INT_C (0xffffffff)) == allocate); + gcc_assert ((args_size & 0xffffffff) == args_size); argval = ((args_size << 16) << 16) + allocate; emit_move_insn (reg10, GEN_INT (argval)); @@ -10508,12 +10529,40 @@ ix86_expand_split_stack_prologue (void) } else { + if (flag_force_indirect_call && flag_pic) + { + rtx x; + + gcc_assert (Pmode == SImode); + + scratch_reg = gen_rtx_REG (Pmode, scratch_regno); + + emit_insn (gen_set_got (scratch_reg)); + x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, split_stack_fn), + UNSPEC_GOT); + x = gen_rtx_CONST (Pmode, x); + x = gen_rtx_PLUS (Pmode, scratch_reg, x); + x = gen_const_mem (Pmode, x); + fn = copy_to_suggested_reg (x, scratch_reg, Pmode); + } + rtx_insn *insn = emit_insn (gen_push (GEN_INT (args_size))); add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (UNITS_PER_WORD)); insn = emit_insn (gen_push (allocate_rtx)); add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (2 * UNITS_PER_WORD)); pop = GEN_INT (2 * UNITS_PER_WORD); } + + if (flag_force_indirect_call && !register_operand (fn, VOIDmode)) + { + scratch_reg = gen_rtx_REG (word_mode, scratch_regno); + + if (GET_MODE (fn) != word_mode) + fn = gen_rtx_ZERO_EXTEND (word_mode, fn); + + fn = copy_to_suggested_reg (fn, scratch_reg, word_mode); + } + call_insn = ix86_expand_call (NULL_RTX, gen_rtx_MEM (QImode, fn), GEN_INT (UNITS_PER_WORD), constm1_rtx, pop, false); @@ -10558,7 +10607,6 @@ ix86_expand_split_stack_prologue (void) slot. */ if (cfun->machine->split_stack_varargs_pointer != NULL_RTX) { - unsigned int scratch_regno; rtx frame_reg; int words; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 0370747..47340c6 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -54,6 +54,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_APX_EGPR (ix86_apx_features & apx_egpr) #define TARGET_APX_PUSH2POP2 (ix86_apx_features & apx_push2pop2) #define TARGET_APX_NDD (ix86_apx_features & apx_ndd) +#define TARGET_APX_PPX (ix86_apx_features & apx_ppx) #include "config/vxworks-dummy.h" @@ -2374,13 +2375,13 @@ constexpr wide_int_bitmask PTA_SKYLAKE = PTA_BROADWELL | PTA_AES | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES | PTA_SGX; constexpr wide_int_bitmask PTA_SKYLAKE_AVX512 = PTA_SKYLAKE | PTA_AVX512F | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU - | PTA_CLWB; + | PTA_CLWB | PTA_EVEX512; constexpr wide_int_bitmask PTA_CASCADELAKE = PTA_SKYLAKE_AVX512 | PTA_AVX512VNNI; constexpr wide_int_bitmask PTA_COOPERLAKE = PTA_CASCADELAKE | PTA_AVX512BF16; constexpr wide_int_bitmask PTA_CANNONLAKE = PTA_SKYLAKE | PTA_AVX512F | PTA_AVX512CD | PTA_AVX512VL | PTA_AVX512BW | PTA_AVX512DQ | PTA_PKU - | PTA_AVX512VBMI | PTA_AVX512IFMA | PTA_SHA; + | PTA_AVX512VBMI | PTA_AVX512IFMA | PTA_SHA | PTA_EVEX512; constexpr wide_int_bitmask PTA_ICELAKE_CLIENT = PTA_CANNONLAKE | PTA_AVX512VNNI | PTA_GFNI | PTA_VAES | PTA_AVX512VBMI2 | PTA_VPCLMULQDQ | PTA_AVX512BITALG | PTA_RDPID | PTA_AVX512VPOPCNTDQ; @@ -2440,7 +2441,7 @@ constexpr wide_int_bitmask PTA_ZNVER3 = PTA_ZNVER2 | PTA_VAES | PTA_VPCLMULQDQ constexpr wide_int_bitmask PTA_ZNVER4 = PTA_ZNVER3 | PTA_AVX512F | PTA_AVX512DQ | PTA_AVX512IFMA | PTA_AVX512CD | PTA_AVX512BW | PTA_AVX512VL | PTA_AVX512BF16 | PTA_AVX512VBMI | PTA_AVX512VBMI2 | PTA_GFNI - | PTA_AVX512VNNI | PTA_AVX512BITALG | PTA_AVX512VPOPCNTDQ; + | PTA_AVX512VNNI | PTA_AVX512BITALG | PTA_AVX512VPOPCNTDQ | PTA_EVEX512; constexpr wide_int_bitmask PTA_LUJIAZUI = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1b5a794..cb32de7 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -210,10 +210,13 @@ ;; For insn_callee_abi: UNSPEC_CALLEE_ABI - ;; For PUSH2/POP2 support + ;; For APX PUSH2/POP2 support UNSPEC_APXPUSH2 UNSPEC_APXPOP2_LOW UNSPEC_APXPOP2_HIGH + + ;; For APX PPX support + UNSPEC_APX_PPX ]) (define_c_enum "unspecv" [ @@ -3769,7 +3772,7 @@ (match_operand:DI 2 "register_operand" "r")] UNSPEC_APXPUSH2))] "TARGET_APX_PUSH2POP2" - "push2\t%1, %2" + "push2\t{%2, %1|%1, %2}" [(set_attr "mode" "TI") (set_attr "type" "multi") (set_attr "prefix" "evex")]) @@ -3781,7 +3784,47 @@ (set (match_operand:DI 2 "register_operand" "=r") (unspec:DI [(const_int 0)] UNSPEC_APXPOP2_HIGH))])] "TARGET_APX_PUSH2POP2" - "pop2\t%0, %2" + "pop2\t{%2, %0|%0, %2}" + [(set_attr "mode" "TI") + (set_attr "prefix" "evex")]) + +(define_insn "pushp_di" + [(set (match_operand:DI 0 "push_operand" "=<") + (match_operand:DI 1 "register_operand" "r")) + (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)] + "TARGET_64BIT" + "pushp\t%1" + [(set_attr "mode" "DI")]) + +(define_insn "popp_di" + [(set (match_operand:DI 0 "register_operand" "=r") + (match_operand:DI 1 "pop_operand" ">")) + (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)] + "TARGET_APX_PPX" + "popp\t%0" + [(set_attr "mode" "DI")]) + +(define_insn "push2p_di" + [(set (match_operand:TI 0 "push_operand" "=<") + (unspec:TI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "register_operand" "r")] + UNSPEC_APXPUSH2)) + (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)] + "TARGET_APX_PUSH2POP2 && TARGET_APX_PPX" + "push2p\t{%2, %1|%1, %2}" + [(set_attr "mode" "TI") + (set_attr "type" "multi") + (set_attr "prefix" "evex")]) + +(define_insn "pop2p_di" + [(parallel [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:TI 1 "pop_operand" ">")] + UNSPEC_APXPOP2_LOW)) + (set (match_operand:DI 2 "register_operand" "=r") + (unspec:DI [(const_int 0)] UNSPEC_APXPOP2_HIGH)) + (unspec:DI [(const_int 0)] UNSPEC_APX_PPX)])] + "TARGET_APX_PUSH2POP2 && TARGET_APX_PPX" + "pop2p\t{%2, %0|%0, %2}" [(set_attr "mode" "TI") (set_attr "prefix" "evex")]) @@ -16836,7 +16879,8 @@ (const_int 1) (and:QI (match_operand:QI 2 "register_operand") - (match_operand 3 "const_int_operand")))]) + (match_operand 3 "const_int_operand"))) + (const_int 0)]) (label_ref (match_operand 4)) (pc))) (clobber (reg:CC FLAGS_REG))] @@ -16872,7 +16916,8 @@ (subreg:QI (and:SWI248 (match_operand:SWI248 2 "register_operand") - (match_operand 3 "const_int_operand")) 0))]) + (match_operand 3 "const_int_operand")) 0)) + (const_int 0)]) (label_ref (match_operand 4)) (pc))) (clobber (reg:CC FLAGS_REG))] @@ -19988,8 +20033,10 @@ "! TARGET_POPCNT" { rtx scratch = gen_reg_rtx (QImode); + rtx tmp = gen_reg_rtx (HImode); - emit_insn (gen_parityhi2_cmp (operands[1])); + emit_move_insn (tmp, operands[1]); + emit_insn (gen_parityhi2_cmp (tmp)); ix86_expand_setcc (scratch, ORDERED, gen_rtx_REG (CCmode, FLAGS_REG), const0_rtx); diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 0c3b8f4..b2edfac 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -36,6 +36,13 @@ HOST_WIDE_INT ix86_isa_flags_explicit Variable HOST_WIDE_INT ix86_isa_flags2_explicit +; Indicate if AVX512 and AVX10.1 are explicitly set no. +Variable +int ix86_no_avx512_explicit = 0 + +Variable +int ix86_no_avx10_1_explicit = 0 + ; Additional target flags Variable int ix86_target_flags @@ -96,6 +103,14 @@ HOST_WIDE_INT x_ix86_isa_flags2_explicit TargetSave HOST_WIDE_INT x_ix86_isa_flags_explicit +;; which flags were passed by the user +TargetSave +HOST_WIDE_INT x_ix86_no_avx512_explicit + +;; which flags were passed by the user +TargetSave +HOST_WIDE_INT x_ix86_no_avx10_1_explicit + ;; whether -mtune was not specified TargetSave unsigned char tune_defaulted @@ -1334,6 +1349,9 @@ EnumValue Enum(apx_features) String(ndd) Value(apx_ndd) Set(4) EnumValue +Enum(apx_features) String(ppx) Value(apx_ppx) Set(5) + +EnumValue Enum(apx_features) String(all) Value(apx_all) Set(1) mapx-inline-asm-use-gpr32 @@ -1348,3 +1366,18 @@ Support 512 bit vector built-in functions and code generation. musermsr Target Mask(ISA2_USER_MSR) Var(ix86_isa_flags2) Save Support USER_MSR built-in functions and code generation. + +mavx10.1-256 +Target Mask(ISA2_AVX10_1_256) Var(ix86_isa_flags2) Save +Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, +and AVX10.1 built-in functions and code generation. + +mavx10.1-512 +Target Mask(ISA2_AVX10_1_512) Var(ix86_isa_flags2) Save +Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, +and AVX10.1-512 built-in functions and code generation. + +mavx10.1 +Target Alias(mavx10.1-256) +Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, +and AVX10.1 built-in functions and code generation. diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 0f16d2a..a07a921 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -120,13 +120,15 @@ [(V2SI "SI") (V2SF "SF") (V4HF "HF") (V4BF "BF") (V2HF "HF") (V2BF "BF") - (V4HI "HI") (V2HI "HI")]) + (V4HI "HI") (V2HI "HI") + (V8QI "QI")]) (define_mode_attr mmxscalarmodelower [(V2SI "si") (V2SF "sf") (V4HF "hf") (V4BF "bf") (V2HF "hf") (V2BF "bf") - (V4HI "hi") (V2HI "hi")]) + (V4HI "hi") (V2HI "hi") + (V8QI "qi")]) (define_mode_attr Yv_Yw [(V8QI "Yw") (V4HI "Yw") (V2SI "Yv") (V1DI "Yv") (V2SF "Yv")]) @@ -6094,6 +6096,31 @@ (set_attr "type" "mmxshft,sseiadd,sseiadd") (set_attr "mode" "DI,TI,TI")]) +(define_expand "reduc_<code>_scal_<mode>" + [(any_logic:MMXMODE12 + (match_operand:<mmxscalarmode> 0 "register_operand") + (match_operand:MMXMODE12 1 "register_operand"))] + "TARGET_MMX_WITH_SSE" +{ + rtx tmp = gen_reg_rtx (<MODE>mode); + ix86_expand_reduc (gen_<code><mode>3, tmp, operands[1]); + emit_insn (gen_vec_extract<mode><mmxscalarmodelower> (operands[0], + tmp, const0_rtx)); + DONE; +}) + +(define_expand "reduc_<code>_scal_v4qi" + [(any_logic:V4QI + (match_operand:QI 0 "register_operand") + (match_operand:V4QI 1 "register_operand"))] + "TARGET_SSE2" +{ + rtx tmp = gen_reg_rtx (V4QImode); + ix86_expand_reduc (gen_<code>v4qi3, tmp, operands[1]); + emit_insn (gen_vec_extractv4qiqi (operands[0], tmp, const0_rtx)); + DONE; +}) + (define_expand "reduc_plus_scal_v8qi" [(plus:V8QI (match_operand:QI 0 "register_operand") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index d250a6c..4f51169 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -514,6 +514,12 @@ (V16SI "TARGET_AVX512F && TARGET_EVEX512") (V8SI "TARGET_AVX2") V4SI (V8DI "TARGET_AVX512F && TARGET_EVEX512") (V4DI "TARGET_AVX2") V2DI]) +(define_mode_iterator VI_AVX_AVX512F + [(V64QI "TARGET_AVX512F && TARGET_EVEX512") (V32QI "TARGET_AVX") V16QI + (V32HI "TARGET_AVX512F && TARGET_EVEX512") (V16HI "TARGET_AVX") V8HI + (V16SI "TARGET_AVX512F && TARGET_EVEX512") (V8SI "TARGET_AVX") V4SI + (V8DI "TARGET_AVX512F && TARGET_EVEX512") (V4DI "TARGET_AVX") V2DI]) + ;; All QImode vector integer modes (define_mode_iterator VI1 [(V32QI "TARGET_AVX") V16QI]) @@ -3417,7 +3423,9 @@ (define_mode_iterator REDUC_SSE_PLUS_MODE [(V2DF "TARGET_SSE") (V4SF "TARGET_SSE") - (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL")]) + (V8HF "TARGET_AVX512FP16 && TARGET_AVX512VL") + (V8HI "TARGET_SSE2") (V4SI "TARGET_SSE2") + (V2DI "TARGET_SSE2")]) (define_expand "reduc_plus_scal_<mode>" [(plus:REDUC_SSE_PLUS_MODE @@ -3458,8 +3466,12 @@ (V8DF "TARGET_AVX512F && TARGET_EVEX512") (V16SF "TARGET_AVX512F && TARGET_EVEX512") (V32HF "TARGET_AVX512FP16 && TARGET_AVX512VL && TARGET_EVEX512") - (V32QI "TARGET_AVX") - (V64QI "TARGET_AVX512F && TARGET_EVEX512")]) + (V32QI "TARGET_AVX") (V16HI "TARGET_AVX") + (V8SI "TARGET_AVX") (V4DI "TARGET_AVX") + (V64QI "TARGET_AVX512F && TARGET_EVEX512") + (V32HI "TARGET_AVX512F && TARGET_EVEX512") + (V16SI "TARGET_AVX512F && TARGET_EVEX512") + (V8DI "TARGET_AVX512F && TARGET_EVEX512")]) (define_expand "reduc_plus_scal_<mode>" [(plus:REDUC_PLUS_MODE @@ -3597,6 +3609,42 @@ (set_attr "prefix" "evex") (set_attr "mode" "<MODE>")]) +(define_expand "reduc_<code>_scal_<mode>" + [(any_logic:VI_128 + (match_operand:<ssescalarmode> 0 "register_operand") + (match_operand:VI_128 1 "register_operand"))] + "TARGET_SSE2" +{ + rtx tmp = gen_reg_rtx (<MODE>mode); + ix86_expand_reduc (gen_<code><mode>3, tmp, operands[1]); + emit_insn (gen_vec_extract<mode><ssescalarmodelower> (operands[0], + tmp, const0_rtx)); + DONE; +}) + +(define_mode_iterator REDUC_ANY_LOGIC_MODE + [(V32QI "TARGET_AVX") (V16HI "TARGET_AVX") + (V8SI "TARGET_AVX") (V4DI "TARGET_AVX") + (V64QI "TARGET_AVX512F && TARGET_EVEX512") + (V32HI "TARGET_AVX512F && TARGET_EVEX512") + (V16SI "TARGET_AVX512F && TARGET_EVEX512") + (V8DI "TARGET_AVX512F && TARGET_EVEX512")]) + +(define_expand "reduc_<code>_scal_<mode>" + [(any_logic:REDUC_ANY_LOGIC_MODE + (match_operand:<ssescalarmode> 0 "register_operand") + (match_operand:REDUC_ANY_LOGIC_MODE 1 "register_operand"))] + "" +{ + rtx tmp = gen_reg_rtx (<ssehalfvecmode>mode); + emit_insn (gen_vec_extract_hi_<mode> (tmp, operands[1])); + rtx tmp2 = gen_reg_rtx (<ssehalfvecmode>mode); + rtx tmp3 = gen_lowpart (<ssehalfvecmode>mode, operands[1]); + emit_insn (gen_<code><ssehalfvecmodelower>3 (tmp2, tmp, tmp3)); + emit_insn (gen_reduc_<code>_scal_<ssehalfvecmodelower> (operands[0], tmp2)); + DONE; +}) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parallel floating point comparisons @@ -27868,8 +27916,8 @@ (define_expand "cbranch<mode>4" [(set (reg:CC FLAGS_REG) - (compare:CC (match_operand:VI48_AVX_AVX512F 1 "register_operand") - (match_operand:VI48_AVX_AVX512F 2 "nonimmediate_operand"))) + (compare:CC (match_operand:VI_AVX_AVX512F 1 "register_operand") + (match_operand:VI_AVX_AVX512F 2 "nonimmediate_operand"))) (set (pc) (if_then_else (match_operator 0 "bt_comparison_operator" [(reg:CC FLAGS_REG) (const_int 0)]) diff --git a/gcc/config/linux-protos.h b/gcc/config/linux-protos.h index f2ea930..8342498 100644 --- a/gcc/config/linux-protos.h +++ b/gcc/config/linux-protos.h @@ -22,3 +22,4 @@ extern bool linux_has_ifunc_p (void); extern bool linux_libc_has_function (enum function_class fn_class, tree); extern unsigned linux_libm_function_max_error (unsigned, machine_mode, bool); +extern unsigned linux_fortify_source_default_level (); diff --git a/gcc/config/linux.cc b/gcc/config/linux.cc index 9114e55..c8df6c7 100644 --- a/gcc/config/linux.cc +++ b/gcc/config/linux.cc @@ -49,3 +49,12 @@ linux_libm_function_max_error (unsigned cfn, machine_mode mode, return glibc_linux_libm_function_max_error (cfn, mode, boundary_p); return default_libm_function_max_error (cfn, mode, boundary_p); } + +unsigned +linux_fortify_source_default_level () +{ + if (OPTION_GLIBC && TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 35) + return 3; + + return 2; +} diff --git a/gcc/config/linux.h b/gcc/config/linux.h index ac56816..79b6537 100644 --- a/gcc/config/linux.h +++ b/gcc/config/linux.h @@ -216,3 +216,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # define TARGET_LIBM_FUNCTION_MAX_ERROR linux_libm_function_max_error #endif + +#undef TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL +#define TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL linux_fortify_source_default_level diff --git a/gcc/config/loongarch/gnu-user.h b/gcc/config/loongarch/gnu-user.h index 9616d6e..e9f4bce 100644 --- a/gcc/config/loongarch/gnu-user.h +++ b/gcc/config/loongarch/gnu-user.h @@ -34,9 +34,9 @@ along with GCC; see the file COPYING3. If not see "/lib" ABI_GRLEN_SPEC "/ld-linux-loongarch-" ABI_SPEC ".so.1" #define MUSL_ABI_SPEC \ - "%{mabi=lp64d:-lp64d}" \ - "%{mabi=lp64f:-lp64f}" \ - "%{mabi=lp64s:-lp64s}" + "%{mabi=lp64d:}" \ + "%{mabi=lp64f:-sp}" \ + "%{mabi=lp64s:-sf}" #undef MUSL_DYNAMIC_LINKER #define MUSL_DYNAMIC_LINKER \ diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h index af7bd63..851ff86 100644 --- a/gcc/config/loongarch/loongarch-def.h +++ b/gcc/config/loongarch/loongarch-def.h @@ -46,7 +46,10 @@ along with GCC; see the file COPYING3. If not see #ifndef LOONGARCH_DEF_H #define LOONGARCH_DEF_H +#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS) #include <stdint.h> +#endif + #include "loongarch-tune.h" #ifdef __cplusplus @@ -62,9 +65,11 @@ extern const char* loongarch_isa_base_strings[]; #define ISA_BASE_LA64V110 1 #define N_ISA_BASE_TYPES 2 +#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS) /* Unlike other arrays, this is defined in loongarch-cpu.cc. The problem is we cannot use the C++ header options.h in loongarch-def.c. */ extern int64_t loongarch_isa_base_features[]; +#endif /* enum isa_ext_* */ extern const char* loongarch_isa_ext_strings[]; @@ -121,6 +126,7 @@ extern const char* loongarch_cmodel_strings[]; #define M_OPT_ABSENT(opt_enum) ((opt_enum) == M_OPT_UNSET) +#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS) /* Internal representation of the target. */ struct loongarch_isa { @@ -150,6 +156,9 @@ struct loongarch_target int cmodel; /* CMODEL_ */ }; +extern struct loongarch_isa loongarch_cpu_default_isa[]; +#endif + /* CPU properties. */ /* index */ #define CPU_NATIVE 0 @@ -162,7 +171,6 @@ struct loongarch_target /* parallel tables. */ extern const char* loongarch_cpu_strings[]; -extern struct loongarch_isa loongarch_cpu_default_isa[]; extern int loongarch_cpu_issue_rate[]; extern int loongarch_cpu_multipass_dfa_lookahead[]; diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index ce601a3..d3896d7 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -142,12 +142,16 @@ struct loongarch_address_info METHOD_LU52I: Load 52-63 bit of the immediate number. + + METHOD_MIRROR: + Copy 0-31 bit of the immediate number to 32-63bit. */ enum loongarch_load_imm_method { METHOD_NORMAL, METHOD_LU32I, - METHOD_LU52I + METHOD_LU52I, + METHOD_MIRROR }; struct loongarch_integer_op @@ -1556,11 +1560,23 @@ loongarch_build_integer (struct loongarch_integer_op *codes, int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31; int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51; + + uint32_t hival = (uint32_t) (value >> 32); + uint32_t loval = (uint32_t) value; + /* Determine whether the upper 32 bits are sign-extended from the lower 32 bits. If it is, the instructions to load the high order can be ommitted. */ if (lu32i[sign31] && lu52i[sign31]) return cost; + /* If the lower 32 bits are the same as the upper 32 bits, just copy + the lower 32 bits to the upper 32 bits. */ + else if (loval == hival) + { + codes[cost].method = METHOD_MIRROR; + codes[cost].curr_value = value; + return cost + 1; + } /* Determine whether bits 32-51 are sign-extended from the lower 32 bits. If so, directly load 52-63 bits. */ else if (lu32i[sign31]) @@ -3234,6 +3250,10 @@ loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) gen_rtx_AND (DImode, x, GEN_INT (0xfffffffffffff)), GEN_INT (codes[i].value)); break; + case METHOD_MIRROR: + gcc_assert (mode == DImode); + emit_insn (gen_insvdi (x, GEN_INT (32), GEN_INT (32), x)); + break; default: gcc_unreachable (); } @@ -4249,7 +4269,7 @@ loongarch_split_plus_constant (rtx *op, machine_mode mode) else if (loongarch_addu16i_imm12_operand_p (v, mode)) a = (v & ~HWIT_UC_0xFFF) + ((v & 0x800) << 1); else if (mode == DImode && DUAL_ADDU16I_OPERAND (v)) - a = (v > 0 ? 0x7fff : -0x8000) << 16; + a = (v > 0 ? 0x7fff0000 : ~0x7fffffff); else gcc_unreachable (); @@ -8607,8 +8627,9 @@ void loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) { machine_mode vmode = GET_MODE (target); + machine_mode vimode = GET_MODE (sel); auto nelt = GET_MODE_NUNITS (vmode); - auto round_reg = gen_reg_rtx (vmode); + auto round_reg = gen_reg_rtx (vimode); rtx round_data[MAX_VECT_LEN]; for (int i = 0; i < nelt; i += 1) @@ -8616,9 +8637,16 @@ loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) round_data[i] = GEN_INT (0x1f); } - rtx round_data_rtx = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, round_data)); + rtx round_data_rtx = gen_rtx_CONST_VECTOR (vimode, gen_rtvec_v (nelt, round_data)); emit_move_insn (round_reg, round_data_rtx); + if (vmode != vimode) + { + target = lowpart_subreg (vimode, target, vmode); + op0 = lowpart_subreg (vimode, op0, vmode); + op1 = lowpart_subreg (vimode, op1, vmode); + } + switch (vmode) { case E_V16QImode: @@ -8626,17 +8654,11 @@ loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) emit_insn (gen_lsx_vshuf_b (target, op1, op0, sel)); break; case E_V2DFmode: - emit_insn (gen_andv2di3 (sel, sel, round_reg)); - emit_insn (gen_lsx_vshuf_d_f (target, sel, op1, op0)); - break; case E_V2DImode: emit_insn (gen_andv2di3 (sel, sel, round_reg)); emit_insn (gen_lsx_vshuf_d (target, sel, op1, op0)); break; case E_V4SFmode: - emit_insn (gen_andv4si3 (sel, sel, round_reg)); - emit_insn (gen_lsx_vshuf_w_f (target, sel, op1, op0)); - break; case E_V4SImode: emit_insn (gen_andv4si3 (sel, sel, round_reg)); emit_insn (gen_lsx_vshuf_w (target, sel, op1, op0)); diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md index 8ea41c8..5e8d8d7 100644 --- a/gcc/config/loongarch/lsx.md +++ b/gcc/config/loongarch/lsx.md @@ -837,7 +837,7 @@ [(match_operand:LSX 0 "register_operand") (match_operand:LSX 1 "register_operand") (match_operand:LSX 2 "register_operand") - (match_operand:LSX 3 "register_operand")] + (match_operand:<VIMODE> 3 "register_operand")] "ISA_HAS_LSX" { loongarch_expand_vec_perm (operands[0], operands[1], diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index a254547..0666310 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -5732,7 +5732,7 @@ (define_insn "rdhwr_synci_step_<mode>" [(set (match_operand:P 0 "register_operand" "=d") - (unspec_volatile [(const_int 1)] + (unspec_volatile:P [(const_int 1)] UNSPEC_RDHWR))] "ISA_HAS_SYNCI" "rdhwr\t%0,$1") diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index 0eeff95..570bcc7 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -721,7 +721,7 @@ nvptx_function_arg_advance (cumulative_args_t cum_v, const function_arg_info &) /* Implement TARGET_FUNCTION_ARG_BOUNDARY. - For nvptx This is only used for varadic args. The type has already + For nvptx This is only used for variadic args. The type has already been promoted and/or converted to invisible reference. */ static unsigned @@ -1549,7 +1549,7 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) if (!TARGET_SOFT_STACK) { /* Declare a local var for outgoing varargs. */ - if (cfun->machine->has_varadic) + if (cfun->machine->has_variadic) init_frame (file, STACK_POINTER_REGNUM, UNITS_PER_WORD, crtl->outgoing_args_size); @@ -1559,7 +1559,7 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) init_frame (file, FRAME_POINTER_REGNUM, alignment, ROUND_UP (sz, GET_MODE_SIZE (DImode))); } - else if (need_frameptr || cfun->machine->has_varadic || cfun->calls_alloca + else if (need_frameptr || cfun->machine->has_variadic || cfun->calls_alloca || (cfun->machine->has_simtreg && !crtl->is_leaf)) init_softstack_frame (file, alignment, sz); @@ -1796,13 +1796,13 @@ nvptx_call_args (rtx arg, tree fntype) if (!cfun->machine->doing_call) { cfun->machine->doing_call = true; - cfun->machine->is_varadic = false; + cfun->machine->is_variadic = false; cfun->machine->num_args = 0; if (fntype && stdarg_p (fntype)) { - cfun->machine->is_varadic = true; - cfun->machine->has_varadic = true; + cfun->machine->is_variadic = true; + cfun->machine->has_variadic = true; cfun->machine->num_args++; } } @@ -1872,7 +1872,7 @@ nvptx_expand_call (rtx retval, rtx address) } unsigned nargs = cfun->machine->num_args; - if (cfun->machine->is_varadic) + if (cfun->machine->is_variadic) { varargs = gen_reg_rtx (Pmode); emit_move_insn (varargs, stack_pointer_rtx); diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index 407fd70..71cab66 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -209,8 +209,8 @@ struct GTY(()) machine_function { rtx_expr_list *call_args; /* Arg list for the current call. */ bool doing_call; /* Within a CALL_ARGS ... CALL_ARGS_END sequence. */ - bool is_varadic; /* This call is varadic */ - bool has_varadic; /* Current function has a varadic call. */ + bool is_variadic; /* This call is variadic */ + bool has_variadic; /* Current function has a variadic call. */ bool has_chain; /* Current function has outgoing static chain. */ bool has_softstack; /* Current function has a soft stack frame. */ bool has_simtreg; /* Current function has an OpenMP SIMD region. */ diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc index 565c948..2ee9877 100644 --- a/gcc/config/pa/pa.cc +++ b/gcc/config/pa/pa.cc @@ -1872,9 +1872,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg) if (reg_plus_base_memory_operand (op1, GET_MODE (op1))) { - if (!(TARGET_PA_20 - && !TARGET_ELF32 - && INT_14_BITS (XEXP (XEXP (op1, 0), 1))) + if (!(INT14_OK_STRICT && INT_14_BITS (XEXP (XEXP (op1, 0), 1))) && !INT_5_BITS (XEXP (XEXP (op1, 0), 1))) { /* SCRATCH_REG will hold an address and maybe the actual data. @@ -1923,9 +1921,7 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode, rtx scratch_reg) if (reg_plus_base_memory_operand (op0, GET_MODE (op0))) { - if (!(TARGET_PA_20 - && !TARGET_ELF32 - && INT_14_BITS (XEXP (XEXP (op0, 0), 1))) + if (!(INT14_OK_STRICT && INT_14_BITS (XEXP (XEXP (op0, 0), 1))) && !INT_5_BITS (XEXP (XEXP (op0, 0), 1))) { /* SCRATCH_REG will hold an address and maybe the actual data. diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index aba2cec..d734286 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -1310,3 +1310,7 @@ do { \ /* Output default function prologue for hpux. */ #define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue + +/* An integer expression for the size in bits of the largest integer machine + mode that should actually be used. We allow pairs of registers. */ +#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode) diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md index 1b50020..4c07c0a 100644 --- a/gcc/config/pa/predicates.md +++ b/gcc/config/pa/predicates.md @@ -308,6 +308,13 @@ if (reg_plus_base_memory_operand (op, mode)) { + /* There is no support for handling secondary reloads of integer + REG+D instructions in pa_emit_move_sequence. Further, the Q + constraint is used in more than simple move instructions. So, + we must return true and let reload handle the reload. */ + if (reload_in_progress) + return true; + /* Extract CONST_INT operand. */ if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize index bbb9261..ea2f67a 100755 --- a/gcc/config/riscv/arch-canonicalize +++ b/gcc/config/riscv/arch-canonicalize @@ -83,7 +83,7 @@ def arch_canonicalize(arch, isa_spec): new_arch = "" extra_long_ext = [] std_exts = [] - if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64i', 'rv64g']: + if arch[:5] in ['rv32e', 'rv32i', 'rv32g', 'rv64e', 'rv64i', 'rv64g']: new_arch = arch[:5].replace("g", "i") if arch[:5] in ['rv32g', 'rv64g']: std_exts = ['m', 'a', 'f', 'd'] diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index 80e41af..2d727c2 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -59,7 +59,7 @@ (match_operand:<RATIO64:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO64:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -74,7 +74,7 @@ (match_operand:<RATIO32:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO32:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -89,7 +89,7 @@ (match_operand:<RATIO16:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO16:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -104,7 +104,7 @@ (match_operand:<RATIO8:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO8:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -119,7 +119,7 @@ (match_operand:<RATIO4:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO4:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -134,7 +134,7 @@ (match_operand:<RATIO2:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO2:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -144,16 +144,16 @@ ;; larger SEW. Since RVV indexed load/store support zero extend ;; implicitly and not support scaling, we should only allow ;; operands[3] and operands[4] to be const_1_operand. -(define_expand "mask_len_gather_load<RATIO1:mode><RATIO1:mode>" +(define_expand "mask_len_gather_load<mode><mode>" [(match_operand:RATIO1 0 "register_operand") (match_operand 1 "pmode_reg_or_0_operand") (match_operand:RATIO1 2 "register_operand") - (match_operand 3 "<RATIO1:gs_extension>") - (match_operand 4 "<RATIO1:gs_scale>") - (match_operand:<RATIO1:VM> 5 "vector_mask_operand") + (match_operand 3 "<gs_extension>") + (match_operand 4 "<gs_scale>") + (match_operand:<VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO1:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, true); DONE; @@ -172,7 +172,7 @@ (match_operand:<RATIO64:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO64:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -187,7 +187,7 @@ (match_operand:<RATIO32:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO32:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -202,7 +202,7 @@ (match_operand:<RATIO16:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO16:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -217,7 +217,7 @@ (match_operand:<RATIO8:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO8:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -232,7 +232,7 @@ (match_operand:<RATIO4:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO4:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -247,7 +247,7 @@ (match_operand:<RATIO2:VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO2:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; @@ -257,16 +257,16 @@ ;; larger SEW. Since RVV indexed load/store support zero extend ;; implicitly and not support scaling, we should only allow ;; operands[3] and operands[4] to be const_1_operand. -(define_expand "mask_len_scatter_store<RATIO1:mode><RATIO1:mode>" +(define_expand "mask_len_scatter_store<mode><mode>" [(match_operand 0 "pmode_reg_or_0_operand") (match_operand:RATIO1 1 "register_operand") - (match_operand 2 "<RATIO1:gs_extension>") - (match_operand 3 "<RATIO1:gs_scale>") + (match_operand 2 "<gs_extension>") + (match_operand 3 "<gs_scale>") (match_operand:RATIO1 4 "register_operand") - (match_operand:<RATIO1:VM> 5 "vector_mask_operand") + (match_operand:<VM> 5 "vector_mask_operand") (match_operand 6 "autovec_length_operand") (match_operand 7 "const_0_operand")] - "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_mode_p (<RATIO1:MODE>mode)" + "TARGET_VECTOR" { riscv_vector::expand_gather_scatter (operands, false); DONE; diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 90567a8..525455f 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -41,6 +41,12 @@ (ior (match_operand 0 "arith_operand") (match_operand 0 "lui_operand"))) +(define_predicate "movcc_operand" + (if_then_else (match_test "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV + || TARGET_ZICOND_LIKE") + (match_operand 0 "sfb_alu_operand") + (match_operand 0 "arith_operand"))) + (define_predicate "const_csr_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) @@ -78,6 +84,10 @@ (and (match_code "const_int") (match_test "INTVAL (op) == 1 || INTVAL (op) == 4"))) +(define_predicate "const_1_or_8_operand" + (and (match_code "const_int") + (match_test "INTVAL (op) == 1 || INTVAL (op) == 8"))) + (define_predicate "reg_or_0_operand" (ior (match_operand 0 "const_0_operand") (match_operand 0 "register_operand"))) @@ -327,12 +337,12 @@ (define_predicate "modular_operator" (match_code "plus,minus,mult,ashift")) +(define_predicate "ne_operator" + (match_code "ne")) + (define_predicate "equality_operator" (match_code "eq,ne")) -(define_predicate "order_operator" - (match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu")) - (define_predicate "signed_order_operator" (match_code "eq,ne,lt,le,ge,gt")) @@ -480,10 +490,6 @@ (ior (match_operand 0 "register_operand") (match_code "const_vector"))) -(define_predicate "vector_gs_scale_operand_64" - (and (match_code "const_int") - (match_test "INTVAL (op) == 1 || (INTVAL (op) == 8 && Pmode == DImode)"))) - (define_predicate "vector_gs_extension_operand" (ior (match_operand 0 "const_1_operand") (and (match_operand 0 "const_0_operand") diff --git a/gcc/config/riscv/riscv-avlprop.cc b/gcc/config/riscv/riscv-avlprop.cc index 1f6ba40..d298f0e 100644 --- a/gcc/config/riscv/riscv-avlprop.cc +++ b/gcc/config/riscv/riscv-avlprop.cc @@ -104,6 +104,29 @@ avlprop_type_to_str (enum avlprop_type type) } } +/* Return true if the AVL of the INSN can be propagated. */ +static bool +avl_can_be_propagated_p (rtx_insn *rinsn) +{ + /* We can't do AVL propagation when the instruction is potentially + touching the element with i > AVL. So, we don't do AVL propagation + on these following situations: + + - The index of "vrgather dest, source, index" may pick up the + element which has index >= AVL, so we can't strip the elements + that has index >= AVL of source register. + - The last element of vslide1down is AVL + 1 according to RVV ISA: + vstart <= i < vl-1 vd[i] = vs2[i+1] if v0.mask[i] enabled + - The last multiple elements of vslidedown can be the element + has index >= AVL according to RVV ISA: + 0 <= i+OFFSET < VLMAX src[i] = vs2[i+OFFSET] + vstart <= i < vl vd[i] = src[i] if v0.mask[i] enabled. */ + return get_attr_type (rinsn) != TYPE_VGATHER + && get_attr_type (rinsn) != TYPE_VSLIDEDOWN + && get_attr_type (rinsn) != TYPE_VISLIDE1DOWN + && get_attr_type (rinsn) != TYPE_VFSLIDE1DOWN; +} + static bool vlmax_ta_p (rtx_insn *rinsn) { @@ -260,6 +283,8 @@ pass_avlprop::get_preferred_avl ( rtx pass_avlprop::get_vlmax_ta_preferred_avl (insn_info *insn) const { + if (!avl_can_be_propagated_p (insn->rtl ())) + return NULL_RTX; int sew = get_sew (insn->rtl ()); enum vlmul_type vlmul = get_vlmul (insn->rtl ()); int ratio = calculate_ratio (sew, vlmul); diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index dd1bd05..d70eb8e 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -51,7 +51,7 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) builtin_define ("__riscv_compressed"); if (TARGET_RVE) - builtin_define ("__riscv_32e"); + builtin_define (TARGET_64BIT ? "__riscv_64e" : "__riscv_32e"); if (TARGET_ATOMIC) builtin_define ("__riscv_atomic"); @@ -76,6 +76,7 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) switch (riscv_abi) { case ABI_ILP32E: + case ABI_LP64E: builtin_define ("__riscv_abi_rve"); gcc_fallthrough (); diff --git a/gcc/config/riscv/riscv-d.cc b/gcc/config/riscv/riscv-d.cc index cfeafa8..3ba3470 100644 --- a/gcc/config/riscv/riscv-d.cc +++ b/gcc/config/riscv/riscv-d.cc @@ -52,6 +52,7 @@ riscv_d_handle_target_float_abi (void) { case ABI_ILP32E: case ABI_ILP32: + case ABI_LP64E: case ABI_LP64: abi = "soft"; break; diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 532b1b6..e6e55ad 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -27,6 +27,7 @@ enum riscv_abi_type { ABI_ILP32F, ABI_ILP32D, ABI_LP64, + ABI_LP64E, ABI_LP64F, ABI_LP64D }; @@ -102,6 +103,18 @@ enum riscv_entity MAX_RISCV_ENTITIES }; +/* RISC-V stringop strategy. */ +enum riscv_stringop_strategy_enum { + /* Use scalar or vector instructions. */ + USE_AUTO, + /* Always use a library call. */ + USE_LIBCALL, + /* Only use scalar instructions. */ + USE_SCALAR, + /* Only use vector instructions. */ + USE_VECTOR +}; + #define TARGET_ZICOND_LIKE (TARGET_ZICOND || (TARGET_XVENTANACONDOPS && TARGET_64BIT)) /* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 196b53f..695ee24 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -132,8 +132,10 @@ riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT, int); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0); -extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx); +extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx, + bool *invert_ptr = nullptr); extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx); +extern rtx riscv_emit_unary (enum rtx_code code, rtx dest, rtx x); extern rtx riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y); #endif extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx); @@ -556,6 +558,7 @@ void expand_cond_binop (unsigned, rtx *); void expand_cond_ternop (unsigned, rtx *); void expand_popcount (rtx *); void expand_rawmemchr (machine_mode, rtx, rtx, rtx); +void emit_vec_extract (rtx, rtx, poly_int64); /* Rounding mode bitfield for fixed point VXRM. */ enum fixed_point_rounding_mode @@ -591,7 +594,6 @@ opt_machine_mode vectorize_related_mode (machine_mode, scalar_mode, unsigned int autovectorize_vector_modes (vec<machine_mode> *, bool); bool cmp_lmul_le_one (machine_mode); bool cmp_lmul_gt_one (machine_mode); -bool gather_scatter_valid_offset_mode_p (machine_mode); bool vls_mode_valid_p (machine_mode); bool vlmax_avl_type_p (rtx_insn *); bool has_vl_op (rtx_insn *); @@ -626,6 +628,7 @@ extern bool riscv_expand_strcmp (rtx, rtx, rtx, rtx, rtx); extern bool riscv_expand_strlen (rtx, rtx, rtx, rtx); /* Routines implemented in thead.cc. */ +extern bool extract_base_offset_in_addr (rtx, rtx *, rtx *); extern bool th_mempair_operands_p (rtx[4], bool, machine_mode); extern void th_mempair_order_operands (rtx[4], bool, machine_mode); extern void th_mempair_prepare_save_restore_operands (rtx[4], bool, diff --git a/gcc/config/riscv/riscv-string.cc b/gcc/config/riscv/riscv-string.cc index 57e8ad6..3b5e05e 100644 --- a/gcc/config/riscv/riscv-string.cc +++ b/gcc/config/riscv/riscv-string.cc @@ -710,6 +710,10 @@ riscv_block_move_loop (rtx dest, rtx src, unsigned HOST_WIDE_INT length, bool riscv_expand_block_move (rtx dest, rtx src, rtx length) { + if (riscv_memcpy_strategy == USE_LIBCALL + || riscv_memcpy_strategy == USE_VECTOR) + return false; + if (CONST_INT_P (length)) { unsigned HOST_WIDE_INT hwi_length = UINTVAL (length); @@ -773,7 +777,8 @@ expand_block_move (rtx dst_in, rtx src_in, rtx length_in) bnez a2, loop # Any more? ret # Return */ - if (!TARGET_VECTOR) + if (!TARGET_VECTOR || riscv_memcpy_strategy == USE_LIBCALL + || riscv_memcpy_strategy == USE_SCALAR) return false; HOST_WIDE_INT potential_ew = (MIN (MIN (MEM_ALIGN (src_in), MEM_ALIGN (dst_in)), BITS_PER_WORD) diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 291f3c7..983c037 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -294,8 +294,6 @@ public: "vsetvl zero, rs1/imm". */ poly_uint64 nunits = GET_MODE_NUNITS (vtype_mode); len = gen_int_mode (nunits, Pmode); - if (!satisfies_constraint_K (len)) - len = force_reg (Pmode, len); vls_p = true; } else if (can_create_pseudo_p ()) @@ -374,10 +372,24 @@ void emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl) { gcc_assert (!can_create_pseudo_p ()); + machine_mode mode = GET_MODE (ops[0]); - insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true); - e.set_vl (vl); - e.emit_insn ((enum insn_code) icode, ops); + if (imm_avl_p (mode)) + { + /* Even though VL is a real hardreg already allocated since + it is post-RA now, we still gain benefits that we emit + vsetivli zero, imm instead of vsetvli VL, zero which is + we can be more flexible in post-RA instruction scheduling. */ + insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, false); + e.set_vl (gen_int_mode (GET_MODE_NUNITS (mode), Pmode)); + e.emit_insn ((enum insn_code) icode, ops); + } + else + { + insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true); + e.set_vl (vl); + e.emit_insn ((enum insn_code) icode, ops); + } } /* Emit an RVV insn with a predefined vector length. Contrary to @@ -825,31 +837,13 @@ emit_vlmax_gather_insn (rtx target, rtx op, rtx sel) insn_code icode; machine_mode data_mode = GET_MODE (target); machine_mode sel_mode = GET_MODE (sel); - if (maybe_ne (GET_MODE_SIZE (data_mode), GET_MODE_SIZE (sel_mode))) - icode = code_for_pred_gatherei16 (data_mode); - else if (const_vec_duplicate_p (sel, &elt)) + if (const_vec_duplicate_p (sel, &elt)) { icode = code_for_pred_gather_scalar (data_mode); sel = elt; } - else if (CONST_VECTOR_P (sel) - && GET_MODE_BITSIZE (GET_MODE_INNER (sel_mode)) > 16 - && riscv_get_v_regno_alignment (data_mode) > 1) - { - /* If the inner mode of data is not QI or HI and data_lmul > 1, - emitting vrgatherei16.vv instruction will lower register - pressure. - data_mode sel_mode ei16 - RVVM1QI RVVM1QI RVVM2HI not needed - RVVM2QI RVVM2QI RVVM4HI not needed - RVVM2HI RVVM2HI RVVM2HI not needed - RVVM2SI RVVM2SI RVVM1HI need - RVVM4SI RVVM4SI RVVM2HI need - RVVM8DI RVVM8DI RVVM2HI need */ - PUT_MODE (sel, get_vector_mode (HImode, - GET_MODE_NUNITS (data_mode)).require ()); - icode = code_for_pred_gatherei16 (data_mode); - } + else if (maybe_ne (GET_MODE_SIZE (data_mode), GET_MODE_SIZE (sel_mode))) + icode = code_for_pred_gatherei16 (data_mode); else icode = code_for_pred_gather (data_mode); rtx ops[] = {target, op, sel}; @@ -863,13 +857,13 @@ emit_vlmax_masked_gather_mu_insn (rtx target, rtx op, rtx sel, rtx mask) insn_code icode; machine_mode data_mode = GET_MODE (target); machine_mode sel_mode = GET_MODE (sel); - if (maybe_ne (GET_MODE_SIZE (data_mode), GET_MODE_SIZE (sel_mode))) - icode = code_for_pred_gatherei16 (data_mode); - else if (const_vec_duplicate_p (sel, &elt)) + if (const_vec_duplicate_p (sel, &elt)) { icode = code_for_pred_gather_scalar (data_mode); sel = elt; } + else if (maybe_ne (GET_MODE_SIZE (data_mode), GET_MODE_SIZE (sel_mode))) + icode = code_for_pred_gatherei16 (data_mode); else icode = code_for_pred_gather (data_mode); rtx ops[] = {target, mask, target, op, sel}; @@ -2094,32 +2088,23 @@ expand_tuple_move (rtx *ops) machine_mode preferred_simd_mode (scalar_mode mode) { - /* We will disable auto-vectorization when TARGET_MIN_VLEN < 128 && - riscv_autovec_lmul < RVV_M2. Since GCC loop vectorizer report ICE when we - enable -march=rv64gc_zve32* and -march=rv32gc_zve64*. in the - 'can_duplicate_and_interleave_p' of tree-vect-slp.cc. Since both - RVVM1SImode in -march=*zve32*_zvl32b and RVVM1DImode in - -march=*zve64*_zvl64b are NUNITS = poly (1, 1), they will cause ICE in loop - vectorizer when we enable them in this target hook. Currently, we can - support auto-vectorization in -march=rv32_zve32x_zvl128b. Wheras, - -march=rv32_zve32x_zvl32b or -march=rv32_zve32x_zvl64b are disabled. */ if (autovec_use_vlmax_p ()) { - if (TARGET_MIN_VLEN < 128 && TARGET_MAX_LMUL < RVV_M2) - return word_mode; /* We use LMUL = 1 as base bytesize which is BYTES_PER_RISCV_VECTOR and riscv_autovec_lmul as multiply factor to calculate the the NUNITS to get the auto-vectorization mode. */ poly_uint64 nunits; poly_uint64 vector_size = BYTES_PER_RISCV_VECTOR * TARGET_MAX_LMUL; poly_uint64 scalar_size = GET_MODE_SIZE (mode); - gcc_assert (multiple_p (vector_size, scalar_size, &nunits)); + /* Disable vectorization when we can't find a RVV mode for it. + E.g. -march=rv64gc_zve32x doesn't have a vector mode to vectorize + a double (DFmode) type. */ + if (!multiple_p (vector_size, scalar_size, &nunits)) + return word_mode; machine_mode rvv_mode; if (get_vector_mode (mode, nunits).exists (&rvv_mode)) return rvv_mode; } - /* TODO: We will support minimum length VLS auto-vectorization in - the future. */ return word_mode; } @@ -2689,15 +2674,21 @@ expand_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1, return false; } -/* Modulo all SEL indices to ensure they are all in range if [0, MAX_SEL]. */ +/* Modulo all SEL indices to ensure they are all in range if [0, MAX_SEL]. + MAX_SEL is nunits - 1 if rtx_equal_p (op0, op1). Otherwise, it is + 2 * nunits - 1. */ static rtx -modulo_sel_indices (rtx sel, poly_uint64 max_sel) +modulo_sel_indices (rtx op0, rtx op1, rtx sel) { rtx sel_mod; machine_mode sel_mode = GET_MODE (sel); poly_uint64 nunits = GET_MODE_NUNITS (sel_mode); - /* If SEL is variable-length CONST_VECTOR, we don't need to modulo it. */ - if (!nunits.is_constant () && CONST_VECTOR_P (sel)) + poly_uint64 max_sel = rtx_equal_p (op0, op1) ? nunits - 1 : 2 * nunits - 1; + /* If SEL is variable-length CONST_VECTOR, we don't need to modulo it. + Or if SEL is constant-length within [0, MAX_SEL], no need to modulo the + indice. */ + if (CONST_VECTOR_P (sel) + && (!nunits.is_constant () || const_vec_all_in_range_p (sel, 0, max_sel))) sel_mod = sel; else { @@ -2747,9 +2738,7 @@ expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) out-of-range indices, so we need to modulo all the vec_perm indices to ensure they are all in range of [0, nunits - 1] when op0 == op1 or all in range of [0, 2 * nunits - 1] when op0 != op1. */ - rtx sel_mod - = modulo_sel_indices (sel, - rtx_equal_p (op0, op1) ? nunits - 1 : 2 * nunits - 1); + rtx sel_mod = modulo_sel_indices (op0, op1, sel); /* Check if the two values vectors are the same. */ if (rtx_equal_p (op0, op1)) @@ -2758,15 +2747,13 @@ expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) return; } - rtx max_sel = gen_const_vector_dup (sel_mode, 2 * nunits - 1); - /* This following sequence is handling the case that: __builtin_shufflevector (vec1, vec2, index...), the index can be any value in range of [0, 2 * nunits - 1]. */ machine_mode mask_mode; mask_mode = get_mask_mode (data_mode); rtx mask = gen_reg_rtx (mask_mode); - max_sel = gen_const_vector_dup (sel_mode, nunits); + rtx max_sel = gen_const_vector_dup (sel_mode, nunits); /* Step 1: generate a mask that should select everything >= nunits into the * mask. */ @@ -2991,14 +2978,15 @@ shuffle_compress_patterns (struct expand_vec_perm_d *d) if (compress_point < 0) return false; - /* It must be series increasing from compress point. */ - if (!d->perm.series_p (compress_point, 1, d->perm[compress_point], 1)) - return false; - /* We can only apply compress approach when all index values from 0 to compress point are increasing. */ for (int i = 1; i < compress_point; i++) - if (known_le (d->perm[i], d->perm[i - 1])) + if (maybe_le (d->perm[i], d->perm[i - 1])) + return false; + + /* It must be series increasing from compress point. */ + for (int i = 1 + compress_point; i < vlen; i++) + if (maybe_ne (d->perm[i], d->perm[i - 1] + 1)) return false; /* Success! */ @@ -3066,10 +3054,10 @@ shuffle_compress_patterns (struct expand_vec_perm_d *d) if (need_slideup_p) { int slideup_cnt = vlen - (d->perm[vlen - 1].to_constant () % vlen) - 1; - rtx ops[] = {d->target, d->op1, gen_int_mode (slideup_cnt, Pmode)}; + merge = gen_reg_rtx (vmode); + rtx ops[] = {merge, d->op1, gen_int_mode (slideup_cnt, Pmode)}; insn_code icode = code_for_pred_slide (UNSPEC_VSLIDEUP, vmode); emit_vlmax_insn (icode, BINARY_OP, ops); - merge = d->target; } insn_code icode = code_for_pred_compress (vmode); @@ -3204,6 +3192,11 @@ shuffle_bswap_pattern (struct expand_vec_perm_d *d) if (!d->perm.series_p (i, step, diff - i, step)) return false; + /* Disable when nunits < 4 since the later generic approach + is more profitable on BSWAP. */ + if (!known_gt (GET_MODE_NUNITS (d->vmode), 2)) + return false; + if (d->testing_p) return true; @@ -3235,6 +3228,42 @@ shuffle_bswap_pattern (struct expand_vec_perm_d *d) return true; } +/* Recognize the pattern that can be shuffled by vec_extract and slide1up + approach. */ + +static bool +shuffle_extract_and_slide1up_patterns (struct expand_vec_perm_d *d) +{ + poly_int64 nunits = GET_MODE_NUNITS (d->vmode); + + /* Recognize { nunits - 1, nunits, nunits + 1, ... }. */ + if (!d->perm.series_p (0, 2, nunits - 1, 2) + || !d->perm.series_p (1, 2, nunits, 2)) + return false; + + /* Disable when nunits < 4 since the later generic approach + is more profitable on indice = { nunits - 1, nunits }. */ + if (!known_gt (nunits, 2)) + return false; + + /* Success! */ + if (d->testing_p) + return true; + + /* Extract the last element of the first vector. */ + scalar_mode smode = GET_MODE_INNER (d->vmode); + rtx tmp = gen_reg_rtx (smode); + emit_vec_extract (tmp, d->op0, nunits - 1); + + /* Insert the scalar into element 0. */ + unsigned int unspec + = FLOAT_MODE_P (d->vmode) ? UNSPEC_VFSLIDE1UP : UNSPEC_VSLIDE1UP; + insn_code icode = code_for_pred_slide (unspec, d->vmode); + rtx ops[] = {d->target, d->op1, tmp}; + emit_vlmax_insn (icode, BINARY_OP, ops); + return true; +} + /* Recognize the pattern that can be shuffled by generic approach. */ static bool @@ -3247,20 +3276,35 @@ shuffle_generic_patterns (struct expand_vec_perm_d *d) if (!pow2p_hwi (d->perm.encoding().npatterns ())) return false; - /* Permuting two SEW8 variable-length vectors need vrgatherei16.vv. - Otherwise, it could overflow the index range. */ - if (!nunits.is_constant () && GET_MODE_INNER (d->vmode) == QImode - && !get_vector_mode (HImode, nunits).exists (&sel_mode)) - return false; + if (GET_MODE_INNER (d->vmode) == QImode) + { + if (nunits.is_constant ()) + { + /* If indice is LMUL8 CONST_VECTOR and any element value + exceed the range of 0 ~ 255, Forbid such permutation + since we need vector HI mode to hold such indice and + we don't have it. */ + if (!d->perm.all_in_range_p (0, 255) + && !get_vector_mode (HImode, nunits).exists (&sel_mode)) + return false; + } + else + { + /* Permuting two SEW8 variable-length vectors need vrgatherei16.vv. + Otherwise, it could overflow the index range. */ + if (!get_vector_mode (HImode, nunits).exists (&sel_mode)) + return false; + } + } + else if (riscv_get_v_regno_alignment (sel_mode) > 1 + && GET_MODE_INNER (sel_mode) != HImode) + sel_mode = get_vector_mode (HImode, nunits).require (); /* Success! */ if (d->testing_p) return true; rtx sel = vec_perm_indices_to_rtx (sel_mode, d->perm); - /* 'mov<mode>' generte interleave vector. */ - if (!nunits.is_constant ()) - sel = force_reg (sel_mode, sel); /* Some FIXED-VLMAX/VLS vector permutation situations call targethook instead of expand vec_perm<mode>, we handle it directly. */ expand_vec_perm (d->target, d->op0, d->op1, sel); @@ -3298,6 +3342,8 @@ expand_vec_perm_const_1 (struct expand_vec_perm_d *d) return true; if (shuffle_bswap_pattern (d)) return true; + if (shuffle_extract_and_slide1up_patterns (d)) + return true; if (shuffle_generic_patterns (d)) return true; return false; @@ -3630,7 +3676,7 @@ expand_gather_scatter (rtx *ops, bool is_load) offset elements. RVV spec only refers to the scale_log == 0 case. */ - if (!zero_extend_p || (zero_extend_p && scale_log2 != 0)) + if (!zero_extend_p || scale_log2 != 0) { if (zero_extend_p) inner_idx_mode @@ -4005,14 +4051,6 @@ vls_mode_valid_p (machine_mode vls_mode) return false; } -/* Return true if the gather/scatter offset mode is valid. */ -bool -gather_scatter_valid_offset_mode_p (machine_mode mode) -{ - machine_mode new_mode; - return get_vector_mode (Pmode, GET_MODE_NUNITS (mode)).exists (&new_mode); -} - /* We don't have to convert the floating point to integer when the mantissa is zero. Thus, ther will be a limitation for both the single and double precision floating point. There will be no @@ -4617,4 +4655,26 @@ can_be_broadcasted_p (rtx op) return can_create_pseudo_p () && nonmemory_operand (op, mode); } +/* Helper function to emit vec_extract_optab. */ +void +emit_vec_extract (rtx target, rtx src, poly_int64 index) +{ + machine_mode vmode = GET_MODE (src); + machine_mode smode = GET_MODE (target); + class expand_operand ops[3]; + enum insn_code icode + = convert_optab_handler (vec_extract_optab, vmode, smode); + gcc_assert (icode != CODE_FOR_nothing); + create_output_operand (&ops[0], target, smode); + ops[0].target = 1; + create_input_operand (&ops[1], src, vmode); + if (index.is_constant ()) + create_integer_operand (&ops[2], index); + else + create_input_operand (&ops[2], gen_int_mode (index, Pmode), Pmode); + expand_insn (icode, 3, ops); + if (ops[0].value != target) + emit_move_insn (target, ops[0].value); +} + } // namespace riscv_vector diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index c2bd1c2..a4fc858 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "calls.h" #include "function.h" #include "explow.h" +#include "ifcvt.h" #include "memmodel.h" #include "emit-rtl.h" #include "reload.h" @@ -249,6 +250,21 @@ struct riscv_integer_op { The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI. */ #define RISCV_MAX_INTEGER_OPS 8 +enum riscv_fusion_pairs +{ + RISCV_FUSE_NOTHING = 0, + RISCV_FUSE_ZEXTW = (1 << 0), + RISCV_FUSE_ZEXTH = (1 << 1), + RISCV_FUSE_ZEXTWS = (1 << 2), + RISCV_FUSE_LDINDEXED = (1 << 3), + RISCV_FUSE_LUI_ADDI = (1 << 4), + RISCV_FUSE_AUIPC_ADDI = (1 << 5), + RISCV_FUSE_LUI_LD = (1 << 6), + RISCV_FUSE_AUIPC_LD = (1 << 7), + RISCV_FUSE_LDPREINCREMENT = (1 << 8), + RISCV_FUSE_ALIGNED_STD = (1 << 9), +}; + /* Costs of various operations on the different architectures. */ struct riscv_tune_param @@ -264,6 +280,7 @@ struct riscv_tune_param unsigned short fmv_cost; bool slow_unaligned_access; bool use_divmod_expansion; + unsigned int fusible_ops; }; @@ -344,6 +361,7 @@ static const struct riscv_tune_param rocket_tune_info = { 8, /* fmv_cost */ true, /* slow_unaligned_access */ false, /* use_divmod_expansion */ + RISCV_FUSE_NOTHING, /* fusible_ops */ }; /* Costs to use when optimizing for Sifive 7 Series. */ @@ -359,6 +377,7 @@ static const struct riscv_tune_param sifive_7_tune_info = { 8, /* fmv_cost */ true, /* slow_unaligned_access */ false, /* use_divmod_expansion */ + RISCV_FUSE_NOTHING, /* fusible_ops */ }; /* Costs to use when optimizing for T-HEAD c906. */ @@ -373,7 +392,8 @@ static const struct riscv_tune_param thead_c906_tune_info = { 5, /* memory_cost */ 8, /* fmv_cost */ false, /* slow_unaligned_access */ - false /* use_divmod_expansion */ + false, /* use_divmod_expansion */ + RISCV_FUSE_NOTHING, /* fusible_ops */ }; /* Costs to use when optimizing for a generic ooo profile. */ @@ -389,6 +409,7 @@ static const struct riscv_tune_param generic_ooo_tune_info = { 4, /* fmv_cost */ false, /* slow_unaligned_access */ false, /* use_divmod_expansion */ + RISCV_FUSE_NOTHING, /* fusible_ops */ }; /* Costs to use when optimizing for size. */ @@ -404,6 +425,7 @@ static const struct riscv_tune_param optimize_size_tune_info = { 8, /* fmv_cost */ false, /* slow_unaligned_access */ false, /* use_divmod_expansion */ + RISCV_FUSE_NOTHING, /* fusible_ops */ }; static bool riscv_avoid_shrink_wrapping_separate (); @@ -1577,6 +1599,14 @@ riscv_const_insns (rtx x) rtx elt; if (const_vec_duplicate_p (x, &elt)) { + /* We don't allow CONST_VECTOR for DI vector on RV32 + system since the ELT constant value can not held + within a single register to disable reload a DI + register vec_duplicate into vmv.v.x. */ + scalar_mode smode = GET_MODE_INNER (GET_MODE (x)); + if (maybe_gt (GET_MODE_SIZE (smode), UNITS_PER_WORD) + && !immediate_operand (elt, Pmode)) + return 0; /* Constants from -16 to 15 can be loaded with vmv.v.i. The Wc0, Wc1 constraints are already covered by the vi constraint so we do not need to check them here @@ -1702,6 +1732,14 @@ riscv_emit_set (rtx target, rtx src) return target; } +/* Emit an instruction of the form (set DEST (CODE X)). */ + +rtx +riscv_emit_unary (enum rtx_code code, rtx dest, rtx x) +{ + return riscv_emit_set (dest, gen_rtx_fmt_e (code, GET_MODE (dest), x)); +} + /* Emit an instruction of the form (set DEST (CODE X Y)). */ rtx @@ -2578,14 +2616,10 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) nunits = nunits * 2; } vmode = riscv_vector::get_vector_mode (smode, nunits).require (); - enum insn_code icode - = convert_optab_handler (vec_extract_optab, vmode, smode); - gcc_assert (icode != CODE_FOR_nothing); rtx v = gen_lowpart (vmode, SUBREG_REG (src)); for (unsigned int i = 0; i < num; i++) { - class expand_operand ops[3]; rtx result; if (num == 1) result = dest; @@ -2593,13 +2627,7 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) result = gen_lowpart (smode, dest); else result = gen_reg_rtx (smode); - create_output_operand (&ops[0], result, smode); - ops[0].target = 1; - create_input_operand (&ops[1], v, vmode); - create_integer_operand (&ops[2], index + i); - expand_insn (icode, 3, ops); - if (ops[0].value != result) - emit_move_insn (result, ops[0].value); + riscv_vector::emit_vec_extract (result, v, index + i); if (i == 1) { @@ -2905,7 +2933,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN *total = COSTS_N_INSNS (SINGLE_SHIFT_COST + 1); return true; } - if (order_operator (XEXP (x, 0), mode)) + if (ordered_comparison_operator (XEXP (x, 0), mode)) { *total = COSTS_N_INSNS (1); return true; @@ -3295,6 +3323,128 @@ riscv_address_cost (rtx addr, machine_mode mode, return riscv_address_insns (addr, mode, false); } +/* Implement TARGET_INSN_COST. We factor in the branch cost in the cost + calculation for conditional branches: one unit is considered the cost + of microarchitecture-dependent actual branch execution and therefore + multiplied by BRANCH_COST and any remaining units are considered fixed + branch overhead. Branches on a floating-point condition incur an extra + instruction cost as they will be split into an FCMP operation followed + by a branch on an integer condition. */ + +static int +riscv_insn_cost (rtx_insn *insn, bool speed) +{ + rtx x = PATTERN (insn); + int cost = pattern_cost (x, speed); + + if (JUMP_P (insn)) + { + if (GET_CODE (x) == PARALLEL) + x = XVECEXP (x, 0, 0); + if (GET_CODE (x) == SET + && GET_CODE (SET_DEST (x)) == PC + && GET_CODE (SET_SRC (x)) == IF_THEN_ELSE) + { + cost += COSTS_N_INSNS (BRANCH_COST (speed, false) - 1); + if (FLOAT_MODE_P (GET_MODE (XEXP (XEXP (SET_SRC (x), 0), 0)))) + cost += COSTS_N_INSNS (1); + } + } + return cost; +} + +/* Implement TARGET_MAX_NOCE_IFCVT_SEQ_COST. Like the default implementation, + but we consider cost units of branch instructions equal to cost units of + other instructions. */ + +static unsigned int +riscv_max_noce_ifcvt_seq_cost (edge e) +{ + bool predictable_p = predictable_edge_p (e); + + if (predictable_p) + { + if (OPTION_SET_P (param_max_rtl_if_conversion_predictable_cost)) + return param_max_rtl_if_conversion_predictable_cost; + } + else + { + if (OPTION_SET_P (param_max_rtl_if_conversion_unpredictable_cost)) + return param_max_rtl_if_conversion_unpredictable_cost; + } + + return COSTS_N_INSNS (BRANCH_COST (true, predictable_p)); +} + +/* Implement TARGET_NOCE_CONVERSION_PROFITABLE_P. We replace the cost of a + conditional branch assumed by `noce_find_if_block' at `COSTS_N_INSNS (2)' + by our actual conditional branch cost, observing that our branches test + conditions directly, so there is no preparatory extra condition-set + instruction. */ + +static bool +riscv_noce_conversion_profitable_p (rtx_insn *seq, + struct noce_if_info *if_info) +{ + struct noce_if_info riscv_if_info = *if_info; + + riscv_if_info.original_cost -= COSTS_N_INSNS (2); + riscv_if_info.original_cost += insn_cost (if_info->jump, if_info->speed_p); + + /* Hack alert! When `noce_try_store_flag_mask' uses `cstore<mode>4' + to emit a conditional set operation on DImode output it comes up + with a sequence such as: + + (insn 26 0 27 (set (reg:SI 140) + (eq:SI (reg/v:DI 137 [ c ]) + (const_int 0 [0]))) 302 {*seq_zero_disi} + (nil)) + (insn 27 26 28 (set (reg:DI 139) + (zero_extend:DI (reg:SI 140))) 116 {*zero_extendsidi2_internal} + (nil)) + + because our `cstore<mode>4' pattern expands to an insn that gives + a SImode output. The output of conditional set is 0 or 1 boolean, + so it is valid for input in any scalar integer mode and therefore + combine later folds the zero extend operation into an equivalent + conditional set operation that produces a DImode output, however + this redundant zero extend operation counts towards the cost of + the replacement sequence. Compensate for that by incrementing the + cost of the original sequence as well as the maximum sequence cost + accordingly. */ + rtx last_dest = NULL_RTX; + for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn)) + { + if (!NONDEBUG_INSN_P (insn)) + continue; + + rtx x = PATTERN (insn); + if (NONJUMP_INSN_P (insn) + && GET_CODE (x) == SET) + { + rtx src = SET_SRC (x); + if (last_dest != NULL_RTX + && GET_CODE (src) == ZERO_EXTEND + && REG_P (XEXP (src, 0)) + && REGNO (XEXP (src, 0)) == REGNO (last_dest)) + { + riscv_if_info.original_cost += COSTS_N_INSNS (1); + riscv_if_info.max_seq_cost += COSTS_N_INSNS (1); + } + last_dest = NULL_RTX; + rtx dest = SET_DEST (x); + if (COMPARISON_P (src) + && REG_P (dest) + && GET_MODE (dest) == SImode) + last_dest = dest; + } + else + last_dest = NULL_RTX; + } + + return default_noce_conversion_profitable_p (seq, &riscv_if_info); +} + /* Return one word of double-word value OP. HIGH_P is true to select the high part or false to select the low part. */ @@ -3779,6 +3929,7 @@ riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1, *op1 = const0_rtx; return; } + gcc_unreachable (); } if (splittable_const_int_operand (*op1, VOIDmode)) @@ -3833,7 +3984,8 @@ riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1, /* Like riscv_emit_int_compare, but for floating-point comparisons. */ static void -riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) +riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1, + bool *invert_ptr = nullptr) { rtx tmp0, tmp1, cmp_op0 = *op0, cmp_op1 = *op1; enum rtx_code fp_code = *code; @@ -3898,8 +4050,14 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) case NE: fp_code = EQ; - *code = EQ; - /* Fall through. */ + if (invert_ptr != nullptr) + *invert_ptr = !*invert_ptr; + else + { + cmp_op0 = riscv_force_binary (word_mode, fp_code, cmp_op0, cmp_op1); + cmp_op1 = const0_rtx; + } + gcc_fallthrough (); case EQ: case LE: @@ -3907,8 +4065,9 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) case GE: case GT: /* We have instructions for these cases. */ - *op0 = riscv_force_binary (word_mode, fp_code, cmp_op0, cmp_op1); - *op1 = const0_rtx; + *code = fp_code; + *op0 = cmp_op0; + *op1 = cmp_op1; break; case LTGT: @@ -3944,12 +4103,19 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *in /* Like riscv_expand_int_scc, but for floating-point comparisons. */ void -riscv_expand_float_scc (rtx target, enum rtx_code code, rtx op0, rtx op1) +riscv_expand_float_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, + bool *invert_ptr) { - riscv_emit_float_compare (&code, &op0, &op1); + riscv_emit_float_compare (&code, &op0, &op1, invert_ptr); - rtx cmp = riscv_force_binary (word_mode, code, op0, op1); - riscv_emit_set (target, lowpart_subreg (SImode, cmp, word_mode)); + machine_mode mode = GET_MODE (target); + if (mode != word_mode) + { + rtx cmp = riscv_force_binary (word_mode, code, op0, op1); + riscv_emit_set (target, lowpart_subreg (mode, cmp, word_mode)); + } + else + riscv_emit_binary (code, target, op0, op1); } /* Jump to LABEL if (CODE OP0 OP1) holds. */ @@ -3962,6 +4128,13 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1) else riscv_emit_int_compare (&code, &op0, &op1); + if (FLOAT_MODE_P (GET_MODE (op0))) + { + op0 = riscv_force_binary (word_mode, code, op0, op1); + op1 = const0_rtx; + code = NE; + } + rtx condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); emit_jump_insn (gen_condjump (condition, label)); } @@ -3976,87 +4149,105 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) rtx_code code = GET_CODE (op); rtx op0 = XEXP (op, 0); rtx op1 = XEXP (op, 1); - bool need_eq_ne_p = false; - - if (TARGET_XTHEADCONDMOV - && GET_MODE_CLASS (mode) == MODE_INT - && reg_or_0_operand (cons, mode) - && reg_or_0_operand (alt, mode) - && (GET_MODE (op) == mode || GET_MODE (op) == E_VOIDmode) - && GET_MODE (op0) == mode - && GET_MODE (op1) == mode - && (code == EQ || code == NE)) - need_eq_ne_p = true; - - if (need_eq_ne_p - || (TARGET_SFB_ALU && GET_MODE (op0) == word_mode)) - { - riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p); - rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); - - /* The expander is a bit loose in its specification of the true - arm of the conditional move. That allows us to support more - cases for extensions which are more general than SFB. But - does mean we need to force CONS into a register at this point. */ - cons = force_reg (GET_MODE (dest), cons); - emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), - cond, cons, alt))); - return true; - } - else if (TARGET_ZICOND_LIKE - && GET_MODE_CLASS (mode) == MODE_INT) + + if (((TARGET_ZICOND_LIKE + || (arith_operand (cons, mode) && arith_operand (alt, mode))) + && (GET_MODE_CLASS (mode) == MODE_INT)) + || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV) { - /* The comparison must be comparing WORD_MODE objects. We must - enforce that so that we don't strip away a sign_extension + machine_mode mode0 = GET_MODE (op0); + machine_mode mode1 = GET_MODE (op1); + + /* An integer comparison must be comparing WORD_MODE objects. We + must enforce that so that we don't strip away a sign_extension thinking it is unnecessary. We might consider using riscv_extend_operands if they are not already properly extended. */ - if ((GET_MODE (op0) != word_mode && GET_MODE (op0) != VOIDmode) - || (GET_MODE (op1) != word_mode && GET_MODE (op1) != VOIDmode)) + if ((INTEGRAL_MODE_P (mode0) && mode0 != word_mode) + || (INTEGRAL_MODE_P (mode1) && mode1 != word_mode)) return false; + /* In the fallback generic case use MODE rather than WORD_MODE for + the output of the SCC instruction, to match the mode of the NEG + operation below. The output of SCC is 0 or 1 boolean, so it is + valid for input in any scalar integer mode. */ + rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE + || TARGET_SFB_ALU || TARGET_XTHEADCONDMOV) + ? word_mode : mode); + bool invert = false; + /* Canonicalize the comparison. It must be an equality comparison - against 0. If it isn't, then emit an SCC instruction so that - we can then use an equality comparison against zero. */ - if (!equality_operator (op, VOIDmode) || op1 != CONST0_RTX (mode)) + of integer operands, or with SFB it can be any comparison of + integer operands. If it isn't, then emit an SCC instruction + so that we can then use an equality comparison against zero. */ + if ((!TARGET_SFB_ALU && !equality_operator (op, VOIDmode)) + || !INTEGRAL_MODE_P (mode0)) { - enum rtx_code new_code = NE; - bool *invert_ptr = 0; - bool invert = false; + bool *invert_ptr = nullptr; - if (code == LE || code == GE) + /* If riscv_expand_int_scc inverts the condition, then it will + flip the value of INVERT. We need to know where so that + we can adjust it for our needs. */ + if (code == LE || code == LEU || code == GE || code == GEU) invert_ptr = &invert; - /* Emit an scc like instruction into a temporary - so that we can use an EQ/NE comparison. */ - rtx tmp = gen_reg_rtx (word_mode); - - /* We can support both FP and integer conditional moves. */ - if (INTEGRAL_MODE_P (GET_MODE (XEXP (op, 0)))) + /* Emit an SCC-like instruction into a temporary so that we can + use an EQ/NE comparison. We can support both FP and integer + conditional moves. */ + if (INTEGRAL_MODE_P (mode0)) riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr); - else if (FLOAT_MODE_P (GET_MODE (XEXP (op, 0))) + else if (FLOAT_MODE_P (mode0) && fp_scc_comparison (op, GET_MODE (op))) - riscv_expand_float_scc (tmp, code, op0, op1); + riscv_expand_float_scc (tmp, code, op0, op1, &invert); else return false; - /* If riscv_expand_int_scc inverts the condition, then it will - flip the value of INVERT. We need to know where so that - we can adjust it for our needs. */ - if (invert) - new_code = EQ; - - op = gen_rtx_fmt_ee (new_code, mode, tmp, const0_rtx); + op = gen_rtx_fmt_ee (invert ? EQ : NE, mode, tmp, const0_rtx); /* We've generated a new comparison. Update the local variables. */ code = GET_CODE (op); op0 = XEXP (op, 0); op1 = XEXP (op, 1); } + else if (!TARGET_ZICOND_LIKE && !TARGET_SFB_ALU && !TARGET_XTHEADCONDMOV) + riscv_expand_int_scc (tmp, code, op0, op1, &invert); + + if (TARGET_SFB_ALU || TARGET_XTHEADCONDMOV) + { + riscv_emit_int_compare (&code, &op0, &op1, !TARGET_SFB_ALU); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + + /* The expander is a bit loose in its specification of the true + arm of the conditional move. That allows us to support more + cases for extensions which are more general than SFB. But + does mean we need to force CONS into a register at this point. */ + cons = force_reg (mode, cons); + /* With XTheadCondMov we need to force ALT into a register too. */ + alt = force_reg (mode, alt); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond, + cons, alt))); + return true; + } + else if (!TARGET_ZICOND_LIKE) + { + if (invert) + std::swap (cons, alt); + rtx reg1 = gen_reg_rtx (mode); + rtx reg2 = gen_reg_rtx (mode); + rtx reg3 = gen_reg_rtx (mode); + rtx reg4 = gen_reg_rtx (mode); + + riscv_emit_unary (NEG, reg1, tmp); + riscv_emit_binary (AND, reg2, reg1, cons); + riscv_emit_unary (NOT, reg3, reg1); + riscv_emit_binary (AND, reg4, reg3, alt); + riscv_emit_binary (IOR, dest, reg2, reg4); + return true; + } /* 0, reg or 0, imm */ - if (cons == CONST0_RTX (mode) - && (REG_P (alt) - || (CONST_INT_P (alt) && alt != CONST0_RTX (mode)))) + else if (cons == CONST0_RTX (mode) + && (REG_P (alt) + || (CONST_INT_P (alt) && alt != CONST0_RTX (mode)))) { riscv_emit_int_compare (&code, &op0, &op1, true); rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); @@ -7794,6 +7985,259 @@ riscv_sched_variable_issue (FILE *, int, rtx_insn *insn, int more) return more - 1; } +/* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports + instruction fusion of some sort. */ + +static bool +riscv_macro_fusion_p (void) +{ + return tune_param->fusible_ops != RISCV_FUSE_NOTHING; +} + +/* Return true iff the instruction fusion described by OP is enabled. */ + +static bool +riscv_fusion_enabled_p(enum riscv_fusion_pairs op) +{ + return tune_param->fusible_ops & op; +} + +/* Implement TARGET_SCHED_MACRO_FUSION_PAIR_P. Return true if PREV and CURR + should be kept together during scheduling. */ + +static bool +riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) +{ + rtx prev_set = single_set (prev); + rtx curr_set = single_set (curr); + /* prev and curr are simple SET insns i.e. no flag setting or branching. */ + bool simple_sets_p = prev_set && curr_set && !any_condjump_p (curr); + + if (!riscv_macro_fusion_p ()) + return false; + + if (simple_sets_p && (riscv_fusion_enabled_p (RISCV_FUSE_ZEXTW) || + riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH))) + { + /* We are trying to match the following: + prev (slli) == (set (reg:DI rD) + (ashift:DI (reg:DI rS) (const_int 32))) + curr (slri) == (set (reg:DI rD) + (lshiftrt:DI (reg:DI rD) (const_int <shift>))) + with <shift> being either 32 for FUSE_ZEXTW, or + `less than 32 for FUSE_ZEXTWS. */ + + if (GET_CODE (SET_SRC (prev_set)) == ASHIFT + && GET_CODE (SET_SRC (curr_set)) == LSHIFTRT + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set)) + && CONST_INT_P (XEXP (SET_SRC (prev_set), 1)) + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)) + && INTVAL (XEXP (SET_SRC (prev_set), 1)) == 32 + && (( INTVAL (XEXP (SET_SRC (curr_set), 1)) == 32 + && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTW) ) + || ( INTVAL (XEXP (SET_SRC (curr_set), 1)) < 32 + && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTWS)))) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH)) + { + /* We are trying to match the following: + prev (slli) == (set (reg:DI rD) + (ashift:DI (reg:DI rS) (const_int 48))) + curr (slri) == (set (reg:DI rD) + (lshiftrt:DI (reg:DI rD) (const_int 48))) */ + + if (GET_CODE (SET_SRC (prev_set)) == ASHIFT + && GET_CODE (SET_SRC (curr_set)) == LSHIFTRT + && REG_P (SET_DEST (prev_set)) + && REG_P (SET_DEST (curr_set)) + && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set)) + && CONST_INT_P (XEXP (SET_SRC (prev_set), 1)) + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)) + && INTVAL (XEXP (SET_SRC (prev_set), 1)) == 48 + && INTVAL (XEXP (SET_SRC (curr_set), 1)) == 48) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDINDEXED)) + { + /* We are trying to match the following: + prev (add) == (set (reg:DI rD) + (plus:DI (reg:DI rS1) (reg:DI rS2)) + curr (ld) == (set (reg:DI rD) + (mem:DI (reg:DI rD))) */ + + if (MEM_P (SET_SRC (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set)) + && GET_CODE (SET_SRC (prev_set)) == PLUS + && REG_P (XEXP (SET_SRC (prev_set), 0)) + && REG_P (XEXP (SET_SRC (prev_set), 1))) + return true; + + /* We are trying to match the following: + prev (add) == (set (reg:DI rD) + (plus:DI (reg:DI rS1) (reg:DI rS2))) + curr (lw) == (set (any_extend:DI (mem:SUBX (reg:DI rD)))) */ + + if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND + || (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)) + && MEM_P (XEXP (SET_SRC (curr_set), 0)) + && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) + && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == REGNO (SET_DEST (prev_set)) + && GET_CODE (SET_SRC (prev_set)) == PLUS + && REG_P (XEXP (SET_SRC (prev_set), 0)) + && REG_P (XEXP (SET_SRC (prev_set), 1))) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT)) + { + /* We are trying to match the following: + prev (add) == (set (reg:DI rS) + (plus:DI (reg:DI rS) (const_int)) + curr (ld) == (set (reg:DI rD) + (mem:DI (reg:DI rS))) */ + + if (MEM_P (SET_SRC (curr_set)) + && REG_P (XEXP (SET_SRC (curr_set), 0)) + && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set)) + && GET_CODE (SET_SRC (prev_set)) == PLUS + && REG_P (XEXP (SET_SRC (prev_set), 0)) + && CONST_INT_P (XEXP (SET_SRC (prev_set), 1))) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_ADDI)) + { + /* We are trying to match the following: + prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20)) + curr (addi) == (set (reg:DI rD) + (plus:DI (reg:DI rD) (const_int IMM12))) */ + + if ((GET_CODE (SET_SRC (curr_set)) == LO_SUM + || (GET_CODE (SET_SRC (curr_set)) == PLUS + && CONST_INT_P (XEXP (SET_SRC (curr_set), 1)) + && SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1))))) + && (GET_CODE (SET_SRC (prev_set)) == HIGH + || (CONST_INT_P (SET_SRC (prev_set)) + && LUI_OPERAND (INTVAL (SET_SRC (prev_set)))))) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_ADDI)) + { + /* We are trying to match the following: + prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC)) + curr (addi) == (set (reg:DI rD) + (plus:DI (reg:DI rD) (const_int IMM12))) + and + prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC)) + curr (addi) == (set (reg:DI rD) + (lo_sum:DI (reg:DI rD) (const_int IMM12))) */ + + if (GET_CODE (SET_SRC (prev_set)) == UNSPEC + && XINT (prev_set, 1) == UNSPEC_AUIPC + && (GET_CODE (SET_SRC (curr_set)) == LO_SUM + || (GET_CODE (SET_SRC (curr_set)) == PLUS + && SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1)))))) + + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_LD)) + { + /* We are trying to match the following: + prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20)) + curr (ld) == (set (reg:DI rD) + (mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) */ + + if (CONST_INT_P (SET_SRC (prev_set)) + && LUI_OPERAND (INTVAL (SET_SRC (prev_set))) + && MEM_P (SET_SRC (curr_set)) + && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS) + return true; + + if (GET_CODE (SET_SRC (prev_set)) == HIGH + && MEM_P (SET_SRC (curr_set)) + && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == LO_SUM + && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))) + return true; + + if (GET_CODE (SET_SRC (prev_set)) == HIGH + && (GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND + || GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND) + && MEM_P (XEXP (SET_SRC (curr_set), 0)) + && (GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == LO_SUM + && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0)))) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_LD)) + { + /* We are trying to match the following: + prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC)) + curr (ld) == (set (reg:DI rD) + (mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) */ + + if (GET_CODE (SET_SRC (prev_set)) == UNSPEC + && XINT (prev_set, 1) == UNSPEC_AUIPC + && MEM_P (SET_SRC (curr_set)) + && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS) + return true; + } + + if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ALIGNED_STD)) + { + /* We are trying to match the following: + prev (sd) == (set (mem (plus (reg sp|fp) (const_int))) + (reg rS1)) + curr (sd) == (set (mem (plus (reg sp|fp) (const_int))) + (reg rS2)) */ + + if (MEM_P (SET_DEST (prev_set)) + && MEM_P (SET_DEST (curr_set)) + /* We can probably relax this condition. The documentation is a bit + unclear about sub-word cases. So we just model DImode for now. */ + && GET_MODE (SET_DEST (curr_set)) == DImode + && GET_MODE (SET_DEST (prev_set)) == DImode) + { + rtx base_prev, base_curr, offset_prev, offset_curr; + + extract_base_offset_in_addr (SET_DEST (prev_set), &base_prev, &offset_prev); + extract_base_offset_in_addr (SET_DEST (curr_set), &base_curr, &offset_curr); + + /* The two stores must be contained within opposite halves of the same + 16 byte aligned block of memory. We know that the stack pointer and + the frame pointer have suitable alignment. So we just need to check + the offsets of the two stores for suitable alignment. + + Originally the thought was to check MEM_ALIGN, but that was reporting + incorrect alignments, even for SP/FP accesses, so we gave up on that + approach. */ + if (base_prev != NULL_RTX + && base_curr != NULL_RTX + && REG_P (base_prev) + && REG_P (base_curr) + && REGNO (base_prev) == REGNO (base_curr) + && (REGNO (base_prev) == STACK_POINTER_REGNUM + || REGNO (base_prev) == HARD_FRAME_POINTER_REGNUM) + && ((INTVAL (offset_prev) == INTVAL (offset_curr) + 8 + && (INTVAL (offset_prev) % 16) == 0) + || ((INTVAL (offset_curr) == INTVAL (offset_prev) + 8) + && (INTVAL (offset_curr) % 16) == 0))) + return true; + } + } + + return false; +} + /* Adjust the cost/latency of instructions for scheduling. For now this is just used to change the latency of vector instructions according to their LMUL. We assume that an insn with LMUL == 8 requires @@ -8225,13 +8669,18 @@ riscv_option_override (void) error ("requested ABI requires %<-march%> to subsume the %qc extension", UNITS_PER_FP_ARG > 8 ? 'Q' : (UNITS_PER_FP_ARG > 4 ? 'D' : 'F')); - if (TARGET_RVE && riscv_abi != ABI_ILP32E) - error ("rv32e requires ilp32e ABI"); + /* RVE requires specific ABI. */ + if (TARGET_RVE) + if (!TARGET_64BIT && riscv_abi != ABI_ILP32E) + error ("rv32e requires ilp32e ABI"); + else if (TARGET_64BIT && riscv_abi != ABI_LP64E) + error ("rv64e requires lp64e ABI"); - // Zfinx require abi ilp32,ilp32e or lp64. - if (TARGET_ZFINX && riscv_abi != ABI_ILP32 - && riscv_abi != ABI_LP64 && riscv_abi != ABI_ILP32E) - error ("z*inx requires ABI ilp32, ilp32e or lp64"); + /* Zfinx require abi ilp32, ilp32e, lp64 or lp64e. */ + if (TARGET_ZFINX + && riscv_abi != ABI_ILP32 && riscv_abi != ABI_LP64 + && riscv_abi != ABI_ILP32E && riscv_abi != ABI_LP64E) + error ("z*inx requires ABI ilp32, ilp32e, lp64 or lp64e"); /* We do not yet support ILP32 on RV64. */ if (BITS_PER_WORD != POINTER_SIZE) @@ -8357,7 +8806,7 @@ static GTY (()) tree riscv_previous_fndecl; static void riscv_conditional_register_usage (void) { - /* We have only x0~x15 on RV32E. */ + /* We have only x0~x15 on RV32E/RV64E. */ if (TARGET_RVE) { for (int r = 16; r <= 31; r++) @@ -9780,6 +10229,40 @@ riscv_preferred_else_value (unsigned ifn, tree vectype, unsigned int nops, return default_preferred_else_value (ifn, vectype, nops, ops); } +/* If MEM is in the form of "base+offset", extract the two parts + of address and set to BASE and OFFSET, otherwise return false + after clearing BASE and OFFSET. */ + +bool +extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset) +{ + rtx addr; + + gcc_assert (MEM_P (mem)); + + addr = XEXP (mem, 0); + + if (REG_P (addr)) + { + *base = addr; + *offset = const0_rtx; + return true; + } + + if (GET_CODE (addr) == PLUS + && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) + { + *base = XEXP (addr, 0); + *offset = XEXP (addr, 1); + return true; + } + + *base = NULL_RTX; + *offset = NULL_RTX; + + return false; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -9802,6 +10285,10 @@ riscv_preferred_else_value (unsigned ifn, tree vectype, unsigned int nops, #undef TARGET_SCHED_ISSUE_RATE #define TARGET_SCHED_ISSUE_RATE riscv_issue_rate +#undef TARGET_SCHED_MACRO_FUSION_P +#define TARGET_SCHED_MACRO_FUSION_P riscv_macro_fusion_p +#undef TARGET_SCHED_MACRO_FUSION_PAIR_P +#define TARGET_SCHED_MACRO_FUSION_PAIR_P riscv_macro_fusion_pair_p #undef TARGET_SCHED_VARIABLE_ISSUE #define TARGET_SCHED_VARIABLE_ISSUE riscv_sched_variable_issue @@ -9823,6 +10310,13 @@ riscv_preferred_else_value (unsigned ifn, tree vectype, unsigned int nops, #define TARGET_RTX_COSTS riscv_rtx_costs #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST riscv_address_cost +#undef TARGET_INSN_COST +#define TARGET_INSN_COST riscv_insn_cost + +#undef TARGET_MAX_NOCE_IFCVT_SEQ_COST +#define TARGET_MAX_NOCE_IFCVT_SEQ_COST riscv_max_noce_ifcvt_seq_cost +#undef TARGET_NOCE_CONVERSION_PROFITABLE_P +#define TARGET_NOCE_CONVERSION_PROFITABLE_P riscv_noce_conversion_profitable_p #undef TARGET_ASM_FILE_START #define TARGET_ASM_FILE_START riscv_file_start diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 6205d75..6df9ec7 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -170,7 +170,7 @@ ASM_MISA_SPEC /* The largest type that can be passed in floating-point registers. */ #define UNITS_PER_FP_ARG \ ((riscv_abi == ABI_ILP32 || riscv_abi == ABI_ILP32E \ - || riscv_abi == ABI_LP64) \ + || riscv_abi == ABI_LP64 || riscv_abi == ABI_LP64E) \ ? 0 \ : ((riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F) ? 4 : 8)) @@ -193,10 +193,15 @@ ASM_MISA_SPEC /* The smallest supported stack boundary the calling convention supports. */ #define STACK_BOUNDARY \ - (riscv_abi == ABI_ILP32E ? BITS_PER_WORD : 2 * BITS_PER_WORD) + (riscv_abi == ABI_ILP32E || riscv_abi == ABI_LP64E \ + ? BITS_PER_WORD \ + : 2 * BITS_PER_WORD) /* The ABI stack alignment. */ -#define ABI_STACK_BOUNDARY (riscv_abi == ABI_ILP32E ? BITS_PER_WORD : 128) +#define ABI_STACK_BOUNDARY \ + (riscv_abi == ABI_ILP32E || riscv_abi == ABI_LP64E \ + ? BITS_PER_WORD \ + : 128) /* There is no point aligning anything to a rounder boundary than this. */ #define BIGGEST_ALIGNMENT 128 @@ -669,7 +674,10 @@ enum reg_class #define GP_RETURN GP_ARG_FIRST #define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST) -#define MAX_ARGS_IN_REGISTERS (riscv_abi == ABI_ILP32E ? 6 : 8) +#define MAX_ARGS_IN_REGISTERS \ + (riscv_abi == ABI_ILP32E || riscv_abi == ABI_LP64E \ + ? 6 \ + : 8) #define MAX_ARGS_IN_VECTOR_REGISTERS (16) #define MAX_ARGS_IN_MASK_REGISTERS (1) @@ -1138,6 +1146,7 @@ extern poly_int64 riscv_v_adjust_bytesize (enum machine_mode, int); "%{mabi=ilp32f:ilp32f}" \ "%{mabi=ilp32d:ilp32d}" \ "%{mabi=lp64:lp64}" \ + "%{mabi=lp64e:lp64e}" \ "%{mabi=lp64f:lp64f}" \ "%{mabi=lp64d:lp64d}" \ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 8f28e8e..935eeb7 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2640,7 +2640,7 @@ (define_insn "*branch<mode>" [(set (pc) (if_then_else - (match_operator 1 "order_operator" + (match_operator 1 "ordered_comparison_operator" [(match_operand:X 2 "register_operand" "r") (match_operand:X 3 "reg_or_0_operand" "rJ")]) (label_ref (match_operand 0 "" "")) @@ -2655,14 +2655,15 @@ [(set_attr "type" "branch") (set_attr "mode" "none")]) -;; Patterns for implementations that optimize short forward branches. +;; Conditional move and add patterns. (define_expand "mov<mode>cc" [(set (match_operand:GPR 0 "register_operand") (if_then_else:GPR (match_operand 1 "comparison_operator") - (match_operand:GPR 2 "sfb_alu_operand") - (match_operand:GPR 3 "sfb_alu_operand")))] - "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE" + (match_operand:GPR 2 "movcc_operand") + (match_operand:GPR 3 "movcc_operand")))] + "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND_LIKE + || TARGET_MOVCC" { if (riscv_expand_conditional_move (operands[0], operands[1], operands[2], operands[3])) @@ -2671,10 +2672,51 @@ FAIL; }) +(define_expand "add<mode>cc" + [(match_operand:GPR 0 "register_operand") + (match_operand 1 "comparison_operator") + (match_operand:GPR 2 "arith_operand") + (match_operand:GPR 3 "arith_operand")] + "TARGET_MOVCC" +{ + rtx cmp = operands[1]; + rtx cmp0 = XEXP (cmp, 0); + rtx cmp1 = XEXP (cmp, 1); + machine_mode mode0 = GET_MODE (cmp0); + + /* We only handle word mode integer compares for now. */ + if (INTEGRAL_MODE_P (mode0) && mode0 != word_mode) + FAIL; + + enum rtx_code code = GET_CODE (cmp); + rtx reg0 = gen_reg_rtx (<MODE>mode); + rtx reg1 = gen_reg_rtx (<MODE>mode); + rtx reg2 = gen_reg_rtx (<MODE>mode); + bool invert = false; + + if (INTEGRAL_MODE_P (mode0)) + riscv_expand_int_scc (reg0, code, cmp0, cmp1, &invert); + else if (FLOAT_MODE_P (mode0) && fp_scc_comparison (cmp, GET_MODE (cmp))) + riscv_expand_float_scc (reg0, code, cmp0, cmp1, &invert); + else + FAIL; + + if (invert) + riscv_emit_binary (PLUS, reg1, reg0, constm1_rtx); + else + riscv_emit_unary (NEG, reg1, reg0); + riscv_emit_binary (AND, reg2, reg1, operands[3]); + riscv_emit_binary (PLUS, operands[0], reg2, operands[2]); + + DONE; +}) + +;; Patterns for implementations that optimize short forward branches. + (define_insn "*mov<GPR:mode><X:mode>cc" [(set (match_operand:GPR 0 "register_operand" "=r,r") (if_then_else:GPR - (match_operator 5 "order_operator" + (match_operator 5 "ordered_comparison_operator" [(match_operand:X 1 "register_operand" "r,r") (match_operand:X 2 "reg_or_0_operand" "rJ,rJ")]) (match_operand:GPR 3 "register_operand" "0,0") @@ -2708,20 +2750,89 @@ DONE; }) -(define_expand "@cbranch<mode>4" - [(set (pc) - (if_then_else (match_operator 0 "fp_branch_comparison" - [(match_operand:ANYF 1 "register_operand") - (match_operand:ANYF 2 "register_operand")]) - (label_ref (match_operand 3 "")) - (pc)))] +(define_expand "@cbranch<ANYF:mode>4" + [(parallel [(set (pc) + (if_then_else (match_operator 0 "fp_branch_comparison" + [(match_operand:ANYF 1 "register_operand") + (match_operand:ANYF 2 "register_operand")]) + (label_ref (match_operand 3 "")) + (pc))) + (clobber (match_operand 4 ""))])] "TARGET_HARD_FLOAT || TARGET_ZFINX" { - riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), - operands[1], operands[2]); - DONE; + if (!signed_order_operator (operands[0], GET_MODE (operands[0]))) + { + riscv_expand_conditional_branch (operands[3], GET_CODE (operands[0]), + operands[1], operands[2]); + DONE; + } + operands[4] = gen_reg_rtx (TARGET_64BIT ? DImode : SImode); }) +(define_insn_and_split "*cbranch<ANYF:mode>4" + [(set (pc) + (if_then_else (match_operator 1 "fp_native_comparison" + [(match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "f")]) + (label_ref (match_operand 0 "")) + (pc))) + (clobber (match_operand:X 4 "register_operand" "=r"))] + "TARGET_HARD_FLOAT || TARGET_ZFINX" + "#" + "&& reload_completed" + [(set (match_dup 4) + (match_op_dup:X 1 [(match_dup 2) (match_dup 3)])) + (set (pc) + (if_then_else (ne:X (match_dup 4) (const_int 0)) + (label_ref (match_operand 0)) + (pc)))] + "" + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (le (minus (match_dup 0) (pc)) + (const_int 4084)) + (le (minus (pc) (match_dup 0)) + (const_int 4096))) + (const_int 8) + (if_then_else (and (le (minus (match_dup 0) (pc)) + (const_int 1048564)) + (le (minus (pc) (match_dup 0)) + (const_int 1048576))) + (const_int 12) + (const_int 16))))]) + +(define_insn_and_split "*cbranch<ANYF:mode>4" + [(set (pc) + (if_then_else (match_operator 1 "ne_operator" + [(match_operand:ANYF 2 "register_operand" "f") + (match_operand:ANYF 3 "register_operand" "f")]) + (label_ref (match_operand 0 "")) + (pc))) + (clobber (match_operand:X 4 "register_operand" "=r"))] + "TARGET_HARD_FLOAT || TARGET_ZFINX" + "#" + "&& reload_completed" + [(set (match_dup 4) + (eq:X (match_dup 2) (match_dup 3))) + (set (pc) + (if_then_else (eq:X (match_dup 4) (const_int 0)) + (label_ref (match_operand 0)) + (pc)))] + "" + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (le (minus (match_dup 0) (pc)) + (const_int 4084)) + (le (minus (pc) (match_dup 0)) + (const_int 4096))) + (const_int 8) + (if_then_else (and (le (minus (match_dup 0) (pc)) + (const_int 1048564)) + (le (minus (pc) (match_dup 0)) + (const_int 1048576))) + (const_int 12) + (const_int 16))))]) + (define_insn_and_split "*branch_on_bit<X:mode>" [(set (pc) (if_then_else @@ -2791,7 +2902,7 @@ (define_expand "cstore<mode>4" [(set (match_operand:SI 0 "register_operand") - (match_operator:SI 1 "order_operator" + (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:GPR 2 "register_operand") (match_operand:GPR 3 "nonmemory_operand")]))] "" @@ -3301,7 +3412,7 @@ (define_insn "riscv_frcsr" [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile [(const_int 0)] UNSPECV_FRCSR))] + (unspec_volatile:SI [(const_int 0)] UNSPECV_FRCSR))] "TARGET_HARD_FLOAT || TARGET_ZFINX" "frcsr\t%0" [(set_attr "type" "fmove")]) @@ -3314,7 +3425,7 @@ (define_insn "riscv_frflags" [(set (match_operand:SI 0 "register_operand" "=r") - (unspec_volatile [(const_int 0)] UNSPECV_FRFLAGS))] + (unspec_volatile:SI [(const_int 0)] UNSPECV_FRFLAGS))] "TARGET_HARD_FLOAT || TARGET_ZFINX" "frflags\t%0" [(set_attr "type" "fmove")]) diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 1bd661a..0c6517b 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -65,6 +65,9 @@ EnumValue Enum(abi_type) String(lp64) Value(ABI_LP64) EnumValue +Enum(abi_type) String(lp64e) Value(ABI_LP64E) + +EnumValue Enum(abi_type) String(lp64f) Value(ABI_LP64F) EnumValue @@ -460,6 +463,10 @@ misa-spec= Target RejectNegative Joined Enum(isa_spec_class) Var(riscv_isa_spec) Init(TARGET_DEFAULT_ISA_SPEC) Set the version of RISC-V ISA spec. +mmovcc +Target Var(TARGET_MOVCC) +Enable conditional moves unconditionally. + minline-atomics Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1) Always inline subword atomic operations. @@ -527,3 +534,23 @@ Target Var(TARGET_ADJUST_LMUL_COST) Init(0) Target Undocumented Bool Var(riscv_vector_abi) Init(0) Enable the use of vector registers for function arguments and return value. This is an experimental switch and may be subject to change in the future. + +Enum +Name(riscv_stringop_strategy) Type(enum riscv_stringop_strategy_enum) +Valid arguments to -mmemcpy-strategy=: + +EnumValue +Enum(riscv_stringop_strategy) String(auto) Value(USE_AUTO) + +EnumValue +Enum(riscv_stringop_strategy) String(libcall) Value(USE_LIBCALL) + +EnumValue +Enum(riscv_stringop_strategy) String(scalar) Value(USE_SCALAR) + +EnumValue +Enum(riscv_stringop_strategy) String(vector) Value(USE_VECTOR) + +mmemcpy-strategy= +Target RejectNegative Joined Enum(riscv_stringop_strategy) Var(riscv_memcpy_strategy) Init(USE_AUTO) +Specify memcpy expansion strategy. diff --git a/gcc/config/riscv/thead.cc b/gcc/config/riscv/thead.cc index a485fb1..bd9af7e 100644 --- a/gcc/config/riscv/thead.cc +++ b/gcc/config/riscv/thead.cc @@ -36,40 +36,6 @@ #include "regs.h" #include "riscv-protos.h" -/* If MEM is in the form of "base+offset", extract the two parts - of address and set to BASE and OFFSET, otherwise return false - after clearing BASE and OFFSET. */ - -static bool -extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset) -{ - rtx addr; - - gcc_assert (MEM_P (mem)); - - addr = XEXP (mem, 0); - - if (REG_P (addr)) - { - *base = addr; - *offset = const0_rtx; - return true; - } - - if (GET_CODE (addr) == PLUS - && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) - { - *base = XEXP (addr, 0); - *offset = XEXP (addr, 1); - return true; - } - - *base = NULL_RTX; - *offset = NULL_RTX; - - return false; -} - /* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR and *OFFSET_PTR. Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise. */ diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index 469875c..56080ed 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -319,23 +319,36 @@ (RVVM1HF "TARGET_VECTOR_ELEN_FP_16") (RVVMF2HF "TARGET_VECTOR_ELEN_FP_16") (RVVMF4HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN > 32") - RVVM4SI RVVM2SI RVVM1SI (RVVMF2SI "TARGET_MIN_VLEN > 32") + (RVVM4SI "TARGET_64BIT") + (RVVM2SI "TARGET_64BIT") + (RVVM1SI "TARGET_64BIT") + (RVVMF2SI "TARGET_MIN_VLEN > 32 && TARGET_64BIT") - (RVVM4SF "TARGET_VECTOR_ELEN_FP_32") (RVVM2SF "TARGET_VECTOR_ELEN_FP_32") - (RVVM1SF "TARGET_VECTOR_ELEN_FP_32") (RVVMF2SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN > 32") + (RVVM4SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_64BIT") + (RVVM2SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_64BIT") + (RVVM1SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_64BIT") + (RVVMF2SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN > 32 && TARGET_64BIT") ]) (define_mode_iterator VEEWTRUNC4 [ RVVM2QI RVVM1QI RVVMF2QI RVVMF4QI (RVVMF8QI "TARGET_MIN_VLEN > 32") - RVVM2HI RVVM1HI RVVMF2HI (RVVMF4HI "TARGET_MIN_VLEN > 32") + (RVVM2HI "TARGET_64BIT") + (RVVM1HI "TARGET_64BIT") + (RVVMF2HI "TARGET_64BIT") + (RVVMF4HI "TARGET_MIN_VLEN > 32 && TARGET_64BIT") - (RVVM2HF "TARGET_VECTOR_ELEN_FP_16") (RVVM1HF "TARGET_VECTOR_ELEN_FP_16") (RVVMF2HF "TARGET_VECTOR_ELEN_FP_16") - (RVVMF4HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN > 32") + (RVVM2HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_64BIT") + (RVVM1HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_64BIT") + (RVVMF2HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_64BIT") + (RVVMF4HF "TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN > 32 && TARGET_64BIT") ]) (define_mode_iterator VEEWTRUNC8 [ - RVVM1QI RVVMF2QI RVVMF4QI (RVVMF8QI "TARGET_MIN_VLEN > 32") + (RVVM1QI "TARGET_64BIT") + (RVVMF2QI "TARGET_64BIT") + (RVVMF4QI "TARGET_64BIT") + (RVVMF8QI "TARGET_MIN_VLEN > 32 && TARGET_64BIT") ]) (define_mode_iterator VEI16 [ @@ -363,13 +376,13 @@ (V4QI "riscv_vector::vls_mode_valid_p (V4QImode)") (V8QI "riscv_vector::vls_mode_valid_p (V8QImode)") (V16QI "riscv_vector::vls_mode_valid_p (V16QImode)") - (V32QI "riscv_vector::vls_mode_valid_p (V32QImode)") - (V64QI "riscv_vector::vls_mode_valid_p (V64QImode) && TARGET_MIN_VLEN >= 64") - (V128QI "riscv_vector::vls_mode_valid_p (V128QImode) && TARGET_MIN_VLEN >= 128") - (V256QI "riscv_vector::vls_mode_valid_p (V256QImode) && TARGET_MIN_VLEN >= 256") - (V512QI "riscv_vector::vls_mode_valid_p (V512QImode) && TARGET_MIN_VLEN >= 512") - (V1024QI "riscv_vector::vls_mode_valid_p (V1024QImode) && TARGET_MIN_VLEN >= 1024") - (V2048QI "riscv_vector::vls_mode_valid_p (V2048QImode) && TARGET_MIN_VLEN >= 2048") + (V32QI "riscv_vector::vls_mode_valid_p (V32QImode) && TARGET_MIN_VLEN >= 64") + (V64QI "riscv_vector::vls_mode_valid_p (V64QImode) && TARGET_MIN_VLEN >= 128") + (V128QI "riscv_vector::vls_mode_valid_p (V128QImode) && TARGET_MIN_VLEN >= 256") + (V256QI "riscv_vector::vls_mode_valid_p (V256QImode) && TARGET_MIN_VLEN >= 512") + (V512QI "riscv_vector::vls_mode_valid_p (V512QImode) && TARGET_MIN_VLEN >= 1024") + (V1024QI "riscv_vector::vls_mode_valid_p (V1024QImode) && TARGET_MIN_VLEN >= 2048") + (V2048QI "riscv_vector::vls_mode_valid_p (V2048QImode) && TARGET_MIN_VLEN >= 4096") (V1HI "riscv_vector::vls_mode_valid_p (V1HImode)") (V2HI "riscv_vector::vls_mode_valid_p (V2HImode)") (V4HI "riscv_vector::vls_mode_valid_p (V4HImode)") @@ -731,6 +744,17 @@ (RVVM2DI "TARGET_FULL_V") (RVVM1DI "TARGET_FULL_V") ]) +;; All RATIO mode iterators are used on gather/scatter vectorization. +;; RISC-V V Spec 18.3: +;; The V extension supports all vector load and store instructions (Section +;; Vector Loads and Stores), except the V extension does not support EEW=64 +;; for index values when XLEN=32. +;; According to RVV ISA description above, all RATIO index DI mode need TARGET_64BIT. +;; +;; In gather/scatter expand, we need to sign/zero extend the index mode into vector +;; Pmode, so we need to check whether vector Pmode is available. +;; E.g. when index mode = RVVM8QImde and Pmode = SImode, if it is not zero_extend or +;; scalar != 1, such gather/scatter is not allowed since we don't have RVVM32SImode. (define_mode_iterator RATIO64 [ (RVVMF8QI "TARGET_MIN_VLEN > 32") (RVVMF4HI "TARGET_MIN_VLEN > 32") @@ -793,28 +817,28 @@ (RVVMF8QI "TARGET_MIN_VLEN > 32") (RVVMF4HI "TARGET_MIN_VLEN > 32") (RVVMF2SI "TARGET_MIN_VLEN > 32") - (RVVM1DI "TARGET_VECTOR_ELEN_64") + (RVVM1DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") ]) (define_mode_iterator RATIO32I [ RVVMF4QI RVVMF2HI RVVM1SI - (RVVM2DI "TARGET_VECTOR_ELEN_64") + (RVVM2DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") ]) (define_mode_iterator RATIO16I [ RVVMF2QI RVVM1HI RVVM2SI - (RVVM4DI "TARGET_VECTOR_ELEN_64") + (RVVM4DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") ]) (define_mode_iterator RATIO8I [ RVVM1QI RVVM2HI RVVM4SI - (RVVM8DI "TARGET_VECTOR_ELEN_64") + (RVVM8DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") ]) (define_mode_iterator RATIO4I [ @@ -1421,11 +1445,123 @@ (V1024BI "riscv_vector::vls_mode_valid_p (V1024BImode) && TARGET_MIN_VLEN >= 1024") (V2048BI "riscv_vector::vls_mode_valid_p (V2048BImode) && TARGET_MIN_VLEN >= 2048") (V4096BI "riscv_vector::vls_mode_valid_p (V4096BImode) && TARGET_MIN_VLEN >= 4096")]) - + (define_mode_iterator VB [ (RVVMF64BI "TARGET_MIN_VLEN > 32") RVVMF32BI RVVMF16BI RVVMF8BI RVVMF4BI RVVMF2BI RVVM1BI ]) +;; Iterator for indexed loads and stores. We must disallow 64-bit indices on +;; XLEN=32 targets. TODO: Split iterators so more of them can be reused, i.e. +;; VI8, VI16, VI32, VI64 and then use +;; VINDEXED [VI8 VI16 VI32 (VI64 "TARGET_64BIT")]. + +(define_mode_iterator VINDEXED [ + RVVM8QI RVVM4QI RVVM2QI RVVM1QI RVVMF2QI RVVMF4QI (RVVMF8QI "TARGET_MIN_VLEN > 32") + + RVVM8HI RVVM4HI RVVM2HI RVVM1HI RVVMF2HI (RVVMF4HI "TARGET_MIN_VLEN > 32") + + RVVM8SI RVVM4SI RVVM2SI RVVM1SI (RVVMF2SI "TARGET_MIN_VLEN > 32") + + (RVVM8DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (RVVM4DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (RVVM2DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (RVVM1DI "TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + + (RVVM8HF "TARGET_ZVFH") (RVVM4HF "TARGET_ZVFH") (RVVM2HF "TARGET_ZVFH") + (RVVM1HF "TARGET_ZVFH") (RVVMF2HF "TARGET_ZVFH") + (RVVMF4HF "TARGET_ZVFH && TARGET_MIN_VLEN > 32") + + (RVVM8SF "TARGET_VECTOR_ELEN_FP_32") (RVVM4SF "TARGET_VECTOR_ELEN_FP_32") + (RVVM2SF "TARGET_VECTOR_ELEN_FP_32") (RVVM1SF "TARGET_VECTOR_ELEN_FP_32") + (RVVMF2SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN > 32") + + (RVVM8DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (RVVM4DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (RVVM2DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (RVVM1DF "TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + + (V1QI "riscv_vector::vls_mode_valid_p (V1QImode)") + (V2QI "riscv_vector::vls_mode_valid_p (V2QImode)") + (V4QI "riscv_vector::vls_mode_valid_p (V4QImode)") + (V8QI "riscv_vector::vls_mode_valid_p (V8QImode)") + (V16QI "riscv_vector::vls_mode_valid_p (V16QImode)") + (V32QI "riscv_vector::vls_mode_valid_p (V32QImode)") + (V64QI "riscv_vector::vls_mode_valid_p (V64QImode) && TARGET_MIN_VLEN >= 64") + (V128QI "riscv_vector::vls_mode_valid_p (V128QImode) && TARGET_MIN_VLEN >= 128") + (V256QI "riscv_vector::vls_mode_valid_p (V256QImode) && TARGET_MIN_VLEN >= 256") + (V512QI "riscv_vector::vls_mode_valid_p (V512QImode) && TARGET_MIN_VLEN >= 512") + (V1024QI "riscv_vector::vls_mode_valid_p (V1024QImode) && TARGET_MIN_VLEN >= 1024") + (V2048QI "riscv_vector::vls_mode_valid_p (V2048QImode) && TARGET_MIN_VLEN >= 2048") + (V4096QI "riscv_vector::vls_mode_valid_p (V4096QImode) && TARGET_MIN_VLEN >= 4096") + (V1HI "riscv_vector::vls_mode_valid_p (V1HImode)") + (V2HI "riscv_vector::vls_mode_valid_p (V2HImode)") + (V4HI "riscv_vector::vls_mode_valid_p (V4HImode)") + (V8HI "riscv_vector::vls_mode_valid_p (V8HImode)") + (V16HI "riscv_vector::vls_mode_valid_p (V16HImode)") + (V32HI "riscv_vector::vls_mode_valid_p (V32HImode) && TARGET_MIN_VLEN >= 64") + (V64HI "riscv_vector::vls_mode_valid_p (V64HImode) && TARGET_MIN_VLEN >= 128") + (V128HI "riscv_vector::vls_mode_valid_p (V128HImode) && TARGET_MIN_VLEN >= 256") + (V256HI "riscv_vector::vls_mode_valid_p (V256HImode) && TARGET_MIN_VLEN >= 512") + (V512HI "riscv_vector::vls_mode_valid_p (V512HImode) && TARGET_MIN_VLEN >= 1024") + (V1024HI "riscv_vector::vls_mode_valid_p (V1024HImode) && TARGET_MIN_VLEN >= 2048") + (V2048HI "riscv_vector::vls_mode_valid_p (V2048HImode) && TARGET_MIN_VLEN >= 4096") + (V1SI "riscv_vector::vls_mode_valid_p (V1SImode)") + (V2SI "riscv_vector::vls_mode_valid_p (V2SImode)") + (V4SI "riscv_vector::vls_mode_valid_p (V4SImode)") + (V8SI "riscv_vector::vls_mode_valid_p (V8SImode)") + (V16SI "riscv_vector::vls_mode_valid_p (V16SImode) && TARGET_MIN_VLEN >= 64") + (V32SI "riscv_vector::vls_mode_valid_p (V32SImode) && TARGET_MIN_VLEN >= 128") + (V64SI "riscv_vector::vls_mode_valid_p (V64SImode) && TARGET_MIN_VLEN >= 256") + (V128SI "riscv_vector::vls_mode_valid_p (V128SImode) && TARGET_MIN_VLEN >= 512") + (V256SI "riscv_vector::vls_mode_valid_p (V256SImode) && TARGET_MIN_VLEN >= 1024") + (V512SI "riscv_vector::vls_mode_valid_p (V512SImode) && TARGET_MIN_VLEN >= 2048") + (V1024SI "riscv_vector::vls_mode_valid_p (V1024SImode) && TARGET_MIN_VLEN >= 4096") + (V1DI "riscv_vector::vls_mode_valid_p (V1DImode) && TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (V2DI "riscv_vector::vls_mode_valid_p (V2DImode) && TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (V4DI "riscv_vector::vls_mode_valid_p (V4DImode) && TARGET_VECTOR_ELEN_64 && TARGET_64BIT") + (V8DI "riscv_vector::vls_mode_valid_p (V8DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 64 && TARGET_64BIT") + (V16DI "riscv_vector::vls_mode_valid_p (V16DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 128 && TARGET_64BIT") + (V32DI "riscv_vector::vls_mode_valid_p (V32DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 256 && TARGET_64BIT") + (V64DI "riscv_vector::vls_mode_valid_p (V64DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 512 && TARGET_64BIT") + (V128DI "riscv_vector::vls_mode_valid_p (V128DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 1024 && TARGET_64BIT") + (V256DI "riscv_vector::vls_mode_valid_p (V256DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 2048 && TARGET_64BIT") + (V512DI "riscv_vector::vls_mode_valid_p (V512DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 4096 && TARGET_64BIT") + + (V1HF "riscv_vector::vls_mode_valid_p (V1HFmode) && TARGET_ZVFH") + (V2HF "riscv_vector::vls_mode_valid_p (V2HFmode) && TARGET_ZVFH") + (V4HF "riscv_vector::vls_mode_valid_p (V4HFmode) && TARGET_ZVFH") + (V8HF "riscv_vector::vls_mode_valid_p (V8HFmode) && TARGET_ZVFH") + (V16HF "riscv_vector::vls_mode_valid_p (V16HFmode) && TARGET_ZVFH") + (V32HF "riscv_vector::vls_mode_valid_p (V32HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 64") + (V64HF "riscv_vector::vls_mode_valid_p (V64HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 128") + (V128HF "riscv_vector::vls_mode_valid_p (V128HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 256") + (V256HF "riscv_vector::vls_mode_valid_p (V256HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 512") + (V512HF "riscv_vector::vls_mode_valid_p (V512HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 1024") + (V1024HF "riscv_vector::vls_mode_valid_p (V1024HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 2048") + (V2048HF "riscv_vector::vls_mode_valid_p (V2048HFmode) && TARGET_ZVFH && TARGET_MIN_VLEN >= 4096") + (V1SF "riscv_vector::vls_mode_valid_p (V1SFmode) && TARGET_VECTOR_ELEN_FP_32") + (V2SF "riscv_vector::vls_mode_valid_p (V2SFmode) && TARGET_VECTOR_ELEN_FP_32") + (V4SF "riscv_vector::vls_mode_valid_p (V4SFmode) && TARGET_VECTOR_ELEN_FP_32") + (V8SF "riscv_vector::vls_mode_valid_p (V8SFmode) && TARGET_VECTOR_ELEN_FP_32") + (V16SF "riscv_vector::vls_mode_valid_p (V16SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 64") + (V32SF "riscv_vector::vls_mode_valid_p (V32SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 128") + (V64SF "riscv_vector::vls_mode_valid_p (V64SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 256") + (V128SF "riscv_vector::vls_mode_valid_p (V128SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 512") + (V256SF "riscv_vector::vls_mode_valid_p (V256SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 1024") + (V512SF "riscv_vector::vls_mode_valid_p (V512SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 2048") + (V1024SF "riscv_vector::vls_mode_valid_p (V1024SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 4096") + (V1DF "riscv_vector::vls_mode_valid_p (V1DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (V2DF "riscv_vector::vls_mode_valid_p (V2DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (V4DF "riscv_vector::vls_mode_valid_p (V4DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_64BIT") + (V8DF "riscv_vector::vls_mode_valid_p (V8DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 64 && TARGET_64BIT") + (V16DF "riscv_vector::vls_mode_valid_p (V16DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 128 && TARGET_64BIT") + (V32DF "riscv_vector::vls_mode_valid_p (V32DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 256 && TARGET_64BIT") + (V64DF "riscv_vector::vls_mode_valid_p (V64DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 512 && TARGET_64BIT") + (V128DF "riscv_vector::vls_mode_valid_p (V128DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 1024 && TARGET_64BIT") + (V256DF "riscv_vector::vls_mode_valid_p (V256DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 2048 && TARGET_64BIT") + (V512DF "riscv_vector::vls_mode_valid_p (V512DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 4096 && TARGET_64BIT") +]) + (define_mode_iterator VB_VLS [VB VLSB]) (define_mode_iterator VLS [VLSI VLSF_ZVFHMIN]) @@ -3198,34 +3334,6 @@ (V512DF "riscv_vector::vls_mode_valid_p (V512DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 4096") ]) -(define_mode_attr VDEMOTE [ - (RVVM8DI "RVVM8SI") (RVVM4DI "RVVM4SI") (RVVM2DI "RVVM2SI") (RVVM1DI "RVVM1SI") - (V1DI "V1SI") - (V2DI "V2SI") - (V4DI "V4SI") - (V8DI "V8SI") - (V16DI "V16SI") - (V32DI "V32SI") - (V64DI "V64SI") - (V128DI "V128SI") - (V256DI "V256SI") - (V512DI "V512SI") -]) - -(define_mode_attr VMDEMOTE [ - (RVVM8DI "RVVMF4BI") (RVVM4DI "RVVMF8BI") (RVVM2DI "RVVMF16BI") (RVVM1DI "RVVMF32BI") - (V1DI "V1BI") - (V2DI "V2BI") - (V4DI "V4BI") - (V8DI "V8BI") - (V16DI "V16BI") - (V32DI "V32BI") - (V64DI "V64BI") - (V128DI "V128BI") - (V256DI "V256BI") - (V512DI "V512BI") -]) - (define_mode_attr stride_predicate [ (RVVM8QI "vector_eew8_stride_operand") (RVVM4QI "vector_eew8_stride_operand") (RVVM2QI "vector_eew8_stride_operand") (RVVM1QI "vector_eew8_stride_operand") @@ -3314,8 +3422,8 @@ ]) (define_mode_attr gs_extension [ - (RVVM8QI "const_1_operand") (RVVM4QI "vector_gs_extension_operand") - (RVVM2QI "immediate_operand") (RVVM1QI "immediate_operand") (RVVMF2QI "immediate_operand") + (RVVM8QI "const_1_operand") (RVVM4QI "const_1_operand") + (RVVM2QI "vector_gs_extension_operand") (RVVM1QI "immediate_operand") (RVVMF2QI "immediate_operand") (RVVMF4QI "immediate_operand") (RVVMF8QI "immediate_operand") (RVVM8HI "const_1_operand") (RVVM4HI "vector_gs_extension_operand") @@ -3358,11 +3466,11 @@ (RVVM8SF "vector_gs_scale_operand_32_rv32") (RVVM4SF "const_1_or_4_operand") (RVVM2SF "const_1_or_4_operand") (RVVM1SF "const_1_or_4_operand") (RVVMF2SF "const_1_or_4_operand") - (RVVM8DI "vector_gs_scale_operand_64") (RVVM4DI "vector_gs_scale_operand_64") - (RVVM2DI "vector_gs_scale_operand_64") (RVVM1DI "vector_gs_scale_operand_64") + (RVVM8DI "const_1_or_8_operand") (RVVM4DI "const_1_or_8_operand") + (RVVM2DI "const_1_or_8_operand") (RVVM1DI "const_1_or_8_operand") - (RVVM8DF "vector_gs_scale_operand_64") (RVVM4DF "vector_gs_scale_operand_64") - (RVVM2DF "vector_gs_scale_operand_64") (RVVM1DF "vector_gs_scale_operand_64") + (RVVM8DF "const_1_or_8_operand") (RVVM4DF "const_1_or_8_operand") + (RVVM2DF "const_1_or_8_operand") (RVVM1DF "const_1_or_8_operand") ]) (define_int_iterator ORDER [UNSPEC_ORDERED UNSPEC_UNORDERED]) diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index d1499d3..ba9c9e5 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -2201,21 +2201,21 @@ ;; DEST eew is same as SOURCE eew, DEST register can overlap SOURCE. (define_insn "@pred_indexed_<order>load<mode>_same_eew" - [(set (match_operand:V 0 "register_operand" "=vd, vr,vd, vr") - (if_then_else:V + [(set (match_operand:VINDEXED 0 "register_operand" "=vd, vr,vd, vr") + (if_then_else:VINDEXED (unspec:<VM> - [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1,vm,Wc1") - (match_operand 5 "vector_length_operand" " rK, rK,rK, rK") - (match_operand 6 "const_int_operand" " i, i, i, i") - (match_operand 7 "const_int_operand" " i, i, i, i") - (match_operand 8 "const_int_operand" " i, i, i, i") + [(match_operand:<VM> 1 "vector_mask_operand" " vm,Wc1,vm,Wc1") + (match_operand 5 "vector_length_operand" " rK, rK,rK, rK") + (match_operand 6 "const_int_operand" " i, i, i, i") + (match_operand 7 "const_int_operand" " i, i, i, i") + (match_operand 8 "const_int_operand" " i, i, i, i") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) - (unspec:V - [(match_operand 3 "pmode_reg_or_0_operand" " rJ, rJ,rJ, rJ") + (unspec:VINDEXED + [(match_operand 3 "pmode_reg_or_0_operand" " rJ, rJ,rJ, rJ") (mem:BLK (scratch)) - (match_operand:<VINDEX> 4 "register_operand" " vr, vr,vr, vr")] ORDER) - (match_operand:V 2 "vector_merge_operand" " vu, vu, 0, 0")))] + (match_operand:<VINDEX> 4 "register_operand" " vr, vr,vr, vr")] ORDER) + (match_operand:VINDEXED 2 "vector_merge_operand" " vu, vu, 0, 0")))] "TARGET_VECTOR" "vl<order>xei<sew>.v\t%0,(%z3),%4%p1" [(set_attr "type" "vld<order>x") @@ -8096,8 +8096,11 @@ (match_operand:<VEL> 4 "reg_or_int_operand")] VSLIDES1))] "TARGET_VECTOR" { + poly_uint64 nunits = GET_MODE_NUNITS (<MODE>mode) * 2; + machine_mode vsimode = riscv_vector::get_vector_mode (SImode, nunits).require (); + machine_mode vbimode = riscv_vector::get_vector_mode (BImode, nunits).require (); if (riscv_vector::slide1_sew64_helper (<UNSPEC>, <MODE>mode, - <VDEMOTE>mode, <VMDEMOTE>mode, + vsimode, vbimode, operands)) DONE; }) diff --git a/gcc/config/s390/s390-builtin-types.def b/gcc/config/s390/s390-builtin-types.def index 22ee348..5057f34 100644 --- a/gcc/config/s390/s390-builtin-types.def +++ b/gcc/config/s390/s390-builtin-types.def @@ -216,7 +216,6 @@ DEF_FN_TYPE_2 (BT_FN_UV16QI_UCHAR_INT, BT_UV16QI, BT_UCHAR, BT_INT) DEF_FN_TYPE_2 (BT_FN_UV16QI_UCHAR_UCHAR, BT_UV16QI, BT_UCHAR, BT_UCHAR) DEF_FN_TYPE_2 (BT_FN_UV16QI_UV16QI_INTPTR, BT_UV16QI, BT_UV16QI, BT_INTPTR) DEF_FN_TYPE_2 (BT_FN_UV16QI_UV16QI_UCHAR, BT_UV16QI, BT_UV16QI, BT_UCHAR) -DEF_FN_TYPE_2 (BT_FN_UV16QI_UV16QI_UINT, BT_UV16QI, BT_UV16QI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_UV16QI_UV16QI_UV16QI, BT_UV16QI, BT_UV16QI, BT_UV16QI) DEF_FN_TYPE_2 (BT_FN_UV16QI_UV2DI_UV2DI, BT_UV16QI, BT_UV2DI, BT_UV2DI) DEF_FN_TYPE_2 (BT_FN_UV16QI_UV4SI_UV4SI, BT_UV16QI, BT_UV4SI, BT_UV4SI) @@ -225,7 +224,6 @@ DEF_FN_TYPE_2 (BT_FN_UV2DI_UCHAR_UCHAR, BT_UV2DI, BT_UCHAR, BT_UCHAR) DEF_FN_TYPE_2 (BT_FN_UV2DI_ULONGLONG_INT, BT_UV2DI, BT_ULONGLONG, BT_INT) DEF_FN_TYPE_2 (BT_FN_UV2DI_UV16QI_UV16QI, BT_UV2DI, BT_UV16QI, BT_UV16QI) DEF_FN_TYPE_2 (BT_FN_UV2DI_UV2DI_UCHAR, BT_UV2DI, BT_UV2DI, BT_UCHAR) -DEF_FN_TYPE_2 (BT_FN_UV2DI_UV2DI_UINT, BT_UV2DI, BT_UV2DI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_UV2DI_UV2DI_UV2DI, BT_UV2DI, BT_UV2DI, BT_UV2DI) DEF_FN_TYPE_2 (BT_FN_UV2DI_UV4SI_UV4SI, BT_UV2DI, BT_UV4SI, BT_UV4SI) DEF_FN_TYPE_2 (BT_FN_UV2DI_UV8HI_UV8HI, BT_UV2DI, BT_UV8HI, BT_UV8HI) @@ -236,7 +234,6 @@ DEF_FN_TYPE_2 (BT_FN_UV4SI_UV16QI_UV16QI, BT_UV4SI, BT_UV16QI, BT_UV16QI) DEF_FN_TYPE_2 (BT_FN_UV4SI_UV2DI_UV2DI, BT_UV4SI, BT_UV2DI, BT_UV2DI) DEF_FN_TYPE_2 (BT_FN_UV4SI_UV4SI_INTPTR, BT_UV4SI, BT_UV4SI, BT_INTPTR) DEF_FN_TYPE_2 (BT_FN_UV4SI_UV4SI_UCHAR, BT_UV4SI, BT_UV4SI, BT_UCHAR) -DEF_FN_TYPE_2 (BT_FN_UV4SI_UV4SI_UINT, BT_UV4SI, BT_UV4SI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_UV4SI_UV4SI_UV4SI, BT_UV4SI, BT_UV4SI, BT_UV4SI) DEF_FN_TYPE_2 (BT_FN_UV4SI_UV8HI_UV8HI, BT_UV4SI, BT_UV8HI, BT_UV8HI) DEF_FN_TYPE_2 (BT_FN_UV8HI_UCHAR_UCHAR, BT_UV8HI, BT_UCHAR, BT_UCHAR) @@ -265,9 +262,9 @@ DEF_FN_TYPE_2 (BT_FN_V2DI_V2DF_V2DF, BT_V2DI, BT_V2DF, BT_V2DF) DEF_FN_TYPE_2 (BT_FN_V2DI_V2DI_V2DI, BT_V2DI, BT_V2DI, BT_V2DI) DEF_FN_TYPE_2 (BT_FN_V2DI_V4SI_V4SI, BT_V2DI, BT_V4SI, BT_V4SI) DEF_FN_TYPE_2 (BT_FN_V4SF_FLT_INT, BT_V4SF, BT_FLT, BT_INT) +DEF_FN_TYPE_2 (BT_FN_V4SF_UV8HI_UINT, BT_V4SF, BT_UV8HI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_V4SF_V4SF_UCHAR, BT_V4SF, BT_V4SF, BT_UCHAR) DEF_FN_TYPE_2 (BT_FN_V4SF_V4SF_V4SF, BT_V4SF, BT_V4SF, BT_V4SF) -DEF_FN_TYPE_2 (BT_FN_V4SF_V8HI_UINT, BT_V4SF, BT_V8HI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_V4SI_BV4SI_V4SI, BT_V4SI, BT_BV4SI, BT_V4SI) DEF_FN_TYPE_2 (BT_FN_V4SI_INT_VOIDCONSTPTR, BT_V4SI, BT_INT, BT_VOIDCONSTPTR) DEF_FN_TYPE_2 (BT_FN_V4SI_UV4SI_UV4SI, BT_V4SI, BT_UV4SI, BT_UV4SI) @@ -279,7 +276,6 @@ DEF_FN_TYPE_2 (BT_FN_V8HI_BV8HI_V8HI, BT_V8HI, BT_BV8HI, BT_V8HI) DEF_FN_TYPE_2 (BT_FN_V8HI_UV8HI_UV8HI, BT_V8HI, BT_UV8HI, BT_UV8HI) DEF_FN_TYPE_2 (BT_FN_V8HI_V16QI_V16QI, BT_V8HI, BT_V16QI, BT_V16QI) DEF_FN_TYPE_2 (BT_FN_V8HI_V4SI_V4SI, BT_V8HI, BT_V4SI, BT_V4SI) -DEF_FN_TYPE_2 (BT_FN_V8HI_V8HI_UINT, BT_V8HI, BT_V8HI, BT_UINT) DEF_FN_TYPE_2 (BT_FN_V8HI_V8HI_V8HI, BT_V8HI, BT_V8HI, BT_V8HI) DEF_FN_TYPE_2 (BT_FN_VOID_UINT64PTR_UINT64, BT_VOID, BT_UINT64PTR, BT_UINT64) DEF_FN_TYPE_2 (BT_FN_VOID_V2DF_FLTPTR, BT_VOID, BT_V2DF, BT_FLTPTR) @@ -317,6 +313,7 @@ DEF_FN_TYPE_3 (BT_FN_UV8HI_UV8HI_USHORT_INT, BT_UV8HI, BT_UV8HI, BT_USHORT, BT_I DEF_FN_TYPE_3 (BT_FN_UV8HI_UV8HI_UV8HI_INT, BT_UV8HI, BT_UV8HI, BT_UV8HI, BT_INT) DEF_FN_TYPE_3 (BT_FN_UV8HI_UV8HI_UV8HI_INTPTR, BT_UV8HI, BT_UV8HI, BT_UV8HI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_UV8HI_UV8HI_UV8HI_UV8HI, BT_UV8HI, BT_UV8HI, BT_UV8HI, BT_UV8HI) +DEF_FN_TYPE_3 (BT_FN_UV8HI_V4SF_V4SF_UINT, BT_UV8HI, BT_V4SF, BT_V4SF, BT_UINT) DEF_FN_TYPE_3 (BT_FN_V16QI_UV16QI_UV16QI_INTPTR, BT_V16QI, BT_UV16QI, BT_UV16QI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_V16QI_V16QI_V16QI_INTPTR, BT_V16QI, BT_V16QI, BT_V16QI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_V16QI_V16QI_V16QI_V16QI, BT_V16QI, BT_V16QI, BT_V16QI, BT_V16QI) @@ -347,7 +344,6 @@ DEF_FN_TYPE_3 (BT_FN_V4SI_V4SI_V4SI_V4SI, BT_V4SI, BT_V4SI, BT_V4SI, BT_V4SI) DEF_FN_TYPE_3 (BT_FN_V4SI_V8HI_V8HI_V4SI, BT_V4SI, BT_V8HI, BT_V8HI, BT_V4SI) DEF_FN_TYPE_3 (BT_FN_V8HI_UV8HI_UV8HI_INTPTR, BT_V8HI, BT_UV8HI, BT_UV8HI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_V8HI_V16QI_V16QI_V8HI, BT_V8HI, BT_V16QI, BT_V16QI, BT_V8HI) -DEF_FN_TYPE_3 (BT_FN_V8HI_V4SF_V4SF_UINT, BT_V8HI, BT_V4SF, BT_V4SF, BT_UINT) DEF_FN_TYPE_3 (BT_FN_V8HI_V4SI_V4SI_INTPTR, BT_V8HI, BT_V4SI, BT_V4SI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_V8HI_V8HI_V8HI_INTPTR, BT_V8HI, BT_V8HI, BT_V8HI, BT_INTPTR) DEF_FN_TYPE_3 (BT_FN_V8HI_V8HI_V8HI_V8HI, BT_V8HI, BT_V8HI, BT_V8HI, BT_V8HI) diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def index b59fa09..b09c303 100644 --- a/gcc/config/s390/s390-builtins.def +++ b/gcc/config/s390/s390-builtins.def @@ -28,7 +28,6 @@ #undef O_U12 #undef O_U16 #undef O_U32 -#undef O_U64 #undef O_M12 @@ -89,11 +88,6 @@ #undef O3_U32 #undef O4_U32 -#undef O1_U64 -#undef O2_U64 -#undef O3_U64 -#undef O4_U64 - #undef O1_M12 #undef O2_M12 #undef O3_M12 @@ -163,21 +157,20 @@ #define O_U12 7 /* unsigned 16 bit literal */ #define O_U16 8 /* unsigned 16 bit literal */ #define O_U32 9 /* unsigned 32 bit literal */ -#define O_U64 10 /* unsigned 64 bit literal */ -#define O_M12 11 /* matches bitmask of 12 */ +#define O_M12 10 /* matches bitmask of 12 */ -#define O_S2 12 /* signed 2 bit literal */ -#define O_S3 13 /* signed 3 bit literal */ -#define O_S4 14 /* signed 4 bit literal */ -#define O_S5 15 /* signed 5 bit literal */ -#define O_S8 16 /* signed 8 bit literal */ -#define O_S12 17 /* signed 12 bit literal */ -#define O_S16 18 /* signed 16 bit literal */ -#define O_S32 19 /* signed 32 bit literal */ +#define O_S2 11 /* signed 2 bit literal */ +#define O_S3 12 /* signed 3 bit literal */ +#define O_S4 13 /* signed 4 bit literal */ +#define O_S5 14 /* signed 5 bit literal */ +#define O_S8 15 /* signed 8 bit literal */ +#define O_S12 16 /* signed 12 bit literal */ +#define O_S16 17 /* signed 16 bit literal */ +#define O_S32 18 /* signed 32 bit literal */ -#define O_ELEM 20 /* Element selector requiring modulo arithmetic. */ -#define O_LIT 21 /* Operand must be a literal fitting the target type. */ +#define O_ELEM 19 /* Element selector requiring modulo arithmetic. */ +#define O_LIT 20 /* Operand must be a literal fitting the target type. */ #define O_SHIFT 5 @@ -230,11 +223,6 @@ #define O3_U32 (O_U32 << (2 * O_SHIFT)) #define O4_U32 (O_U32 << (3 * O_SHIFT)) -#define O1_U64 O_U64 -#define O2_U64 (O_U64 << O_SHIFT) -#define O3_U64 (O_U64 << (2 * O_SHIFT)) -#define O4_U64 (O_U64 << (3 * O_SHIFT)) - #define O1_M12 O_M12 #define O2_M12 (O_M12 << O_SHIFT) #define O3_M12 (O_M12 << (2 * O_SHIFT)) @@ -2001,19 +1989,19 @@ B_DEF (s390_verllvf, vrotlv4si3, 0, B_DEF (s390_verllvg, vrotlv2di3, 0, B_VX, 0, BT_FN_UV2DI_UV2DI_UV2DI) OB_DEF (s390_vec_rli, s390_vec_rli_u8, s390_vec_rli_s64, B_VX, BT_FN_OV4SI_OV4SI_ULONG) -OB_DEF_VAR (s390_vec_rli_u8, s390_verllb, 0, O2_U64, BT_OV_UV16QI_UV16QI_ULONG) -OB_DEF_VAR (s390_vec_rli_s8, s390_verllb, 0, O2_U64, BT_OV_V16QI_V16QI_ULONG) -OB_DEF_VAR (s390_vec_rli_u16, s390_verllh, 0, O2_U64, BT_OV_UV8HI_UV8HI_ULONG) -OB_DEF_VAR (s390_vec_rli_s16, s390_verllh, 0, O2_U64, BT_OV_V8HI_V8HI_ULONG) -OB_DEF_VAR (s390_vec_rli_u32, s390_verllf, 0, O2_U64, BT_OV_UV4SI_UV4SI_ULONG) -OB_DEF_VAR (s390_vec_rli_s32, s390_verllf, 0, O2_U64, BT_OV_V4SI_V4SI_ULONG) -OB_DEF_VAR (s390_vec_rli_u64, s390_verllg, 0, O2_U64, BT_OV_UV2DI_UV2DI_ULONG) -OB_DEF_VAR (s390_vec_rli_s64, s390_verllg, 0, O2_U64, BT_OV_V2DI_V2DI_ULONG) - -B_DEF (s390_verllb, rotlv16qi3, 0, B_VX, O2_U32, BT_FN_UV16QI_UV16QI_UINT) -B_DEF (s390_verllh, rotlv8hi3, 0, B_VX, O2_U32, BT_FN_UV8HI_UV8HI_UINT) -B_DEF (s390_verllf, rotlv4si3, 0, B_VX, O2_U32, BT_FN_UV4SI_UV4SI_UINT) -B_DEF (s390_verllg, rotlv2di3, 0, B_VX, O2_U32, BT_FN_UV2DI_UV2DI_UINT) +OB_DEF_VAR (s390_vec_rli_u8, s390_verllb, 0, 0, BT_OV_UV16QI_UV16QI_ULONG) +OB_DEF_VAR (s390_vec_rli_s8, s390_verllb, 0, 0, BT_OV_V16QI_V16QI_ULONG) +OB_DEF_VAR (s390_vec_rli_u16, s390_verllh, 0, 0, BT_OV_UV8HI_UV8HI_ULONG) +OB_DEF_VAR (s390_vec_rli_s16, s390_verllh, 0, 0, BT_OV_V8HI_V8HI_ULONG) +OB_DEF_VAR (s390_vec_rli_u32, s390_verllf, 0, 0, BT_OV_UV4SI_UV4SI_ULONG) +OB_DEF_VAR (s390_vec_rli_s32, s390_verllf, 0, 0, BT_OV_V4SI_V4SI_ULONG) +OB_DEF_VAR (s390_vec_rli_u64, s390_verllg, 0, 0, BT_OV_UV2DI_UV2DI_ULONG) +OB_DEF_VAR (s390_vec_rli_s64, s390_verllg, 0, 0, BT_OV_V2DI_V2DI_ULONG) + +B_DEF (s390_verllb, rotlv16qi3, 0, B_VX, 0, BT_FN_UV16QI_UV16QI_UCHAR) +B_DEF (s390_verllh, rotlv8hi3, 0, B_VX, 0, BT_FN_UV8HI_UV8HI_UCHAR) +B_DEF (s390_verllf, rotlv4si3, 0, B_VX, 0, BT_FN_UV4SI_UV4SI_UCHAR) +B_DEF (s390_verllg, rotlv2di3, 0, B_VX, 0, BT_FN_UV2DI_UV2DI_UCHAR) OB_DEF (s390_vec_rl_mask, s390_vec_rl_mask_s8,s390_vec_rl_mask_u64,B_VX, BT_FN_OV4SI_OV4SI_OV4SI_UCHAR) OB_DEF_VAR (s390_vec_rl_mask_s8, s390_verimb, 0, O3_U8, BT_OV_V16QI_V16QI_UV16QI_UCHAR) @@ -2840,10 +2828,10 @@ OB_DEF (s390_vec_double, s390_vec_double_s64,s390_vec_double_u64, OB_DEF_VAR (s390_vec_double_s64, s390_vcdgb, 0, 0, BT_OV_V2DF_V2DI) OB_DEF_VAR (s390_vec_double_u64, s390_vcdlgb, 0, 0, BT_OV_V2DF_UV2DI) -B_DEF (s390_vcefb, floatv4siv4sf2, 0, B_VXE2, O2_U4 | O3_U3, BT_FN_V4SF_V4SI) -B_DEF (s390_vcdgb, floatv2div2df2, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DF_V2DI) -B_DEF (s390_vcelfb, floatunsv4siv4sf2, 0, B_VXE2, O2_U4 | O3_U3, BT_FN_V4SF_UV4SI) -B_DEF (s390_vcdlgb, floatunsv2div2df2, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DF_UV2DI) +B_DEF (s390_vcefb, floatv4siv4sf2, 0, B_VXE2, 0, BT_FN_V4SF_V4SI) +B_DEF (s390_vcdgb, floatv2div2df2, 0, B_VX, 0, BT_FN_V2DF_V2DI) +B_DEF (s390_vcelfb, floatunsv4siv4sf2, 0, B_VXE2, 0, BT_FN_V4SF_UV4SI) +B_DEF (s390_vcdlgb, floatunsv2div2df2, 0, B_VX, 0, BT_FN_V2DF_UV2DI) OB_DEF (s390_vec_signed, s390_vec_signed_flt,s390_vec_signed_dbl,B_VX, BT_FN_OV4SI_OV4SI) OB_DEF_VAR (s390_vec_signed_flt, s390_vcfeb, B_VXE2, 0, BT_OV_V4SI_V4SF) @@ -2853,10 +2841,10 @@ OB_DEF (s390_vec_unsigned, s390_vec_unsigned_flt,s390_vec_unsigned_ OB_DEF_VAR (s390_vec_unsigned_flt, s390_vclfeb, B_VXE2, 0, BT_OV_UV4SI_V4SF) OB_DEF_VAR (s390_vec_unsigned_dbl, s390_vclgdb, 0, 0, BT_OV_UV2DI_V2DF) -B_DEF (s390_vcfeb, fix_truncv4sfv4si2, 0, B_VXE2, O2_U4 | O3_U3, BT_FN_V4SI_V4SF) -B_DEF (s390_vcgdb, fix_truncv2dfv2di2, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DI_V2DF) -B_DEF (s390_vclfeb, fixuns_truncv4sfv4si2, 0, B_VXE2, O2_U4 | O3_U3, BT_FN_UV4SI_V4SF) -B_DEF (s390_vclgdb, fixuns_truncv2dfv2di2, 0, B_VX, O2_U4 | O3_U3, BT_FN_UV2DI_V2DF) +B_DEF (s390_vcfeb, fix_truncv4sfv4si2, 0, B_VXE2, 0, BT_FN_V4SI_V4SF) +B_DEF (s390_vcgdb, fix_truncv2dfv2di2, 0, B_VX, 0, BT_FN_V2DI_V2DF) +B_DEF (s390_vclfeb, fixuns_truncv4sfv4si2, 0, B_VXE2, 0, BT_FN_UV4SI_V4SF) +B_DEF (s390_vclgdb, fixuns_truncv2dfv2di2, 0, B_VX, 0, BT_FN_UV2DI_V2DF) B_DEF (s390_vfisb, vec_fpintv4sf, 0, B_VXE, O2_U4 | O3_U3, BT_FN_V4SF_V4SF_UCHAR_UCHAR) B_DEF (s390_vfidb, vec_fpintv2df, 0, B_VX, O2_U4 | O3_U3, BT_FN_V2DF_V2DF_UCHAR_UCHAR) @@ -3037,10 +3025,10 @@ B_DEF (s390_vstrszf, vstrszv4si, 0, /* arch 14 builtins */ -B_DEF (s390_vclfnhs, vclfnhs_v8hi, 0, B_NNPA, O2_U4, BT_FN_V4SF_V8HI_UINT) -B_DEF (s390_vclfnls, vclfnls_v8hi, 0, B_NNPA, O2_U4, BT_FN_V4SF_V8HI_UINT) +B_DEF (s390_vclfnhs, vclfnhs_v8hi, 0, B_NNPA, O2_U4, BT_FN_V4SF_UV8HI_UINT) +B_DEF (s390_vclfnls, vclfnls_v8hi, 0, B_NNPA, O2_U4, BT_FN_V4SF_UV8HI_UINT) -B_DEF (s390_vcrnfs, vcrnfs_v8hi, 0, B_NNPA, O3_U4, BT_FN_V8HI_V4SF_V4SF_UINT) +B_DEF (s390_vcrnfs, vcrnfs_v8hi, 0, B_NNPA, O3_U4, BT_FN_UV8HI_V4SF_V4SF_UINT) -B_DEF (s390_vcfn, vcfn_v8hi, 0, B_NNPA, O2_U4, BT_FN_V8HI_V8HI_UINT) -B_DEF (s390_vcnf, vcnf_v8hi, 0, B_NNPA, O2_U4, BT_FN_V8HI_V8HI_UINT) +B_DEF (s390_vcfn, vcfn_v8hi, 0, B_NNPA, O2_U4, BT_FN_UV8HI_UV8HI_UINT) +B_DEF (s390_vcnf, vcnf_v8hi, 0, B_NNPA, O2_U4, BT_FN_UV8HI_UV8HI_UINT) diff --git a/gcc/config/s390/s390-c.cc b/gcc/config/s390/s390-c.cc index fce56934..7e455ab 100644 --- a/gcc/config/s390/s390-c.cc +++ b/gcc/config/s390/s390-c.cc @@ -409,6 +409,7 @@ s390_cpu_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__LONG_DOUBLE_128__"); cl_target_option_save (&opts, &global_options, &global_options_set); s390_cpu_cpp_builtins_internal (pfile, &opts, NULL); + cpp_define (pfile, "__GCC_ASM_FLAG_OUTPUTS__"); } #if S390_USE_TARGET_ATTRIBUTE diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc index e36efec..29b5dc9 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -815,8 +815,8 @@ s390_const_operand_ok (tree arg, int argnum, int op_flags, tree decl) { if (O_UIMM_P (op_flags)) { - unsigned HOST_WIDE_INT bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32, 64, 4 }; - unsigned HOST_WIDE_INT bitmasks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 }; + unsigned HOST_WIDE_INT bitwidths[] = { 1, 2, 3, 4, 5, 8, 12, 16, 32, 4 }; + unsigned HOST_WIDE_INT bitmasks[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 12 }; unsigned HOST_WIDE_INT bitwidth = bitwidths[op_flags - O_U1]; unsigned HOST_WIDE_INT bitmask = bitmasks[op_flags - O_U1]; @@ -824,7 +824,7 @@ s390_const_operand_ok (tree arg, int argnum, int op_flags, tree decl) gcc_assert(ARRAY_SIZE(bitmasks) == (O_M12 - O_U1 + 1)); if (!tree_fits_uhwi_p (arg) - || tree_to_uhwi (arg) > ((HOST_WIDE_INT_1U << (bitwidth - 1) << 1) - 1) + || tree_to_uhwi (arg) > (HOST_WIDE_INT_1U << bitwidth) - 1 || (bitmask && tree_to_uhwi (arg) & ~bitmask)) { if (bitmask) @@ -1874,6 +1874,97 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1, *code = new_code; } } + /* Remove UNSPEC_CC_TO_INT from connectives. This happens for + checks against multiple condition codes. */ + if (GET_CODE (*op0) == AND + && GET_CODE (XEXP (*op0, 0)) == UNSPEC + && XINT (XEXP (*op0, 0), 1) == UNSPEC_CC_TO_INT + && XVECLEN (XEXP (*op0, 0), 0) == 1 + && REGNO (XVECEXP (XEXP (*op0, 0), 0, 0)) == CC_REGNUM + && CONST_INT_P (XEXP (*op0, 1)) + && CONST_INT_P (*op1) + && INTVAL (XEXP (*op0, 1)) == -3 + && *code == EQ) + { + if (INTVAL (*op1) == 0) + { + /* case cc == 0 || cc = 2 => mask = 0xa */ + *op0 = XVECEXP (XEXP (*op0, 0), 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0xa); + } + else if (INTVAL (*op1) == 1) + { + /* case cc == 1 || cc == 3 => mask = 0x5 */ + *op0 = XVECEXP (XEXP (*op0, 0), 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0x5); + } + } + if (GET_CODE (*op0) == PLUS + && GET_CODE (XEXP (*op0, 0)) == UNSPEC + && XINT (XEXP (*op0, 0), 1) == UNSPEC_CC_TO_INT + && XVECLEN (XEXP (*op0, 0), 0) == 1 + && REGNO (XVECEXP (XEXP (*op0, 0), 0, 0)) == CC_REGNUM + && CONST_INT_P (XEXP (*op0, 1)) + && CONST_INT_P (*op1) + && (*code == LEU || *code == GTU)) + { + if (INTVAL (*op1) == 1) + { + if (INTVAL (XEXP (*op0, 1)) == -1) + { + /* case cc == 1 || cc == 2 => mask = 0x6 */ + *op0 = XVECEXP (XEXP (*op0, 0), 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0x6); + *code = *code == GTU ? NE : EQ; + } + else if (INTVAL (XEXP (*op0, 1)) == -2) + { + /* case cc == 2 || cc == 3 => mask = 0x3 */ + *op0 = XVECEXP (XEXP (*op0, 0), 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0x3); + *code = *code == GTU ? NE : EQ; + } + } + else if (INTVAL (*op1) == 2 + && INTVAL (XEXP (*op0, 1)) == -1) + { + /* case cc == 1 || cc == 2 || cc == 3 => mask = 0x7 */ + *op0 = XVECEXP (XEXP (*op0, 0), 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0x7); + *code = *code == GTU ? NE : EQ; + } + } + else if (*code == LEU || *code == GTU) + { + if (GET_CODE (*op0) == UNSPEC + && XINT (*op0, 1) == UNSPEC_CC_TO_INT + && XVECLEN (*op0, 0) == 1 + && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM + && CONST_INT_P (*op1)) + { + if (INTVAL (*op1) == 1) + { + /* case cc == 0 || cc == 1 => mask = 0xc */ + *op0 = XVECEXP (*op0, 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0xc); + *code = *code == GTU ? NE : EQ; + } + else if (INTVAL (*op1) == 2) + { + /* case cc == 0 || cc == 1 || cc == 2 => mask = 0xd */ + *op0 = XVECEXP (*op0, 0, 0); + *op1 = gen_rtx_CONST_INT (VOIDmode, 0xd); + *code = *code == GTU ? NE : EQ; + } + else if (INTVAL (*op1) == 3) + { + /* always true */ + *op0 = const0_rtx; + *op1 = const0_rtx; + *code = *code == GTU ? NE : EQ; + } + } + } /* Simplify cascaded EQ, NE with const0_rtx. */ if ((*code == NE || *code == EQ) @@ -17425,22 +17516,60 @@ static rtx_insn * s390_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &inputs, vec<machine_mode> &input_modes, vec<const char *> &constraints, vec<rtx> & /*clobbers*/, - HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/) + HARD_REG_SET &clobbered_regs, location_t loc) { - if (!TARGET_VXE) - /* Long doubles are stored in FPR pairs - nothing to do. */ - return NULL; rtx_insn *after_md_seq = NULL, *after_md_end = NULL; + bool saw_cc = false; unsigned ninputs = inputs.length (); unsigned noutputs = outputs.length (); for (unsigned i = 0; i < noutputs; i++) { + const char *constraint = constraints[i]; + if (strncmp (constraint, "=@cc", 4) == 0) + { + if (constraint[4] != 0) + { + error_at (loc, "invalid cc output constraint: %qs", constraint); + continue; + } + if (saw_cc) + { + error_at (loc, "multiple cc output constraints not supported"); + continue; + } + if (TEST_HARD_REG_BIT (clobbered_regs, CC_REGNUM)) + { + error_at (loc, "%<asm%> specifier for cc output conflicts with %<asm%> clobber list"); + continue; + } + rtx dest = outputs[i]; + if (GET_MODE (dest) != SImode) + { + error ("invalid type for cc output constraint"); + continue; + } + saw_cc = true; + constraints[i] = "=c"; + outputs[i] = gen_rtx_REG (CCRAWmode, CC_REGNUM); + + push_to_sequence2 (after_md_seq, after_md_end); + emit_insn (gen_rtx_SET (dest, + gen_rtx_UNSPEC (SImode, + gen_rtvec (1, outputs[i]), + UNSPEC_CC_TO_INT))); + after_md_seq = get_insns (); + after_md_end = get_last_insn (); + end_sequence (); + continue; + } + if (!TARGET_VXE) + /* Long doubles are stored in FPR pairs - nothing to do. */ + continue; if (GET_MODE (outputs[i]) != TFmode) /* Not a long double - nothing to do. */ continue; - const char *constraint = constraints[i]; bool allows_mem, allows_reg, is_inout; bool ok = parse_output_constraint (&constraint, i, ninputs, noutputs, &allows_mem, &allows_reg, &is_inout); diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 4bdb679..685bb28 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -1356,13 +1356,13 @@ (define_insn "*cmphi_ccu" [(set (reg CC_REGNUM) (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,Q,BQ") - (match_operand:HI 1 "general_operand" "Q,S,D,BQ,Q")))] + (match_operand:HI 1 "general_operand" "Q,S,n,BQ,Q")))] "s390_match_ccmode (insn, CCUmode) && !register_operand (operands[1], HImode)" "@ clm\t%0,3,%S1 clmy\t%0,3,%S1 - clhhsi\t%0,%1 + clhhsi\t%0,%x1 # #" [(set_attr "op_type" "RS,RSY,SIL,SS,SS") @@ -1688,8 +1688,6 @@ [(set (match_operand:TI 0 "nonimmediate_operand" "") (match_operand:TI 1 "general_operand" ""))] "TARGET_ZARCH && reload_completed - && !s_operand (operands[0], TImode) - && !s_operand (operands[1], TImode) && s390_split_ok_p (operands[0], operands[1], TImode, 0)" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] @@ -1704,8 +1702,6 @@ [(set (match_operand:TI 0 "nonimmediate_operand" "") (match_operand:TI 1 "general_operand" ""))] "TARGET_ZARCH && reload_completed - && !s_operand (operands[0], TImode) - && !s_operand (operands[1], TImode) && s390_split_ok_p (operands[0], operands[1], TImode, 1)" [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] @@ -6932,7 +6928,7 @@ [(set (match_operand:SI 0 "register_operand" "") (match_operator:SI 1 "s390_eqne_operator" [(match_operand 2 "cc_reg_operand") - (match_operand 3 "const0_operand")])) + (match_operand 3 "const_mask_operand")])) (clobber (reg:CC CC_REGNUM))])] "" "machine_mode mode = GET_MODE (operands[2]); @@ -6941,15 +6937,15 @@ rtx cond, ite; if (GET_CODE (operands[1]) == NE) - cond = gen_rtx_NE (VOIDmode, operands[2], const0_rtx); + cond = gen_rtx_NE (VOIDmode, operands[2], operands[3]); else - cond = gen_rtx_EQ (VOIDmode, operands[2], const0_rtx); + cond = gen_rtx_EQ (VOIDmode, operands[2], operands[3]); ite = gen_rtx_IF_THEN_ELSE (SImode, cond, const1_rtx, const0_rtx); emit_insn (gen_rtx_SET (operands[0], ite)); } else { - if (mode != CCZ1mode) + if (mode != CCZ1mode || operands[3] != const0_rtx) FAIL; emit_insn (gen_sne (operands[0], operands[2])); if (GET_CODE (operands[1]) == EQ) @@ -12252,9 +12248,9 @@ (define_insn "@split_stack_call<mode>" [(set (pc) (label_ref (match_operand 2 "" ""))) ; call done label - (set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X") - (reg:P 1)] - UNSPECV_SPLIT_STACK_CALL)) + (set (reg:P 1) (unspec_volatile:P [(match_operand 0 "bras_sym_operand" "X") + (reg:P 1)] + UNSPECV_SPLIT_STACK_CALL)) (use (label_ref (match_operand 1 "" "X"))) ; parm block label (use (match_operand 3 "const_int_operand" "X")) ; frame size (use (match_operand 4 "const_int_operand" "X"))] ; arg size @@ -12274,9 +12270,9 @@ (match_operand 5 "" "") ; condition (label_ref (match_operand 2 "" "")) ; call done label (pc))) - (set (reg:P 1) (unspec_volatile [(match_operand 0 "bras_sym_operand" "X") - (reg:P 1)] - UNSPECV_SPLIT_STACK_CALL)) + (set (reg:P 1) (unspec_volatile:P [(match_operand 0 "bras_sym_operand" "X") + (reg:P 1)] + UNSPECV_SPLIT_STACK_CALL)) (use (label_ref (match_operand 1 "" "X"))) ; parm block label (use (match_operand 3 "const_int_operand" "X")) ; frame size (use (match_operand 4 "const_int_operand" "X"))] ; arg size diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 4f4c9d9..626ec11 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -531,12 +531,14 @@ (match_operand:V 1 "nonmemory_operand" "v,v") (parallel [(match_operand:SI 2 "nonmemory_operand" "an,I")])))] - "TARGET_VX - && (!CONST_INT_P (operands[2]) - || UINTVAL (operands[2]) < GET_MODE_NUNITS (<V:MODE>mode))" - "@ - vlgv<bhfgq>\t%0,%v1,%Y2 - vste<bhfgq>\t%v1,%0,%2" + "TARGET_VX" + { + if (CONST_INT_P (operands[2])) + operands[2] = GEN_INT (UINTVAL (operands[2]) & (GET_MODE_NUNITS (<V:MODE>mode) - 1)); + if (which_alternative == 0) + return "vlgv<bhfgq>\t%0,%v1,%Y2"; + return "vste<bhfgq>\t%v1,%0,%2"; + } [(set_attr "op_type" "VRS,VRX")]) ; vlgvb, vlgvh, vlgvf, vlgvg diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 193f40d..8321d9f 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -10936,7 +10936,7 @@ ;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). (define_insn "sp_switch_1" - [(set (reg:SI SP_REG) (unspec_volatile [(match_operand:SI 0 "" "")] + [(set (reg:SI SP_REG) (unspec_volatile:SI [(match_operand:SI 0 "" "")] UNSPECV_SP_SWITCH_B))] "TARGET_SH1" { diff --git a/gcc/config/vax/vax.cc b/gcc/config/vax/vax.cc index df9478d..032de71 100644 --- a/gcc/config/vax/vax.cc +++ b/gcc/config/vax/vax.cc @@ -1831,7 +1831,9 @@ nonindexed_address_p (rtx x, bool strict) } /* True if PROD is either a reg times size of mode MODE and MODE is less - than or equal 8 bytes, or just a reg if MODE is one byte. */ + than or equal 8 bytes, or just a reg if MODE is one byte. For a MULT + RTX we accept its operands in either order, however ASHIFT is not + commutative, so in that case reg has to be the left operand. */ static bool index_term_p (rtx prod, machine_mode mode, bool strict) @@ -1850,8 +1852,9 @@ index_term_p (rtx prod, machine_mode mode, bool strict) xfoo0 = XEXP (prod, 0); xfoo1 = XEXP (prod, 1); - if (CONST_INT_P (xfoo0) - && GET_MODE_SIZE (mode) == (log_p ? 1 << INTVAL (xfoo0) : INTVAL (xfoo0)) + if (!log_p + && CONST_INT_P (xfoo0) + && GET_MODE_SIZE (mode) == INTVAL (xfoo0) && INDEX_REGISTER_P (xfoo1, strict)) return true; diff --git a/gcc/configure b/gcc/configure index cc0c3aa..de72cb1 100755 --- a/gcc/configure +++ b/gcc/configure @@ -1009,6 +1009,7 @@ enable_rpath with_libiconv_prefix with_libiconv_type enable_sjlj_exceptions +enable_win32_utf8_manifest with_gcc_major_version_only enable_nls with_libintl_prefix @@ -1740,6 +1741,11 @@ Optional Features: --disable-rpath do not hardcode runtime library paths --enable-sjlj-exceptions arrange to use setjmp/longjmp exception handling + --disable-win32-utf8-manifest + disable embedding a utf8 manifest on mingw hosts + --enable-win32-utf8-manifest + enable embedding a utf8 manifest on mingw hosts + (default) --disable-nls do not use Native Language Support --enable-secureplt enable -msecure-plt by default for PowerPC --enable-mingw-wildcard Set whether to expand wildcard on command-line. @@ -7679,63 +7685,6 @@ $as_echo "#define ENABLE_FOLD_CHECKING 1" >>confdefs.h fi valgrind_path_defines= valgrind_command= - -ac_fn_cxx_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default" -if test "x$ac_cv_header_valgrind_h" = xyes; then : - have_valgrind_h=yes -else - have_valgrind_h=no -fi - - - -# It is certainly possible that there's valgrind but no valgrind.h. -# GCC relies on making annotations so we must have both. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5 -$as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <valgrind/memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - gcc_cv_header_valgrind_memcheck_h=yes -else - gcc_cv_header_valgrind_memcheck_h=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5 -$as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5 -$as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif -_ACEOF -if ac_fn_cxx_try_cpp "$LINENO"; then : - gcc_cv_header_memcheck_h=yes -else - gcc_cv_header_memcheck_h=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5 -$as_echo "$gcc_cv_header_memcheck_h" >&6; } -if test $gcc_cv_header_valgrind_memcheck_h = yes; then - -$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h - -fi -if test $gcc_cv_header_memcheck_h = yes; then - -$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h - -fi - if test x$ac_valgrind_checking != x ; then # Prepare PATH_SEPARATOR. @@ -7804,11 +7753,8 @@ else $as_echo "no" >&6; } fi - if test "x$valgrind_path" = "x" \ - || (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - as_fn_error $? "*** Can't find both valgrind and valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 + if test "x$valgrind_path" = "x"; then + as_fn_error $? "*** Cannot find valgrind" "$LINENO" 5 fi valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"' valgrind_command="$valgrind_path -q" @@ -7864,12 +7810,16 @@ else enable_valgrind_annotations=no fi +ac_fn_cxx_check_header_mongrel "$LINENO" "valgrind/memcheck.h" "ac_cv_header_valgrind_memcheck_h" "$ac_includes_default" +if test "x$ac_cv_header_valgrind_memcheck_h" = xyes; then : + +fi + + if test x$enable_valgrind_annotations != xno \ || test x$ac_valgrind_checking != x; then - if (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - as_fn_error $? "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 + if test $ac_cv_header_valgrind_memcheck_h = no; then + as_fn_error $? "*** Cannot find valgrind/memcheck.h" "$LINENO" 5 fi $as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h @@ -13046,6 +12996,23 @@ _ACEOF fi +# Windows32 UTF-8 manifest support for running the driver and compiler +# executables with the UTF-8 active code page on mingw hosts. +# Non-mingw hosts ignore this option. +# The shell variables this sets are picked up from the mingw branches +# of config.host so they have to be set before it gets sourced. +# Check whether --enable-win32-utf8-manifest was given. +if test "${enable_win32_utf8_manifest+set}" = set; then : + enableval=$enable_win32_utf8_manifest; +fi + + +if test "x$enable_win32_utf8_manifest" != xno; then + host_xmake_mingw=i386/x-mingw32-utf8 + host_extra_gcc_objs_mingw=utf8rc-mingw32.o + host_extra_objs_mingw=utf8-mingw32.o +fi + # -------------------------------------------------------- # Build, host, and target specific configuration fragments # -------------------------------------------------------- @@ -21602,7 +21569,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21605 "configure" +#line 21572 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -21708,7 +21675,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 21711 "configure" +#line 21678 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -34615,7 +34582,7 @@ if test x"$ld_is_gold" = xno; then ld_bndplt_support=yes fi elif test x$gcc_cv_ld != x; then - # Check if linker supports -a bndplt option + # Check if linker supports -z bndplt option if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then ld_bndplt_support=yes fi @@ -34744,6 +34711,72 @@ $as_echo "#define ENABLE_S390_EXCESS_FLOAT_PRECISION 1" >>confdefs.h ;; esac +# Check if the linker supports '-z now' +ld_now_support=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z now option" >&5 +$as_echo_n "checking linker -z now option... " >&6; } +if test x"$ld_is_gold" = xyes; then + ld_now_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_now_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z now + if $gcc_cv_ld --help 2>&1 | grep -- '-z now' > /dev/null; then + ld_now_support=yes + fi +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_LD_NOW_SUPPORT `if test x"$ld_now_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_now_support" >&5 +$as_echo "$ld_now_support" >&6; } + +# Check if the linker supports '-z relro' +ld_relro_support=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z relro option" >&5 +$as_echo_n "checking linker -z relro option... " >&6; } +if test x"$ld_is_gold" = xyes; then + ld_relro_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 15 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_relro_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z relro + if $gcc_cv_ld --help 2>&1 | grep -- '-z relro' > /dev/null; then + ld_relro_support=yes + fi +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_LD_RELRO_SUPPORT `if test x"$ld_relro_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_relro_support" >&5 +$as_echo "$ld_relro_support" >&6; } + +case $target_os in +linux* | gnu*) + # -fhardened is only supported on GNU/Linux. + fhardened_support=yes + ;; +*) + fhardened_support=no + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_FHARDENED_SUPPORT `if test x"$fhardened_support" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $fhardened_support" >&5 +$as_echo "$fhardened_support" >&6; } + # Configure the subdirectories # AC_CONFIG_SUBDIRS($subdirs) diff --git a/gcc/configure.ac b/gcc/configure.ac index d9a3506..21ba631 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -778,49 +778,11 @@ if test x$ac_fold_checking != x ; then fi valgrind_path_defines= valgrind_command= - -dnl # This check AC_REQUIREs various stuff, so it *must not* be inside -dnl # an if statement. This was the source of very frustrating bugs -dnl # in converting to autoconf 2.5x! -AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no) - -# It is certainly possible that there's valgrind but no valgrind.h. -# GCC relies on making annotations so we must have both. -AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>) -AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <valgrind/memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif]])], - [gcc_cv_header_valgrind_memcheck_h=yes], - [gcc_cv_header_valgrind_memcheck_h=no]) -AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h) -AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>) -AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif]])], - [gcc_cv_header_memcheck_h=yes], - [gcc_cv_header_memcheck_h=no]) -AC_MSG_RESULT($gcc_cv_header_memcheck_h) -if test $gcc_cv_header_valgrind_memcheck_h = yes; then - AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, - [Define if valgrind's valgrind/memcheck.h header is installed.]) -fi -if test $gcc_cv_header_memcheck_h = yes; then - AC_DEFINE(HAVE_MEMCHECK_H, 1, - [Define if valgrind's memcheck.h header is installed.]) -fi - if test x$ac_valgrind_checking != x ; then AM_PATH_PROG_WITH_TEST(valgrind_path, valgrind, [$ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1]) - if test "x$valgrind_path" = "x" \ - || (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - AC_MSG_ERROR([*** Can't find both valgrind and valgrind/memcheck.h, memcheck.h or valgrind.h]) + if test "x$valgrind_path" = "x"; then + AC_MSG_ERROR([*** Cannot find valgrind]) fi valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"' valgrind_command="$valgrind_path -q" @@ -869,12 +831,11 @@ AC_ARG_ENABLE(valgrind-annotations, [AS_HELP_STRING([--enable-valgrind-annotations], [enable valgrind runtime interaction])], [], [enable_valgrind_annotations=no]) +AC_CHECK_HEADER(valgrind/memcheck.h) if test x$enable_valgrind_annotations != xno \ || test x$ac_valgrind_checking != x; then - if (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h]) + if test $ac_cv_header_valgrind_memcheck_h = no; then + AC_MSG_ERROR([*** Cannot find valgrind/memcheck.h]) fi AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1, [Define to get calls to the valgrind runtime enabled.]) @@ -1894,6 +1855,23 @@ if test $force_sjlj_exceptions = yes; then [Define 0/1 to force the choice for exception handling model.]) fi +# Windows32 UTF-8 manifest support for running the driver and compiler +# executables with the UTF-8 active code page on mingw hosts. +# Non-mingw hosts ignore this option. +# The shell variables this sets are picked up from the mingw branches +# of config.host so they have to be set before it gets sourced. +AC_ARG_ENABLE(win32-utf8-manifest, +[AS_HELP_STRING([--disable-win32-utf8-manifest], + [disable embedding a utf8 manifest on mingw hosts]) +AS_HELP_STRING([--enable-win32-utf8-manifest], + [enable embedding a utf8 manifest on mingw hosts (default)])],,) + +if test "x$enable_win32_utf8_manifest" != xno; then + host_xmake_mingw=i386/x-mingw32-utf8 + host_extra_gcc_objs_mingw=utf8rc-mingw32.o + host_extra_objs_mingw=utf8-mingw32.o +fi + # -------------------------------------------------------- # Build, host, and target specific configuration fragments # -------------------------------------------------------- @@ -7747,7 +7725,7 @@ if test x"$ld_is_gold" = xno; then ld_bndplt_support=yes fi elif test x$gcc_cv_ld != x; then - # Check if linker supports -a bndplt option + # Check if linker supports -z bndplt option if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then ld_bndplt_support=yes fi @@ -7848,6 +7826,61 @@ standards-compatible mode on s390 targets.]) ;; esac +# Check if the linker supports '-z now' +ld_now_support=no +AC_MSG_CHECKING(linker -z now option) +if test x"$ld_is_gold" = xyes; then + ld_now_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_now_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z now + if $gcc_cv_ld --help 2>&1 | grep -- '-z now' > /dev/null; then + ld_now_support=yes + fi +fi +AC_DEFINE_UNQUOTED(HAVE_LD_NOW_SUPPORT, + [`if test x"$ld_now_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your linker supports -z now]) +AC_MSG_RESULT($ld_now_support) + +# Check if the linker supports '-z relro' +ld_relro_support=no +AC_MSG_CHECKING(linker -z relro option) +if test x"$ld_is_gold" = xyes; then + ld_relro_support=yes +elif test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 15 -o "$gcc_cv_gld_major_version" -gt 2; then + ld_relro_support=yes + fi +elif test x$gcc_cv_ld != x; then + # Check if linker supports -z relro + if $gcc_cv_ld --help 2>&1 | grep -- '-z relro' > /dev/null; then + ld_relro_support=yes + fi +fi +AC_DEFINE_UNQUOTED(HAVE_LD_RELRO_SUPPORT, + [`if test x"$ld_relro_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your linker supports -z relro]) +AC_MSG_RESULT($ld_relro_support) + +case $target_os in +linux* | gnu*) + # -fhardened is only supported on GNU/Linux. + fhardened_support=yes + ;; +*) + fhardened_support=no + ;; +esac + +AC_DEFINE_UNQUOTED(HAVE_FHARDENED_SUPPORT, + [`if test x"$fhardened_support" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if -fhardened is supported]) +AC_MSG_RESULT($fhardened_support) + # Configure the subdirectories # AC_CONFIG_SUBDIRS($subdirs) diff --git a/gcc/convert.cc b/gcc/convert.cc index ac6af70..46c8bcb 100644 --- a/gcc/convert.cc +++ b/gcc/convert.cc @@ -292,7 +292,7 @@ convert_to_real_1 (tree type, tree expr, bool fold_p) case NEGATE_EXPR: if (!flag_rounding_math && FLOAT_TYPE_P (itype) - && TYPE_PRECISION (type) < TYPE_PRECISION (itype)) + && element_precision (type) < element_precision (itype)) { tree arg = convert_to_real_1 (type, TREE_OPERAND (expr, 0), fold_p); @@ -334,6 +334,10 @@ convert_to_real_1 (tree type, tree expr, bool fold_p) error ("pointer value used where a floating-point was expected"); return error_mark_node; + case VECTOR_TYPE: + error ("vector value used where a floating-point was expected"); + return error_mark_node; + default: error ("aggregate value used where a floating-point was expected"); return error_mark_node; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1feb5b3..fb257ad 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,100 @@ +2023-11-25 Nathaniel Shead <nathanieloshead@gmail.com> + + * name-lookup.cc (check_can_export_using_decl): New. + (do_nonmember_using_decl): Use above to check if names can be + exported. + +2023-11-25 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/102341 + * decl.cc (duplicate_decls): Allow exporting a redeclaration of + a typedef. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * parser.cc (cp_parser_omp_clause_dist_schedule, + cp_parser_omp_scan_loop_body, cp_parser_omp_assumption_clauses, + cp_parser_omp_depobj): Add OPT_Wopenmp to warning_at. + * semantics.cc (finish_omp_clauses): Likewise. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * parser.cc (cp_parser_omp_depobj): Accept optionally an argument + to the destroy clause. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/99232 + * decl.cc (grokvardecl): Don't mark variables attached to + modules as internal. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/107398 + * module.cc (trees_out::get_merge_kind): Handle lambdas in class + scope. + (maybe_key_decl): Remove assertion and fix whitespace. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/98885 + * decl.cc (duplicate_decls): Adjust error message. + (xref_tag): Adjust error message. Check exporting decl that is + already declared as non-exporting. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR c++/110348 + * parser.cc: Implement C++26 P2741R3 - user-generated static_assert + messages. + (cp_parser_static_assert): Parse message argument as + conditional-expression if it is not a pure string literal or + several of them concatenated followed by closing paren. + * semantics.cc (finish_static_assert): Handle message which is not + STRING_CST. For condition with bare parameter packs return early. + * pt.cc (tsubst_expr) <case STATIC_ASSERT>: Also tsubst_expr + message and make sure that if it wasn't originally STRING_CST, it + isn't after tsubst_expr either. + +2023-11-22 Patrick Palka <ppalka@redhat.com> + + PR c++/112633 + * pt.cc (tsubst_aggr_type): Handle empty TYPE_TEMPLATE_INFO + in the entering_scope adjustment. + +2023-11-22 Jason Merrill <jason@redhat.com> + + * decl.cc (start_preparsed_function): Clarify ctype logic. + +2023-11-20 Marc Poulhiès <dkm@kataplop.net> + + * lambda.cc (compare_lambda_sig): Fix typo in variadic. + +2023-11-20 Jason Merrill <jason@redhat.com> + + * pt.cc (comp_template_parms): Just one level. + (template_parameter_lists_equivalent_p): Likewise. + +2023-11-20 Jason Merrill <jason@redhat.com> + + * cp-tree.h (DECL_TEMPLATE_PARM_CHECK): New. + (DECL_IMPLICIT_TEMPLATE_PARM_P): New. + (decl_template_parm_check): New. + * mangle.cc (write_closure_template_head): Use it. + * parser.cc (synthesize_implicit_template_parm): Likewise. + * pt.cc (template_parameters_equivalent_p): Likewise. + +2023-11-19 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/99187 + * cp-tree.h (enum cp_tree_index): Add CPTI_THREAD_ATEXIT. + (thread_atexit_node): New. + * decl.cc (get_thread_atexit_node): Cache in thread_atexit_node. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * mapper-client.cc: Include "rich-location.h". + 2023-11-16 Jakub Jelinek <jakub@redhat.com> PR c++/112365 diff --git a/gcc/cp/cp-lang.cc b/gcc/cp/cp-lang.cc index f2ed83d..bdc25dd 100644 --- a/gcc/cp/cp-lang.cc +++ b/gcc/cp/cp-lang.cc @@ -119,6 +119,15 @@ objcp_tsubst_expr (tree /*t*/, tree /*args*/, tsubst_flags_t /*complain*/, return NULL_TREE; } +/* Implement c-family hook to add language-specific features + for __has_{feature,extension}. */ + +void +c_family_register_lang_features () +{ + cp_register_features (); +} + static const char * cxx_dwarf_name (tree t, int verbosity) { diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc index 2093ae0..70f9e4a 100644 --- a/gcc/cp/cp-objcp-common.cc +++ b/gcc/cp/cp-objcp-common.cc @@ -23,10 +23,154 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "cp-tree.h" #include "cp-objcp-common.h" +#include "c-family/c-common.h" #include "dwarf2.h" #include "stringpool.h" #include "contracts.h" +/* Class to determine whether a given C++ language feature is available. + Used to implement __has_{feature,extension}. */ + +struct cp_feature_selector +{ + enum + { + DIALECT, + FLAG + } kind; + + enum class result + { + NONE, + EXT, + FEAT + }; + + union + { + const int *enable_flag; + struct { + enum cxx_dialect feat; + enum cxx_dialect ext; + } dialect; + }; + + constexpr cp_feature_selector (const int *flag) + : kind (FLAG), enable_flag (flag) {} + constexpr cp_feature_selector (enum cxx_dialect feat, + enum cxx_dialect ext) + : kind (DIALECT), dialect{feat, ext} {} + constexpr cp_feature_selector (enum cxx_dialect feat) + : cp_feature_selector (feat, feat) {} + + inline result has_feature () const; +}; + +/* Check whether this language feature is available as a feature, + extension, or not at all. */ + +cp_feature_selector::result +cp_feature_selector::has_feature () const +{ + switch (kind) + { + case DIALECT: + if (cxx_dialect >= dialect.feat) + return result::FEAT; + else if (cxx_dialect >= dialect.ext) + return result::EXT; + else + return result::NONE; + case FLAG: + return *enable_flag ? result::FEAT : result::NONE; + } + + gcc_unreachable (); +} + +/* Information about a C++ language feature which can be queried + through __has_{feature,extension}. IDENT is the name of the feature, + and SELECTOR encodes how to compute whether the feature is available. */ + +struct cp_feature_info +{ + const char *ident; + cp_feature_selector selector; +}; + +/* Table of features for __has_{feature,extension}. */ + +static constexpr cp_feature_info cp_feature_table[] = +{ + { "cxx_exceptions", &flag_exceptions }, + { "cxx_rtti", &flag_rtti }, + { "cxx_access_control_sfinae", { cxx11, cxx98 } }, + { "cxx_alias_templates", cxx11 }, + { "cxx_alignas", cxx11 }, + { "cxx_alignof", cxx11 }, + { "cxx_attributes", cxx11 }, + { "cxx_constexpr", cxx11 }, + { "cxx_constexpr_string_builtins", cxx11 }, + { "cxx_decltype", cxx11 }, + { "cxx_decltype_incomplete_return_types", cxx11 }, + { "cxx_default_function_template_args", cxx11 }, + { "cxx_defaulted_functions", cxx11 }, + { "cxx_delegating_constructors", cxx11 }, + { "cxx_deleted_functions", cxx11 }, + { "cxx_explicit_conversions", cxx11 }, + { "cxx_generalized_initializers", cxx11 }, + { "cxx_implicit_moves", cxx11 }, + { "cxx_inheriting_constructors", cxx11 }, + { "cxx_inline_namespaces", { cxx11, cxx98 } }, + { "cxx_lambdas", cxx11 }, + { "cxx_local_type_template_args", cxx11 }, + { "cxx_noexcept", cxx11 }, + { "cxx_nonstatic_member_init", cxx11 }, + { "cxx_nullptr", cxx11 }, + { "cxx_override_control", cxx11 }, + { "cxx_reference_qualified_functions", cxx11 }, + { "cxx_range_for", cxx11 }, + { "cxx_raw_string_literals", cxx11 }, + { "cxx_rvalue_references", cxx11 }, + { "cxx_static_assert", cxx11 }, + { "cxx_thread_local", cxx11 }, + { "cxx_auto_type", cxx11 }, + { "cxx_strong_enums", cxx11 }, + { "cxx_trailing_return", cxx11 }, + { "cxx_unicode_literals", cxx11 }, + { "cxx_unrestricted_unions", cxx11 }, + { "cxx_user_literals", cxx11 }, + { "cxx_variadic_templates", { cxx11, cxx98 } }, + { "cxx_binary_literals", { cxx14, cxx98 } }, + { "cxx_contextual_conversions", { cxx14, cxx98 } }, + { "cxx_decltype_auto", cxx14 }, + { "cxx_aggregate_nsdmi", cxx14 }, + { "cxx_init_captures", cxx14 }, + { "cxx_generic_lambdas", cxx14 }, + { "cxx_relaxed_constexpr", cxx14 }, + { "cxx_return_type_deduction", cxx14 }, + { "cxx_variable_templates", cxx14 }, + { "modules", &flag_modules }, +}; + +/* Register C++ language features for __has_{feature,extension}. */ + +void +cp_register_features () +{ + using result = cp_feature_selector::result; + + for (unsigned i = 0; i < ARRAY_SIZE (cp_feature_table); i++) + { + const cp_feature_info *info = cp_feature_table + i; + const auto res = info->selector.has_feature (); + if (res == result::NONE) + continue; + + c_common_register_feature (info->ident, res == result::FEAT); + } +} + /* Special routine to get the alias set for C++. */ alias_set_type diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 1408301..5b175b0 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -34,6 +34,7 @@ extern tree cp_classtype_as_base (const_tree); extern tree cp_get_global_decls (); extern tree cp_pushdecl (tree); extern void cp_register_dumps (gcc::dump_manager *); +extern void cp_register_features (); extern bool cp_handle_option (size_t, const char *, HOST_WIDE_INT, int, location_t, const struct cl_option_handlers *); extern tree cxx_make_type_hook (tree_code); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1fa710d..7b0b7c6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -231,6 +231,7 @@ enum cp_tree_index CPTI_RETHROW_FN, CPTI_ATEXIT_FN_PTR_TYPE, CPTI_ATEXIT, + CPTI_THREAD_ATEXIT, CPTI_DSO_HANDLE, CPTI_DCAST, @@ -375,6 +376,9 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; /* A pointer to `std::atexit'. */ #define atexit_node cp_global_trees[CPTI_ATEXIT] +/* A pointer to `__cxa_thread_atexit'. */ +#define thread_atexit_node cp_global_trees[CPTI_THREAD_ATEXIT] + /* A pointer to `__dso_handle'. */ #define dso_handle_node cp_global_trees[CPTI_DSO_HANDLE] @@ -673,10 +677,14 @@ template_info_decl_check (const_tree t, const char* f, int l, const char* fn) tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \ __t; }) +#define DECL_TEMPLATE_PARM_CHECK(NODE) \ + decl_template_parm_check ((NODE), __FILE__, __LINE__, __FUNCTION__) + #else /* ENABLE_TREE_CHECKING */ #define TEMPLATE_INFO_DECL_CHECK(NODE) (NODE) #define THUNK_FUNCTION_CHECK(NODE) (NODE) +#define DECL_TEMPLATE_PARM_CHECK(NODE) (NODE) #endif /* ENABLE_TREE_CHECKING */ @@ -3573,6 +3581,11 @@ struct GTY(()) lang_decl { need. But we want a more descriptive name. */ #define DECL_VTABLE_OR_VTT_P(NODE) DECL_VIRTUAL_P (VAR_DECL_CHECK (NODE)) +/* 1 iff a _DECL for a template parameter came from + synthesize_implicit_template_parm. */ +#define DECL_IMPLICIT_TEMPLATE_PARM_P(NODE) \ + DECL_VIRTUAL_P (DECL_TEMPLATE_PARM_CHECK (NODE)) + /* 1 iff FUNCTION_TYPE or METHOD_TYPE has a ref-qualifier (either & or &&). */ #define FUNCTION_REF_QUALIFIED(NODE) \ TREE_LANG_FLAG_4 (FUNC_OR_METHOD_CHECK (NODE)) @@ -5053,6 +5066,16 @@ get_vec_init_expr (tree t) || TREE_CODE (NODE) == TYPE_DECL \ || TREE_CODE (NODE) == TEMPLATE_DECL)) +#if ENABLE_TREE_CHECKING +inline tree +decl_template_parm_check (const_tree t, const char *f, int l, const char *fn) +{ + if (!DECL_TEMPLATE_PARM_P (t)) + tree_check_failed (t, f, l, fn, 0); + return const_cast<tree>(t); +} +#endif + /* Nonzero for a raw template parameter node. */ #define TEMPLATE_PARM_P(NODE) \ (TREE_CODE (NODE) == TEMPLATE_TYPE_PARM \ diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index b8e1098..e269f68 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2231,13 +2231,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } tree not_tmpl = STRIP_TEMPLATE (olddecl); - if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl)) + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_ATTACH_P (not_tmpl) + /* Typedefs are not entities and so are OK to be redeclared + as exported: see [module.interface]/p6. */ + && TREE_CODE (olddecl) != TYPE_DECL) { if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl)) && !DECL_MODULE_EXPORT_P (not_tmpl)) { - error ("conflicting exporting declaration %qD", newdecl); - inform (olddecl_loc, "previous declaration %q#D here", olddecl); + auto_diagnostic_group d; + error ("conflicting exporting for declaration %qD", newdecl); + inform (olddecl_loc, + "previously declared here without exporting"); } } else if (DECL_MODULE_EXPORT_P (newdecl)) @@ -9593,6 +9599,9 @@ get_atexit_node (void) static tree get_thread_atexit_node (void) { + if (thread_atexit_node) + return thread_atexit_node; + /* The declaration for `__cxa_thread_atexit' is: int __cxa_thread_atexit (void (*)(void *), void *, void *) */ @@ -9601,10 +9610,18 @@ get_thread_atexit_node (void) ptr_type_node, ptr_type_node, NULL_TREE); - /* Now, build the function declaration. */ + /* Now, build the function declaration, as with __cxa_atexit. */ + unsigned flags = push_abi_namespace (); tree atexit_fndecl = build_library_fn_ptr ("__cxa_thread_atexit", fn_type, ECF_LEAF | ECF_NOTHROW); - return decay_conversion (atexit_fndecl, tf_warning_or_error); + DECL_CONTEXT (atexit_fndecl) = FROB_CONTEXT (current_namespace); + DECL_SOURCE_LOCATION (atexit_fndecl) = BUILTINS_LOCATION; + atexit_fndecl = pushdecl (atexit_fndecl, /*hiding=*/true); + pop_abi_namespace (flags); + mark_used (atexit_fndecl); + thread_atexit_node = decay_conversion (atexit_fndecl, tf_warning_or_error); + + return thread_atexit_node; } /* Returns the __dso_handle VAR_DECL. */ @@ -10993,7 +11010,8 @@ grokvardecl (tree type, && (DECL_THIS_EXTERN (decl) || ! constp || volatilep - || inlinep)); + || inlinep + || module_attach_p ())); TREE_STATIC (decl) = ! DECL_EXTERNAL (decl); } /* Not at top level, only `static' makes a static definition. */ @@ -16250,11 +16268,24 @@ xref_tag (enum tag_types tag_code, tree name, tree decl = TYPE_NAME (t); if (!module_may_redeclare (decl)) { + auto_diagnostic_group d; error ("cannot declare %qD in a different module", decl); - inform (DECL_SOURCE_LOCATION (decl), "declared here"); + inform (DECL_SOURCE_LOCATION (decl), "previously declared here"); return error_mark_node; } + tree not_tmpl = STRIP_TEMPLATE (decl); + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_ATTACH_P (not_tmpl) + && !DECL_MODULE_EXPORT_P (not_tmpl) + && module_exporting_p ()) + { + auto_diagnostic_group d; + error ("conflicting exporting for declaration %qD", decl); + inform (DECL_SOURCE_LOCATION (decl), + "previously declared here without exporting"); + } + tree maybe_tmpl = decl; if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t)) maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t); @@ -17381,8 +17412,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags) gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE); tree fntype = TREE_TYPE (decl1); - if (TREE_CODE (fntype) == METHOD_TYPE) - ctype = TYPE_METHOD_BASETYPE (fntype); + if (DECL_CLASS_SCOPE_P (decl1)) + ctype = DECL_CONTEXT (decl1); else { ctype = DECL_FRIEND_CONTEXT (decl1); @@ -17413,15 +17444,13 @@ start_preparsed_function (tree decl1, tree attrs, int flags) /* Sometimes we don't notice that a function is a static member, and build a METHOD_TYPE for it. Fix that up now. */ - gcc_assert (!(ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1) + gcc_assert (!(DECL_STATIC_FUNCTION_P (decl1) && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)); /* Set up current_class_type, and enter the scope of the class, if appropriate. */ if (ctype) push_nested_class (ctype); - else if (DECL_STATIC_FUNCTION_P (decl1)) - push_nested_class (DECL_CONTEXT (decl1)); /* Now that we have entered the scope of the class, we must restore the bindings for any template parameters surrounding DECL1, if it @@ -17458,7 +17487,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) tree newdecl1 = push_template_decl (decl1, doing_friend); if (newdecl1 == error_mark_node) { - if (ctype || DECL_STATIC_FUNCTION_P (decl1)) + if (ctype) pop_nested_class (); return false; } @@ -17610,7 +17639,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) /* Start the statement-tree, start the tree now. */ DECL_SAVED_TREE (decl1) = push_stmt_list (); - if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1)) + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1)) { /* We know that this was set up by `grokclassfn'. We do not wait until `store_parm_decls', since evil parse errors may diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index a359bc6..34d0190 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -1619,7 +1619,7 @@ compare_lambda_sig (tree fn_a, tree fn_b) { if (!args_a || !args_b) return false; - // This check also deals with differing varadicness + // This check also deals with differing variadicness if (!same_type_p (TREE_VALUE (args_a), TREE_VALUE (args_b))) return false; } diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index afa68da..5137305 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1744,7 +1744,7 @@ write_closure_template_head (tree tmpl) continue; parm = TREE_VALUE (parm); - if (DECL_VIRTUAL_P (parm)) + if (DECL_IMPLICIT_TEMPLATE_PARM_P (parm)) // A synthetic parm, we're done. break; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 4f5b6e2..33fcf39 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -10418,13 +10418,16 @@ trees_out::get_merge_kind (tree decl, depset *dep) case RECORD_TYPE: case UNION_TYPE: + case NAMESPACE_DECL: if (DECL_NAME (decl) == as_base_identifier) - mk = MK_as_base; - else if (IDENTIFIER_ANON_P (DECL_NAME (decl))) - mk = MK_field; - break; + { + mk = MK_as_base; + break; + } - case NAMESPACE_DECL: + /* A lambda may have a class as its context, even though it + isn't a member in the traditional sense; see the test + g++.dg/modules/lambda-6_a.C. */ if (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl)) && LAMBDA_TYPE_P (TREE_TYPE (decl))) if (tree scope @@ -10437,6 +10440,13 @@ trees_out::get_merge_kind (tree decl, depset *dep) break; } + if (RECORD_OR_UNION_TYPE_P (ctx)) + { + if (IDENTIFIER_ANON_P (DECL_NAME (decl))) + mk = MK_field; + break; + } + if (TREE_CODE (decl) == TEMPLATE_DECL && DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)) mk = MK_local_friend; @@ -18893,18 +18903,16 @@ maybe_key_decl (tree ctx, tree decl) if (TREE_CODE (ctx) != VAR_DECL) return; - gcc_checking_assert (DECL_NAMESPACE_SCOPE_P (ctx)); - - if (!keyed_table) + if (!keyed_table) keyed_table = new keyed_map_t (EXPERIMENT (1, 400)); - auto &vec = keyed_table->get_or_insert (ctx); - if (!vec.length ()) - { - retrofit_lang_decl (ctx); - DECL_MODULE_KEYED_DECLS_P (ctx) = true; - } - vec.safe_push (decl); + auto &vec = keyed_table->get_or_insert (ctx); + if (!vec.length ()) + { + retrofit_lang_decl (ctx); + DECL_MODULE_KEYED_DECLS_P (ctx) = true; + } + vec.safe_push (decl); } /* Create the flat name string. It is simplest to have it handy. */ diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 50aeb77..d19ea5d 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -4802,6 +4802,49 @@ pushdecl_outermost_localscope (tree x) return b ? do_pushdecl_with_scope (x, b) : error_mark_node; } +/* Checks if BINDING is a binding that we can export. */ + +static bool +check_can_export_using_decl (tree binding) +{ + tree decl = STRIP_TEMPLATE (binding); + + /* Linkage is determined by the owner of an enumerator. */ + if (TREE_CODE (decl) == CONST_DECL) + decl = TYPE_NAME (DECL_CONTEXT (decl)); + + /* If the using decl is exported, the things it refers + to must also be exported (or not have module attachment). */ + if (!DECL_MODULE_EXPORT_P (decl) + && (DECL_LANG_SPECIFIC (decl) + && DECL_MODULE_ATTACH_P (decl))) + { + bool internal_p = !TREE_PUBLIC (decl); + + /* A template in an anonymous namespace doesn't constrain TREE_PUBLIC + until it's instantiated, so double-check its context. */ + if (!internal_p && TREE_CODE (binding) == TEMPLATE_DECL) + internal_p = decl_internal_context_p (decl); + + auto_diagnostic_group d; + error ("exporting %q#D that does not have external linkage", + binding); + if (TREE_CODE (decl) == TYPE_DECL && !DECL_IMPLICIT_TYPEDEF_P (decl)) + /* An un-exported explicit type alias has no linkage. */ + inform (DECL_SOURCE_LOCATION (binding), + "%q#D declared here with no linkage", binding); + else if (internal_p) + inform (DECL_SOURCE_LOCATION (binding), + "%q#D declared here with internal linkage", binding); + else + inform (DECL_SOURCE_LOCATION (binding), + "%q#D declared here with module linkage", binding); + return false; + } + + return true; +} + /* Process a local-scope or namespace-scope using declaration. LOOKUP is the result of qualified lookup (both value & type are significant). FN_SCOPE_P indicates if we're at function-scope (as @@ -4845,23 +4888,7 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p, tree new_fn = *usings; bool exporting = revealing_p && module_exporting_p (); if (exporting) - { - /* Module flags for templates are on the template_result. */ - tree decl = STRIP_TEMPLATE (new_fn); - - /* If the using decl is exported, the things it refers - to must also be exported (or not have module attachment). */ - if (!DECL_MODULE_EXPORT_P (decl) - && (DECL_LANG_SPECIFIC (decl) - && DECL_MODULE_ATTACH_P (decl))) - { - auto_diagnostic_group d; - error ("%q#D does not have external linkage", new_fn); - inform (DECL_SOURCE_LOCATION (new_fn), - "%q#D declared here", new_fn); - exporting = false; - } - } + exporting = check_can_export_using_decl (new_fn); /* [namespace.udecl] @@ -4939,20 +4966,26 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p, failed = true; } else if (insert_p) - // FIXME:what if we're newly exporting lookup.value - value = lookup.value; + { + value = lookup.value; + if (revealing_p && module_exporting_p ()) + check_can_export_using_decl (value); + } /* Now the type binding. */ if (lookup.type && lookup.type != type) { - // FIXME: What if we're exporting lookup.type? if (type && !decls_match (lookup.type, type)) { diagnose_name_conflict (lookup.type, type); failed = true; } else if (insert_p) - type = lookup.type; + { + type = lookup.type; + if (revealing_p && module_exporting_p ()) + check_can_export_using_decl (type); + } } if (insert_p) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index d110433..2464d1a 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -16616,6 +16616,7 @@ cp_parser_linkage_specification (cp_parser* parser, tree prefix_attr) static_assert-declaration: static_assert ( constant-expression , string-literal ) ; static_assert ( constant-expression ) ; (C++17) + static_assert ( constant-expression, conditional-expression ) ; (C++26) If MEMBER_P, this static_assert is a class member. */ @@ -16646,10 +16647,10 @@ cp_parser_static_assert (cp_parser *parser, bool member_p) /* Parse the constant-expression. Allow a non-constant expression here in order to give better diagnostics in finish_static_assert. */ - condition = - cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/true, - /*non_constant_p=*/nullptr); + condition + = cp_parser_constant_expression (parser, + /*allow_non_constant_p=*/true, + /*non_constant_p=*/nullptr); if (cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN) { @@ -16668,8 +16669,32 @@ cp_parser_static_assert (cp_parser *parser, bool member_p) /* Parse the separating `,'. */ cp_parser_require (parser, CPP_COMMA, RT_COMMA); - /* Parse the string-literal message. */ - if (cxx_dialect >= cxx26) + /* Parse the message expression. */ + bool string_lit = true; + for (unsigned int i = 1; ; ++i) + { + cp_token *tok = cp_lexer_peek_nth_token (parser->lexer, i); + if (cp_parser_is_pure_string_literal (tok)) + continue; + else if (tok->type == CPP_CLOSE_PAREN) + break; + string_lit = false; + break; + } + if (!string_lit) + { + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + if (cxx_dialect < cxx26) + pedwarn (loc, OPT_Wc__26_extensions, + "%<static_assert%> with non-string message only " + "available with %<-std=c++2c%> or %<-std=gnu++2c%>"); + + message = cp_parser_conditional_expression (parser); + if (TREE_CODE (message) == STRING_CST) + message = build1_loc (loc, PAREN_EXPR, TREE_TYPE (message), + message); + } + else if (cxx_dialect >= cxx26) message = cp_parser_unevaluated_string_literal (parser); else message = cp_parser_string_literal (parser, /*translate=*/false, @@ -41136,7 +41161,7 @@ cp_parser_omp_clause_dist_schedule (cp_parser *parser, tree list, /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE, "dist_schedule", location); */ if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE)) - warning_at (location, 0, "too many %qs clauses", "dist_schedule"); + warning_at (location, OPT_Wopenmp, "too many %qs clauses", "dist_schedule"); OMP_CLAUSE_CHAIN (c) = list; return c; @@ -43148,6 +43173,9 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p) destroy update (dependence-type) + OpenMP 5.2 additionally: + destroy ( depobj ) + dependence-type: in out @@ -43194,7 +43222,27 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok) clause = error_mark_node; } else if (!strcmp ("destroy", p)) - kind = OMP_CLAUSE_DEPEND_LAST; + { + kind = OMP_CLAUSE_DEPEND_LAST; + matching_parens c_parens; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) + && c_parens.require_open (parser)) + { + tree destobj = cp_parser_assignment_expression (parser); + if (depobj != error_mark_node + && destobj != error_mark_node + && !operand_equal_p (destobj, depobj, OEP_MATCH_SIDE_EFFECTS + | OEP_LEXICOGRAPHIC)) + warning_at (EXPR_LOC_OR_LOC (destobj, c_loc), OPT_Wopenmp, + "the %<destroy%> expression %qE should be the same " + "as the %<depobj%> argument %qE", destobj, depobj); + if (!c_parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + } + } else if (!strcmp ("update", p)) { matching_parens c_parens; @@ -44058,8 +44106,9 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); else { - warning_at (tok->location, 0, "%<#pragma omp scan%> with zero preceding " - "executable statements"); + warning_at (tok->location, OPT_Wopenmp, + "%<#pragma omp scan%> with zero preceding executable " + "statements"); substmt = build_empty_stmt (tok->location); } substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); @@ -44105,8 +44154,9 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) else { if (found_scan) - warning_at (tok->location, 0, "%<#pragma omp scan%> with zero " - "succeeding executable statements"); + warning_at (tok->location, OPT_Wopenmp, + "%<#pragma omp scan%> with zero succeeding executable " + "statements"); substmt = build_empty_stmt (tok->location); } substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, @@ -47803,7 +47853,7 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok, } else if (startswith (p, "ext_")) { - warning_at (cloc, 0, "unknown assumption clause %qs", p); + warning_at (cloc, OPT_Wopenmp, "unknown assumption clause %qs", p); cp_lexer_consume_token (parser->lexer); if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; @@ -50895,7 +50945,7 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr) Note that DECL_ARTIFICIAL is used elsewhere for template parameters. */ if (TREE_VALUE (new_parm) != error_mark_node) - DECL_VIRTUAL_P (TREE_VALUE (new_parm)) = true; + DECL_IMPLICIT_TEMPLATE_PARM_P (TREE_VALUE (new_parm)) = true; tree new_decl = get_local_decls (); if (non_type) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 324f6f0..092e6fd 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -3274,53 +3274,40 @@ check_explicit_specialization (tree declarator, int comp_template_parms (const_tree parms1, const_tree parms2) { - const_tree p1; - const_tree p2; - if (parms1 == parms2) return 1; - for (p1 = parms1, p2 = parms2; - p1 != NULL_TREE && p2 != NULL_TREE; - p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2)) - { - tree t1 = TREE_VALUE (p1); - tree t2 = TREE_VALUE (p2); - int i; + tree t1 = TREE_VALUE (parms1); + tree t2 = TREE_VALUE (parms2); + int i; - gcc_assert (TREE_CODE (t1) == TREE_VEC); - gcc_assert (TREE_CODE (t2) == TREE_VEC); + gcc_assert (TREE_CODE (t1) == TREE_VEC); + gcc_assert (TREE_CODE (t2) == TREE_VEC); - if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) - return 0; + if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) + return 0; - for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) - { - tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); - tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); + for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) + { + tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); + tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); - /* If either of the template parameters are invalid, assume - they match for the sake of error recovery. */ - if (error_operand_p (parm1) || error_operand_p (parm2)) - return 1; + /* If either of the template parameters are invalid, assume + they match for the sake of error recovery. */ + if (error_operand_p (parm1) || error_operand_p (parm2)) + return 1; - if (TREE_CODE (parm1) != TREE_CODE (parm2)) - return 0; + if (TREE_CODE (parm1) != TREE_CODE (parm2)) + return 0; - if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM - && (TEMPLATE_TYPE_PARAMETER_PACK (parm1) - == TEMPLATE_TYPE_PARAMETER_PACK (parm2))) - continue; - else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2))) - return 0; - } + if (TREE_CODE (parm1) == TYPE_DECL + && (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm1)) + == TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm2)))) + continue; + else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2))) + return 0; } - if ((p1 != NULL_TREE) != (p2 != NULL_TREE)) - /* One set of parameters has more parameters lists than the - other. */ - return 0; - return 1; } @@ -3359,7 +3346,8 @@ template_parameters_equivalent_p (const_tree parm1, const_tree parm2) /* ... one parameter was introduced by a parameter declaration, then both are. This case arises as a result of eagerly rewriting declarations during parsing. */ - if (DECL_VIRTUAL_P (decl1) != DECL_VIRTUAL_P (decl2)) + if (DECL_IMPLICIT_TEMPLATE_PARM_P (decl1) + != DECL_IMPLICIT_TEMPLATE_PARM_P (decl2)) return false; /* ... if either declares a pack, they both do. */ @@ -3402,31 +3390,20 @@ template_parameter_lists_equivalent_p (const_tree parms1, const_tree parms2) if (parms1 == parms2) return true; - const_tree p1 = parms1; - const_tree p2 = parms2; - while (p1 != NULL_TREE && p2 != NULL_TREE) - { - tree list1 = TREE_VALUE (p1); - tree list2 = TREE_VALUE (p2); - - if (TREE_VEC_LENGTH (list1) != TREE_VEC_LENGTH (list2)) - return 0; + tree list1 = TREE_VALUE (parms1); + tree list2 = TREE_VALUE (parms2); - for (int i = 0; i < TREE_VEC_LENGTH (list2); ++i) - { - tree parm1 = TREE_VEC_ELT (list1, i); - tree parm2 = TREE_VEC_ELT (list2, i); - if (!template_parameters_equivalent_p (parm1, parm2)) - return false; - } + if (TREE_VEC_LENGTH (list1) != TREE_VEC_LENGTH (list2)) + return 0; - p1 = TREE_CHAIN (p1); - p2 = TREE_CHAIN (p2); + for (int i = 0; i < TREE_VEC_LENGTH (list2); ++i) + { + tree parm1 = TREE_VEC_ELT (list1, i); + tree parm2 = TREE_VEC_ELT (list2, i); + if (!template_parameters_equivalent_p (parm1, parm2)) + return false; } - if ((p1 != NULL_TREE) != (p2 != NULL_TREE)) - return false; - return true; } @@ -13999,6 +13976,7 @@ tsubst_aggr_type (tree t, if (entering_scope && CLASS_TYPE_P (t) && dependent_type_p (t) + && TYPE_TEMPLATE_INFO (t) && TYPE_CANONICAL (t) == TREE_TYPE (TYPE_TI_TEMPLATE (t))) t = TYPE_CANONICAL (t); @@ -18724,15 +18702,20 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl) case STATIC_ASSERT: { - tree condition; + tree condition, message; ++c_inhibit_evaluation_warnings; condition = tsubst_expr (STATIC_ASSERT_CONDITION (t), args, complain, in_decl); + message = tsubst_expr (STATIC_ASSERT_MESSAGE (t), args, + complain, in_decl); + if (TREE_CODE (STATIC_ASSERT_MESSAGE (t)) != STRING_CST + && TREE_CODE (message) == STRING_CST) + message = build1_loc (STATIC_ASSERT_SOURCE_LOCATION (t), + PAREN_EXPR, TREE_TYPE (message), message); --c_inhibit_evaluation_warnings; - finish_static_assert (condition, - STATIC_ASSERT_MESSAGE (t), + finish_static_assert (condition, message, STATIC_ASSERT_SOURCE_LOCATION (t), /*member_p=*/false, /*show_expr_p=*/true); } diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8090c71..3bf5864 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -7561,7 +7561,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) "positive"); break; default: - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), + (flag_openmp || flag_openmp_simd) + ? OPT_Wopenmp : 0, "%qs value must be positive", omp_clause_code_name [OMP_CLAUSE_CODE (c)]); @@ -7596,7 +7598,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) != 1) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%qs value must be positive", omp_clause_code_name [OMP_CLAUSE_CODE (c)]); @@ -7610,7 +7612,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) && TREE_CODE (upper) == INTEGER_CST && tree_int_cst_lt (upper, t)) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%<num_teams%> lower bound %qE bigger " "than upper bound %qE", t, upper); t = NULL_TREE; @@ -7643,7 +7645,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) != 1) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "chunk size value must be positive"); t = integer_one_node; } @@ -7739,7 +7741,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) != 1) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%<thread_limit%> value must be positive"); t = integer_one_node; } @@ -7935,7 +7937,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%qD appears more than once in %<allocate%> clauses", t); remove = true; @@ -8707,7 +8709,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) != 1) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%<grainsize%> value must be positive"); t = integer_one_node; } @@ -8737,7 +8739,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) == -1) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, "%<priority%> value must be non-negative"); t = integer_one_node; } @@ -11434,6 +11436,7 @@ finish_static_assert (tree condition, tree message, location_t location, bool member_p, bool show_expr_p) { tsubst_flags_t complain = tf_warning_or_error; + tree message_sz = NULL_TREE, message_data = NULL_TREE; if (message == NULL_TREE || message == error_mark_node @@ -11441,13 +11444,61 @@ finish_static_assert (tree condition, tree message, location_t location, || condition == error_mark_node) return; - if (check_for_bare_parameter_packs (condition)) - condition = error_mark_node; + if (check_for_bare_parameter_packs (condition) + || check_for_bare_parameter_packs (message)) + return; + + if (TREE_CODE (message) != STRING_CST + && !type_dependent_expression_p (message)) + { + message_sz + = finish_class_member_access_expr (message, + get_identifier ("size"), + false, complain); + if (message_sz != error_mark_node) + message_data + = finish_class_member_access_expr (message, + get_identifier ("data"), + false, complain); + if (message_sz == error_mark_node || message_data == error_mark_node) + { + error_at (location, "%<static_assert%> message must be a string " + "literal or object with %<size%> and " + "%<data%> members"); + return; + } + releasing_vec size_args, data_args; + message_sz = finish_call_expr (message_sz, &size_args, false, false, + complain); + message_data = finish_call_expr (message_data, &data_args, false, false, + complain); + if (message_sz == error_mark_node || message_data == error_mark_node) + return; + message_sz = build_converted_constant_expr (size_type_node, message_sz, + complain); + if (message_sz == error_mark_node) + { + error_at (location, "%<static_assert%> message %<size()%> " + "must be implicitly convertible to " + "%<std::size_t%>"); + return; + } + message_data = build_converted_constant_expr (const_string_type_node, + message_data, complain); + if (message_data == error_mark_node) + { + error_at (location, "%<static_assert%> message %<data()%> " + "must be implicitly convertible to " + "%<const char*%>"); + return; + } + } /* Save the condition in case it was a concept check. */ tree orig_condition = condition; - if (instantiation_dependent_expression_p (condition)) + if (instantiation_dependent_expression_p (condition) + || instantiation_dependent_expression_p (message)) { /* We're in a template; build a STATIC_ASSERT and put it in the right place. */ @@ -11485,9 +11536,89 @@ finish_static_assert (tree condition, tree message, location_t location, if (processing_template_decl) goto defer; - int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT - (TREE_TYPE (TREE_TYPE (message)))); - int len = TREE_STRING_LENGTH (message) / sz - 1; + int len; + const char *msg = NULL; + char *buf = NULL; + if (message_sz && message_data) + { + tree msz = cxx_constant_value (message_sz, NULL_TREE, complain); + if (!tree_fits_uhwi_p (msz)) + { + error_at (location, + "%<static_assert%> message %<size()%> " + "must be a constant expression"); + return; + } + else if ((unsigned HOST_WIDE_INT) (int) tree_to_uhwi (msz) + != tree_to_uhwi (msz)) + { + error_at (location, + "%<static_assert%> message %<size()%> " + "%qE too large", msz); + return; + } + len = tree_to_uhwi (msz); + tree data = maybe_constant_value (message_data, NULL_TREE, + mce_true); + if (!reduced_constant_expression_p (data)) + data = NULL_TREE; + if (len) + { + if (data) + msg = c_getstr (data); + if (msg == NULL) + buf = XNEWVEC (char, len); + for (int i = 0; i < len; ++i) + { + tree t = message_data; + if (i) + t = build2 (POINTER_PLUS_EXPR, + TREE_TYPE (message_data), message_data, + size_int (i)); + t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); + tree t2 = cxx_constant_value (t, NULL_TREE, complain); + if (!tree_fits_shwi_p (t2)) + { + error_at (location, + "%<static_assert%> message %<data()[%d]%> " + "must be a constant expression", i); + return; + } + if (msg == NULL) + buf[i] = tree_to_shwi (t2); + /* If c_getstr worked, just verify the first and + last characters using constant evaluation. */ + else if (len > 2 && i == 0) + i = len - 2; + } + if (msg == NULL) + msg = buf; + } + else if (!data) + { + /* We don't have any function to test whether some + expression is a core constant expression. So, instead + test whether (message.data (), 0) is a constant + expression. */ + data = build2 (COMPOUND_EXPR, integer_type_node, + message_data, integer_zero_node); + tree t = cxx_constant_value (data, NULL_TREE, complain); + if (!integer_zerop (t)) + { + error_at (location, + "%<static_assert%> message %<data()%> " + "must be a core constant expression"); + return; + } + } + } + else + { + tree eltype = TREE_TYPE (TREE_TYPE (message)); + int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (eltype)); + msg = TREE_STRING_POINTER (message); + len = TREE_STRING_LENGTH (message) / sz - 1; + } /* See if we can find which clause was failing (for logical AND). */ tree bad = find_failing_clause (NULL, orig_condition); @@ -11497,12 +11628,13 @@ finish_static_assert (tree condition, tree message, location_t location, auto_diagnostic_group d; - /* Report the error. */ + /* Report the error. */ if (len == 0) error_at (cloc, "static assertion failed"); else - error_at (cloc, "static assertion failed: %s", - TREE_STRING_POINTER (message)); + error_at (cloc, "static assertion failed: %.*s", len, msg); + + XDELETEVEC (buf); diagnose_failing_condition (bad, cloc, show_expr_p); } diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index cef86f2..2454da4 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,17 @@ +2023-11-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * dmd/MERGE: Merge upstream dmd ff57fec515. + * dmd/VERSION: Bump version to v2.106.0-rc.1. + * expr.cc (ExprVisitor::visit (CatAssignExp *)): Update for new + front-end interface. + (ExprVisitor::visit (NewExp *)): Likewise. + * runtime.def (NEWARRAYMTX): Remove. + (NEWARRAYMITX): Remove. + +2023-11-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * dmd/MERGE: Merge upstream dmd 65a3da148c. + 2023-11-02 Iain Buclaw <ibuclaw@gdcproject.org> * dmd/MERGE: Merge upstream dmd 643b1261bb. diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 235db4b..aa0062c 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -643b1261bba0757d97efa3ff1f63e461271eb000 +ff57fec51558013b25cadb7e83da9f4675915d56 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/VERSION b/gcc/d/dmd/VERSION index b272d4b..41fdc65 100644 --- a/gcc/d/dmd/VERSION +++ b/gcc/d/dmd/VERSION @@ -1 +1 @@ -v2.106.0-beta.1 +v2.106.0-rc.1 diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d index d42ef95..307bb01 100644 --- a/gcc/d/dmd/aggregate.d +++ b/gcc/d/dmd/aggregate.d @@ -663,7 +663,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol */ extern (D) final Dsymbol searchCtor() { - auto s = search(Loc.initial, Id.ctor); + auto s = this.search(Loc.initial, Id.ctor); if (s) { if (!(s.isCtorDeclaration() || diff --git a/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h index 58a0126..cd8f1a1 100644 --- a/gcc/d/dmd/aggregate.h +++ b/gcc/d/dmd/aggregate.h @@ -167,7 +167,6 @@ private: public: static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; const char *kind() const override; void finalizeSize() override final; bool isPOD(); @@ -285,7 +284,6 @@ public: virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; void finalizeSize() override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration *fd); diff --git a/gcc/d/dmd/arrayop.d b/gcc/d/dmd/arrayop.d index 25bbb3f..c3b8526 100644 --- a/gcc/d/dmd/arrayop.d +++ b/gcc/d/dmd/arrayop.d @@ -172,7 +172,7 @@ Expression arrayOp(BinAssignExp e, Scope* sc) } if (e.e1.op == EXP.arrayLiteral) { - return e.e1.modifiableLvalue(sc, e.e1); + return e.e1.modifiableLvalue(sc); } return arrayOp(e.isBinExp(), sc); diff --git a/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d index 77f36f3..6a9c010 100644 --- a/gcc/d/dmd/astenums.d +++ b/gcc/d/dmd/astenums.d @@ -383,6 +383,7 @@ enum STMT : ubyte enum InitKind : ubyte { void_, + default_, error, struct_, array, diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index 49fc308..251e2e8 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -32,7 +32,7 @@ import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic; +import dmd.dsymbolsem; import dmd.errors; import dmd.expression; import dmd.expressionsem; @@ -123,18 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return sc; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - Dsymbols* d = include(sc); - if (d) - { - Scope* sc2 = newScope(sc); - d.foreachDsymbol( s => s.addMember(sc2, sds) ); - if (sc2 != sc) - sc2.pop(); - } - } - override void setScope(Scope* sc) { Dsymbols* d = include(sc); @@ -295,34 +283,6 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration return t; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - Dsymbols* d = include(sc); - if (d) - { - Scope* sc2 = newScope(sc); - - d.foreachDsymbol( (s) - { - //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars()); - // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol) - if (auto decl = s.isDeclaration()) - { - decl.storage_class |= stc & STC.local; - if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case? - { - sdecl.stc |= stc & STC.local; - } - } - s.addMember(sc2, sds); - }); - - if (sc2 != sc) - sc2.pop(); - } - - } - override inout(StorageClassDeclaration) isStorageClassDeclaration() inout { return this; @@ -640,37 +600,6 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.visibility, 1, sc.aligndecl, sc.inlining); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - if (pkg_identifiers) - { - Dsymbol tmp; - Package.resolve(pkg_identifiers, &tmp, null); - visibility.pkg = tmp ? tmp.isPackage() : null; - pkg_identifiers = null; - } - if (visibility.kind == Visibility.Kind.package_ && visibility.pkg && sc._module) - { - Module m = sc._module; - - // https://issues.dlang.org/show_bug.cgi?id=17441 - // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if - // each package's .isModule() properites are equal. - // - // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null. - // This breaks package declarations of the package in question if they are declared in - // the same package.d file, which _do_ have a module associated with them, and hence a non-null - // isModule() - if (!m.isPackage() || !visibility.pkg.ident.equals(m.isPackage().ident)) - { - Package pkg = m.parent ? m.parent.isPackage() : null; - if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg)) - .error(loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", kind(), toPrettyChars(false), m.toPrettyChars(true)); - } - } - return AttribDeclaration.addMember(sc, sds); - } - override const(char)* kind() const { return "visibility attribute"; @@ -1054,23 +983,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("StaticIfDeclaration::addMember() '%s'\n", toChars()); - /* This is deferred until the condition evaluated later (by the include() call), - * so that expressions in the condition can refer to declarations - * in the same scope, such as: - * - * template Foo(int i) - * { - * const int j = i + 1; - * static if (j == 3) - * const int k; - * } - */ - this.scopesym = sds; - } - override void setScope(Scope* sc) { // do not evaluate condition before semantic pass @@ -1186,12 +1098,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration return d; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - // used only for caching the enclosing symbol - this.scopesym = sds; - } - override void addComment(const(char)* comment) { // do nothing @@ -1266,15 +1172,6 @@ extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration return sc.push(sym); } - /*************************************** - * Lazily initializes the scope to forward to. - */ - override void addMember(Scope* sc, ScopeDsymbol sds) - { - sym.parent = sds; - return super.addMember(sc, sym); - } - override inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout { return this; @@ -1312,12 +1209,6 @@ extern (C++) final class MixinDeclaration : AttribDeclaration return new MixinDeclaration(loc, Expression.arraySyntaxCopy(exps)); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, memnum); - this.scopesym = sds; - } - override void setScope(Scope* sc) { Dsymbol.setScope(sc); diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index f47a1f6..efea9af 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -26,7 +26,6 @@ public: virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; void addComment(const utf8_t *comment) override; @@ -49,7 +48,6 @@ public: StorageClassDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override final; - void addMember(Scope *sc, ScopeDsymbol *sds) override; StorageClassDeclaration *isStorageClassDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -110,7 +108,6 @@ public: VisibilityDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; const char *toPrettyChars(bool unused) override; VisibilityDeclaration *isVisibilityDeclaration() override { return this; } @@ -179,7 +176,6 @@ public: StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbols *include(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; StaticIfDeclaration *isStaticIfDeclaration() override { return this; } @@ -199,7 +195,6 @@ public: StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void addComment(const utf8_t *comment) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; @@ -213,7 +208,6 @@ public: ForwardingScopeDsymbol *sym; Scope *newScope(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; ForwardingAttribDeclaration *isForwardingAttribDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } }; @@ -229,7 +223,6 @@ public: d_bool compiled; MixinDeclaration *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/canthrow.d b/gcc/d/dmd/canthrow.d index 8aece3b..6730592 100644 --- a/gcc/d/dmd/canthrow.d +++ b/gcc/d/dmd/canthrow.d @@ -22,6 +22,7 @@ import dmd.declaration; import dmd.dsymbol; import dmd.errorsink; import dmd.expression; +import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.init; @@ -80,7 +81,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink) if (!f.isDtorDeclaration()) errorSupplementalInferredAttr(f, 10, false, STC.nothrow_); - e.checkOverriddenDtor(null, f, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); + f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); } else if (func) { diff --git a/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d index b8ad785..4e7a82f 100644 --- a/gcc/d/dmd/common/outbuffer.d +++ b/gcc/d/dmd/common/outbuffer.d @@ -281,7 +281,7 @@ struct OutBuffer write(&v, v.sizeof); } - /// NOT zero-terminated + /// Buffer will NOT be zero-terminated extern (C++) void writestring(const(char)* s) pure nothrow @system { if (!s) @@ -302,14 +302,14 @@ struct OutBuffer write(s); } - /// NOT zero-terminated, followed by newline + /// Buffer will NOT be zero-terminated, followed by newline void writestringln(const(char)[] s) pure nothrow @safe { writestring(s); writenl(); } - /** Write string to buffer, ensure it is zero terminated + /** Write C string AND null byte */ void writeStringz(const(char)* s) pure nothrow @system { diff --git a/gcc/d/dmd/compiler.d b/gcc/d/dmd/compiler.d index e85cc20..8b8a453 100644 --- a/gcc/d/dmd/compiler.d +++ b/gcc/d/dmd/compiler.d @@ -12,6 +12,7 @@ module dmd.compiler; import dmd.arraytypes; +import dmd.ctfeexpr; import dmd.dmodule; import dmd.expression; import dmd.mtype; diff --git a/gcc/d/dmd/cond.d b/gcc/d/dmd/cond.d index a8d0994..568b639 100644 --- a/gcc/d/dmd/cond.d +++ b/gcc/d/dmd/cond.d @@ -29,6 +29,7 @@ import dmd.globals; import dmd.identifier; import dmd.location; import dmd.mtype; +import dmd.optimize; import dmd.typesem; import dmd.common.outbuffer; import dmd.rootobject; diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index b8e8052..ed5f1f8 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -2023,6 +2023,9 @@ final class CParser(AST) : Parser!AST } symbols.push(s); } + if (level == LVL.global && !id) + error("expected identifier for declaration"); + first = false; switch (token.value) @@ -2165,6 +2168,7 @@ final class CParser(AST) : Parser!AST * C11 Initialization * initializer: * assignment-expression + * { } // C23 6.7.10 addition * { initializer-list } * { initializer-list , } * @@ -2195,6 +2199,12 @@ final class CParser(AST) : Parser!AST nextToken(); const loc = token.loc; + if (token.value == TOK.rightCurly) // { } + { + nextToken(); + return new AST.DefaultInitializer(loc); + } + /* Collect one or more `designation (opt) initializer` * into ci.initializerList, but lazily create ci */ @@ -2736,7 +2746,7 @@ final class CParser(AST) : Parser!AST private AST.Type cparseDeclarator(DTR declarator, AST.Type tbase, out Identifier pident, ref Specifier specifier) { - //printf("cparseDeclarator(%d, %p)\n", declarator, t); + //printf("cparseDeclarator(%d, %s)\n", declarator, tbase.toChars()); AST.Types constTypes; // all the Types that will need `const` applied to them /* Insert tx -> t into @@ -2755,6 +2765,7 @@ final class CParser(AST) : Parser!AST AST.Type parseDecl(AST.Type t) { + //printf("parseDecl() t: %s\n", t.toChars()); AST.Type ts; while (1) { @@ -2770,9 +2781,18 @@ final class CParser(AST) : Parser!AST break; case TOK.leftParenthesis: // ( declarator ) + //printf("leftParen\n"); /* like: T (*fp)(); * T ((*fp))(); */ + auto tk = &token; + if (!isCDeclarator(tk, declarator)) + { + /* Not ( declarator ), might be parameter-list + */ + ts = t; + break; + } nextToken(); if (token.value == TOK.__stdcall) // T (__stdcall*fp)(); @@ -2786,6 +2806,7 @@ final class CParser(AST) : Parser!AST break; case TOK.mul: // pointer + //printf("star\n"); t = new AST.TypePointer(t); nextToken(); // add post fixes const/volatile/restrict/_Atomic @@ -2797,6 +2818,7 @@ final class CParser(AST) : Parser!AST continue; default: + //printf("default %s\n", token.toChars()); if (declarator == DTR.xdirect) { if (!t || t.isTypeIdentifier()) @@ -2914,7 +2936,7 @@ final class CParser(AST) : Parser!AST if (specifier._pure) stc |= STC.pure_; AST.Type tf = new AST.TypeFunction(parameterList, t, lkg, stc); - // tf = tf.addSTC(storageClass); // TODO + //tf = tf.addSTC(storageClass); // TODO insertTx(ts, tf, t); // ts -> ... -> tf -> t if (ts != tf) @@ -2927,6 +2949,8 @@ final class CParser(AST) : Parser!AST } break; } + if (declarator == DTR.xdirect && !pident) + error("expected identifier for declarator"); return ts; } @@ -4556,6 +4580,7 @@ final class CParser(AST) : Parser!AST */ private bool isCDeclarator(ref Token* pt, DTR declarator) { + //printf("isCDeclarator()\n"); auto t = pt; while (1) { @@ -4578,6 +4603,8 @@ final class CParser(AST) : Parser!AST else if (t.value == TOK.leftParenthesis) { t = peek(t); + if (t.value == TOK.__stdcall) + t = peek(t); if (!isCDeclarator(t, declarator)) return false; if (t.value != TOK.rightParenthesis) diff --git a/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d index ddfb57d..43efc05 100644 --- a/gcc/d/dmd/ctfeexpr.d +++ b/gcc/d/dmd/ctfeexpr.d @@ -28,6 +28,7 @@ import dmd.func; import dmd.globals; import dmd.location; import dmd.mtype; +import dmd.root.bitarray; import dmd.root.complex; import dmd.root.ctfloat; import dmd.root.port; @@ -35,75 +36,98 @@ import dmd.root.rmem; import dmd.tokens; import dmd.visitor; - -/*********************************************************** - * A reference to a class, or an interface. We need this when we - * point to a base class (we must record what the type is). +/****************************************************************/ +/* A type meant as a union of all the Expression types, + * to serve essentially as a Variant that will sit on the stack + * during CTFE to reduce memory consumption. */ -extern (C++) final class ClassReferenceExp : Expression +extern (D) struct UnionExp { - StructLiteralExp value; - - extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe + // yes, default constructor does nothing + extern (D) this(Expression e) nothrow { - super(loc, EXP.classReference); - assert(lit && lit.sd && lit.sd.isClassDeclaration()); - this.value = lit; - this.type = type; + memcpy(&this, cast(void*)e, e.size); } - ClassDeclaration originalClass() + /* Extract pointer to Expression + */ + extern (D) Expression exp() return nothrow { - return value.sd.isClassDeclaration(); + return cast(Expression)&u; } - // Return index of the field, or -1 if not found - private int getFieldIndex(Type fieldtype, uint fieldoffset) + /* Convert to an allocated Expression + */ + extern (D) Expression copy() { - ClassDeclaration cd = originalClass(); - uint fieldsSoFar = 0; - for (size_t j = 0; j < value.elements.length; j++) + Expression e = exp(); + //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr); + assert(e.size <= u.sizeof); + switch (e.op) { - while (j - fieldsSoFar >= cd.fields.length) - { - fieldsSoFar += cd.fields.length; - cd = cd.baseClass; - } - VarDeclaration v2 = cd.fields[j - fieldsSoFar]; - if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size()) - { - return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar)); - } + case EXP.cantExpression: return CTFEExp.cantexp; + case EXP.voidExpression: return CTFEExp.voidexp; + case EXP.break_: return CTFEExp.breakexp; + case EXP.continue_: return CTFEExp.continueexp; + case EXP.goto_: return CTFEExp.gotoexp; + default: return e.copy(); } - return -1; } - // Return index of the field, or -1 if not found - // Same as getFieldIndex, but checks for a direct match with the VarDeclaration - int findFieldIndexByName(VarDeclaration v) - { - ClassDeclaration cd = originalClass(); - size_t fieldsSoFar = 0; - for (size_t j = 0; j < value.elements.length; j++) - { - while (j - fieldsSoFar >= cd.fields.length) - { - fieldsSoFar += cd.fields.length; - cd = cd.baseClass; - } - VarDeclaration v2 = cd.fields[j - fieldsSoFar]; - if (v == v2) - { - return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar)); - } - } - return -1; - } +private: + // Ensure that the union is suitably aligned. + align(8) union _AnonStruct_u + { + char[__traits(classInstanceSize, Expression)] exp; + char[__traits(classInstanceSize, IntegerExp)] integerexp; + char[__traits(classInstanceSize, ErrorExp)] errorexp; + char[__traits(classInstanceSize, RealExp)] realexp; + char[__traits(classInstanceSize, ComplexExp)] complexexp; + char[__traits(classInstanceSize, SymOffExp)] symoffexp; + char[__traits(classInstanceSize, StringExp)] stringexp; + char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp; + char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp; + char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp; + char[__traits(classInstanceSize, CompoundLiteralExp)] compoundliteralexp; + char[__traits(classInstanceSize, NullExp)] nullexp; + char[__traits(classInstanceSize, DotVarExp)] dotvarexp; + char[__traits(classInstanceSize, AddrExp)] addrexp; + char[__traits(classInstanceSize, IndexExp)] indexexp; + char[__traits(classInstanceSize, SliceExp)] sliceexp; + char[__traits(classInstanceSize, VectorExp)] vectorexp; + } + + _AnonStruct_u u; +} - override void accept(Visitor v) - { - v.visit(this); - } +void emplaceExp(T : Expression, Args...)(void* p, Args args) +{ + static if (__VERSION__ < 2099) + const init = typeid(T).initializer; + else + const init = __traits(initSymbol, T); + p[0 .. __traits(classInstanceSize, T)] = init[]; + (cast(T)p).__ctor(args); +} + +void emplaceExp(T : UnionExp)(T* p, Expression e) nothrow +{ + memcpy(p, cast(void*)e, e.size); +} + +// Generate an error message when this exception is not caught +void generateUncaughtError(ThrownExceptionExp tee) +{ + UnionExp ue = void; + Expression e = resolveSlice((*tee.thrown.value.elements)[0], &ue); + StringExp se = e.toStringExp(); + error(tee.thrown.loc, "uncaught CTFE exception `%s(%s)`", tee.thrown.type.toChars(), se ? se.toChars() : e.toChars()); + /* Also give the line where the throw statement was. We won't have it + * in the case where the ThrowStatement is generated internally + * (eg, in ScopeStatement) + */ + if (tee.loc.isValid() && !tee.loc.equals(tee.thrown.loc)) + .errorSupplemental(tee.loc, "thrown from here"); } /************************* @@ -111,7 +135,7 @@ extern (C++) final class ClassReferenceExp : Expression * Returns: * index of the field, or -1 if not found */ -int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe +int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe nothrow { foreach (i, field; sd.fields) { @@ -121,102 +145,8 @@ int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pur return -1; } -/*********************************************************** - * Fake class which holds the thrown exception. - * Used for implementing exception handling. - */ -extern (C++) final class ThrownExceptionExp : Expression -{ - ClassReferenceExp thrown; // the thing being tossed - - extern (D) this(const ref Loc loc, ClassReferenceExp victim) @safe - { - super(loc, EXP.thrownException); - this.thrown = victim; - this.type = victim.type; - } - - override const(char)* toChars() const - { - return "CTFE ThrownException"; - } - - // Generate an error message when this exception is not caught - extern (D) void generateUncaughtError() - { - UnionExp ue = void; - Expression e = resolveSlice((*thrown.value.elements)[0], &ue); - StringExp se = e.toStringExp(); - error(thrown.loc, "uncaught CTFE exception `%s(%s)`", thrown.type.toChars(), se ? se.toChars() : e.toChars()); - /* Also give the line where the throw statement was. We won't have it - * in the case where the ThrowStatement is generated internally - * (eg, in ScopeStatement) - */ - if (loc.isValid() && !loc.equals(thrown.loc)) - .errorSupplemental(loc, "thrown from here"); - } - - override void accept(Visitor v) - { - v.visit(this); - } -} - -/*********************************************************** - * This type is only used by the interpreter. - */ -extern (C++) final class CTFEExp : Expression -{ - extern (D) this(EXP tok) - { - super(Loc.initial, tok); - type = Type.tvoid; - } - - override const(char)* toChars() const - { - switch (op) - { - case EXP.cantExpression: - return "<cant>"; - case EXP.voidExpression: - return "cast(void)0"; - case EXP.showCtfeContext: - return "<error>"; - case EXP.break_: - return "<break>"; - case EXP.continue_: - return "<continue>"; - case EXP.goto_: - return "<goto>"; - default: - assert(0); - } - } - - extern (D) __gshared CTFEExp cantexp; - extern (D) __gshared CTFEExp voidexp; - extern (D) __gshared CTFEExp breakexp; - extern (D) __gshared CTFEExp continueexp; - extern (D) __gshared CTFEExp gotoexp; - /* Used when additional information is needed regarding - * a ctfe error. - */ - extern (D) __gshared CTFEExp showcontext; - - extern (D) static bool isCantExp(const Expression e) @safe - { - return e && e.op == EXP.cantExpression; - } - - extern (D) static bool isGotoExp(const Expression e) @safe - { - return e && e.op == EXP.goto_; - } -} - // True if 'e' is CTFEExp::cantexp, or an exception -bool exceptionOrCantInterpret(const Expression e) @safe +bool exceptionOrCantInterpret(const Expression e) @safe nothrow { return e && (e.op == EXP.cantExpression || e.op == EXP.thrownException || e.op == EXP.showCtfeContext); } @@ -224,7 +154,7 @@ bool exceptionOrCantInterpret(const Expression e) @safe /************** Aggregate literals (AA/string/array/struct) ******************/ // Given expr, which evaluates to an array/AA/string literal, // return true if it needs to be copied -bool needToCopyLiteral(const Expression expr) +bool needToCopyLiteral(const Expression expr) nothrow { Expression e = cast()expr; for (;;) @@ -664,7 +594,7 @@ TypeAArray toBuiltinAAType(Type t) /************** TypeInfo operations ************************************/ // Return true if type is TypeInfo_Class -bool isTypeInfo_Class(const Type type) +bool isTypeInfo_Class(const Type type) nothrow { auto tc = cast()type.isTypeClass(); return tc && (Type.dtypeinfo == tc.sym || Type.dtypeinfo.isBaseOf(tc.sym, null)); @@ -812,14 +742,14 @@ Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expres Expression agg2 = getAggregateFromPointer(e2, &ofs2); if (agg1 == agg2) { - Type pointee = (cast(TypePointer)agg1.type).next; + Type pointee = agg1.type.nextOf(); const sz = pointee.size(); emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type); } else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ && agg1.isStringExp().peekString().ptr == agg2.isStringExp().peekString().ptr) { - Type pointee = (cast(TypePointer)agg1.type).next; + Type pointee = agg1.type.nextOf(); const sz = pointee.size(); emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type); } @@ -865,14 +795,14 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type goto Lcant; } dinteger_t ofs2 = e2.toInteger(); - Type pointee = (cast(TypeNext)agg1.type.toBasetype()).next; + Type pointee = agg1.type.toBasetype().nextOf(); dinteger_t sz = pointee.size(); sinteger_t indx; dinteger_t len; - if (agg1.op == EXP.symbolOffset) + if (auto soe = agg1.isSymOffExp()) { indx = ofs1 / sz; - len = (cast(TypeSArray)agg1.isSymOffExp().var.type).dim.toInteger(); + len = soe.var.type.isTypeSArray().dim.toInteger(); } else { @@ -907,9 +837,9 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type error(loc, "CTFE internal error: pointer arithmetic `%s`", agg1.toChars()); goto Lcant; } - if (eptr.type.toBasetype().ty == Tsarray) + if (auto tsa = eptr.type.toBasetype().isTypeSArray()) { - dinteger_t dim = (cast(TypeSArray)eptr.type.toBasetype()).dim.toInteger(); + dinteger_t dim = tsa.dim.toInteger(); // Create a CTFE pointer &agg1[indx .. indx+dim] auto se = ctfeEmplaceExp!SliceExp(loc, agg1, ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t), @@ -1049,7 +979,7 @@ bool isCtfeComparable(Expression e) } /// Map EXP comparison ops -private bool numCmp(N)(EXP op, N n1, N n2) +private bool numCmp(N)(EXP op, N n1, N n2) nothrow { switch (op) { @@ -1068,25 +998,25 @@ private bool numCmp(N)(EXP op, N n1, N n2) } /// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool specificCmp(EXP op, int rawCmp) @safe +bool specificCmp(EXP op, int rawCmp) @safe nothrow { return numCmp!int(op, rawCmp, 0); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe +bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe nothrow { return numCmp!dinteger_t(op, n1, n2); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe +bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe nothrow { return numCmp!sinteger_t(op, n1, n2); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool realCmp(EXP op, real_t r1, real_t r2) @safe +bool realCmp(EXP op, real_t r1, real_t r2) @safe nothrow { // Don't rely on compiler, handle NAN arguments separately if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered @@ -1176,7 +1106,7 @@ private int ctfeCmpArrays(const ref Loc loc, Expression e1, Expression e2, uinte /* Given a delegate expression e, return .funcptr. * If e is NullExp, return NULL. */ -private FuncDeclaration funcptrOf(Expression e) @safe +private FuncDeclaration funcptrOf(Expression e) @safe nothrow { assert(e.type.ty == Tdelegate); if (auto de = e.isDelegateExp()) @@ -1187,7 +1117,7 @@ private FuncDeclaration funcptrOf(Expression e) @safe return null; } -private bool isArray(const Expression e) @safe +private bool isArray(const Expression e) @safe nothrow { return e.op == EXP.arrayLiteral || e.op == EXP.string_ || e.op == EXP.slice || e.op == EXP.null_; } @@ -1341,8 +1271,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide size_t dim = es1.keys.length; if (es2.keys.length != dim) return 1; - bool* used = cast(bool*)mem.xmalloc(bool.sizeof * dim); - memset(used, 0, bool.sizeof * dim); + BitArray used; + used.length = dim; foreach (size_t i; 0 .. dim) { Expression k1 = (*es1.keys)[i]; @@ -1361,11 +1291,9 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide } if (!v2 || ctfeRawCmp(loc, v1, v2, identity)) { - mem.xfree(used); return 1; } } - mem.xfree(used); return 0; } else if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.null_) @@ -2071,9 +1999,8 @@ void showCtfeExpr(Expression e, int level = 0) UnionExp voidInitLiteral(Type t, VarDeclaration var) { UnionExp ue; - if (t.ty == Tsarray) + if (auto tsa = t.isTypeSArray()) { - TypeSArray tsa = cast(TypeSArray)t; Expression elem = voidInitLiteral(tsa.next, var).copy(); // For aggregate value types (structs, static arrays) we must // create an a separate copy for each element. @@ -2090,9 +2017,8 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var) ArrayLiteralExp ae = ue.exp().isArrayLiteralExp(); ae.ownedByCtfe = OwnedBy.ctfe; } - else if (t.ty == Tstruct) + else if (auto ts = t.isTypeStruct()) { - TypeStruct ts = cast(TypeStruct)t; auto exps = new Expressions(ts.sym.fields.length); foreach (size_t i; 0 .. ts.sym.fields.length) { diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index f769473..14c67f0 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -38,6 +38,7 @@ import dmd.init; import dmd.intrange; import dmd.mtype; import dmd.opover; +import dmd.optimize; import dmd.root.ctfloat; import dmd.common.outbuffer; import dmd.root.rmem; @@ -1630,6 +1631,13 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) } else if (tob.ty == Tvector && t1b.ty != Tvector) { + if (t1b.ty == Tsarray) + { + // Casting static array to vector with same size, e.g. `cast(int4) int[4]` + if (t1b.size(e.loc) != tob.size(e.loc)) + goto Lfail; + return new VectorExp(e.loc, e, tob).expressionSemantic(sc); + } //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars()); TypeVector tv = tob.isTypeVector(); Expression result = new CastExp(e.loc, e, tv.elementType()); diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d index bae942c..72b85cf 100644 --- a/gcc/d/dmd/dclass.d +++ b/gcc/d/dmd/dclass.d @@ -180,7 +180,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration int cppDtorVtblIndex = -1; /// to prevent recursive attempts - private bool inuse; + bool inuse; ThreeState isabstract; @@ -367,7 +367,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration baseok = Baseok.none; } - extern (D) private void classError(const(char)* fmt, const(char)* arg) + extern (D) final void classError(const(char)* fmt, const(char)* arg) { .error(loc, fmt, kind, toPrettyChars, arg); } @@ -468,67 +468,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return baseok >= Baseok.done; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags); - //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); - if (_scope && baseok < Baseok.semanticdone) - { - if (!inuse) - { - // must semantic on base class/interfaces - inuse = true; - dsymbolSemantic(this, null); - inuse = false; - } - } - - if (!members || !symtab) // opaque or addMember is not yet done - { - // .stringof is always defined (but may be hidden by some other symbol) - if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone) - classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars()); - //*(char*)0=0; - return null; - } - - auto s = ScopeDsymbol.search(loc, ident, flags); - - // don't search imports of base classes - if (flags & SearchImportsOnly) - return s; - - if (s) - return s; - - // Search bases classes in depth-first, left to right order - foreach (b; (*baseclasses)[]) - { - if (!b.sym) - continue; - - if (!b.sym.symtab) - { - classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars()); - continue; - } - - import dmd.access : symbolIsVisible; - - s = b.sym.search(loc, ident, flags); - if (!s) - continue; - else if (s == this) // happens if s is nested in this and derives from this - s = null; - else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s)) - s = null; - else - break; - } - - return s; - } - /************************************ * Search base classes in depth-first, left-to-right order for * a class or interface named 'ident'. @@ -675,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration final bool isFuncHidden(FuncDeclaration fd) { //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars()); - Dsymbol s = search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors); + Dsymbol s = this.search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors); if (!s) { //printf("not found\n"); diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index 76a31f4..0e125fd 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -421,18 +421,6 @@ extern (C++) abstract class Declaration : Dsymbol return Modifiable.yes; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - Dsymbol s = Dsymbol.search(loc, ident, flags); - if (!s && type) - { - s = type.toDsymbol(_scope); - if (s) - s = s.search(loc, ident, flags); - } - return s; - } - final bool isStatic() const pure nothrow @nogc @safe { return (storage_class & STC.static_) != 0; diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 8cd295f..a65fb44 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -124,7 +124,6 @@ public: const char *kind() const override; uinteger_t size(const Loc &loc) override final; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; bool isStatic() const { return (storage_class & STCstatic) != 0; } LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one diff --git a/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d index f33b5fd..797f6ee 100644 --- a/gcc/d/dmd/denum.d +++ b/gcc/d/dmd/denum.d @@ -83,25 +83,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return ed; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - version (none) - { - printf("EnumDeclaration::addMember() %s\n", toChars()); - for (size_t i = 0; i < members.length; i++) - { - EnumMember em = (*members)[i].isEnumMember(); - printf(" member %s\n", em.toChars()); - } - } - if (!isAnonymous()) - { - ScopeDsymbol.addMember(sc, sds); - } - - addEnumMembersToSymtab(this, sc, sds); - } - override void setScope(Scope* sc) { if (semanticRun > PASS.initial) @@ -126,19 +107,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return "enum"; } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident.toChars()); - if (_scope) - { - // Try one last time to resolve this enum - dsymbolSemantic(this, _scope); - } - - Dsymbol s = ScopeDsymbol.search(loc, ident, flags); - return s; - } - // is Dsymbol deprecated? override bool isDeprecated() const { diff --git a/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d index d74c860..0132e49 100644 --- a/gcc/d/dmd/dimport.d +++ b/gcc/d/dmd/dimport.d @@ -305,33 +305,6 @@ extern (C++) final class Import : Dsymbol return this; } - /***************************** - * Add import to sd's symbol table. - */ - override void addMember(Scope* sc, ScopeDsymbol sd) - { - //printf("Import.addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd.toChars(), sc); - if (names.length == 0) - return Dsymbol.addMember(sc, sd); - if (aliasId) - Dsymbol.addMember(sc, sd); - /* Instead of adding the import to sd's symbol table, - * add each of the alias=name pairs - */ - for (size_t i = 0; i < names.length; i++) - { - Identifier name = names[i]; - Identifier _alias = aliases[i]; - if (!_alias) - _alias = name; - auto tname = new TypeIdentifier(loc, name); - auto ad = new AliasDeclaration(loc, _alias, tname); - ad._import = this; - ad.addMember(sc, sd); - aliasdecls.push(ad); - } - } - override void setScope(Scope* sc) { Dsymbol.setScope(sc); @@ -348,19 +321,6 @@ extern (C++) final class Import : Dsymbol } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - if (!pkg) - { - load(null); - mod.importAll(null); - mod.dsymbolSemantic(null); - } - // Forward it to the package/module - return pkg.search(loc, ident, flags); - } - override bool overloadInsert(Dsymbol s) { /* Allow multiple imports with the same package base, but disallow diff --git a/gcc/d/dmd/dmangle.d b/gcc/d/dmd/dmangle.d index c58b585..2bedccb 100644 --- a/gcc/d/dmd/dmangle.d +++ b/gcc/d/dmd/dmangle.d @@ -152,6 +152,7 @@ import dmd.identifier; import dmd.mtype; import dmd.root.ctfloat; import dmd.common.outbuffer; +import dmd.optimize; import dmd.root.aav; import dmd.root.string; import dmd.root.stringtable; diff --git a/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d index 548928a..5f5de63 100644 --- a/gcc/d/dmd/dmodule.d +++ b/gcc/d/dmd/dmodule.d @@ -268,22 +268,6 @@ extern (C++) class Package : ScopeDsymbol return isAncestorPackageOf(pkg.parent.isPackage()); } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s Package.search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - flags &= ~SearchLocalsOnly; // searching an import is always transitive - if (!isModule() && mod) - { - // Prefer full package name. - Dsymbol s = symtab ? symtab.lookup(ident) : null; - if (s) - return s; - //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars()); - return mod.search(loc, ident, flags); - } - return ScopeDsymbol.search(loc, ident, flags); - } - override void accept(Visitor v) { v.visit(this); @@ -414,10 +398,10 @@ extern (C++) final class Module : Package return rootimports == ThreeState.yes; } - private Identifier searchCacheIdent; - private Dsymbol searchCacheSymbol; // cached value of search - private int searchCacheFlags; // cached flags - private bool insearch; + Identifier searchCacheIdent; + Dsymbol searchCacheSymbol; // cached value of search + int searchCacheFlags; // cached flags + bool insearch; /** * A root module is one that will be compiled all the way to @@ -793,7 +777,7 @@ extern (C++) final class Module : Package } else { - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); scope p = new Parser!AST(this, buf, cast(bool) docfile, global.errorSink, &global.compileEnv, doUnittests); p.transitionIn = global.params.v.vin; p.nextToken(); @@ -1036,47 +1020,6 @@ extern (C++) final class Module : Package } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - /* Since modules can be circularly referenced, - * need to stop infinite recursive searches. - * This is done with the cache. - */ - //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", toChars(), ident.toChars(), flags, insearch); - if (insearch) - return null; - - /* Qualified module searches always search their imports, - * even if SearchLocalsOnly - */ - if (!(flags & SearchUnqualifiedModule)) - flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly); - - if (searchCacheIdent == ident && searchCacheFlags == flags) - { - //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", - // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null"); - return searchCacheSymbol; - } - - uint errors = global.errors; - - insearch = true; - Dsymbol s = ScopeDsymbol.search(loc, ident, flags); - insearch = false; - - if (errors == global.errors) - { - // https://issues.dlang.org/show_bug.cgi?id=10752 - // Can cache the result only when it does not cause - // access error so the side-effect should be reproduced in later search. - searchCacheIdent = ident; - searchCacheSymbol = s; - searchCacheFlags = flags; - } - return s; - } - override bool isPackageAccessible(Package p, Visibility visibility, int flags = 0) { if (insearch) // don't follow import cycles diff --git a/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d index 3853512..d68bcda 100644 --- a/gcc/d/dmd/dscope.d +++ b/gcc/d/dmd/dscope.d @@ -66,13 +66,15 @@ enum SCOPE fullinst = 0x10000, /// fully instantiate templates ctfeBlock = 0x20000, /// inside a `if (__ctfe)` block + dip1000 = 0x40000, /// dip1000 errors enabled for this scope + dip25 = 0x80000, /// dip25 errors enabled for this scope } /// Flags that are carried along with a scope push() private enum PersistentFlags = SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility | - SCOPE.Cfile | SCOPE.ctfeBlock; + SCOPE.Cfile | SCOPE.ctfeBlock | SCOPE.dip1000 | SCOPE.dip25; extern (C++) struct Scope { @@ -176,6 +178,10 @@ extern (C++) struct Scope m = m.parent; m.addMember(null, sc.scopesym); m.parent = null; // got changed by addMember() + if (global.params.useDIP1000 == FeatureState.enabled) + sc.flags |= SCOPE.dip1000; + if (global.params.useDIP25 == FeatureState.enabled) + sc.flags |= SCOPE.dip25; if (_module.filetype == FileType.c) sc.flags |= SCOPE.Cfile; // Create the module scope underneath the global scope @@ -344,7 +350,7 @@ extern (C++) struct Scope * Returns: * symbol if found, null if not */ - extern (D) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone) + extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone) { version (LOGSEARCH) { @@ -821,4 +827,16 @@ extern (C++) struct Scope { return (flags & (SCOPE.ctfe | SCOPE.ctfeBlock | SCOPE.compile)) == 0; } + + /// Returns: whether to raise DIP1000 warnings (FeatureStabe.default) or errors (FeatureState.enabled) + extern (D) FeatureState useDIP1000() + { + return (flags & SCOPE.dip1000) ? FeatureState.enabled : FeatureState.disabled; + } + + /// Returns: whether to raise DIP25 warnings (FeatureStabe.default) or errors (FeatureState.enabled) + extern (D) FeatureState useDIP25() + { + return (flags & SCOPE.dip25) ? FeatureState.enabled : FeatureState.disabled; + } } diff --git a/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d index f77a263..36e847c 100644 --- a/gcc/d/dmd/dstruct.d +++ b/gcc/d/dmd/dstruct.d @@ -263,23 +263,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return sd; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - if (_scope && !symtab) - dsymbolSemantic(this, _scope); - - if (!members || !symtab) // opaque or semantic() is not yet called - { - // .stringof is always defined (but may be hidden by some other symbol) - if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone) - .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars()); - return null; - } - - return ScopeDsymbol.search(loc, ident, flags); - } - override const(char)* kind() const { return "struct"; diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index 914213c..a52745f 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -35,7 +35,6 @@ import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.id; @@ -750,67 +749,6 @@ extern (C++) class Dsymbol : ASTNode return toAlias(); } - void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("Dsymbol::addMember('%s')\n", toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab); - parent = sds; - if (isAnonymous()) // no name, so can't add it to symbol table - return; - - if (!sds.symtabInsert(this)) // if name is already defined - { - if (isAliasDeclaration() && !_scope) - setScope(sc); - Dsymbol s2 = sds.symtabLookup(this,ident); - /* https://issues.dlang.org/show_bug.cgi?id=17434 - * - * If we are trying to add an import to the symbol table - * that has already been introduced, then keep the one with - * larger visibility. This is fine for imports because if - * we have multiple imports of the same file, if a single one - * is public then the symbol is reachable. - */ - if (auto i1 = isImport()) - { - if (auto i2 = s2.isImport()) - { - if (sc.explicitVisibility && sc.visibility > i2.visibility) - sds.symtab.update(this); - } - } - - // If using C tag/prototype/forward declaration rules - if (sc.flags & SCOPE.Cfile && !this.isImport()) - { - if (handleTagSymbols(*sc, this, s2, sds)) - return; - if (handleSymbolRedeclarations(*sc, this, s2, sds)) - return; - - sds.multiplyDefined(Loc.initial, this, s2); // ImportC doesn't allow overloading - errors = true; - return; - } - - if (!s2.overloadInsert(this)) - { - sds.multiplyDefined(Loc.initial, this, s2); - errors = true; - } - } - if (sds.isAggregateDeclaration() || sds.isEnumDeclaration()) - { - if (ident == Id.__sizeof || - !(sc && sc.flags & SCOPE.Cfile) && (ident == Id.__xalignof || ident == Id._mangleof)) - { - .error(loc, "%s `%s` `.%s` property cannot be redefined", kind, toPrettyChars, ident.toChars()); - errors = true; - } - } - } - /************************************* * Set scope for future semantic analysis so we can * deal better with forward references. @@ -831,21 +769,6 @@ extern (C++) class Dsymbol : ASTNode { } - /********************************************* - * Search for ident as member of s. - * Params: - * loc = location to print for error messages - * ident = identifier to search for - * flags = IgnoreXXXX - * Returns: - * null if not found - */ - Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone) - { - //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - return null; - } - extern (D) final Dsymbol search_correct(Identifier ident) { /*************************************************** @@ -870,7 +793,7 @@ extern (C++) class Dsymbol : ASTNode if (global.gag) return null; // don't do it for speculative compiles; too time consuming // search for exact name first - if (auto s = search(Loc.initial, ident, IgnoreErrors)) + if (auto s = this.search(Loc.initial, ident, IgnoreErrors)) return s; return speller!symbol_search_fp(ident.toString()); } @@ -1339,12 +1262,12 @@ extern (C++) class ScopeDsymbol : Dsymbol Dsymbols* members; // all Dsymbol's in this scope DsymbolTable symtab; // members[] sorted into table uint endlinnum; // the linnumber of the statement after the scope (0 if unknown) - -private: /// symbols whose members have been imported, i.e. imported modules and template mixins Dsymbols* importedScopes; Visibility.Kind* visibilities; // array of Visibility.Kind, one for each import +private: + import dmd.root.bitarray; BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages @@ -1373,166 +1296,7 @@ public: return sds; } - /***************************************** - * This function is #1 on the list of functions that eat cpu time. - * Be very, very careful about slowing it down. - */ - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags); - //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0; - - // Look in symbols declared in this module - if (symtab && !(flags & SearchImportsOnly)) - { - //printf(" look in locals\n"); - auto s1 = symtab.lookup(ident); - if (s1) - { - //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars()); - return s1; - } - } - //printf(" not found in locals\n"); - - // Look in imported scopes - if (!importedScopes) - return null; - - //printf(" look in imports\n"); - Dsymbol s = null; - OverloadSet a = null; - // Look in imported modules - for (size_t i = 0; i < importedScopes.length; i++) - { - // If private import, don't search it - if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_) - continue; - int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches - Dsymbol ss = (*importedScopes)[i]; - //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport()); - - if (ss.isModule()) - { - if (flags & SearchLocalsOnly) - continue; - } - else // mixin template - { - if (flags & SearchImportsOnly) - continue; - - sflags |= SearchLocalsOnly; - } - - /* Don't find private members if ss is a module - */ - Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone)); - import dmd.access : symbolIsVisible; - if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2)) - continue; - if (!s) - { - s = s2; - if (s && s.isOverloadSet()) - a = mergeOverloadSet(ident, a, s); - } - else if (s2 && s != s2) - { - if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType()) - { - /* After following aliases, we found the same - * symbol, so it's not an ambiguity. But if one - * alias is deprecated or less accessible, prefer - * the other. - */ - if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none) - s = s2; - } - else - { - /* Two imports of the same module should be regarded as - * the same. - */ - Import i1 = s.isImport(); - Import i2 = s2.isImport(); - if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident))))) - { - /* https://issues.dlang.org/show_bug.cgi?id=8668 - * Public selective import adds AliasDeclaration in module. - * To make an overload set, resolve aliases in here and - * get actual overload roots which accessible via s and s2. - */ - s = s.toAlias(); - s2 = s2.toAlias(); - /* If both s2 and s are overloadable (though we only - * need to check s once) - */ - - auto so2 = s2.isOverloadSet(); - if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable())) - { - if (symbolIsVisible(this, s2)) - { - a = mergeOverloadSet(ident, a, s2); - } - if (!symbolIsVisible(this, s)) - s = s2; - continue; - } - - /* Two different overflow sets can have the same members - * https://issues.dlang.org/show_bug.cgi?id=16709 - */ - auto so = s.isOverloadSet(); - if (so && so2) - { - if (so.a.length == so2.a.length) - { - foreach (j; 0 .. so.a.length) - { - if (so.a[j] !is so2.a[j]) - goto L1; - } - continue; // the same - L1: - { } // different - } - } - - if (flags & IgnoreAmbiguous) // if return NULL on ambiguity - return null; - - /* If two imports from C import files, pick first one, as C has global name space - */ - if (s.isCsymbol() && s2.isCsymbol()) - continue; - - if (!(flags & IgnoreErrors)) - ScopeDsymbol.multiplyDefined(loc, s, s2); - break; - } - } - } - } - if (s) - { - /* Build special symbol if we had multiple finds - */ - if (a) - { - if (!s.isOverloadSet()) - a = mergeOverloadSet(ident, a, s); - s = a; - } - //printf("\tfound in imports %s.%s\n", toChars(), s.toChars()); - return s; - } - //printf(" not found in imports\n"); - return null; - } - - extern (D) private OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s) + extern (D) final OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s) { if (!os) { @@ -1844,40 +1608,6 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol this.withstate = withstate; } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("WithScopeSymbol.search(%s)\n", ident.toChars()); - if (flags & SearchImportsOnly) - return null; - // Acts as proxy to the with class declaration - Dsymbol s = null; - Expression eold = null; - for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true)) - { - if (auto se = e.isScopeExp()) - { - s = se.sds; - } - else if (e.isTypeExp()) - { - s = e.type.toDsymbol(null); - } - else - { - Type t = e.type.toBasetype(); - s = t.toDsymbol(null); - } - if (s) - { - s = s.search(loc, ident, flags); - if (s) - return s; - } - eold = e; - } - return null; - } - override inout(WithScopeSymbol) isWithScopeSymbol() inout { return this; @@ -1896,217 +1626,28 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol { // either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration. // Discriminated using DYNCAST and, for expressions, also EXP - private RootObject arrayContent; - Scope* sc; + RootObject arrayContent; extern (D) this(Scope* sc, Expression exp) nothrow @safe { super(exp.loc, null); assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array); - this.sc = sc; + this._scope = sc; this.arrayContent = exp; } extern (D) this(Scope* sc, TypeTuple type) nothrow @safe { - this.sc = sc; + this._scope = sc; this.arrayContent = type; } extern (D) this(Scope* sc, TupleDeclaration td) nothrow @safe { - this.sc = sc; + this._scope = sc; this.arrayContent = td; } - /// This override is used to solve `$` - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone) - { - //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags); - if (ident != Id.dollar) - return null; - - VarDeclaration* pvar; - Expression ce; - - static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc) - { - - /* $ gives the number of type entries in the type tuple - */ - auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); - Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t); - v._init = new ExpInitializer(Loc.initial, e); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - v.dsymbolSemantic(sc); - return v; - } - - const DYNCAST kind = arrayContent.dyncast(); - switch (kind) with (DYNCAST) - { - case dsymbol: - TupleDeclaration td = cast(TupleDeclaration) arrayContent; - /* $ gives the number of elements in the tuple - */ - auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); - Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t); - v._init = new ExpInitializer(Loc.initial, e); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - v.dsymbolSemantic(sc); - return v; - case type: - return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc); - default: - break; - } - Expression exp = cast(Expression) arrayContent; - if (auto ie = exp.isIndexExp()) - { - /* array[index] where index is some function of $ - */ - pvar = &ie.lengthVar; - ce = ie.e1; - } - else if (auto se = exp.isSliceExp()) - { - /* array[lwr .. upr] where lwr or upr is some function of $ - */ - pvar = &se.lengthVar; - ce = se.e1; - } - else if (auto ae = exp.isArrayExp()) - { - /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $ - * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...) - */ - pvar = &ae.lengthVar; - ce = ae.e1; - } - else - { - /* Didn't find $, look in enclosing scope(s). - */ - return null; - } - ce = ce.lastComma(); - /* If we are indexing into an array that is really a type - * tuple, rewrite this as an index into a type tuple and - * try again. - */ - if (auto te = ce.isTypeExp()) - { - if (auto ttp = te.type.isTypeTuple()) - return dollarFromTypeTuple(loc, ttp, sc); - } - /* *pvar is lazily initialized, so if we refer to $ - * multiple times, it gets set only once. - */ - if (!*pvar) // if not already initialized - { - /* Create variable v and set it to the value of $ - */ - VarDeclaration v; - Type t; - if (auto tupexp = ce.isTupleExp()) - { - /* It is for an expression tuple, so the - * length will be a const. - */ - Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t); - v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e)); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - } - else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass)) - { - // Look for opDollar - assert(exp.op == EXP.array || exp.op == EXP.slice); - AggregateDeclaration ad = isAggregate(t); - assert(ad); - Dsymbol s = ad.search(loc, Id.opDollar); - if (!s) // no dollar exists -- search in higher scope - return null; - s = s.toAlias(); - Expression e = null; - // Check for multi-dimensional opDollar(dim) template. - if (TemplateDeclaration td = s.isTemplateDeclaration()) - { - dinteger_t dim = 0; - if (auto ae = exp.isArrayExp()) - { - dim = ae.currentDimension; - } - else if (exp.isSliceExp()) - { - dim = 0; // slices are currently always one-dimensional - } - else - { - assert(0); - } - auto tiargs = new Objects(); - Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t); - edim = edim.expressionSemantic(sc); - tiargs.push(edim); - e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs); - } - else - { - /* opDollar exists, but it's not a template. - * This is acceptable ONLY for single-dimension indexing. - * Note that it's impossible to have both template & function opDollar, - * because both take no arguments. - */ - auto ae = exp.isArrayExp(); - if (ae && ae.arguments.length != 1) - { - error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars()); - return null; - } - Declaration d = s.isDeclaration(); - assert(d); - e = new DotVarExp(loc, ce, d); - } - e = e.expressionSemantic(sc); - if (!e.type) - error(exp.loc, "`%s` has no value", e.toChars()); - t = e.type.toBasetype(); - if (t && t.ty == Tfunction) - e = new CallExp(e.loc, e); - v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e)); - v.storage_class |= STC.temp | STC.ctfe | STC.rvalue; - } - else - { - /* For arrays, $ will either be a compile-time constant - * (in which case its value in set during constant-folding), - * or a variable (in which case an expression is created in - * toir.c). - */ - - // https://issues.dlang.org/show_bug.cgi?id=16213 - // For static arrays $ is known at compile time, - // so declare it as a manifest constant. - auto tsa = ce.type ? ce.type.isTypeSArray() : null; - if (tsa) - { - auto e = new ExpInitializer(loc, tsa.dim); - v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest); - } - else - { - auto e = new VoidInitializer(Loc.initial); - e.type = Type.tsize_t; - v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); - v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable - } - } - *pvar = v; - } - (*pvar).dsymbolSemantic(sc); - return (*pvar); - } - override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout { return this; diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 0278975..e0c2046 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -228,10 +228,8 @@ public: virtual const char *kind() const; virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias2(); - virtual void addMember(Scope *sc, ScopeDsymbol *sds); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); - virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone); virtual bool overloadInsert(Dsymbol *s); virtual uinteger_t size(const Loc &loc); virtual bool isforwardRef(); @@ -331,16 +329,14 @@ public: Dsymbols *members; // all Dsymbol's in this scope DsymbolTable *symtab; // members[] sorted into table unsigned endlinnum; // the linnumber of the statement after the scope (0 if unknown) - -private: Dsymbols *importedScopes; // imported Dsymbol's Visibility::Kind *visibilities; // array of `Visibility.Kind`, one for each import +private: BitArray accessiblePackages, privateAccessiblePackages; public: ScopeDsymbol *syntaxCopy(Dsymbol *s) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; virtual void importScope(Dsymbol *s, Visibility visibility); virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0); bool isforwardRef() override final; @@ -362,7 +358,6 @@ class WithScopeSymbol final : public ScopeDsymbol public: WithStatement *withstate; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; WithScopeSymbol *isWithScopeSymbol() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -372,12 +367,8 @@ public: class ArrayScopeSymbol final : public ScopeDsymbol { -private: - RootObject *arrayContent; public: - Scope *sc; - - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override; + RootObject *arrayContent; ArrayScopeSymbol *isArrayScopeSymbol() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -437,3 +428,6 @@ public: // Number of symbols in symbol table size_t length() const; }; + +void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); +Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 397c5e5..430377f 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -23,6 +23,7 @@ import dmd.astenums; import dmd.attrib; import dmd.blockexit; import dmd.clone; +import dmd.cond; import dmd.compiler; import dmd.dcast; import dmd.dclass; @@ -57,6 +58,7 @@ import dmd.nogc; import dmd.nspace; import dmd.objc; import dmd.opover; +import dmd.optimize; import dmd.parse; import dmd.root.array; import dmd.root.filename; @@ -1140,7 +1142,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else if (auto ale = ex.isArrayLiteralExp()) { // or an array literal assigned to a `scope` variable - if (global.params.useDIP1000 == FeatureState.enabled + if (sc.useDIP1000 == FeatureState.enabled && !dsym.type.nextOf().needsDestruction()) ale.onstack = true; } @@ -1169,10 +1171,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // https://issues.dlang.org/show_bug.cgi?id=14166 // Don't run CTFE for the temporary variables inside typeof dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret); + import dmd.semantic2 : lowerStaticAAs; + lowerStaticAAs(dsym, sc); const init_err = dsym._init.isExpInitializer(); if (init_err && init_err.exp.op == EXP.showCtfeContext) { - errorSupplemental(dsym.loc, "compile time context created here"); + errorSupplemental(dsym.loc, "compile time context created here"); } } } @@ -1951,7 +1955,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); auto loc = adjustLocForMixin(str, cd.loc, global.params.mixinOut); scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests); p.transitionIn = global.params.v.vin; @@ -1978,7 +1982,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!cd.compiled) { cd.decl = compileIt(cd); - cd.AttribDeclaration.addMember(sc, cd.scopesym); + attribAddMember(cd, sc, cd.scopesym); cd.compiled = true; if (cd._scope && cd.decl) @@ -3384,9 +3388,13 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested())) { - OutBuffer buf; - MODtoBuffer(buf, tf.mod); - .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, buf.peekChars()); + import core.bitop : popcnt; + auto mods = MODtoChars(tf.mod); + .error(funcdecl.loc, "%s `%s` without `this` cannot be `%s`", funcdecl.kind, funcdecl.toPrettyChars, mods); + if (tf.next && tf.next.ty != Tvoid && popcnt(tf.mod) == 1) + .errorSupplemental(funcdecl.loc, + "did you mean to use `%s(%s)` as the return type?", mods, tf.next.toChars()); + tf.mod = 0; // remove qualifiers } @@ -5826,6 +5834,365 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } +/* +Adds dsym as a member of scope sds. + +Params: + dsym = dsymbol to inserted + sc = scope where the dsymbol is declared + sds = ScopeDsymbol where dsym is inserted +*/ +extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds) +{ + auto addMemberVisitor = new AddMemberVisitor(sc, sds); + dsym.accept(addMemberVisitor); +} + +private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds) +{ + Dsymbols* d = atb.include(sc); + if (d) + { + Scope* sc2 = atb.newScope(sc); + d.foreachDsymbol( s => s.addMember(sc2, sds) ); + if (sc2 != sc) + sc2.pop(); + } +} + +private extern(C++) class AddMemberVisitor : Visitor +{ + alias visit = Visitor.visit; + + Scope* sc; + ScopeDsymbol sds; + + this(Scope* sc, ScopeDsymbol sds) + { + this.sc = sc; + this.sds = sds; + } + + override void visit(Dsymbol dsym) + { + //printf("Dsymbol::addMember('%s')\n", toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab); + dsym.parent = sds; + if (dsym.isAnonymous()) // no name, so can't add it to symbol table + return; + + if (!sds.symtabInsert(dsym)) // if name is already defined + { + if (dsym.isAliasDeclaration() && !dsym._scope) + dsym.setScope(sc); + Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident); + /* https://issues.dlang.org/show_bug.cgi?id=17434 + * + * If we are trying to add an import to the symbol table + * that has already been introduced, then keep the one with + * larger visibility. This is fine for imports because if + * we have multiple imports of the same file, if a single one + * is public then the symbol is reachable. + */ + if (auto i1 = dsym.isImport()) + { + if (auto i2 = s2.isImport()) + { + if (sc.explicitVisibility && sc.visibility > i2.visibility) + sds.symtab.update(dsym); + } + } + + // If using C tag/prototype/forward declaration rules + if (sc.flags & SCOPE.Cfile && !dsym.isImport()) + { + if (handleTagSymbols(*sc, dsym, s2, sds)) + return; + if (handleSymbolRedeclarations(*sc, dsym, s2, sds)) + return; + + sds.multiplyDefined(Loc.initial, dsym, s2); // ImportC doesn't allow overloading + dsym.errors = true; + return; + } + + if (!s2.overloadInsert(dsym)) + { + sds.multiplyDefined(Loc.initial, dsym, s2); + dsym.errors = true; + } + } + if (sds.isAggregateDeclaration() || sds.isEnumDeclaration()) + { + if (dsym.ident == Id.__sizeof || + !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof)) + { + .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars()); + dsym.errors = true; + } + } + } + + + override void visit(StaticAssert _) + { + // we didn't add anything + } + + /***************************** + * Add import to sd's symbol table. + */ + override void visit(Import imp) + { + //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc); + if (imp.names.length == 0) + return visit(cast(Dsymbol)imp); + if (imp.aliasId) + visit(cast(Dsymbol)imp); + + /* Instead of adding the import to sds's symbol table, + * add each of the alias=name pairs + */ + for (size_t i = 0; i < imp.names.length; i++) + { + Identifier name = imp.names[i]; + Identifier _alias = imp.aliases[i]; + if (!_alias) + _alias = name; + auto tname = new TypeIdentifier(imp.loc, name); + auto ad = new AliasDeclaration(imp.loc, _alias, tname); + ad._import = imp; + addMember(ad, sc, sds); + imp.aliasdecls.push(ad); + } + } + + override void visit(AttribDeclaration atb) + { + attribAddMember(atb, sc, sds); + } + + override void visit(StorageClassDeclaration stcd) + { + Dsymbols* d = stcd.include(sc); + if (d) + { + Scope* sc2 = stcd.newScope(sc); + + d.foreachDsymbol( (s) + { + //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars()); + // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol) + if (auto decl = s.isDeclaration()) + { + decl.storage_class |= stcd.stc & STC.local; + if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case? + { + sdecl.stc |= stcd.stc & STC.local; + } + } + s.addMember(sc2, sds); + }); + + if (sc2 != sc) + sc2.pop(); + } + } + + override void visit(VisibilityDeclaration visd) + { + if (visd.pkg_identifiers) + { + Dsymbol tmp; + Package.resolve(visd.pkg_identifiers, &tmp, null); + visd.visibility.pkg = tmp ? tmp.isPackage() : null; + visd.pkg_identifiers = null; + } + if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module) + { + Module m = sc._module; + + // https://issues.dlang.org/show_bug.cgi?id=17441 + // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if + // each package's .isModule() properites are equal. + // + // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null. + // This breaks package declarations of the package in question if they are declared in + // the same package.d file, which _do_ have a module associated with them, and hence a non-null + // isModule() + if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident)) + { + Package pkg = m.parent ? m.parent.isPackage() : null; + if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg)) + .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true)); + } + } + attribAddMember(visd, sc, sds); + } + + override void visit(StaticIfDeclaration sid) + { + //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars()); + /* This is deferred until the condition evaluated later (by the include() call), + * so that expressions in the condition can refer to declarations + * in the same scope, such as: + * + * template Foo(int i) + * { + * const int j = i + 1; + * static if (j == 3) + * const int k; + * } + */ + sid.scopesym = sds; + } + + + override void visit(StaticForeachDeclaration sfd) + { + // used only for caching the enclosing symbol + sfd.scopesym = sds; + } + + /*************************************** + * Lazily initializes the scope to forward to. + */ + override void visit(ForwardingAttribDeclaration fad) + { + fad.sym.parent = sds; + sds = fad.sym; + attribAddMember(fad, sc, fad.sym); + } + + override void visit(MixinDeclaration md) + { + //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum); + md.scopesym = sds; + } + + override void visit(DebugSymbol ds) + { + //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars()); + Module m = sds.isModule(); + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + if (ds.ident) + { + if (!m) + { + .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + else + { + if (findCondition(m.debugidsNot, ds.ident)) + { + .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + if (!m.debugids) + m.debugids = new Identifiers(); + m.debugids.push(ds.ident); + } + } + else + { + if (!m) + { + .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + else + m.debuglevel = ds.level; + } + } + + override void visit(VersionSymbol vs) + { + //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars()); + Module m = sds.isModule(); + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + if (vs.ident) + { + VersionCondition.checkReserved(vs.loc, vs.ident.toString()); + if (!m) + { + .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + else + { + if (findCondition(m.versionidsNot, vs.ident)) + { + .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + if (!m.versionids) + m.versionids = new Identifiers(); + m.versionids.push(vs.ident); + } + } + else + { + if (!m) + { + .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + else + m.versionlevel = vs.level; + } + } + + override void visit(Nspace ns) + { + visit(cast(Dsymbol)ns); + + if (ns.members) + { + if (!ns.symtab) + ns.symtab = new DsymbolTable(); + // The namespace becomes 'imported' into the enclosing scope + for (Scope* sce = sc; 1; sce = sce.enclosing) + { + ScopeDsymbol sds2 = sce.scopesym; + if (sds2) + { + sds2.importScope(ns, Visibility(Visibility.Kind.public_)); + break; + } + } + assert(sc); + sc = sc.push(ns); + sc.linkage = LINK.cpp; // namespaces default to C++ linkage + sc.parent = ns; + ns.members.foreachDsymbol(s => s.addMember(sc, ns)); + sc.pop(); + } + } + + override void visit(EnumDeclaration ed) + { + version (none) + { + printf("EnumDeclaration::addMember() %s\n", ed.toChars()); + for (size_t i = 0; i < ed.members.length; i++) + { + EnumMember em = (*ed.members)[i].isEnumMember(); + printf(" member %s\n", em.toChars()); + } + } + if (!ed.isAnonymous()) + { + visit(cast(Dsymbol)ed); + } + + addEnumMembersToSymtab(ed, sc, sds); + } +} + /******************************************* * Add members of EnumDeclaration to the symbol table(s). * Params: @@ -5899,7 +6266,7 @@ private bool isDRuntimeHook(Identifier id) id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT || id == Id._d_arraysetlengthTTrace || id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace || - id == Id._d_arrayappendcTXImpl; + id == Id._d_arrayappendcTX; } void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList) @@ -7426,3 +7793,617 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* p, funcdecl.toChars()); } } + +/********************************************* + * Search for ident as member of d. + * Params: + * d = dsymbol where ident is searched for + * loc = location to print for error messages + * ident = identifier to search for + * flags = IgnoreXXXX + * Returns: + * null if not found + */ +extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone) +{ + scope v = new SearchVisitor(loc, ident, flags); + d.accept(v); + return v.result; +} + +private extern(C++) class SearchVisitor : Visitor +{ + alias visit = Visitor.visit; + + const Loc loc; + Identifier ident; + int flags; + Dsymbol result; + + this(const ref Loc loc, Identifier ident, int flags) + { + this.loc = loc; + this.ident = ident; + this.flags = flags; + } + + void setResult(Dsymbol d) + { + result = d; + } + + override void visit(Dsymbol d) + { + //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars()); + return setResult(null); + } + + override void visit(ScopeDsymbol sds) + { + //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags); + //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0; + + // Look in symbols declared in this module + if (sds.symtab && !(flags & SearchImportsOnly)) + { + //printf(" look in locals\n"); + auto s1 = sds.symtab.lookup(ident); + if (s1) + { + //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars()); + return setResult(s1); + } + } + //printf(" not found in locals\n"); + + // Look in imported scopes + if (!sds.importedScopes) + return setResult(null); + + //printf(" look in imports\n"); + Dsymbol s = null; + OverloadSet a = null; + // Look in imported modules + for (size_t i = 0; i < sds.importedScopes.length; i++) + { + // If private import, don't search it + if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_) + continue; + int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches + Dsymbol ss = (*sds.importedScopes)[i]; + //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport()); + + if (ss.isModule()) + { + if (flags & SearchLocalsOnly) + continue; + } + else // mixin template + { + if (flags & SearchImportsOnly) + continue; + + sflags |= SearchLocalsOnly; + } + + /* Don't find private members if ss is a module + */ + Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone)); + import dmd.access : symbolIsVisible; + if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2)) + continue; + if (!s) + { + s = s2; + if (s && s.isOverloadSet()) + a = sds.mergeOverloadSet(ident, a, s); + } + else if (s2 && s != s2) + { + if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType()) + { + /* After following aliases, we found the same + * symbol, so it's not an ambiguity. But if one + * alias is deprecated or less accessible, prefer + * the other. + */ + if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none) + s = s2; + } + else + { + /* Two imports of the same module should be regarded as + * the same. + */ + Import i1 = s.isImport(); + Import i2 = s2.isImport(); + if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident))))) + { + /* https://issues.dlang.org/show_bug.cgi?id=8668 + * Public selective import adds AliasDeclaration in module. + * To make an overload set, resolve aliases in here and + * get actual overload roots which accessible via s and s2. + */ + s = s.toAlias(); + s2 = s2.toAlias(); + /* If both s2 and s are overloadable (though we only + * need to check s once) + */ + + auto so2 = s2.isOverloadSet(); + if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable())) + { + if (symbolIsVisible(sds, s2)) + { + a = sds.mergeOverloadSet(ident, a, s2); + } + if (!symbolIsVisible(sds, s)) + s = s2; + continue; + } + + /* Two different overflow sets can have the same members + * https://issues.dlang.org/show_bug.cgi?id=16709 + */ + auto so = s.isOverloadSet(); + if (so && so2) + { + if (so.a.length == so2.a.length) + { + foreach (j; 0 .. so.a.length) + { + if (so.a[j] !is so2.a[j]) + goto L1; + } + continue; // the same + L1: + { } // different + } + } + + if (flags & IgnoreAmbiguous) // if return NULL on ambiguity + return setResult(null); + + /* If two imports from C import files, pick first one, as C has global name space + */ + if (s.isCsymbol() && s2.isCsymbol()) + continue; + + if (!(flags & IgnoreErrors)) + ScopeDsymbol.multiplyDefined(loc, s, s2); + break; + } + } + } + } + if (s) + { + /* Build special symbol if we had multiple finds + */ + if (a) + { + if (!s.isOverloadSet()) + a = sds.mergeOverloadSet(ident, a, s); + s = a; + } + //printf("\tfound in imports %s.%s\n", toChars(), s.toChars()); + return setResult(s); + } + //printf(" not found in imports\n"); + return setResult(null); + } + + override void visit(WithScopeSymbol ws) + { + //printf("WithScopeSymbol.search(%s)\n", ident.toChars()); + if (flags & SearchImportsOnly) + return setResult(null); + // Acts as proxy to the with class declaration + Dsymbol s = null; + Expression eold = null; + for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true)) + { + if (auto se = e.isScopeExp()) + { + s = se.sds; + } + else if (e.isTypeExp()) + { + s = e.type.toDsymbol(null); + } + else + { + Type t = e.type.toBasetype(); + s = t.toDsymbol(null); + } + if (s) + { + s = s.search(loc, ident, flags); + if (s) + return setResult(s); + } + eold = e; + } + return setResult(null); + } + + override void visit(ArrayScopeSymbol ass) + { + //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags); + if (ident != Id.dollar) + return setResult(null); + + VarDeclaration* pvar; + Expression ce; + + static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc) + { + + /* $ gives the number of type entries in the type tuple + */ + auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); + Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t); + v._init = new ExpInitializer(Loc.initial, e); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + v.dsymbolSemantic(sc); + return v; + } + + const DYNCAST kind = ass.arrayContent.dyncast(); + switch (kind) with (DYNCAST) + { + case dsymbol: + TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent; + /* $ gives the number of elements in the tuple + */ + auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); + Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t); + v._init = new ExpInitializer(Loc.initial, e); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + v.dsymbolSemantic(ass._scope); + return setResult(v); + case type: + return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope)); + default: + break; + } + Expression exp = cast(Expression) ass.arrayContent; + if (auto ie = exp.isIndexExp()) + { + /* array[index] where index is some function of $ + */ + pvar = &ie.lengthVar; + ce = ie.e1; + } + else if (auto se = exp.isSliceExp()) + { + /* array[lwr .. upr] where lwr or upr is some function of $ + */ + pvar = &se.lengthVar; + ce = se.e1; + } + else if (auto ae = exp.isArrayExp()) + { + /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $ + * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...) + */ + pvar = &ae.lengthVar; + ce = ae.e1; + } + else + { + /* Didn't find $, look in enclosing scope(s). + */ + return setResult(null); + } + ce = ce.lastComma(); + /* If we are indexing into an array that is really a type + * tuple, rewrite this as an index into a type tuple and + * try again. + */ + if (auto te = ce.isTypeExp()) + { + if (auto ttp = te.type.isTypeTuple()) + return setResult(dollarFromTypeTuple(loc, ttp, ass._scope)); + } + /* *pvar is lazily initialized, so if we refer to $ + * multiple times, it gets set only once. + */ + if (!*pvar) // if not already initialized + { + /* Create variable v and set it to the value of $ + */ + VarDeclaration v; + Type t; + if (auto tupexp = ce.isTupleExp()) + { + /* It is for an expression tuple, so the + * length will be a const. + */ + Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t); + v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e)); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + } + else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass)) + { + // Look for opDollar + assert(exp.op == EXP.array || exp.op == EXP.slice); + AggregateDeclaration ad = isAggregate(t); + assert(ad); + Dsymbol s = ad.search(loc, Id.opDollar); + if (!s) // no dollar exists -- search in higher scope + return setResult(null); + s = s.toAlias(); + Expression e = null; + // Check for multi-dimensional opDollar(dim) template. + if (TemplateDeclaration td = s.isTemplateDeclaration()) + { + dinteger_t dim = 0; + if (auto ae = exp.isArrayExp()) + { + dim = ae.currentDimension; + } + else if (exp.isSliceExp()) + { + dim = 0; // slices are currently always one-dimensional + } + else + { + assert(0); + } + auto tiargs = new Objects(); + Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t); + edim = edim.expressionSemantic(ass._scope); + tiargs.push(edim); + e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs); + } + else + { + /* opDollar exists, but it's not a template. + * This is acceptable ONLY for single-dimension indexing. + * Note that it's impossible to have both template & function opDollar, + * because both take no arguments. + */ + auto ae = exp.isArrayExp(); + if (ae && ae.arguments.length != 1) + { + error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars()); + return setResult(null); + } + Declaration d = s.isDeclaration(); + assert(d); + e = new DotVarExp(loc, ce, d); + } + e = e.expressionSemantic(ass._scope); + if (!e.type) + error(exp.loc, "`%s` has no value", e.toChars()); + t = e.type.toBasetype(); + if (t && t.ty == Tfunction) + e = new CallExp(e.loc, e); + v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e)); + v.storage_class |= STC.temp | STC.ctfe | STC.rvalue; + } + else + { + /* For arrays, $ will either be a compile-time constant + * (in which case its value in set during constant-folding), + * or a variable (in which case an expression is created in + * toir.c). + */ + + // https://issues.dlang.org/show_bug.cgi?id=16213 + // For static arrays $ is known at compile time, + // so declare it as a manifest constant. + auto tsa = ce.type ? ce.type.isTypeSArray() : null; + if (tsa) + { + auto e = new ExpInitializer(loc, tsa.dim); + v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest); + } + else + { + auto e = new VoidInitializer(Loc.initial); + e.type = Type.tsize_t; + v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); + v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable + } + } + *pvar = v; + } + (*pvar).dsymbolSemantic(ass._scope); + return setResult((*pvar)); + + } + + override void visit(Import imp) + { + //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags); + if (!imp.pkg) + { + imp.load(null); + imp.mod.importAll(null); + imp.mod.dsymbolSemantic(null); + } + // Forward it to the package/module + return setResult(imp.pkg.search(loc, ident, flags)); + + } + + override void visit(Nspace ns) + { + //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars()); + if (ns._scope && !ns.symtab) + dsymbolSemantic(ns, ns._scope); + + if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called + { + if (!(flags & IgnoreErrors)) + .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars()); + return setResult(null); + } + + visit(cast(ScopeDsymbol)ns); + } + + override void visit(EnumDeclaration em) + { + //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars()); + if (em._scope) + { + // Try one last time to resolve this enum + dsymbolSemantic(em, em._scope); + } + + visit(cast(ScopeDsymbol)em); + } + + override void visit(Package pkg) + { + //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags); + flags &= ~SearchLocalsOnly; // searching an import is always transitive + if (!pkg.isModule() && pkg.mod) + { + // Prefer full package name. + Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null; + if (s) + return setResult(s); + //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars()); + return setResult(pkg.mod.search(loc, ident, flags)); + } + + visit(cast(ScopeDsymbol)pkg); + } + + override void visit(Module m) + { + /* Since modules can be circularly referenced, + * need to stop infinite recursive searches. + * This is done with the cache. + */ + //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch); + if (m.insearch) + return setResult(null); + + /* Qualified module searches always search their imports, + * even if SearchLocalsOnly + */ + if (!(flags & SearchUnqualifiedModule)) + flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly); + + if (m.searchCacheIdent == ident && m.searchCacheFlags == flags) + { + //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", + // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null"); + return setResult(m.searchCacheSymbol); + } + + uint errors = global.errors; + + m.insearch = true; + visit(cast(ScopeDsymbol)m); + Dsymbol s = result; + m.insearch = false; + + if (errors == global.errors) + { + // https://issues.dlang.org/show_bug.cgi?id=10752 + // Can cache the result only when it does not cause + // access error so the side-effect should be reproduced in later search. + m.searchCacheIdent = ident; + m.searchCacheSymbol = s; + m.searchCacheFlags = flags; + } + return setResult(s); + } + + override void visit(Declaration decl) + { + Dsymbol s = null; + if (decl.type) + { + s = decl.type.toDsymbol(decl._scope); + if (s) + s = s.search(loc, ident, flags); + } + return setResult(s); + } + + override void visit(StructDeclaration sd) + { + //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags); + if (sd._scope && !sd.symtab) + dsymbolSemantic(sd, sd._scope); + + if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called + { + // .stringof is always defined (but may be hidden by some other symbol) + if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone) + .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars()); + return setResult(null); + } + + visit(cast(ScopeDsymbol)sd); + } + + override void visit(ClassDeclaration cd) + { + //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags); + //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); + if (cd._scope && cd.baseok < Baseok.semanticdone) + { + if (!cd.inuse) + { + // must semantic on base class/interfaces + cd.inuse = true; + dsymbolSemantic(cd, null); + cd.inuse = false; + } + } + + if (!cd.members || !cd.symtab) // opaque or addMember is not yet done + { + // .stringof is always defined (but may be hidden by some other symbol) + if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone) + cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars()); + //*(char*)0=0; + return setResult(null); + } + + visit(cast(ScopeDsymbol)cd); + auto s = result; + + // don't search imports of base classes + if (flags & SearchImportsOnly) + return setResult(s); + + if (s) + return setResult(s); + + // Search bases classes in depth-first, left to right order + foreach (b; (*cd.baseclasses)[]) + { + if (!b.sym) + continue; + + if (!b.sym.symtab) + { + cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars()); + continue; + } + + import dmd.access : symbolIsVisible; + + s = b.sym.search(loc, ident, flags); + if (!s) + continue; + else if (s == cd) // happens if s is nested in this and derives from this + s = null; + else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s)) + s = null; + else + break; + } + + return setResult(s); + } +} diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 883f4ac..037e0d0 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -69,6 +69,7 @@ import dmd.initsem; import dmd.location; import dmd.mtype; import dmd.opover; +import dmd.optimize; import dmd.root.array; import dmd.common.outbuffer; import dmd.rootobject; @@ -745,7 +746,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol OutBuffer buf; HdrGenState hgs; - buf.writestring(ident.toString()); + buf.writestring(ident == Id.ctor ? "this" : ident.toString()); buf.writeByte('('); foreach (i, const tp; *parameters) { @@ -762,6 +763,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol { TypeFunction tf = cast(TypeFunction)fd.type; buf.writestring(parametersTypeToChars(tf.parameterList)); + if (tf.mod) + { + buf.writeByte(' '); + buf.MODtoBuffer(tf.mod); + } } } diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d index 7c76da9..9f85574 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -20,6 +20,7 @@ import dmd.astenums; import dmd.arraytypes; import dmd.attrib; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.errors; import dmd.globals; import dmd.hdrgen; diff --git a/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d index aa22532..31725c8 100644 --- a/gcc/d/dmd/dversion.d +++ b/gcc/d/dmd/dversion.d @@ -68,43 +68,6 @@ extern (C++) final class DebugSymbol : Dsymbol } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); - Module m = sds.isModule(); - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - if (ident) - { - if (!m) - { - .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - { - if (findCondition(m.debugidsNot, ident)) - { - .error(loc, "%s `%s` defined after use", kind, toPrettyChars); - errors = true; - } - if (!m.debugids) - m.debugids = new Identifiers(); - m.debugids.push(ident); - } - } - else - { - if (!m) - { - .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - m.debuglevel = level; - } - } - override const(char)* kind() const nothrow { return "debug"; @@ -162,44 +125,6 @@ extern (C++) final class VersionSymbol : Dsymbol } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); - Module m = sds.isModule(); - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - if (ident) - { - VersionCondition.checkReserved(loc, ident.toString()); - if (!m) - { - .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - { - if (findCondition(m.versionidsNot, ident)) - { - .error(loc, "%s `%s` defined after use", kind, toPrettyChars); - errors = true; - } - if (!m.versionids) - m.versionids = new Identifiers(); - m.versionids.push(ident); - } - } - else - { - if (!m) - { - .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - m.versionlevel = level; - } - } - override const(char)* kind() const nothrow { return "version"; diff --git a/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h index be12c65..e17e8cf 100644 --- a/gcc/d/dmd/enum.h +++ b/gcc/d/dmd/enum.h @@ -46,12 +46,10 @@ public: bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Type *getType() override; const char *kind() const override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool isDeprecated() const override; // is Dsymbol deprecated? Visibility visible() override; bool isSpecial() const; diff --git a/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d index 3f85ea0..e25fc84 100644 --- a/gcc/d/dmd/escape.d +++ b/gcc/d/dmd/escape.d @@ -25,7 +25,7 @@ import dmd.dsymbol; import dmd.errors; import dmd.expression; import dmd.func; -import dmd.globals; +import dmd.globals : FeatureState; import dmd.id; import dmd.identifier; import dmd.init; @@ -169,7 +169,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) + if (!tf.islive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) return; if (!gag) @@ -377,7 +377,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc)) { result = true; - printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10); + printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), sc.useDIP1000), vPar, 10); } } @@ -1094,7 +1094,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) { if (p == sc.func) { - result |= escapingRef(v, global.params.useDIP1000); + result |= escapingRef(v, sc.useDIP1000); continue; } } @@ -1110,7 +1110,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) { //printf("escaping reference to local ref variable %s\n", v.toChars()); //printf("storage class = x%llx\n", v.storage_class); - result |= escapingRef(v, global.params.useDIP25); + result |= escapingRef(v, sc.useDIP25); continue; } // Don't need to be concerned if v's parent does not return a ref @@ -1125,12 +1125,12 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) const(char)* msg = "storing reference to outer local variable `%s` into allocated memory causes it to escape"; if (!gag) { - previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars()); + previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars()); } // If -preview=dip25 is used, the user wants an error // Otherwise, issue a deprecation - result |= (global.params.useDIP25 == FeatureState.enabled); + result |= (sc.useDIP25 == FeatureState.enabled); } } @@ -1264,7 +1264,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) // https://issues.dlang.org/show_bug.cgi?id=23191 if (!gag) { - previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)(e.loc, + previewErrorFunc(sc.isDeprecated(), sc.useDIP1000)(e.loc, "scope parameter `%s` may not be returned", v.toChars() ); result = true; @@ -1403,7 +1403,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) { //printf("escaping reference to local ref variable %s\n", v.toChars()); //printf("storage class = x%llx\n", v.storage_class); - escapingRef(v, global.params.useDIP25); + escapingRef(v, sc.useDIP25); continue; } // Don't need to be concerned if v's parent does not return a ref @@ -1415,7 +1415,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) { const(char)* msg = "escaping reference to outer local variable `%s`"; if (!gag) - previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars()); + previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars()); result = true; continue; } @@ -2588,7 +2588,7 @@ public bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1, arg2); + return setUnsafePreview(sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2); } /*************************************** diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 87611f4..cd93e54 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -18,25 +18,19 @@ import core.stdc.stdio; import core.stdc.string; import dmd.aggregate; -import dmd.aliasthis; -import dmd.arrayop; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; import dmd.gluelayer; -import dmd.ctfeexpr; -import dmd.ctorflow; import dmd.dclass; import dmd.declaration; import dmd.dimport; import dmd.dmodule; -import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; import dmd.dtemplate; import dmd.errors; import dmd.errorsink; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.hdrgen; @@ -45,39 +39,20 @@ import dmd.identifier; import dmd.init; import dmd.location; import dmd.mtype; -import dmd.opover; -import dmd.optimize; import dmd.root.complex; import dmd.root.ctfloat; -import dmd.root.filename; import dmd.common.outbuffer; import dmd.root.optional; import dmd.root.rmem; import dmd.rootobject; import dmd.root.string; import dmd.root.utf; -import dmd.safe; import dmd.target; import dmd.tokens; import dmd.visitor; enum LOGSEMANTIC = false; -void emplaceExp(T : Expression, Args...)(void* p, Args args) -{ - static if (__VERSION__ < 2099) - const init = typeid(T).initializer; - else - const init = __traits(initSymbol, T); - p[0 .. __traits(classInstanceSize, T)] = init[]; - (cast(T)p).__ctor(args); -} - -void emplaceExp(T : UnionExp)(T* p, Expression e) -{ - memcpy(p, cast(void*)e, e.size); -} - /// Return value for `checkModifiable` enum Modifiable { @@ -118,45 +93,6 @@ inout(Expression) lastComma(inout Expression e) } -/*********************************** - * Determine if a `this` is needed to access `d`. - * Params: - * sc = context - * d = declaration to check - * Returns: - * true means a `this` is needed - */ -bool isNeedThisScope(Scope* sc, Declaration d) -{ - if (sc.intypeof == 1) - return false; - - AggregateDeclaration ad = d.isThis(); - if (!ad) - return false; - //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars()); - - for (Dsymbol s = sc.parent; s; s = s.toParentLocal()) - { - //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2()); - if (AggregateDeclaration ad2 = s.isAggregateDeclaration()) - { - if (ad2 == ad) - return false; - else if (ad2.isNested()) - continue; - else - return true; - } - if (FuncDeclaration f = s.isFuncDeclaration()) - { - if (f.isMemberLocal()) - break; - } - } - return true; -} - /**************************************** * Expand tuples in-place. * @@ -315,70 +251,6 @@ TemplateDeclaration getFuncTemplateDecl(Dsymbol s) @safe return null; } -/****************************************************************/ -/* A type meant as a union of all the Expression types, - * to serve essentially as a Variant that will sit on the stack - * during CTFE to reduce memory consumption. - */ -extern (D) struct UnionExp -{ - // yes, default constructor does nothing - extern (D) this(Expression e) - { - memcpy(&this, cast(void*)e, e.size); - } - - /* Extract pointer to Expression - */ - extern (D) Expression exp() return - { - return cast(Expression)&u; - } - - /* Convert to an allocated Expression - */ - extern (D) Expression copy() - { - Expression e = exp(); - //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr); - assert(e.size <= u.sizeof); - switch (e.op) - { - case EXP.cantExpression: return CTFEExp.cantexp; - case EXP.voidExpression: return CTFEExp.voidexp; - case EXP.break_: return CTFEExp.breakexp; - case EXP.continue_: return CTFEExp.continueexp; - case EXP.goto_: return CTFEExp.gotoexp; - default: return e.copy(); - } - } - -private: - // Ensure that the union is suitably aligned. - align(8) union _AnonStruct_u - { - char[__traits(classInstanceSize, Expression)] exp; - char[__traits(classInstanceSize, IntegerExp)] integerexp; - char[__traits(classInstanceSize, ErrorExp)] errorexp; - char[__traits(classInstanceSize, RealExp)] realexp; - char[__traits(classInstanceSize, ComplexExp)] complexexp; - char[__traits(classInstanceSize, SymOffExp)] symoffexp; - char[__traits(classInstanceSize, StringExp)] stringexp; - char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp; - char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp; - char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp; - char[__traits(classInstanceSize, CompoundLiteralExp)] compoundliteralexp; - char[__traits(classInstanceSize, NullExp)] nullexp; - char[__traits(classInstanceSize, DotVarExp)] dotvarexp; - char[__traits(classInstanceSize, AddrExp)] addrexp; - char[__traits(classInstanceSize, IndexExp)] indexexp; - char[__traits(classInstanceSize, SliceExp)] sliceexp; - char[__traits(classInstanceSize, VectorExp)] vectorexp; - } - - _AnonStruct_u u; -} - /************************ TypeDotIdExp ************************************/ /* Things like: * int.size @@ -678,71 +550,6 @@ extern (C++) abstract class Expression : ASTNode return false; } - /******************************* - * Give error if we're not an lvalue. - * If we can, convert expression to be an lvalue. - */ - Expression toLvalue(Scope* sc, Expression e) - { - if (!e) - e = this; - else if (!loc.isValid()) - loc = e.loc; - - if (e.op == EXP.type) - error(loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind()); - else - error(loc, "`%s` is not an lvalue and cannot be modified", e.toChars()); - - return ErrorExp.get(); - } - - Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars()); - // See if this expression is a modifiable lvalue (i.e. not const) - if (checkModifiable(this, sc) == Modifiable.yes) - { - assert(type); - if (!type.isMutable()) - { - if (auto dve = this.isDotVarExp()) - { - if (isNeedThisScope(sc, dve.var)) - for (Dsymbol s = sc.func; s; s = s.toParentLocal()) - { - FuncDeclaration ff = s.isFuncDeclaration(); - if (!ff) - break; - if (!ff.type.isMutable) - { - error(loc, "cannot modify `%s` in `%s` function", toChars(), MODtoChars(type.mod)); - return ErrorExp.get(); - } - } - } - error(loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), toChars()); - return ErrorExp.get(); - } - else if (!type.isAssignable()) - { - error(loc, "cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members", - toChars(), type.toChars()); - return ErrorExp.get(); - } - } - return toLvalue(sc, e); - } - - /**************************************** - * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc. - */ - Expression resolveLoc(const ref Loc loc, Scope* sc) - { - this.loc = loc; - return this; - } - /**************************************** * Check that the expression has a valid type. * If not, generates an error "... has no type". @@ -835,417 +642,6 @@ extern (C++) abstract class Expression : ASTNode return checkValue(); } - extern (D) final bool checkDeprecated(Scope* sc, Dsymbol s) - { - return s.checkDeprecated(loc, sc); - } - - extern (D) final bool checkDisabled(Scope* sc, Dsymbol s) - { - if (auto d = s.isDeclaration()) - { - return d.checkDisabled(loc, sc); - } - - return false; - } - - /********************************************* - * Calling function f. - * Check the purity, i.e. if we're in a pure function - * we can only call other pure functions. - * Returns true if error occurs. - */ - extern (D) final bool checkPurity(Scope* sc, FuncDeclaration f) - { - if (!sc.func) - return false; - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; - - // If the call has a pure parent, then the called func must be pure. - if (!f.isPure() && checkImpure(sc, loc, null, f)) - { - error(loc, "`pure` %s `%s` cannot call impure %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), - f.toPrettyChars()); - - if (!f.isDtorDeclaration()) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); - return true; - } - return false; - } - - /** - * Checks whether `f` is a generated `DtorDeclaration` that hides a user-defined one - * which passes `check` while `f` doesn't (e.g. when the user defined dtor is pure but - * the generated dtor is not). - * In that case the method will identify and print all members causing the attribute - * missmatch. - * - * Params: - * sc = scope - * f = potential `DtorDeclaration` - * check = current check (e.g. whether it's pure) - * checkName = the kind of check (e.g. `"pure"`) - */ - extern (D) final void checkOverriddenDtor(Scope* sc, FuncDeclaration f, - scope bool function(DtorDeclaration) check, const string checkName - ) { - auto dd = f.isDtorDeclaration(); - if (!dd || !dd.isGenerated()) - return; - - // DtorDeclaration without parents should fail at an earlier stage - auto ad = cast(AggregateDeclaration) f.toParent2(); - assert(ad); - - if (ad.userDtors.length) - { - if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well) - return; - - // Sanity check - assert(!check(ad.fieldDtor)); - } - - dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:", - dd.isGenerated() ? "generated " : "".ptr, - ad.toChars, - cast(int) checkName.length, checkName.ptr); - - // Search for the offending fields - foreach (field; ad.fields) - { - // Only structs may define automatically called destructors - auto ts = field.type.isTypeStruct(); - if (!ts) - { - // But they might be part of a static array - auto ta = field.type.isTypeSArray(); - if (!ta) - continue; - - ts = ta.baseElemOf().isTypeStruct(); - if (!ts) - continue; - } - - auto fieldSym = ts.toDsymbol(sc); - assert(fieldSym); // Resolving ts must succeed because missing defs. should error before - - auto fieldSd = fieldSym.isStructDeclaration(); - assert(fieldSd); // ts is a TypeStruct, this would imply a malformed ASR - - if (fieldSd.dtor && !check(fieldSd.dtor)) - { - field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars()); - - if (fieldSd.dtor.isGenerated()) - checkOverriddenDtor(sc, fieldSd.dtor, check, checkName); - else - fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here", - cast(int) checkName.length, checkName.ptr, fieldSd.toChars()); - } - } - } - - /******************************************* - * Accessing variable v. - * Check for purity and safety violations. - * Returns true if error occurs. - */ - extern (D) final bool checkPurity(Scope* sc, VarDeclaration v) - { - //printf("v = %s %s\n", v.type.toChars(), v.toChars()); - /* Look for purity and safety violations when accessing variable v - * from current function. - */ - if (!sc.func) - return false; - if (sc.intypeof == 1) - return false; // allow violations inside typeof(expression) - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; // allow violations inside compile-time evaluated expressions and debug conditionals - if (v.ident == Id.ctfe) - return false; // magic variable never violates pure and safe - if (v.isImmutable()) - return false; // always safe and pure to access immutables... - if (v.isConst() && !v.isReference() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf())) - return false; // or const global/parameter values which have no mutable indirections - if (v.storage_class & STC.manifest) - return false; // ...or manifest constants - - // accessing empty structs is pure - // https://issues.dlang.org/show_bug.cgi?id=18694 - // https://issues.dlang.org/show_bug.cgi?id=21464 - // https://issues.dlang.org/show_bug.cgi?id=23589 - if (v.type.ty == Tstruct) - { - StructDeclaration sd = (cast(TypeStruct)v.type).sym; - if (sd.members) // not opaque - { - if (sd.semanticRun >= PASS.semanticdone) - sd.determineSize(v.loc); - if (sd.hasNoFields) - return false; - } - } - - bool err = false; - if (v.isDataseg()) - { - // https://issues.dlang.org/show_bug.cgi?id=7533 - // Accessing implicit generated __gate is pure. - if (v.ident == Id.gate) - return false; - - if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v)) - { - error(loc, "`pure` %s `%s` cannot access mutable static data `%s`", - sc.func.kind(), sc.func.toPrettyChars(), v.toChars()); - err = true; - } - } - else - { - /* Given: - * void f() { - * int fx; - * pure void g() { - * int gx; - * /+pure+/ void h() { - * int hx; - * /+pure+/ void i() { } - * } - * } - * } - * i() can modify hx and gx but not fx - */ - - Dsymbol vparent = v.toParent2(); - for (Dsymbol s = sc.func; !err && s; s = s.toParentP(vparent)) - { - if (s == vparent) - break; - - if (AggregateDeclaration ad = s.isAggregateDeclaration()) - { - if (ad.isNested()) - continue; - break; - } - FuncDeclaration ff = s.isFuncDeclaration(); - if (!ff) - break; - if (ff.isNested() || ff.isThis()) - { - if (ff.type.isImmutable() || - ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod)) - { - OutBuffer ffbuf; - OutBuffer vbuf; - MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod); - MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod); - error(loc, "%s%s `%s` cannot access %sdata `%s`", - ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars()); - err = true; - break; - } - continue; - } - break; - } - } - - /* Do not allow safe functions to access __gshared data - */ - if (v.storage_class & STC.gshared) - { - if (sc.setUnsafe(false, this.loc, - "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) - { - err = true; - } - } - - return err; - } - - /* - Check if sc.func is impure or can be made impure. - Returns true on error, i.e. if sc.func is pure and cannot be made impure. - */ - private static bool checkImpure(Scope* sc, Loc loc, const(char)* fmt, RootObject arg0) - { - return sc.func && (isRootTraitsCompilesScope(sc) - ? sc.func.isPureBypassingInference() >= PURE.weak - : sc.func.setImpure(loc, fmt, arg0)); - } - - /********************************************* - * Calling function f. - * Check the safety, i.e. if we're in a @safe function - * we can only call @safe or @trusted functions. - * Returns true if error occurs. - */ - extern (D) final bool checkSafety(Scope* sc, FuncDeclaration f) - { - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & SCOPE.debug_) - return false; - if ((sc.flags & SCOPE.ctfe) && sc.func) - return false; - - if (!sc.func) - { - if (sc.varDecl && !f.safetyInprocess && !f.isSafe() && !f.isTrusted()) - { - if (sc.varDecl.storage_class & STC.safe) - { - error(loc, "`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`", - sc.varDecl.toChars(), f.toChars()); - return true; - } - else - { - sc.varDecl.storage_class |= STC.system; - sc.varDecl.systemInferred = true; - } - } - return false; - } - - if (!f.isSafe() && !f.isTrusted()) - { - if (isRootTraitsCompilesScope(sc) ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) - { - if (!loc.isValid()) // e.g. implicitly generated dtor - loc = sc.func.loc; - - const prettyChars = f.toPrettyChars(); - error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), - prettyChars); - if (!f.isDtorDeclaration) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); - .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); - - return true; - } - } - else if (f.isSafe() && f.safetyViolation) - { - // for dip1000 by default transition, print deprecations for calling functions that will become `@system` - if (sc.func.isSafeBypassingInference()) - { - .deprecation(this.loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); - errorSupplementalInferredAttr(f, 10, true, STC.safe); - } - else if (!sc.func.safetyViolation) - { - import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null, null); - } - } - return false; - } - - /********************************************* - * Calling function f. - * Check the @nogc-ness, i.e. if we're in a @nogc function - * we can only call other @nogc functions. - * Returns true if error occurs. - */ - extern (D) final bool checkNogc(Scope* sc, FuncDeclaration f) - { - if (!sc.func) - return false; - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; - /* The original expressions (`new S(...)` or `new S[...]``) will be - * verified instead. This is to keep errors related to the original code - * and not the lowering. - */ - if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT) - return false; - - if (!f.isNogc()) - { - if (isRootTraitsCompilesScope(sc) ? sc.func.isNogcBypassingInference() : sc.func.setGCCall(f)) - { - if (loc.linnum == 0) // e.g. implicitly generated dtor - loc = sc.func.loc; - - // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)), - // so don't print anything to avoid double error messages. - if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT - || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX - || f.ident == Id._d_arraycatnTX || f.ident == Id._d_newclassT)) - { - error(loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); - - if (!f.isDtorDeclaration) - f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); - } - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); - - return true; - } - } - return false; - } - - /******************************************** - * Check that the postblit is callable if t is an array of structs. - * Returns true if error happens. - */ - extern (D) final bool checkPostblit(Scope* sc, Type t) - { - if (auto ts = t.baseElemOf().isTypeStruct()) - { - if (global.params.useTypeInfo && Type.dtypeinfo) - { - // https://issues.dlang.org/show_bug.cgi?id=11395 - // Require TypeInfo generation for array concatenation - semanticTypeInfo(sc, t); - } - - StructDeclaration sd = ts.sym; - if (sd.postblit) - { - if (sd.postblit.checkDisabled(loc, sc)) - return true; - - //checkDeprecated(sc, sd.postblit); // necessary? - checkPurity(sc, sd.postblit); - checkSafety(sc, sd.postblit); - checkNogc(sc, sd.postblit); - //checkAccess(sd, loc, sc, sd.postblit); // necessary? - return false; - } - } - return false; - } - /******************************* * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) @@ -1308,11 +704,6 @@ extern (C++) abstract class Expression : ASTNode return this; } - final Expression optimize(int result, bool keepLvalue = false) - { - return Expression_optimize(this, result, keepLvalue); - } - final int isConst() { //printf("Expression::isConst(): %s\n", e.toChars()); @@ -1587,16 +978,6 @@ extern (C++) final class IntegerExp : Expression return typeof(return)(r); } - override Expression toLvalue(Scope* sc, Expression e) - { - if (!e) - e = this; - else if (!loc.isValid()) - loc = e.loc; - error(e.loc, "cannot modify constant `%s`", e.toChars()); - return ErrorExp.get(); - } - override void accept(Visitor v) { v.visit(this); @@ -1722,7 +1103,7 @@ extern (C++) final class IntegerExp : Expression */ extern (C++) final class ErrorExp : Expression { - private extern (D) this() + extern (D) this() { super(Loc.initial, EXP.error); type = Type.terror; @@ -1745,11 +1126,6 @@ extern (C++) final class ErrorExp : Expression return errorexp; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -1987,11 +1363,6 @@ extern (C++) class IdentifierExp : Expression return true; } - override final Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2036,11 +1407,6 @@ extern (C++) final class DsymbolExp : Expression return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2087,16 +1453,6 @@ extern (C++) class ThisExp : Expression return type.toBasetype().ty != Tclass; } - override final Expression toLvalue(Scope* sc, Expression e) - { - if (type.toBasetype().ty == Tclass) - { - // Class `this` is an rvalue; struct `this` is an lvalue. - return Expression.toLvalue(sc, e); - } - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2464,18 +1820,6 @@ extern (C++) final class StringExp : Expression return (type && type.toBasetype().ty == Tsarray); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type.toChars() : NULL); - return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e); - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - error(loc, "cannot modify string literal `%s`", toChars()); - return ErrorExp.get(); - } - /******************************** * Convert string contents to a 0 terminated string, * allocated by mem.xmalloc(). @@ -3050,14 +2394,6 @@ extern (C++) final class StructLiteralExp : Expression return -1; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (sc.flags & SCOPE.Cfile) - return this; // C struct literals are lvalues - else - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -3203,15 +2539,6 @@ extern (C++) final class TemplateExp : Expression return fd !is null; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (!fd) - return Expression.toLvalue(sc, e); - - assert(sc); - return symbolToExp(fd, loc, sc, true); - } - override bool checkType() { error(loc, "%s `%s` has no type", td.kind(), toChars()); @@ -3409,43 +2736,6 @@ extern (C++) final class VarExp : SymbolExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (var.storage_class & STC.manifest) - { - error(loc, "manifest constant `%s` cannot be modified", var.toChars()); - return ErrorExp.get(); - } - if (var.storage_class & STC.lazy_ && !delegateWasExtracted) - { - error(loc, "lazy variable `%s` cannot be modified", var.toChars()); - return ErrorExp.get(); - } - if (var.ident == Id.ctfe) - { - error(loc, "cannot modify compiler-generated variable `__ctfe`"); - return ErrorExp.get(); - } - if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574 - { - error(loc, "cannot modify operator `$`"); - return ErrorExp.get(); - } - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); - if (var.storage_class & STC.manifest) - { - error(loc, "cannot modify manifest constant `%s`", toChars()); - return ErrorExp.get(); - } - // See if this expression is a modifiable lvalue (i.e. not const) - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -3472,11 +2762,6 @@ extern (C++) final class OverExp : Expression return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -3522,52 +2807,6 @@ extern (C++) final class FuncExp : Expression return false; } - extern (D) void genIdent(Scope* sc) - { - if (fd.ident == Id.empty) - { - const(char)[] s; - if (fd.fes) - s = "__foreachbody"; - else if (fd.tok == TOK.reserved) - s = "__lambda"; - else if (fd.tok == TOK.delegate_) - s = "__dgliteral"; - else - s = "__funcliteral"; - - DsymbolTable symtab; - if (FuncDeclaration func = sc.parent.isFuncDeclaration()) - { - if (func.localsymtab is null) - { - // Inside template constraint, symtab is not set yet. - // Initialize it lazily. - func.localsymtab = new DsymbolTable(); - } - symtab = func.localsymtab; - } - else - { - ScopeDsymbol sds = sc.parent.isScopeDsymbol(); - if (!sds.symtab) - { - // Inside template constraint, symtab may not be set yet. - // Initialize it lazily. - assert(sds.isTemplateInstance()); - sds.symtab = new DsymbolTable(); - } - symtab = sds.symtab; - } - assert(symtab); - Identifier id = Identifier.generateId(s, symtab.length() + 1); - fd.ident = id; - if (td) - td.ident = id; - symtab.insert(td ? cast(Dsymbol)td : cast(Dsymbol)fd); - } - } - override FuncExp syntaxCopy() { if (td) @@ -3815,12 +3054,6 @@ extern (C++) abstract class UnaExp : Expression } - override final Expression resolveLoc(const ref Loc loc, Scope* sc) - { - e1 = e1.resolveLoc(loc, sc); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -3936,18 +3169,6 @@ extern (C++) class BinAssignExp : BinExp return true; } - override final Expression toLvalue(Scope* sc, Expression ex) - { - // Lvalue-ness will be handled in glue layer. - return this; - } - - override final Expression modifiableLvalue(Scope* sc, Expression e) - { - // should check e1.checkModifiable() ? - return toLvalue(sc, this); - } - override void accept(Visitor v) { v.visit(this); @@ -4156,58 +3377,6 @@ extern (C++) final class DotVarExp : UnaExp return !(vd && vd.isField()); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("DotVarExp::toLvalue(%s)\n", toChars()); - if (sc && sc.flags & SCOPE.Cfile) - { - /* C11 6.5.2.3-3: A postfix expression followed by the '.' or '->' operator - * is an lvalue if the first expression is an lvalue. - */ - if (!e1.isLvalue()) - return Expression.toLvalue(sc, e); - } - if (!isLvalue()) - return Expression.toLvalue(sc, e); - if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor)) - { - if (VarDeclaration vd = var.isVarDeclaration()) - { - auto ad = vd.isMember2(); - if (ad && ad.fields.length == sc.ctorflow.fieldinit.length) - { - foreach (i, f; ad.fields) - { - if (f == vd) - { - if (!(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor)) - { - /* If the address of vd is taken, assume it is thereby initialized - * https://issues.dlang.org/show_bug.cgi?id=15869 - */ - modifyFieldVar(loc, sc, vd, e1); - } - break; - } - } - } - } - } - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - version (none) - { - printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); - printf("e1.type = %s\n", e1.type.toChars()); - printf("var.type = %s\n", var.type.toChars()); - } - - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4239,49 +3408,6 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp return new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs)); } - extern (D) bool findTempDecl(Scope* sc) - { - static if (LOGSEMANTIC) - { - printf("DotTemplateInstanceExp::findTempDecl('%s')\n", toChars()); - } - if (ti.tempdecl) - return true; - - Expression e = new DotIdExp(loc, e1, ti.name); - e = e.expressionSemantic(sc); - if (e.op == EXP.dot) - e = (cast(DotExp)e).e2; - - Dsymbol s = null; - switch (e.op) - { - case EXP.overloadSet: - s = (cast(OverExp)e).vars; - break; - - case EXP.dotTemplateDeclaration: - s = (cast(DotTemplateExp)e).td; - break; - - case EXP.scope_: - s = (cast(ScopeExp)e).sds; - break; - - case EXP.dotVariable: - s = (cast(DotVarExp)e).var; - break; - - case EXP.variable: - s = (cast(VarExp)e).var; - break; - - default: - return false; - } - return ti.updateTempDecl(sc, s); - } - override bool checkType() { // Same logic as ScopeExp.checkType() @@ -4486,13 +3612,6 @@ extern (C++) final class CallExp : UnaExp return false; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4600,30 +3719,6 @@ extern (C++) final class PtrExp : UnaExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type.toChars()); - Declaration var; - if (auto se = e1.isSymOffExp()) - var = se.var; - else if (auto ve = e1.isVarExp()) - var = ve.var; - if (var && var.type.isFunction_Delegate_PtrToFunction()) - { - if (var.type.isTypeFunction()) - error(loc, "function `%s` is not an lvalue and cannot be modified", var.toChars()); - else - error(loc, "function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars()); - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4755,19 +3850,6 @@ extern (C++) final class CastExp : UnaExp e1.type.mutableOf().unSharedOf().equals(to.mutableOf().unSharedOf()); } - override Expression toLvalue(Scope* sc, Expression e) - { - if (sc && sc.flags & SCOPE.Cfile) - { - /* C11 6.5.4-5: A cast does not yield an lvalue. - */ - return Expression.toLvalue(sc, e); - } - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4822,12 +3904,6 @@ extern (C++) final class VectorArrayExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -4885,18 +3961,6 @@ extern (C++) final class SliceExp : UnaExp return (type && type.toBasetype().ty == Tsarray); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type.toChars() : NULL); - return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e); - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - error(loc, "slice expression `%s` is not a modifiable lvalue", toChars()); - return this; - } - override Optional!bool toBool() { return e1.toBool(); @@ -4964,13 +4028,6 @@ extern (C++) final class ArrayExp : UnaExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (type && type.toBasetype().ty == Tvoid) - error(loc, "`void`s have no value"); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -5018,18 +4075,6 @@ extern (C++) final class CommaExp : BinExp return e2.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e2 = e2.toLvalue(sc, null); - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - e2 = e2.modifiableLvalue(sc, e); - return this; - } - override Optional!bool toBool() { return e2.toBool(); @@ -5105,21 +4150,6 @@ extern (C++) final class DelegatePtrExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (sc.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this)) - { - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -5143,21 +4173,6 @@ extern (C++) final class DelegateFuncptrExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (sc.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this)) - { - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -5205,23 +4220,6 @@ extern (C++) final class IndexExp : BinExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); - Expression ex = markSettingAAElem(); - if (ex.op == EXP.error) - return ex; - - return Expression.modifiableLvalue(sc, e); - } - extern (D) Expression markSettingAAElem() { if (e1.type.toBasetype().ty == Taarray) @@ -5324,20 +4322,6 @@ extern (C++) class AssignExp : BinExp return true; } - override final Expression toLvalue(Scope* sc, Expression ex) - { - if (e1.op == EXP.slice || e1.op == EXP.arrayLength) - { - return Expression.toLvalue(sc, ex); - } - - /* In front-end level, AssignExp should make an lvalue of e1. - * Taking the address of e1 will be handled in low level layer, - * so this function does nothing. - */ - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -5633,7 +4617,9 @@ extern (C++) final class UshrAssignExp : BinAssignExp */ extern (C++) class CatAssignExp : BinAssignExp { - extern (D) this(const ref Loc loc, Expression e1, Expression e2) @safe + Expression lowering; // lowered druntime hook `_d_arrayappend{cTX,T}` + + extern (D) this(const ref Loc loc, Expression e1, Expression e2) { super(loc, EXP.concatenateAssign, e1, e2); } @@ -5733,13 +4719,6 @@ extern (C++) final class CatExp : BinExp super(loc, EXP.concatenate, e1, e2); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - e1 = e1.resolveLoc(loc, sc); - e2 = e2.resolveLoc(loc, sc); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -6074,28 +5053,6 @@ extern (C++) final class CondExp : BinExp return e1.isLvalue() && e2.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression ex) - { - // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) - CondExp e = cast(CondExp)copy(); - e.e1 = e1.toLvalue(sc, null).addressOf(); - e.e2 = e2.toLvalue(sc, null).addressOf(); - e.type = type.pointerTo(); - return new PtrExp(loc, e, type); - } - - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (!e1.isLvalue() && !e2.isLvalue()) - { - error(loc, "conditional expression `%s` is not a modifiable lvalue", toChars()); - return ErrorExp.get(); - } - e1 = e1.modifiableLvalue(sc, e1); - e2 = e2.modifiableLvalue(sc, e2); - return toLvalue(sc, this); - } - override void accept(Visitor v) { v.visit(this); @@ -6145,19 +5102,6 @@ extern (C++) final class FileInitExp : DefaultInitExp super(loc, tok); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - //printf("FileInitExp::resolve() %s\n", toChars()); - const(char)* s; - if (op == EXP.fileFullPath) - s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars()); - else - s = loc.isValid() ? loc.filename : sc._module.ident.toChars(); - - Expression e = new StringExp(loc, s.toDString()); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -6174,12 +5118,6 @@ extern (C++) final class LineInitExp : DefaultInitExp super(loc, EXP.line); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -6196,13 +5134,6 @@ extern (C++) final class ModuleInitExp : DefaultInitExp super(loc, EXP.moduleString); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString(); - Expression e = new StringExp(loc, s); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -6219,19 +5150,6 @@ extern (C++) final class FuncInitExp : DefaultInitExp super(loc, EXP.functionString); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - const(char)* s; - if (sc.callsc && sc.callsc.func) - s = sc.callsc.func.Dsymbol.toPrettyChars(); - else if (sc.func) - s = sc.func.Dsymbol.toPrettyChars(); - else - s = ""; - Expression e = new StringExp(loc, s.toDString()); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -6248,29 +5166,153 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp super(loc, EXP.prettyFunction); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) + override void accept(Visitor v) { - FuncDeclaration fd = (sc.callsc && sc.callsc.func) - ? sc.callsc.func - : sc.func; + v.visit(this); + } +} + +/*********************************************************** + * A reference to a class, or an interface. We need this when we + * point to a base class (we must record what the type is). + */ +extern (C++) final class ClassReferenceExp : Expression +{ + StructLiteralExp value; - const(char)* s; - if (fd) + extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe + { + super(loc, EXP.classReference); + assert(lit && lit.sd && lit.sd.isClassDeclaration()); + this.value = lit; + this.type = type; + } + + ClassDeclaration originalClass() + { + return value.sd.isClassDeclaration(); + } + + // Return index of the field, or -1 if not found + int getFieldIndex(Type fieldtype, uint fieldoffset) + { + ClassDeclaration cd = originalClass(); + uint fieldsSoFar = 0; + for (size_t j = 0; j < value.elements.length; j++) { - const funcStr = fd.Dsymbol.toPrettyChars(); - OutBuffer buf; - functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic); - s = buf.extractChars(); + while (j - fieldsSoFar >= cd.fields.length) + { + fieldsSoFar += cd.fields.length; + cd = cd.baseClass; + } + VarDeclaration v2 = cd.fields[j - fieldsSoFar]; + if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size()) + { + return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar)); + } } - else + return -1; + } + + // Return index of the field, or -1 if not found + // Same as getFieldIndex, but checks for a direct match with the VarDeclaration + int findFieldIndexByName(VarDeclaration v) + { + ClassDeclaration cd = originalClass(); + size_t fieldsSoFar = 0; + for (size_t j = 0; j < value.elements.length; j++) { - s = ""; + while (j - fieldsSoFar >= cd.fields.length) + { + fieldsSoFar += cd.fields.length; + cd = cd.baseClass; + } + VarDeclaration v2 = cd.fields[j - fieldsSoFar]; + if (v == v2) + { + return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar)); + } } + return -1; + } - Expression e = new StringExp(loc, s.toDString()); - e = e.expressionSemantic(sc); - e.type = Type.tstring; - return e; + override void accept(Visitor v) + { + v.visit(this); + } +} + +/*********************************************************** + * This type is only used by the interpreter. + */ +extern (C++) final class CTFEExp : Expression +{ + extern (D) this(EXP tok) + { + super(Loc.initial, tok); + type = Type.tvoid; + } + + override const(char)* toChars() const + { + switch (op) + { + case EXP.cantExpression: + return "<cant>"; + case EXP.voidExpression: + return "cast(void)0"; + case EXP.showCtfeContext: + return "<error>"; + case EXP.break_: + return "<break>"; + case EXP.continue_: + return "<continue>"; + case EXP.goto_: + return "<goto>"; + default: + assert(0); + } + } + + extern (D) __gshared CTFEExp cantexp; + extern (D) __gshared CTFEExp voidexp; + extern (D) __gshared CTFEExp breakexp; + extern (D) __gshared CTFEExp continueexp; + extern (D) __gshared CTFEExp gotoexp; + /* Used when additional information is needed regarding + * a ctfe error. + */ + extern (D) __gshared CTFEExp showcontext; + + extern (D) static bool isCantExp(const Expression e) @safe + { + return e && e.op == EXP.cantExpression; + } + + extern (D) static bool isGotoExp(const Expression e) @safe + { + return e && e.op == EXP.goto_; + } +} + +/*********************************************************** + * Fake class which holds the thrown exception. + * Used for implementing exception handling. + */ +extern (C++) final class ThrownExceptionExp : Expression +{ + ClassReferenceExp thrown; // the thing being tossed + + extern (D) this(const ref Loc loc, ClassReferenceExp victim) @safe + { + super(loc, EXP.thrownException); + this.thrown = victim; + this.type = victim.type; + } + + override const(char)* toChars() const + { + return "CTFE ThrownException"; } override void accept(Visitor v) @@ -6330,154 +5372,6 @@ extern (C++) final class GenericExp : Expression } } -/*************************************** - * Parameters: - * sc: scope - * flag: 1: do not issue error message for invalid modification - 2: the exp is a DotVarExp and a subfield of the leftmost - variable is modified - * Returns: - * Whether the type is modifiable - */ -extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyFlags.none) -{ - switch(exp.op) - { - case EXP.variable: - auto varExp = cast(VarExp)exp; - - //printf("VarExp::checkModifiable %s", varExp.toChars()); - assert(varExp.type); - return varExp.var.checkModify(varExp.loc, sc, null, flag); - - case EXP.dotVariable: - auto dotVarExp = cast(DotVarExp)exp; - - //printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars()); - if (dotVarExp.e1.op == EXP.this_) - return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag); - - /* https://issues.dlang.org/show_bug.cgi?id=12764 - * If inside a constructor and an expression of type `this.field.var` - * is encountered, where `field` is a struct declaration with - * default construction disabled, we must make sure that - * assigning to `var` does not imply that `field` was initialized - */ - if (sc.func && sc.func.isCtorDeclaration()) - { - // if inside a constructor scope and e1 of this DotVarExp - // is another DotVarExp, then check if the leftmost expression is a `this` identifier - if (auto dve = dotVarExp.e1.isDotVarExp()) - { - // Iterate the chain of DotVarExp to find `this` - // Keep track whether access to fields was limited to union members - // s.t. one can initialize an entire struct inside nested unions - // (but not its members) - bool onlyUnion = true; - while (true) - { - auto v = dve.var.isVarDeclaration(); - assert(v); - - // Accessing union member? - auto t = v.type.isTypeStruct(); - if (!t || !t.sym.isUnionDeclaration()) - onlyUnion = false; - - // Another DotVarExp left? - if (!dve.e1 || dve.e1.op != EXP.dotVariable) - break; - - dve = cast(DotVarExp) dve.e1; - } - - if (dve.e1.op == EXP.this_) - { - scope v = dve.var.isVarDeclaration(); - /* if v is a struct member field with no initializer, no default construction - * and v wasn't intialized before - */ - if (v && v.isField() && !v._init && !v.ctorinit) - { - if (auto ts = v.type.isTypeStruct()) - { - if (ts.sym.noDefaultCtor) - { - /* checkModify will consider that this is an initialization - * of v while it is actually an assignment of a field of v - */ - scope modifyLevel = v.checkModify(dotVarExp.loc, sc, dve.e1, !onlyUnion ? (flag | ModifyFlags.fieldAssign) : flag); - if (modifyLevel == Modifiable.initialization) - { - // https://issues.dlang.org/show_bug.cgi?id=22118 - // v is a union type field that was assigned - // a variable, therefore it counts as initialization - if (v.ctorinit) - return Modifiable.initialization; - - return Modifiable.yes; - } - return modifyLevel; - } - } - } - } - } - } - - //printf("\te1 = %s\n", e1.toChars()); - return dotVarExp.e1.checkModifiable(sc, flag); - - case EXP.star: - auto ptrExp = cast(PtrExp)exp; - if (auto se = ptrExp.e1.isSymOffExp()) - { - return se.var.checkModify(ptrExp.loc, sc, null, flag); - } - else if (auto ae = ptrExp.e1.isAddrExp()) - { - return ae.e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.slice: - auto sliceExp = cast(SliceExp)exp; - - //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars()); - auto e1 = sliceExp.e1; - if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice) - { - return e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.comma: - return (cast(CommaExp)exp).e2.checkModifiable(sc, flag); - - case EXP.index: - auto indexExp = cast(IndexExp)exp; - auto e1 = indexExp.e1; - if (e1.type.ty == Tsarray || - e1.type.ty == Taarray || - (e1.op == EXP.index && e1.type.ty != Tarray) || - e1.op == EXP.slice) - { - return e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.question: - auto condExp = cast(CondExp)exp; - if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no - && condExp.e2.checkModifiable(sc, flag) != Modifiable.no) - return Modifiable.yes; - return Modifiable.no; - - default: - return exp.type ? Modifiable.yes : Modifiable.no; // default modifiable - } -} - /** * Verify if the given identifier is _d_array{,set}ctor. * diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h index f7f6b0b..b4ace74b 100644 --- a/gcc/d/dmd/expression.h +++ b/gcc/d/dmd/expression.h @@ -50,7 +50,10 @@ struct Symbol; // back end symbol Expression *ctfeInterpret(Expression *e); void expandTuples(Expressions *exps, Identifiers *names = nullptr); StringExp *toUTF8(StringExp *se, Scope *sc); +Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc); MATCH implicitConvTo(Expression *e, Type *t); +Expression *toLvalue(Expression *_this, Scope *sc, const char* action); +Expression *modifiableLvalue(Expression* exp, Scope *sc); typedef unsigned char OwnedBy; enum @@ -99,9 +102,6 @@ public: virtual complex_t toComplex(); virtual StringExp *toStringExp(); virtual bool isLvalue(); - virtual Expression *toLvalue(Scope *sc, Expression *e); - virtual Expression *modifiableLvalue(Scope *sc, Expression *e); - virtual Expression *resolveLoc(const Loc &loc, Scope *sc); virtual bool checkType(); virtual bool checkValue(); Expression *addressOf(); @@ -244,7 +244,6 @@ public: real_t toImaginary() override; complex_t toComplex() override; Optional<bool> toBool() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } dinteger_t getInteger() { return value; } template<int v> @@ -254,7 +253,6 @@ public: class ErrorExp final : public Expression { public: - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } static ErrorExp *errorexp; // handy shared value @@ -302,7 +300,6 @@ public: static IdentifierExp *create(const Loc &loc, Identifier *ident); bool isLvalue() override final; - Expression *toLvalue(Scope *sc, Expression *e) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -320,7 +317,6 @@ public: DsymbolExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -331,8 +327,7 @@ public: ThisExp *syntaxCopy() override; Optional<bool> toBool() override; - bool isLvalue() override final; - Expression *toLvalue(Scope *sc, Expression *e) override final; + bool isLvalue() override; void accept(Visitor *v) override { v->visit(this); } }; @@ -370,8 +365,6 @@ public: StringExp *toStringExp() override; Optional<bool> toBool() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } size_t numberOfCodeUnits(int tynto = 0) const; void writeTo(void* dest, bool zero, int tyto = 0) const; @@ -469,7 +462,6 @@ public: static StructLiteralExp *create(const Loc &loc, StructDeclaration *sd, void *elements, Type *stype = NULL); bool equals(const RootObject * const o) const override; StructLiteralExp *syntaxCopy() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -501,7 +493,6 @@ public: FuncDeclaration *fd; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; bool checkType() override; bool checkValue() override; void accept(Visitor *v) override { v->visit(this); } @@ -575,8 +566,6 @@ public: static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true); bool equals(const RootObject * const o) const override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -589,7 +578,6 @@ public: OverloadSet *vars; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -678,7 +666,6 @@ public: Expression *e1; UnaExp *syntaxCopy() override; - Expression *resolveLoc(const Loc &loc, Scope *sc) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -701,8 +688,6 @@ class BinAssignExp : public BinExp { public: bool isLvalue() override final; - Expression *toLvalue(Scope *sc, Expression *ex) override final; - Expression *modifiableLvalue(Scope *sc, Expression *e) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -767,8 +752,6 @@ public: d_bool hasOverloads; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -821,7 +804,6 @@ public: CallExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -836,8 +818,6 @@ class PtrExp final : public UnaExp { public: bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -882,7 +862,6 @@ public: CastExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -903,7 +882,6 @@ class VectorArrayExp final : public UnaExp { public: bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -926,8 +904,6 @@ private: public: SliceExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional<bool> toBool() override; void accept(Visitor *v) override { v->visit(this); } @@ -953,8 +929,6 @@ class DelegatePtrExp final : public UnaExp { public: bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -962,8 +936,6 @@ class DelegateFuncptrExp final : public UnaExp { public: bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -978,7 +950,6 @@ public: ArrayExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -997,8 +968,6 @@ public: d_bool isGenerated; d_bool allowCommaExp; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional<bool> toBool() override; void accept(Visitor *v) override { v->visit(this); } }; @@ -1012,8 +981,6 @@ public: IndexExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -1047,7 +1014,6 @@ public: MemorySet memset; bool isLvalue() override final; - Expression *toLvalue(Scope *sc, Expression *ex) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -1148,6 +1114,8 @@ public: class CatAssignExp : public BinAssignExp { public: + Expression *lowering; // lowered druntime hook `_d_arrayappend{cTX,T}` + void accept(Visitor *v) override { v->visit(this); } }; @@ -1292,8 +1260,6 @@ public: CondExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -1320,35 +1286,30 @@ public: class FileInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; class LineInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; class ModuleInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; class FuncInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; class PrettyFuncInitExp final : public DefaultInitExp { public: - Expression *resolveLoc(const Loc &loc, Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 1ddb2b1..e6b9018 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -87,6 +87,46 @@ import dmd.visitor; enum LOGSEMANTIC = false; +/*********************************** + * Determine if a `this` is needed to access `d`. + * Params: + * sc = context + * d = declaration to check + * Returns: + * true means a `this` is needed + */ +private bool isNeedThisScope(Scope* sc, Declaration d) +{ + if (sc.intypeof == 1) + return false; + + AggregateDeclaration ad = d.isThis(); + if (!ad) + return false; + //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars()); + + for (Dsymbol s = sc.parent; s; s = s.toParentLocal()) + { + //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2()); + if (AggregateDeclaration ad2 = s.isAggregateDeclaration()) + { + if (ad2 == ad) + return false; + else if (ad2.isNested()) + continue; + else + return true; + } + if (FuncDeclaration f = s.isFuncDeclaration()) + { + if (f.isMemberLocal()) + break; + } + } + return true; +} + + /******************************************************** * Perform semantic analysis and CTFE on expressions to produce * a string. @@ -196,6 +236,51 @@ FuncDeclaration hasThis(Scope* sc) } +extern (D) bool findTempDecl(DotTemplateInstanceExp exp, Scope* sc) +{ + auto ti = exp.ti; + auto e1 = exp.e1; + static if (LOGSEMANTIC) + { + printf("DotTemplateInstanceExp::findTempDecl('%s')\n", exp.toChars()); + } + if (ti.tempdecl) + return true; + + Expression e = new DotIdExp(exp.loc, e1, ti.name); + e = e.expressionSemantic(sc); + if (e.op == EXP.dot) + e = (cast(DotExp)e).e2; + + Dsymbol s = null; + switch (e.op) + { + case EXP.overloadSet: + s = (cast(OverExp)e).vars; + break; + + case EXP.dotTemplateDeclaration: + s = (cast(DotTemplateExp)e).td; + break; + + case EXP.scope_: + s = (cast(ScopeExp)e).sds; + break; + + case EXP.dotVariable: + s = (cast(DotVarExp)e).var; + break; + + case EXP.variable: + s = (cast(VarExp)e).var; + break; + + default: + return false; + } + return ti.updateTempDecl(sc, s); +} + /*********************************************************** * Resolve `exp` as a compile-time known string. * Params: @@ -1731,6 +1816,403 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) return false; } +/********************************************* + * Calling function f. + * Check the purity, i.e. if we're in a pure function + * we can only call other pure functions. + * Returns true if error occurs. + */ +private bool checkPurity(FuncDeclaration f, const ref Loc loc, Scope* sc) +{ + if (!sc.func) + return false; + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; + + // If the call has a pure parent, then the called func must be pure. + if (!f.isPure() && checkImpure(sc, loc, null, f)) + { + error(loc, "`pure` %s `%s` cannot call impure %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), + f.toPrettyChars()); + + if (!f.isDtorDeclaration()) + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); + return true; + } + return false; +} + +/** + * Checks whether `f` is a generated `DtorDeclaration` that hides a user-defined one + * which passes `check` while `f` doesn't (e.g. when the user defined dtor is pure but + * the generated dtor is not). + * In that case the method will identify and print all members causing the attribute + * missmatch. + * + * Params: + * f = potential `DtorDeclaration` + * sc = scope + * loc = location + * check = current check (e.g. whether it's pure) + * checkName = the kind of check (e.g. `"pure"`) + */ +void checkOverriddenDtor(FuncDeclaration f, Scope* sc, const ref Loc loc, + scope bool function(DtorDeclaration) check, const string checkName) +{ + auto dd = f.isDtorDeclaration(); + if (!dd || !dd.isGenerated()) + return; + + // DtorDeclaration without parents should fail at an earlier stage + auto ad = cast(AggregateDeclaration) f.toParent2(); + assert(ad); + + if (ad.userDtors.length) + { + if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well) + return; + + // Sanity check + assert(!check(ad.fieldDtor)); + } + + dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:", + dd.isGenerated() ? "generated " : "".ptr, + ad.toChars, + cast(int) checkName.length, checkName.ptr); + + // Search for the offending fields + foreach (field; ad.fields) + { + // Only structs may define automatically called destructors + auto ts = field.type.isTypeStruct(); + if (!ts) + { + // But they might be part of a static array + auto ta = field.type.isTypeSArray(); + if (!ta) + continue; + + ts = ta.baseElemOf().isTypeStruct(); + if (!ts) + continue; + } + + auto fieldSym = ts.toDsymbol(sc); + assert(fieldSym); // Resolving ts must succeed because missing defs. should error before + + auto fieldSd = fieldSym.isStructDeclaration(); + assert(fieldSd); // ts is a TypeStruct, this would imply a malformed ASR + + if (fieldSd.dtor && !check(fieldSd.dtor)) + { + field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars()); + + if (fieldSd.dtor.isGenerated()) + fieldSd.dtor.checkOverriddenDtor(sc, loc, check, checkName); + else + fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here", + cast(int) checkName.length, checkName.ptr, fieldSd.toChars()); + } + } +} + +/******************************************* + * Accessing variable v. + * Check for purity and safety violations. + * Returns true if error occurs. + */ +private bool checkPurity(VarDeclaration v, const ref Loc loc, Scope* sc) +{ + //printf("v = %s %s\n", v.type.toChars(), v.toChars()); + /* Look for purity and safety violations when accessing variable v + * from current function. + */ + if (!sc.func) + return false; + if (sc.intypeof == 1) + return false; // allow violations inside typeof(expression) + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; // allow violations inside compile-time evaluated expressions and debug conditionals + if (v.ident == Id.ctfe) + return false; // magic variable never violates pure and safe + if (v.isImmutable()) + return false; // always safe and pure to access immutables... + if (v.isConst() && !v.isReference() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf())) + return false; // or const global/parameter values which have no mutable indirections + if (v.storage_class & STC.manifest) + return false; // ...or manifest constants + + // accessing empty structs is pure + // https://issues.dlang.org/show_bug.cgi?id=18694 + // https://issues.dlang.org/show_bug.cgi?id=21464 + // https://issues.dlang.org/show_bug.cgi?id=23589 + if (v.type.ty == Tstruct) + { + StructDeclaration sd = (cast(TypeStruct)v.type).sym; + if (sd.members) // not opaque + { + if (sd.semanticRun >= PASS.semanticdone) + sd.determineSize(v.loc); + if (sd.hasNoFields) + return false; + } + } + + bool err = false; + if (v.isDataseg()) + { + // https://issues.dlang.org/show_bug.cgi?id=7533 + // Accessing implicit generated __gate is pure. + if (v.ident == Id.gate) + return false; + + if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v)) + { + error(loc, "`pure` %s `%s` cannot access mutable static data `%s`", + sc.func.kind(), sc.func.toPrettyChars(), v.toChars()); + err = true; + } + } + else + { + /* Given: + * void f() { + * int fx; + * pure void g() { + * int gx; + * /+pure+/ void h() { + * int hx; + * /+pure+/ void i() { } + * } + * } + * } + * i() can modify hx and gx but not fx + */ + + Dsymbol vparent = v.toParent2(); + for (Dsymbol s = sc.func; !err && s; s = s.toParentP(vparent)) + { + if (s == vparent) + break; + + if (AggregateDeclaration ad = s.isAggregateDeclaration()) + { + if (ad.isNested()) + continue; + break; + } + FuncDeclaration ff = s.isFuncDeclaration(); + if (!ff) + break; + if (ff.isNested() || ff.isThis()) + { + if (ff.type.isImmutable() || + ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod)) + { + OutBuffer ffbuf; + OutBuffer vbuf; + MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod); + MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod); + error(loc, "%s%s `%s` cannot access %sdata `%s`", + ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars()); + err = true; + break; + } + continue; + } + break; + } + } + + /* Do not allow safe functions to access __gshared data + */ + if (v.storage_class & STC.gshared) + { + if (sc.setUnsafe(false, loc, + "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) + { + err = true; + } + } + + return err; +} + +/* +Check if sc.func is impure or can be made impure. +Returns true on error, i.e. if sc.func is pure and cannot be made impure. +*/ +private bool checkImpure(Scope* sc, Loc loc, const(char)* fmt, RootObject arg0) +{ + return sc.func && (isRootTraitsCompilesScope(sc) + ? sc.func.isPureBypassingInference() >= PURE.weak + : sc.func.setImpure(loc, fmt, arg0)); +} + +/********************************************* + * Calling function f. + * Check the safety, i.e. if we're in a @safe function + * we can only call @safe or @trusted functions. + * Returns true if error occurs. + */ +private bool checkSafety(FuncDeclaration f, ref Loc loc, Scope* sc) +{ + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & SCOPE.debug_) + return false; + if ((sc.flags & SCOPE.ctfe) && sc.func) + return false; + + if (!sc.func) + { + if (sc.varDecl && !f.safetyInprocess && !f.isSafe() && !f.isTrusted()) + { + if (sc.varDecl.storage_class & STC.safe) + { + error(loc, "`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`", + sc.varDecl.toChars(), f.toChars()); + return true; + } + else + { + sc.varDecl.storage_class |= STC.system; + sc.varDecl.systemInferred = true; + } + } + return false; + } + + if (!f.isSafe() && !f.isTrusted()) + { + if (isRootTraitsCompilesScope(sc) ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) + { + if (!loc.isValid()) // e.g. implicitly generated dtor + loc = sc.func.loc; + + const prettyChars = f.toPrettyChars(); + error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), + prettyChars); + if (!f.isDtorDeclaration) + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); + .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); + + return true; + } + } + else if (f.isSafe() && f.safetyViolation) + { + // for dip1000 by default transition, print deprecations for calling functions that will become `@system` + if (sc.func.isSafeBypassingInference()) + { + .deprecation(loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); + errorSupplementalInferredAttr(f, 10, true, STC.safe); + } + else if (!sc.func.safetyViolation) + { + import dmd.func : AttributeViolation; + sc.func.safetyViolation = new AttributeViolation(loc, null, f, null, null); + } + } + return false; +} + +/********************************************* + * Calling function f. + * Check the @nogc-ness, i.e. if we're in a @nogc function + * we can only call other @nogc functions. + * Returns true if error occurs. + */ +private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc) +{ + if (!sc.func) + return false; + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; + /* The original expressions (`new S(...)` or `new S[...]``) will be + * verified instead. This is to keep errors related to the original code + * and not the lowering. + */ + if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT || f.ident == Id._d_newarraymTX) + return false; + + if (!f.isNogc()) + { + if (isRootTraitsCompilesScope(sc) ? sc.func.isNogcBypassingInference() : sc.func.setGCCall(f)) + { + if (loc.linnum == 0) // e.g. implicitly generated dtor + loc = sc.func.loc; + + // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)), + // so don't print anything to avoid double error messages. + if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT + || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX + || f.ident == Id._d_arraycatnTX || f.ident == Id._d_newclassT)) + { + error(loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); + + if (!f.isDtorDeclaration) + f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); + } + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); + + return true; + } + } + return false; +} + +/******************************************** + * Check that the postblit is callable if t is an array of structs. + * Returns true if error happens. + */ +private bool checkPostblit(Type t, ref Loc loc, Scope* sc) +{ + if (auto ts = t.baseElemOf().isTypeStruct()) + { + if (global.params.useTypeInfo && Type.dtypeinfo) + { + // https://issues.dlang.org/show_bug.cgi?id=11395 + // Require TypeInfo generation for array concatenation + semanticTypeInfo(sc, t); + } + + StructDeclaration sd = ts.sym; + if (sd.postblit) + { + if (sd.postblit.checkDisabled(loc, sc)) + return true; + + //checkDeprecated(sc, sd.postblit); // necessary? + sd.postblit.checkPurity(loc, sc); + sd.postblit.checkSafety(loc, sc); + sd.postblit.checkNogc(loc, sc); + //checkAccess(sd, loc, sc, sd.postblit); // necessary? + return false; + } + } + return false; +} + /*************************************** * Pull out any properties. */ @@ -1942,7 +2424,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = { if (auto v = ve.var.isVarDeclaration()) { - if (ve.checkPurity(sc, v)) + if (v.checkPurity(ve.loc, sc)) return ErrorExp.get(); } } @@ -2647,7 +3129,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc, "create `in` parameter from"); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -2665,7 +3147,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc, "create `ref` parameter from"); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -2684,7 +3166,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, err |= checkUnsafeAccess(sc, arg, false, true); err |= checkDefCtor(arg.loc, t); // t must be default constructible } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc, "create `out` parameter from"); } else if (p.isLazy()) { @@ -2727,7 +3209,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, const explicitScope = p.isLazy() || ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred)); if ((pStc & (STC.scope_ | STC.lazy_)) && - ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) && + ((sc.useDIP1000 == FeatureState.enabled) || explicitScope) && !(pStc & STC.return_)) { /* Argument value cannot escape from the called function. @@ -4633,23 +5115,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tb = tb.isTypeDArray().next.toBasetype(); } - if (nargs == 1) - { - if (global.params.betterC || !sc.needsCodegen()) + if (global.params.betterC || !sc.needsCodegen()) goto LskipNewArrayLowering; - /* Class types may inherit base classes that have errors. - * This may leak errors from the base class to the derived one - * and then to the hook. Semantic analysis is performed eagerly - * to a void this. - */ - if (auto tc = exp.type.nextOf.isTypeClass()) - { - tc.sym.dsymbolSemantic(sc); - if (tc.sym.errors) - goto LskipNewArrayLowering; - } + /* Class types may inherit base classes that have errors. + * This may leak errors from the base class to the derived one + * and then to the hook. Semantic analysis is performed eagerly + * to a void this. + */ + if (auto tc = exp.type.nextOf.isTypeClass()) + { + tc.sym.dsymbolSemantic(sc); + if (tc.sym.errors) + goto LskipNewArrayLowering; + } + if (nargs == 1) + { auto hook = global.params.tracegc ? Id._d_newarrayTTrace : Id._d_newarrayT; if (!verifyHookExist(exp.loc, *sc, hook, "new array")) goto LskipNewArrayLowering; @@ -4684,6 +5166,45 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor lowering = new CallExp(exp.loc, lowering, arguments); exp.lowering = lowering.expressionSemantic(sc); } + else + { + auto hook = global.params.tracegc ? Id._d_newarraymTXTrace : Id._d_newarraymTX; + if (!verifyHookExist(exp.loc, *sc, hook, "new multi-dimensional array")) + goto LskipNewArrayLowering; + + /* Lower the memory allocation and initialization of `new T[][]...[](n1, n2, ...)` + * to `_d_newarraymTX!(T[][]...[], T)([n1, n2, ...])`. + */ + Expression lowering = new IdentifierExp(exp.loc, Id.empty); + lowering = new DotIdExp(exp.loc, lowering, Id.object); + + auto tbn = exp.type.nextOf(); + while (tbn.ty == Tarray) + tbn = tbn.nextOf(); + auto unqualTbn = tbn.unqualify(MODFlags.wild | MODFlags.const_ | + MODFlags.immutable_ | MODFlags.shared_); + + auto tiargs = new Objects(); + tiargs.push(exp.type); + tiargs.push(unqualTbn); + lowering = new DotTemplateInstanceExp(exp.loc, lowering, hook, tiargs); + + auto arguments = new Expressions(); + if (global.params.tracegc) + { + auto funcname = (sc.callsc && sc.callsc.func) ? + sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); + arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString())); + arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32)); + arguments.push(new StringExp(exp.loc, funcname.toDString())); + } + + arguments.push(new ArrayLiteralExp(exp.loc, Type.tsize_t.sarrayOf(nargs), exp.arguments)); + arguments.push(new IntegerExp(exp.loc, tbn.isShared(), Type.tbool)); + + lowering = new CallExp(exp.loc, lowering, arguments); + exp.lowering = lowering.expressionSemantic(sc); + } } else if (tb.isscalar()) { @@ -4852,6 +5373,52 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = e; } + private void genIdent(FuncExp exp, Scope* sc) + { + if (exp.fd.ident == Id.empty) + { + const(char)[] s; + if (exp.fd.fes) + s = "__foreachbody"; + else if (exp.fd.tok == TOK.reserved) + s = "__lambda"; + else if (exp.fd.tok == TOK.delegate_) + s = "__dgliteral"; + else + s = "__funcliteral"; + + DsymbolTable symtab; + if (FuncDeclaration func = sc.parent.isFuncDeclaration()) + { + if (func.localsymtab is null) + { + // Inside template constraint, symtab is not set yet. + // Initialize it lazily. + func.localsymtab = new DsymbolTable(); + } + symtab = func.localsymtab; + } + else + { + ScopeDsymbol sds = sc.parent.isScopeDsymbol(); + if (!sds.symtab) + { + // Inside template constraint, symtab may not be set yet. + // Initialize it lazily. + assert(sds.isTemplateInstance()); + sds.symtab = new DsymbolTable(); + } + symtab = sds.symtab; + } + assert(symtab); + Identifier id = Identifier.generateId(s, symtab.length() + 1); + exp.fd.ident = id; + if (exp.td) + exp.td.ident = id; + symtab.insert(exp.td ? cast(Dsymbol)exp.td : cast(Dsymbol)exp.fd); + } + } + override void visit(FuncExp exp) { static if (LOGSEMANTIC) @@ -4882,7 +5449,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor //if (fd.treq) // fd.treq = fd.treq.dsymbolSemantic(loc, sc); - exp.genIdent(sc); + genIdent(exp, sc); // Set target of return type inference if (exp.fd.treq && !exp.fd.type.nextOf()) @@ -4995,7 +5562,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return checkarg; } - exp.genIdent(sc); + genIdent(exp, sc); assert(exp.td.parameters && exp.td.parameters.length); exp.td.dsymbolSemantic(sc); @@ -5257,7 +5824,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor ve.type = t.typeSemantic(exp.loc, sc); } VarDeclaration v = ve.var.isVarDeclaration(); - if (v && ve.checkPurity(sc, v)) + if (v && v.checkPurity(ve.loc, sc)) return setError(); } @@ -5885,9 +6452,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Purity and safety check should run after testing arguments matching if (exp.f) { - exp.checkPurity(sc, exp.f); - exp.checkSafety(sc, exp.f); - exp.checkNogc(sc, exp.f); + exp.f.checkPurity(exp.loc, sc); + exp.f.checkSafety(exp.loc, sc); + exp.f.checkNogc(exp.loc, sc); if (exp.f.checkNestedReference(sc, exp.loc)) return setError(); } @@ -6795,7 +7362,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } exp.e1 = exp.e1.expressionSemantic(sc); - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true); exp.type = exp.e1.type; @@ -6873,7 +7440,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor uint errors = global.errors; const len = buf.length; const str = buf.extractChars()[0 .. len]; - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); auto loc = adjustLocForMixin(str, exp.loc, global.params.mixinOut); scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests); p.transitionIn = global.params.v.vin; @@ -7767,7 +8334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else { // `toLvalue` call further below is upon exp.e1, omitting & from the error message - exp.toLvalue(sc, null); + exp.toLvalue(sc, "take address of"); return setError(); } } @@ -7857,7 +8424,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - exp.e1 = exp.e1.toLvalue(sc, null); + exp.e1 = exp.e1.toLvalue(sc, "take address of"); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -7934,7 +8501,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!checkAddressVar(sc, exp.e1, v)) return setError(); - ve.checkPurity(sc, v); + v.checkPurity(ve.loc, sc); } FuncDeclaration f = ve.var.isFuncDeclaration(); if (f) @@ -8006,7 +8573,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (VarDeclaration v = expToVariable(exp.e1)) { - exp.e1.checkPurity(sc, v); + v.checkPurity(exp.e1.loc, sc); } } else if (wasCond) @@ -8275,7 +8842,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } exp.e1 = resolveProperties(sc, exp.e1); - exp.e1 = exp.e1.modifiableLvalue(sc, null); + exp.e1 = exp.e1.modifiableLvalue(sc); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -8306,9 +8873,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (cd.dtor) { err |= !cd.dtor.functionSemantic(); - err |= exp.checkPurity(sc, cd.dtor); - err |= exp.checkSafety(sc, cd.dtor); - err |= exp.checkNogc(sc, cd.dtor); + err |= cd.dtor.checkPurity(exp.loc, sc); + err |= cd.dtor.checkSafety(exp.loc, sc); + err |= cd.dtor.checkNogc(exp.loc, sc); } if (err) return setError(); @@ -8489,14 +9056,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return setError(); } - // Look for casting to a vector type - if (tob.ty == Tvector && t1b.ty != Tvector) - { - result = new VectorExp(exp.loc, exp.e1, exp.to); - result = result.expressionSemantic(sc); - return; - } - Expression ex = exp.e1.castTo(sc, exp.to); if (ex.op == EXP.error) { @@ -9491,7 +10050,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true); e = exp; @@ -10253,7 +10812,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expression ex; ex = new IndexExp(exp.loc, ea, ek); ex = ex.expressionSemantic(sc); - ex = ex.modifiableLvalue(sc, ex); // allocate new slot + ex = ex.modifiableLvalue(sc); // allocate new slot ex = ex.optimize(WANTvalue); ey = new ConstructExp(exp.loc, ex, ey); @@ -10344,7 +10903,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue())) { - if (e1x.checkPostblit(sc, t1)) + if (t1.checkPostblit(e1x.loc, sc)) return setError(); } @@ -10446,7 +11005,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // e1 is not an lvalue, but we let code generator handle it - auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1); + auto ale1x = ale.e1.modifiableLvalueImpl(sc, exp.e1); if (ale1x.op == EXP.error) return setResult(ale1x); ale.e1 = ale1x; @@ -10532,7 +11091,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor se = cast(SliceExp)se.e1; if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray) { - se.e1 = se.e1.modifiableLvalue(sc, exp.e1); + se.e1 = se.e1.modifiableLvalueImpl(sc, exp.e1); if (se.e1.op == EXP.error) return setResult(se.e1); } @@ -10556,7 +11115,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Try to do a decent error message with the expression // before it gets constant folded if (exp.op == EXP.assign) - e1x = e1x.modifiableLvalue(sc, e1old); + e1x = e1x.modifiableLvalueImpl(sc, e1old); e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true); @@ -10587,7 +11146,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // '= null' is the only allowable block assignment (Bug 7493) exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is e2x = e2x.implicitCastTo(sc, t1.nextOf()); - if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf())) + if (exp.op != EXP.blit && e2x.isLvalue() && t1.nextOf.checkPostblit(exp.e1.loc, sc)) return setError(); } else if (exp.e1.op == EXP.slice && @@ -10625,7 +11184,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue())) { - if (exp.e1.checkPostblit(sc, t1.nextOf())) + if (t1.nextOf().checkPostblit(exp.e1.loc, sc)) return setError(); } @@ -11004,7 +11563,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); } if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating())) @@ -11063,7 +11622,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -11095,7 +11654,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // EXP.concatenateAssign assert(exp.op == EXP.concatenateAssign); - if (exp.e1.checkPostblit(sc, tb1next)) + if (tb1next.checkPostblit(exp.e1.loc, sc)) return setError(); exp.e2 = exp.e2.castTo(sc, exp.e1.type); @@ -11113,7 +11672,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next)) goto Laliasthis; // Append element - if (exp.e2.checkPostblit(sc, tb2)) + if (tb2.checkPostblit(exp.e2.loc, sc)) return setError(); if (checkNewEscape(sc, exp.e2, false)) @@ -11199,8 +11758,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = res; - if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && - sc.needsCodegen()) + if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && sc.needsCodegen()) { // if aa ordering is triggered, `res` will be a CommaExp // and `.e2` will be the rewritten original expression. @@ -11244,7 +11802,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor arguments.push(exp.e1); arguments.push(exp.e2); Expression ce = new CallExp(exp.loc, id, arguments); - *output = ce.expressionSemantic(sc); + + exp.lowering = ce.expressionSemantic(sc); + *output = exp; } else if (exp.op == EXP.concatenateElemAssign) { @@ -11264,15 +11824,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX; - if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object)) + if (!verifyHookExist(exp.loc, *sc, hook, "appending element to arrays", Id.object)) return setError(); - // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2 + // Lower to object._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2 Expression id = new IdentifierExp(exp.loc, Id.empty); id = new DotIdExp(exp.loc, id, Id.object); - auto tiargs = new Objects(); - tiargs.push(exp.e1.type); - id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs); id = new DotIdExp(exp.loc, id, hook); auto arguments = new Expressions(); @@ -11299,11 +11856,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { /* Before the template hook, this check was performed in e2ir.d * for expressions like `a ~= a[$-1]`. Here, $ will be modified - * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in + * by calling `_d_arrayappendcTX`, so we need to save `a[$-1]` in * a temporary variable. */ value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true); - exp.e2 = value2; // `__appendtmp*` will be destroyed together with the array `exp.e1`. auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration(); @@ -11319,13 +11875,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor auto e0 = Expression.combine(ce, ae).expressionSemantic(sc); e0 = Expression.combine(e0, value1); e0 = Expression.combine(eValue1, e0); - e0 = Expression.combine(eValue2, e0); - *output = e0.expressionSemantic(sc); + exp.lowering = e0.expressionSemantic(sc); + *output = exp; } } - } override void visit(AddExp exp) @@ -11746,7 +12301,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (exp.e2.checkPostblit(sc, tb2)) + if (tb2.checkPostblit(exp.e2.loc, sc)) return setError(); // Postblit call will be done in runtime helper function } @@ -11781,7 +12336,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (exp.e1.checkPostblit(sc, tb1)) + if (tb1.checkPostblit(exp.e1.loc, sc)) return setError(); } @@ -11836,7 +12391,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (Type tbn = tb.nextOf()) { - if (exp.checkPostblit(sc, tbn)) + if (tbn.checkPostblit(exp.loc, sc)) return setError(); } Type t1 = exp.e1.type.toBasetype(); @@ -13582,6 +14137,14 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) return exp; } +private bool checkDisabled(Dsymbol s, ref Loc loc, Scope* sc) +{ + if (auto d = s.isDeclaration()) + return d.checkDisabled(loc, sc); + + return false; +} + /****************************** * Resolve properties, i.e. `e1.ident`, without seeing UFCS. * Params: @@ -13675,8 +14238,8 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) // if 's' is a tuple variable, the tuple is returned. s = s.toAlias(); - exp.checkDeprecated(sc, s); - exp.checkDisabled(sc, s); + s.checkDeprecated(exp.loc, sc); + s.checkDisabled(exp.loc, sc); if (auto em = s.isEnumMember()) { @@ -14466,6 +15029,106 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) return check(e, returnRef); } +/**************************************** + * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc. + */ +Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) +{ + Expression visit(Expression exp) + { + if (auto unaExp = exp.isUnaExp()) + { + unaExp.e1 = unaExp.e1.resolveLoc(loc, sc); + return unaExp; + } + exp.loc = loc; + return exp; + } + + Expression visitCat(CatExp exp) + { + exp.e1 = exp.e1.resolveLoc(loc, sc); + exp.e2 = exp.e2.resolveLoc(loc, sc); + return exp; + } + + Expression visitFileInit(FileInitExp exp) + { + //printf("FileInitExp::resolve() %s\n", exp.toChars()); + const(char)* s; + if (exp.op == EXP.fileFullPath) + s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars()); + else + s = loc.isValid() ? loc.filename : sc._module.ident.toChars(); + + Expression e = new StringExp(loc, s.toDString()); + return e.expressionSemantic(sc); + } + + Expression visitLineInit(LineInitExp _) + { + Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); + return e.expressionSemantic(sc); + } + + Expression visitModuleInit(ModuleInitExp _) + { + const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString(); + Expression e = new StringExp(loc, s); + return e.expressionSemantic(sc); + } + + Expression visitFuncInit(FuncInitExp _) + { + const(char)* s; + if (sc.callsc && sc.callsc.func) + s = sc.callsc.func.Dsymbol.toPrettyChars(); + else if (sc.func) + s = sc.func.Dsymbol.toPrettyChars(); + else + s = ""; + Expression e = new StringExp(loc, s.toDString()); + return e.expressionSemantic(sc); + } + + Expression visitPrettyFunc(PrettyFuncInitExp _) + { + FuncDeclaration fd = (sc.callsc && sc.callsc.func) + ? sc.callsc.func + : sc.func; + + const(char)* s; + if (fd) + { + const funcStr = fd.Dsymbol.toPrettyChars(); + OutBuffer buf; + functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic); + s = buf.extractChars(); + } + else + { + s = ""; + } + + Expression e = new StringExp(loc, s.toDString()); + e = e.expressionSemantic(sc); + e.type = Type.tstring; + return e; + } + + switch(exp.op) + { + default: return visit(exp); + case EXP.concatenate: return visitCat(exp.isCatExp()); + case EXP.file: + case EXP.fileFullPath: return visitFileInit(exp.isFileInitExp()); + case EXP.line: return visitLineInit(exp.isLineInitExp); + case EXP.moduleString: return visitModuleInit(exp.isModuleInitExp()); + case EXP.functionString: return visitFuncInit(exp.isFuncInitExp()); + case EXP.prettyFunction: return visitPrettyFunc(exp.isPrettyFuncInitExp()); + } +} + /************************************************ * Destructors are attached to VarDeclarations. * Hence, if expression returns a temp that needs a destructor, @@ -14567,6 +15230,593 @@ Expression addDtorHook(Expression e, Scope* sc) } } +/******************************* + * Try to convert an expression to be an lvalue. + * + * Give error if we're not an lvalue. + * Params: + * _this = expression to convert + * sc = scope + * action = for error messages, what the lvalue is needed for (e.g. take address of for `&x`, modify for `x++`) + * Returns: converted expression, or `ErrorExp` on error +*/ +extern(C++) Expression toLvalue(Expression _this, Scope* sc, const(char)* action) +{ + return toLvalueImpl(_this, sc, action, _this); +} + +// e = original un-lowered expression for error messages, in case of recursive calls +private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action, Expression e) +{ + if (!action) + action = "create lvalue of"; + + assert(e); + Expression visit(Expression _this) + { + // BinaryAssignExp does not have an EXP associated + // so it's treated on the default path. + // Lvalue-ness will be handled in glue :layer. + if (_this.isBinAssignExp()) + return _this; + if (!_this.loc.isValid()) + _this.loc = e.loc; + + if (e.op == EXP.type) + error(_this.loc, "cannot %s type `%s`", action, e.type.toChars()); + else if (e.op == EXP.template_) + error(_this.loc, "cannot %s template `%s`, perhaps instantiate it first", action, e.toChars()); + else + error(_this.loc, "cannot %s expression `%s` because it is not an lvalue", action, e.toChars()); + + return ErrorExp.get(); + } + + Expression visitInteger(IntegerExp _this) + { + if (!_this.loc.isValid()) + _this.loc = e.loc; + error(e.loc, "cannot %s constant `%s`", action, e.toChars()); + return ErrorExp.get(); + } + + Expression visitThis(ThisExp _this) + { + if (_this.type.toBasetype().ty == Tclass) + { + // Class `this` is an rvalue; struct `this` is an lvalue. + return visit(_this); + } + + return _this; + } + + Expression visitString(StringExp _this) + { + //printf("StringExp::toLvalue(%s) type = %s\n", _this.toChars(), _this.type ? _this.type.toChars() : NULL); + return (_this.type && _this.type.toBasetype().ty == Tsarray) ? _this : visit(_this); + } + + Expression visitStructLiteral(StructLiteralExp _this) + { + if (sc.flags & SCOPE.Cfile) + return _this; // C struct literals are lvalues + else + return visit(_this); + } + + Expression visitTemplate(TemplateExp _this) + { + if (!_this.fd) + return visit(_this); + + assert(sc); + return symbolToExp(_this.fd, _this.loc, sc, true); + + } + + Expression visitVar(VarExp _this) + { + auto var = _this.var; + if (var.storage_class & STC.manifest) + { + error(_this.loc, "cannot %s manifest constant `%s`", action, var.toChars()); + return ErrorExp.get(); + } + if (var.storage_class & STC.lazy_ && !_this.delegateWasExtracted) + { + error(_this.loc, "cannot %s lazy variable `%s`", action, var.toChars()); + return ErrorExp.get(); + } + if (var.ident == Id.ctfe) + { + error(_this.loc, "cannot %s compiler-generated variable `__ctfe`", action); + return ErrorExp.get(); + } + if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574 + { + error(_this.loc, "cannot %s operator `$`", action); + return ErrorExp.get(); + } + return _this; + } + + Expression visitDotVar(DotVarExp _this) + { + auto e1 = _this.e1; + auto var = _this.var; + //printf("DotVarExp::toLvalue(%s)\n", toChars()); + if (sc && sc.flags & SCOPE.Cfile) + { + /* C11 6.5.2.3-3: A postfix expression followed by the '.' or '->' operator + * is an lvalue if the first expression is an lvalue. + */ + if (!e1.isLvalue()) + return visit(_this); + } + if (!_this.isLvalue()) + return visit(_this); + if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor)) + { + if (VarDeclaration vd = var.isVarDeclaration()) + { + auto ad = vd.isMember2(); + if (ad && ad.fields.length == sc.ctorflow.fieldinit.length) + { + foreach (i, f; ad.fields) + { + if (f == vd) + { + if (!(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor)) + { + /* If the address of vd is taken, assume it is thereby initialized + * https://issues.dlang.org/show_bug.cgi?id=15869 + */ + modifyFieldVar(_this.loc, sc, vd, e1); + } + break; + } + } + } + } + } + return _this; + } + + Expression visitCall(CallExp _this) + { + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitCast(CastExp _this) + { + if (sc && sc.flags & SCOPE.Cfile) + { + /* C11 6.5.4-5: A cast does not yield an lvalue. + */ + return visit(_this); + } + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitVectorArray(VectorArrayExp _this) + { + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + return _this; + } + + Expression visitSlice(SliceExp _this) + { + //printf("SliceExp::toLvalue(%s) _this.type = %s\n", _this.toChars(), _this.type ? _this.type.toChars() : NULL); + return (_this.type && _this.type.toBasetype().ty == Tsarray) ? _this : visit(_this); + } + + Expression visitArray(ArrayExp _this) + { + if (_this.type && _this.type.toBasetype().ty == Tvoid) + error(_this.loc, "`void`s have no value"); + return _this; + } + + Expression visitComma(CommaExp _this) + { + _this.e2 = _this.e2.toLvalue(sc, action); + return _this; + } + + Expression visitDelegatePointer(DelegatePtrExp _this) + { + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + return _this; + } + + Expression visitDelegateFuncptr(DelegateFuncptrExp _this) + { + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + return _this; + } + + Expression visitIndex(IndexExp _this) + { + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitAssign(AssignExp _this) + { + if (_this.e1.op == EXP.slice || _this.e1.op == EXP.arrayLength) + { + return visit(_this); + } + + /* In front-end level, AssignExp should make an lvalue of e1. + * Taking the address of e1 will be handled in low level layer, + * so this function does nothing. + */ + return _this; + } + + Expression visitCond(CondExp _this) + { + // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) + CondExp e = cast(CondExp)(_this.copy()); + e.e1 = _this.e1.toLvalue(sc, action).addressOf(); + e.e2 = _this.e2.toLvalue(sc, action).addressOf(); + e.type = _this.type.pointerTo(); + return new PtrExp(_this.loc, e, _this.type); + + } + + switch(_this.op) + { + default: return visit(_this); + + case EXP.int64: return visitInteger(_this.isIntegerExp()); + case EXP.error: return _this; + case EXP.identifier: return _this; + case EXP.dSymbol: return _this; + case EXP.this_: return visitThis(_this.isThisExp()); + case EXP.super_: return visitThis(_this.isSuperExp()); + case EXP.string_: return visitString(_this.isStringExp()); + case EXP.structLiteral: return visitStructLiteral(_this.isStructLiteralExp()); + case EXP.template_: return visitTemplate(_this.isTemplateExp()); + case EXP.variable: return visitVar(_this.isVarExp()); + case EXP.overloadSet: return _this; + case EXP.dotVariable: return visitDotVar(_this.isDotVarExp()); + case EXP.call: return visitCall(_this.isCallExp()); + case EXP.star: return _this; + case EXP.cast_: return visitCast(_this.isCastExp()); + case EXP.vectorArray: return visitVectorArray(_this.isVectorArrayExp()); + case EXP.slice: return visitSlice(_this.isSliceExp()); + case EXP.array: return visitArray(_this.isArrayExp()); + case EXP.comma: return visitComma(_this.isCommaExp()); + case EXP.delegatePointer: return visitDelegatePointer(_this.isDelegatePtrExp()); + case EXP.delegateFunctionPointer: return visitDelegateFuncptr(_this.isDelegateFuncptrExp()); + case EXP.index: return visitIndex(_this.isIndexExp()); + case EXP.construct: return visitAssign(_this.isConstructExp()); + case EXP.loweredAssignExp: return visitAssign(_this.isLoweredAssignExp()); + case EXP.blit: return visitAssign(_this.isBlitExp()); + case EXP.assign: return visitAssign(_this.isAssignExp()); + case EXP.question: return visitCond(_this.isCondExp()); + } +} + +/*************************************** + * Parameters: + * sc: scope + * flag: 1: do not issue error message for invalid modification + 2: the exp is a DotVarExp and a subfield of the leftmost + variable is modified + * Returns: + * Whether the type is modifiable + */ +Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyFlags.none) +{ + switch(exp.op) + { + case EXP.variable: + auto varExp = cast(VarExp)exp; + + //printf("VarExp::checkModifiable %s", varExp.toChars()); + assert(varExp.type); + return varExp.var.checkModify(varExp.loc, sc, null, flag); + + case EXP.dotVariable: + auto dotVarExp = cast(DotVarExp)exp; + + //printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars()); + if (dotVarExp.e1.op == EXP.this_) + return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag); + + /* https://issues.dlang.org/show_bug.cgi?id=12764 + * If inside a constructor and an expression of type `this.field.var` + * is encountered, where `field` is a struct declaration with + * default construction disabled, we must make sure that + * assigning to `var` does not imply that `field` was initialized + */ + if (sc.func && sc.func.isCtorDeclaration()) + { + // if inside a constructor scope and e1 of this DotVarExp + // is another DotVarExp, then check if the leftmost expression is a `this` identifier + if (auto dve = dotVarExp.e1.isDotVarExp()) + { + // Iterate the chain of DotVarExp to find `this` + // Keep track whether access to fields was limited to union members + // s.t. one can initialize an entire struct inside nested unions + // (but not its members) + bool onlyUnion = true; + while (true) + { + auto v = dve.var.isVarDeclaration(); + assert(v); + + // Accessing union member? + auto t = v.type.isTypeStruct(); + if (!t || !t.sym.isUnionDeclaration()) + onlyUnion = false; + + // Another DotVarExp left? + if (!dve.e1 || dve.e1.op != EXP.dotVariable) + break; + + dve = cast(DotVarExp) dve.e1; + } + + if (dve.e1.op == EXP.this_) + { + scope v = dve.var.isVarDeclaration(); + /* if v is a struct member field with no initializer, no default construction + * and v wasn't intialized before + */ + if (v && v.isField() && !v._init && !v.ctorinit) + { + if (auto ts = v.type.isTypeStruct()) + { + if (ts.sym.noDefaultCtor) + { + /* checkModify will consider that this is an initialization + * of v while it is actually an assignment of a field of v + */ + scope modifyLevel = v.checkModify(dotVarExp.loc, sc, dve.e1, !onlyUnion ? (flag | ModifyFlags.fieldAssign) : flag); + if (modifyLevel == Modifiable.initialization) + { + // https://issues.dlang.org/show_bug.cgi?id=22118 + // v is a union type field that was assigned + // a variable, therefore it counts as initialization + if (v.ctorinit) + return Modifiable.initialization; + + return Modifiable.yes; + } + return modifyLevel; + } + } + } + } + } + } + + //printf("\te1 = %s\n", e1.toChars()); + return dotVarExp.e1.checkModifiable(sc, flag); + + case EXP.star: + auto ptrExp = cast(PtrExp)exp; + if (auto se = ptrExp.e1.isSymOffExp()) + { + return se.var.checkModify(ptrExp.loc, sc, null, flag); + } + else if (auto ae = ptrExp.e1.isAddrExp()) + { + return ae.e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.slice: + auto sliceExp = cast(SliceExp)exp; + + //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars()); + auto e1 = sliceExp.e1; + if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice) + { + return e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.comma: + return (cast(CommaExp)exp).e2.checkModifiable(sc, flag); + + case EXP.index: + auto indexExp = cast(IndexExp)exp; + auto e1 = indexExp.e1; + if (e1.type.ty == Tsarray || + e1.type.ty == Taarray || + (e1.op == EXP.index && e1.type.ty != Tarray) || + e1.op == EXP.slice) + { + return e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.question: + auto condExp = cast(CondExp)exp; + if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no + && condExp.e2.checkModifiable(sc, flag) != Modifiable.no) + return Modifiable.yes; + return Modifiable.no; + + default: + return exp.type ? Modifiable.yes : Modifiable.no; // default modifiable + } +} + +/** + * Similar to `toLvalue`, but also enforce it is mutable or raise an error. + * Params: + * _this = Expression to convert + * sc = scope + * Returns: `_this` converted to an lvalue, or an `ErrorExp` + */ +extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc) +{ + return modifiableLvalueImpl(_this, sc, _this); +} + +// e = original / un-lowered expression to print in error messages +private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression e) +{ + assert(e); + Expression visit(Expression exp) + { + //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars()); + // See if this expression is a modifiable lvalue (i.e. not const) + if (exp.isBinAssignExp()) + return exp.toLvalue(sc, "modify"); + + auto type = exp.type; + if (checkModifiable(exp, sc) == Modifiable.yes) + { + assert(type); + if (!type.isMutable()) + { + if (auto dve = exp.isDotVarExp()) + { + if (isNeedThisScope(sc, dve.var)) + for (Dsymbol s = sc.func; s; s = s.toParentLocal()) + { + FuncDeclaration ff = s.isFuncDeclaration(); + if (!ff) + break; + if (!ff.type.isMutable) + { + error(exp.loc, "cannot modify `%s` in `%s` function", exp.toChars(), MODtoChars(type.mod)); + return ErrorExp.get(); + } + } + } + error(exp.loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), exp.toChars()); + return ErrorExp.get(); + } + else if (!type.isAssignable()) + { + error(exp.loc, "cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members", + exp.toChars(), type.toChars()); + return ErrorExp.get(); + } + } + return exp.toLvalueImpl(sc, "modify", e); + } + + Expression visitString(StringExp exp) + { + error(exp.loc, "cannot modify string literal `%s`", exp.toChars()); + return ErrorExp.get(); + } + + Expression visitVar(VarExp exp) + { + //printf("VarExp::modifiableLvalue('%s')\n", exp.var.toChars()); + if (exp.var.storage_class & STC.manifest) + { + error(exp.loc, "cannot modify manifest constant `%s`", exp.toChars()); + return ErrorExp.get(); + } + // See if this expression is a modifiable lvalue (i.e. not const) + return visit(exp); + } + + Expression visitPtr(PtrExp exp) + { + //printf("PtrExp::modifiableLvalue() %s, type %s\n", exp.toChars(), exp.type.toChars()); + Declaration var; + auto e1 = exp.e1; + if (auto se = e1.isSymOffExp()) + var = se.var; + else if (auto ve = e1.isVarExp()) + var = ve.var; + if (var && var.type.isFunction_Delegate_PtrToFunction()) + { + if (var.type.isTypeFunction()) + error(exp.loc, "function `%s` is not an lvalue and cannot be modified", var.toChars()); + else + error(exp.loc, "function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars()); + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitSlice(SliceExp exp) + { + error(exp.loc, "slice expression `%s` is not a modifiable lvalue", exp.toChars()); + return exp; + } + + Expression visitComma(CommaExp exp) + { + exp.e2 = exp.e2.modifiableLvalueImpl(sc, e); + return exp; + } + + Expression visitDelegatePtr(DelegatePtrExp exp) + { + if (sc.setUnsafe(false, exp.loc, "cannot modify delegate pointer in `@safe` code `%s`", exp)) + { + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitDelegateFuncptr(DelegateFuncptrExp exp) + { + if (sc.setUnsafe(false, exp.loc, "cannot modify delegate function pointer in `@safe` code `%s`", exp)) + { + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitIndex(IndexExp exp) + { + //printf("IndexExp::modifiableLvalue(%s)\n", exp.toChars()); + Expression ex = exp.markSettingAAElem(); + if (ex.op == EXP.error) + return ex; + + return visit(exp); + } + + Expression visitCond(CondExp exp) + { + if (!exp.e1.isLvalue() && !exp.e2.isLvalue()) + { + error(exp.loc, "conditional expression `%s` is not a modifiable lvalue", exp.toChars()); + return ErrorExp.get(); + } + exp.e1 = exp.e1.modifiableLvalue(sc); + exp.e2 = exp.e2.modifiableLvalue(sc); + return exp.toLvalue(sc, "modify"); + } + + switch(_this.op) + { + default: return visit(_this); + case EXP.string_: return visitString(_this.isStringExp()); + case EXP.variable: return visitVar(_this.isVarExp()); + case EXP.star: return visitPtr(_this.isPtrExp()); + case EXP.slice: return visitSlice(_this.isSliceExp()); + case EXP.comma: return visitComma(_this.isCommaExp()); + case EXP.delegatePointer: return visitDelegatePtr(_this.isDelegatePtrExp()); + case EXP.delegateFunctionPointer: return visitDelegateFuncptr(_this.isDelegateFuncptrExp()); + case EXP.index: return visitIndex(_this.isIndexExp()); + case EXP.question: return visitCond(_this.isCondExp()); + } +} + + /**************************************************** * Determine if `exp`, which gets its address taken, can do so safely. * Params: @@ -14589,7 +15839,7 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) } if (sc.func && !sc.intypeof && !v.isDataseg()) { - if (global.params.useDIP1000 != FeatureState.enabled && + if (sc.useDIP1000 != FeatureState.enabled && !(v.storage_class & STC.temp) && sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func)) { @@ -14676,15 +15926,12 @@ bool checkAddressable(Expression e, Scope* sc) */ private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f) { - with(exp) - { - bool error = checkDisabled(sc, f); - error |= checkDeprecated(sc, f); - error |= checkPurity(sc, f); - error |= checkSafety(sc, f); - error |= checkNogc(sc, f); - return error; - } + bool error = f.checkDisabled(exp.loc, sc); + error |= f.checkDeprecated(exp.loc, sc); + error |= f.checkPurity(exp.loc, sc); + error |= f.checkSafety(exp.loc, sc); + error |= f.checkNogc(exp.loc, sc); + return error; } /******************************* diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index edf113e..351faa47 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -3241,13 +3241,6 @@ unittest assert(mismatches.isMutable); } -private const(char)* prependSpace(const(char)* str) -{ - if (!str || !*str) return ""; - - return (" " ~ str.toDString() ~ "\0").ptr; -} - /// Flag used by $(LREF resolveFuncCall). enum FuncResolveFlag : ubyte { @@ -3361,14 +3354,11 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, const(char)* lastprms = parametersTypeToChars(tf1.parameterList); const(char)* nextprms = parametersTypeToChars(tf2.parameterList); - const(char)* mod1 = prependSpace(MODtoChars(tf1.mod)); - const(char)* mod2 = prependSpace(MODtoChars(tf2.mod)); - .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`", s.parent.toPrettyChars(), s.ident.toChars(), fargsBuf.peekChars(), - m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, mod1, - m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, mod2); + m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(), + m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars()); return null; } @@ -3422,15 +3412,25 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (!tf) tf = fd.originalType.toTypeFunction(); - if (tthis && !MODimplicitConv(tthis.mod, tf.mod)) // modifier mismatch + // modifier mismatch + if (tthis && (fd.isCtorDeclaration() ? + !MODimplicitConv(tf.mod, tthis.mod) : + !MODimplicitConv(tthis.mod, tf.mod))) { OutBuffer thisBuf, funcBuf; MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod); auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod); if (hasOverloads) { - .error(loc, "none of the overloads of `%s` are callable using a %sobject", - fd.ident.toChars(), thisBuf.peekChars()); + OutBuffer buf; + buf.argExpTypesToCBuffer(fargs); + if (fd.isCtorDeclaration()) + .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`", + fd.toChars(), thisBuf.peekChars(), buf.peekChars()); + else + .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`", + fd.toChars(), thisBuf.peekChars(), buf.peekChars()); + if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, fd, sc.isDeprecated()); return null; @@ -3447,8 +3447,12 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, return null; } - .error(loc, "%smethod `%s` is not callable using a %sobject", - funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars()); + if (fd.isCtorDeclaration()) + .error(loc, "%s%s `%s` cannot construct a %sobject", + funcBuf.peekChars(), fd.kind(), fd.toPrettyChars(), thisBuf.peekChars()); + else + .error(loc, "%smethod `%s` is not callable using a %sobject", + funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars()); if (mismatches.isNotShared) .errorSupplemental(fd.loc, "Consider adding `shared` here"); @@ -3535,11 +3539,17 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) if (!print) return true; auto tf = cast(TypeFunction) fd.type; + OutBuffer buf; + buf.writestring(fd.toPrettyChars()); + buf.writestring(parametersTypeToChars(tf.parameterList)); + if (tf.mod) + { + buf.writeByte(' '); + buf.MODtoBuffer(tf.mod); + } .errorSupplemental(fd.loc, - printed ? " `%s%s`" : - single_candidate ? "Candidate is: `%s%s`" : "Candidates are: `%s%s`", - fd.toPrettyChars(), - parametersTypeToChars(tf.parameterList)); + printed ? " `%s`" : + single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars()); } else if (auto td = s.isTemplateDeclaration()) { @@ -4621,7 +4631,14 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) case default_: if (!sc.func) return false; - if (!sc.func.isSafeBypassingInference() && !sc.func.safetyViolation) + if (sc.func.isSafeBypassingInference()) + { + if (!gag) + { + warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + } + } + else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); diff --git a/gcc/d/dmd/globals.d b/gcc/d/dmd/globals.d index 2f6fae3..8d88207 100644 --- a/gcc/d/dmd/globals.d +++ b/gcc/d/dmd/globals.d @@ -250,6 +250,12 @@ extern (C++) struct Param const(char)[] resfile; const(char)[] exefile; const(char)[] mapfile; + + /// + bool parsingUnittestsRequired() + { + return useUnitTests || ddoc.doOutput || dihdr.doOutput; + } } enum mars_ext = "d"; // for D source files diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index d935bd3..ac2dda3 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -41,6 +41,7 @@ import dmd.identifier; import dmd.init; import dmd.mtype; import dmd.nspace; +import dmd.optimize; import dmd.parse; import dmd.root.complex; import dmd.root.ctfloat; @@ -1942,7 +1943,7 @@ private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuff { if (i) buf.writestring(", "); - p.templateParameterToBuffer(buf, &hgs); + toCBuffer(p, buf, hgs); } } @@ -2884,10 +2885,10 @@ void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool } } -private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs) +void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs) { - scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs); - tp.accept(v); + scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs); + (cast() tp).accept(v); } private extern (C++) final class TemplateParameterPrettyPrintVisitor : Visitor @@ -3261,12 +3262,6 @@ void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments) } } -void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs) -{ - scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs); - (cast() tp).accept(v); -} - void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects) { if (!objects || !objects.length) @@ -3836,7 +3831,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te { if (i) buf.writestring(", "); - p.templateParameterToBuffer(buf, hgs); + toCBuffer(p, buf, *hgs); } buf.writeByte(')'); } @@ -3861,6 +3856,11 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState buf.writestring("void"); } + void visitDefault(DefaultInitializer iz) + { + buf.writestring("{ }"); + } + void visitStruct(StructInitializer si) { //printf("StructInitializer::toCBuffer()\n"); diff --git a/gcc/d/dmd/iasmgcc.d b/gcc/d/dmd/iasmgcc.d index 5494fec..92837b4 100644 --- a/gcc/d/dmd/iasmgcc.d +++ b/gcc/d/dmd/iasmgcc.d @@ -302,7 +302,7 @@ Ldone: extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc) { //printf("GccAsmStatement.semantic()\n"); - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink, &global.compileEnv, doUnittests); // Make a safe copy of the token list before parsing. @@ -341,7 +341,7 @@ extern (C++) public Statement gccAsmSemantic(GccAsmStatement s, Scope *sc) e = e.expressionSemantic(sc); // Check argument is a valid lvalue/rvalue. if (i < s.outputargs) - e = e.modifiableLvalue(sc, null); + e = e.modifiableLvalue(sc); else if (e.checkValue()) e = ErrorExp.get(); (*s.args)[i] = e; diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 5fcda91..32221d9 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -323,6 +323,8 @@ immutable Msgtable[] msgtable = { "_d_newitemTTrace" }, { "_d_newarrayT" }, { "_d_newarrayTTrace" }, + { "_d_newarraymTX" }, + { "_d_newarraymTXTrace" }, { "_d_assert_fail" }, { "dup" }, { "_aaApply" }, @@ -366,7 +368,6 @@ immutable Msgtable[] msgtable = { "_d_arraysetlengthTTrace"}, { "_d_arrayappendT" }, { "_d_arrayappendTTrace" }, - { "_d_arrayappendcTXImpl" }, { "_d_arrayappendcTX" }, { "_d_arrayappendcTXTrace" }, { "_d_arraycatnTX" }, diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h index 31ee61a..aeb3621 100644 --- a/gcc/d/dmd/import.h +++ b/gcc/d/dmd/import.h @@ -43,9 +43,7 @@ public: Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees void importAll(Scope *sc) override; Dsymbol *toAlias() override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope* sc) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool overloadInsert(Dsymbol *s) override; Import *isImport() override { return this; } diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d index 98ac903..2c7699b 100644 --- a/gcc/d/dmd/importc.d +++ b/gcc/d/dmd/importc.d @@ -20,6 +20,7 @@ import dmd.dcast; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.errors; import dmd.expression; import dmd.expressionsem; diff --git a/gcc/d/dmd/init.d b/gcc/d/dmd/init.d index ebcd011..e484100 100644 --- a/gcc/d/dmd/init.d +++ b/gcc/d/dmd/init.d @@ -68,6 +68,11 @@ extern (C++) class Initializer : ASTNode return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null; } + final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure + { + return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null; + } + final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure { return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null; @@ -112,6 +117,24 @@ extern (C++) final class VoidInitializer : Initializer } /*********************************************************** + * The C23 default initializer `{ }` + */ +extern (C++) final class DefaultInitializer : Initializer +{ + Type type; // type that this will initialize to + + extern (D) this(const ref Loc loc) @safe + { + super(loc, InitKind.default_); + } + + override void accept(Visitor v) + { + v.visit(this); + } +} + +/*********************************************************** */ extern (C++) final class ErrorInitializer : Initializer { @@ -266,6 +289,11 @@ Initializer syntaxCopy(Initializer inx) return new VoidInitializer(vi.loc); } + static Initializer visitDefault(DefaultInitializer vi) + { + return new DefaultInitializer(vi.loc); + } + static Initializer visitError(ErrorInitializer vi) { return vi; @@ -352,6 +380,7 @@ mixin template VisitInitializer(Result) final switch (init.kind) { case InitKind.void_: mixin(visitCase("Void")); break; + case InitKind.default_: mixin(visitCase("Default")); break; case InitKind.error: mixin(visitCase("Error")); break; case InitKind.struct_: mixin(visitCase("Struct")); break; case InitKind.array: mixin(visitCase("Array")); break; diff --git a/gcc/d/dmd/init.h b/gcc/d/dmd/init.h index 67d0527..21bd07f 100644 --- a/gcc/d/dmd/init.h +++ b/gcc/d/dmd/init.h @@ -20,6 +20,7 @@ class Expression; class Type; class ErrorInitializer; class VoidInitializer; +class DefaultInitializer; class StructInitializer; class ArrayInitializer; class ExpInitializer; @@ -37,6 +38,7 @@ public: ErrorInitializer *isErrorInitializer(); VoidInitializer *isVoidInitializer(); + DefaultInitializer *isDefaultInitializer(); StructInitializer *isStructInitializer(); ArrayInitializer *isArrayInitializer(); ExpInitializer *isExpInitializer(); @@ -53,6 +55,14 @@ public: void accept(Visitor *v) override { v->visit(this); } }; +class DefaultInitializer final : public Initializer +{ +public: + Type *type; // type that this will initialize to + + void accept(Visitor *v) override { v->visit(this); } +}; + class ErrorInitializer final : public Initializer { public: diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 632c0d0..76c2d89 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -24,6 +24,7 @@ import dmd.dinterpret; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; @@ -38,6 +39,7 @@ import dmd.init; import dmd.location; import dmd.mtype; import dmd.opover; +import dmd.optimize; import dmd.statement; import dmd.target; import dmd.tokens; @@ -105,6 +107,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai) */ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret) { + //printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars()); Type t = tx; static Initializer err() @@ -118,6 +121,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ return i; } + Initializer visitDefault(DefaultInitializer i) + { + i.type = t; + return i; + } + Initializer visitError(ErrorInitializer i) { return i; @@ -1016,6 +1025,12 @@ Initializer inferType(Initializer init, Scope* sc) return new ErrorInitializer(); } + Initializer visitDefault(DefaultInitializer i) + { + error(i.loc, "cannot infer type from default initializer"); + return new ErrorInitializer(); + } + Initializer visitError(ErrorInitializer i) { return i; @@ -1174,6 +1189,11 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n return null; } + Expression visitDefault(DefaultInitializer di) + { + return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null; + } + Expression visitError(ErrorInitializer) { return ErrorExp.get(); diff --git a/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d index ec070d8..d19d435 100644 --- a/gcc/d/dmd/lambdacomp.d +++ b/gcc/d/dmd/lambdacomp.d @@ -22,6 +22,7 @@ import dmd.astenums; import dmd.declaration; import dmd.denum; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.expression; import dmd.func; diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index a1214b2..b8faec7 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -3258,6 +3258,24 @@ class Lexer scanloc.linnum = scanloc.linnum + 1; line = p; } + + /**************************** + * Print the tokens from the current `token` to the end, + * while not advancing the parser forward. + * Useful for debugging. + */ + void printRestOfTokens() + { + auto tk = &token; + while (1) + { + printf("%s ", (*tk).toChars()); + if (tk.value == TOK.endOfFile) + break; + tk = peek(tk); + } + printf("\n"); + } } diff --git a/gcc/d/dmd/module.h b/gcc/d/dmd/module.h index 6e8153d..92efc16 100644 --- a/gcc/d/dmd/module.h +++ b/gcc/d/dmd/module.h @@ -43,7 +43,6 @@ public: bool isAncestorPackageOf(const Package * const pkg) const; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; void accept(Visitor *v) override { v->visit(this); } Module *isPackageMod(); @@ -124,7 +123,6 @@ public: Module *parse(); // syntactic parse void importAll(Scope *sc) override; int needModuleInfo(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override; Dsymbol *symtabInsert(Dsymbol *s) override; static void runDeferredSemantic(); diff --git a/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d index 59bf1d5..e59b010 100644 --- a/gcc/d/dmd/nogc.d +++ b/gcc/d/dmd/nogc.d @@ -108,12 +108,6 @@ public: return; f.printGCUsage(e.loc, "setting `length` may cause a GC allocation"); } - else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX) - { - if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`")) - return; - f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation"); - } } override void visit(ArrayLiteralExp e) @@ -187,20 +181,14 @@ public: override void visit(CatAssignExp e) { - /* CatAssignExp will exist in `__traits(compiles, ...)` and in the `.e1` branch of a `__ctfe ? :` CondExp. - * The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about - * GC usage. See visit(CallExp). - */ if (checkOnly) { err = true; return; } - if (f.setGC(e.loc, null)) - { - err = true; + if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`")) return; - } + f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation"); } override void visit(CatExp e) diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d index 2d3367a..a49e0bf 100644 --- a/gcc/d/dmd/nspace.d +++ b/gcc/d/dmd/nspace.d @@ -85,33 +85,6 @@ extern (C++) final class Nspace : ScopeDsymbol return ns; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - ScopeDsymbol.addMember(sc, sds); - - if (members) - { - if (!symtab) - symtab = new DsymbolTable(); - // The namespace becomes 'imported' into the enclosing scope - for (Scope* sce = sc; 1; sce = sce.enclosing) - { - ScopeDsymbol sds2 = sce.scopesym; - if (sds2) - { - sds2.importScope(this, Visibility(Visibility.Kind.public_)); - break; - } - } - assert(sc); - sc = sc.push(this); - sc.linkage = LINK.cpp; // namespaces default to C++ linkage - sc.parent = this; - members.foreachDsymbol(s => s.addMember(sc, this)); - sc.pop(); - } - } - override void setScope(Scope* sc) { ScopeDsymbol.setScope(sc); @@ -126,22 +99,6 @@ extern (C++) final class Nspace : ScopeDsymbol } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars()); - if (_scope && !symtab) - dsymbolSemantic(this, _scope); - - if (!members || !symtab) // opaque or semantic() is not yet called - { - if (!(flags & IgnoreErrors)) - .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars()); - return null; - } - - return ScopeDsymbol.search(loc, ident, flags); - } - override bool hasPointers() { //printf("Nspace::hasPointers() %s\n", toChars()); diff --git a/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h index e9fb7bd..7d30402 100644 --- a/gcc/d/dmd/nspace.h +++ b/gcc/d/dmd/nspace.h @@ -21,9 +21,7 @@ class Nspace final : public ScopeDsymbol public: Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d index addcd01..b7bc925 100644 --- a/gcc/d/dmd/opover.d +++ b/gcc/d/dmd/opover.d @@ -23,6 +23,7 @@ import dmd.declaration; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; @@ -34,6 +35,7 @@ import dmd.id; import dmd.identifier; import dmd.location; import dmd.mtype; +import dmd.optimize; import dmd.statement; import dmd.tokens; import dmd.typesem; diff --git a/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d index 0065b01..a979168 100644 --- a/gcc/d/dmd/optimize.d +++ b/gcc/d/dmd/optimize.d @@ -272,9 +272,9 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type) * Returns: * Constant folded version of `e` */ -Expression Expression_optimize(Expression e, int result, bool keepLvalue) +Expression optimize(Expression e, int result, bool keepLvalue = false) { - //printf("Expression_optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue); + //printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue); Expression ret = e; void errorReturn() @@ -288,7 +288,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) { if (!e) return false; - Expression ex = Expression_optimize(e, flags, keepLvalue); + Expression ex = optimize(e, flags, keepLvalue); if (ex.op == EXP.error) { ret = ex; // store error result @@ -591,7 +591,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) Expression add = new AddExp(ae.loc, ex, new IntegerExp(ae.e2.loc, offset, ae.e2.type)); add.type = e.type; - ret = Expression_optimize(add, result, keepLvalue); + ret = optimize(add, result, keepLvalue); return; } } @@ -928,6 +928,14 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) } } + void visitCatAssign(CatAssignExp e) + { + if (auto lowering = e.lowering) + optimize(lowering, result, keepLvalue); + else + visitBinAssign(e); + } + void visitBin(BinExp e) { //printf("BinExp::optimize(result = %d) %s\n", result, e.toChars()); @@ -1239,7 +1247,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) ret = new CastExp(e.loc, ret, Type.tvoid); ret.type = e.type; } - ret = Expression_optimize(ret, result, false); + ret = optimize(ret, result, false); return; } expOptimize(e.e2, WANTvalue); @@ -1294,7 +1302,7 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) // `["c"] ~ "a" ~ "b"` becoming `["c"] ~ "ab"` scope CatExp cex = new CatExp(e.loc, ce1.e2, e.e2); cex.type = e.type; - Expression ex = Expression_optimize(cex, result, false); + Expression ex = optimize(cex, result, false); if (ex != cex) { e.e1 = ce1.e1; @@ -1323,9 +1331,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) return; const opt = e.econd.toBool(); if (opt.hasValue(true)) - ret = Expression_optimize(e.e1, result, keepLvalue); + ret = optimize(e.e1, result, keepLvalue); else if (opt.hasValue(false)) - ret = Expression_optimize(e.e2, result, keepLvalue); + ret = optimize(e.e2, result, keepLvalue); else { expOptimize(e.e1, result, keepLvalue); @@ -1392,9 +1400,9 @@ Expression Expression_optimize(Expression e, int result, bool keepLvalue) case EXP.leftShiftAssign: case EXP.rightShiftAssign: case EXP.unsignedRightShiftAssign: + case EXP.concatenateDcharAssign: visitBinAssign(ex.isBinAssignExp()); break; case EXP.concatenateElemAssign: - case EXP.concatenateDcharAssign: - case EXP.concatenateAssign: visitBinAssign(ex.isBinAssignExp()); break; + case EXP.concatenateAssign: visitCatAssign(cast(CatAssignExp) ex); break; case EXP.minusMinus: case EXP.plusPlus: diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 51e522d..f9d174a 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -4878,30 +4878,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Declaration v; AST.Dsymbol s; - // try to parse function type: - // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes bool attributesAppended; const StorageClass funcStc = parseTypeCtor(); - Token* tlu = &token; Token* tk; - if (token.value != TOK.function_ && - token.value != TOK.delegate_ && - isBasicType(&tlu) && tlu && - tlu.value == TOK.leftParenthesis) - { - AST.Type tret = parseBasicType(); - auto parameterList = parseParameterList(null); - - parseAttributes(); - if (udas) - error("user-defined attributes not allowed for `alias` declarations"); - - attributesAppended = true; - storage_class = appendStorageClass(storage_class, funcStc); - AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class); - v = new AST.AliasDeclaration(loc, ident, tf); - } - else if (token.value == TOK.function_ || + // function literal? + if (token.value == TOK.function_ || token.value == TOK.delegate_ || token.value == TOK.leftParenthesis && skipAttributes(peekPastParen(&token), &tk) && @@ -4911,10 +4892,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis && skipAttributes(peekPastParen(peek(&token)), &tk) && (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) || - token.value == TOK.auto_ && peekNext() == TOK.ref_ && - peekNext2() == TOK.leftParenthesis && - skipAttributes(peekPastParen(peek(peek(&token))), &tk) && - (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) + token.value == TOK.auto_ && + (peekNext() == TOK.leftParenthesis || // for better error + peekNext() == TOK.ref_ && + peekNext2() == TOK.leftParenthesis) ) { // function (parameters) { statements... } @@ -4955,21 +4936,46 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else { - parseAttributes(); // type + parseAttributes(); if (udas) error("user-defined attributes not allowed for `alias` declarations"); - auto t = parseType(); + auto t = parseBasicType(); + t = parseTypeSuffixes(t); + if (token.value == TOK.identifier) + { + error("unexpected identifier `%s` after `%s`", + token.ident.toChars(), t.toChars()); + nextToken(); + } + else if (token.value == TOK.leftParenthesis) + { + // function type: + // StorageClasses Type ( Parameters ) MemberFunctionAttributes + auto parameterList = parseParameterList(null); + udas = null; + parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc); + if (udas) + error("user-defined attributes not allowed for `alias` declarations"); + + attributesAppended = true; + // Note: method types can have a TypeCtor attribute + storage_class = appendStorageClass(storage_class, funcStc); + t = new AST.TypeFunction(parameterList, t, link, storage_class); + } // Disallow meaningless storage classes on type aliases if (storage_class) { // Don't raise errors for STC that are part of a function/delegate type, e.g. // `alias F = ref pure nothrow @nogc @safe int function();` - auto tp = t.isTypePointer; - const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate; - const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class; + const remStc = t.isTypeFunction ? + storage_class & ~(STC.FUNCATTR | STC.TYPECTOR) : { + auto tp = t.isTypePointer; + const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate; + return isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class; + }(); if (remStc) { @@ -7217,6 +7223,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer return false; } + // pt = test token. If found, pt is set to the token after BasicType private bool isBasicType(Token** pt) { // This code parallels parseBasicType() diff --git a/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d index a4a9434..3d0a585 100644 --- a/gcc/d/dmd/parsetimevisitor.d +++ b/gcc/d/dmd/parsetimevisitor.d @@ -298,5 +298,6 @@ public: void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.ArrayInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.VoidInitializer i) { visit(cast(AST.Initializer)i); } + void visit(AST.DefaultInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.CInitializer i) { visit(cast(AST.CInitializer)i); } } diff --git a/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h index 178542e..2cac5f2 100644 --- a/gcc/d/dmd/scope.h +++ b/gcc/d/dmd/scope.h @@ -61,6 +61,9 @@ enum class SCOPE Cfile = 0x0800, // C semantics apply free = 0x8000, // is on free list fullinst = 0x10000, // fully instantiate templates + ctfeBlock = 0x20000, // inside a `if (__ctfe)` block + dip1000 = 0x40000, // dip1000 errors enabled for this scope + dip25 = 0x80000, // dip25 errors enabled for this scope }; struct Scope @@ -126,4 +129,6 @@ struct Scope AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value, // do not set wasRead for it + + Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, int flags = IgnoreNone); }; diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 0b0ca91..c255701 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -54,6 +54,7 @@ import dmd.nspace; import dmd.ob; import dmd.objc; import dmd.opover; +import dmd.optimize; import dmd.parse; import dmd.root.filename; import dmd.common.outbuffer; @@ -917,7 +918,7 @@ private extern(C++) final class Semantic3Visitor : Visitor if (f.isref) { // Function returns a reference - exp = exp.toLvalue(sc2, exp); + exp = exp.toLvalue(sc2, "`ref` return"); checkReturnEscapeRef(sc2, exp, false); exp = exp.optimize(WANTvalue, /*keepLvalue*/ true); } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index d43d915..3873adc 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -55,6 +55,7 @@ import dmd.location; import dmd.mtype; import dmd.mustuse; import dmd.nogc; +import dmd.optimize; import dmd.opover; import dmd.parse; import dmd.common.outbuffer; @@ -3800,7 +3801,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, { version (none) { - if (global.params.useDIP1000 == FeatureState.enabled) + if (sc2.useDIP1000 == FeatureState.enabled) { message(loc, "To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`"); } @@ -3808,7 +3809,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, } else { - if (global.params.useDIP1000 == FeatureState.enabled) + if (sc2.useDIP1000 == FeatureState.enabled) ++(cast(FuncExp)flde).fd.tookAddressOf; // allocate a closure unless the opApply() uses 'scope' } assert(tab.ty == Tstruct || tab.ty == Tclass); @@ -4887,7 +4888,7 @@ private Statements* flatten(Statement statement, Scope* sc) const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); auto loc = adjustLocForMixin(str, cs.loc, global.params.mixinOut); scope p = new Parser!ASTCodegen(loc, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests); p.transitionIn = global.params.v.vin; diff --git a/gcc/d/dmd/staticassert.d b/gcc/d/dmd/staticassert.d index 15c46b3..7f22c4c 100644 --- a/gcc/d/dmd/staticassert.d +++ b/gcc/d/dmd/staticassert.d @@ -52,11 +52,6 @@ extern (C++) final class StaticAssert : Dsymbol return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - // we didn't add anything - } - override bool oneMember(Dsymbol* ps, Identifier ident) { //printf("StaticAssert::oneMember())\n"); diff --git a/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h index 2b7d300..c0d5363 100644 --- a/gcc/d/dmd/staticassert.h +++ b/gcc/d/dmd/staticassert.h @@ -21,7 +21,6 @@ public: Expressions *msg; StaticAssert *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; const char *kind() const override; StaticAssert *isStaticAssert() override { return this; } diff --git a/gcc/d/dmd/staticcond.d b/gcc/d/dmd/staticcond.d index 923f1a9..1d18de3 100644 --- a/gcc/d/dmd/staticcond.d +++ b/gcc/d/dmd/staticcond.d @@ -22,6 +22,7 @@ import dmd.expressionsem; import dmd.globals; import dmd.identifier; import dmd.mtype; +import dmd.optimize; import dmd.root.array; import dmd.common.outbuffer; import dmd.tokens; diff --git a/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d index ca2af79..0acadbb 100644 --- a/gcc/d/dmd/traits.d +++ b/gcc/d/dmd/traits.d @@ -32,6 +32,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.func; @@ -42,6 +43,7 @@ import dmd.identifier; import dmd.location; import dmd.mtype; import dmd.nogc; +import dmd.optimize; import dmd.parse; import dmd.root.array; import dmd.root.speller; @@ -91,43 +93,50 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg) } /** - * get an array of size_t values that indicate possible pointer words in memory - * if interpreted as the type given as argument - * Returns: the size of the type in bytes, ulong.max on error + * Fill an array of target size_t values that indicate possible pointer words in memory + * if interpreted as the type given as argument. + * One bit in the array per pointer-sized piece of memory + * Params: + * loc = location for error messages + * t = type to generate pointer bitmap from + * data = array forming the bitmap + * eSink = error message sink + * Returns: + * size of the type `t` in bytes, ulong.max on error */ -ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) +ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink) { - ulong sz; - if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration()) - sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc); - else - sz = t.size(loc); + auto tc = t.isTypeClass(); + const ulong sz = (tc && !tc.sym.isInterfaceDeclaration()) + ? tc.sym.AggregateDeclaration.size(loc) + : t.size(loc); if (sz == SIZE_INVALID) return ulong.max; - const sz_size_t = Type.tsize_t.size(loc); + const sz_size_t = Type.tsize_t.size(loc); // size of target's size_t + assert(sz_size_t <= ulong.sizeof); if (sz > sz.max - sz_size_t) { - error(loc, "size overflow for type `%s`", t.toChars()); + eSink.error(loc, "size overflow for type `%s`", t.toChars()); return ulong.max; } - ulong bitsPerWord = sz_size_t * 8; - ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; - ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord; + const ulong bitsPerElement = sz_size_t * 8; // bits used in each array element + const ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; // pointers have same size as sz_size_t + const ulong length = (cntptr + bitsPerElement - 1) / bitsPerElement; // a bit per pointer - data.setDim(cast(size_t)cntdata); + data.setDim(cast(size_t)length); data.zero(); ulong offset; - bool error; + bool error; // sticky error indicator void visit(Type t) { void setpointer(ulong off) { ulong ptroff = off / sz_size_t; - (*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t)); + data[cast(size_t)(ptroff / bitsPerElement)] |= 1L << (ptroff % bitsPerElement); } void visitType(Type t) @@ -246,7 +255,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) visit.VisitType(t); } - if (auto tc = t.isTypeClass()) + if (auto tcx = t.isTypeClass()) { // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references void visitTopLevelClass(TypeClass t) @@ -263,7 +272,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) offset = classoff; } - visitTopLevelClass(tc); + visitTopLevelClass(tcx); } else visit(t); @@ -280,28 +289,28 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) * * Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...] */ -private Expression pointerBitmap(TraitsExp e) +private Expression pointerBitmap(TraitsExp e, ErrorSink eSink) { if (!e.args || e.args.length != 1) { - error(e.loc, "a single type expected for trait pointerBitmap"); + eSink.error(e.loc, "a single type expected for trait pointerBitmap"); return ErrorExp.get(); } Type t = getType((*e.args)[0]); if (!t) { - error(e.loc, "`%s` is not a type", (*e.args)[0].toChars()); + eSink.error(e.loc, "`%s` is not a type", (*e.args)[0].toChars()); return ErrorExp.get(); } Array!(ulong) data; - ulong sz = getTypePointerBitmap(e.loc, t, &data); + const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink); if (sz == ulong.max) return ErrorExp.get(); auto exps = new Expressions(data.length + 1); - (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); + (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); // [0] is size in bytes of t foreach (size_t i; 1 .. exps.length) (*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t); @@ -471,13 +480,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } if (e.ident == Id.isAbstractClass) { - return isTypeX(t => t.toBasetype().ty == Tclass && - (cast(TypeClass)t.toBasetype()).sym.isAbstract()); + return isTypeX(t => t.toBasetype().isTypeClass() && + t.toBasetype().isTypeClass().sym.isAbstract()); } if (e.ident == Id.isFinalClass) { - return isTypeX(t => t.toBasetype().ty == Tclass && - ((cast(TypeClass)t.toBasetype()).sym.storage_class & STC.final_) != 0); + return isTypeX(t => t.toBasetype().isTypeClass() && + (t.toBasetype().isTypeClass().sym.storage_class & STC.final_) != 0); } if (e.ident == Id.isTemplate) { @@ -507,7 +516,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } Type tb = t.baseElemOf(); - if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null) + auto ts = tb.isTypeStruct(); + if (auto sd = ts ? ts.sym : null) { return sd.isPOD() ? True() : False(); } @@ -528,7 +538,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } Type tb = t.baseElemOf(); - if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null) + auto ts = tb.isTypeStruct(); + if (auto sd = ts ? ts.sym : null) { return (e.ident == Id.hasPostblit) ? (sd.postblit ? True() : False()) : (sd.hasCopyCtor ? True() : False()); @@ -792,10 +803,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc) { if (auto p = s.toParent()) // `C`'s parent is `C!2`, believe it or not { - if (p.isTemplateInstance()) // `C!2` is a template instance + if (auto ti = p.isTemplateInstance()) // `C!2` is a template instance { s = p; // `C!2`'s parent is `T1` - auto td = (cast(TemplateInstance)p).tempdecl; + auto td = ti.tempdecl; if (td) s = td; // get the declaration context just in case there's two contexts } @@ -1296,7 +1307,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) if (fd && fd.parent && fd.parent.isTemplateInstance) { fd.functionSemantic3(); - tf = cast(TypeFunction)fd.type; + tf = fd.type.isTypeFunction(); } auto mods = new Expressions(); @@ -1737,9 +1748,9 @@ Expression semanticTraits(TraitsExp e, Scope* sc) ex = ex.expressionSemantic(sc2); ex = resolvePropertiesOnly(sc2, ex); ex = ex.optimize(WANTvalue); - if (sc2.func && sc2.func.type.ty == Tfunction) + if (sc2.func && sc2.func.type.isTypeFunction()) { - const tf = cast(TypeFunction)sc2.func.type; + const tf = sc2.func.type.isTypeFunction(); err |= tf.isnothrow && canThrow(ex, sc2.func, null); } ex = checkGC(sc2, ex); @@ -1867,7 +1878,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } if (e.ident == Id.getPointerBitmap) { - return pointerBitmap(e); + return pointerBitmap(e, global.errorSink); } if (e.ident == Id.initSymbol) { @@ -1875,16 +1886,24 @@ Expression semanticTraits(TraitsExp e, Scope* sc) return dimError(1); auto o = (*e.args)[0]; - Type t = isType(o); - AggregateDeclaration ad = t ? isAggregate(t) : null; - // Interfaces don't have an init symbol and hence cause linker errors - if (!ad || ad.isInterfaceDeclaration()) + ErrorExp badArgument() { error(e.loc, "struct / class type expected as argument to __traits(initSymbol) instead of `%s`", o.toChars()); return ErrorExp.get(); } + Type t = isType(o); + + if (!t || t.isTypeEnum()) + return badArgument(); + + AggregateDeclaration ad = isAggregate(t); + + // Interfaces don't have an init symbol and hence cause linker errors + if (!ad || ad.isInterfaceDeclaration()) + return badArgument(); + Declaration d = new SymbolDeclaration(ad.loc, ad); d.type = Type.tvoid.arrayOf().constOf(); d.storage_class |= STC.rvalue; diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index bbe11f6..8795002 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -53,6 +53,7 @@ import dmd.visitor; import dmd.mtype; import dmd.objc; import dmd.opover; +import dmd.optimize; import dmd.parse; import dmd.root.complex; import dmd.root.ctfloat; @@ -1098,7 +1099,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) if (isRefOrOut && !isAuto && !(global.params.previewIn && (fparam.storageClass & STC.in_)) && global.params.rvalueRefParam != FeatureState.enabled) - e = e.toLvalue(sc, e); + e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from"); fparam.defaultArg = e; return (e.op != EXP.error); @@ -3748,7 +3749,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag } // check before alias resolution; the alias itself might be deprecated! if (s.isAliasDeclaration) - e.checkDeprecated(sc, s); + s.checkDeprecated(e.loc, sc); s = s.toAlias(); if (auto em = s.isEnumMember()) @@ -5009,7 +5010,7 @@ RootObject compileTypeMixin(TypeMixin tm, ref const Loc loc, Scope* sc) const len = buf.length; buf.writeByte(0); const str = buf.extractSlice()[0 .. len]; - const bool doUnittests = global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput; + const bool doUnittests = global.params.parsingUnittestsRequired(); auto locm = adjustLocForMixin(str, loc, global.params.mixinOut); scope p = new Parser!ASTCodegen(locm, sc._module, str, false, global.errorSink, &global.compileEnv, doUnittests); p.transitionIn = global.params.v.vin; diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h index 697d46e..c268bc9 100644 --- a/gcc/d/dmd/version.h +++ b/gcc/d/dmd/version.h @@ -20,7 +20,6 @@ public: DebugSymbol *syntaxCopy(Dsymbol *) override; const char *toChars() const override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; DebugSymbol *isDebugSymbol() override; void accept(Visitor *v) override { v->visit(this); } @@ -34,7 +33,6 @@ public: VersionSymbol *syntaxCopy(Dsymbol *) override; const char *toChars() const override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; VersionSymbol *isVersionSymbol() override; void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h index 3d8c3e6..360784a 100644 --- a/gcc/d/dmd/visitor.h +++ b/gcc/d/dmd/visitor.h @@ -176,6 +176,7 @@ class NewDeclaration; class Initializer; class VoidInitializer; +class DefaultInitializer; class ErrorInitializer; class StructInitializer; class ArrayInitializer; @@ -591,6 +592,7 @@ public: virtual void visit(StructInitializer *i) { visit((Initializer *)i); } virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); } virtual void visit(VoidInitializer *i) { visit((Initializer *)i); } + virtual void visit(DefaultInitializer *i) { visit((Initializer *)i); } virtual void visit(CInitializer *i) { visit((Initializer *)i); } }; diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 17801a3..a907979 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -789,42 +789,58 @@ public: void visit (CatAssignExp *e) final override { + if (!global.params.useGC) + { + error_at (make_location_t (e->loc), + "appending to array in %qs requires the GC and cannot be " + "used with %<-fno-druntime%>", e->toChars ()); + this->result_ = error_mark_node; + return; + } + Type *tb1 = e->e1->type->toBasetype (); Type *tb2 = e->e2->type->toBasetype (); - Type *etype = tb1->nextOf ()->toBasetype (); - - /* Save the address of `e1', so it can be evaluated first. - As all D run-time library functions for concat assignments update `e1' - in-place and then return its value, the saved address can also be used as - the result of this expression as well. */ - tree lhs = build_expr (e->e1); - tree lexpr = stabilize_expr (&lhs); - tree ptr = d_save_expr (build_address (lhs)); - tree result = NULL_TREE; - if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar - && (etype->ty == TY::Tchar || etype->ty == TY::Twchar)) + if (e->op == EXP::concatenateDcharAssign) { /* Append a dchar to a char[] or wchar[]: The assignment is handled by the D run-time library, so only need to call `_d_arrayappend[cw]d(&e1, e2)' */ + Type *etype = tb1->nextOf ()->toBasetype (); + + /* Save the address of `e1', so it can be evaluated first. + As all D run-time library functions for concat assignments update + `e1' in-place and then return its value, the saved address can also + be used as the result of this expression as well. */ + tree lhs = build_expr (e->e1); + tree lexpr = stabilize_expr (&lhs); + tree ptr = d_save_expr (build_address (lhs)); + tree result = NULL_TREE; + + gcc_assert (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar + && (etype->ty == TY::Tchar || etype->ty == TY::Twchar)); + libcall_fn libcall = (etype->ty == TY::Tchar) ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD; result = build_libcall (libcall, e->type, 2, ptr, build_expr (e->e2)); + + /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */ + result = compound_expr (compound_expr (lexpr, ptr), result); + this->result_ = compound_expr (result, build_deref (ptr)); } else { + gcc_assert (e->op == EXP::concatenateAssign + || e->op == EXP::concatenateElemAssign); + gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray); /* Appending an element or array to another array has already been handled by the front-end. */ - gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray); - gcc_unreachable (); - } + gcc_assert (e->lowering); - /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */ - result = compound_expr (compound_expr (lexpr, ptr), result); - this->result_ = compound_expr (result, build_deref (ptr)); + this->result_ = build_expr (e->lowering); + } } /* Build an assignment expression. The right operand is implicitly @@ -2359,50 +2375,9 @@ public: /* Allocating memory for a new D array. */ gcc_assert (e->arguments && e->arguments->length >= 1); - if (e->arguments->length == 1) - { - /* Single dimension array allocations has already been handled by - the front-end. */ - gcc_assert (e->lowering); - result = build_expr (e->lowering); - } - else - { - /* Multidimensional array allocations. */ - tree tarray = make_array_type (Type::tsize_t, e->arguments->length); - tree var = build_local_temp (tarray); - vec <constructor_elt, va_gc> *elms = NULL; - - /* Get the base element type for the array, generating the - initializer for the dims parameter along the way. */ - Type *telem = e->newtype->toBasetype (); - for (size_t i = 0; i < e->arguments->length; i++) - { - Expression *arg = (*e->arguments)[i]; - CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg)); - - gcc_assert (telem->ty == TY::Tarray); - telem = telem->toBasetype ()->nextOf (); - gcc_assert (telem); - } - - /* Initialize the temporary. */ - tree init = modify_expr (var, build_constructor (tarray, elms)); - var = compound_expr (init, var); - - /* Generate: _d_newarraymTX(ti, dims) - or: _d_newarraymiTX(ti, dims) */ - libcall_fn libcall = telem->isZeroInit () - ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX; - - tree tinfo = build_typeinfo (e, e->type); - tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()), - size_int (e->arguments->length), - build_address (var)); - - result = build_libcall (libcall, e->newtype->toBasetype (), 2, - tinfo, dims); - } + /* Array allocations have already been handled by the front-end. */ + gcc_assert (e->lowering != NULL); + result = build_expr (e->lowering); if (e->argprefix) result = compound_expr (build_expr (e->argprefix), result); diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def index f7887e1..3307b3b 100644 --- a/gcc/d/runtime.def +++ b/gcc/d/runtime.def @@ -70,13 +70,6 @@ DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT), DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT), P2(OBJECT, CLASSINFO), 0) -/* Used when calling `new' on a multi-dimensional array. - The `i' variant is for when the initializer is nonzero. */ -DEF_D_RUNTIME (NEWARRAYMTX, "_d_newarraymTX", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0) -DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID), - P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0) - /* Used for allocating an array literal on the GC heap. */ DEF_D_RUNTIME (ARRAYLITERALTX, "_d_arrayliteralTX", RT(VOIDPTR), P2(CONST_TYPEINFO, SIZE_T), 0) diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index 04f357c..7bfe72b 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -3199,6 +3199,8 @@ directive}: @samp{#if}, @samp{#ifdef} or @samp{#ifndef}. * @code{__has_cpp_attribute}:: * @code{__has_c_attribute}:: * @code{__has_builtin}:: +* @code{__has_feature}:: +* @code{__has_extension}:: * @code{__has_include}:: @end menu @@ -3561,6 +3563,45 @@ the operator is as follows: #endif @end smallexample +@node @code{__has_feature} +@subsection @code{__has_feature} +@cindex @code{__has_feature} + +The special operator @code{__has_feature (@var{operand})} may be used in +constant integer contexts and in preprocessor @samp{#if} and @samp{#elif} +expressions to test whether the identifier given in @var{operand} is recognized +as a feature supported by GCC given the current options and, in the case of +standard language features, whether the feature is available in the chosen +version of the language standard. + +Note that @code{__has_feature} and @code{__has_extension} are not recommended +for use in new code, and are only provided for compatibility with Clang. For +details of which identifiers are accepted by these function-like macros, see +@w{@uref{https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension, +the Clang documentation}}. + +@node @code{__has_extension} +@subsection @code{__has_extension} +@cindex @code{__has_extension} + +The special operator @code{__has_extension (@var{operand})} may be used in +constant integer contexts and in preprocessor @samp{#if} and @samp{#elif} +expressions to test whether the identifier given in @var{operand} is recognized +as an extension supported by GCC given the current options. In any given +context, the features accepted by @code{__has_extension} are a strict superset +of those accepted by @code{__has_feature}. Unlike @code{__has_feature}, +@code{__has_extension} tests whether a given feature is available regardless of +strict language standards conformance. + +If the @option{-pedantic-errors} flag is given, @code{__has_extension} is +equivalent to @code{__has_feature}. + +Note that @code{__has_feature} and @code{__has_extension} are not recommended +for use in new code, and are only provided for compatibility with Clang. For +details of which identifiers are accepted by these function-like macros, see +@w{@uref{https://clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension, +the Clang documentation}}. + @node @code{__has_include} @subsection @code{__has_include} @cindex @code{__has_include} diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8293a7b..1ae589a 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7341,6 +7341,21 @@ Enable/disable the generation of the SM4 instructions. @itemx no-usermsr Enable/disable the generation of the USER_MSR instructions. +@cindex @code{target("avx10.1")} function attribute, x86 +@item avx10.1 +@itemx no-avx10.1 +Enable/disable the generation of the AVX10.1 instructions. + +@cindex @code{target("avx10.1-256")} function attribute, x86 +@item avx10.1-256 +@itemx no-avx10.1-256 +Enable/disable the generation of the AVX10.1 instructions. + +@cindex @code{target("avx10.1-512")} function attribute, x86 +@item avx10.1-512 +@itemx no-avx10.1-512 +Enable/disable the generation of the AVX10.1 512 bit instructions. + @cindex @code{target("cld")} function attribute, x86 @item cld @itemx no-cld @@ -10914,6 +10929,11 @@ sign flag set ``not'' @var{flag}, or inverted versions of those above @end table +@item s390 +The flag output constraint for s390 is @samp{=@@cc}. Only one such +constraint is allowed. The variable has to be stored in a @samp{int} +variable. + @end table @anchor{InputOperands} @@ -14731,11 +14751,11 @@ The @code{__builtin_classify_type} returns a small integer with a category of @var{arg} argument's type, like void type, integer type, enumeral type, boolean type, pointer type, reference type, offset type, real type, complex type, function type, method type, record type, union type, array type, -string type, etc. When the argument is an expression, for -backwards compatibility reason the argument is promoted like arguments -passed to @code{...} in varargs function, so some classes are never returned -in certain languages. Alternatively, the argument of the built-in -function can be a typename, such as the @code{typeof} specifier. +string type, bit-precise integer type, vector type, etc. When the argument +is an expression, for backwards compatibility reason the argument is promoted +like arguments passed to @code{...} in varargs function, so some classes are +never returned in certain languages. Alternatively, the argument of the +built-in function can be a typename, such as the @code{typeof} specifier. @smallexample int a[2]; @@ -15060,6 +15080,125 @@ unsigned integer (standard, extended or bit-precise). No integral argument promotions are performed on the argument. @enddefbuiltin +@defbuiltin{@var{type} __builtin_stdc_bit_ceil (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_ceil} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{@var{arg} <= 1 ? (@var{type}) 1 +: (@var{type}) 2 << (@var{prec} - 1 - __builtin_clzg ((@var{type}) (@var{arg} - 1)))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg} are evaluated just once. +@enddefbuiltin + +@defbuiltin{@var{type} __builtin_stdc_bit_floor (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_floor} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{@var{arg} == 0 ? (@var{type}) 0 +: (@var{type}) 1 << (@var{prec} - 1 - __builtin_clzg (@var{arg}))} +where @var{prec} is bit width of @var{type}, except that side-effects +in @var{arg} are evaluated just once. +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_bit_width (@var{type} @var{arg})} +The @code{__builtin_stdc_bit_width} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) (@var{prec} - __builtin_clzg (@var{arg}, @var{prec}))} +where @var{prec} is bit width of @var{type}. +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_count_ones (@var{type} @var{arg})} +The @code{__builtin_stdc_count_ones} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_popcountg (@var{arg})} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_count_zeros (@var{type} @var{arg})} +The @code{__builtin_stdc_count_zeros} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_popcountg ((@var{type}) ~@var{arg})} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_first_leading_one (@var{type} @var{arg})} +The @code{__builtin_stdc_first_leading_one} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{__builtin_clzg (@var{arg}, -1) + 1U} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_first_leading_zero (@var{type} @var{arg})} +The @code{__builtin_stdc_first_leading_zero} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{__builtin_clzg ((@var{type}) ~@var{arg}, -1) + 1U} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_first_trailing_one (@var{type} @var{arg})} +The @code{__builtin_stdc_first_trailing_one} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{__builtin_ctzg (@var{arg}, -1) + 1U} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_first_trailing_zero (@var{type} @var{arg})} +The @code{__builtin_stdc_first_trailing_zero} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{__builtin_ctzg ((@var{type}) ~@var{arg}, -1) + 1U} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_has_single_bit (@var{type} @var{arg})} +The @code{__builtin_stdc_has_single_bit} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(_Bool) (__builtin_popcountg (@var{arg}) == 1)} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_leading_ones (@var{type} @var{arg})} +The @code{__builtin_stdc_leading_ones} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_clzg ((@var{type}) ~@var{arg}, @var{prec})} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_leading_zeros (@var{type} @var{arg})} +The @code{__builtin_stdc_leading_zeros} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_clzg (@var{arg}, @var{prec})} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_trailing_ones (@var{type} @var{arg})} +The @code{__builtin_stdc_trailing_ones} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_ctzg ((@var{type}) ~@var{arg}, @var{prec})} +@enddefbuiltin + +@defbuiltin{unsigned int __builtin_stdc_trailing_zeros (@var{type} @var{arg})} +The @code{__builtin_stdc_trailing_zeros} function is available only +in C. It is type-generic, the argument can be any unsigned integer +(standard, extended or bit-precise). No integral argument promotions are +performed on the argument. It is equivalent to +@code{(unsigned int) __builtin_ctzg (@var{arg}, @var{prec})} +@enddefbuiltin + @defbuiltin{double __builtin_powi (double, int)} @defbuiltinx{float __builtin_powif (float, int)} @defbuiltinx{{long double} __builtin_powil (long double, int)} diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index f995b77..c1ccb8b 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -628,9 +628,9 @@ HTTPS as tarballs compressed with @command{gzip} or @command{bzip2}. Please refer to the @uref{https://gcc.gnu.org/releases.html,,releases web page} for information on how to obtain GCC@. -The source distribution includes the C, C++, Objective-C, Fortran, -and Ada (in the case of GCC 3.1 and later) compilers, as well as -runtime libraries for C++, Objective-C, and Fortran. +The source distribution includes the Ada, C, C++, Objective-C, D (GCC 9 +and later), Fortran, Go, and Modula-2 (GCC 13 and later) compilers, as +well as runtime libraries for C++, Objective-C, and Fortran. For previous versions these were downloadable as separate components such as the core GCC distribution, which included the C language front end and shared components, and language-specific distributions including the @@ -3991,7 +3991,7 @@ Instead of GNU Binutils, you will need to install LLVM 13.0.1, or later, and cop Use Newlib (4.3.0 or newer). To run the binaries, install the HSA Runtime from the -@uref{https://rocm.github.io,,ROCm Platform}, and use +@uref{https://rocm.docs.amd.com/,,ROCm Platform}, and use @file{libexec/gcc/amdhsa-amdhsa/@var{version}/gcn-run} to launch them on the GPU. @@ -3999,7 +3999,7 @@ To enable support for GCN3 Fiji devices (gfx803), GCC has to be configured with @option{--with-arch=@code{fiji}} or @option{--with-multilib-list=@code{fiji},...}. Note that support for Fiji devices has been removed in ROCm 4.0 and support in LLVM is deprecated and will -be removed in the future. +be removed in LLVM 18. @html <hr /> @@ -4126,14 +4126,6 @@ This configuration is intended for embedded systems. @end html @anchor{x-x-freebsd} @heading *-*-freebsd* -In order to better utilize FreeBSD base system functionality and match -the configuration of the system compiler, GCC 4.5 and above as well as -GCC 4.4 past 2010-06-20 leverage SSP support in libc (which is present -on FreeBSD 7 or later) and the use of @code{__cxa_atexit} by default -(on FreeBSD 6 or later). The use of @code{dl_iterate_phdr} inside -@file{libgcc_s.so.1} and boehm-gc (on FreeBSD 7 or later) is enabled -by GCC 4.5 and above. - We support FreeBSD using the ELF file format with DWARF 2 debugging for all CPU architectures. There are no known issues with mixing object files and libraries with different diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 1f10967..2e6bac3 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -366,7 +366,7 @@ Objective-C and Objective-C++ Dialects}. -Wformat-y2k -Wframe-address -Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object -Wno-if-not-aligned -Wno-ignored-attributes --Wignored-qualifiers -Wno-incompatible-pointer-types +-Wignored-qualifiers -Wno-incompatible-pointer-types -Whardened -Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} -Wno-implicit-function-declaration -Wno-implicit-int -Winfinite-recursion @@ -383,7 +383,7 @@ Objective-C and Objective-C++ Dialects}. -Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} -Wnull-dereference -Wno-odr -Wopenacc-parallelism --Wopenmp-simd +-Wopenmp -Wopenmp-simd -Wno-overflow -Woverlength-strings -Wno-override-init-side-effects -Wpacked -Wno-packed-bitfield-compat -Wpacked-not-aligned -Wpadded -Wparentheses -Wno-pedantic-ms-format @@ -644,7 +644,7 @@ Objective-C and Objective-C++ Dialects}. -fasan-shadow-offset=@var{number} -fsanitize-sections=@var{s1},@var{s2},... -fsanitize-undefined-trap-on-error -fbounds-check -fcf-protection=@r{[}full@r{|}branch@r{|}return@r{|}none@r{|}check@r{]} --fharden-compares -fharden-conditional-branches +-fharden-compares -fharden-conditional-branches -fhardened -fharden-control-flow-redundancy -fhardcfr-skip-leaf -fhardcfr-check-exceptions -fhardcfr-check-returning-calls -fhardcfr-check-noreturn-calls=@r{[}always@r{|}no-xthrow@r{|}nothrow@r{|}never@r{]} @@ -1245,6 +1245,7 @@ See RS/6000 and PowerPC Options. -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} -mstack-protector-guard-offset=@var{offset} -mcsr-check -mno-csr-check +-mmovcc -mno-movcc -minline-atomics -mno-inline-atomics -minline-strlen -mno-inline-strlen -minline-strcmp -mno-inline-strcmp @@ -1453,7 +1454,7 @@ See RS/6000 and PowerPC Options. -mamx-tile -mamx-int8 -mamx-bf16 -muintr -mhreset -mavxvnni -mavx512fp16 -mavxifma -mavxvnniint8 -mavxneconvert -mcmpccxadd -mamx-fp16 -mprefetchi -mraoint -mamx-complex -mavxvnniint16 -msm3 -msha512 -msm4 -mapxf --musermsr +-musermsr -mavx10.1 -mavx10.1-256 -mavx10.1-512 -mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops -minline-stringops-dynamically -mstringop-strategy=@var{alg} -mkl -mwidekl @@ -6872,6 +6873,18 @@ This warning is upgraded to an error by @option{-pedantic-errors}. Same as @option{-Wimplicit-int} and @option{-Wimplicit-function-declaration}. This warning is enabled by @option{-Wall}. +@opindex Whardened +@opindex Wno-hardened +@item -Whardened +Warn when @option{-fhardened} did not enable an option from its set (for +which see @option{-fhardened}). For instance, using @option{-fhardened} +and @option{-fstack-protector} at the same time on the command line causes +@option{-Whardened} to warn because @option{-fstack-protector-strong} is +not enabled by @option{-fhardened}. + +This warning is enabled by default and has effect only when @option{-fhardened} +is enabled. + @opindex Wimplicit-fallthrough @opindex Wno-implicit-fallthrough @item -Wimplicit-fallthrough @@ -8093,7 +8106,7 @@ if the array is referenced as a flexible array member. @opindex Wsuggest-attribute= @opindex Wno-suggest-attribute= -@item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]} +@item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]}returns_nonnull@r{|} Warn for cases where adding an attribute may be beneficial. The attributes currently supported are listed below. @@ -8113,9 +8126,11 @@ attributes currently supported are listed below. @itemx -Wsuggest-attribute=noreturn @itemx -Wmissing-noreturn @itemx -Wsuggest-attribute=malloc +@itemx -Wsuggest-attribute=returns_nonnull +@itemx -Wno-suggest-attribute=returns_nonnull Warn about functions that might be candidates for attributes -@code{pure}, @code{const} or @code{noreturn} or @code{malloc}. The compiler +@code{pure}, @code{const}, @code{noreturn}, @code{malloc} or @code{returns_nonnull}. The compiler only warns for functions visible in other compilation units or (in the case of @code{pure} and @code{const}) if it cannot prove that the function returns normally. A function returns normally if it doesn't contain an infinite loop or @@ -9104,6 +9119,13 @@ Do not warn about C++23 constructs in code being compiled using an older C++ standard. Even without this option, some C++23 constructs will only be diagnosed if @option{-Wpedantic} is used. +@opindex Wc++26-extensions +@opindex Wno-c++26-extensions +@item -Wno-c++26-extensions @r{(C++ and Objective-C++ only)} +Do not warn about C++26 constructs in code being compiled using +an older C++ standard. Even without this option, some C++26 constructs +will only be diagnosed if @option{-Wpedantic} is used. + @opindex Wcast-qual @opindex Wno-cast-qual @item -Wcast-qual @@ -9935,6 +9957,11 @@ Enabled by default. @item -Wopenacc-parallelism Warn about potentially suboptimal choices related to OpenACC parallelism. +@opindex Wopenmp +@opindex Wno-openmp +@item -Wno-openmp +Warn about suspicious OpenMP code. + @opindex Wopenmp-simd @opindex Wno-openmp-simd @item -Wopenmp-simd @@ -17628,6 +17655,39 @@ made @option{no-xthrow} the default setting for this option: it excludes from the @code{noreturn} treatment only internal functions used to (re)raise exceptions, that are not affected by these optimizations. +@opindex fhardened +@item -fhardened +Enable a set of flags for C and C++ that improve the security of the +generated code without affecting its ABI. The precise flags enabled +may change between major releases of GCC, but are currently: + +@c Keep this in sync with print_help_hardened! +@gccoptlist{ +-D_FORTIFY_SOURCE=3 +-D_GLIBCXX_ASSERTIONS +-ftrivial-auto-var-init=zero +-fPIE -pie -Wl,-z,relro,-z,now +-fstack-protector-strong +-fstack-clash-protection +-fcf-protection=full @r{(x86 GNU/Linux only)} +} + +The list of options enabled by @option{-fhardened} can be generated using +the @option{--help=hardened} option. + +When the system glibc is older than 2.35, @option{-D_FORTIFY_SOURCE=2} +is used instead. + +This option is intended to be used in production builds, not merely +in debug builds. + +Currently, @option{-fhardened} is only supported on GNU/Linux targets. + +@option{-fhardened} only enables a particular option if it wasn't +already specified anywhere on the command line. For instance, +@option{-fhardened} @option{-fstack-protector} will only enable +@option{-fstack-protector}, but not @option{-fstack-protector-strong}. + @opindex fstack-protector @item -fstack-protector Emit extra code to check for buffer overflows, such as stack smashing @@ -29587,9 +29647,10 @@ conventions are: @samp{ilp32}, @samp{ilp32f}, @samp{ilp32d}, @samp{lp64}, @samp{lp64f}, and @samp{lp64d}. Some calling conventions are impossible to implement on some ISAs: for example, @samp{-march=rv32if -mabi=ilp32d} is invalid because the ABI requires 64-bit values be passed in F registers, but F -registers are only 32 bits wide. There is also the @samp{ilp32e} ABI that can -only be used with the @samp{rv32e} architecture. This ABI is not well -specified at present, and is subject to change. +registers are only 32 bits wide. There are also the @samp{ilp32e} ABI that can +only be used with the @samp{rv32e} architecture and the @samp{lp64e} ABI that +can only be used with the @samp{rv64e}. Those ABIs are not well specified at +present, and are subject to change. @opindex mfdiv @item -mfdiv @@ -29679,6 +29740,14 @@ Do or don't use smaller but slower prologue and epilogue code that uses library function calls. The default is to use fast inline prologues and epilogues. +@opindex mmovcc +@item -mmovcc +@itemx -mno-movcc +Do or don't produce branchless conditional-move code sequences even with +targets that do not have specific instructions for conditional operations. +If enabled, sequences of ALU operations are produced using base integer +ISA instructions where profitable. + @opindex minline-atomics @item -minline-atomics @itemx -mno-inline-atomics @@ -34123,6 +34192,15 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @need 200 @opindex musermsr @itemx -musermsr +@need 200 +@opindex mavx10.1 +@itemx -mavx10.1 +@need 200 +@opindex mavx10.1-256 +@itemx -mavx10.1-256 +@need 200 +@opindex mavx10.1-512 +@itemx -mavx10.1-512 These switches enable the use of instructions in the MMX, SSE, AVX512ER, AVX512CD, AVX512VL, AVX512BW, AVX512DQ, AVX512IFMA, AVX512VBMI, SHA, AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG, @@ -34133,9 +34211,9 @@ GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16, ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, SERIALIZE, UINTR, HRESET, AMXTILE, AMXINT8, AMXBF16, KL, WIDEKL, AVXVNNI, AVX512-FP16, AVXIFMA, AVXVNNIINT8, AVXNECONVERT, CMPCCXADD, AMX-FP16, PREFETCHI, RAOINT, -AMX-COMPLEX, AVXVNNIINT16, SM3, SHA512, SM4, APX_F, USER_MSR or CLDEMOTE -extended instruction sets. Each has a corresponding @option{-mno-} option -to disable use of these instructions. +AMX-COMPLEX, AVXVNNIINT16, SM3, SHA512, SM4, APX_F, USER_MSR, AVX10.1 or +CLDEMOTE extended instruction sets. Each has a corresponding @option{-mno-} +option to disable use of these instructions. These extensions are also available as built-in functions: see @ref{x86 Built-in Functions}, for details of the functions enabled and diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index e01cdcb..536ce99 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4516,8 +4516,8 @@ Register constraints correspond directly to register classes. @xref{Register Classes}. There is thus not much flexibility in their definitions. -@deffn {MD Expression} define_register_constraint name regclass docstring -All three arguments are string constants. +@deffn {MD Expression} define_register_constraint name regclass docstring [filter] +All arguments are string constants. @var{name} is the name of the constraint, as it will appear in @code{match_operand} expressions. If @var{name} is a multi-letter constraint its length shall be the same for all constraints starting @@ -4529,6 +4529,43 @@ look at the operand. The usual use of expressions is to map some register constraints to @code{NO_REGS} when the register class is not available on a given subarchitecture. +If an operand occupies multiple hard registers, the constraint +requires all of those registers to belong to @var{regclass}. +For example, if @var{regclass} is @code{GENERAL_REGS} and +@code{GENERAL_REGS} contains registers @code{r0} to @code{r15}, +the constraint does not allow @var{r15} to be used for modes +that occupy more than one register. + +@cindex @code{TARGET_HARD_REGNO_MODE_OK} and constraints +The choice of register is also constrained by @code{TARGET_HARD_REGNO_MODE_OK}. +For example, if @code{TARGET_HARD_REGNO_MODE_OK} disallows @samp{(reg:DI r1)}, +that requirement applies to all constraints whose classes include @code{r1}. + +However, it is sometimes useful to impose extra operand-specific +requirements on the register number. For example, a target might not +want to prevent @emph{all} odd-even pairs from holding @code{DImode} +values, but it might still need to prevent specific operands from +having an odd-numbered register. The optional @var{filter} argument +exists for such cases. When given, @var{filter} is a C++ expression +that evaluates to true if @code{regno} is a valid register for the +operand. If an operand occupies multiple registers, the condition +applies only to the first register. + +For example: + +@smallexample +(define_register_constraint "e" "GENERAL_REGS" "..." "regno % 2 == 0") +@end smallexample + +defines a constraint that requires an even-numbered general register. + +Filter conditions that impose an alignment are encouraged to test +the alignment of @code{regno} itself, as in the example, rather than +calculate an offset relative to the start of the class. If it is +sometimes necessary for a register of class @var{c} to be aligned +to @var{n}, the first register in @var{c} should itself by divisible +by @var{n}. + @var{docstring} is a sentence documenting the meaning of the constraint. Docstrings are explained further below. @end deffn @@ -6878,8 +6915,9 @@ individually copied data units in the block. The @code{cpymem@var{m}} patterns need not give special consideration to the possibility that the source and destination strings might -overlap. These patterns are used to do inline expansion of -@code{__builtin_memcpy}. +overlap. An exception is the case where source and destination are +equal, this case needs to be handled correctly. +These patterns are used to do inline expansion of @code{__builtin_memcpy}. @cindex @code{movmem@var{m}} instruction pattern @item @samp{movmem@var{m}} diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index eaa75f0..e27e0fa 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -2496,6 +2496,15 @@ Target supports compiling @code{avx} instructions. @item avx_runtime Target supports the execution of @code{avx} instructions. +@item avx10.1 +Target supports the execution of @code{avx10.1} instructions. + +@item avx10.1-256 +Target supports the execution of @code{avx10.1} instructions. + +@item avx10.1-512 +Target supports the execution of @code{avx10.1-512} instructions. + @item avx2 Target supports compiling @code{avx2} instructions. diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi index 4eb43f1..4b18fa9 100644 --- a/gcc/doc/standards.texi +++ b/gcc/doc/standards.texi @@ -184,7 +184,9 @@ GNU C library). @xref{Standard Libraries,,Standard Libraries}. Most of the compiler support routines used by GCC are present in @file{libgcc}, but there are a few exceptions. GCC requires the freestanding environment provide @code{memcpy}, @code{memmove}, -@code{memset} and @code{memcmp}. +@code{memset} and @code{memcmp}. Contrary to the standards +covering @code{memcpy} GCC expects the case of an exact overlap +of source and destination to work and not invoke undefined behavior. Finally, if @code{__builtin_trap} is used, and the target does not implement the @code{trap} pattern, then GCC emits a call to @code{abort}. @@ -238,7 +240,7 @@ new specification. For further details see To select this standard in GCC, use the option @option{-std=c++20}. More information about the C++ standards is available on the ISO C++ -committee's web site at @uref{http://www.open-std.org/@/jtc1/@/sc22/@/wg21/}. +committee's web site at @uref{https://www.open-std.org/@/jtc1/@/sc22/@/wg21/}. To obtain all the diagnostics required by any of the standard versions described above you should specify @option{-pedantic} diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index dcf7735..c0f949b 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2478,7 +2478,8 @@ When a value occupying several consecutive registers is expected in a certain class, all the registers used must belong to that class. Therefore, register classes cannot be used to enforce a requirement for a register pair to start with an even-numbered register. The way to -specify this requirement is with @code{TARGET_HARD_REGNO_MODE_OK}. +specify this requirement is with @code{TARGET_HARD_REGNO_MODE_OK}, +or with a filter expression in a @code{define_register_constraint}. Register classes used for input-operands of bitwise-and or shift instructions have a special requirement: each such class must have, for @@ -5822,6 +5823,11 @@ This hook determines whether a function from a class of functions @code{(enum function_class)}@var{fcode} has a fast implementation. @end deftypefn +@deftypefn {Target Hook} unsigned TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL (void) +This hook determines what value _FORTIFY_SOURCE will be set to when using +the command-line option -fhardened. +@end deftypefn + @deftypefn {Target Hook} unsigned TARGET_LIBM_FUNCTION_MAX_ERROR (unsigned @var{cfn}, machine_mode @var{mode}, bool @var{boundary_p}) This hook determines expected maximum errors for math functions measured in ulps (units of the last place). 0 means 0.5ulps precision (correctly diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index b61a59f..ef04c89 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -2060,7 +2060,8 @@ When a value occupying several consecutive registers is expected in a certain class, all the registers used must belong to that class. Therefore, register classes cannot be used to enforce a requirement for a register pair to start with an even-numbered register. The way to -specify this requirement is with @code{TARGET_HARD_REGNO_MODE_OK}. +specify this requirement is with @code{TARGET_HARD_REGNO_MODE_OK}, +or with a filter expression in a @code{define_register_constraint}. Register classes used for input-operands of bitwise-and or shift instructions have a special requirement: each such class must have, for @@ -4043,6 +4044,8 @@ macro, a reasonable default is used. @hook TARGET_LIBC_HAS_FAST_FUNCTION +@hook TARGET_FORTIFY_SOURCE_DEFAULT_LEVEL + @hook TARGET_LIBM_FUNCTION_MAX_ERROR @defmac NEXT_OBJC_RUNTIME @@ -1900,8 +1900,11 @@ get_stored_val (store_info *store_info, machine_mode read_mode, else gap = read_offset - store_info->offset; - if (gap.is_constant () && maybe_ne (gap, 0)) + if (maybe_ne (gap, 0)) { + if (!gap.is_constant ()) + return NULL_RTX; + poly_int64 shift = gap * BITS_PER_UNIT; poly_int64 access_size = GET_MODE_SIZE (read_mode) + gap; read_reg = find_shift_sequence (access_size, store_info, read_mode, @@ -1940,6 +1943,10 @@ get_stored_val (store_info *store_info, machine_mode read_mode, || GET_MODE_CLASS (read_mode) != GET_MODE_CLASS (store_mode))) read_reg = extract_low_bits (read_mode, store_mode, copy_rtx (store_info->const_rhs)); + else if (VECTOR_MODE_P (read_mode) && VECTOR_MODE_P (store_mode) + && known_le (GET_MODE_BITSIZE (read_mode), GET_MODE_BITSIZE (store_mode)) + && targetm.modes_tieable_p (read_mode, store_mode)) + read_reg = gen_lowpart (read_mode, copy_rtx (store_info->rhs)); else read_reg = extract_low_bits (read_mode, store_mode, copy_rtx (store_info->rhs)); diff --git a/gcc/expr.cc b/gcc/expr.cc index 556bcf7..c432170 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -1090,18 +1090,16 @@ by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align, unsigned HOST_WIDE_INT n_insns = 0; fixed_size_mode mode; - if (targetm.overlap_op_by_pieces_p () && op != COMPARE_BY_PIECES) + if (targetm.overlap_op_by_pieces_p ()) { /* NB: Round up L and ALIGN to the widest integer mode for MAX_SIZE. */ mode = widest_fixed_size_mode_for_size (max_size, op); - if (optab_handler (mov_optab, mode) != CODE_FOR_nothing) - { - unsigned HOST_WIDE_INT up = ROUND_UP (l, GET_MODE_SIZE (mode)); - if (up > l) - l = up; - align = GET_MODE_ALIGNMENT (mode); - } + gcc_assert (optab_handler (mov_optab, mode) != CODE_FOR_nothing); + unsigned HOST_WIDE_INT up = ROUND_UP (l, GET_MODE_SIZE (mode)); + if (up > l) + l = up; + align = GET_MODE_ALIGNMENT (mode); } align = alignment_for_piecewise_move (MOVE_MAX_PIECES, align); @@ -1109,12 +1107,11 @@ by_pieces_ninsns (unsigned HOST_WIDE_INT l, unsigned int align, while (max_size > 1 && l > 0) { mode = widest_fixed_size_mode_for_size (max_size, op); - enum insn_code icode; + gcc_assert (optab_handler (mov_optab, mode) != CODE_FOR_nothing); unsigned int modesize = GET_MODE_SIZE (mode); - icode = optab_handler (mov_optab, mode); - if (icode != CODE_FOR_nothing && align >= GET_MODE_ALIGNMENT (mode)) + if (align >= GET_MODE_ALIGNMENT (mode)) { unsigned HOST_WIDE_INT n_pieces = l / modesize; l %= modesize; @@ -10698,6 +10695,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, && mode != BLKmode \ && modifier != EXPAND_MEMORY \ && modifier != EXPAND_WRITE \ + && modifier != EXPAND_INITIALIZER \ && modifier != EXPAND_CONST_ADDRESS) \ ? reduce_to_bit_field_precision ((expr), NULL_RTX, type) : (expr)) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 686c771..21c5f2a 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,33 @@ +2023-11-26 Harald Anlauf <anlauf@gmx.de> + + PR fortran/111880 + * resolve.cc (resolve_common_vars): Do not call gfc_add_in_common + for symbols that are USE associated or used in a submodule. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * lang.opt (Wopenmp): Add, enabled by dafault and documented in C. + * openmp.cc (gfc_match_omp_declare_target, resolve_positive_int_expr, + resolve_nonnegative_int_expr, resolve_omp_clauses, + gfc_resolve_omp_do_blocks): Use OPT_Wopenmp with gfc_warning{,_now}. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * openmp.cc (gfc_match_omp_depobj): Accept optionally an argument + to the destroy clause. + +2023-11-23 Harald Anlauf <anlauf@gmx.de> + + PR fortran/112609 + * check.cc (gfc_check_system_clock): Add checks on integer arguments + to SYSTEM_CLOCK specific to F2023. + * error.cc (notify_std_msg): Adjust to handle new features added + in F2023. + * gfortran.texi (_gfortran_set_options): Document GFC_STD_F2023_DEL, + remove obsolete option GFC_STD_F2008_TS and fix enumeration values. + * libgfortran.h (GFC_STD_F2023_DEL): Add and use in GFC_STD_OPT_F23. + * options.cc (set_default_std_flags): Add GFC_STD_F2023_DEL. + 2023-11-17 Tobias Burnus <tobias@codesourcery.com> * gfortran.texi (_gfortran_set_options): Document GFC_STD_F2023. diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 6c45e65..3b1a0f9 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -6774,6 +6774,8 @@ bool gfc_check_system_clock (gfc_expr *count, gfc_expr *count_rate, gfc_expr *count_max) { + int first_int_kind = -1; + if (count != NULL) { if (!scalar_check (count, 0)) @@ -6788,8 +6790,17 @@ gfc_check_system_clock (gfc_expr *count, gfc_expr *count_rate, &count->where)) return false; + if (count->ts.kind < gfc_default_integer_kind + && !gfc_notify_std (GFC_STD_F2023_DEL, + "COUNT argument to SYSTEM_CLOCK at %L " + "with kind smaller than default integer", + &count->where)) + return false; + if (!variable_check (count, 0, false)) return false; + + first_int_kind = count->ts.kind; } if (count_rate != NULL) @@ -6816,6 +6827,16 @@ gfc_check_system_clock (gfc_expr *count, gfc_expr *count_rate, "SYSTEM_CLOCK at %L has non-default kind", &count_rate->where)) return false; + + if (count_rate->ts.kind < gfc_default_integer_kind + && !gfc_notify_std (GFC_STD_F2023_DEL, + "COUNT_RATE argument to SYSTEM_CLOCK at %L " + "with kind smaller than default integer", + &count_rate->where)) + return false; + + if (first_int_kind < 0) + first_int_kind = count_rate->ts.kind; } } @@ -6836,6 +6857,35 @@ gfc_check_system_clock (gfc_expr *count, gfc_expr *count_rate, if (!variable_check (count_max, 2, false)) return false; + + if (count_max->ts.kind < gfc_default_integer_kind + && !gfc_notify_std (GFC_STD_F2023_DEL, + "COUNT_MAX argument to SYSTEM_CLOCK at %L " + "with kind smaller than default integer", + &count_max->where)) + return false; + + if (first_int_kind < 0) + first_int_kind = count_max->ts.kind; + } + + if (first_int_kind > 0) + { + if (count_rate + && count_rate->ts.type == BT_INTEGER + && count_rate->ts.kind != first_int_kind + && !gfc_notify_std (GFC_STD_F2023_DEL, + "integer arguments to SYSTEM_CLOCK at %L " + "with different kind parameters", + &count_rate->where)) + return false; + + if (count_max && count_max->ts.kind != first_int_kind + && !gfc_notify_std (GFC_STD_F2023_DEL, + "integer arguments to SYSTEM_CLOCK at %L " + "with different kind parameters", + &count_max->where)) + return false; } return true; diff --git a/gcc/fortran/error.cc b/gcc/fortran/error.cc index 2ac51e9..56d2e63 100644 --- a/gcc/fortran/error.cc +++ b/gcc/fortran/error.cc @@ -980,7 +980,11 @@ char const* notify_std_msg(int std) { - if (std & GFC_STD_F2018_DEL) + if (std & GFC_STD_F2023_DEL) + return _("Prohibited in Fortran 2023:"); + else if (std & GFC_STD_F2023) + return _("Fortran 2023:"); + else if (std & GFC_STD_F2018_DEL) return _("Fortran 2018 deleted feature:"); else if (std & GFC_STD_F2018_OBS) return _("Fortran 2018 obsolescent feature:"); diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 41857cc..c29cb78 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3476,13 +3476,13 @@ standard. Possible values are (bitwise or-ed) @code{GFC_STD_F77} (1), @code{GFC_STD_F95_OBS} (2), @code{GFC_STD_F95_DEL} (4), @code{GFC_STD_F95} (8), @code{GFC_STD_F2003} (16), @code{GFC_STD_GNU} (32), @code{GFC_STD_LEGACY} (64), @code{GFC_STD_F2008} (128), -@code{GFC_STD_F2008_OBS} (256), @code{GFC_STD_F2008_TS} (512), -@code{GFC_STD_F2018} (1024), @code{GFC_STD_F2018_OBS} (2048), -@code{GFC_STD=F2018_DEL} (4096), and @code{GFC_STD=F2023} (8192). +@code{GFC_STD_F2008_OBS} (256), @code{GFC_STD_F2018} (512), +@code{GFC_STD_F2018_OBS} (1024), @code{GFC_STD_F2018_DEL} (2048), +@code{GFC_STD_F2023} (4096), and @code{GFC_STD_F2023_DEL} (8192). Default: @code{GFC_STD_F95_OBS | GFC_STD_F95_DEL | GFC_STD_F95 | -GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F2008_TS | GFC_STD_F2008_OBS +GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F2008_OBS | GFC_STD_F77 | GFC_STD_F2018 | GFC_STD_F2018_OBS | GFC_STD_F2018_DEL -| GFC_STD_F2023 | GFC_STD_GNU | GFC_STD_LEGACY}. +| GFC_STD_F2023 | GFC_STD_F2023_DEL | GFC_STD_GNU | GFC_STD_LEGACY}. @item @var{option}[1] @tab Standard-warning flag; prints a warning to standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}. @item @var{option}[2] @tab If non zero, enable pedantic checking. diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index 08c7539..adcfc28 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -289,6 +289,10 @@ Wopenacc-parallelism Fortran ; Documented in C +Wopenmp +Fortran +; Documented in C + Wopenmp-simd Fortran ; Documented in C diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h index bdddb31..2c71b90 100644 --- a/gcc/fortran/libgfortran.h +++ b/gcc/fortran/libgfortran.h @@ -20,8 +20,10 @@ along with GCC; see the file COPYING3. If not see /* Flags to specify which standard/extension contains a feature. Note that no features were obsoleted nor deleted in F2003 nor in F2023. + Nevertheless, some features available in F2018 are prohibited in F2023. Please remember to keep those definitions in sync with gfortran.texi. */ +#define GFC_STD_F2023_DEL (1<<13) /* Prohibited in F2023. */ #define GFC_STD_F2023 (1<<12) /* New in F2023. */ #define GFC_STD_F2018_DEL (1<<11) /* Deleted in F2018. */ #define GFC_STD_F2018_OBS (1<<10) /* Obsolescent in F2018. */ @@ -41,12 +43,13 @@ along with GCC; see the file COPYING3. If not see * are allowed with a certain -std option. */ #define GFC_STD_OPT_F95 (GFC_STD_F77 | GFC_STD_F95 | GFC_STD_F95_OBS \ | GFC_STD_F2008_OBS | GFC_STD_F2018_OBS \ - | GFC_STD_F2018_DEL) + | GFC_STD_F2018_DEL | GFC_STD_F2023_DEL) #define GFC_STD_OPT_F03 (GFC_STD_OPT_F95 | GFC_STD_F2003) #define GFC_STD_OPT_F08 (GFC_STD_OPT_F03 | GFC_STD_F2008) #define GFC_STD_OPT_F18 ((GFC_STD_OPT_F08 | GFC_STD_F2018) \ & (~GFC_STD_F2018_DEL)) -#define GFC_STD_OPT_F23 (GFC_STD_OPT_F18 | GFC_STD_F2023) +#define GFC_STD_OPT_F23 ((GFC_STD_OPT_F18 | GFC_STD_F2023) \ + & (~GFC_STD_F2023_DEL)) /* Bitmasks for the various FPE that can be enabled. These need to be straight integers e.g., 8 instead of (1<<3), because they will be included in Fortran source. */ diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 2e2e23d..794df19 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "options.h" #include "gfortran.h" #include "arith.h" #include "match.h" @@ -4731,10 +4732,20 @@ gfc_match_omp_depobj (void) goto error; } } - else if (gfc_match ("destroy") == MATCH_YES) + else if (gfc_match ("destroy ") == MATCH_YES) { + gfc_expr *destroyobj = NULL; c = gfc_get_omp_clauses (); c->destroy = true; + + if (gfc_match (" ( %v ) ", &destroyobj) == MATCH_YES) + { + if (destroyobj->symtree != depobj->symtree) + gfc_warning (0, "The same depend object should be used as DEPOBJ " + "argument at %L and as DESTROY argument at %L", + &depobj->where, &destroyobj->where); + gfc_free_expr (destroyobj); + } } else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_DEPEND), true, false) != MATCH_YES) @@ -5553,8 +5564,9 @@ gfc_match_omp_declare_target (void) && !c->lists[OMP_LIST_ENTER] && !c->lists[OMP_LIST_TO] && !c->lists[OMP_LIST_LINK]) - gfc_warning_now (0, "OMP DECLARE TARGET directive at %L with only " - "DEVICE_TYPE clause is ignored", &old_loc); + gfc_warning_now (OPT_Wopenmp, + "OMP DECLARE TARGET directive at %L with only " + "DEVICE_TYPE clause is ignored", &old_loc); gfc_buffer_error (true); @@ -7020,7 +7032,8 @@ resolve_positive_int_expr (gfc_expr *expr, const char *clause) if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_INTEGER && mpz_sgn (expr->value.integer) <= 0) - gfc_warning (0, "INTEGER expression of %s clause at %L must be positive", + gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0, + "INTEGER expression of %s clause at %L must be positive", clause, &expr->where); } @@ -7031,8 +7044,9 @@ resolve_nonnegative_int_expr (gfc_expr *expr, const char *clause) if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_INTEGER && mpz_sgn (expr->value.integer) < 0) - gfc_warning (0, "INTEGER expression of %s clause at %L must be " - "non-negative", clause, &expr->where); + gfc_warning ((flag_openmp || flag_openmp_simd) ? OPT_Wopenmp : 0, + "INTEGER expression of %s clause at %L must be non-negative", + clause, &expr->where); } /* Emits error when symbol is pointer, cray pointer or cray pointee @@ -7595,8 +7609,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, else if (expr->expr_type == EXPR_CONSTANT && expr->ts.type == BT_INTEGER && mpz_sgn (expr->value.integer) <= 0) - gfc_warning (0, "INTEGER expression of SCHEDULE clause's chunk_size " - "at %L must be positive", &expr->where); + gfc_warning (OPT_Wopenmp, "INTEGER expression of SCHEDULE clause's " + "chunk_size at %L must be positive", &expr->where); } if (omp_clauses->sched_kind != OMP_SCHED_NONE && omp_clauses->sched_nonmonotonic) @@ -7906,8 +7920,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, } if (n->sym->mark == 1) { - gfc_warning (0, "%qs appears more than once in %<allocate%> " - "at %L" , n->sym->name, &n->where); + gfc_warning (OPT_Wopenmp, "%qs appears more than once in " + "%<allocate%> at %L" , n->sym->name, &n->where); /* We have already seen this variable so it is a duplicate. Remove it. */ if (prev != NULL && prev->next == n) @@ -8905,8 +8919,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, && omp_clauses->num_teams_upper->expr_type == EXPR_CONSTANT && mpz_cmp (omp_clauses->num_teams_lower->value.integer, omp_clauses->num_teams_upper->value.integer) > 0) - gfc_warning (0, "NUM_TEAMS lower bound at %L larger than upper bound at %L", - &omp_clauses->num_teams_lower->where, + gfc_warning (OPT_Wopenmp, "NUM_TEAMS lower bound at %L larger than upper " + "bound at %L", &omp_clauses->num_teams_lower->where, &omp_clauses->num_teams_upper->where); if (omp_clauses->device) resolve_scalar_int_expr (omp_clauses->device, "DEVICE"); @@ -9743,13 +9757,15 @@ gfc_resolve_omp_do_blocks (gfc_code *code, gfc_namespace *ns) else { if (block->op == EXEC_OMP_SCAN) - gfc_warning (0, "!$OMP SCAN at %L with zero executable " + gfc_warning (OPT_Wopenmp, + "!$OMP SCAN at %L with zero executable " "statements in preceding structured block " "sequence", &block->loc); if ((block->op == EXEC_OMP_SCAN && !block->next) || (block->next && block->next->op == EXEC_OMP_SCAN && !block->next->next)) - gfc_warning (0, "!$OMP SCAN at %L with zero executable " + gfc_warning (OPT_Wopenmp, + "!$OMP SCAN at %L with zero executable " "statements in succeeding structured block " "sequence", block->op == EXEC_OMP_SCAN ? &block->loc : &block->next->loc); diff --git a/gcc/fortran/options.cc b/gcc/fortran/options.cc index b788521..02a29f8 100644 --- a/gcc/fortran/options.cc +++ b/gcc/fortran/options.cc @@ -57,8 +57,10 @@ set_default_std_flags (void) gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95_DEL | GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77 | GFC_STD_F2008_OBS | GFC_STD_GNU | GFC_STD_LEGACY - | GFC_STD_F2018 | GFC_STD_F2018_DEL | GFC_STD_F2018_OBS | GFC_STD_F2023; - gfc_option.warn_std = GFC_STD_F2018_DEL | GFC_STD_F95_DEL | GFC_STD_LEGACY; + | GFC_STD_F2018 | GFC_STD_F2018_DEL | GFC_STD_F2018_OBS | GFC_STD_F2023 + | GFC_STD_F2023_DEL; + gfc_option.warn_std = GFC_STD_F2018_DEL | GFC_STD_F95_DEL | GFC_STD_LEGACY + | GFC_STD_F2023_DEL; } /* Set (or unset) the DEC extension flags. */ diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index 81a1465..166b702 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -986,8 +986,8 @@ resolve_common_vars (gfc_common_head *common_block, bool named_common) /* gfc_add_in_common may have been called before, but the reported errors have been ignored to continue parsing. - We do the checks again here. */ - if (!csym->attr.use_assoc) + We do the checks again here, unless the symbol is USE associated. */ + if (!csym->attr.use_assoc && !csym->attr.used_in_submodule) { gfc_add_in_common (&csym->attr, csym->name, &common_block->where); gfc_notify_std (GFC_STD_F2018_OBS, "COMMON block at %L", @@ -302,6 +302,13 @@ static size_t dumpdir_length = 0; driver added to dumpdir after dumpbase or linker output name. */ static bool dumpdir_trailing_dash_added = false; +/* True if -r, -shared, -pie, or -no-pie were specified on the command + line. */ +static bool any_link_options_p; + +/* True if -static was specified on the command line. */ +static bool static_p; + /* Basename of dump and aux outputs, computed from dumpbase (given or derived from output name), to override input_basename in non-%w %b et al. */ @@ -4605,10 +4612,20 @@ driver_handle_option (struct gcc_options *opts, save_switch ("-o", 1, &arg, validated, true); return true; -#ifdef ENABLE_DEFAULT_PIE case OPT_pie: +#ifdef ENABLE_DEFAULT_PIE /* -pie is turned on by default. */ + validated = true; #endif + case OPT_r: + case OPT_shared: + case OPT_no_pie: + any_link_options_p = true; + break; + + case OPT_static: + static_p = true; + break; case OPT_static_libgcc: case OPT_shared_libgcc: @@ -4984,6 +5001,35 @@ process_command (unsigned int decoded_options_count, #endif } + /* TODO: check if -static -pie works and maybe use it. */ + if (flag_hardened) + { + if (!any_link_options_p && !static_p) + { +#ifdef HAVE_LD_PIE + save_switch (LD_PIE_SPEC, 0, NULL, /*validated=*/true, /*known=*/false); +#endif + /* These are passed straight down to collect2 so we have to break + it up like this. */ + if (HAVE_LD_NOW_SUPPORT) + { + add_infile ("-z", "*"); + add_infile ("now", "*"); + } + if (HAVE_LD_RELRO_SUPPORT) + { + add_infile ("-z", "*"); + add_infile ("relro", "*"); + } + } + /* We can't use OPT_Whardened yet. Sigh. */ + else if (warn_hardened) + warning_at (UNKNOWN_LOCATION, 0, + "linker hardening options not enabled by %<-fhardened%> " + "because other link options were specified on the command " + "line"); + } + /* Handle -gtoggle as it would later in toplev.cc:process_options to make the debug-level-gt spec function work as expected. */ if (flag_gtoggle) diff --git a/gcc/genconfig.cc b/gcc/genconfig.cc index 2ee323f..c8c2ebe 100644 --- a/gcc/genconfig.cc +++ b/gcc/genconfig.cc @@ -360,6 +360,8 @@ main (int argc, const char **argv) printf ("#define MAX_INSNS_PER_PEEP2 0\n"); } + printf ("#define NUM_REGISTER_FILTERS %d\n", register_filters.length ()); + puts ("\n#endif /* GCC_INSN_CONFIG_H */"); if (ferror (stdout) || fflush (stdout) || fclose (stdout)) diff --git a/gcc/genpreds.cc b/gcc/genpreds.cc index bdd65ef..5535a75 100644 --- a/gcc/genpreds.cc +++ b/gcc/genpreds.cc @@ -677,6 +677,7 @@ public: size_t namelen; const char *regclass; /* for register constraints */ rtx exp; /* for other constraints */ + const char *filter; /* the register filter condition, or null if none */ unsigned int is_register : 1; unsigned int is_const_int : 1; unsigned int is_const_dbl : 1; @@ -763,7 +764,8 @@ mangle (const char *name) is the register class, if any; EXP is the expression to test, if any; IS_MEMORY, IS_SPECIAL_MEMORY, IS_RELAXED_MEMORY and IS_ADDRESS indicate memory, special memory, and address constraints, respectively; LOC is the .md - file location. + file location; FILTER is the filter condition for a register constraint, + or null if none. Not all combinations of arguments are valid; most importantly, REGCLASS is mutually exclusive with EXP, and @@ -776,7 +778,8 @@ mangle (const char *name) static void add_constraint (const char *name, const char *regclass, rtx exp, bool is_memory, bool is_special_memory, - bool is_relaxed_memory, bool is_address, file_location loc) + bool is_relaxed_memory, bool is_address, file_location loc, + const char *filter = nullptr) { class constraint_data *c, **iter, **slot; const char *p; @@ -908,6 +911,7 @@ add_constraint (const char *name, const char *regclass, c->namelen = namelen; c->regclass = regclass; c->exp = exp; + c->filter = filter; c->is_register = regclass != 0; c->is_const_int = is_const_int; c->is_const_dbl = is_const_dbl; @@ -966,7 +970,8 @@ static void process_define_register_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), - 0, false, false, false, false, info->loc); + 0, false, false, false, false, info->loc, + XSTR (info->def, 3)); } /* Put the constraints into enum order. We want to keep constraints @@ -1319,6 +1324,34 @@ write_insn_const_int_ok_for_constraint (void) " return false;\n" "}\n"); } + +/* Print the init_reg_class_start_regs function, which initializes + this_target_constraints->register_filters from the C conditions + in the define_register_constraints. */ +static void +write_init_reg_class_start_regs () +{ + printf ("\n" + "void\n" + "init_reg_class_start_regs ()\n" + "{\n"); + if (!register_filters.is_empty ()) + { + printf (" for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER;" + " ++regno)\n" + " {\n"); + for (unsigned int i = 0; i < register_filters.length (); ++i) + { + printf (" if ("); + rtx_reader_ptr->print_c_condition (register_filters[i]); + printf (")\n" + " SET_HARD_REG_BIT (%s[%d], regno);\n", + "this_target_constraints->register_filters", i); + } + printf (" }\n"); + } + printf ("}\n"); +} /* Write a definition for a function NAME that returns true if a given constraint_num is in the range [START, END). */ @@ -1401,6 +1434,54 @@ print_type_tree (const vec <std::pair <unsigned int, const char *> > &vec, printf ("%*sreturn %s;\n", indent, "", fallback); } +/* Print the get_register_filter function, which returns a pointer + to the start register filter for a given constraint, or null if none. */ +static void +write_get_register_filter () +{ + constraint_data *c; + + printf ("\n" + "#ifdef GCC_HARD_REG_SET_H\n" + "static inline const HARD_REG_SET *\n" + "get_register_filter (constraint_num%s)\n", + register_filters.is_empty () ? "" : " c"); + printf ("{\n"); + FOR_ALL_CONSTRAINTS (c) + if (c->is_register && c->filter) + { + printf (" if (c == CONSTRAINT_%s)\n", c->c_name); + printf (" return &this_target_constraints->register_filters[%d];\n", + get_register_filter_id (c->filter)); + } + printf (" return nullptr;\n" + "}\n" + "#endif\n"); +} + +/* Print the get_register_filter_id function, which returns the index + of the given constraint's register filter in + this_target_constraints->register_filters, or -1 if none. */ +static void +write_get_register_filter_id () +{ + constraint_data *c; + + printf ("\n" + "static inline int\n" + "get_register_filter_id (constraint_num%s)\n", + register_filters.is_empty () ? "" : " c"); + printf ("{\n"); + FOR_ALL_CONSTRAINTS (c) + if (c->is_register && c->filter) + { + printf (" if (c == CONSTRAINT_%s)\n", c->c_name); + printf (" return %d;\n", get_register_filter_id (c->filter)); + } + printf (" return -1;\n" + "}\n"); +} + /* Write tm-preds.h. Unfortunately, it is impossible to forward-declare an enumeration in portable C, so we have to condition all these prototypes on HAVE_MACHINE_MODES. */ @@ -1425,6 +1506,53 @@ write_tm_preds_h (void) puts ("#endif /* HAVE_MACHINE_MODES */\n"); + /* Print the definition of the target_constraints structure. */ + printf ("#ifdef GCC_HARD_REG_SET_H\n" + "struct target_constraints {\n" + " HARD_REG_SET register_filters[%d];\n", + MAX (register_filters.length (), 1)); + printf ("};\n" + "\n" + "extern struct target_constraints default_target_constraints;\n" + "#if SWITCHABLE_TARGET\n" + "extern struct target_constraints *this_target_constraints;\n" + "#else\n" + "#define this_target_constraints (&default_target_constraints)\n" + "#endif\n"); + + /* Print TEST_REGISTER_FILTER_BIT, which tests whether register REGNO + is a valid start register for register filter ID. */ + printf ("\n" + "#define TEST_REGISTER_FILTER_BIT(ID, REGNO) \\\n"); + if (register_filters.is_empty ()) + printf (" ((void) (ID), (void) (REGNO), false)\n"); + else + printf (" TEST_HARD_REG_BIT (" + "this_target_constraints->register_filters[ID], REGNO)\n"); + + /* Print test_register_filters, which tests whether register REGNO + is a valid start register for the mask of register filters in MASK. */ + printf ("\n" + "inline bool\n" + "test_register_filters (unsigned int%s, unsigned int%s)\n", + register_filters.is_empty () ? "" : " mask", + register_filters.is_empty () ? "" : " regno"); + printf ("{\n"); + if (register_filters.is_empty ()) + printf (" return true;\n"); + else + { + printf (" for (unsigned int id = 0; id < %d; ++id)\n", + register_filters.length ()); + printf (" if ((mask & (1U << id))\n" + "\t&& !TEST_REGISTER_FILTER_BIT (id, regno))\n" + " return false;\n" + " return true;\n"); + } + printf ("}\n" + "#endif\n" + "\n"); + if (constraint_max_namelen > 0) { write_enum_constraint_num (); @@ -1548,6 +1676,9 @@ write_tm_preds_h (void) values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM")); print_type_tree (values, 0, values.length (), "CT_REGISTER", 2); puts ("}"); + + write_get_register_filter (); + write_get_register_filter_id (); } puts ("#endif /* tm-preds.h */"); @@ -1599,6 +1730,13 @@ write_insn_preds_c (void) #include \"tm-constrs.h\"\n\ #include \"target.h\"\n"); + printf ("\n" + "struct target_constraints default_target_constraints;\n" + "#if SWITCHABLE_TARGET\n" + "struct target_constraints *this_target_constraints" + " = &default_target_constraints;\n" + "#endif\n"); + FOR_ALL_PREDICATES (p) write_one_predicate_function (p); @@ -1613,6 +1751,8 @@ write_insn_preds_c (void) if (have_const_int_constraints) write_insn_const_int_ok_for_constraint (); } + + write_init_reg_class_start_regs (); } /* Argument parsing. */ diff --git a/gcc/gensupport.cc b/gcc/gensupport.cc index 688808c..0ac0d07 100644 --- a/gcc/gensupport.cc +++ b/gcc/gensupport.cc @@ -400,6 +400,45 @@ process_define_predicate (rtx desc, file_location loc) #undef I #undef N #undef Y + +/* Maps register filter conditions to the associated filter identifier. */ +static hash_map<nofree_string_hash, unsigned int> register_filter_map; + +/* All register filter conditions, indexed by identifier. */ +vec<const char *> register_filters; + +/* Return the unique identifier for filter condition FILTER. Identifiers + are assigned automatically when the define_register_constraint is + parsed. */ + +unsigned int +get_register_filter_id (const char *filter) +{ + unsigned int *slot = register_filter_map.get (filter); + gcc_assert (slot); + return *slot; +} + +/* Process define_register_constraint directive DESC, at location LOC. */ + +static void +process_define_register_constraint (rtx desc, file_location loc) +{ + /* Assign identifiers to each unique register filter condition. */ + if (const char *filter = XSTR (desc, 3)) + { + bool existed = false; + unsigned int &id = register_filter_map.get_or_insert (filter, &existed); + if (!existed) + { + id = register_filters.length (); + if (id == 32) + fatal_at (loc, "too many distinct register filters, maximum" + " is 32"); + register_filters.safe_push (filter); + } + } +} /* Queue PATTERN on LIST_TAIL. Return the address of the new queue element. */ @@ -1075,10 +1114,15 @@ process_rtx (rtx desc, file_location loc) case DEFINE_PREDICATE: case DEFINE_SPECIAL_PREDICATE: process_define_predicate (desc, loc); - /* Fall through. */ + queue_pattern (desc, &define_pred_tail, loc); + break; - case DEFINE_CONSTRAINT: case DEFINE_REGISTER_CONSTRAINT: + process_define_register_constraint (desc, loc); + queue_pattern (desc, &define_pred_tail, loc); + break; + + case DEFINE_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: case DEFINE_SPECIAL_MEMORY_CONSTRAINT: case DEFINE_RELAXED_MEMORY_CONSTRAINT: diff --git a/gcc/gensupport.h b/gcc/gensupport.h index 7396118..27e8444 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -108,6 +108,9 @@ struct optab_def extern optab_def optabs[]; extern unsigned int num_optabs; +extern vec<const char *> register_filters; +extern unsigned int get_register_filter_id (const char *); + /* Information about an instruction name that matches an optab pattern. */ struct optab_pattern { diff --git a/gcc/gimple-iterator.h b/gcc/gimple-iterator.h index b709923..a7a8077 100644 --- a/gcc/gimple-iterator.h +++ b/gcc/gimple-iterator.h @@ -169,6 +169,41 @@ gsi_last_bb (basic_block bb) return i; } +/* Return a new iterator pointing to before the first statement or after + last statement (depending on whether adding statements after it or before it) + in a GIMPLE_SEQ. */ + +inline gimple_stmt_iterator +gsi_end (gimple_seq &seq) +{ + gimple_stmt_iterator i; + gimple *g = gimple_seq_last (seq); + + i.ptr = NULL; + i.seq = &seq; + i.bb = g ? gimple_bb (g) : NULL; + + return i; +} + +/* Return a new iterator pointing to before the first statement or after + last statement (depending on whether adding statements after it or before it) + in basic block BB. */ + +inline gimple_stmt_iterator +gsi_end_bb (basic_block bb) +{ + gimple_stmt_iterator i; + gimple_seq *seq; + + seq = bb_seq_addr (bb); + i.ptr = NULL; + i.seq = seq; + i.bb = bb; + + return i; +} + /* Return true if I is at the end of its sequence. */ inline bool diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc index c429cb2..5024815 100644 --- a/gcc/gimple-lower-bitint.cc +++ b/gcc/gimple-lower-bitint.cc @@ -1294,6 +1294,11 @@ bitint_large_huge::handle_cast (tree lhs_type, tree rhs1, tree idx) g = gimple_build_assign (n, RSHIFT_EXPR, t, lpm1); insert_before (g); m_data[save_data_cnt + 1] = add_cast (m_limb_type, n); + m_init_gsi = m_gsi; + if (gsi_end_p (m_init_gsi)) + m_init_gsi = gsi_last_bb (gsi_bb (m_init_gsi)); + else + gsi_prev (&m_init_gsi); m_gsi = save_gsi; } else if (m_upwards_2limb * limb_prec < TYPE_PRECISION (rhs_type)) @@ -1523,6 +1528,11 @@ bitint_large_huge::handle_cast (tree lhs_type, tree rhs1, tree idx) insert_before (g); rext = add_cast (m_limb_type, gimple_assign_lhs (g)); } + m_init_gsi = m_gsi; + if (gsi_end_p (m_init_gsi)) + m_init_gsi = gsi_last_bb (gsi_bb (m_init_gsi)); + else + gsi_prev (&m_init_gsi); m_gsi = save_gsi; } tree t; @@ -1687,9 +1697,23 @@ bitint_large_huge::handle_load (gimple *stmt, tree idx) edge e = split_block (gsi_bb (m_gsi), g); make_edge (e->src, eh_edge->dest, EDGE_EH)->probability = profile_probability::very_unlikely (); - m_init_gsi.bb = e->dest; + m_gsi = gsi_after_labels (e->dest); + if (gsi_bb (save_gsi) == e->src) + { + if (gsi_end_p (save_gsi)) + save_gsi = gsi_end_bb (e->dest); + else + save_gsi = gsi_for_stmt (gsi_stmt (save_gsi)); + } + if (m_preheader_bb == e->src) + m_preheader_bb = e->dest; } } + m_init_gsi = m_gsi; + if (gsi_end_p (m_init_gsi)) + m_init_gsi = gsi_last_bb (gsi_bb (m_init_gsi)); + else + gsi_prev (&m_init_gsi); m_gsi = save_gsi; tree out; prepare_data_in_out (iv, idx, &out); @@ -2359,11 +2383,7 @@ bitint_large_huge::lower_mergeable_stmt (gimple *stmt, tree_code &cmp_code, edge e = split_block (gsi_bb (gsi), gsi_stmt (gsi)); edge_bb = e->src; if (kind == bitint_prec_large) - { - m_gsi = gsi_last_bb (edge_bb); - if (!gsi_end_p (m_gsi)) - gsi_next (&m_gsi); - } + m_gsi = gsi_end_bb (edge_bb); } else m_after_stmt = stmt; @@ -2816,9 +2836,7 @@ bitint_large_huge::lower_comparison_stmt (gimple *stmt, tree_code &cmp_code, gsi_prev (&gsi); edge e = split_block (gsi_bb (gsi), gsi_stmt (gsi)); edge_bb = e->src; - m_gsi = gsi_last_bb (edge_bb); - if (!gsi_end_p (m_gsi)) - gsi_next (&m_gsi); + m_gsi = gsi_end_bb (edge_bb); edge *edges = XALLOCAVEC (edge, cnt * 2); for (unsigned i = 0; i < cnt; i++) @@ -4288,9 +4306,7 @@ bitint_large_huge::lower_mul_overflow (tree obj, gimple *stmt) gsi_prev (&gsi); edge e = split_block (gsi_bb (gsi), gsi_stmt (gsi)); edge_bb = e->src; - m_gsi = gsi_last_bb (edge_bb); - if (!gsi_end_p (m_gsi)) - gsi_next (&m_gsi); + m_gsi = gsi_end_bb (edge_bb); tree cmp = build_zero_cst (m_limb_type); for (unsigned i = 0; i < cnt; i++) @@ -4560,11 +4576,7 @@ bitint_large_huge::lower_bit_query (gimple *stmt) edge e = split_block (gsi_bb (gsi), gsi_stmt (gsi)); edge_bb = e->src; if (kind == bitint_prec_large) - { - m_gsi = gsi_last_bb (edge_bb); - if (!gsi_end_p (m_gsi)) - gsi_next (&m_gsi); - } + m_gsi = gsi_end_bb (edge_bb); bqp = XALLOCAVEC (struct bq_details, cnt); } else @@ -4717,9 +4729,7 @@ bitint_large_huge::lower_bit_query (gimple *stmt) gsi_prev (&gsi); edge e = split_block (gsi_bb (gsi), gsi_stmt (gsi)); edge_bb = e->src; - m_gsi = gsi_last_bb (edge_bb); - if (!gsi_end_p (m_gsi)) - gsi_next (&m_gsi); + m_gsi = gsi_end_bb (edge_bb); if (ifn == IFN_CLZ) bqp = XALLOCAVEC (struct bq_details, cnt); @@ -5625,6 +5635,21 @@ gimple_lower_bitint (void) break; } } + /* Similarly, e.g. with -frounding-math casts from _BitInt INTEGER_CSTs + to floating point types need to be rewritten. */ + else if (SCALAR_FLOAT_TYPE_P (type)) + { + gimple *g = SSA_NAME_DEF_STMT (s); + if (is_gimple_assign (g) && gimple_assign_rhs_code (g) == FLOAT_EXPR) + { + tree t = gimple_assign_rhs1 (g); + if (TREE_CODE (t) == INTEGER_CST + && TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + && (bitint_precision_kind (TREE_TYPE (t)) + != bitint_prec_small)) + break; + } + } } if (i == num_ssa_names) return 0; @@ -5845,6 +5870,21 @@ gimple_lower_bitint (void) has_large_huge = true; } } + /* Similarly, e.g. with -frounding-math casts from _BitInt INTEGER_CSTs + to floating point types need to be rewritten. */ + else if (SCALAR_FLOAT_TYPE_P (type)) + { + gimple *g = SSA_NAME_DEF_STMT (s); + if (is_gimple_assign (g) && gimple_assign_rhs_code (g) == FLOAT_EXPR) + { + tree t = gimple_assign_rhs1 (g); + if (TREE_CODE (t) == INTEGER_CST + && TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + && (bitint_precision_kind (TREE_TYPE (t)) + >= bitint_prec_large)) + has_large_huge = true; + } + } } for (i = first_large_huge; i < num_ssa_names; ++i) { @@ -6176,6 +6216,19 @@ gimple_lower_bitint (void) kind = this_kind; } } + if (is_gimple_assign (stmt) + && gimple_assign_rhs_code (stmt) == FLOAT_EXPR) + { + t = gimple_assign_rhs1 (stmt); + if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + && TREE_CODE (t) == INTEGER_CST) + { + bitint_prec_kind this_kind + = bitint_precision_kind (TREE_TYPE (t)); + if (this_kind > kind) + kind = this_kind; + } + } if (is_gimple_call (stmt)) { t = gimple_call_lhs (stmt); diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 6e9530c..998b760 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -44,6 +44,11 @@ along with GCC; see the file COPYING3. If not see #include "value-query.h" #include "gimple-range-op.h" #include "gimple-range.h" +#include "cgraph.h" +#include "alloc-pool.h" +#include "symbol-summary.h" +#include "ipa-utils.h" +#include "ipa-prop.h" // Construct a fur_source, and set the m_query field. fur_source::fur_source (range_query *q) @@ -1013,6 +1018,25 @@ fold_using_range::range_of_call (vrange &r, gcall *call, fur_source &) else r.set_varying (type); + tree callee = gimple_call_fndecl (call); + if (callee + && useless_type_conversion_p (TREE_TYPE (TREE_TYPE (callee)), type)) + { + Value_Range val; + if (ipa_return_value_range (val, callee)) + { + r.intersect (val); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Using return value range of "); + print_generic_expr (dump_file, callee, TDF_SLIM); + fprintf (dump_file, ": "); + val.dump (dump_file); + fprintf (dump_file, "\n"); + } + } + } + // If there is an LHS, intersect that with what is known. if (lhs) { diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index d52d71b..02f85e7 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -14382,7 +14382,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) OMP_CLAUSE_LASTPRIVATE)) if (OMP_CLAUSE_DECL (c3) == decl) { - warning_at (OMP_CLAUSE_LOCATION (c3), 0, + warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp, "conditional %<lastprivate%> on loop " "iterator %qD ignored", decl); OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0; @@ -14490,7 +14490,7 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) OMP_CLAUSE_LASTPRIVATE)) if (OMP_CLAUSE_DECL (c3) == decl) { - warning_at (OMP_CLAUSE_LOCATION (c3), 0, + warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp, "conditional %<lastprivate%> on loop " "iterator %qD ignored", decl); OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0; diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index a0af553..be42609 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -3492,44 +3492,6 @@ noce_convert_multiple_sets_1 (struct noce_if_info *if_info, if (if_info->then_else_reversed) std::swap (old_val, new_val); - - /* We allow simple lowpart register subreg SET sources in - bb_ok_for_noce_convert_multiple_sets. Be careful when processing - sequences like: - (set (reg:SI r1) (reg:SI r2)) - (set (reg:HI r3) (subreg:HI (r1))) - For the second insn new_val or old_val (r1 in this example) will be - taken from the temporaries and have the wider mode which will not - match with the mode of the other source of the conditional move, so - we'll end up trying to emit r4:HI = cond ? (r1:SI) : (r3:HI). - Wrap the two cmove operands into subregs if appropriate to prevent - that. */ - - if (!CONSTANT_P (new_val) - && GET_MODE (new_val) != GET_MODE (temp)) - { - machine_mode src_mode = GET_MODE (new_val); - machine_mode dst_mode = GET_MODE (temp); - if (!partial_subreg_p (dst_mode, src_mode)) - { - end_sequence (); - return false; - } - new_val = lowpart_subreg (dst_mode, new_val, src_mode); - } - if (!CONSTANT_P (old_val) - && GET_MODE (old_val) != GET_MODE (temp)) - { - machine_mode src_mode = GET_MODE (old_val); - machine_mode dst_mode = GET_MODE (temp); - if (!partial_subreg_p (dst_mode, src_mode)) - { - end_sequence (); - return false; - } - old_val = lowpart_subreg (dst_mode, old_val, src_mode); - } - /* Try emitting a conditional move passing the backend the canonicalized comparison. The backend is then able to recognize expressions like diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 5a998e7..cce73b3 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -102,8 +102,6 @@ lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi) { default: gcc_unreachable (); -#undef DEF_INTERNAL_FN -#undef DEF_INTERNAL_WIDENING_OPTAB_FN #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE) #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \ case IFN_##NAME: \ @@ -111,8 +109,6 @@ lookup_hilo_internal_fn (internal_fn ifn, internal_fn *lo, internal_fn *hi) *hi = internal_fn (IFN_##NAME##_HI); \ break; #include "internal-fn.def" -#undef DEF_INTERNAL_FN -#undef DEF_INTERNAL_WIDENING_OPTAB_FN } } @@ -129,8 +125,6 @@ lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even, { default: gcc_unreachable (); -#undef DEF_INTERNAL_FN -#undef DEF_INTERNAL_WIDENING_OPTAB_FN #define DEF_INTERNAL_FN(NAME, FLAGS, TYPE) #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \ case IFN_##NAME: \ @@ -138,8 +132,6 @@ lookup_evenodd_internal_fn (internal_fn ifn, internal_fn *even, *odd = internal_fn (IFN_##NAME##_ODD); \ break; #include "internal-fn.def" -#undef DEF_INTERNAL_FN -#undef DEF_INTERNAL_WIDENING_OPTAB_FN } } @@ -4261,7 +4253,6 @@ widening_fn_p (code_helper code) internal_fn fn = as_internal_fn ((combined_fn) code); switch (fn) { - #undef DEF_INTERNAL_WIDENING_OPTAB_FN #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \ case IFN_##NAME: \ case IFN_##NAME##_HI: \ @@ -4270,7 +4261,6 @@ widening_fn_p (code_helper code) case IFN_##NAME##_ODD: \ return true; #include "internal-fn.def" - #undef DEF_INTERNAL_WIDENING_OPTAB_FN default: return false; @@ -4295,6 +4285,7 @@ set_edom_supported_p (void) { \ expand_##TYPE##_optab_fn (fn, stmt, OPTAB##_optab); \ } +#define DEF_INTERNAL_INT_EXT_FN(CODE, FLAGS, OPTAB, TYPE) #define DEF_INTERNAL_SIGNED_OPTAB_FN(CODE, FLAGS, SELECTOR, SIGNED_OPTAB, \ UNSIGNED_OPTAB, TYPE) \ static void \ @@ -4305,8 +4296,6 @@ set_edom_supported_p (void) expand_##TYPE##_optab_fn (fn, stmt, which_optab); \ } #include "internal-fn.def" -#undef DEF_INTERNAL_OPTAB_FN -#undef DEF_INTERNAL_SIGNED_OPTAB_FN /* Routines to expand each internal function, indexed by function number. Each routine has the prototype: @@ -4465,8 +4454,6 @@ get_len_internal_fn (internal_fn fn) { switch (fn) { -#undef DEF_INTERNAL_COND_FN -#undef DEF_INTERNAL_SIGNED_COND_FN #define DEF_INTERNAL_COND_FN(NAME, ...) \ case IFN_COND_##NAME: \ return IFN_COND_LEN_##NAME; @@ -4474,8 +4461,6 @@ get_len_internal_fn (internal_fn fn) case IFN_COND_##NAME: \ return IFN_COND_LEN_##NAME; #include "internal-fn.def" -#undef DEF_INTERNAL_COND_FN -#undef DEF_INTERNAL_SIGNED_COND_FN default: return IFN_LAST; } @@ -5113,3 +5098,67 @@ expand_BITINTTOFLOAT (internal_fn, gcall *stmt) if (val != target) emit_move_insn (target, val); } + +void +expand_POPCOUNT (internal_fn fn, gcall *stmt) +{ + if (gimple_call_num_args (stmt) == 1) + { + expand_unary_optab_fn (fn, stmt, popcount_optab); + return; + } + /* If .POPCOUNT call has 2 arguments, match_single_bit_test marked it + because the result is only used in an equality comparison against 1. + Use rtx costs in that case to determine if .POPCOUNT (arg) == 1 + or (arg ^ (arg - 1)) > arg - 1 is cheaper. */ + bool speed_p = optimize_insn_for_speed_p (); + tree lhs = gimple_call_lhs (stmt); + tree arg = gimple_call_arg (stmt, 0); + tree type = TREE_TYPE (arg); + machine_mode mode = TYPE_MODE (type); + do_pending_stack_adjust (); + start_sequence (); + expand_unary_optab_fn (fn, stmt, popcount_optab); + rtx_insn *popcount_insns = get_insns (); + end_sequence (); + start_sequence (); + rtx plhs = expand_normal (lhs); + rtx pcmp = emit_store_flag (NULL_RTX, EQ, plhs, const1_rtx, mode, 0, 0); + if (pcmp == NULL_RTX) + { + fail: + end_sequence (); + emit_insn (popcount_insns); + return; + } + rtx_insn *popcount_cmp_insns = get_insns (); + end_sequence (); + start_sequence (); + rtx op0 = expand_normal (arg); + rtx argm1 = expand_simple_binop (mode, PLUS, op0, constm1_rtx, NULL_RTX, + 1, OPTAB_DIRECT); + if (argm1 == NULL_RTX) + goto fail; + rtx argxorargm1 = expand_simple_binop (mode, XOR, op0, argm1, NULL_RTX, + 1, OPTAB_DIRECT); + if (argxorargm1 == NULL_RTX) + goto fail; + rtx cmp = emit_store_flag (NULL_RTX, GTU, argxorargm1, argm1, mode, 1, 1); + if (cmp == NULL_RTX) + goto fail; + rtx_insn *cmp_insns = get_insns (); + end_sequence (); + unsigned popcount_cost = (seq_cost (popcount_insns, speed_p) + + seq_cost (popcount_cmp_insns, speed_p)); + unsigned cmp_cost = seq_cost (cmp_insns, speed_p); + if (popcount_cost <= cmp_cost) + emit_insn (popcount_insns); + else + { + emit_insn (cmp_insns); + plhs = expand_normal (lhs); + if (GET_MODE (cmp) != GET_MODE (plhs)) + cmp = convert_to_mode (GET_MODE (plhs), cmp, 1); + emit_move_insn (plhs, cmp); + } +} diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 3d5aca0..ba5e4ce 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -33,9 +33,13 @@ along with GCC; see the file COPYING3. If not see DEF_INTERNAL_SIGNED_OPTAB_FN (NAME, FLAGS, SELECTOR, SIGNED_OPTAB, UNSIGNED_OPTAB, TYPE) DEF_INTERNAL_FLT_FN (NAME, FLAGS, OPTAB, TYPE) + DEF_INTERNAL_FLT_FLOATN_FN (NAME, FLAGS, OPTAB, TYPE) DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE) + DEF_INTERNAL_INT_EXT_FN (NAME, FLAGS, OPTAB, TYPE) DEF_INTERNAL_COND_FN (NAME, FLAGS, OPTAB, TYPE) DEF_INTERNAL_SIGNED_COND_FN (NAME, FLAGS, OPTAB, TYPE) + DEF_INTERNAL_WIDENING_OPTAB_FN (NAME, FLAGS, SELECTOR, SOPTAB, UOPTAB, + TYPE) where NAME is the name of the function, FLAGS is a set of ECF_* flags and FNSPEC is a string describing functions fnspec. @@ -97,6 +101,10 @@ along with GCC; see the file COPYING3. If not see says that the function extends the C-level BUILT_IN_<NAME>{,L,LL,IMAX} group of functions to any integral mode (including vector modes). + DEF_INTERNAL_INT_EXT_FN is like DEF_INTERNAL_INT_FN, except that it + has expand_##NAME defined in internal-fn.cc to override the + DEF_INTERNAL_INT_FN expansion behavior. + DEF_INTERNAL_WIDENING_OPTAB_FN is a wrapper that defines five internal functions with DEF_INTERNAL_SIGNED_OPTAB_FN: - one that describes a widening operation with the same number of elements @@ -160,6 +168,11 @@ along with GCC; see the file COPYING3. If not see DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE) #endif +#ifndef DEF_INTERNAL_INT_EXT_FN +#define DEF_INTERNAL_INT_EXT_FN(NAME, FLAGS, OPTAB, TYPE) \ + DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE) +#endif + #ifndef DEF_INTERNAL_WIDENING_OPTAB_FN #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, FLAGS, SELECTOR, SOPTAB, UOPTAB, TYPE) \ DEF_INTERNAL_SIGNED_OPTAB_FN (NAME, FLAGS, SELECTOR, SOPTAB, UOPTAB, TYPE) \ @@ -432,7 +445,7 @@ DEF_INTERNAL_INT_FN (CLZ, ECF_CONST | ECF_NOTHROW, clz, unary) DEF_INTERNAL_INT_FN (CTZ, ECF_CONST | ECF_NOTHROW, ctz, unary) DEF_INTERNAL_INT_FN (FFS, ECF_CONST | ECF_NOTHROW, ffs, unary) DEF_INTERNAL_INT_FN (PARITY, ECF_CONST | ECF_NOTHROW, parity, unary) -DEF_INTERNAL_INT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary) +DEF_INTERNAL_INT_EXT_FN (POPCOUNT, ECF_CONST | ECF_NOTHROW, popcount, unary) DEF_INTERNAL_FN (GOMP_TARGET_REV, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) DEF_INTERNAL_FN (GOMP_USE_SIMT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) @@ -572,6 +585,10 @@ DEF_INTERNAL_FN (DIVMODBITINT, ECF_LEAF, ". O . O . R . R . ") DEF_INTERNAL_FN (FLOATTOBITINT, ECF_LEAF | ECF_NOTHROW, ". O . . ") DEF_INTERNAL_FN (BITINTTOFLOAT, ECF_PURE | ECF_LEAF, ". R . ") +#undef DEF_INTERNAL_WIDENING_OPTAB_FN +#undef DEF_INTERNAL_SIGNED_COND_FN +#undef DEF_INTERNAL_COND_FN +#undef DEF_INTERNAL_INT_EXT_FN #undef DEF_INTERNAL_INT_FN #undef DEF_INTERNAL_FLT_FN #undef DEF_INTERNAL_FLT_FLOATN_FN diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index 7d72f4d..93598fa 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -262,6 +262,7 @@ extern void expand_MULBITINT (internal_fn, gcall *); extern void expand_DIVMODBITINT (internal_fn, gcall *); extern void expand_FLOATTOBITINT (internal_fn, gcall *); extern void expand_BITINTTOFLOAT (internal_fn, gcall *); +extern void expand_POPCOUNT (internal_fn, gcall *); extern bool vectorized_internal_fn_supported_p (internal_fn, tree); diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 7de2b78..e77bc9c 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -237,6 +237,35 @@ gt_ggc_mx (ipa_vr *&x) return gt_ggc_mx ((ipa_vr *) x); } +/* Analysis summery of function call return value. */ +struct GTY(()) ipa_return_value_summary +{ + /* Known value range. + This needs to be wrapped in struccture due to specific way + we allocate ipa_vr. */ + ipa_vr *vr; +}; + +/* Function summary for return values. */ +class ipa_return_value_sum_t : public function_summary <ipa_return_value_summary *> +{ +public: + ipa_return_value_sum_t (symbol_table *table, bool ggc): + function_summary <ipa_return_value_summary *> (table, ggc) { } + + /* Hook that is called by summary when a node is duplicated. */ + void duplicate (cgraph_node *, + cgraph_node *, + ipa_return_value_summary *data, + ipa_return_value_summary *data2) final override + { + *data2=*data; + } +}; + +/* Variable hoding the return value summary. */ +static GTY(()) function_summary <ipa_return_value_summary *> *ipa_return_value_sum; + /* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl associated with NODE should prevent us from analyzing it for the purposes of IPA-CP. */ @@ -5915,5 +5944,49 @@ ipcp_transform_function (struct cgraph_node *node) return modified_mem_access ? TODO_update_ssa_only_virtuals : 0; } +/* Record that current function return value range is VAL. */ + +void +ipa_record_return_value_range (Value_Range val) +{ + cgraph_node *n = cgraph_node::get (current_function_decl); + if (!ipa_return_value_sum) + { + if (!ipa_vr_hash_table) + ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37); + ipa_return_value_sum = new (ggc_alloc_no_dtor <ipa_return_value_sum_t> ()) + ipa_return_value_sum_t (symtab, true); + ipa_return_value_sum->disable_insertion_hook (); + } + ipa_return_value_sum->get_create (n)->vr = ipa_get_value_range (val); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Recording return range "); + val.dump (dump_file); + fprintf (dump_file, "\n"); + } +} + +/* Return true if value range of DECL is known and if so initialize RANGE. */ + +bool +ipa_return_value_range (Value_Range &range, tree decl) +{ + cgraph_node *n = cgraph_node::get (decl); + if (!n || !ipa_return_value_sum) + return false; + enum availability avail; + n = n->ultimate_alias_target (&avail); + if (avail < AVAIL_AVAILABLE) + return false; + if (n->decl != decl && !useless_type_conversion_p (TREE_TYPE (decl), TREE_TYPE (n->decl))) + return false; + ipa_return_value_summary *v = ipa_return_value_sum->get (n); + if (!v) + return false; + v->vr->get_vrange (range); + return true; +} + #include "gt-ipa-prop.h" diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index fcd0e5c..5901c80 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -309,7 +309,7 @@ public: void get_vrange (Value_Range &) const; bool equal_p (const vrange &) const; const vrange_storage *storage () const { return m_storage; } - void streamer_read (lto_input_block *, data_in *); + void streamer_read (lto_input_block *, class data_in *); void streamer_write (output_block *) const; void dump (FILE *) const; @@ -1274,4 +1274,7 @@ ipa_range_set_and_normalize (vrange &r, tree val) r.set (val, val); } +bool ipa_return_value_range (Value_Range &range, tree decl); +void ipa_record_return_value_range (Value_Range val); + #endif /* IPA_PROP_H */ diff --git a/gcc/ipa-pure-const.cc b/gcc/ipa-pure-const.cc index 058a7dd..3060ffe 100644 --- a/gcc/ipa-pure-const.cc +++ b/gcc/ipa-pure-const.cc @@ -292,6 +292,15 @@ warn_function_cold (tree decl) true, warned_about, "cold"); } +void +warn_function_returns_nonnull (tree decl) +{ + static hash_set<tree> *warned_about; + warned_about + = suggest_attribute (OPT_Wsuggest_attribute_returns_nonnull, decl, + true, warned_about, "returns_nonnull"); +} + /* Check to see if the use (or definition when CHECKING_WRITE is true) variable T is legal in a function that is either pure or const. */ diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 0eefcf4..84728c5 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -105,6 +105,7 @@ tree prevailing_odr_type (tree type); void enable_odr_based_tbaa (tree type); bool odr_based_tbaa_p (const_tree type); void set_type_canonical_for_odr_type (tree type, tree canonical); +void warn_function_returns_nonnull (tree); void register_odr_enum (tree type); diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc index 93e4603..c715a83 100644 --- a/gcc/ira-build.cc +++ b/gcc/ira-build.cc @@ -498,6 +498,7 @@ ira_create_allocno (int regno, bool cap_p, ALLOCNO_NREFS (a) = 0; ALLOCNO_FREQ (a) = 0; ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P (a) = false; + ALLOCNO_SET_REGISTER_FILTERS (a, 0); ALLOCNO_HARD_REGNO (a) = -1; ALLOCNO_CALL_FREQ (a) = 0; ALLOCNO_CALLS_CROSSED_NUM (a) = 0; @@ -902,6 +903,7 @@ create_cap_allocno (ira_allocno_t a) ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a); ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a); ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a); + ALLOCNO_SET_REGISTER_FILTERS (cap, ALLOCNO_REGISTER_FILTERS (a)); merge_hard_reg_conflicts (a, cap, false); @@ -2064,6 +2066,9 @@ propagate_allocno_info (void) ALLOCNO_BAD_SPILL_P (parent_a) = false; ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a); ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a); + ALLOCNO_SET_REGISTER_FILTERS (parent_a, + ALLOCNO_REGISTER_FILTERS (parent_a) + | ALLOCNO_REGISTER_FILTERS (a)); /* If A's allocation can differ from PARENT_A's, we can if necessary spill PARENT_A on entry to A's loop and restore it afterwards. @@ -2465,6 +2470,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a) ALLOCNO_CROSSED_CALLS_ABIS (a) |= ALLOCNO_CROSSED_CALLS_ABIS (from_a); ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a) |= ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a); + ALLOCNO_SET_REGISTER_FILTERS (a, + ALLOCNO_REGISTER_FILTERS (from_a) + | ALLOCNO_REGISTER_FILTERS (a)); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a); diff --git a/gcc/ira-color.cc b/gcc/ira-color.cc index f2e8ea3..214a4f1 100644 --- a/gcc/ira-color.cc +++ b/gcc/ira-color.cc @@ -2163,6 +2163,9 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) if (! check_hard_reg_p (a, hard_regno, conflicting_regs, profitable_hard_regs)) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hard_regno)) + continue; cost = costs[i]; full_cost = full_costs[i]; if (!HONOR_REG_ALLOC_ORDER) @@ -3205,6 +3208,9 @@ improve_allocation (void) if (! check_hard_reg_p (a, hregno, conflicting_regs, profitable_hard_regs)) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), hregno)) + continue; ira_assert (ira_class_hard_reg_index[aclass][hregno] == j); k = allocno_costs == NULL ? 0 : j; costs[hregno] = (allocno_costs == NULL @@ -5275,6 +5281,10 @@ fast_allocation (void) || (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[aclass][mode], hard_regno))) continue; + if (NUM_REGISTER_FILTERS + && !test_register_filters (ALLOCNO_REGISTER_FILTERS (a), + hard_regno)) + continue; if (costs == NULL) { best_hard_regno = hard_regno; diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc index e0528e7..c3efd295 100644 --- a/gcc/ira-costs.cc +++ b/gcc/ira-costs.cc @@ -1662,16 +1662,16 @@ scan_one_insn (rtx_insn *insn) -/* Print allocnos costs to file F. */ +/* Print allocnos costs to the dump file. */ static void -print_allocno_costs (FILE *f) +print_allocno_costs (void) { int k; ira_allocno_t a; ira_allocno_iterator ai; ira_assert (allocno_p); - fprintf (f, "\n"); + fprintf (ira_dump_file, "\n"); FOR_EACH_ALLOCNO (a, ai) { int i, rclass; @@ -1681,32 +1681,34 @@ print_allocno_costs (FILE *f) enum reg_class *cost_classes = cost_classes_ptr->classes; i = ALLOCNO_NUM (a); - fprintf (f, " a%d(r%d,", i, regno); + fprintf (ira_dump_file, " a%d(r%d,", i, regno); if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL) - fprintf (f, "b%d", bb->index); + fprintf (ira_dump_file, "b%d", bb->index); else - fprintf (f, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num); - fprintf (f, ") costs:"); + fprintf (ira_dump_file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num); + fprintf (ira_dump_file, ") costs:"); for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; - fprintf (f, " %s:%d", reg_class_names[rclass], + fprintf (ira_dump_file, " %s:%d", reg_class_names[rclass], COSTS (costs, i)->cost[k]); if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED) - fprintf (f, ",%d", COSTS (total_allocno_costs, i)->cost[k]); + fprintf (ira_dump_file, ",%d", + COSTS (total_allocno_costs, i)->cost[k]); } - fprintf (f, " MEM:%i", COSTS (costs, i)->mem_cost); + fprintf (ira_dump_file, " MEM:%i", COSTS (costs, i)->mem_cost); if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED) - fprintf (f, ",%d", COSTS (total_allocno_costs, i)->mem_cost); - fprintf (f, "\n"); + fprintf (ira_dump_file, ",%d", + COSTS (total_allocno_costs, i)->mem_cost); + fprintf (ira_dump_file, "\n"); } } -/* Print pseudo costs to file F. */ +/* Print pseudo costs to the dump file. */ static void -print_pseudo_costs (FILE *f) +print_pseudo_costs (void) { int regno, k; int rclass; @@ -1714,21 +1716,21 @@ print_pseudo_costs (FILE *f) enum reg_class *cost_classes; ira_assert (! allocno_p); - fprintf (f, "\n"); + fprintf (ira_dump_file, "\n"); for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--) { if (REG_N_REFS (regno) <= 0) continue; cost_classes_ptr = regno_cost_classes[regno]; cost_classes = cost_classes_ptr->classes; - fprintf (f, " r%d costs:", regno); + fprintf (ira_dump_file, " r%d costs:", regno); for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; - fprintf (f, " %s:%d", reg_class_names[rclass], + fprintf (ira_dump_file, " %s:%d", reg_class_names[rclass], COSTS (costs, regno)->cost[k]); } - fprintf (f, " MEM:%i\n", COSTS (costs, regno)->mem_cost); + fprintf (ira_dump_file, " MEM:%i\n", COSTS (costs, regno)->mem_cost); } } @@ -1939,7 +1941,7 @@ calculate_equiv_gains (void) and their best costs. Set up preferred, alternative and allocno classes for pseudos. */ static void -find_costs_and_classes (FILE *dump_file) +find_costs_and_classes (void) { int i, k, start, max_cost_classes_num; int pass; @@ -1991,8 +1993,8 @@ find_costs_and_classes (FILE *dump_file) classes to guide the selection. */ for (pass = start; pass <= flag_expensive_optimizations; pass++) { - if ((!allocno_p || internal_flag_ira_verbose > 0) && dump_file) - fprintf (dump_file, + if ((!allocno_p || internal_flag_ira_verbose > 0) && ira_dump_file) + fprintf (ira_dump_file, "\nPass %i for finding pseudo/allocno costs\n\n", pass); if (pass != start) @@ -2244,8 +2246,8 @@ find_costs_and_classes (FILE *dump_file) alt_class = NO_REGS; setup_reg_classes (i, best, alt_class, regno_aclass[i]); if ((!allocno_p || internal_flag_ira_verbose > 2) - && dump_file != NULL) - fprintf (dump_file, + && ira_dump_file != NULL) + fprintf (ira_dump_file, " r%d: preferred %s, alternative %s, allocno %s\n", i, reg_class_names[best], reg_class_names[alt_class], reg_class_names[regno_aclass[i]]); @@ -2295,16 +2297,16 @@ find_costs_and_classes (FILE *dump_file) } ALLOCNO_CLASS_COST (a) = allocno_cost; } - if (internal_flag_ira_verbose > 2 && dump_file != NULL + if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL && (pass == 0 || pref[a_num] != best)) { - fprintf (dump_file, " a%d (r%d,", a_num, i); + fprintf (ira_dump_file, " a%d (r%d,", a_num, i); if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL) - fprintf (dump_file, "b%d", bb->index); + fprintf (ira_dump_file, "b%d", bb->index); else - fprintf (dump_file, "l%d", + fprintf (ira_dump_file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num); - fprintf (dump_file, ") best %s, allocno %s\n", + fprintf (ira_dump_file, ") best %s, allocno %s\n", reg_class_names[best], reg_class_names[aclass]); } @@ -2329,13 +2331,13 @@ find_costs_and_classes (FILE *dump_file) } } - if (internal_flag_ira_verbose > 4 && dump_file) + if (internal_flag_ira_verbose > 4 && ira_dump_file) { if (allocno_p) - print_allocno_costs (dump_file); + print_allocno_costs (); else - print_pseudo_costs (dump_file); - fprintf (dump_file,"\n"); + print_pseudo_costs (); + fprintf (ira_dump_file,"\n"); } } ira_free (regno_best_class); @@ -2594,7 +2596,7 @@ ira_costs (void) /* Process equivs in reload to update costs through hook ira_adjust_equiv_reg_cost. */ calculate_elim_costs_all_insns (); - find_costs_and_classes (ira_dump_file); + find_costs_and_classes (); setup_allocno_class_and_costs (); finish_regno_cost_classes (); finish_costs (); @@ -2606,17 +2608,20 @@ ira_costs (void) void ira_set_pseudo_classes (bool define_pseudo_classes, FILE *dump_file) { + FILE *saved_file = ira_dump_file; allocno_p = false; internal_flag_ira_verbose = flag_ira_verbose; + ira_dump_file = dump_file; cost_elements_num = max_reg_num (); init_costs (); initiate_regno_cost_classes (); - find_costs_and_classes (dump_file); + find_costs_and_classes (); finish_regno_cost_classes (); if (define_pseudo_classes) pseudo_classes_defined_p = true; finish_costs (); + ira_dump_file = saved_file; } diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 0685e1f..1c3548d 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -328,6 +328,13 @@ struct ira_allocno This is only ever true for non-cap allocnos. */ unsigned int might_conflict_with_parent_p : 1; +#ifndef NUM_REGISTER_FILTERS +#error "insn-config.h not included" +#elif NUM_REGISTER_FILTERS + /* The set of register filters applied to the allocno by operand + alternatives that accept class ACLASS. */ + unsigned int register_filters : NUM_REGISTER_FILTERS; +#endif /* Accumulated usage references of the allocno. Here and below, word 'accumulated' means info for given region and all nested subregions. In this case, 'accumulated' means sum of references @@ -432,6 +439,13 @@ struct ira_allocno #define ALLOCNO_FREQ(A) ((A)->freq) #define ALLOCNO_MIGHT_CONFLICT_WITH_PARENT_P(A) \ ((A)->might_conflict_with_parent_p) +#if NUM_REGISTER_FILTERS +#define ALLOCNO_REGISTER_FILTERS(A) (A)->register_filters +#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((A)->register_filters = (X)) +#else +#define ALLOCNO_REGISTER_FILTERS(A) 0 +#define ALLOCNO_SET_REGISTER_FILTERS(A, X) ((void) (A), gcc_assert ((X) == 0)) +#endif #define ALLOCNO_HARD_REGNO(A) ((A)->hard_regno) #define ALLOCNO_CALL_FREQ(A) ((A)->call_freq) #define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num) diff --git a/gcc/ira-lives.cc b/gcc/ira-lives.cc index 81af5c0..63f2314 100644 --- a/gcc/ira-lives.cc +++ b/gcc/ira-lives.cc @@ -1066,6 +1066,66 @@ process_single_reg_class_operands (bool in_p, int freq) } } +/* Go through the operands of the extracted insn looking for operand + alternatives that apply a register filter. Record any such filters + in the operand's allocno. */ +static void +process_register_constraint_filters () +{ + for (int opno = 0; opno < recog_data.n_operands; ++opno) + { + rtx op = recog_data.operand[opno]; + if (SUBREG_P (op)) + op = SUBREG_REG (op); + if (REG_P (op) && !HARD_REGISTER_P (op)) + { + ira_allocno_t a = ira_curr_regno_allocno_map[REGNO (op)]; + for (int alt = 0; alt < recog_data.n_alternatives; alt++) + { + if (!TEST_BIT (preferred_alternatives, alt)) + continue; + + auto *op_alt = &recog_op_alt[alt * recog_data.n_operands]; + auto cl = alternative_class (op_alt, opno); + /* The two extremes are easy: + + - We should record the filter if CL matches the + allocno class. + + - We should ignore the filter if CL and the allocno class + are disjoint. We'll either pick a different alternative + or reload the operand. + + Things are trickier if the classes overlap. However: + + - If the allocno class includes registers that are not + in CL, some choices of hard register will need a reload + anyway. It isn't obvious that reloads due to filters + are worse than reloads due to regnos being outside CL. + + - Conversely, if the allocno class is a subset of CL, + any allocation will satisfy the class requirement. + We should try to make sure it satisfies the filter + requirement too. This is useful if, for example, + an allocno needs to be in "low" registers to satisfy + some uses, and its allocno class is therefore those + low registers, but the allocno is elsewhere allowed + to be in any even-numbered register. Picking an + even-numbered low register satisfies both types of use. */ + if (!ira_class_subset_p[ALLOCNO_CLASS (a)][cl]) + continue; + + auto filters = alternative_register_filters (op_alt, opno); + if (!filters) + continue; + + filters |= ALLOCNO_REGISTER_FILTERS (a); + ALLOCNO_SET_REGISTER_FILTERS (a, filters); + } + } + } +} + /* Look through the CALL_INSN_FUNCTION_USAGE of a call insn INSN, and see if we find a SET rtx that we can use to deduce that a register can be cheaply caller-saved. Return such a register, or NULL_RTX if none is found. */ @@ -1378,6 +1438,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) } preferred_alternatives = ira_setup_alts (insn); + process_register_constraint_filters (); process_single_reg_class_operands (false, freq); if (call_p) diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 0607c8b..9b6a2af 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -2149,6 +2149,7 @@ process_alt_operands (int only_alternative) int reload_nregs, reload_sum; bool costly_p; enum reg_class cl; + const HARD_REG_SET *cl_filter; /* Calculate some data common for all alternatives to speed up the function. */ @@ -2514,6 +2515,7 @@ process_alt_operands (int only_alternative) || spilled_pseudo_p (op)) win = true; cl = GENERAL_REGS; + cl_filter = nullptr; goto reg; default: @@ -2523,7 +2525,10 @@ process_alt_operands (int only_alternative) case CT_REGISTER: cl = reg_class_for_constraint (cn); if (cl != NO_REGS) - goto reg; + { + cl_filter = get_register_filter (cn); + goto reg; + } break; case CT_CONST_INT: @@ -2567,6 +2572,7 @@ process_alt_operands (int only_alternative) win = true; cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH); + cl_filter = nullptr; badop = false; goto reg; @@ -2600,6 +2606,8 @@ process_alt_operands (int only_alternative) this_alternative_exclude_start_hard_regs |= ira_exclude_class_mode_regs[cl][mode]; this_alternative_set |= reg_class_contents[cl]; + if (cl_filter) + this_alternative_exclude_start_hard_regs |= ~*cl_filter; if (costly_p) { this_costly_alternative @@ -2613,6 +2621,9 @@ process_alt_operands (int only_alternative) if (hard_regno[nop] >= 0 && in_hard_reg_set_p (this_alternative_set, mode, hard_regno[nop]) + && (!cl_filter + || TEST_HARD_REG_BIT (*cl_filter, + hard_regno[nop])) && ((REG_ATTRS (op) && (decl = REG_EXPR (op)) != NULL && VAR_P (decl) && DECL_HARD_REGISTER (decl)) || !(TEST_HARD_REG_BIT diff --git a/gcc/match.pd b/gcc/match.pd index b30de36..95225e4 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2596,6 +2596,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) (op @0 @1)))) +/* And similar for pointers. */ +(for op (eq ne) + (simplify + (op (pointer_plus @0 @1) (pointer_plus @0 @2)) + (op @1 @2))) +(simplify + (pointer_diff (pointer_plus @0 @1) (pointer_plus @0 @2)) + (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1))) + (convert (minus @1 @2)))) /* X - Z < Y - Z is the same as X < Y when there is no overflow. */ (for op (lt le ge gt) @@ -8285,7 +8294,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (simplify (BIT_FIELD_REF (view_convert @0) @1 @2) - (BIT_FIELD_REF @0 @1 @2)) + (if (! INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || type_has_mode_precision_p (TREE_TYPE (@0))) + (BIT_FIELD_REF @0 @1 @2))) (simplify (BIT_FIELD_REF @0 @1 integer_zerop) diff --git a/gcc/objc/objc-act.cc b/gcc/objc/objc-act.cc index fe19aa5..02ed6d9 100644 --- a/gcc/objc/objc-act.cc +++ b/gcc/objc/objc-act.cc @@ -10340,5 +10340,51 @@ objc_common_init_ts (void) MARK_TS_TYPED (PROPERTY_REF); } +/* Information for Objective-C-specific features known to __has_feature. */ + +struct objc_feature_info +{ + typedef bool (*predicate_t) (); + + const char *ident; + predicate_t predicate; + + constexpr objc_feature_info (const char *name) + : ident (name), predicate (nullptr) {} + constexpr objc_feature_info (const char *name, predicate_t p) + : ident (name), predicate (p) {} + + bool has_feature () const + { + return predicate ? predicate () : true; + } +}; + +static bool objc_nonfragile_abi_p () +{ + return flag_next_runtime && flag_objc_abi >= 2; +} + +static constexpr objc_feature_info objc_features[] = +{ + { "objc_default_synthesize_properties" }, + { "objc_instancetype" }, + { "objc_nonfragile_abi", objc_nonfragile_abi_p } +}; + +/* Register Objective-C-specific features for __has_feature. */ + +void +objc_common_register_features () +{ + for (unsigned i = 0; i < ARRAY_SIZE (objc_features); i++) + { + const objc_feature_info *info = objc_features + i; + if (!info->has_feature ()) + continue; + + c_common_register_feature (info->ident, true); + } +} #include "gt-objc-objc-act.h" diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h index 68f9029..df40127 100644 --- a/gcc/objc/objc-act.h +++ b/gcc/objc/objc-act.h @@ -29,6 +29,9 @@ int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *); void objc_common_init_ts (void); const char *objc_get_sarif_source_language (const char *); +/* Register features common to Objective-C and Objective-C++. */ +void objc_common_register_features (); + /* NB: The remaining public functions are prototyped in c-common.h, for the benefit of stub-objc.cc and objc-act.cc. */ diff --git a/gcc/objc/objc-lang.cc b/gcc/objc/objc-lang.cc index 8e56de6..107fb0e 100644 --- a/gcc/objc/objc-lang.cc +++ b/gcc/objc/objc-lang.cc @@ -56,6 +56,16 @@ objc_get_sarif_source_language (const char *) return "objectivec"; } +/* Implement c-family hook to add language-specific features + for __has_{feature,extension}. */ + +void +c_family_register_lang_features () +{ + objc_common_register_features (); + c_register_features (); +} + /* Lang hook routines common to C and ObjC appear in c-objc-common.cc; there should be very few (if any) routines below. */ diff --git a/gcc/objcp/objcp-lang.cc b/gcc/objcp/objcp-lang.cc index ee39aec..8a2c9f7 100644 --- a/gcc/objcp/objcp-lang.cc +++ b/gcc/objcp/objcp-lang.cc @@ -85,6 +85,16 @@ objcp_tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) #undef RECURSE } +/* Implement c-family hook to add language-specific features + for __has_{feature,extension}. */ + +void +c_family_register_lang_features () +{ + objc_common_register_features (); + cp_register_features (); +} + static void objcxx_init_ts (void) { diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index 5c6a7f2..8281ec6 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -3416,8 +3416,9 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, forward = tree_int_cst_sgn (step) != -1; } if (forward ^ OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (deps)) - warning_at (loc, 0, "%qs clause with %<sink%> modifier " - "waiting for lexically later iteration", + warning_at (loc, OPT_Wopenmp, + "%qs clause with %<sink%> modifier " + "waiting for lexically later iteration", OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross"); break; @@ -3555,9 +3556,9 @@ expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd, build_int_cst (itype, 0)); if (integer_zerop (t) && !warned_step) { - warning_at (loc, 0, "%qs clause with %<sink%> modifier " - "refers to iteration never in the iteration " - "space", + warning_at (loc, OPT_Wopenmp, + "%qs clause with %<sink%> modifier refers to " + "iteration never in the iteration space", OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross"); warned_step = true; diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index b88d593..8241574 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -1201,12 +1201,12 @@ omp_check_context_selector (location_t loc, tree ctx) return error_mark_node; } else if (TREE_PURPOSE (t2)) - warning_at (loc, 0, + warning_at (loc, OPT_Wopenmp, "unknown property %qs of %qs selector", IDENTIFIER_POINTER (TREE_PURPOSE (t2)), props[i].selector); else - warning_at (loc, 0, + warning_at (loc, OPT_Wopenmp, "unknown property %qE of %qs selector", TREE_VALUE (t2), props[i].selector); break; diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc index 161bcfe..dd802ca 100644 --- a/gcc/omp-low.cc +++ b/gcc/omp-low.cc @@ -2844,12 +2844,13 @@ scan_omp_for (gomp_for *stmt, omp_context *outer_ctx) tree_code outer_op = OMP_CLAUSE_REDUCTION_CODE (outer_clause); if (outer_var == local_var && outer_op != local_op) { - warning_at (OMP_CLAUSE_LOCATION (local_clause), 0, - "conflicting reduction operations for %qE", - local_var); - inform (OMP_CLAUSE_LOCATION (outer_clause), - "location of the previous reduction for %qE", - outer_var); + if (warning_at (OMP_CLAUSE_LOCATION (local_clause), + OPT_Wopenmp, "conflicting reduction " + "operations for %qE", + local_var)) + inform (OMP_CLAUSE_LOCATION (outer_clause), + "location of the previous reduction for %qE", + outer_var); } if (outer_var == local_var) { @@ -2880,7 +2881,7 @@ scan_omp_for (gomp_for *stmt, omp_context *outer_ctx) } } if (!found) - warning_at (gimple_location (curr_loop->stmt), 0, + warning_at (gimple_location (curr_loop->stmt), OPT_Wopenmp, "nested loop in reduction needs " "reduction clause for %qE", local_var); @@ -3427,12 +3428,12 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) ctx->cancellable = true; if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt), OMP_CLAUSE_NOWAIT)) - warning_at (gimple_location (stmt), 0, + warning_at (gimple_location (stmt), OPT_Wopenmp, "%<cancel for%> inside " "%<nowait%> for construct"); if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt), OMP_CLAUSE_ORDERED)) - warning_at (gimple_location (stmt), 0, + warning_at (gimple_location (stmt), OPT_Wopenmp, "%<cancel for%> inside " "%<ordered%> for construct"); } @@ -3452,7 +3453,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (omp_find_clause (gimple_omp_sections_clauses (ctx->stmt), OMP_CLAUSE_NOWAIT)) - warning_at (gimple_location (stmt), 0, + warning_at (gimple_location (stmt), OPT_Wopenmp, "%<cancel sections%> inside " "%<nowait%> sections construct"); } @@ -3465,7 +3466,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (omp_find_clause (gimple_omp_sections_clauses (ctx->outer->stmt), OMP_CLAUSE_NOWAIT)) - warning_at (gimple_location (stmt), 0, + warning_at (gimple_location (stmt), OPT_Wopenmp, "%<cancel sections%> inside " "%<nowait%> sections construct"); } @@ -3928,7 +3929,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c)) break; } - warning_at (gimple_location (stmt), 0, + warning_at (gimple_location (stmt), OPT_Wopenmp, "%qs construct inside of %qs region", stmt_name, ctx_stmt_name); } @@ -9783,8 +9784,8 @@ lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt, wi::abs (wi::to_wide (fd.loops[i].step)), UNSIGNED)) { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "ignoring sink clause with offset that is not " + warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp, + "ignoring %<sink%> clause with offset that is not " "a multiple of the loop step"); remove = true; goto next_ordered_clause; diff --git a/gcc/omp-simd-clone.cc b/gcc/omp-simd-clone.cc index 57b0793..3fbe428 100644 --- a/gcc/omp-simd-clone.cc +++ b/gcc/omp-simd-clone.cc @@ -387,13 +387,13 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, step = fold_convert (ssizetype, step); if (!tree_fits_shwi_p (step)) { - warning_at (OMP_CLAUSE_LOCATION (t), 0, + warning_at (OMP_CLAUSE_LOCATION (t), OPT_Wopenmp, "ignoring large linear step"); return NULL; } else if (integer_zerop (step)) { - warning_at (OMP_CLAUSE_LOCATION (t), 0, + warning_at (OMP_CLAUSE_LOCATION (t), OPT_Wopenmp, "ignoring zero linear step"); return NULL; } @@ -455,7 +455,7 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, out: if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (node->decl)))) { - warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wopenmp, "ignoring %<#pragma omp declare simd%> on function " "with %<_Atomic%> qualified return type"); return NULL; @@ -465,7 +465,7 @@ simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, if (TYPE_ATOMIC (args[argno]) && clone_info->args[argno].arg_type != SIMD_CLONE_ARG_TYPE_UNIFORM) { - warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wopenmp, "ignoring %<#pragma omp declare simd%> on function " "with %<_Atomic%> qualified non-%<uniform%> argument"); args.release (); diff --git a/gcc/opts.cc b/gcc/opts.cc index 33165c9..5d5efaf 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -42,6 +42,10 @@ along with GCC; see the file COPYING3. If not see /* Set by -fcanon-prefix-map. */ bool flag_canon_prefix_map; +/* Set by finish_options when flag_stack_protector was set only because of + -fhardened. Yuck. */ +bool flag_stack_protector_set_by_fhardened_p; + static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff); /* Names of fundamental debug info formats indexed by enum @@ -1092,6 +1096,17 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_section_anchors = 0; } + if (opts->x_flag_hardened) + { + if (!opts_set->x_flag_auto_var_init) + opts->x_flag_auto_var_init = AUTO_INIT_ZERO; + else if (opts->x_flag_auto_var_init != AUTO_INIT_ZERO) + warning_at (loc, OPT_Whardened, + "%<-ftrivial-auto-var-init=zero%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); + } + if (!opts->x_flag_opts_finished) { /* We initialize opts->x_flag_pie to -1 so that targets can set a @@ -1101,7 +1116,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, /* We initialize opts->x_flag_pic to -1 so that we can tell if -fpic, -fPIC, -fno-pic or -fno-PIC is used. */ if (opts->x_flag_pic == -1) - opts->x_flag_pie = DEFAULT_FLAG_PIE; + opts->x_flag_pie = (opts->x_flag_hardened + ? /*-fPIE*/ 2 : DEFAULT_FLAG_PIE); else opts->x_flag_pie = 0; } @@ -1116,9 +1132,29 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, } /* We initialize opts->x_flag_stack_protect to -1 so that targets - can set a default value. */ + can set a default value. With --enable-default-ssp or -fhardened + the default is -fstack-protector-strong. */ if (opts->x_flag_stack_protect == -1) - opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; + { + /* This should check FRAME_GROWS_DOWNWARD, but on some targets it's + defined in such a way that it uses flag_stack_protect which can't + be used here. Moreover, some targets like BPF don't support + -fstack-protector at all but we don't know that here. So remember + that flag_stack_protect was set at the behest of -fhardened. */ + if (opts->x_flag_hardened) + { + opts->x_flag_stack_protect = SPCT_FLAG_STRONG; + flag_stack_protector_set_by_fhardened_p = true; + } + else + opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; + } + else if (opts->x_flag_hardened + && opts->x_flag_stack_protect != SPCT_FLAG_STRONG) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fstack-protector-strong%> is not enabled by " + "%<-fhardened%> because it was specified on the command " + "line"); if (opts->x_optimize == 0) { @@ -2460,6 +2496,30 @@ parse_and_check_patch_area (const char *arg, bool report_error, free (patch_area_arg); } +/* Print options enabled by -fhardened. Keep this in sync with the manual! */ + +static void +print_help_hardened () +{ + printf ("%s\n", "The following options are enabled by -fhardened:"); + /* Unfortunately, I can't seem to use targetm.fortify_source_default_level + here. */ + printf (" %s\n", "-D_FORTIFY_SOURCE=3 (or =2 for glibc < 2.35)"); + printf (" %s\n", "-D_GLIBCXX_ASSERTIONS"); + printf (" %s\n", "-ftrivial-auto-var-init=zero"); +#ifdef HAVE_LD_PIE + printf (" %s %s\n", "-fPIE", "-pie"); +#endif + if (HAVE_LD_NOW_SUPPORT) + printf (" %s\n", "-Wl,-z,now"); + if (HAVE_LD_RELRO_SUPPORT) + printf (" %s\n", "-Wl,-z,relro"); + printf (" %s\n", "-fstack-protector-strong"); + printf (" %s\n", "-fstack-clash-protection"); + printf (" %s\n", "-fcf-protection=full"); + putchar ('\n'); +} + /* Print help when OPT__help_ is set. */ void @@ -2575,6 +2635,8 @@ print_help (struct gcc_options *opts, unsigned int lang_mask, } else if (lang_flag != 0) *pflags |= lang_flag; + else if (strncasecmp (a, "hardened", len) == 0) + print_help_hardened (); else warning (0, "unrecognized argument to %<--help=%> option: %q.*s", @@ -344,6 +344,7 @@ struct cl_option_handlers /* Hold command-line options associated with stack limitation. */ extern const char *opt_fstack_limit_symbol_arg; extern int opt_fstack_limit_register_no; +extern bool flag_stack_protector_set_by_fhardened_p; /* Input file names. */ diff --git a/gcc/recog.cc b/gcc/recog.cc index 3bd2d73..eaab79c 100644 --- a/gcc/recog.cc +++ b/gcc/recog.cc @@ -2857,6 +2857,7 @@ preprocess_constraints (int n_operands, int n_alternatives, for (j = 0; j < n_alternatives; j++, op_alt += n_operands) { op_alt[i].cl = NO_REGS; + op_alt[i].register_filters = 0; op_alt[i].constraint = p; op_alt[i].matches = -1; op_alt[i].matched = -1; @@ -2919,7 +2920,12 @@ preprocess_constraints (int n_operands, int n_alternatives, case CT_REGISTER: cl = reg_class_for_constraint (cn); if (cl != NO_REGS) - op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl]; + { + op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl]; + auto filter_id = get_register_filter_id (cn); + if (filter_id >= 0) + op_alt[i].register_filters |= 1U << filter_id; + } break; case CT_CONST_INT: @@ -3219,13 +3225,17 @@ constrain_operands (int strict, alternative_mask alternatives) enum reg_class cl = reg_class_for_constraint (cn); if (cl != NO_REGS) { + auto *filter = get_register_filter (cn); if (strict < 0 || (strict == 0 && REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER) || (strict == 0 && GET_CODE (op) == SCRATCH) || (REG_P (op) - && reg_fits_class_p (op, cl, offset, mode))) + && reg_fits_class_p (op, cl, offset, mode) + && (!filter + || TEST_HARD_REG_BIT (*filter, + REGNO (op) + offset)))) win = true; } diff --git a/gcc/recog.h b/gcc/recog.h index c6ef619..5c801e7 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -42,6 +42,7 @@ enum op_type { OP_INOUT }; +#ifndef GENERATOR_FILE struct operand_alternative { /* Pointer to the beginning of the constraint string for this alternative, @@ -62,6 +63,11 @@ struct operand_alternative matches this one. */ int matched : 8; + /* Bit ID is set if the constraint string includes a register constraint with + register filter ID. Use test_register_filters (REGISTER_FILTERS, REGNO) + to test whether REGNO is a valid start register for the operand. */ + unsigned int register_filters : MAX (NUM_REGISTER_FILTERS, 1); + /* Nonzero if '&' was found in the constraint string. */ unsigned int earlyclobber : 1; /* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint @@ -72,8 +78,6 @@ struct operand_alternative /* Nonzero if 'X' was found in the constraint string, or if the constraint string for this alternative was empty. */ unsigned int anything_ok : 1; - - unsigned int unused : 12; }; /* Return the class for operand I of alternative ALT, taking matching @@ -85,6 +89,18 @@ alternative_class (const operand_alternative *alt, int i) return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl; } +/* Return the mask of register filters that should be applied to operand I + of alternative ALT, taking matching constraints into account. */ + +inline unsigned int +alternative_register_filters (const operand_alternative *alt, int i) +{ + return (alt[i].matches >= 0 + ? alt[alt[i].matches].register_filters + : alt[i].register_filters); +} +#endif + /* A class for substituting one rtx for another within an instruction, or for recursively simplifying the instruction as-is. Derived classes can record or filter certain decisions. */ @@ -242,9 +258,11 @@ extern void extract_insn (rtx_insn *); extern void extract_constrain_insn (rtx_insn *insn); extern void extract_constrain_insn_cached (rtx_insn *); extern void extract_insn_cached (rtx_insn *); +#ifndef GENERATOR_FILE extern void preprocess_constraints (int, int, const char **, operand_alternative *, rtx **); extern const operand_alternative *preprocess_insn_constraints (unsigned int); +#endif extern void preprocess_constraints (rtx_insn *); extern rtx_insn *peep2_next_insn (int); extern bool peep2_regno_dead_p (int, int); @@ -380,6 +398,7 @@ struct recog_data_d extern struct recog_data_d recog_data; +#ifndef GENERATOR_FILE extern const operand_alternative *recog_op_alt; /* Return a pointer to an array in which index OP describes the constraints @@ -393,6 +412,7 @@ which_op_alt () recog_data.n_alternatives - 1)); return &recog_op_alt[which_alternative * recog_data.n_operands]; } +#endif /* A table defined in insn-output.cc that give information about each insn-code value. */ diff --git a/gcc/reginfo.cc b/gcc/reginfo.cc index d472a35..5b6e706 100644 --- a/gcc/reginfo.cc +++ b/gcc/reginfo.cc @@ -140,6 +140,9 @@ reginfo_cc_finalize (void) CLEAR_HARD_REG_SET (global_reg_set); } +/* In insn-preds.cc. */ +extern void init_reg_class_start_regs (); + /* Given a register bitmap, turn on the bits in a HARD_REG_SET that correspond to the hard registers, if any, set in that map. This could be done far more efficiently by having all sorts of special-cases @@ -198,6 +201,8 @@ init_reg_sets (void) SET_HARD_REG_SET (accessible_reg_set); SET_HARD_REG_SET (operand_reg_set); + + init_reg_class_start_regs (); } /* We need to save copies of some of the register information which diff --git a/gcc/rtl-ssa/access-utils.h b/gcc/rtl-ssa/access-utils.h index f078625b..9a62add 100644 --- a/gcc/rtl-ssa/access-utils.h +++ b/gcc/rtl-ssa/access-utils.h @@ -78,6 +78,46 @@ drop_memory_access (T accesses) return T (arr.begin (), accesses.size () - 1); } +// Filter ACCESSES to return an access_array of only those accesses that +// satisfy PREDICATE. Alocate the new array above WATERMARK. +template<typename T, typename FilterPredicate> +inline T +filter_accesses (obstack_watermark &watermark, + T accesses, + FilterPredicate predicate) +{ + access_array_builder builder (watermark); + builder.reserve (accesses.size ()); + for (auto access : accesses) + if (predicate (access)) + builder.quick_push (access); + return T (builder.finish ()); +} + +// Given an array of ACCESSES, remove any access with regno REGNO. +// Allocate the new access array above WM. +template<typename T> +inline T +remove_regno_access (obstack_watermark &watermark, + T accesses, unsigned int regno) +{ + using Access = decltype (accesses[0]); + auto pred = [regno](Access a) { return a->regno () != regno; }; + return filter_accesses (watermark, accesses, pred); +} + +// As above, but additionally check that we actually did remove an access. +template<typename T> +inline T +check_remove_regno_access (obstack_watermark &watermark, + T accesses, unsigned regno) +{ + auto orig_size = accesses.size (); + auto result = remove_regno_access (watermark, accesses, regno); + gcc_assert (result.size () < orig_size); + return result; +} + // If sorted array ACCESSES includes a reference to REGNO, return the // access, otherwise return null. template<typename T> diff --git a/gcc/rtl-ssa/accesses.cc b/gcc/rtl-ssa/accesses.cc index 510545a..9ec0e6b 100644 --- a/gcc/rtl-ssa/accesses.cc +++ b/gcc/rtl-ssa/accesses.cc @@ -1456,6 +1456,16 @@ function_info::make_uses_available (obstack_watermark &watermark, return use_array (new_uses, num_uses); } +set_info * +function_info::create_set (obstack_watermark &watermark, + insn_info *insn, + resource_info resource) +{ + auto set = change_alloc<set_info> (watermark, insn, resource); + set->m_is_temp = true; + return set; +} + // Return true if ACCESS1 can represent ACCESS2 and if ACCESS2 can // represent ACCESS1. static bool @@ -1587,16 +1597,14 @@ access_array rtl_ssa::remove_note_accesses_base (obstack_watermark &watermark, access_array accesses) { + auto predicate = [](access_info *a) { + return !a->only_occurs_in_notes (); + }; + for (access_info *access : accesses) if (access->only_occurs_in_notes ()) - { - access_array_builder builder (watermark); - builder.reserve (accesses.size ()); - for (access_info *access2 : accesses) - if (!access2->only_occurs_in_notes ()) - builder.quick_push (access2); - return builder.finish (); - } + return filter_accesses (watermark, accesses, predicate); + return accesses; } diff --git a/gcc/rtl-ssa/accesses.h b/gcc/rtl-ssa/accesses.h index fce31d4..7e7a90e 100644 --- a/gcc/rtl-ssa/accesses.h +++ b/gcc/rtl-ssa/accesses.h @@ -204,6 +204,10 @@ public: // in the main instruction pattern. bool only_occurs_in_notes () const { return m_only_occurs_in_notes; } + // Return true if this is a temporary access, e.g. one created for + // an insn that is about to be inserted. + bool is_temporary () const { return m_is_temp; } + protected: access_info (resource_info, access_kind); diff --git a/gcc/rtl-ssa/changes.cc b/gcc/rtl-ssa/changes.cc index aab532b..2f2d12d 100644 --- a/gcc/rtl-ssa/changes.cc +++ b/gcc/rtl-ssa/changes.cc @@ -394,14 +394,20 @@ move_insn (insn_change &change, insn_info *after) // At the moment we don't support moving instructions between EBBs, // but this would be worth adding if it's useful. insn_info *insn = change.insn (); - gcc_assert (after->ebb () == insn->ebb ()); + bb_info *bb = after->bb (); basic_block cfg_bb = bb->cfg_bb (); - if (insn->bb () != bb) - // Force DF to mark the old block as dirty. - df_insn_delete (rtl); - ::remove_insn (rtl); + if (!insn->is_temporary ()) + { + gcc_assert (after->ebb () == insn->ebb ()); + + if (insn->bb () != bb) + // Force DF to mark the old block as dirty. + df_insn_delete (rtl); + ::remove_insn (rtl); + } + ::add_insn_after (rtl, after_rtl, cfg_bb); } @@ -437,12 +443,33 @@ function_info::finalize_new_accesses (insn_change &change, insn_info *pos) { def_info *def = find_access (change.new_defs, ref.regno); gcc_assert (def); + + if (def->m_is_temp && is_a<set_info *> (def) && def->last_def ()) + { + // For temporary sets being added with this change, we keep track of + // the corresponding permanent def using the last_def link. + // + // So if we have one of these, follow it to get the permanent def. + def = def->last_def (); + gcc_assert (!def->m_is_temp && !def->m_has_been_superceded); + } + if (def->m_is_temp) { - // At present, the only temporary instruction definitions we - // create are clobbers, such as those added during recog. - gcc_assert (is_a<clobber_info *> (def)); - def = allocate<clobber_info> (change.insn (), ref.regno); + if (is_a<clobber_info *> (def)) + def = allocate<clobber_info> (change.insn (), ref.regno); + else if (is_a<set_info *> (def)) + { + // Install the permanent set in the last_def link of the + // temporary def. This allows us to find the permanent def + // later in case we see a second write to the same resource. + def_info *perm_def = allocate<set_info> (change.insn (), + def->resource ()); + def->set_last_def (perm_def); + def = perm_def; + } + else + gcc_unreachable (); } else if (!def->m_has_been_superceded) { @@ -645,6 +672,8 @@ function_info::apply_changes_to_insn (insn_change &change) insn->set_accesses (builder.finish ().begin (), num_defs, num_uses); } + + insn->m_is_temp = false; } // Add a temporary placeholder instruction after AFTER. @@ -677,7 +706,8 @@ function_info::change_insns (array_slice<insn_change *> changes) if (!change->is_deletion ()) { // Remove any notes that are no longer relevant. - update_notes (change->rtl ()); + if (!change->insn ()->m_is_temp) + update_notes (change->rtl ()); // Make sure that the placement of this instruction would still // leave room for previous instructions. @@ -686,6 +716,17 @@ function_info::change_insns (array_slice<insn_change *> changes) // verify_insn_changes is supposed to make sure that this holds. gcc_unreachable (); min_insn = later_insn (min_insn, change->move_range.first); + + if (change->insn ()->m_is_temp) + { + change->m_insn = allocate<insn_info> (change->insn ()->bb (), + change->rtl (), + change->insn_uid ()); + + // Set the flag again so subsequent logic is aware. + // It will be cleared later on. + change->m_insn->m_is_temp = true; + } } } @@ -784,7 +825,8 @@ function_info::change_insns (array_slice<insn_change *> changes) // Remove the placeholder first so that we have a wider range of // program points when inserting INSN. insn_info *after = placeholder->prev_any_insn (); - remove_insn (insn); + if (!insn->is_temporary ()) + remove_insn (insn); remove_insn (placeholder); insn->set_bb (after->bb ()); add_insn_after (insn, after); @@ -1105,6 +1147,28 @@ function_info::perform_pending_updates () return changed_cfg; } +insn_info * +function_info::create_insn (obstack_watermark &watermark, + rtx_code insn_code, + rtx pat) +{ + rtx_insn *rti = nullptr; + + // TODO: extend, move in to emit-rtl.cc. + switch (insn_code) + { + case INSN: + rti = make_insn_raw (pat); + break; + default: + gcc_unreachable (); + } + + auto insn = change_alloc<insn_info> (watermark, nullptr, rti, INSN_UID (rti)); + insn->m_is_temp = true; + return insn; +} + // Print a description of CHANGE to PP. void rtl_ssa::pp_insn_change (pretty_printer *pp, const insn_change &change) diff --git a/gcc/rtl-ssa/changes.h b/gcc/rtl-ssa/changes.h index d56e3a6..d91cf43 100644 --- a/gcc/rtl-ssa/changes.h +++ b/gcc/rtl-ssa/changes.h @@ -32,6 +32,8 @@ namespace rtl_ssa { // something that we might do. class insn_change { + friend class function_info; + public: enum delete_action { DELETE }; diff --git a/gcc/rtl-ssa/functions.h b/gcc/rtl-ssa/functions.h index ecb40fd..4ffd3fa 100644 --- a/gcc/rtl-ssa/functions.h +++ b/gcc/rtl-ssa/functions.h @@ -68,6 +68,16 @@ public: // Return the SSA information for CFG_BB. bb_info *bb (basic_block cfg_bb) const { return m_bbs[cfg_bb->index]; } + // Create a temporary def. + set_info *create_set (obstack_watermark &watermark, + insn_info *insn, + resource_info resource); + + // Create a temporary insn with code INSN_CODE and pattern PAT. + insn_info *create_insn (obstack_watermark &watermark, + rtx_code insn_code, + rtx pat); + // Return a list of all the instructions in the function, in reverse // postorder. The list includes both real and artificial instructions. // @@ -195,6 +205,10 @@ public: // Print the contents of the function to PP. void print (pretty_printer *pp) const; + // Allocate an object of type T above the obstack watermark WM. + template<typename T, typename... Ts> + T *change_alloc (obstack_watermark &wm, Ts... args); + private: class bb_phi_info; class build_info; diff --git a/gcc/rtl-ssa/insns.cc b/gcc/rtl-ssa/insns.cc index 5fde3f2..2fa48e0 100644 --- a/gcc/rtl-ssa/insns.cc +++ b/gcc/rtl-ssa/insns.cc @@ -192,6 +192,11 @@ insn_info::print_full (pretty_printer *pp) const pp_newline_and_indent (pp, 0); pp_string (pp, "has volatile refs"); } + if (m_is_temp) + { + pp_newline_and_indent (pp, 0); + pp_string (pp, "temporary"); + } } pp_indentation (pp) -= 2; } diff --git a/gcc/rtl-ssa/insns.h b/gcc/rtl-ssa/insns.h index a604fe2..6d05067 100644 --- a/gcc/rtl-ssa/insns.h +++ b/gcc/rtl-ssa/insns.h @@ -306,6 +306,8 @@ public: // Print a full description of the instruction. void print_full (pretty_printer *) const; + bool is_temporary () const { return m_is_temp; } + private: // The first-order way of representing the order between instructions // is to assign "program points", with higher point numbers coming @@ -414,8 +416,11 @@ private: unsigned int m_has_pre_post_modify : 1; unsigned int m_has_volatile_refs : 1; + // Indicates the insn is a temporary / new user-allocated insn. + unsigned int m_is_temp : 1; + // For future expansion. - unsigned int m_spare : 27; + unsigned int m_spare : 26; // The program point at which the instruction occurs. // diff --git a/gcc/rtl-ssa/internals.inl b/gcc/rtl-ssa/internals.inl index e49297c..907c450 100644 --- a/gcc/rtl-ssa/internals.inl +++ b/gcc/rtl-ssa/internals.inl @@ -415,6 +415,7 @@ inline insn_info::insn_info (bb_info *bb, rtx_insn *rtl, int cost_or_uid) m_is_asm (false), m_has_pre_post_modify (false), m_has_volatile_refs (false), + m_is_temp (false), m_spare (0), m_point (0), m_cost_or_uid (cost_or_uid), diff --git a/gcc/rtl-ssa/member-fns.inl b/gcc/rtl-ssa/member-fns.inl index ce2db04..b8940ca 100644 --- a/gcc/rtl-ssa/member-fns.inl +++ b/gcc/rtl-ssa/member-fns.inl @@ -962,4 +962,16 @@ function_info::add_regno_clobber (obstack_watermark &watermark, return true; } +template<typename T, typename... Ts> +inline T * +function_info::change_alloc (obstack_watermark &wm, Ts... args) +{ + static_assert (std::is_trivially_destructible<T>::value, + "destructor won't be called"); + static_assert (alignof (T) <= obstack_alignment, + "too much alignment required"); + void *addr = XOBNEW (wm, T); + return new (addr) T (std::forward<Ts> (args)...); +} + } diff --git a/gcc/rtl-ssa/movement.h b/gcc/rtl-ssa/movement.h index ec076db..41226dd 100644 --- a/gcc/rtl-ssa/movement.h +++ b/gcc/rtl-ssa/movement.h @@ -182,6 +182,11 @@ restrict_movement_for_defs_ignoring (insn_range_info &move_range, { for (def_info *def : defs) { + // Skip fresh defs that are being inserted, as these shouldn't + // constrain movement. + if (def->is_temporary ()) + continue; + // If the definition is a clobber, we can move it with respect // to other clobbers. // @@ -247,7 +252,8 @@ restrict_movement_for_defs_ignoring (insn_range_info &move_range, // Make sure that we don't move stores between basic blocks, since we // don't have enough information to tell whether it's safe. - if (def_info *def = memory_access (defs)) + def_info *def = memory_access (defs); + if (def && !def->is_temporary ()) { move_range = move_later_than (move_range, def->bb ()->head_insn ()); move_range = move_earlier_than (move_range, def->bb ()->end_insn ()); diff --git a/gcc/rtl.def b/gcc/rtl.def index 88e2b19..a40e1a7 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -1016,8 +1016,10 @@ DEF_RTL_EXPR(DEFINE_SPECIAL_PREDICATE, "define_special_predicate", "ses", RTX_EX at -m switches and the like. 2: A docstring for this constraint, in Texinfo syntax; not currently used, in future will be incorporated into the manual's list of - machine-specific operand constraints. */ -DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RTX_EXTRA) + machine-specific operand constraints. + 3: A C expression that evalutes to true if "regno" is a valid + start register. */ +DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sssS", RTX_EXTRA) /* Definition of a non-register operand constraint. These look at the operand and decide whether it fits the constraint. diff --git a/gcc/rust/ChangeLog b/gcc/rust/ChangeLog index 186ff4c..f942a8f 100644 --- a/gcc/rust/ChangeLog +++ b/gcc/rust/ChangeLog @@ -1,3 +1,7 @@ +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * rust-location.h: Include "rich-location.h". + 2023-10-20 Patrick Palka <ppalka@redhat.com> PR rust/111899 diff --git a/gcc/sort.cc b/gcc/sort.cc index 9a0113f..feef345 100644 --- a/gcc/sort.cc +++ b/gcc/sort.cc @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see - deterministic (but not necessarily stable) - fast, especially for common cases (0-5 elements of size 8 or 4) - The implementation uses a network sort for up to 5 elements and + The implementation uses sorting networks for up to 5 elements and a merge sort on top of that. Neither stage has branches depending on comparator result, trading extra arithmetic for branch mispredictions. */ @@ -53,7 +53,7 @@ struct sort_ctx char *out; // output buffer size_t n; // number of elements size_t size; // element size - size_t nlim; // limit for network sort + size_t nlim; // limit for using sorting networks }; /* Like sort_ctx, but for use with qsort_r-style comparators. Several @@ -151,7 +151,7 @@ cmp1 (char *e0, char *e1, sort_ctx *c) return x & (c->cmp (e0, e1) >> 31); } -/* Execute network sort on 2 to 5 elements from IN, placing them into C->OUT. +/* Apply a sorting network to 2 to 5 elements from IN, placing them into C->OUT. IN may be equal to C->OUT, in which case elements are sorted in place. */ template<typename sort_ctx> static void diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h index 3ed6162..5fd49a2 100644 --- a/gcc/symbol-summary.h +++ b/gcc/symbol-summary.h @@ -71,7 +71,7 @@ public: = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this); } - /* Enable insertion hook invocation. */ + /* Disable insertion hook invocation. */ void disable_insertion_hook () { if (m_symtab_insertion_hook != NULL) diff --git a/gcc/system.h b/gcc/system.h index e924152..16db87b 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -1217,28 +1217,11 @@ helper_const_non_const_cast (const char *p) #endif #ifdef ENABLE_VALGRIND_ANNOTATIONS -# ifdef HAVE_VALGRIND_MEMCHECK_H -# include <valgrind/memcheck.h> -# elif defined HAVE_MEMCHECK_H -# include <memcheck.h> -# else -# include <valgrind.h> -# endif -/* Compatibility macros to let valgrind 3.1 work. */ -# ifndef VALGRIND_MAKE_MEM_NOACCESS -# define VALGRIND_MAKE_MEM_NOACCESS VALGRIND_MAKE_NOACCESS -# endif -# ifndef VALGRIND_MAKE_MEM_DEFINED -# define VALGRIND_MAKE_MEM_DEFINED VALGRIND_MAKE_READABLE -# endif -# ifndef VALGRIND_MAKE_MEM_UNDEFINED -# define VALGRIND_MAKE_MEM_UNDEFINED VALGRIND_MAKE_WRITABLE -# endif +#include <valgrind/memcheck.h> #else -/* Avoid #ifdef:s when we can help it. */ +/* VALGRIND_DISCARD unregisters the given block handle, + but our code misuses it for discarding annotations. */ #define VALGRIND_DISCARD(x) -#define VALGRIND_MALLOCLIKE_BLOCK(w,x,y,z) -#define VALGRIND_FREELIKE_BLOCK(x,y) #endif /* Macros to temporarily ignore some warnings. */ diff --git a/gcc/target-globals.cc b/gcc/target-globals.cc index 81244b1..cfa0045 100644 --- a/gcc/target-globals.cc +++ b/gcc/target-globals.cc @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "bb-reorder.h" #include "lower-subreg.h" #include "function-abi.h" +#include "tm_p.h" #if SWITCHABLE_TARGET class target_globals default_target_globals = { @@ -60,7 +61,8 @@ class target_globals default_target_globals = { &default_target_builtins, &default_target_gcse, &default_target_bb_reorder, - &default_target_lower_subreg + &default_target_lower_subreg, + &default_target_constraints }; class target_globals * @@ -84,6 +86,7 @@ save_target_globals (void) g->gcse = XCNEW (struct target_gcse); g->bb_reorder = XCNEW (struct target_bb_reorder); g->lower_subreg = XCNEW (struct target_lower_subreg); + g->constraints = XCNEW (target_constraints); restore_target_globals (g); init_reg_sets (); target_reinit (); @@ -141,6 +144,7 @@ target_globals::~target_globals () XDELETE (gcse); XDELETE (bb_reorder); XDELETE (lower_subreg); + XDELETE (constraints); } } diff --git a/gcc/target-globals.h b/gcc/target-globals.h index daedf66..42f082c 100644 --- a/gcc/target-globals.h +++ b/gcc/target-globals.h @@ -38,6 +38,7 @@ extern struct target_builtins *this_target_builtins; extern struct target_gcse *this_target_gcse; extern struct target_bb_reorder *this_target_bb_reorder; extern struct target_lower_subreg *this_target_lower_subreg; +extern struct target_constraints *this_target_constraints; #endif class GTY(()) target_globals { @@ -61,6 +62,7 @@ public: struct target_gcse *GTY((skip)) gcse; struct target_bb_reorder *GTY((skip)) bb_reorder; struct target_lower_subreg *GTY((skip)) lower_subreg; + struct target_constraints *GTY((skip)) constraints; }; #if SWITCHABLE_TARGET @@ -89,6 +91,7 @@ restore_target_globals (class target_globals *g) this_target_gcse = g->gcse; this_target_bb_reorder = g->bb_reorder; this_target_lower_subreg = g->lower_subreg; + this_target_constraints = g->constraints; } #endif diff --git a/gcc/target.def b/gcc/target.def index 475c55c..eae7959 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2671,6 +2671,13 @@ DEFHOOK default_libc_has_fast_function) DEFHOOK +(fortify_source_default_level, + "This hook determines what value _FORTIFY_SOURCE will be set to when using\n\ +the command-line option -fhardened.", + unsigned, (void), + default_fortify_source_default_level) + +DEFHOOK (libm_function_max_error, "This hook determines expected maximum errors for math functions measured\n\ in ulps (units of the last place). 0 means 0.5ulps precision (correctly\n\ diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 6b5173b..a2dc733 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -1906,6 +1906,14 @@ bsd_libc_has_function (enum function_class fn_class, return false; } +/* By default, -fhardened will add -D_FORTIFY_SOURCE=2. */ + +unsigned +default_fortify_source_default_level () +{ + return 2; +} + unsigned default_libm_function_max_error (unsigned, machine_mode, bool) { diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 0b35e8a..26695ab 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -219,6 +219,7 @@ extern bool default_libc_has_fast_function (int fcode); extern bool no_c99_libc_has_function (enum function_class, tree); extern bool gnu_libc_has_function (enum function_class, tree); extern bool bsd_libc_has_function (enum function_class, tree); +extern unsigned default_fortify_source_default_level (void); extern unsigned default_libm_function_max_error (unsigned, machine_mode, bool); extern unsigned glibc_linux_libm_function_max_error (unsigned, machine_mode, bool); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 53e7e89..e331429 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,1413 @@ +2023-11-26 Hans-Peter Nilsson <hp@axis.com> + + * gcc.dg/uninit-pred-9_b.c: Remove xfail for line 20. Pass + --param=logical-op-non-short-circuit=0. Comment why. + +2023-11-26 Hans-Peter Nilsson <hp@axis.com> + + * gcc.dg/uninit-pred-9_b.c: Remove xfail for MMIX from line 23. + +2023-11-26 Harald Anlauf <anlauf@gmx.de> + + PR fortran/111880 + * gfortran.dg/pr111880.f90: New test. + +2023-11-26 John David Anglin <danglin@gcc.gnu.org> + + * gcc.dg/analyzer/strndup-1.c: Skip on hppa*-*-hpux*. + +2023-11-26 John David Anglin <danglin@gcc.gnu.org> + + * gcc.dg/analyzer/fd-glibc-datagram-client.c: Skip on hppa*-*-hpux*. + * gcc.dg/analyzer/fd-glibc-datagram-socket.c: Likewise. + +2023-11-26 John David Anglin <danglin@gcc.gnu.org> + + * g++.dg/pr104869.C: Add attribute visibility default to + main prototype. + +2023-11-26 John David Anglin <danglin@gcc.gnu.org> + + * g++.dg/modules/bad-mapper-1.C: Add hppa*-*-hpux* to dg-error + "this-will-not-work" targets. + +2023-11-26 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gcc.target/i386/cf_check-6.c: Only run on Linux. + +2023-11-26 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * gcc.target/i386/pr112686.c: Add a requirement for split_stack. + +2023-11-26 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + * gcc.target/riscv/rvv/base/vf_avl-1.c: Adapt test. + * gcc.target/riscv/rvv/autovec/pr112599-3.c: New test. + +2023-11-26 Andrew Pinski <quic_apinski@quicinc.com> + + PR testsuite/112691 + * gcc.dg/vla-1.c: Add -fno-ipa-vrp. + Remove noipa from f1. + +2023-11-26 Andrew Pinski <quic_apinski@quicinc.com> + + PR testsuite/112688 + * gcc.target/aarch64/simd/vmulx.x (foo32): Mark as noipa rather + than noinline. + (foo4): Likewise. + +2023-11-26 Andrew Pinski <quic_apinski@quicinc.com> + + PR testsuite/108321 + * g++.dg/contracts/contracts-tmpl-spec2.C: Add -fsigned-char + to options. + +2023-11-25 Andrew Pinski <quic_apinski@quicinc.com> + + PR testsuite/112688 + * gcc.target/aarch64/movk.c: Add noipa on dummy_number_generator + and remove -fno-inline option. + +2023-11-25 Jakub Jelinek <jakub@redhat.com> + + PR target/111408 + * gcc.c-torture/execute/pr111408.c: New test. + +2023-11-25 Andrew Pinski <pinskia@gmail.com> + Jakub Jelinek <jakub@redhat.com> + + PR target/109977 + * gcc.dg/pr109977.c: New test. + +2023-11-25 Nathaniel Shead <nathanieloshead@gmail.com> + + * g++.dg/modules/using-10.C: New test. + * g++.dg/modules/using-enum-2.C: New test. + +2023-11-25 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/102341 + * g++.dg/modules/export-1.C: Adjust test. + * g++.dg/modules/export-2_a.C: New test. + * g++.dg/modules/export-2_b.C: New test. + +2023-11-24 Lewis Hyatt <lhyatt@gmail.com> + + PR pch/112319 + * g++.dg/pch/pr112319.C: New test. + * g++.dg/pch/pr112319.Hs: New test. + * gcc.dg/pch/pr112319.c: New test. + * gcc.dg/pch/pr112319.hs: New test. + +2023-11-24 Martin Jambor <mjambor@suse.cz> + + PR middle-end/109849 + * g++.dg/tree-ssa/pr109849.C: New test. + * g++.dg/tree-ssa/sra-eh-1.C: Likewise. + * gcc.dg/tree-ssa/pr109849.c: Likewise. + * gcc.dg/tree-ssa/sra-longjmp-1.c: Likewise. + * gfortran.dg/pr43984.f90: Added -fno-tree-sra to dg-options. + +2023-11-24 Uros Bizjak <ubizjak@gmail.com> + + PR target/112686 + * gcc.target/i386/pr112686.c: New test. + +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * c-c++-common/gomp/depobj-3.c: New test. + * gfortran.dg/gomp/depobj-3.f90: New test. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/99232 + * g++.dg/modules/pr99232_a.C: New test. + * g++.dg/modules/pr99232_b.C: New test. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112694 + * gcc.target/riscv/rvv/autovec/pr112694-1.c: New test. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR target/112681 + * gcc.target/i386/sse4-pr112681.c: New test. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/112673 + * gcc.dg/pr112673.c: New test. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112679 + * gcc.dg/bitint-42.c: New test. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112668 + * gcc.dg/bitint-40.c: New test. + +2023-11-24 Jakub Jelinek <jakub@redhat.com> + + PR c++/112619 + * g++.dg/eh/pr112619.C: New test. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + * gcc.target/riscv/rvv/autovec/pr112599-2.c: New test. + +2023-11-24 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/autovec/vls-vlmax/perm-4.c: Adapt test. + * gcc.target/riscv/rvv/autovec/vls/perm-4.c: Ditto. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/107398 + * g++.dg/modules/lambda-6_a.C: New test. + * g++.dg/modules/lambda-6_b.C: New test. + +2023-11-24 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/98885 + * g++.dg/modules/export-1.C: Adjust error messages. Remove + xfails for working case. Add new test case. + +2023-11-23 John David Anglin <danglin@gcc.gnu.org> + + * g++.dg/modules/bad-mapper-1.C: Add hppa*-*-hpux* to dg-error + "-:failed mapper handshake communication" targets. + +2023-11-23 John David Anglin <danglin@gcc.gnu.org> + + * gcc.dg/analyzer/fd-4.c: Define _MODE_T on hpux. + +2023-11-23 John David Anglin <danglin@gcc.gnu.org> + + * g++.dg/pr104869.C: Export main on hpux. + +2023-11-23 Iain Sandoe <iain@sandoe.co.uk> + + * lib/scanasm.exp: Allow multiple function start symbols, + taking the last as the function name. + +2023-11-23 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104819 + * gfortran.dg/assumed_rank_10.f90: Add MOLD argument to NULL(). + * gfortran.dg/assumed_rank_8.f90: Likewise. + +2023-11-23 Harald Anlauf <anlauf@gmx.de> + + PR fortran/112609 + * gfortran.dg/system_clock_1.f90: Add option -std=f2003. + * gfortran.dg/system_clock_3.f08: Add option -std=f2008. + * gfortran.dg/system_clock_4.f90: New test. + +2023-11-23 John David Anglin <danglin@gcc.gnu.org> + + * g++.dg/cpp0x/initlist-const1.C: xfail scan-assembler-not + check on hppa*-*-hpux*. + +2023-11-23 John David Anglin <danglin@gcc.gnu.org> + + * c-c++-common/Wattributes.c: Don't skip check for warning + at line 411 in Wattributes.c on hppa*64*-*-*. + +2023-11-23 Marek Polacek <polacek@redhat.com> + + * gcc.misc-tests/help.exp: Test -fhardened. + * c-c++-common/fhardened-1.S: New test. + * c-c++-common/fhardened-1.c: New test. + * c-c++-common/fhardened-10.c: New test. + * c-c++-common/fhardened-11.c: New test. + * c-c++-common/fhardened-12.c: New test. + * c-c++-common/fhardened-13.c: New test. + * c-c++-common/fhardened-14.c: New test. + * c-c++-common/fhardened-15.c: New test. + * c-c++-common/fhardened-2.c: New test. + * c-c++-common/fhardened-3.c: New test. + * c-c++-common/fhardened-4.c: New test. + * c-c++-common/fhardened-5.c: New test. + * c-c++-common/fhardened-6.c: New test. + * c-c++-common/fhardened-7.c: New test. + * c-c++-common/fhardened-8.c: New test. + * c-c++-common/fhardened-9.c: New test. + * gcc.target/i386/cf_check-6.c: New test. + +2023-11-23 Maciej W. Rozycki <macro@embecosm.com> + + * lib/scanasm.exp (scan-assembler-times): Remove the `-inline' + option to `regexp' and the wrapping `llength' call. + +2023-11-23 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/aarch64/ccmp_1.c: Use non-capturing parentheses + with `scan-assembler-times'. + +2023-11-23 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/arm/pr53447-5.c: Use non-capturing parentheses with + `scan-assembler-times'. + +2023-11-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/112672 + * gcc.target/i386/pr112672.c: New test. + +2023-11-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/89316 + * g++.target/i386/pr89316.C: New test. + * gcc.target/i386/pr112605-1.c: New test. + * gcc.target/i386/pr112605-2.c: New test. + * gcc.target/i386/pr112605.c: New test. + +2023-11-23 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/ccor.c: New test. + +2023-11-23 Juergen Christ <jchrist@linux.ibm.com> + + * gcc.target/s390/int128load.c: New test. + +2023-11-23 Di Zhao <dizhao@os.amperecomputing.com> + + * gcc.dg/pr110279-1.c: New test. + +2023-11-23 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112599 + PR target/112670 + * gcc.target/riscv/rvv/autovec/pr112599-1.c: New test. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112336 + * gcc.dg/bitint-41.c: New test. + +2023-11-23 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/110879 + * g++.dg/opt/pr110879.C: Require C++11 or later. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/builtin-stdc-bit-1.c: New test. + * gcc.dg/builtin-stdc-bit-2.c: New test. + +2023-11-23 Jakub Jelinek <jakub@redhat.com> + + PR c++/110348 + * g++.dg/cpp26/static_assert1.C: New test. + * g++.dg/cpp26/feat-cxx26.C (__cpp_static_assert): Expect + 202306L rather than 201411L. + * g++.dg/cpp0x/udlit-error1.C: Expect different diagnostics for + static_assert with user-defined literal. + +2023-11-23 Pan Li <pan2.li@intel.com> + + PR target/111720 + * gcc.target/riscv/rvv/base/pr111720-0.c: New test. + * gcc.target/riscv/rvv/base/pr111720-1.c: New test. + * gcc.target/riscv/rvv/base/pr111720-10.c: New test. + * gcc.target/riscv/rvv/base/pr111720-2.c: New test. + * gcc.target/riscv/rvv/base/pr111720-3.c: New test. + * gcc.target/riscv/rvv/base/pr111720-4.c: New test. + * gcc.target/riscv/rvv/base/pr111720-5.c: New test. + * gcc.target/riscv/rvv/base/pr111720-6.c: New test. + * gcc.target/riscv/rvv/base/pr111720-7.c: New test. + * gcc.target/riscv/rvv/base/pr111720-8.c: New test. + * gcc.target/riscv/rvv/base/pr111720-9.c: New test. + +2023-11-23 Hans-Peter Nilsson <hp@axis.com> + + PR testsuite/106120 + * g++.dg/warn/Wstringop-overflow-4.C:144 XFAIL bogus warning for + lp64 targets with c++98. + +2023-11-22 Patrick Palka <ppalka@redhat.com> + + PR c++/112633 + * g++.dg/cpp0x/alias-decl-75.C: New test. + +2023-11-22 Iain Sandoe <iain@sandoe.co.uk> + + * lib/plugin-support.exp: Update the expected path to an + in-tree build of libintl. + +2023-11-22 Iain Sandoe <iain@sandoe.co.uk> + Richard Sandiford <richard.sandiford@arm.com> + + * lib/scanasm.exp: Initial handling for Mach-O function body scans. + +2023-11-22 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112344 + * gcc.dg/torture/pr112344.c: New testcase. + +2023-11-22 Florian Weimer <fweimer@redhat.com> + + * gcc.misc-tests/linkage-y.c (puts): Declare. + (main): Add int return type and return 0. + +2023-11-22 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * gcc.target/riscv/rvv/autovec/pr112598-3.c: New test. + +2023-11-22 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/uxtl-combine-4.c: Fix typo. + * gcc.target/aarch64/uxtl-combine-5.c: Likewise. + * gcc.target/aarch64/uxtl-combine-6.c: Likewise. + +2023-11-22 Jakub Jelinek <jakub@redhat.com> + + PR target/112518 + * gcc.target/i386/bmi2-pr112518.c: New test. + +2023-11-22 Xi Ruoyao <xry111@xry111.site> + + * gcc.target/loongarch/vect-shuf-fp.c: New test. + +2023-11-22 Hongyu Wang <hongyu.wang@intel.com> + + * gcc.target/i386/apx-push2pop2-1.c: Adjust output scan. + * gcc.target/i386/apx-push2pop2_force_drap-1.c: Likewise. + +2023-11-22 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * gcc.target/riscv/rvv/autovec/pr112598-2.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + PR target/111815 + * gcc.dg/torture/pr111815.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddifne.c: New test. + * gcc.target/riscv/addsifne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddibfne.c: New test. + * gcc.target/riscv/addsibfne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdifeq-sfb.c: New test. + * gcc.target/riscv/movdifeq-thead.c: New test. + * gcc.target/riscv/movdifeq-ventana.c: New test. + * gcc.target/riscv/movdifeq-zicond.c: New test. + * gcc.target/riscv/movdifeq.c: New test. + * gcc.target/riscv/movsifeq-sfb.c: New test. + * gcc.target/riscv/movsifeq-thead.c: New test. + * gcc.target/riscv/movsifeq-ventana.c: New test. + * gcc.target/riscv/movsifeq-zicond.c: New test. + * gcc.target/riscv/movsifeq.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibfeq-ventana.c: New test. + * gcc.target/riscv/movdibfeq-zicond.c: New test. + * gcc.target/riscv/movdibfeq.c: New test. + * gcc.target/riscv/movsibfeq-ventana.c: New test. + * gcc.target/riscv/movsibfeq-zicond.c: New test. + * gcc.target/riscv/movsibfeq.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddifeq.c: New test. + * gcc.target/riscv/adddifge.c: New test. + * gcc.target/riscv/adddifgt.c: New test. + * gcc.target/riscv/adddifle.c: New test. + * gcc.target/riscv/adddiflt.c: New test. + * gcc.target/riscv/addsifeq.c: New test. + * gcc.target/riscv/addsifge.c: New test. + * gcc.target/riscv/addsifgt.c: New test. + * gcc.target/riscv/addsifle.c: New test. + * gcc.target/riscv/addsiflt.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddibfeq.c: New test. + * gcc.target/riscv/adddibfge.c: New test. + * gcc.target/riscv/adddibfgt.c: New test. + * gcc.target/riscv/adddibfle.c: New test. + * gcc.target/riscv/adddibflt.c: New test. + * gcc.target/riscv/addsibfeq.c: New test. + * gcc.target/riscv/addsibfge.c: New test. + * gcc.target/riscv/addsibfgt.c: New test. + * gcc.target/riscv/addsibfle.c: New test. + * gcc.target/riscv/addsibflt.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdifge.c: New test. + * gcc.target/riscv/movdifgt.c: New test. + * gcc.target/riscv/movdifle.c: New test. + * gcc.target/riscv/movdiflt.c: New test. + * gcc.target/riscv/movdifne.c: New test. + * gcc.target/riscv/movsifge.c: New test. + * gcc.target/riscv/movsifgt.c: New test. + * gcc.target/riscv/movsifle.c: New test. + * gcc.target/riscv/movsiflt.c: New test. + * gcc.target/riscv/movsifne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibfge.c: New test. + * gcc.target/riscv/movdibfgt.c: New test. + * gcc.target/riscv/movdibfle.c: New test. + * gcc.target/riscv/movdibflt.c: New test. + * gcc.target/riscv/movdibfne.c: New test. + * gcc.target/riscv/movsibfge.c: New test. + * gcc.target/riscv/movsibfgt.c: New test. + * gcc.target/riscv/movsibfle.c: New test. + * gcc.target/riscv/movsibflt.c: New test. + * gcc.target/riscv/movsibfne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdifge-sfb.c: Reject "if-conversion + succeeded through" rather than accepting it. + * gcc.target/riscv/movdifge-thead.c: Likewise. + * gcc.target/riscv/movdifge-ventana.c: Likewise. + * gcc.target/riscv/movdifge-zicond.c: Likewise. + * gcc.target/riscv/movdifgt-sfb.c: Likewise. + * gcc.target/riscv/movdifgt-thead.c: Likewise. + * gcc.target/riscv/movdifgt-ventana.c: Likewise. + * gcc.target/riscv/movdifgt-zicond.c: Likewise. + * gcc.target/riscv/movdifle-sfb.c: Likewise. + * gcc.target/riscv/movdifle-thead.c: Likewise. + * gcc.target/riscv/movdifle-ventana.c: Likewise. + * gcc.target/riscv/movdifle-zicond.c: Likewise. + * gcc.target/riscv/movdiflt-sfb.c: Likewise. + * gcc.target/riscv/movdiflt-thead.c: Likewise. + * gcc.target/riscv/movdiflt-ventana.c: Likewise. + * gcc.target/riscv/movdiflt-zicond.c: Likewise. + * gcc.target/riscv/movsifge-sfb.c: Likewise. + * gcc.target/riscv/movsifge-thead.c: Likewise. + * gcc.target/riscv/movsifge-ventana.c: Likewise. + * gcc.target/riscv/movsifge-zicond.c: Likewise. + * gcc.target/riscv/movsifgt-sfb.c: Likewise. + * gcc.target/riscv/movsifgt-thead.c: Likewise. + * gcc.target/riscv/movsifgt-ventana.c: Likewise. + * gcc.target/riscv/movsifgt-zicond.c: Likewise. + * gcc.target/riscv/movsifle-sfb.c: Likewise. + * gcc.target/riscv/movsifle-thead.c: Likewise. + * gcc.target/riscv/movsifle-ventana.c: Likewise. + * gcc.target/riscv/movsifle-zicond.c: Likewise. + * gcc.target/riscv/movsiflt-sfb.c: Likewise. + * gcc.target/riscv/movsiflt-thead.c: Likewise. + * gcc.target/riscv/movsiflt-ventana.c: Likewise. + * gcc.target/riscv/movsiflt-zicond.c: Likewise. + * gcc.target/riscv/smax-ieee.c: Also accept FLT.D. + * gcc.target/riscv/smaxf-ieee.c: Also accept FLT.S. + * gcc.target/riscv/smin-ieee.c: Also accept FGT.D. + * gcc.target/riscv/sminf-ieee.c: Also accept FGT.S. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddieq.c: New test. + * gcc.target/riscv/adddige.c: New test. + * gcc.target/riscv/adddigeu.c: New test. + * gcc.target/riscv/adddigt.c: New test. + * gcc.target/riscv/adddigtu.c: New test. + * gcc.target/riscv/adddile.c: New test. + * gcc.target/riscv/adddileu.c: New test. + * gcc.target/riscv/adddilt.c: New test. + * gcc.target/riscv/adddiltu.c: New test. + * gcc.target/riscv/adddine.c: New test. + * gcc.target/riscv/addsieq.c: New test. + * gcc.target/riscv/addsige.c: New test. + * gcc.target/riscv/addsigeu.c: New test. + * gcc.target/riscv/addsigt.c: New test. + * gcc.target/riscv/addsigtu.c: New test. + * gcc.target/riscv/addsile.c: New test. + * gcc.target/riscv/addsileu.c: New test. + * gcc.target/riscv/addsilt.c: New test. + * gcc.target/riscv/addsiltu.c: New test. + * gcc.target/riscv/addsine.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/adddibeq.c: New test. + * gcc.target/riscv/adddibge.c: New test. + * gcc.target/riscv/adddibgeu.c: New test. + * gcc.target/riscv/adddibgt.c: New test. + * gcc.target/riscv/adddibgtu.c: New test. + * gcc.target/riscv/adddible.c: New test. + * gcc.target/riscv/adddibleu.c: New test. + * gcc.target/riscv/adddiblt.c: New test. + * gcc.target/riscv/adddibltu.c: New test. + * gcc.target/riscv/adddibne.c: New test. + * gcc.target/riscv/addsibeq.c: New test. + * gcc.target/riscv/addsibge.c: New test. + * gcc.target/riscv/addsibgeu.c: New test. + * gcc.target/riscv/addsibgt.c: New test. + * gcc.target/riscv/addsibgtu.c: New test. + * gcc.target/riscv/addsible.c: New test. + * gcc.target/riscv/addsibleu.c: New test. + * gcc.target/riscv/addsiblt.c: New test. + * gcc.target/riscv/addsibltu.c: New test. + * gcc.target/riscv/addsibne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdieq.c: New test. + * gcc.target/riscv/movdige.c: New test. + * gcc.target/riscv/movdigeu.c: New test. + * gcc.target/riscv/movdigt.c: New test. + * gcc.target/riscv/movdigtu.c: New test. + * gcc.target/riscv/movdile.c: New test. + * gcc.target/riscv/movdileu.c: New test. + * gcc.target/riscv/movdilt.c: New test. + * gcc.target/riscv/movdiltu.c: New test. + * gcc.target/riscv/movdine.c: New test. + * gcc.target/riscv/movsieq.c: New test. + * gcc.target/riscv/movsige.c: New test. + * gcc.target/riscv/movsigeu.c: New test. + * gcc.target/riscv/movsigt.c: New test. + * gcc.target/riscv/movsigtu.c: New test. + * gcc.target/riscv/movsile.c: New test. + * gcc.target/riscv/movsileu.c: New test. + * gcc.target/riscv/movsilt.c: New test. + * gcc.target/riscv/movsiltu.c: New test. + * gcc.target/riscv/movsine.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibeq.c: New test. + * gcc.target/riscv/movdibge.c: New test. + * gcc.target/riscv/movdibgeu.c: New test. + * gcc.target/riscv/movdibgt.c: New test. + * gcc.target/riscv/movdibgtu.c: New test. + * gcc.target/riscv/movdible.c: New test. + * gcc.target/riscv/movdibleu.c: New test. + * gcc.target/riscv/movdiblt.c: New test. + * gcc.target/riscv/movdibltu.c: New test. + * gcc.target/riscv/movdibne.c: New test. + * gcc.target/riscv/movsibeq.c: New test. + * gcc.target/riscv/movsibge.c: New test. + * gcc.target/riscv/movsibgeu.c: New test. + * gcc.target/riscv/movsibgt.c: New test. + * gcc.target/riscv/movsibgtu.c: New test. + * gcc.target/riscv/movsible.c: New test. + * gcc.target/riscv/movsibleu.c: New test. + * gcc.target/riscv/movsiblt.c: New test. + * gcc.target/riscv/movsibltu.c: New test. + * gcc.target/riscv/movsibne.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/zbs-bext-02.c: Adjust to reject SLL rather + than AND. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdige-thead.c: New test. + * gcc.target/riscv/movdigeu-thead.c: New test. + * gcc.target/riscv/movdigt-thead.c: New test. + * gcc.target/riscv/movdigtu-thead.c: New test. + * gcc.target/riscv/movdile-thead.c: New test. + * gcc.target/riscv/movdileu-thead.c: New test. + * gcc.target/riscv/movdilt-thead.c: New test. + * gcc.target/riscv/movdiltu-thead.c: New test. + * gcc.target/riscv/movsige-thead.c: New test. + * gcc.target/riscv/movsigeu-thead.c: New test. + * gcc.target/riscv/movsigt-thead.c: New test. + * gcc.target/riscv/movsigtu-thead.c: New test. + * gcc.target/riscv/movsile-thead.c: New test. + * gcc.target/riscv/movsileu-thead.c: New test. + * gcc.target/riscv/movsilt-thead.c: New test. + * gcc.target/riscv/movsiltu-thead.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibge-thead.c: New test. + * gcc.target/riscv/movdibgeu-thead.c: New test. + * gcc.target/riscv/movdibgt-thead.c: New test. + * gcc.target/riscv/movdibgtu-thead.c: New test. + * gcc.target/riscv/movdible-thead.c: New test. + * gcc.target/riscv/movdibleu-thead.c: New test. + * gcc.target/riscv/movdiblt-thead.c: New test. + * gcc.target/riscv/movdibltu-thead.c: New test. + * gcc.target/riscv/movsibge-thead.c: New test. + * gcc.target/riscv/movsibgeu-thead.c: New test. + * gcc.target/riscv/movsibgt-thead.c: New test. + * gcc.target/riscv/movsibgtu-thead.c: New test. + * gcc.target/riscv/movsible-thead.c: New test. + * gcc.target/riscv/movsibleu-thead.c: New test. + * gcc.target/riscv/movsiblt-thead.c: New test. + * gcc.target/riscv/movsibltu-thead.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdieq-ventana.c: New test. + * gcc.target/riscv/movdieq-zicond.c: New test. + * gcc.target/riscv/movdine-ventana.c: New test. + * gcc.target/riscv/movdine-zicond.c: New test. + * gcc.target/riscv/movsieq-ventana.c: New test. + * gcc.target/riscv/movsieq-zicond.c: New test. + * gcc.target/riscv/movsine-ventana.c: New test. + * gcc.target/riscv/movsine-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibeq-ventana.c: New test. + * gcc.target/riscv/movdibeq-zicond.c: New test. + * gcc.target/riscv/movdibne-ventana.c: New test. + * gcc.target/riscv/movdibne-zicond.c: New test. + * gcc.target/riscv/movsibeq-ventana.c: New test. + * gcc.target/riscv/movsibeq-zicond.c: New test. + * gcc.target/riscv/movsibne-ventana.c: New test. + * gcc.target/riscv/movsibne-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c: + Lower `-mbranch-cost=' setting. + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c: + Likewise. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdigtu-ventana.c: New test. + * gcc.target/riscv/movdigtu-zicond.c: New test. + * gcc.target/riscv/movdiltu-ventana.c: New test. + * gcc.target/riscv/movdiltu-zicond.c: New test. + * gcc.target/riscv/movsigtu-ventana.c: New test. + * gcc.target/riscv/movsigtu-zicond.c: New test. + * gcc.target/riscv/movsiltu-ventana.c: New test. + * gcc.target/riscv/movsiltu-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibgtu-ventana.c: New test. + * gcc.target/riscv/movdibgtu-zicond.c: New test. + * gcc.target/riscv/movdibltu-ventana.c: New test. + * gcc.target/riscv/movdibltu-zicond.c: New test. + * gcc.target/riscv/movsibgtu-ventana.c: New test. + * gcc.target/riscv/movsibgtu-zicond.c: New test. + * gcc.target/riscv/movsibltu-ventana.c: New test. + * gcc.target/riscv/movsibltu-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdifge-sfb.c: New test. + * gcc.target/riscv/movdifge-thead.c: New test. + * gcc.target/riscv/movdifge-ventana.c: New test. + * gcc.target/riscv/movdifge-zicond.c: New test. + * gcc.target/riscv/movdifgt-sfb.c: New test. + * gcc.target/riscv/movdifgt-thead.c: New test. + * gcc.target/riscv/movdifgt-ventana.c: New test. + * gcc.target/riscv/movdifgt-zicond.c: New test. + * gcc.target/riscv/movdifle-sfb.c: New test. + * gcc.target/riscv/movdifle-thead.c: New test. + * gcc.target/riscv/movdifle-ventana.c: New test. + * gcc.target/riscv/movdifle-zicond.c: New test. + * gcc.target/riscv/movdiflt-sfb.c: New test. + * gcc.target/riscv/movdiflt-thead.c: New test. + * gcc.target/riscv/movdiflt-ventana.c: New test. + * gcc.target/riscv/movdiflt-zicond.c: New test. + * gcc.target/riscv/movdifne-sfb.c: New test. + * gcc.target/riscv/movdifne-thead.c: New test. + * gcc.target/riscv/movdifne-ventana.c: New test. + * gcc.target/riscv/movdifne-zicond.c: New test. + * gcc.target/riscv/movsifge-sfb.c: New test. + * gcc.target/riscv/movsifge-thead.c: New test. + * gcc.target/riscv/movsifge-ventana.c: New test. + * gcc.target/riscv/movsifge-zicond.c: New test. + * gcc.target/riscv/movsifgt-sfb.c: New test. + * gcc.target/riscv/movsifgt-thead.c: New test. + * gcc.target/riscv/movsifgt-ventana.c: New test. + * gcc.target/riscv/movsifgt-zicond.c: New test. + * gcc.target/riscv/movsifle-sfb.c: New test. + * gcc.target/riscv/movsifle-thead.c: New test. + * gcc.target/riscv/movsifle-ventana.c: New test. + * gcc.target/riscv/movsifle-zicond.c: New test. + * gcc.target/riscv/movsiflt-sfb.c: New test. + * gcc.target/riscv/movsiflt-thead.c: New test. + * gcc.target/riscv/movsiflt-ventana.c: New test. + * gcc.target/riscv/movsiflt-zicond.c: New test. + * gcc.target/riscv/movsifne-sfb.c: New test. + * gcc.target/riscv/movsifne-thead.c: New test. + * gcc.target/riscv/movsifne-ventana.c: New test. + * gcc.target/riscv/movsifne-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibfge-ventana.c: New test. + * gcc.target/riscv/movdibfge-zicond.c: New test. + * gcc.target/riscv/movdibfgt-ventana.c: New test. + * gcc.target/riscv/movdibfgt-zicond.c: New test. + * gcc.target/riscv/movdibfle-ventana.c: New test. + * gcc.target/riscv/movdibfle-zicond.c: New test. + * gcc.target/riscv/movdibflt-ventana.c: New test. + * gcc.target/riscv/movdibflt-zicond.c: New test. + * gcc.target/riscv/movdibfne-ventana.c: New test. + * gcc.target/riscv/movdibfne-zicond.c: New test. + * gcc.target/riscv/movsibfge-ventana.c: New test. + * gcc.target/riscv/movsibfge-zicond.c: New test. + * gcc.target/riscv/movsibfgt-ventana.c: New test. + * gcc.target/riscv/movsibfgt-zicond.c: New test. + * gcc.target/riscv/movsibfle-ventana.c: New test. + * gcc.target/riscv/movsibfle-zicond.c: New test. + * gcc.target/riscv/movsibflt-ventana.c: New test. + * gcc.target/riscv/movsibflt-zicond.c: New test. + * gcc.target/riscv/movsibfne-ventana.c: New test. + * gcc.target/riscv/movsibfne-zicond.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdieq-thead.c: New test. + * gcc.target/riscv/movdige-ventana.c: New test. + * gcc.target/riscv/movdige-zicond.c: New test. + * gcc.target/riscv/movdigeu-ventana.c: New test. + * gcc.target/riscv/movdigeu-zicond.c: New test. + * gcc.target/riscv/movdigt-ventana.c: New test. + * gcc.target/riscv/movdigt-zicond.c: New test. + * gcc.target/riscv/movdile-ventana.c: New test. + * gcc.target/riscv/movdile-zicond.c: New test. + * gcc.target/riscv/movdileu-ventana.c: New test. + * gcc.target/riscv/movdileu-zicond.c: New test. + * gcc.target/riscv/movdilt-ventana.c: New test. + * gcc.target/riscv/movdilt-zicond.c: New test. + * gcc.target/riscv/movdine-thead.c: New test. + * gcc.target/riscv/movsieq-thead.c: New test. + * gcc.target/riscv/movsige-ventana.c: New test. + * gcc.target/riscv/movsige-zicond.c: New test. + * gcc.target/riscv/movsigeu-ventana.c: New test. + * gcc.target/riscv/movsigeu-zicond.c: New test. + * gcc.target/riscv/movsigt-ventana.c: New test. + * gcc.target/riscv/movsigt-zicond.c: New test. + * gcc.target/riscv/movsile-ventana.c: New test. + * gcc.target/riscv/movsile-zicond.c: New test. + * gcc.target/riscv/movsileu-ventana.c: New test. + * gcc.target/riscv/movsileu-zicond.c: New test. + * gcc.target/riscv/movsilt-ventana.c: New test. + * gcc.target/riscv/movsilt-zicond.c: New test. + * gcc.target/riscv/movsine-thead.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdibeq-thead.c: New test. + * gcc.target/riscv/movdibge-ventana.c: New test. + * gcc.target/riscv/movdibge-zicond.c: New test. + * gcc.target/riscv/movdibgeu-ventana.c: New test. + * gcc.target/riscv/movdibgeu-zicond.c: New test. + * gcc.target/riscv/movdibgt-ventana.c: New test. + * gcc.target/riscv/movdibgt-zicond.c: New test. + * gcc.target/riscv/movdible-ventana.c: New test. + * gcc.target/riscv/movdible-zicond.c: New test. + * gcc.target/riscv/movdibleu-ventana.c: New test. + * gcc.target/riscv/movdibleu-zicond.c: New test. + * gcc.target/riscv/movdiblt-ventana.c: New test. + * gcc.target/riscv/movdiblt-zicond.c: New test. + * gcc.target/riscv/movdibne-thead.c: New test. + * gcc.target/riscv/movsibeq-thead.c: New test. + * gcc.target/riscv/movsibge-ventana.c: New test. + * gcc.target/riscv/movsibge-zicond.c: New test. + * gcc.target/riscv/movsibgeu-ventana.c: New test. + * gcc.target/riscv/movsibgeu-zicond.c: New test. + * gcc.target/riscv/movsibgt-ventana.c: New test. + * gcc.target/riscv/movsibgt-zicond.c: New test. + * gcc.target/riscv/movsible-ventana.c: New test. + * gcc.target/riscv/movsible-zicond.c: New test. + * gcc.target/riscv/movsibleu-ventana.c: New test. + * gcc.target/riscv/movsibleu-zicond.c: New test. + * gcc.target/riscv/movsiblt-ventana.c: New test. + * gcc.target/riscv/movsiblt-zicond.c: New test. + * gcc.target/riscv/movsibne-thead.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c: + Explicitly set the branch cost. + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c: + Likewise. + * gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c: + Likewise. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.target/riscv/movdieq-sfb.c: New test. + * gcc.target/riscv/movdige-sfb.c: New test. + * gcc.target/riscv/movdigeu-sfb.c: New test. + * gcc.target/riscv/movdigt-sfb.c: New test. + * gcc.target/riscv/movdigtu-sfb.c: New test. + * gcc.target/riscv/movdile-sfb.c: New test. + * gcc.target/riscv/movdileu-sfb.c: New test. + * gcc.target/riscv/movdilt-sfb.c: New test. + * gcc.target/riscv/movdiltu-sfb.c: New test. + * gcc.target/riscv/movdine-sfb.c: New test. + * gcc.target/riscv/movsieq-sfb.c: New test. + * gcc.target/riscv/movsige-sfb.c: New test. + * gcc.target/riscv/movsigeu-sfb.c: New test. + * gcc.target/riscv/movsigt-sfb.c: New test. + * gcc.target/riscv/movsigtu-sfb.c: New test. + * gcc.target/riscv/movsile-sfb.c: New test. + * gcc.target/riscv/movsileu-sfb.c: New test. + * gcc.target/riscv/movsilt-sfb.c: New test. + * gcc.target/riscv/movsiltu-sfb.c: New test. + * gcc.target/riscv/movsine-sfb.c: New test. + +2023-11-22 Maciej W. Rozycki <macro@embecosm.com> + + * gcc.dg/torture/addieq.c: New test. + * gcc.dg/torture/addifeq.c: New test. + * gcc.dg/torture/addifge.c: New test. + * gcc.dg/torture/addifgt.c: New test. + * gcc.dg/torture/addifle.c: New test. + * gcc.dg/torture/addiflt.c: New test. + * gcc.dg/torture/addifne.c: New test. + * gcc.dg/torture/addige.c: New test. + * gcc.dg/torture/addigeu.c: New test. + * gcc.dg/torture/addigt.c: New test. + * gcc.dg/torture/addigtu.c: New test. + * gcc.dg/torture/addile.c: New test. + * gcc.dg/torture/addileu.c: New test. + * gcc.dg/torture/addilt.c: New test. + * gcc.dg/torture/addiltu.c: New test. + * gcc.dg/torture/addine.c: New test. + * gcc.dg/torture/addleq.c: New test. + * gcc.dg/torture/addlfeq.c: New test. + * gcc.dg/torture/addlfge.c: New test. + * gcc.dg/torture/addlfgt.c: New test. + * gcc.dg/torture/addlfle.c: New test. + * gcc.dg/torture/addlflt.c: New test. + * gcc.dg/torture/addlfne.c: New test. + * gcc.dg/torture/addlge.c: New test. + * gcc.dg/torture/addlgeu.c: New test. + * gcc.dg/torture/addlgt.c: New test. + * gcc.dg/torture/addlgtu.c: New test. + * gcc.dg/torture/addlle.c: New test. + * gcc.dg/torture/addlleu.c: New test. + * gcc.dg/torture/addllt.c: New test. + * gcc.dg/torture/addlltu.c: New test. + * gcc.dg/torture/addlne.c: New test. + * gcc.dg/torture/movieq.c: New test. + * gcc.dg/torture/movifeq.c: New test. + * gcc.dg/torture/movifge.c: New test. + * gcc.dg/torture/movifgt.c: New test. + * gcc.dg/torture/movifle.c: New test. + * gcc.dg/torture/moviflt.c: New test. + * gcc.dg/torture/movifne.c: New test. + * gcc.dg/torture/movige.c: New test. + * gcc.dg/torture/movigeu.c: New test. + * gcc.dg/torture/movigt.c: New test. + * gcc.dg/torture/movigtu.c: New test. + * gcc.dg/torture/movile.c: New test. + * gcc.dg/torture/movileu.c: New test. + * gcc.dg/torture/movilt.c: New test. + * gcc.dg/torture/moviltu.c: New test. + * gcc.dg/torture/movine.c: New test. + * gcc.dg/torture/movleq.c: New test. + * gcc.dg/torture/movlfeq.c: New test. + * gcc.dg/torture/movlfge.c: New test. + * gcc.dg/torture/movlfgt.c: New test. + * gcc.dg/torture/movlfle.c: New test. + * gcc.dg/torture/movlflt.c: New test. + * gcc.dg/torture/movlfne.c: New test. + * gcc.dg/torture/movlge.c: New test. + * gcc.dg/torture/movlgeu.c: New test. + * gcc.dg/torture/movlgt.c: New test. + * gcc.dg/torture/movlgtu.c: New test. + * gcc.dg/torture/movlle.c: New test. + * gcc.dg/torture/movlleu.c: New test. + * gcc.dg/torture/movllt.c: New test. + * gcc.dg/torture/movlltu.c: New test. + * gcc.dg/torture/movlne.c: New test. + +2023-11-21 Thomas Schwinge <thomas@codesourcery.com> + + * gcc.dg/tree-ssa/return-value-range-1.c: Fix. + +2023-11-21 Robin Dapp <rdapp@ventanamicro.com> + + * gcc.target/aarch64/pr112406-2.c: New test. + +2023-11-21 Robin Dapp <rdapp@ventanamicro.com> + + * gcc.target/riscv/rvv/autovec/unop/popcount.c: Adjust check. + * lib/target-supports.exp: Add riscv_zbb. + +2023-11-21 Robin Dapp <rdapp@ventanamicro.com> + + * g++.target/riscv/rvv/base/bug-14.C: Add + dg-require-effective-target rv64. + * g++.target/riscv/rvv/base/bug-9.C: Ditto. + +2023-11-21 Robin Dapp <rdapp@ventanamicro.com> + + * gcc.target/riscv/rvv/rvv.exp: Remove -march and -mabi from + default CFLAGS. + +2023-11-21 Patrick O'Neill <patrick@rivosinc.com> + + * gfortran.dg/vect/pr107254.f90: Remove dg-do run directive. + * gfortran.dg/vect/pr85853.f90: Ditto. + * gfortran.dg/vect/vect-alias-check-1.F90: Ditto. + +2023-11-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112623 + * gcc.target/i386/pr112623.c: New testcase. + +2023-11-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * gdc.dg/asm1.d: Adjust expected diagnostic. + +2023-11-21 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112598 + * gcc.target/riscv/rvv/autovec/pr112598-1.c: New test. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + PR target/111370 + * gcc.target/aarch64/sve/cond_asrd_1.c: Updated. + * gcc.target/aarch64/sve/cond_cnot_4.c: Likewise. + * gcc.target/aarch64/sve/cond_unary_5.c: Likewise. + * gcc.target/aarch64/sve/cond_uxt_5.c: Likewise. + * gcc.target/aarch64/target_attr_13.c: Likewise. + * gcc.target/aarch64/target_attr_15.c: Likewise. + +2023-11-21 Tamar Christina <tamar.christina@arm.com> + + * gcc.target/aarch64/simd/vmovl_high_1.c: Update codegen. + * gcc.target/aarch64/uxtl-combine-1.c: New test. + * gcc.target/aarch64/uxtl-combine-2.c: New test. + * gcc.target/aarch64/uxtl-combine-3.c: New test. + * gcc.target/aarch64/uxtl-combine-4.c: New test. + * gcc.target/aarch64/uxtl-combine-5.c: New test. + * gcc.target/aarch64/uxtl-combine-6.c: New test. + +2023-11-21 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/autovec/pr112438.c: Add missing dump check. + +2023-11-21 Thomas Schwinge <thomas@codesourcery.com> + + * gcc.dg/tree-ssa/return-value-range-1.c: Fix. + +2023-11-21 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/warn25.adb: Add xfail. + +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + PR c/111309 + * c-c++-common/pr111309-2.c (foo): Don't expect errors for C++ with + -fshort-enums if second argument is E0. + +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/112639 + * gcc.dg/torture/pr112639.c: New test. + +2023-11-21 Hongyu Wang <hongyu.wang@intel.com> + + * gcc.target/i386/apx-interrupt-1.c: Adjust option to restrict them + under certain subfeatures. + * gcc.target/i386/apx-push2pop2-1.c: Likewise. + * gcc.target/i386/apx-push2pop2_force_drap-1.c: Likewise. + * gcc.target/i386/apx-push2pop2_interrupt-1.c: Likewise. + * gcc.target/i386/apx-ppx-1.c: New test. + +2023-11-21 Richard Biener <rguenther@suse.de> + + * gcc.target/arm/bfloat16_vector_typecheck_1.c: Adjust. + * gcc.target/arm/bfloat16_vector_typecheck_2.c: Likewise. + * gcc.target/aarch64/bfloat16_vector_typecheck_1.c: Likewise. + * gcc.target/aarch64/bfloat16_vector_typecheck_2.c: Likewise. + +2023-11-21 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/autovec/reduc/reduc_run-9.c: Fix bug. + +2023-11-21 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr112325-mmx-1.c: New test. + +2023-11-20 Jan Hubicka <jh@suse.cz> + + * g++.dg/ipa/devirt-2.C: Add noipa attribute to prevent ipa-vrp. + * g++.dg/ipa/devirt-7.C: Disable ipa-vrp. + * g++.dg/ipa/ipa-icf-2.C: Disable ipa-vrp. + * g++.dg/ipa/ipa-icf-3.C: Disable ipa-vrp. + * g++.dg/ipa/ivinline-1.C: Disable ipa-vrp. + * g++.dg/ipa/ivinline-3.C: Disable ipa-vrp. + * g++.dg/ipa/ivinline-5.C: Disable ipa-vrp. + * g++.dg/ipa/ivinline-8.C: Disable ipa-vrp. + * g++.dg/ipa/nothrow-1.C: Disable ipa-vrp. + * g++.dg/ipa/pure-const-1.C: Disable ipa-vrp. + * g++.dg/ipa/pure-const-2.C: Disable ipa-vrp. + * g++.dg/lto/inline-crossmodule-1_0.C: Disable ipa-vrp. + * gcc.c-torture/compile/pr106433.c: Add noipa attribute to prevent ipa-vrp. + * gcc.c-torture/execute/frame-address.c: Likewise. + * gcc.dg/vla-1.c: Add noipa attribute to prevent ipa-vrp. + * gcc.dg/ipa/fopt-info-inline-1.c: Disable ipa-vrp. + * gcc.dg/ipa/ipa-icf-25.c: Disable ipa-vrp. + * gcc.dg/ipa/ipa-icf-38.c: Disable ipa-vrp. + * gcc.dg/ipa/pure-const-1.c: Disable ipa-vrp. + * gcc.dg/ipa/remref-0.c: Add noipa attribute to prevent ipa-vrp. + * gcc.dg/tree-prof/time-profiler-1.c: Disable ipa-vrp. + * gcc.dg/tree-prof/time-profiler-2.c: Disable ipa-vrp. + * gcc.dg/tree-ssa/pr110269.c: Disable ipa-vrp. + * gcc.dg/tree-ssa/pr20701.c: Disable ipa-vrp. + * gcc.dg/tree-ssa/vrp05.c: Disable ipa-vrp. + * gcc.dg/tree-ssa/return-value-range-1.c: New test. + * gcc.dg/nonnull-7.c: New file. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112618 + * gcc.dg/pr112618.c: New testcase. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/112281 + * gcc.dg/torture/pr112281-1.c: New testcase. + * gcc.dg/torture/pr112281-2.c: Likewise. + +2023-11-20 Richard Biener <rguenther@suse.de> + + PR middle-end/112622 + * gcc.dg/pr112622.c: New testcase. + * gcc.dg/simd-2.c: Adjust. + * gcc.target/i386/vect-bfloat16-typecheck_1.c: Likewise. + * gcc.target/i386/vect-bfloat16-typecheck_2.c: Likewise. + +2023-11-20 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + PR target/112597 + * gcc.target/riscv/rvv/autovec/pr112597-1.c: New test. + +2023-11-20 Robin Dapp <rdapp@ventanamicro.com> + + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-1.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-1.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-10.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-10.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-11.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-11.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-12.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-12.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-2.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-2.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-3.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-3.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-4.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-4.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-5.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-5.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-6.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-6.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-7.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-7.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-8.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-8.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-9.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-9.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-1.c: + Adjust include. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-10.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-11.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-12.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-2.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-3.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-4.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-5.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-6.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-7.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-8.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-9.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-1.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-1.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-10.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-10.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-11.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-11.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-2.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-2.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-3.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-3.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-4.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-4.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-5.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-5.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-6.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-6.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-7.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-7.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-8.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-8.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-9.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-9.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-1.c: + Adjust include. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-10.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-11.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-2.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-3.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-4.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-5.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-6.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-7.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-8.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-9.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-1.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-1.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-10.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-10.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-2.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-2.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-3.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-3.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-4.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-4.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-5.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-5.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-6.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-6.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-7.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-7.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-8.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-8.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-9.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-9.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-1.c: + Adjust include. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-10.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-2.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-3.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-4.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-5.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-6.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-7.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-8.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-9.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-1.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-1.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-10.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-10.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-3.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-2.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-4.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-4.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-5.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-5.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-6.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-6.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-7.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-7.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-8.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-8.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-9.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-9.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-2.c: Moved to... + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-2.c: ...here. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-1.c: + Adjust include. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-10.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-2.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-3.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-4.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-5.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-6.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-7.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-8.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-9.c: Ditto. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-1.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-10.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-11.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-12.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-2.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-3.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-4.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-5.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-6.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-7.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-8.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-9.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-1.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-10.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-11.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-2.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-3.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-4.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-5.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-6.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-7.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-8.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-9.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-1.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-10.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-2.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-3.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-4.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-5.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-6.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-7.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-8.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-9.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-1.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-10.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-3.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-4.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-5.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-6.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-7.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-8.c: New test. + * gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-9.c: New test. + +2023-11-20 Christophe Lyon <christophe.lyon@linaro.org> + + * gcc.target/arm/mve/intrinsics/vst1q_f16.c: Remove 'return'. + * gcc.target/arm/mve/intrinsics/vst1q_f32.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_s16.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_s32.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_s8.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_u16.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_u32.c: Likewise. + * gcc.target/arm/mve/intrinsics/vst1q_u8.c: Likewise. + +2023-11-20 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * lib/target-supports.exp: Remove scalable compile option. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/builtin-classify-type-1.c (main): Add tests for vector + types. + +2023-11-20 Robin Dapp <rdapp@ventanamicro.com> + + * gfortran.dg/pr112406.f90: New test. + +2023-11-20 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/90693 + * gcc.target/i386/pr90693.c: New test. + +2023-11-20 Alexandre Oliva <oliva@adacore.com> + + * lib/target-supports.exp + (check_effective_target_arm_thumb1_cbz_ok): Fix prop name + cut&pasto. + +2023-11-20 Alexandre Oliva <oliva@adacore.com> + + * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c: + Expect "unaligned pointer value" warning on short_enums + targets, but not in c++. + * c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c: + Likewise. + +2023-11-20 Alexandre Oliva <oliva@adacore.com> + + * gcc.dg/tree-ssa/scev-3.c: xfail on all ilp32 targets, + though some of these do pass. + * gcc.dg/tree-ssa/scev-4.c: Likewise. + * gcc.dg/tree-ssa/scev-5.c: Likewise. + +2023-11-20 Haochen Jiang <haochen.jiang@intel.com> + + * gcc.target/i386/avx10_1-1.c: New test. + * gcc.target/i386/avx10_1-10.c: Ditto. + * gcc.target/i386/avx10_1-11.c: Ditto. + * gcc.target/i386/avx10_1-12.c: Ditto. + * gcc.target/i386/avx10_1-13.c: Ditto. + * gcc.target/i386/avx10_1-14.c: Ditto. + * gcc.target/i386/avx10_1-15.c: Ditto. + * gcc.target/i386/avx10_1-16.c: Ditto. + * gcc.target/i386/avx10_1-17.c: Ditto. + * gcc.target/i386/avx10_1-18.c: Ditto. + * gcc.target/i386/avx10_1-19.c: Ditto. + * gcc.target/i386/avx10_1-2.c: Ditto. + * gcc.target/i386/avx10_1-20.c: Ditto. + * gcc.target/i386/avx10_1-21.c: Ditto. + * gcc.target/i386/avx10_1-22.c: Ditto. + * gcc.target/i386/avx10_1-23.c: Ditto. + * gcc.target/i386/avx10_1-3.c: Ditto. + * gcc.target/i386/avx10_1-4.c: Ditto. + * gcc.target/i386/avx10_1-5.c: Ditto. + * gcc.target/i386/avx10_1-6.c: Ditto. + * gcc.target/i386/avx10_1-7.c: Ditto. + * gcc.target/i386/avx10_1-8.c: Ditto. + * gcc.target/i386/avx10_1-9.c: Ditto. + +2023-11-20 liuhongt <hongtao.liu@intel.com> + + * lib/target-supports.exp (vect_logical_reduc): Add i?86-*-* + and x86_64-*-*. + +2023-11-20 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/pr112325-1.c: New test. + * gcc.target/i386/pr112325-2.c: New test. + +2023-11-20 xuli <xuli1@eswincomputing.com> + + PR target/112537 + * gcc.target/riscv/rvv/base/cpymem-strategy-1.c: New test. + * gcc.target/riscv/rvv/base/cpymem-strategy-2.c: New test. + * gcc.target/riscv/rvv/base/cpymem-strategy-3.c: New test. + * gcc.target/riscv/rvv/base/cpymem-strategy-4.c: New test. + * gcc.target/riscv/rvv/base/cpymem-strategy-5.c: New test. + * gcc.target/riscv/rvv/base/cpymem-strategy.h: New test. + +2023-11-19 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/autovec/post-ra-avl.c: New test. + +2023-11-19 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/99187 + * g++.dg/modules/pr99187.C: New test. + +2023-11-19 David Edelsohn <dje.gcc@gmail.com> + + * lib/target-supports.exp (add_options_for___float128): Only add + -mfloat128 to powerpc*-*-linux*. + +2023-11-19 Juzhe-Zhong <juzhe.zhong@rivai.ai> + + * gcc.target/riscv/rvv/autovec/pr112561.c: New test. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/107573 + * c-c++-common/analyzer/strtok-1.c: New test. + * c-c++-common/analyzer/strtok-2.c: New test. + * c-c++-common/analyzer/strtok-3.c: New test. + * c-c++-common/analyzer/strtok-4.c: New test. + * c-c++-common/analyzer/strtok-cppreference.c: New test. + 2023-11-18 Xi Ruoyao <xry111@xry111.site> * gcc.target/loongarch/div-div32.c: New test. diff --git a/gcc/testsuite/c-c++-common/Wattributes.c b/gcc/testsuite/c-c++-common/Wattributes.c index 978f3f9..49a085d 100644 --- a/gcc/testsuite/c-c++-common/Wattributes.c +++ b/gcc/testsuite/c-c++-common/Wattributes.c @@ -408,7 +408,7 @@ finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .warn_unused /* { dg-note "previous declaration here" "" { target *-*-* } .-1 } */ inline int ATTR ((aligned (4))) - finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .aligned \\(4\\). because it conflicts with attribute .aligned \\(8\\)." "" { target { ! { hppa*64*-*-* } } } } */ + finline_hot_noret_align (int); /* { dg-warning "ignoring attribute .aligned \\(4\\). because it conflicts with attribute .aligned \\(8\\)." "" } */ inline int ATTR ((aligned (8))) finline_hot_noret_align (int); /* { dg-note "previous declaration here" } */ diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c index c46ffe9..aaa2031 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early-O2.c @@ -61,7 +61,7 @@ static inline enum obj_type obj_type(const enum obj_type *t) } static inline struct connection *__objt_conn(enum obj_type *t) { - return ((struct connection *)(((char *)(t)) - ((long)&((struct connection *)0)->obj_type))); + return ((struct connection *)(((char *)(t)) - ((long)&((struct connection *)0)->obj_type))); /* { dg-warning "unaligned pointer value" "warning" { target { short_enums && { ! c++ } } } } */ } static inline struct connection *objt_conn(enum obj_type *t) { diff --git a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c index ef34a76..6c96f5a 100644 --- a/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c +++ b/gcc/testsuite/c-c++-common/analyzer/null-deref-pr108251-smp_fetch_ssl_fc_has_early.c @@ -60,7 +60,7 @@ static inline enum obj_type obj_type(const enum obj_type *t) } static inline struct connection *__objt_conn(enum obj_type *t) { - return ((struct connection *)(((char *)(t)) - ((long)&((struct connection *)0)->obj_type))); + return ((struct connection *)(((char *)(t)) - ((long)&((struct connection *)0)->obj_type))); /* { dg-warning "unaligned pointer value" "warning" { target { short_enums && { ! c++ } } } } */ } static inline struct connection *objt_conn(enum obj_type *t) { diff --git a/gcc/testsuite/c-c++-common/builtin-classify-type-1.c b/gcc/testsuite/c-c++-common/builtin-classify-type-1.c index a41dbe1..f90f2d9 100644 --- a/gcc/testsuite/c-c++-common/builtin-classify-type-1.c +++ b/gcc/testsuite/c-c++-common/builtin-classify-type-1.c @@ -22,6 +22,10 @@ main () const char *p = (const char *) 0; float f = 0.0; _Complex double c = 0.0; + typedef int VI __attribute__((vector_size (4 * sizeof (int)))); + typedef float VF __attribute__((vector_size (4 * sizeof (int)))); + VI vi = { 0, 0, 0, 0 }; + VF vf = { 0.0f, 0.0f, 0.0f, 0.0f }; #ifdef __cplusplus struct T { void foo (); }; int &r = a[0]; @@ -43,6 +47,8 @@ main () static_assert (__builtin_classify_type (struct S) == 12, ""); static_assert (__builtin_classify_type (union U) == 13, ""); static_assert (__builtin_classify_type (int [2]) == 14, ""); + static_assert (__builtin_classify_type (VI) == 19, ""); + static_assert (__builtin_classify_type (VF) == 19, ""); static_assert (__builtin_classify_type (__typeof__ (a[0])) == 1, ""); static_assert (__builtin_classify_type (__typeof__ (e)) == 3, ""); static_assert (__builtin_classify_type (__typeof__ (b)) == 4, ""); @@ -57,6 +63,8 @@ main () static_assert (__builtin_classify_type (__typeof__ (s)) == 12, ""); static_assert (__builtin_classify_type (__typeof__ (u)) == 13, ""); static_assert (__builtin_classify_type (__typeof__ (a)) == 14, ""); + static_assert (__builtin_classify_type (__typeof__ (vi)) == 19, ""); + static_assert (__builtin_classify_type (__typeof__ (vf)) == 19, ""); #ifndef __cplusplus static_assert (__builtin_classify_type (a[0]) == 1, ""); static_assert (__builtin_classify_type (e) == 1, ""); @@ -102,4 +110,8 @@ main () abort (); if (__builtin_classify_type (a) != 5) abort (); + if (__builtin_classify_type (vi) != 19) + abort (); + if (__builtin_classify_type (vf) != 19) + abort (); } diff --git a/gcc/testsuite/c-c++-common/fhardened-1.S b/gcc/testsuite/c-c++-common/fhardened-1.S new file mode 100644 index 0000000..9d0a577 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-1.S @@ -0,0 +1,6 @@ +/* { dg-do preprocess { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O" } */ + +#if __PIE__ != 2 +# error "-fPIE not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-1.c b/gcc/testsuite/c-c++-common/fhardened-1.c new file mode 100644 index 0000000..7e67406 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O" } */ + +#ifndef __SSP_STRONG__ +# error "-fstack-protector-strong not enabled" +#endif + +#if _FORTIFY_SOURCE < 2 +# error "_FORTIFY_SOURCE not enabled" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-10.c b/gcc/testsuite/c-c++-common/fhardened-10.c new file mode 100644 index 0000000..badebc5 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-10.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -D_FORTIFY_SOURCE=1" } */ + +#if _FORTIFY_SOURCE != 1 +# error "_FORTIFY_SOURCE != 1" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS disabled when it should not be" +#endif + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-11.c b/gcc/testsuite/c-c++-common/fhardened-11.c new file mode 100644 index 0000000..d1a973d --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-11.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -D_FORTIFY_SOURCE_ -D_GLIBCXX_ASSERTIONS_" } */ + +#ifndef _FORTIFY_SOURCE +# error "_FORTIFY_SOURCE disabled when it should not be" +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# error "_GLIBCXX_ASSERTIONS disabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-12.c b/gcc/testsuite/c-c++-common/fhardened-12.c new file mode 100644 index 0000000..eb128f6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-12.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump ".DEFERRED_INIT" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-13.c b/gcc/testsuite/c-c++-common/fhardened-13.c new file mode 100644 index 0000000..8722e6d --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-13.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O" } */ + +#if __PIE__ != 2 +# error "-fPIE not enabled" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-14.c b/gcc/testsuite/c-c++-common/fhardened-14.c new file mode 100644 index 0000000..04d6c8f --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-14.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fno-PIE" } */ + +#ifdef __PIE__ +# error "PIE enabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-15.c b/gcc/testsuite/c-c++-common/fhardened-15.c new file mode 100644 index 0000000..86dc522 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-15.c @@ -0,0 +1,5 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-require-stack-check "specific" } */ +/* { dg-options "-fhardened -O -fstack-check" } */ + +/* { dg-warning ".-fstack-clash-protection. is not enabled by .-fhardened. because .-fstack-check. was specified" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-2.c b/gcc/testsuite/c-c++-common/fhardened-2.c new file mode 100644 index 0000000..280ff96 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -fstack-protector" } */ + +#ifdef __SSP_STRONG__ +# error "-fstack-protector-strong enabled when it should not be" +#endif +#ifndef __SSP__ +# error "-fstack-protector not enabled" +#endif + +/* { dg-warning ".-fstack-protector-strong. is not enabled" "" { target *-*-* } 0 } */ +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-3.c b/gcc/testsuite/c-c++-common/fhardened-3.c new file mode 100644 index 0000000..f2306ca --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O0" } */ +/* Test that we don't get any diagnostic coming from libc headers. */ + +#include <stdio.h> + +/* The most useful C program known to man. */ + +int +main () +{ +} + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-4.c b/gcc/testsuite/c-c++-common/fhardened-4.c new file mode 100644 index 0000000..312fabb --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-4.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O0 -Wno-hardened" } */ + +/* { dg-bogus "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-5.c b/gcc/testsuite/c-c++-common/fhardened-5.c new file mode 100644 index 0000000..eb128f6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump ".DEFERRED_INIT" "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-6.c b/gcc/testsuite/c-c++-common/fhardened-6.c new file mode 100644 index 0000000..d3cb7c8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -O -ftrivial-auto-var-init=uninitialized -fdump-tree-gimple" } */ + +int +foo () +{ + int i; + return i; +} + +/* { dg-final { scan-tree-dump-not ".DEFERRED_INIT" "gimple" } } */ +/* { dg-warning ".-ftrivial-auto-var-init=zero. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/fhardened-7.c b/gcc/testsuite/c-c++-common/fhardened-7.c new file mode 100644 index 0000000..b47bf43 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-7.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fpie" } */ + +/* -fpie takes precedence over -fhardened */ +#if __PIE__ != 1 +# error "__PIE__ != 1" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-8.c b/gcc/testsuite/c-c++-common/fhardened-8.c new file mode 100644 index 0000000..85c9ad9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-8.c @@ -0,0 +1,7 @@ +/* { dg-do compile { target { { *-*-linux* *-*-gnu* } && pie } } } */ +/* { dg-options "-fhardened -O -fPIC" } */ + +/* -fPIC takes precedence over -fhardened */ +#ifdef __PIE__ +# error "PIE enabled when it should not be" +#endif diff --git a/gcc/testsuite/c-c++-common/fhardened-9.c b/gcc/testsuite/c-c++-common/fhardened-9.c new file mode 100644 index 0000000..4e4131f --- /dev/null +++ b/gcc/testsuite/c-c++-common/fhardened-9.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-fhardened -U_FORTIFY_SOURCE -U_GLIBCXX_ASSERTIONS" } */ + +#if defined(_FORTIFY_SOURCE) || defined(_GLIBCXX_ASSERTIONS) +# error "hardening enabled when it should not be" +#endif + +/* { dg-warning "._FORTIFY_SOURCE. is not enabled" "" { target *-*-* } 0 } */ +/* { dg-warning "._GLIBCXX_ASSERTIONS. is not enabled" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/c-c++-common/gomp/depobj-3.c b/gcc/testsuite/c-c++-common/gomp/depobj-3.c new file mode 100644 index 0000000..a5017a4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/depobj-3.c @@ -0,0 +1,47 @@ +typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t { + char __omp_depend_t__[2 * sizeof (void *)]; +} omp_depend_t; + +void +f () +{ + omp_depend_t obj2; + struct { omp_depend_t c; } s; + float a; + #pragma omp depobj(s.c) depend(inout: a) + + #pragma omp depobj(s.c) destroy(s.c) /* OK */ + + #pragma omp depobj(s.c) destroy(obj2) +/* { dg-warning "the 'destroy' expression 'obj2' should be the same as the 'depobj' argument 's.c'" "" { target c } .-1 } */ +/* { dg-warning "the 'destroy' expression 'obj2' should be the same as the 'depobj' argument 's.f\\(\\)::<unnamed struct>::c'" "" { target c++ } .-2 } */ +} + +void +g () +{ + volatile omp_depend_t obj3; + #pragma omp depobj(obj3) destroy(obj3) +} + +int +main () +{ + float a; + omp_depend_t obj; + + #pragma omp depobj(obj) depend(inout: a) + + #pragma omp depobj(obj) destroy(obj) /* OK */ + + #pragma omp depobj(obj) destroy(a + 5) +/* { dg-error "'destroy' expression is not lvalue expression" "" { target c } .-1 } */ +/* { dg-warning "the 'destroy' expression '\\(a \\+ \\(float\\)5\\)' should be the same as the 'depobj' argument 'obj'" "" { target c++ } .-2 } */ + + #pragma omp depobj(obj+5) destroy(a) +/* { dg-error "invalid operands to binary \\+ \\(have 'omp_depend_t' and 'int'\\)" "" { target c } .-1 } */ +/* { dg-error "no match for 'operator\\+' in 'obj \\+ 5' \\(operand types are 'omp_depend_t' and 'int'\\)" "" { target c++ } .-2 } */ + + #pragma omp depobj(obj) destroy(a) /* { dg-warning "the 'destroy' expression 'a' should be the same as the 'depobj' argument 'obj'" } */ + return 0; +} diff --git a/gcc/testsuite/c-c++-common/has-feature-common.c b/gcc/testsuite/c-c++-common/has-feature-common.c new file mode 100644 index 0000000..1604d77 --- /dev/null +++ b/gcc/testsuite/c-c++-common/has-feature-common.c @@ -0,0 +1,73 @@ +/* { dg-do compile } */ +/* Test __has_{feature,extension} for generic features. */ + +#define FEAT(x) (__has_feature (x) && __has_extension (x)) +#define EXT(x) (__has_extension (x) && !__has_feature (x)) + +#if __has_feature (unknown_feature) || __has_extension (unknown_feature) +#error unknown feature is known! +#endif + +#if !EXT (gnu_asm_goto_with_outputs) +#error +#endif + +#if !EXT (__gnu_asm_goto_with_outputs__) +#error +#endif + +#if !EXT (gnu_asm_goto_with_outputs_full) +#error +#endif + +#if !EXT (__gnu_asm_goto_with_outputs_full__) +#error +#endif + +#if !FEAT (enumerator_attributes) +#error +#endif + +#if !FEAT (__enumerator_attributes__) +#error +#endif + +#if !FEAT (attribute_deprecated_with_message) +#error +#endif + +#if !FEAT (__attribute_deprecated_with_message__) +#error +#endif + +#if !FEAT (attribute_unavailable_with_message) +#error +#endif + +#if !FEAT (__attribute_unavailable_with_message__) +#error +#endif + +#if !FEAT (tls) +#error +#endif + +#if !FEAT(__tls__) +#error +#endif + +#if defined (__SANITIZE_ADDRESS__) != __has_feature (address_sanitizer) +#error +#endif + +#if defined (__SANITIZE_ADDRESS__) != __has_extension (address_sanitizer) +#error +#endif + +#if defined (__SANITIZE_THREAD__) != __has_feature (thread_sanitizer) +#error +#endif + +#if defined (__SANITIZE_THREAD__) != __has_extension (thread_sanitizer) +#error +#endif diff --git a/gcc/testsuite/c-c++-common/has-feature-pedantic.c b/gcc/testsuite/c-c++-common/has-feature-pedantic.c new file mode 100644 index 0000000..4ac16a4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/has-feature-pedantic.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-pedantic-errors" } */ + +/* When -pedantic-errors is passed, __has_extension should behave like + __has_feature. */ + +#if __has_feature (gnu_asm_goto_with_outputs) +#error extension recognized as feature +#endif + +#if __has_extension (gnu_asm_goto_with_outputs) +#error pure extensions should not be recognized with -pedantic-errors +#endif + +#if !__has_feature (tls) || !__has_extension (tls) +#error features should still be recognized with -pedantic-errors +#endif + +/* Make this TU non-empty to appease -pedantic-errors. */ +int foo; diff --git a/gcc/testsuite/c-c++-common/pr111309-2.c b/gcc/testsuite/c-c++-common/pr111309-2.c index 535208b..13e9673 100644 --- a/gcc/testsuite/c-c++-common/pr111309-2.c +++ b/gcc/testsuite/c-c++-common/pr111309-2.c @@ -32,7 +32,7 @@ foo (void) __builtin_clzg (0U, 2LL); /* { dg-error "does not have 'int' type" } */ __builtin_clzg (0U, 2U); /* { dg-error "does not have 'int' type" } */ __builtin_clzg (0U, true); - __builtin_clzg (0U, E0); /* { dg-error "does not have 'int' type" "" { target c++ } } */ + __builtin_clzg (0U, E0); /* { dg-error "does not have 'int' type" "" { target { c++ && { ! short_enums } } } } */ __builtin_ctzg (); /* { dg-error "too few arguments" } */ __builtin_ctzg (0U, 1, 2); /* { dg-error "too many arguments" } */ __builtin_ctzg (0); /* { dg-error "has signed type" } */ @@ -51,7 +51,7 @@ foo (void) __builtin_ctzg (0U, 2LL); /* { dg-error "does not have 'int' type" } */ __builtin_ctzg (0U, 2U); /* { dg-error "does not have 'int' type" } */ __builtin_ctzg (0U, true); - __builtin_ctzg (0U, E0); /* { dg-error "does not have 'int' type" "" { target c++ } } */ + __builtin_ctzg (0U, E0); /* { dg-error "does not have 'int' type" "" { target { c++ && { ! short_enums } } } } */ __builtin_clrsbg (); /* { dg-error "too few arguments" } */ __builtin_clrsbg (0, 1); /* { dg-error "too many arguments" } */ __builtin_clrsbg (0U); /* { dg-error "has unsigned type" } */ diff --git a/gcc/testsuite/g++.dg/contracts/contracts-tmpl-spec2.C b/gcc/testsuite/g++.dg/contracts/contracts-tmpl-spec2.C index 8211767..fd3a25b 100644 --- a/gcc/testsuite/g++.dg/contracts/contracts-tmpl-spec2.C +++ b/gcc/testsuite/g++.dg/contracts/contracts-tmpl-spec2.C @@ -1,6 +1,6 @@ // basic test to ensure contracts work for class and member specializations // { dg-do run } -// { dg-options "-std=c++2a -fcontracts -fcontract-continuation-mode=on" } +// { dg-options "-std=c++2a -fcontracts -fcontract-continuation-mode=on -fsigned-char" } #include <cstdio> // template specializations can have differing contracts diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C new file mode 100644 index 0000000..1a73a99 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-75.C @@ -0,0 +1,13 @@ +// PR c++/112633 +// { dg-do compile { target c++11 } } + +struct A { using type = void; }; + +template<class> +using ty1 = A; + +template<class T> +using ty2 = typename ty1<T>::type; + +template<class T> +ty2<T> f(); diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C index 0da0759..260448aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-const1.C @@ -6,4 +6,4 @@ const auto x = { 1, 2 }; -// { dg-final { scan-assembler-not {\.data} { xfail powerpc-ibm-aix* } } } +// { dg-final { scan-assembler-not {\.data} { xfail hppa*-*-hpux* powerpc-ibm-aix* } } } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C index 40566e0..6d6cd45 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-error1.C @@ -11,7 +11,9 @@ void operator""_x(const char *, decltype(sizeof(0))); #pragma message "hi"_x // { dg-warning "string literal with user-defined suffix is invalid in this context" } extern "C"_x { void g(); } // { dg-error "before user-defined string literal" } -static_assert(true, "foo"_x); // { dg-error "string literal with user-defined suffix is invalid in this context|expected" } +static_assert(true, "foo"_x); // { dg-error "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "invalid use of 'void'" "" { target *-*-* } .-2 } [[deprecated("oof"_x)]] // { dg-error "string literal with user-defined suffix is invalid in this context" "" { target c++26 } } void diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C index 0977d96..80e8ef6 100644 --- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C +++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C @@ -304,8 +304,8 @@ #ifndef __cpp_static_assert # error "__cpp_static_assert" -#elif __cpp_static_assert != 201411 -# error "__cpp_static_assert != 201411" +#elif __cpp_static_assert != 202306 +# error "__cpp_static_assert != 202306" #endif #ifndef __cpp_namespace_attributes diff --git a/gcc/testsuite/g++.dg/cpp26/static_assert1.C b/gcc/testsuite/g++.dg/cpp26/static_assert1.C new file mode 100644 index 0000000..9dec52b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/static_assert1.C @@ -0,0 +1,309 @@ +// C++26 P2741R3 - user-generated static_assert messages +// { dg-do compile { target c++11 } } +// { dg-options "" } + +static_assert (true, ""); +static_assert (true, ("")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "request for member 'size' in '\\\(\\\"\\\"\\\)', which is of non-class type 'const char \\\[1\\\]'" "" { target *-*-* } .-2 } +static_assert (true, "" + 0); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "request for member 'size' in '\\\(const char\\\*\\\)\\\"\\\"', which is of non-class type 'const char\\\*'" "" { target *-*-* } .-2 } +static_assert (true, 0); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "request for member 'size' in '0', which is of non-class type 'int'" "" { target *-*-* } .-2 } +struct A {}; +static_assert (true, A {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "'struct A' has no member named 'size'" "" { target *-*-* } .-2 } +struct B { int size; }; +static_assert (true, B {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "'struct B' has no member named 'data'" "" { target *-*-* } .-2 } +struct C { constexpr int size () const { return 0; } }; +static_assert (true, C {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "'struct C' has no member named 'data'" "" { target *-*-* } .-2 } +struct D { constexpr int size () const { return 0; } int data; }; +static_assert (true, D {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'D\\\(\\\).D::data' cannot be used as a function" "" { target *-*-* } .-1 } +struct E { int size = 0; + constexpr const char *data () const { return ""; } }; +static_assert (true, E {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'E\\\(\\\).E::size' cannot be used as a function" "" { target c++11_only } .-1 } + // { dg-error "'E\\\{0\\\}.E::size' cannot be used as a function" "" { target c++14 } .-2 } +struct F { constexpr const char *size () const { return ""; } + constexpr const char *data () const { return ""; } }; +static_assert (true, F {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message 'size\\\(\\\)' must be implicitly convertible to 'std::size_t'" "" { target *-*-* } .-1 } + // { dg-error "could not convert 'F\\\(\\\).F::size\\\(\\\)' from 'const char\\\*' to '\[^']*'" "" { target *-*-* } .-2 } + // { dg-error "conversion from 'const char\\\*' to '\[^']*' in a converted constant expression" "" { target *-*-* } .-3 } +struct G { constexpr long size () const { return 0; } + constexpr float data () const { return 0.0f; } }; +static_assert (true, G {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } + // { dg-error "could not convert 'G\\\(\\\).G::data\\\(\\\)' from 'float' to 'const char\\\*'" "" { target *-*-* } .-2 } +struct H { short size () const { return 0; } + constexpr const char *data () const { return ""; } }; +static_assert (true, H {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +struct I { constexpr signed char size () const { return 0; } + const char *data () const { return ""; } }; +static_assert (true, I {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +struct J { constexpr int size () const { return j ? throw 1 : 0; } // { dg-error "expression '<throw-expression>' is not a constant expression" } + constexpr const char *data () const { return ""; }; + constexpr J (int x) : j (x) {} + int j; }; +static_assert (true, J (1)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +static_assert (false, J (0)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed" "" { target *-*-* } .-1 } +static_assert (false, J (1)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message 'size\\\(\\\)' must be a constant expression" "" { target *-*-* } .-1 } +struct K { constexpr operator int () { return 4; } }; +struct L { constexpr operator const char * () { return "test"; } }; +struct M { constexpr K size () const { return {}; } + constexpr L data () const { return {}; } }; +static_assert (true, M {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +static_assert (false, M {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +#if __cpp_constexpr_dynamic_alloc >= 201907L +struct N { constexpr int size () const { return 3; } + constexpr const char *data () const { return new char[3] { 'b', 'a', 'd' }; } }; // { dg-error "'\\\* N\\\(\\\).N::data\\\(\\\)' is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } } +static_assert (true, N {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } +static_assert (false, N {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } + // { dg-error "'static_assert' message 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } .-1 } +#endif +constexpr const char a[] = { 't', 'e', 's', 't' }; +struct O { constexpr int size () const { return 4; } + constexpr const char *data () const { return a; } }; +static_assert (false, O {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +struct P { constexpr int size () const { return 4 - p; } + constexpr const char *data () const { return &a[p]; } + constexpr P (int x) : p (x) {} + int p; }; +static_assert (false, P (0)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +static_assert (false, P (2)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: st" "" { target *-*-* } .-1 } +struct Q { constexpr int size () const { return 4 - q; } + constexpr const char *data () const { return &"test"[q]; } + constexpr Q (int x) : q (x) {} + int q; }; +static_assert (false, Q (0)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +static_assert (false, Q (1)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: est" "" { target *-*-* } .-1 } +struct R { constexpr int size () const { return 4 - r; } + constexpr const char *d () const { return "test"; } + constexpr const char *data () const { return d () + r; } + constexpr R (int x) : r (x) {} + int r; }; +static_assert (false, R (0)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +static_assert (false, R (2)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: st" "" { target *-*-* } .-1 } +struct S { constexpr float size (float) const { return 42.0f; } + constexpr int size (void * = nullptr) const { return 4; } + constexpr double data (double) const { return 42.0; } + constexpr const char *data (int = 0) const { return "test"; } }; +static_assert (true, S {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +static_assert (false, S {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + +using size_t = decltype (sizeof (0)); +struct string_view { + size_t s; + const char *d; + constexpr string_view () : s (0), d (nullptr) {} + constexpr string_view (const char *p) : s (__builtin_strlen (p)), d (p) {} + constexpr string_view (size_t l, const char *p) : s (l), d (p) {} + constexpr size_t size () const noexcept { return s; } + constexpr const char *data () const noexcept { return d; } +}; +static_assert (true, string_view{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +static_assert (false, string_view ("test")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +static_assert (false, string_view ("א")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: א" "" { target *-*-* } .-1 } +static_assert (false, string_view (0, nullptr)); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed" "" { target *-*-* } .-1 } +static_assert (false, string_view (4, "testwithextrachars")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } +static_assert (false, string_view (42, "test")); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "array subscript value '41' is outside the bounds of array type 'const char \\\[5\\\]'" "" { target *-*-* } .-1 } + // { dg-error "'static_assert' message 'data\\\(\\\)\\\[41\\\]' must be a constant expression" "" { target *-*-* } .-2 } + +template <typename T, size_t N> +struct array { + constexpr size_t size () const { return N; } + constexpr const T *data () const { return a; } + const T a[N]; +}; +static_assert (true, array<char, 2> { 'O', 'K' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +static_assert (true, array<wchar_t, 2> { L'O', L'K' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "'static_assert' message 'data\\\(\\\)' must be implicitly convertible to 'const char\\\*'" "" { target *-*-* } .-1 } + // { dg-error "could not convert 'array<wchar_t, 2>{const wchar_t \\\[2\\\]{\[0-9]+, \[0-9]+}}.array<wchar_t, 2>::data\\\(\\\)' from 'const wchar_t\\\*' to 'const char\\\*'" "" { target *-*-* } .-2 } +static_assert (false, array<char, 4> { 't', 'e', 's', 't' }); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + +void +foo () +{ + constexpr auto a = array<char, 4> { 't', 'e', 's', 't' }; + static_assert (false, a); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } +} // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + +#if __cpp_constexpr_dynamic_alloc >= 201907L +struct T { + const char *d = init (); + constexpr int size () const { return 4; } + constexpr const char *data () const { return d; } + constexpr const char *init () const { return new char[4] { 't', 'e', 's', 't' }; } + constexpr ~T () { delete[] d; } +}; +static_assert (false, T{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } + // { dg-error "static assertion failed: test" "" { target c++20 } .-1 } +#endif +struct U { constexpr operator const char * () const { return u; } + char u[5] = "test"; }; +#if __cplusplus >= 201402L +struct V { constexpr auto size () const { return K{}; } + constexpr auto data () const { return U{}; } }; +static_assert (false, V{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } + // { dg-error "static assertion failed: test" "" { target c++14 } .-1 } +#endif +struct W { constexpr int size (int) const { return 4; } + constexpr const char *data () const { return "test"; } }; +static_assert (true, W{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "no matching function for call to 'W::size\\\(\\\)'" "" { target *-*-* } .-1 } +struct X { constexpr int size () const { return 4; } + constexpr const char *data (int) const { return "test"; } }; +static_assert (true, X{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "no matching function for call to 'X::data\\\(\\\)'" "" { target *-*-* } .-1 } +struct Y { constexpr int size () { return 4; } + constexpr const char *data (int) { return "test"; } }; +static_assert (true, Y{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "no matching function for call to 'Y::data\\\(\\\)'" "" { target *-*-* } .-1 } +#if __cpp_concepts >= 201907L +struct Z { constexpr int size (auto...) const { return 4; } + constexpr const char *data (auto...) const { return "test"; } }; +static_assert (false, Z{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } + // { dg-error "static assertion failed: test" "" { target c++20 } .-1 } +#endif + +namespace NN +{ + template <typename T> + struct A { + constexpr int size () const = delete; + constexpr const char *data () const { return "test"; } }; + static_assert (true, A<int>{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "use of deleted function 'constexpr int NN::A<T>::size\\\(\\\) const \\\[with T = int\\\]'" "" { target *-*-* } .-1 } +#if __cpp_concepts >= 201907L + template <typename T> + struct B { + constexpr int size () const { return 4; } + constexpr const char *data () const requires false { return "test"; } }; + static_assert (true, B<short>{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++20 && c++23_down } } } + // { dg-error "no matching function for call to 'NN::B<short int>::data\\\(\\\)'" "" { target c++20 } .-1 } +#endif + class C { + constexpr int size () const = delete; + constexpr const char *data () const { return "test"; } }; + static_assert (true, C{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "use of deleted function 'constexpr int NN::C::size\\\(\\\) const'" "" { target *-*-* } .-1 } + // { dg-error "'constexpr const char\\\* NN::C::data\\\(\\\) const' is private within this context" "" { target *-*-* } .-2 } +#if __cplusplus >= 201402L + struct D { + constexpr int size () { return 4; } + constexpr int size () const { return 3; } + constexpr const char *data () { return "test"; } + constexpr const char *data () const { return "ehlo"; } }; + static_assert (true, D{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } + static_assert (false, D{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } + // { dg-error "static assertion failed: test" "" { target c++14 } .-1 } +#endif + struct E { + constexpr int size () const { return 4; } + constexpr const char *data () const { return "test"; } }; + template <typename T> + struct F { + static_assert (false, T{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + }; // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + template <typename T> + struct G { + static_assert (false, T{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + }; // { dg-error "'static_assert' message must be a string literal or object with 'size' and 'data' members" "" { target *-*-* } .-1 } + // { dg-error "request for member 'size' in '0', which is of non-class type 'long int'" "" { target *-*-* } .-2 } + F<E> fe; + G<long> gl; + constexpr E operator ""_myd (const char *, size_t) { return E{}; } + static_assert (false, "foo"_myd); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + constexpr E operator + (const char *, const E &) { return E{}; } + static_assert (false, "foo" + E{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: test" "" { target *-*-* } .-1 } + struct H { + static constexpr int size () { return 7; } + static constexpr const char *data () { return "message"; } }; + static_assert (true, H{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + static_assert (false, H{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: message" "" { target *-*-* } .-1 } + struct I { + static constexpr int size () { return 0; } + static constexpr const char *data () { return nullptr; } }; + static_assert (true, I{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + static_assert (false, I{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed" "" { target *-*-* } .-1 } +#if __cplusplus >= 201402L + struct J { + static constexpr int size () { return 0; } + static constexpr const char *data (int x = 0) { if (x) return nullptr; else throw 1; } }; // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++14 } } + static_assert (true, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } + static_assert (false, J{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target { c++14 && c++23_down } } } + // { dg-error "'static_assert' message 'data\\\(\\\)' must be a core constant expression" "" { target c++14 } .-1 } +#endif +#if __cpp_if_consteval >= 202106L + struct K { + static constexpr int size () { if consteval { return 4; } else { throw 1; } } + static constexpr const char *data () { return "test"; } + }; + static_assert (true, K{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + static_assert (false, K{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + // { dg-error "static assertion failed: test" "" { target c++23 } .-1 } + struct L { + static constexpr int size () { return 4; } + static constexpr const char *data () { if consteval { return "test"; } else { throw 1; } } + }; + static_assert (true, L{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + static_assert (false, L{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + // { dg-error "static assertion failed: test" "" { target c++23 } .-1 } + struct M { + static constexpr int size () { if consteval { throw 1; } else { return 4; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + static constexpr const char *data () { return "test"; } + }; + static_assert (true, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + static_assert (false, M{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + // { dg-error "'static_assert' message 'size\\\(\\\)' must be a constant expression" "" { target c++23 } .-1 } + struct N { + static constexpr int size () { return 4; } + static constexpr const char *data () { if consteval { throw 1; } else { return "test"; } } // { dg-error "expression '<throw-expression>' is not a constant expression" "" { target c++23 } } + }; + static_assert (true, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + static_assert (false, N{}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_only } } + // { dg-error "'static_assert' message 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++23 } .-1 } +#endif + struct O { constexpr int operator () () const { return 12; } }; + struct P { constexpr const char *operator () () const { return "another test"; } }; + struct Q { O size; P data; }; + static_assert (true, Q ()); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + static_assert (false, Q {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: another test" "" { target *-*-* } .-1 } + constexpr int get_size () { return 16; } + constexpr const char *get_data () { return "yet another test"; } + struct R { int (*size) () = NN::get_size; + const char *(*data) () = NN::get_data; }; + static_assert (true, R ()); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + static_assert (false, R {}); // { dg-warning "'static_assert' with non-string message only available with" "" { target c++23_down } } + // { dg-error "static assertion failed: yet another test" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/g++.dg/eh/pr112619.C b/gcc/testsuite/g++.dg/eh/pr112619.C new file mode 100644 index 0000000..f04e1c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/pr112619.C @@ -0,0 +1,15 @@ +// PR c++/112619 +// { dg-do compile } + +struct S { S (); ~S (); }; + +S +foo (int a, int b) +{ + if (a || b) + { + S s; + return s; + } + return S (); +} diff --git a/gcc/testsuite/g++.dg/ext/has-feature.C b/gcc/testsuite/g++.dg/ext/has-feature.C new file mode 100644 index 0000000..52191b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/has-feature.C @@ -0,0 +1,206 @@ +// { dg-do compile } +// { dg-options "" } + +#define FEAT(x) (__has_feature(x) && __has_extension(x)) +#define CXX11 (__cplusplus >= 201103L) +#define CXX14 (__cplusplus >= 201402L) + +#if !FEAT(cxx_exceptions) || !FEAT(cxx_rtti) +#error +#endif + +#if __has_feature (cxx_access_control_sfinae) != CXX11 +#error +#endif + +#if !__has_extension (cxx_access_control_sfinae) +#error +#endif + +#if FEAT(cxx_alias_templates) != CXX11 +#error +#endif + +#if FEAT(cxx_alignas) != CXX11 +#error +#endif + +#if FEAT(cxx_alignof) != CXX11 +#error +#endif + +#if FEAT(cxx_attributes) != CXX11 +#error +#endif + +#if FEAT(cxx_constexpr) != CXX11 +#error +#endif + +#if FEAT(cxx_decltype) != CXX11 +#error +#endif + +#if FEAT(cxx_decltype_incomplete_return_types) != CXX11 +#error +#endif + +#if FEAT(cxx_default_function_template_args) != CXX11 +#error +#endif + +#if FEAT(cxx_defaulted_functions) != CXX11 +#error +#endif + +#if __has_feature (cxx_delegating_constructors) != CXX11 +#error +#endif + +#if FEAT (cxx_deleted_functions) != CXX11 +#error +#endif + +#if __has_feature (cxx_explicit_conversions) != CXX11 +#error +#endif + +#if FEAT (cxx_generalized_initializers) != CXX11 +#error +#endif + +#if FEAT (cxx_implicit_moves) != CXX11 +#error +#endif + +#if FEAT (cxx_inheriting_constructors) != CXX11 +#error +#endif + +#if !__has_extension (cxx_inline_namespaces) +#error +#endif + +#if __has_feature (cxx_inline_namespaces) != CXX11 +#error +#endif + +#if FEAT (cxx_lambdas) != CXX11 +#error +#endif + +#if FEAT (cxx_local_type_template_args) != CXX11 +#error +#endif + +#if FEAT (cxx_noexcept) != CXX11 +#error +#endif + +#if __has_feature (cxx_nonstatic_member_init) != CXX11 +#error +#endif + +#if FEAT (cxx_nullptr) != CXX11 +#error +#endif + +#if __has_feature (cxx_override_control) != CXX11 +#error +#endif + +#if FEAT (cxx_reference_qualified_functions) != CXX11 +#error +#endif + +#if FEAT (cxx_range_for) != CXX11 +#error +#endif + +#if FEAT (cxx_raw_string_literals) != CXX11 +#error +#endif + +#if FEAT (cxx_rvalue_references) != CXX11 +#error +#endif + +#if FEAT (cxx_static_assert) != CXX11 +#error +#endif + +#if FEAT (cxx_thread_local) != CXX11 +#error +#endif + +#if FEAT (cxx_auto_type) != CXX11 +#error +#endif + +#if FEAT (cxx_strong_enums) != CXX11 +#error +#endif + +#if FEAT (cxx_trailing_return) != CXX11 +#error +#endif + +#if FEAT (cxx_unicode_literals) != CXX11 +#error +#endif + +#if FEAT (cxx_unrestricted_unions) != CXX11 +#error +#endif + +#if FEAT (cxx_user_literals) != CXX11 +#error +#endif + +#if !__has_extension (cxx_variadic_templates) +#error +#endif + +#if __has_feature (cxx_variadic_templates) != CXX11 +#error +#endif + +#if !__has_extension (cxx_binary_literals) +#error +#endif + +#if __has_feature (cxx_binary_literals) != CXX14 +#error +#endif + +#if FEAT (cxx_decltype_auto) != CXX14 +#error +#endif + +#if FEAT (cxx_aggregate_nsdmi) != CXX14 +#error +#endif + +#if __has_extension (cxx_init_captures) != CXX11 +#error +#endif + +#if __has_feature (cxx_init_captures) != CXX14 +#error +#endif + +#if FEAT (cxx_generic_lambdas) != CXX14 +#error +#endif + +#if FEAT (cxx_relaxed_constexpr) != CXX14 +#error +#endif + +#if FEAT (cxx_return_type_deduction) != CXX14 +#error +#endif + +#if __has_feature (cxx_variable_templates) != CXX14 +#error +#endif diff --git a/gcc/testsuite/g++.dg/ipa/devirt-2.C b/gcc/testsuite/g++.dg/ipa/devirt-2.C index 48a94e0..1797db6 100644 --- a/gcc/testsuite/g++.dg/ipa/devirt-2.C +++ b/gcc/testsuite/g++.dg/ipa/devirt-2.C @@ -43,7 +43,7 @@ int C::foo (int i) return i + 3; } -int __attribute__ ((noinline,noclone)) get_input(void) +int __attribute__ ((noinline,noclone,noipa)) get_input(void) { return 1; } diff --git a/gcc/testsuite/g++.dg/ipa/devirt-7.C b/gcc/testsuite/g++.dg/ipa/devirt-7.C index f27a264..b24b2bc 100644 --- a/gcc/testsuite/g++.dg/ipa/devirt-7.C +++ b/gcc/testsuite/g++.dg/ipa/devirt-7.C @@ -1,7 +1,7 @@ /* Verify that IPA-CP can do devirtualization even if the virtual call comes from a method that has been early-inlined into a descendant. */ /* { dg-do run } */ -/* { dg-options "-O3 -fdump-ipa-cp" } */ +/* { dg-options "-O3 -fdump-ipa-cp -fno-ipa-vrp" } */ /* { dg-add-options bind_pic_locally } */ extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C b/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C index 7f56189..ae121e8 100644 --- a/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C +++ b/gcc/testsuite/g++.dg/ipa/ipa-icf-2.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-ipa-icf-optimized" } */ +/* { dg-options "-O2 -fdump-ipa-icf-optimized -fno-ipa-vrp" } */ class A { diff --git a/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C b/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C index 5a3cca2..03c10f1 100644 --- a/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C +++ b/gcc/testsuite/g++.dg/ipa/ipa-icf-3.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-ipa-icf-optimized" } */ +/* { dg-options "-O2 -fdump-ipa-icf-optimized -fno-ipa-vrp" } */ __attribute__ ((noinline)) int zero() diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-1.C b/gcc/testsuite/g++.dg/ipa/ivinline-1.C index 2d988bc..ccb1870 100644 --- a/gcc/testsuite/g++.dg/ipa/ivinline-1.C +++ b/gcc/testsuite/g++.dg/ipa/ivinline-1.C @@ -1,7 +1,7 @@ /* Verify that simple virtual calls are inlined even without early inlining. */ /* { dg-do run { target { nonpic || pie_enabled } } } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp -fno-ipa-vrp" } */ extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-3.C b/gcc/testsuite/g++.dg/ipa/ivinline-3.C index f756a16..02e7e44 100644 --- a/gcc/testsuite/g++.dg/ipa/ivinline-3.C +++ b/gcc/testsuite/g++.dg/ipa/ivinline-3.C @@ -1,7 +1,7 @@ /* Verify that simple virtual calls on an object refrence are inlined even without early inlining. */ /* { dg-do run { target { nonpic || pie_enabled } } } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp -fno-ipa-vrp" } */ extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-5.C b/gcc/testsuite/g++.dg/ipa/ivinline-5.C index 6c19907..cb889d1 100644 --- a/gcc/testsuite/g++.dg/ipa/ivinline-5.C +++ b/gcc/testsuite/g++.dg/ipa/ivinline-5.C @@ -1,7 +1,7 @@ /* Verify that virtual call inlining does not pick a wrong method when there is a user defined ancestor in an object. */ /* { dg-do run { target { nonpic || pie_enabled } } } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp -fno-ipa-vrp" } */ extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-8.C b/gcc/testsuite/g++.dg/ipa/ivinline-8.C index bc81abf..f29e818 100644 --- a/gcc/testsuite/g++.dg/ipa/ivinline-8.C +++ b/gcc/testsuite/g++.dg/ipa/ivinline-8.C @@ -1,7 +1,7 @@ /* Verify that virtual calls are inlined (ithout early inlining) even when their caller is itself indirectly inlined. */ /* { dg-do run { target { nonpic || pie_enabled } } } */ -/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp" } */ +/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp -fno-ipa-vrp" } */ extern "C" void abort (void); diff --git a/gcc/testsuite/g++.dg/ipa/nothrow-1.C b/gcc/testsuite/g++.dg/ipa/nothrow-1.C index b30b021..1f24310 100644 --- a/gcc/testsuite/g++.dg/ipa/nothrow-1.C +++ b/gcc/testsuite/g++.dg/ipa/nothrow-1.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fnon-call-exceptions -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fnon-call-exceptions -fdump-tree-optimized -fno-ipa-vrp" } */ int *ptr; static int barvar; diff --git a/gcc/testsuite/g++.dg/ipa/pure-const-1.C b/gcc/testsuite/g++.dg/ipa/pure-const-1.C index 61940c6..c18278c 100644 --- a/gcc/testsuite/g++.dg/ipa/pure-const-1.C +++ b/gcc/testsuite/g++.dg/ipa/pure-const-1.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-vrp" } */ int *ptr; static int barvar; diff --git a/gcc/testsuite/g++.dg/ipa/pure-const-2.C b/gcc/testsuite/g++.dg/ipa/pure-const-2.C index 6e739de..d5f18bf 100644 --- a/gcc/testsuite/g++.dg/ipa/pure-const-2.C +++ b/gcc/testsuite/g++.dg/ipa/pure-const-2.C @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-optimized -fno-ipa-vrp" } */ int *ptr; static int barvar; /* We can not detect A to be const because it may be interposed by unoptimized diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C index 0294dcc..c56360e 100644 --- a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C +++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C @@ -1,5 +1,5 @@ // { dg-lto-do link } -/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr -flto -fdump-ipa-inline-details" } } */ +/* { dg-lto-options { "-O2 -fno-early-inlining -fno-implicit-constexpr -flto -fdump-ipa-inline-details -fno-ipa-vrp" } } */ #include "inline-crossmodule-1.h" int a::key () { diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-1.C b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C index 53e3e1d..b0b0b86 100644 --- a/gcc/testsuite/g++.dg/modules/bad-mapper-1.C +++ b/gcc/testsuite/g++.dg/modules/bad-mapper-1.C @@ -1,9 +1,9 @@ // { dg-additional-options "-fmodules-ts -fmodule-mapper=|this-will-not-work" } import unique1.bob; -// { dg-error "-:failed (exec|CreateProcess|posix_spawn).*mapper.* .*this-will-not-work" "" { target { ! { *-*-darwin[89]* *-*-darwin10* } } } 0 } +// { dg-error "-:failed (exec|CreateProcess|posix_spawn).*mapper.* .*this-will-not-work" "" { target { ! { *-*-darwin[89]* *-*-darwin10* hppa*-*-hpux* } } } 0 } // { dg-prune-output "fatal error:" } // { dg-prune-output "failed to read" } // { dg-prune-output "compilation terminated" } -// { dg-error "-:failed mapper handshake communication" "" { target { *-*-darwin[89]* *-*-darwin10* } } 0 } +// { dg-error "-:failed mapper handshake communication" "" { target { *-*-darwin[89]* *-*-darwin10* hppa*-*-hpux* } } 0 } // { dg-prune-output "trying to exec .this-will-not-work." } // { dg-prune-output "unknown Compiled Module Interface" } diff --git a/gcc/testsuite/g++.dg/modules/export-1.C b/gcc/testsuite/g++.dg/modules/export-1.C index 8ca696e..5988143 100644 --- a/gcc/testsuite/g++.dg/modules/export-1.C +++ b/gcc/testsuite/g++.dg/modules/export-1.C @@ -4,19 +4,25 @@ export module frob; // { dg-module-cmi !frob } int x (); -export int x (); // { dg-error "conflicting exporting declaration" } +export int x (); // { dg-error "conflicting exporting for declaration" } int y; -export extern int y; // { dg-error "conflicting exporting declaration" } +export extern int y; // { dg-error "conflicting exporting for declaration" } +// A typedef is not an entity so the following is OK; see [module.interface] example 4 typedef int z; -export typedef int z; // { dg-error "conflicting exporting declaration" } +export typedef int z; // { dg-bogus "conflicting exporting for declaration" } + +template <typename T> using w = T; +export template <typename T> using w = T; // { dg-error "conflicting exporting for declaration" } template <typename T> int f (T); -export template <typename T> int f (T); // { dg-error "conflicting exporting declaration" } +export template <typename T> int f (T); // { dg-error "conflicting exporting for declaration" } -// doesn't go via duplicate_decls so we miss this for now class A; -export class A; // { dg-error "conflicting exporting declaration" "" { xfail *-*-* } } +export class A; // { dg-error "conflicting exporting for declaration" } + +template <typename T> struct B; +export template <typename T> struct B {}; // { dg-error "conflicting exporting for declaration" } -// { dg-warning "due to errors" "" { target *-*-* } 0 } +// { dg-warning "due to errors" "" { target *-*-* } 0 } diff --git a/gcc/testsuite/g++.dg/modules/export-2_a.C b/gcc/testsuite/g++.dg/modules/export-2_a.C new file mode 100644 index 0000000..9a201bf --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/export-2_a.C @@ -0,0 +1,14 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi aliases } + +export module aliases; + +typedef int x; +export typedef int x; + +using y = double; +export using y = double; + +struct S {}; +using T = S; +export using T = S; diff --git a/gcc/testsuite/g++.dg/modules/export-2_b.C b/gcc/testsuite/g++.dg/modules/export-2_b.C new file mode 100644 index 0000000..456aa8d --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/export-2_b.C @@ -0,0 +1,7 @@ +// { dg-additional-options "-fmodules-ts" } + +import aliases; + +x a = 123; +y b = 12.45; +T c = T{}; diff --git a/gcc/testsuite/g++.dg/modules/lambda-6_a.C b/gcc/testsuite/g++.dg/modules/lambda-6_a.C new file mode 100644 index 0000000..28bfb35 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-6_a.C @@ -0,0 +1,16 @@ +// PR c++/107398 +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi Lambda6 } + +export module Lambda6; + +template <typename T> +struct R { static int x; }; + +template <typename T> +int R<T>::x = []{int i; return 1;}(); + +export int foo(); +int foo() { + return R<int>::x; +} diff --git a/gcc/testsuite/g++.dg/modules/lambda-6_b.C b/gcc/testsuite/g++.dg/modules/lambda-6_b.C new file mode 100644 index 0000000..ab0c4ab --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-6_b.C @@ -0,0 +1,9 @@ +// PR c++/107398 +// { dg-additional-options "-fmodules-ts" } + +import Lambda6; + +int main() { + if (foo() != 1) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/modules/pr99187.C b/gcc/testsuite/g++.dg/modules/pr99187.C new file mode 100644 index 0000000..7f707e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99187.C @@ -0,0 +1,10 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi pr99187 } + +export module pr99187; + +export struct A { ~A() {} }; + +export inline void f() { + static thread_local A a; +} diff --git a/gcc/testsuite/g++.dg/modules/pr99232_a.C b/gcc/testsuite/g++.dg/modules/pr99232_a.C new file mode 100644 index 0000000..097fb5e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99232_a.C @@ -0,0 +1,12 @@ +// PR c++/99232 +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi pr99232 } + +export module pr99232; + +export const double lambda{ 1.3 }; +export constexpr int a = 42; + +export const double* get_lambda_addr() { + return λ +} diff --git a/gcc/testsuite/g++.dg/modules/pr99232_b.C b/gcc/testsuite/g++.dg/modules/pr99232_b.C new file mode 100644 index 0000000..a36a76f --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99232_b.C @@ -0,0 +1,13 @@ +// PR c++/99232 +// { dg-module-do run } +// { dg-additional-options "-fmodules-ts" } + +import pr99232; + +double foo() { return lambda * 2.0; } +static_assert(a == 42); + +int main() { + if (&lambda != get_lambda_addr()) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/modules/using-10.C b/gcc/testsuite/g++.dg/modules/using-10.C new file mode 100644 index 0000000..5735353 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-10.C @@ -0,0 +1,71 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi !bad } + +export module bad; + +// internal linkage +namespace s { + namespace { + struct a1 {}; // { dg-message "declared here with internal linkage" } + + template <typename T> + struct b1; // { dg-message "declared here with internal linkage" } + + int x1; // { dg-message "declared here with internal linkage" } + + template <typename T> + T y1; // { dg-message "declared here with internal linkage" } + + void f1(); // { dg-message "declared here with internal linkage" } + + template <typename T> + void g1(); // { dg-message "declared here with internal linkage" } + } +} + +// module linkage +namespace m { + struct a2 {}; // { dg-message "declared here with module linkage" } + + template <typename T> + struct b2; // { dg-message "declared here with module linkage" } + + int x2; // { dg-message "declared here with module linkage" } + + template <typename T> + T y2; // { dg-message "declared here with module linkage" } + + void f2(); // { dg-message "declared here with module linkage" } + + template <typename T> + void g2(); // { dg-message "declared here with module linkage" } +} + +export using s::a1; // { dg-error "does not have external linkage" } +export using s::b1; // { dg-error "does not have external linkage" } +export using s::x1; // { dg-error "does not have external linkage" } +export using s::y1; // { dg-error "does not have external linkage" } +export using s::f1; // { dg-error "does not have external linkage" } +export using s::g1; // { dg-error "does not have external linkage" } + +export using m::a2; // { dg-error "does not have external linkage" } +export using m::b2; // { dg-error "does not have external linkage" } +export using m::x2; // { dg-error "does not have external linkage" } +export using m::y2; // { dg-error "does not have external linkage" } +export using m::f2; // { dg-error "does not have external linkage" } +export using m::g2; // { dg-error "does not have external linkage" } + +namespace t { + using a = int; // { dg-message "declared here with no linkage" } + + template <typename T> + using b = int; // { dg-message "declared here with no linkage" } + + typedef int c; // { dg-message "declared here with no linkage" } +} + +export using t::a; // { dg-error "does not have external linkage" } +export using t::b; // { dg-error "does not have external linkage" } +export using t::c; // { dg-error "does not have external linkage" } + +// { dg-prune-output "not writing module" } diff --git a/gcc/testsuite/g++.dg/modules/using-enum-2.C b/gcc/testsuite/g++.dg/modules/using-enum-2.C new file mode 100644 index 0000000..813e2f6 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/using-enum-2.C @@ -0,0 +1,23 @@ +// { dg-additional-options "-fmodules-ts -std=c++2a" } +// { dg-module-cmi !bad } + +export module bad; + +namespace s { + namespace { + enum e1 { x1 }; // { dg-message "declared here with internal linkage" } + enum class e2 { x2 }; // { dg-message "declared here with internal linkage" } + } +} + +namespace m { + enum e3 { x3 }; // { dg-message "declared here with module linkage" } + enum class e4 { x4 }; // { dg-message "declared here with module linkage" } +} + +export using enum s::e1; // { dg-error "does not have external linkage" } +export using enum s::e2; // { dg-error "does not have external linkage" } +export using enum m::e3; // { dg-error "does not have external linkage" } +export using enum m::e4; // { dg-error "does not have external linkage" } + +// { dg-prune-output "not writing module" } diff --git a/gcc/testsuite/g++.dg/opt/pr110879.C b/gcc/testsuite/g++.dg/opt/pr110879.C index 7f0a0a8..5755660 100644 --- a/gcc/testsuite/g++.dg/opt/pr110879.C +++ b/gcc/testsuite/g++.dg/opt/pr110879.C @@ -1,4 +1,4 @@ -// { dg-do compile } +// { dg-do compile { target c++11 } } // { dg-options "-O3 -fdump-tree-optimized" } #include <vector> diff --git a/gcc/testsuite/g++.dg/pch/pr112319.C b/gcc/testsuite/g++.dg/pch/pr112319.C new file mode 100644 index 0000000..9e0457e --- /dev/null +++ b/gcc/testsuite/g++.dg/pch/pr112319.C @@ -0,0 +1,5 @@ +/* { dg-additional-options "-Wpragmas -save-temps" } */ +#include "pr112319.H" +#pragma GCC diagnostic error "-Wpragmas" +#pragma GCC diagnostic ignored "oops" /* { dg-error "oops" } */ +/* { dg-regexp {[^[:space:]]*: some warnings being treated as errors} } */ diff --git a/gcc/testsuite/g++.dg/pch/pr112319.Hs b/gcc/testsuite/g++.dg/pch/pr112319.Hs new file mode 100644 index 0000000..3b6178b --- /dev/null +++ b/gcc/testsuite/g++.dg/pch/pr112319.Hs @@ -0,0 +1 @@ +/* This space intentionally left blank. */ diff --git a/gcc/testsuite/g++.dg/pr104869.C b/gcc/testsuite/g++.dg/pr104869.C index 9a6ef88..851d653 100644 --- a/gcc/testsuite/g++.dg/pr104869.C +++ b/gcc/testsuite/g++.dg/pr104869.C @@ -68,6 +68,9 @@ struct ControlFlow { foo(2); return false; } +#ifdef __hpux__ +extern int main(void) __attribute__ ((visibility ("default"))); +#endif int main() { ControlFlow cf = { nullptr, ControlFlow::UnwindType::EE }; diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr109849.C b/gcc/testsuite/g++.dg/tree-ssa/pr109849.C new file mode 100644 index 0000000..cd348c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr109849.C @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sra" } */ + +#include <vector> +typedef unsigned int uint32_t; +std::pair<uint32_t, uint32_t> pair; +void +test() +{ + std::vector<std::pair<uint32_t, uint32_t> > stack; + stack.push_back (pair); + while (!stack.empty()) { + std::pair<uint32_t, uint32_t> cur = stack.back(); + stack.pop_back(); + if (!cur.first) + { + cur.second++; + stack.push_back (cur); + } + if (cur.second > 10000) + break; + } +} +int +main() +{ + for (int i = 0; i < 10000; i++) + test(); +} + +/* { dg-final { scan-tree-dump "Created a replacement for stack offset" "sra"} } */ diff --git a/gcc/testsuite/g++.dg/tree-ssa/sra-eh-1.C b/gcc/testsuite/g++.dg/tree-ssa/sra-eh-1.C new file mode 100644 index 0000000..9c216a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/sra-eh-1.C @@ -0,0 +1,187 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-sra" } */ + +struct E +{ + short c; + E (short param) : c(param) {}; +}; + +volatile short vs = 0; +long buf[16]; +long * volatile pbuf = (long *) &buf; + +static void __attribute__((noinline)) +unrelated_throwing (void) +{ + throw E (256); +} + +struct S { + long *b; + int c; + int s; +}; + +static void __attribute__((noinline)) +crazy_alloc_s (struct S *p) +{ + int s = p->c ? p->c * 2 : 16; + + long *b = pbuf; + if (!b || s > 16) + { + p->s = -p->s; + throw E (127); + } + + __builtin_memcpy (b, p->b, p->c); + p->b = b; + p->s = s; + pbuf = 0; + return; +} + +long __attribute__((noipa)) +process (long v) +{ + return v + 1; +} + +void __attribute__((noipa)) +check (int s, short c) +{ + if (vs < c) + vs = c; + if (c == 127) + { + if (s >= 0) + __builtin_abort (); + } + else + { + if (s != 0) + __builtin_abort (); + } + return; +} + + +void +foo (void) +{ + struct S foo_stack; + + foo_stack.c = 0; + crazy_alloc_s (&foo_stack); + foo_stack.b[0] = 1; + foo_stack.c = 1; + + while (foo_stack.c) + { + long l = foo_stack.b[--foo_stack.c]; + + if (l > 0) + { + for (int i = 0; i < 4; i++) + { + try + { + if (foo_stack.s <= foo_stack.c + 1) + crazy_alloc_s (&foo_stack); + } + catch (E e) + { + check (foo_stack.s, e.c); + return; + } + l = process (l); + foo_stack.b[foo_stack.c++] = l; + } + } + } + return; +} + + +volatile int vi; + +int __attribute__((noipa)) +save (int s) +{ + vi = s; + return 0; +} + +int __attribute__((noipa)) +restore () +{ + return vi; +} + + +void +bar (void) +{ + struct S bar_stack; + + bar_stack.c = 0; + crazy_alloc_s (&bar_stack); + bar_stack.b[0] = 1; + bar_stack.c = 1; + + while (bar_stack.c) + { + long l = bar_stack.b[--bar_stack.c]; + + if (l > 0) + { + for (int i = 0; i < 4; i++) + { + try + { + if (i == 2) + { + bar_stack.s = save (bar_stack.s); + unrelated_throwing (); + } + if (bar_stack.s <= bar_stack.c + 1) + crazy_alloc_s (&bar_stack); + } + catch (E e) + { + check (bar_stack.s, e.c); + if (e.c == 127) + return; + bar_stack.s = restore (); + continue; + } + l = process (l); + bar_stack.b[bar_stack.c++] = l; + } + } + } + return; +} + + + + +int main (int argc, char **argv) +{ + vs = 0; + pbuf = (long *) &buf; + foo (); + if (vs != 127) + __builtin_abort (); + + vs = 0; + pbuf = (long *) &buf; + bar (); + if (vs != 256) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "Created a replacement for foo_stack offset" "sra"} } */ +/* { dg-final { scan-tree-dump "Created a replacement for bar_stack offset" "sra"} } */ diff --git a/gcc/testsuite/g++.dg/vect/pr36648.cc b/gcc/testsuite/g++.dg/vect/pr36648.cc index 8d24d3d..7bda828 100644 --- a/gcc/testsuite/g++.dg/vect/pr36648.cc +++ b/gcc/testsuite/g++.dg/vect/pr36648.cc @@ -25,6 +25,6 @@ int main() { } targets, ! vect_no_align is a sufficient test. */ /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { { { ! vect_no_align } && { ! powerpc*-*-* } } || { powerpc*-*-* && vect_hw_misalign } } } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { { { ! vect_no_align } && { ! powerpc*-*-* } } || { powerpc*-*-* && vect_hw_misalign } } xfail { vect_variable_length && vect_load_lanes } } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { { { ! vect_no_align } && { ! powerpc*-*-* } } || { powerpc*-*-* && vect_hw_misalign } } } } } */ diff --git a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-4.C b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-4.C index 275ecac..2024f8d 100644 --- a/gcc/testsuite/g++.dg/warn/Wstringop-overflow-4.C +++ b/gcc/testsuite/g++.dg/warn/Wstringop-overflow-4.C @@ -141,7 +141,7 @@ void test_strcpy_new_int16_t (size_t n, const size_t vals[]) int r_imin_imax = SR (INT_MIN, INT_MAX); T (S (1), new int16_t[r_imin_imax]); - T (S (2), new int16_t[r_imin_imax + 1]); // { dg-bogus "into a region of size" "pr106120" { xfail { c++98_only } } } + T (S (2), new int16_t[r_imin_imax + 1]); // { dg-bogus "into a region of size" "pr106120" { xfail { lp64 && c++98_only } } } T (S (9), new int16_t[r_imin_imax * 2 + 1]); int r_0_imax = SR (0, INT_MAX); diff --git a/gcc/testsuite/g++.target/i386/pr89316.C b/gcc/testsuite/g++.target/i386/pr89316.C new file mode 100644 index 0000000..2f05ef7 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr89316.C @@ -0,0 +1,6 @@ +// PR target/89316 +// { dg-do compile } +// { dg-require-effective-target split_stack } +// { dg-options "-fsplit-stack -mforce-indirect-call" } + +struct foo { foo (); } foobar; diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/bug-14.C b/gcc/testsuite/g++.target/riscv/rvv/base/bug-14.C index bf0c7bd..f2d67c85 100644 --- a/gcc/testsuite/g++.target/riscv/rvv/base/bug-14.C +++ b/gcc/testsuite/g++.target/riscv/rvv/base/bug-14.C @@ -1,5 +1,7 @@ -/* { dg-do run { target { { {riscv_v} && {rv64} } } } } */ +/* { dg-do run } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-require-effective-target riscv_v } */ #include<cstdalign> #include<cmath> diff --git a/gcc/testsuite/g++.target/riscv/rvv/base/bug-9.C b/gcc/testsuite/g++.target/riscv/rvv/base/bug-9.C index 8d17883..c43dfae 100644 --- a/gcc/testsuite/g++.target/riscv/rvv/base/bug-9.C +++ b/gcc/testsuite/g++.target/riscv/rvv/base/bug-9.C @@ -1,5 +1,7 @@ -/* { dg-do run { target { { {riscv_v} && {rv64} } } } } */ +/* { dg-do run } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-require-effective-target riscv_v } */ #include<cstdalign> #include<cmath> diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106433.c b/gcc/testsuite/gcc.c-torture/compile/pr106433.c index b840e5e..e02ad5f 100644 --- a/gcc/testsuite/gcc.c-torture/compile/pr106433.c +++ b/gcc/testsuite/gcc.c-torture/compile/pr106433.c @@ -2,7 +2,7 @@ int m, *p; -__attribute__ ((simd)) int +__attribute__ ((simd,noipa)) int bar (int x) { if (x) diff --git a/gcc/testsuite/gcc.c-torture/execute/frame-address.c b/gcc/testsuite/gcc.c-torture/execute/frame-address.c index 5afa691..5950581 100644 --- a/gcc/testsuite/gcc.c-torture/execute/frame-address.c +++ b/gcc/testsuite/gcc.c-torture/execute/frame-address.c @@ -1,10 +1,10 @@ /* { dg-require-effective-target return_address } */ void abort (void); -int check_fa_work (const char *, const char *) __attribute__((noinline)); -int check_fa_mid (const char *) __attribute__((noinline)); -int check_fa (char *) __attribute__((noinline)); -int how_much (void) __attribute__((noinline)); +int check_fa_work (const char *, const char *) __attribute__((noinline,noipa)); +int check_fa_mid (const char *) __attribute__((noinline,noipa)); +int check_fa (char *) __attribute__((noinline,noipa)); +int how_much (void) __attribute__((noinline,noipa)); int check_fa_work (const char *c, const char *f) { diff --git a/gcc/testsuite/gcc.c-torture/execute/pr111408.c b/gcc/testsuite/gcc.c-torture/execute/pr111408.c new file mode 100644 index 0000000..6dfb0a3 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr111408.c @@ -0,0 +1,26 @@ +/* PR target/111408 */ + +int a, b, c, d; +short e; + +int +foo () +{ + c = a % (sizeof (int) * 8); + if (b & 1 << c) + return -1; + return 0; +} + +int +main () +{ + for (; e != 1; e++) + { + int g = foo (); + if (g + d - 9 + d) + continue; + for (;;) + __builtin_abort (); + } +} diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-4.c b/gcc/testsuite/gcc.dg/analyzer/fd-4.c index 994bad8..3a961e4 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-4.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-4.c @@ -1,4 +1,4 @@ -#ifdef _AIX +#if defined(_AIX) || defined(__hpux) #define _MODE_T #endif #include <stdio.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-client.c b/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-client.c index fa98e3c..6d4dc60 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-client.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-client.c @@ -1,6 +1,6 @@ /* Example from the glibc manual (16.10.4). */ /* { dg-require-effective-target sockets } */ -/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "" { hppa*-*-hpux* powerpc*-*-aix* } } */ #include <stdio.h> #include <errno.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-socket.c b/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-socket.c index 0d4894d..7e179cf 100644 --- a/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-socket.c +++ b/gcc/testsuite/gcc.dg/analyzer/fd-glibc-datagram-socket.c @@ -1,6 +1,6 @@ /* Example from glibc manual (16.10.3). */ /* { dg-require-effective-target sockets } */ -/* { dg-skip-if "" { powerpc*-*-aix* } } */ +/* { dg-skip-if "" { hppa*-*-hpux* powerpc*-*-aix* } } */ #include <stdio.h> #include <errno.h> diff --git a/gcc/testsuite/gcc.dg/analyzer/strndup-1.c b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c index 8cf7a42..85ccae8 100644 --- a/gcc/testsuite/gcc.dg/analyzer/strndup-1.c +++ b/gcc/testsuite/gcc.dg/analyzer/strndup-1.c @@ -1,4 +1,4 @@ -/* { dg-skip-if "no strndup in libc" { *-*-darwin[789]* *-*-darwin10* *-*-mingw* *-*-vxworks* } } */ +/* { dg-skip-if "no strndup in libc" { *-*-darwin[789]* *-*-darwin10* hppa*-*-hpux* *-*-mingw* *-*-vxworks* } } */ #include <string.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/asan/has-feature-asan.c b/gcc/testsuite/gcc.dg/asan/has-feature-asan.c new file mode 100644 index 0000000..810b69b --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/has-feature-asan.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=address" } */ +#define FEAT(x) (__has_feature (x) && __has_extension (x)) +#if !FEAT (address_sanitizer) +#error +#endif diff --git a/gcc/testsuite/gcc.dg/bitint-40.c b/gcc/testsuite/gcc.dg/bitint-40.c new file mode 100644 index 0000000..e418509 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-40.c @@ -0,0 +1,29 @@ +/* PR middle-end/112668 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c23 -fnon-call-exceptions" } */ + +#if __BITINT_MAXWIDTH__ >= 156 +struct T156 { _BitInt(156) a : 2; unsigned _BitInt(156) b : 135; _BitInt(156) c : 2; }; +extern void foo156 (struct T156 *); + +unsigned _BitInt(156) +bar156 (int i) +{ + struct T156 r156[12]; + foo156 (&r156[0]); + return r156[i].b; +} +#endif + +#if __BITINT_MAXWIDTH__ >= 495 +struct T495 { _BitInt(495) a : 2; unsigned _BitInt(495) b : 471; _BitInt(495) c : 2; }; +extern void foo495 (struct T495 *r495); + +unsigned _BitInt(495) +bar495 (int i) +{ + struct T495 r495[12]; + foo495 (r495); + return r495[i].b; +} +#endif diff --git a/gcc/testsuite/gcc.dg/bitint-41.c b/gcc/testsuite/gcc.dg/bitint-41.c new file mode 100644 index 0000000..d87ea08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-41.c @@ -0,0 +1,36 @@ +/* PR middle-end/112336 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c2x" } */ + +unsigned _BitInt(1) v1; +unsigned _BitInt(1) *p1 = &v1; +signed _BitInt(2) v2; +signed _BitInt(2) *p2 = &v2; +unsigned _BitInt(11) v11; +unsigned _BitInt(11) *p11 = &v11; +signed _BitInt(12) v12; +signed _BitInt(12) *p12 = &v12; +unsigned _BitInt(21) v21; +unsigned _BitInt(21) *p21 = &v21; +signed _BitInt(22) v22; +signed _BitInt(22) *p22 = &v22; +unsigned _BitInt(31) v31; +unsigned _BitInt(31) *p31 = &v31; +signed _BitInt(32) v32; +signed _BitInt(32) *p32 = &v32; +unsigned _BitInt(41) v41; +unsigned _BitInt(41) *p41 = &v41; +signed _BitInt(42) v42; +signed _BitInt(42) *p42 = &v42; +#if __BITINT_MAXWIDTH__ >= 128 +unsigned _BitInt(127) v127; +unsigned _BitInt(127) *p127 = &v127; +signed _BitInt(128) v128; +signed _BitInt(128) *p128 = &v128; +#endif +#if __BITINT_MAXWIDTH__ >= 258 +unsigned _BitInt(257) v257; +unsigned _BitInt(257) *p257 = &v257; +signed _BitInt(258) v258; +signed _BitInt(258) *p258 = &v258; +#endif diff --git a/gcc/testsuite/gcc.dg/bitint-42.c b/gcc/testsuite/gcc.dg/bitint-42.c new file mode 100644 index 0000000..9d3090b --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-42.c @@ -0,0 +1,9 @@ +/* PR middle-end/112679 */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-frounding-math" } */ + +float +foo (void) +{ + return 0x353eab28b46b03ea99b84f9736cd8dbe5e986915a0383c3cb381c0da41e31b3621c75fd53262bfcb1b0e6251dbf00f3988784e29b08b65640c263e4d0959832a20e2ff5245be1e60uwb; +} diff --git a/gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c b/gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c new file mode 100644 index 0000000..6ba95ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-stdc-bit-1.c @@ -0,0 +1,927 @@ +/* { dg-do run } */ +/* { dg-options "-std=c11" } */ + +unsigned int +leading_zeros (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_leading_zeros (a) + + __builtin_stdc_leading_zeros (b) + + __builtin_stdc_leading_zeros (c) + + __builtin_stdc_leading_zeros (d) + + __builtin_stdc_leading_zeros (e)); +} + +unsigned int +leading_ones (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_leading_ones (a) + + __builtin_stdc_leading_ones (b) + + __builtin_stdc_leading_ones (c) + + __builtin_stdc_leading_ones (d) + + __builtin_stdc_leading_ones (e)); +} + +unsigned int +trailing_zeros (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_trailing_zeros (a) + + __builtin_stdc_trailing_zeros (b) + + __builtin_stdc_trailing_zeros (c) + + __builtin_stdc_trailing_zeros (d) + + __builtin_stdc_trailing_zeros (e)); +} + +unsigned int +trailing_ones (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_trailing_ones (a) + + __builtin_stdc_trailing_ones (b) + + __builtin_stdc_trailing_ones (c) + + __builtin_stdc_trailing_ones (d) + + __builtin_stdc_trailing_ones (e)); +} + +unsigned int +first_leading_zero (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_first_leading_zero (a) + + __builtin_stdc_first_leading_zero (b) + + __builtin_stdc_first_leading_zero (c) + + __builtin_stdc_first_leading_zero (d) + + __builtin_stdc_first_leading_zero (e)); +} + +unsigned int +first_leading_one (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_first_leading_one (a) + + __builtin_stdc_first_leading_one (b) + + __builtin_stdc_first_leading_one (c) + + __builtin_stdc_first_leading_one (d) + + __builtin_stdc_first_leading_one (e)); +} + +unsigned int +first_trailing_zero (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_first_trailing_zero (a) + + __builtin_stdc_first_trailing_zero (b) + + __builtin_stdc_first_trailing_zero (c) + + __builtin_stdc_first_trailing_zero (d) + + __builtin_stdc_first_trailing_zero (e)); +} + +unsigned int +first_trailing_one (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_first_trailing_one (a) + + __builtin_stdc_first_trailing_one (b) + + __builtin_stdc_first_trailing_one (c) + + __builtin_stdc_first_trailing_one (d) + + __builtin_stdc_first_trailing_one (e)); +} + +unsigned int +count_zeros (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_count_zeros (a) + + __builtin_stdc_count_zeros (b) + + __builtin_stdc_count_zeros (c) + + __builtin_stdc_count_zeros (d) + + __builtin_stdc_count_zeros (e)); +} + +unsigned int +count_ones (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_count_ones (a) + + __builtin_stdc_count_ones (b) + + __builtin_stdc_count_ones (c) + + __builtin_stdc_count_ones (d) + + __builtin_stdc_count_ones (e)); +} + +unsigned int +has_single_bit (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_has_single_bit (a) + || __builtin_stdc_has_single_bit (b) + || __builtin_stdc_has_single_bit (c) + || __builtin_stdc_has_single_bit (d) + || __builtin_stdc_has_single_bit (e)); +} + +unsigned int +bit_width (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_bit_width (a) + + __builtin_stdc_bit_width (b) + + __builtin_stdc_bit_width (c) + + __builtin_stdc_bit_width (d) + + __builtin_stdc_bit_width (e)); +} + +unsigned long long +bit_floor (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_bit_floor (a) + + __builtin_stdc_bit_floor (b) + + __builtin_stdc_bit_floor (c) + + __builtin_stdc_bit_floor (d) + + __builtin_stdc_bit_floor (e)); +} + +unsigned long long +bit_ceil (unsigned char a, unsigned short b, unsigned int c, + unsigned long d, unsigned long long e) +{ + return (__builtin_stdc_bit_ceil (a) + + __builtin_stdc_bit_ceil (b) + + __builtin_stdc_bit_ceil (c) + + __builtin_stdc_bit_ceil (d) + + __builtin_stdc_bit_ceil (e)); +} + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) + +int +main () +{ + if (__builtin_stdc_leading_zeros ((unsigned char) 0) != __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros ((unsigned char) 0), unsigned int) + || __builtin_stdc_leading_zeros ((unsigned short) 0) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros ((unsigned short) 0), unsigned int) + || __builtin_stdc_leading_zeros (0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros (0U), unsigned int) + || __builtin_stdc_leading_zeros (0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros (0UL), unsigned int) + || __builtin_stdc_leading_zeros (0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_leading_zeros ((unsigned char) ~0U) != 0 + || __builtin_stdc_leading_zeros ((unsigned short) ~0U) != 0 + || __builtin_stdc_leading_zeros (~0U) != 0 + || __builtin_stdc_leading_zeros (~0UL) != 0 + || __builtin_stdc_leading_zeros (~0ULL) != 0) + __builtin_abort (); + if (__builtin_stdc_leading_zeros ((unsigned char) 3) != __CHAR_BIT__ - 2 + || __builtin_stdc_leading_zeros ((unsigned short) 9) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 4 + || __builtin_stdc_leading_zeros (34U) != __SIZEOF_INT__ * __CHAR_BIT__ - 6 + || __builtin_stdc_leading_zeros (130UL) != __SIZEOF_LONG__ * __CHAR_BIT__ - 8 + || __builtin_stdc_leading_zeros (512ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 10) + __builtin_abort (); + if (__builtin_stdc_leading_ones ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_leading_ones ((unsigned char) 0), unsigned int) + || __builtin_stdc_leading_ones ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_leading_ones ((unsigned short) 0), unsigned int) + || __builtin_stdc_leading_ones (0U) != 0 + || !expr_has_type (__builtin_stdc_leading_ones (0U), unsigned int) + || __builtin_stdc_leading_ones (0UL) != 0 + || !expr_has_type (__builtin_stdc_leading_ones (0UL), unsigned int) + || __builtin_stdc_leading_ones (0ULL) != 0 + || !expr_has_type (__builtin_stdc_leading_ones (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_leading_ones ((unsigned char) ~0U) != __CHAR_BIT__ + || __builtin_stdc_leading_ones ((unsigned short) ~0U) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || __builtin_stdc_leading_ones (~0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || __builtin_stdc_leading_ones (~0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || __builtin_stdc_leading_ones (~0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_leading_ones ((unsigned char) ~3) != __CHAR_BIT__ - 2 + || __builtin_stdc_leading_ones ((unsigned short) ~9) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 4 + || __builtin_stdc_leading_ones (~34U) != __SIZEOF_INT__ * __CHAR_BIT__ - 6 + || __builtin_stdc_leading_ones (~130UL) != __SIZEOF_LONG__ * __CHAR_BIT__ - 8 + || __builtin_stdc_leading_ones (~512ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 10) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned char) 0) != __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros ((unsigned char) 0), unsigned int) + || __builtin_stdc_trailing_zeros ((unsigned short) 0) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros ((unsigned short) 0), unsigned int) + || __builtin_stdc_trailing_zeros (0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros (0U), unsigned int) + || __builtin_stdc_trailing_zeros (0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros (0UL), unsigned int) + || __builtin_stdc_trailing_zeros (0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned char) ~0U) != 0 + || __builtin_stdc_trailing_zeros ((unsigned short) ~0U) != 0 + || __builtin_stdc_trailing_zeros (~0U) != 0 + || __builtin_stdc_trailing_zeros (~0UL) != 0 + || __builtin_stdc_trailing_zeros (~0ULL) != 0) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned char) 2) != 1 + || __builtin_stdc_trailing_zeros ((unsigned short) 24) != 3 + || __builtin_stdc_trailing_zeros (32U) != 5 + || __builtin_stdc_trailing_zeros (128UL) != 7 + || __builtin_stdc_trailing_zeros (512ULL) != 9) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones ((unsigned char) 0), unsigned int) + || __builtin_stdc_trailing_ones ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones ((unsigned short) 0), unsigned int) + || __builtin_stdc_trailing_ones (0U) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones (0U), unsigned int) + || __builtin_stdc_trailing_ones (0UL) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones (0UL), unsigned int) + || __builtin_stdc_trailing_ones (0ULL) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned char) ~0U) != __CHAR_BIT__ + || __builtin_stdc_trailing_ones ((unsigned short) ~0U) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || __builtin_stdc_trailing_ones (~0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || __builtin_stdc_trailing_ones (~0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || __builtin_stdc_trailing_ones (~0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned char) 5) != 1 + || __builtin_stdc_trailing_ones ((unsigned short) 15) != 4 + || __builtin_stdc_trailing_ones (127U) != 7 + || __builtin_stdc_trailing_ones (511UL) != 9 + || __builtin_stdc_trailing_ones (~0ULL >> 2) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 2) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero ((unsigned char) 0) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero ((unsigned char) 0), unsigned int) + || __builtin_stdc_first_leading_zero ((unsigned short) 0) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero ((unsigned short) 0), unsigned int) + || __builtin_stdc_first_leading_zero (0U) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero (0U), unsigned int) + || __builtin_stdc_first_leading_zero (0UL) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero (0UL), unsigned int) + || __builtin_stdc_first_leading_zero (0ULL) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero ((unsigned char) ~0U) != 0 + || __builtin_stdc_first_leading_zero ((unsigned short) ~0U) != 0 + || __builtin_stdc_first_leading_zero (~0U) != 0 + || __builtin_stdc_first_leading_zero (~0UL) != 0 + || __builtin_stdc_first_leading_zero (~0ULL) != 0) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero ((unsigned char) ~3U) != __CHAR_BIT__ - 1 + || __builtin_stdc_first_leading_zero ((unsigned short) ~15U) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 3 + || __builtin_stdc_first_leading_zero (~63U) != __SIZEOF_INT__ * __CHAR_BIT__ - 5 + || __builtin_stdc_first_leading_zero (~255UL) != __SIZEOF_LONG__ * __CHAR_BIT__ - 7 + || __builtin_stdc_first_leading_zero (~1023ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 9) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one ((unsigned char) 0), unsigned int) + || __builtin_stdc_first_leading_one ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one ((unsigned short) 0), unsigned int) + || __builtin_stdc_first_leading_one (0U) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one (0U), unsigned int) + || __builtin_stdc_first_leading_one (0UL) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one (0UL), unsigned int) + || __builtin_stdc_first_leading_one (0ULL) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned char) ~0U) != 1 + || __builtin_stdc_first_leading_one ((unsigned short) ~0U) != 1 + || __builtin_stdc_first_leading_one (~0U) != 1 + || __builtin_stdc_first_leading_one (~0UL) != 1 + || __builtin_stdc_first_leading_one (~0ULL) != 1) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned char) 3) != __CHAR_BIT__ - 1 + || __builtin_stdc_first_leading_one ((unsigned short) 9) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 3 + || __builtin_stdc_first_leading_one (34U) != __SIZEOF_INT__ * __CHAR_BIT__ - 5 + || __builtin_stdc_first_leading_one (130UL) != __SIZEOF_LONG__ * __CHAR_BIT__ - 7 + || __builtin_stdc_first_leading_one (512ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 9) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned char) 0) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero ((unsigned char) 0), unsigned int) + || __builtin_stdc_first_trailing_zero ((unsigned short) 0) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero ((unsigned short) 0), unsigned int) + || __builtin_stdc_first_trailing_zero (0U) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero (0U), unsigned int) + || __builtin_stdc_first_trailing_zero (0UL) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero (0UL), unsigned int) + || __builtin_stdc_first_trailing_zero (0ULL) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned char) ~0U) != 0 + || __builtin_stdc_first_trailing_zero ((unsigned short) ~0U) != 0 + || __builtin_stdc_first_trailing_zero (~0U) != 0 + || __builtin_stdc_first_trailing_zero (~0UL) != 0 + || __builtin_stdc_first_trailing_zero (~0ULL) != 0) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned char) 2) != 1 + || __builtin_stdc_first_trailing_zero ((unsigned short) 15) != 5 + || __builtin_stdc_first_trailing_zero (63U) != 7 + || __builtin_stdc_first_trailing_zero (128UL) != 1 + || __builtin_stdc_first_trailing_zero (511ULL) != 10) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one ((unsigned char) 0), unsigned int) + || __builtin_stdc_first_trailing_one ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one ((unsigned short) 0), unsigned int) + || __builtin_stdc_first_trailing_one (0U) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one (0U), unsigned int) + || __builtin_stdc_first_trailing_one (0UL) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one (0UL), unsigned int) + || __builtin_stdc_first_trailing_one (0ULL) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one ((unsigned char) ~0U) != 1 + || __builtin_stdc_first_trailing_one ((unsigned short) ~0U) != 1 + || __builtin_stdc_first_trailing_one (~0U) != 1 + || __builtin_stdc_first_trailing_one (~0UL) != 1 + || __builtin_stdc_first_trailing_one (~0ULL) != 1) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one ((unsigned char) 4) != 3 + || __builtin_stdc_first_trailing_one ((unsigned short) 96) != 6 + || __builtin_stdc_first_trailing_one (127U) != 1 + || __builtin_stdc_first_trailing_one (511UL) != 1 + || __builtin_stdc_first_trailing_one (~0ULL << 12) != 13) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned char) 0) != __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros ((unsigned char) 0), unsigned int) + || __builtin_stdc_count_zeros ((unsigned short) 0) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros ((unsigned short) 0), unsigned int) + || __builtin_stdc_count_zeros (0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros (0U), unsigned int) + || __builtin_stdc_count_zeros (0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros (0UL), unsigned int) + || __builtin_stdc_count_zeros (0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned char) ~0U) != 0 + || __builtin_stdc_count_zeros ((unsigned short) ~0U) != 0 + || __builtin_stdc_count_zeros (~0U) != 0 + || __builtin_stdc_count_zeros (~0UL) != 0 + || __builtin_stdc_count_zeros (~0ULL) != 0) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned char) 1U) != __CHAR_BIT__ - 1 + || __builtin_stdc_count_zeros ((unsigned short) 42) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 3 + || __builtin_stdc_count_zeros (291U) != __SIZEOF_INT__ * __CHAR_BIT__ - 4 + || __builtin_stdc_count_zeros (~1315UL) != 5 + || __builtin_stdc_count_zeros (3363ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 6) + __builtin_abort (); + if (__builtin_stdc_count_ones ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_count_ones ((unsigned char) 0), unsigned int) + || __builtin_stdc_count_ones ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_count_ones ((unsigned short) 0), unsigned int) + || __builtin_stdc_count_ones (0U) != 0 + || !expr_has_type (__builtin_stdc_count_ones (0U), unsigned int) + || __builtin_stdc_count_ones (0UL) != 0 + || !expr_has_type (__builtin_stdc_count_ones (0UL), unsigned int) + || __builtin_stdc_count_ones (0ULL) != 0 + || !expr_has_type (__builtin_stdc_count_ones (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_ones ((unsigned char) ~0U) != __CHAR_BIT__ + || __builtin_stdc_count_ones ((unsigned short) ~0U) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || __builtin_stdc_count_ones (~0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || __builtin_stdc_count_ones (~0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || __builtin_stdc_count_ones (~0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_count_ones ((unsigned char) ~1U) != __CHAR_BIT__ - 1 + || __builtin_stdc_count_ones ((unsigned short) ~42) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 3 + || __builtin_stdc_count_ones (~291U) != __SIZEOF_INT__ * __CHAR_BIT__ - 4 + || __builtin_stdc_count_ones (1315UL) != 5 + || __builtin_stdc_count_ones (~3363ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 6) + __builtin_abort (); + if (__builtin_stdc_has_single_bit ((unsigned char) 0) + || !expr_has_type (__builtin_stdc_has_single_bit ((unsigned char) 0), _Bool) + || __builtin_stdc_has_single_bit ((unsigned short) 0) + || !expr_has_type (__builtin_stdc_has_single_bit ((unsigned short) 0), _Bool) + || __builtin_stdc_has_single_bit (0U) + || !expr_has_type (__builtin_stdc_has_single_bit (0U), _Bool) + || __builtin_stdc_has_single_bit (0UL) + || !expr_has_type (__builtin_stdc_has_single_bit (0UL), _Bool) + || __builtin_stdc_has_single_bit (0ULL) + || !expr_has_type (__builtin_stdc_has_single_bit (0ULL), _Bool)) + __builtin_abort (); + if (!__builtin_stdc_has_single_bit ((unsigned char) 2) + || !__builtin_stdc_has_single_bit ((unsigned short) 8) + || !__builtin_stdc_has_single_bit (32U) + || !__builtin_stdc_has_single_bit (128UL) + || !__builtin_stdc_has_single_bit (512ULL)) + __builtin_abort (); + if (__builtin_stdc_has_single_bit ((unsigned char) 7) + || __builtin_stdc_has_single_bit ((unsigned short) 96) + || __builtin_stdc_has_single_bit (513U) + || __builtin_stdc_has_single_bit (1022UL) + || __builtin_stdc_has_single_bit (12ULL)) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned char) 0), unsigned int) + || __builtin_stdc_bit_width ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned short) 0), unsigned int) + || __builtin_stdc_bit_width (0U) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0U), unsigned int) + || __builtin_stdc_bit_width (0UL) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0UL), unsigned int) + || __builtin_stdc_bit_width (0ULL) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0ULL), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned char) ~0U) != __CHAR_BIT__ + || __builtin_stdc_bit_width ((unsigned short) ~0U) != __SIZEOF_SHORT__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0U) != __SIZEOF_INT__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0UL) != __SIZEOF_LONG__ * __CHAR_BIT__ + || __builtin_stdc_bit_width (~0ULL) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned char) ((unsigned char) ~0U >> 1)) != __CHAR_BIT__ - 1 + || __builtin_stdc_bit_width ((unsigned char) 6) != 3 + || __builtin_stdc_bit_width ((unsigned short) 12U) != 4 + || __builtin_stdc_bit_width ((unsigned short) ((unsigned short) ~0U >> 5)) != __SIZEOF_SHORT__ * __CHAR_BIT__ - 5 + || __builtin_stdc_bit_width (137U) != 8 + || __builtin_stdc_bit_width (269U) != 9 + || __builtin_stdc_bit_width (39UL) != 6 + || __builtin_stdc_bit_width (~0UL >> 2) != __SIZEOF_LONG__ * __CHAR_BIT__ - 2 + || __builtin_stdc_bit_width (1023ULL) != 10 + || __builtin_stdc_bit_width (1024ULL) != 11) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned char) 0), unsigned char) + || __builtin_stdc_bit_floor ((unsigned short) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned short) 0), unsigned short) + || __builtin_stdc_bit_floor (0U) != 0U + || !expr_has_type (__builtin_stdc_bit_floor (0U), unsigned int) + || __builtin_stdc_bit_floor (0UL) != 0UL + || !expr_has_type (__builtin_stdc_bit_floor (0UL), unsigned long) + || __builtin_stdc_bit_floor (0ULL) != 0ULL + || !expr_has_type (__builtin_stdc_bit_floor (0ULL), unsigned long long)) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) ~0U) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor ((unsigned short) ~0U) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0U) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0UL) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_floor (~0ULL) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1))) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned char) 4) != 4 + || __builtin_stdc_bit_floor ((unsigned char) 7) != 4 + || __builtin_stdc_bit_floor ((unsigned short) 8U) != 8 + || __builtin_stdc_bit_floor ((unsigned short) 31U) != 16 + || __builtin_stdc_bit_floor (137U) != 128U + || __builtin_stdc_bit_floor (269U) != 256U + || __builtin_stdc_bit_floor (511UL) != 256UL + || __builtin_stdc_bit_floor (512UL) != 512UL + || __builtin_stdc_bit_floor (513UL) != 512ULL + || __builtin_stdc_bit_floor (1024ULL) != 1024ULL) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned char) 0), unsigned char) + || __builtin_stdc_bit_ceil ((unsigned short) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned short) 0), unsigned short) + || __builtin_stdc_bit_ceil (0U) != 1U + || !expr_has_type (__builtin_stdc_bit_ceil (0U), unsigned int) + || __builtin_stdc_bit_ceil (0UL) != 1UL + || !expr_has_type (__builtin_stdc_bit_ceil (0UL), unsigned long) + || __builtin_stdc_bit_ceil (0ULL) != 1ULL + || !expr_has_type (__builtin_stdc_bit_ceil (0ULL), unsigned long long)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) ~0U) != 0 + || __builtin_stdc_bit_ceil ((unsigned short) ~0U) != 0 + || __builtin_stdc_bit_ceil (~0U) != 0U + || __builtin_stdc_bit_ceil (~0UL) != 0UL + || __builtin_stdc_bit_ceil (~0ULL) != 0ULL) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) ((unsigned char) ~0U >> 1)) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned char) ((unsigned char) ~0U >> 1)) != (1U << (__CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned short) ((unsigned short) ~0U >> 1)) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil ((unsigned short) ((unsigned short) ~0U >> 1)) != (1U << (__SIZEOF_SHORT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0U >> 1) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) != (1U << (__SIZEOF_INT__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0UL >> 1) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0UL >> 1) != (1UL << (__SIZEOF_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1)) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1)) + || __builtin_stdc_bit_ceil (~0ULL >> 1) != (1ULL << (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1))) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned char) 1) != 1 + || __builtin_stdc_bit_ceil ((unsigned char) 2) != 2 + || __builtin_stdc_bit_ceil ((unsigned short) 3U) != 4 + || __builtin_stdc_bit_ceil ((unsigned short) 4U) != 4 + || __builtin_stdc_bit_ceil (5U) != 8U + || __builtin_stdc_bit_ceil (269U) != 512U + || __builtin_stdc_bit_ceil (511UL) != 512UL + || __builtin_stdc_bit_ceil (512UL) != 512UL + || __builtin_stdc_bit_ceil (513ULL) != 1024ULL + || __builtin_stdc_bit_ceil (1025ULL) != 2048ULL) + __builtin_abort (); +#ifdef __SIZEOF_INT128__ + if (__builtin_stdc_leading_zeros ((unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_leading_zeros ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_leading_zeros (~(unsigned __int128) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_leading_ones ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_leading_ones ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_leading_ones (~(unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_trailing_zeros ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_trailing_zeros (~(unsigned __int128) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_trailing_ones (~(unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero ((unsigned __int128) 0) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_first_leading_zero (~(unsigned __int128) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_first_leading_one (~(unsigned __int128) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned __int128) 0) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_first_trailing_zero (~(unsigned __int128) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_first_trailing_one (~(unsigned __int128) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__ + || !expr_has_type (__builtin_stdc_count_zeros ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_count_zeros (~(unsigned __int128) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_count_ones ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_count_ones ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_count_ones (~(unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_has_single_bit ((unsigned __int128) 0) + || !expr_has_type (__builtin_stdc_has_single_bit ((unsigned __int128) 0), _Bool) + || __builtin_stdc_has_single_bit (~(unsigned __int128) 0)) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned __int128) 0), unsigned int) + || __builtin_stdc_bit_width (~(unsigned __int128) 0) != __SIZEOF_INT128__ * __CHAR_BIT__) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned __int128) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned __int128) 0), unsigned __int128) + || __builtin_stdc_bit_floor (~(unsigned __int128) 0) != ((unsigned __int128) 1) << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned __int128) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned __int128) 0), unsigned __int128) + || __builtin_stdc_bit_ceil ((unsigned __int128) 1) != 1 + || __builtin_stdc_bit_ceil ((~(unsigned __int128) 0) >> 1) != ((unsigned __int128) 1) << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1) + || __builtin_stdc_bit_ceil (~(unsigned __int128) 0) != 0) + __builtin_abort (); +#endif +#if __has_builtin (__builtin_stdc_leading_zeros) != 1 +#error __builtin_stdc_leading_zeros not implemented +#endif +#if __has_builtin (__builtin_stdc_leading_ones) != 1 +#error __builtin_stdc_leading_ones not implemented +#endif +#if __has_builtin (__builtin_stdc_trailing_zeros) != 1 +#error __builtin_stdc_trailing_zeros not implemented +#endif +#if __has_builtin (__builtin_stdc_trailing_ones) != 1 +#error __builtin_stdc_trailing_ones not implemented +#endif +#if __has_builtin (__builtin_stdc_first_leading_zero) != 1 +#error __builtin_stdc_first_leading_zero not implemented +#endif +#if __has_builtin (__builtin_stdc_first_leading_one) != 1 +#error __builtin_stdc_first_leading_one not implemented +#endif +#if __has_builtin (__builtin_stdc_first_trailing_zero) != 1 +#error __builtin_stdc_first_trailing_zero not implemented +#endif +#if __has_builtin (__builtin_stdc_first_trailing_one) != 1 +#error __builtin_stdc_first_trailing_one not implemented +#endif +#if __has_builtin (__builtin_stdc_count_zeros) != 1 +#error __builtin_stdc_count_zeros not implemented +#endif +#if __has_builtin (__builtin_stdc_count_ones) != 1 +#error __builtin_stdc_count_ones not implemented +#endif +#if __has_builtin (__builtin_stdc_has_single_bit) != 1 +#error __builtin_stdc_single_bit not implemented +#endif +#if __has_builtin (__builtin_stdc_bit_width) != 1 +#error __builtin_stdc_bit_width not implemented +#endif +#if __has_builtin (__builtin_stdc_bit_floor) != 1 +#error __builtin_stdc_bit_floor not implemented +#endif +#if __has_builtin (__builtin_stdc_bit_ceil) != 1 +#error __builtin_stdc_bit_ceil not implemented +#endif + unsigned char a = 0; + if (__builtin_stdc_bit_width (a++) != 0 || a != 1) + __builtin_abort (); + unsigned long long b = 0; + if (__builtin_stdc_bit_width (b++) != 0 || b != 1) + __builtin_abort (); + if (__builtin_stdc_bit_floor (a++) != 1 || a != 2) + __builtin_abort (); + if (__builtin_stdc_bit_floor (b++) != 1 || b != 2) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (a++) != 2 || a != 3) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (b++) != 2 || b != 3) + __builtin_abort (); + if (__builtin_stdc_leading_zeros (a++) != __CHAR_BIT__ - 2 || a != 4) + __builtin_abort (); + if (__builtin_stdc_leading_zeros (b++) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 2 || b != 4) + __builtin_abort (); + if (__builtin_stdc_leading_ones (a++) != 0 || a != 5) + __builtin_abort (); + if (__builtin_stdc_leading_ones (b++) != 0 || b != 5) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros (a++) != 0 || a != 6) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros (b++) != 0 || b != 6) + __builtin_abort (); + if (__builtin_stdc_trailing_ones (a++) != 0 || a != 7) + __builtin_abort (); + if (__builtin_stdc_trailing_ones (b++) != 0 || b != 7) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero (a++) != 1 || a != 8) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero (b++) != 1 || b != 8) + __builtin_abort (); + if (__builtin_stdc_first_leading_one (a++) != __CHAR_BIT__ - 3 || a != 9) + __builtin_abort (); + if (__builtin_stdc_first_leading_one (b++) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 3 || b != 9) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero (a++) != 2 || a != 10) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero (b++) != 2 || b != 10) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one (a++) != 2 || a != 11) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one (b++) != 2 || b != 11) + __builtin_abort (); + if (__builtin_stdc_count_zeros (a++) != __CHAR_BIT__ - 3 || a != 12) + __builtin_abort (); + if (__builtin_stdc_count_zeros (b++) != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 3 || b != 12) + __builtin_abort (); + if (__builtin_stdc_count_ones (a++) != 2 || a != 13) + __builtin_abort (); + if (__builtin_stdc_count_ones (b++) != 2 || b != 13) + __builtin_abort (); + if (__builtin_stdc_has_single_bit (a++) || a != 14) + __builtin_abort (); + if (__builtin_stdc_has_single_bit (b++) || b != 14) + __builtin_abort (); +#if __BITINT_MAXWIDTH__ >= 64 + if (__builtin_stdc_leading_zeros (0uwb) != 1 + || !expr_has_type (__builtin_stdc_leading_zeros (0uwb), unsigned int) + || __builtin_stdc_leading_zeros (1uwb) != 0 + || !expr_has_type (__builtin_stdc_leading_zeros (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_leading_ones (0uwb) != 0 + || !expr_has_type (__builtin_stdc_leading_ones (0uwb), unsigned int) + || __builtin_stdc_leading_ones (1uwb) != 1 + || !expr_has_type (__builtin_stdc_leading_ones (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros (0uwb) != 1 + || !expr_has_type (__builtin_stdc_trailing_zeros (0uwb), unsigned int) + || __builtin_stdc_trailing_zeros (1uwb) != 0 + || !expr_has_type (__builtin_stdc_trailing_zeros (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_ones (0uwb) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones (0uwb), unsigned int) + || __builtin_stdc_trailing_ones (1uwb) != 1 + || !expr_has_type (__builtin_stdc_trailing_ones (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero (0uwb) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero (0uwb), unsigned int) + || __builtin_stdc_first_leading_zero (1uwb) != 0 + || !expr_has_type (__builtin_stdc_first_leading_zero (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_one (0uwb) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one (0uwb), unsigned int) + || __builtin_stdc_first_leading_one (1uwb) != 1 + || !expr_has_type (__builtin_stdc_first_leading_one (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero (0uwb) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero (0uwb), unsigned int) + || __builtin_stdc_first_trailing_zero (1uwb) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_zero (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one (0uwb) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one (0uwb), unsigned int) + || __builtin_stdc_first_trailing_one (1uwb) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_one (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_zeros (0uwb) != 1 + || !expr_has_type (__builtin_stdc_count_zeros (0uwb), unsigned int) + || __builtin_stdc_count_zeros (1uwb) != 0 + || !expr_has_type (__builtin_stdc_count_zeros (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_ones (0uwb) != 0 + || !expr_has_type (__builtin_stdc_count_ones (0uwb), unsigned int) + || __builtin_stdc_count_ones (1uwb) != 1 + || !expr_has_type (__builtin_stdc_count_ones (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_has_single_bit (0uwb) + || !expr_has_type (__builtin_stdc_has_single_bit (0uwb), _Bool) + || !__builtin_stdc_has_single_bit (1uwb) + || !expr_has_type (__builtin_stdc_has_single_bit (1uwb), _Bool)) + __builtin_abort (); + if (__builtin_stdc_bit_width (0uwb) != 0 + || !expr_has_type (__builtin_stdc_bit_width (0uwb), unsigned int) + || __builtin_stdc_bit_width (1uwb) != 1 + || !expr_has_type (__builtin_stdc_bit_width (1uwb), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_bit_floor (0uwb) != 0 + || !expr_has_type (__builtin_stdc_bit_floor (0uwb), unsigned _BitInt(1)) + || __builtin_stdc_bit_floor (1uwb) != 1 + || !expr_has_type (__builtin_stdc_bit_floor (1uwb), unsigned _BitInt(1))) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (0uwb) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil (0uwb), unsigned _BitInt(1)) + || __builtin_stdc_bit_ceil (1uwb) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil (1uwb), unsigned _BitInt(1))) + __builtin_abort (); + unsigned _BitInt(1) c = 0; + if (__builtin_stdc_bit_floor (c++) != 0 || c != 1) + __builtin_abort (); + if (__builtin_stdc_bit_floor (c++) != 1 || c != 0) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (c++) != 1 || c != 1) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (c++) != 1 || c != 0) + __builtin_abort (); +#endif +#if __BITINT_MAXWIDTH__ >= 512 + if (__builtin_stdc_leading_zeros ((unsigned _BitInt(512)) 0) != 512 + || !expr_has_type (__builtin_stdc_leading_zeros ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_leading_zeros ((unsigned _BitInt(373)) 0) != 373 + || !expr_has_type (__builtin_stdc_leading_zeros ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_leading_zeros (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_leading_zeros (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_leading_zeros ((unsigned _BitInt(512)) 275) != 512 - 9 + || __builtin_stdc_leading_zeros ((unsigned _BitInt(373)) 512) != 373 - 10) + __builtin_abort (); + if (__builtin_stdc_leading_ones ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_leading_ones ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_leading_ones ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_leading_ones ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_leading_ones (~(unsigned _BitInt(512)) 0) != 512 + || __builtin_stdc_leading_ones (~(unsigned _BitInt(373)) 0) != 373) + __builtin_abort (); + if (__builtin_stdc_leading_ones (~(unsigned _BitInt(512)) 275) != 512 - 9 + || __builtin_stdc_leading_ones (~(unsigned _BitInt(373)) 512) != 373 - 10) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned _BitInt(512)) 0) != 512 + || !expr_has_type (__builtin_stdc_trailing_zeros ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_trailing_zeros ((unsigned _BitInt(373)) 0) != 373 + || !expr_has_type (__builtin_stdc_trailing_zeros ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_trailing_zeros (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_trailing_zeros ((unsigned _BitInt(512)) 256) != 8 + || __builtin_stdc_trailing_zeros ((unsigned _BitInt(373)) 512) != 9) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_trailing_ones ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_trailing_ones ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_trailing_ones (~(unsigned _BitInt(512)) 0) != 512 + || __builtin_stdc_trailing_ones (~(unsigned _BitInt(373)) 0) != 373) + __builtin_abort (); + if (__builtin_stdc_trailing_ones ((unsigned _BitInt(512)) 255) != 8 + || __builtin_stdc_trailing_ones ((~(unsigned _BitInt(373)) 0) >> 2) != 373 - 2) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero ((unsigned _BitInt(512)) 0) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_first_leading_zero ((unsigned _BitInt(373)) 0) != 1 + || !expr_has_type (__builtin_stdc_first_leading_zero ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_first_leading_zero (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_first_leading_zero (~(unsigned _BitInt(512)) 511) != 512 - 8 + || __builtin_stdc_first_leading_zero (~(unsigned _BitInt(373)) 1023) != 373 - 9) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_first_leading_one ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_first_leading_one ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_leading_one (~(unsigned _BitInt(512)) 0) != 1 + || __builtin_stdc_first_leading_one (~(unsigned _BitInt(373)) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_first_leading_one ((unsigned _BitInt(512)) 275) != 512 - 8 + || __builtin_stdc_first_leading_one ((unsigned _BitInt(373)) 512) != 373 - 9) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned _BitInt(512)) 0) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_first_trailing_zero ((unsigned _BitInt(373)) 0) != 1 + || !expr_has_type (__builtin_stdc_first_trailing_zero ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_first_trailing_zero (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_first_trailing_zero ((unsigned _BitInt(512)) 255) != 9 + || __builtin_stdc_first_trailing_zero ((unsigned _BitInt(373)) 511) != 10) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_first_trailing_one ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_first_trailing_one ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one (~(unsigned _BitInt(512)) 0) != 1 + || __builtin_stdc_first_trailing_one (~(unsigned _BitInt(373)) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_first_trailing_one (((unsigned _BitInt(512)) 255) << 175) != 176 + || __builtin_stdc_first_trailing_one ((~(unsigned _BitInt(373)) 0) << 311) != 312) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned _BitInt(512)) 0) != 512 + || !expr_has_type (__builtin_stdc_count_zeros ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_count_zeros ((unsigned _BitInt(373)) 0) != 373 + || !expr_has_type (__builtin_stdc_count_zeros ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_zeros (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_count_zeros (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_count_zeros ((unsigned _BitInt(512)) 1315) != 512 - 5 + || __builtin_stdc_count_zeros ((unsigned _BitInt(373)) 3363) != 373 - 6) + __builtin_abort (); + if (__builtin_stdc_count_ones ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_count_ones ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_count_ones ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_count_ones ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_count_ones (~(unsigned _BitInt(512)) 0) != 512 + || __builtin_stdc_count_ones (~(unsigned _BitInt(373)) 0) != 373) + __builtin_abort (); + if (__builtin_stdc_count_ones (~(unsigned _BitInt(512)) 1315) != 512 - 5 + || __builtin_stdc_count_ones (~(unsigned _BitInt(373)) 3363) != 373 - 6) + __builtin_abort (); + if (__builtin_stdc_has_single_bit ((unsigned _BitInt(512)) 0) + || !expr_has_type (__builtin_stdc_has_single_bit ((unsigned _BitInt(512)) 0), _Bool) + || __builtin_stdc_has_single_bit ((unsigned _BitInt(373)) 0) + || !expr_has_type (__builtin_stdc_has_single_bit ((unsigned _BitInt(373)) 0), _Bool)) + __builtin_abort (); + if (__builtin_stdc_has_single_bit (~(unsigned _BitInt(512)) 0) + || __builtin_stdc_has_single_bit (~(unsigned _BitInt(373)) 0)) + __builtin_abort (); + if (__builtin_stdc_has_single_bit (((unsigned _BitInt(512)) 1022) << 279) + || __builtin_stdc_has_single_bit (((unsigned _BitInt(373)) 12) << 305)) + __builtin_abort (); + if (__builtin_stdc_bit_width ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned _BitInt(512)) 0), unsigned int) + || __builtin_stdc_bit_width ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_width ((unsigned _BitInt(373)) 0), unsigned int)) + __builtin_abort (); + if (__builtin_stdc_bit_width (~(unsigned _BitInt(512)) 0) != 512 + || __builtin_stdc_bit_width (~(unsigned _BitInt(373)) 0) != 373) + __builtin_abort (); + if (__builtin_stdc_bit_width (((unsigned _BitInt(512)) 1023) << 405) != 405 + 10 + || __builtin_stdc_bit_width (((unsigned _BitInt(373)) 1024) << 242) != 242 + 11) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned _BitInt(512)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned _BitInt(512)) 0), unsigned _BitInt(512)) + || __builtin_stdc_bit_floor ((unsigned _BitInt(373)) 0) != 0 + || !expr_has_type (__builtin_stdc_bit_floor ((unsigned _BitInt(373)) 0), unsigned _BitInt(373))) + __builtin_abort (); + if (__builtin_stdc_bit_floor (~(unsigned _BitInt(512)) 0) != ((unsigned _BitInt(512)) 1) << (512 - 1) + || __builtin_stdc_bit_floor (~(unsigned _BitInt(373)) 0) != ((unsigned _BitInt(373)) 1) << (373 - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_floor (((unsigned _BitInt(512)) 511) << 405) != (((unsigned _BitInt(512)) 256) << 405) + || __builtin_stdc_bit_floor (((unsigned _BitInt(373)) 512) << 242) != (((unsigned _BitInt(512)) 512) << 242)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned _BitInt(512)) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned _BitInt(512)) 0), unsigned _BitInt(512)) + || __builtin_stdc_bit_ceil ((unsigned _BitInt(373)) 0) != 1 + || !expr_has_type (__builtin_stdc_bit_ceil ((unsigned _BitInt(373)) 0), unsigned _BitInt(373))) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (~(unsigned _BitInt(512)) 0) != 0 + || __builtin_stdc_bit_ceil (~(unsigned _BitInt(373)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(512)) 1) << (512 - 1)) != ((unsigned _BitInt(512)) 1) << (512 - 1) + || __builtin_stdc_bit_ceil ((~(unsigned _BitInt(373)) 0) >> 1) != ((unsigned _BitInt(373)) 1) << (373 - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(512)) 512) << 405) != (((unsigned _BitInt(512)) 512) << 405) + || __builtin_stdc_bit_ceil (((unsigned _BitInt(373)) 513) << 242) != (((unsigned _BitInt(512)) 1024) << 242)) + __builtin_abort (); + if (__builtin_stdc_bit_floor ((unsigned _BitInt(__BITINT_MAXWIDTH__)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_bit_floor (~(unsigned _BitInt(__BITINT_MAXWIDTH__)) 0) != ((unsigned _BitInt(__BITINT_MAXWIDTH__)) 1) << (__BITINT_MAXWIDTH__ - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_floor (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 511) << 405) != (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 256) << 405) + || __builtin_stdc_bit_floor (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 512) << 405) != (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 512) << 405)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil ((unsigned _BitInt(__BITINT_MAXWIDTH__)) 0) != 1) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (~(unsigned _BitInt(__BITINT_MAXWIDTH__)) 0) != 0) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 1) << (__BITINT_MAXWIDTH__ - 1)) != ((unsigned _BitInt(__BITINT_MAXWIDTH__)) 1) << (__BITINT_MAXWIDTH__ - 1)) + __builtin_abort (); + if (__builtin_stdc_bit_ceil (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 512) << 405) != (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 512) << 405) + || __builtin_stdc_bit_ceil (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 513) << 405) != (((unsigned _BitInt(__BITINT_MAXWIDTH__)) 1024) << 405)) + __builtin_abort (); +#endif +} diff --git a/gcc/testsuite/gcc.dg/builtin-stdc-bit-2.c b/gcc/testsuite/gcc.dg/builtin-stdc-bit-2.c new file mode 100644 index 0000000..1997753 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-stdc-bit-2.c @@ -0,0 +1,150 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void +foo (void) +{ + typedef int V __attribute__ ((vector_size (4 * sizeof (int)))); + struct S { int s; }; + enum E { E0, E1 }; + __builtin_stdc_leading_zeros (0.0f); /* { dg-error "'__builtin_stdc_leading_zeros' operand not an integral type" } */ + __builtin_stdc_leading_zeros (0.0); /* { dg-error "'__builtin_stdc_leading_zeros' operand not an integral type" } */ + __builtin_stdc_leading_zeros (0.0L); /* { dg-error "'__builtin_stdc_leading_zeros' operand not an integral type" } */ + __builtin_stdc_leading_zeros ((V) {}); /* { dg-error "'__builtin_stdc_leading_zeros' operand not an integral type" } */ + __builtin_stdc_leading_zeros ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_leading_zeros' operand not an integral type" } */ + __builtin_stdc_leading_zeros (); /* { dg-error "wrong number of arguments to '__builtin_stdc_leading_zeros'" } */ + __builtin_stdc_leading_zeros (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_leading_zeros'" } */ + __builtin_stdc_leading_zeros ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_leading_zeros ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_leading_zeros (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_leading_ones (0.0f); /* { dg-error "'__builtin_stdc_leading_ones' operand not an integral type" } */ + __builtin_stdc_leading_ones (0.0); /* { dg-error "'__builtin_stdc_leading_ones' operand not an integral type" } */ + __builtin_stdc_leading_ones (0.0L); /* { dg-error "'__builtin_stdc_leading_ones' operand not an integral type" } */ + __builtin_stdc_leading_ones ((V) {}); /* { dg-error "'__builtin_stdc_leading_ones' operand not an integral type" } */ + __builtin_stdc_leading_ones ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_leading_ones' operand not an integral type" } */ + __builtin_stdc_leading_ones (); /* { dg-error "wrong number of arguments to '__builtin_stdc_leading_ones'" } */ + __builtin_stdc_leading_ones (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_leading_ones'" } */ + __builtin_stdc_leading_ones ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_leading_ones ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_leading_ones (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_trailing_zeros (0.0f); /* { dg-error "'__builtin_stdc_trailing_zeros' operand not an integral type" } */ + __builtin_stdc_trailing_zeros (0.0); /* { dg-error "'__builtin_stdc_trailing_zeros' operand not an integral type" } */ + __builtin_stdc_trailing_zeros (0.0L); /* { dg-error "'__builtin_stdc_trailing_zeros' operand not an integral type" } */ + __builtin_stdc_trailing_zeros ((V) {}); /* { dg-error "'__builtin_stdc_trailing_zeros' operand not an integral type" } */ + __builtin_stdc_trailing_zeros ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_trailing_zeros' operand not an integral type" } */ + __builtin_stdc_trailing_zeros (); /* { dg-error "wrong number of arguments to '__builtin_stdc_trailing_zeros'" } */ + __builtin_stdc_trailing_zeros (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_trailing_zeros'" } */ + __builtin_stdc_trailing_zeros ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has boolean type" } */ + __builtin_stdc_trailing_zeros ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has enumerated type" } */ + __builtin_stdc_trailing_zeros (0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has signed type" } */ + __builtin_stdc_trailing_ones (0.0f); /* { dg-error "'__builtin_stdc_trailing_ones' operand not an integral type" } */ + __builtin_stdc_trailing_ones (0.0); /* { dg-error "'__builtin_stdc_trailing_ones' operand not an integral type" } */ + __builtin_stdc_trailing_ones (0.0L); /* { dg-error "'__builtin_stdc_trailing_ones' operand not an integral type" } */ + __builtin_stdc_trailing_ones ((V) {}); /* { dg-error "'__builtin_stdc_trailing_ones' operand not an integral type" } */ + __builtin_stdc_trailing_ones ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_trailing_ones' operand not an integral type" } */ + __builtin_stdc_trailing_ones (); /* { dg-error "wrong number of arguments to '__builtin_stdc_trailing_ones'" } */ + __builtin_stdc_trailing_ones (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_trailing_ones'" } */ + __builtin_stdc_trailing_ones ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has boolean type" } */ + __builtin_stdc_trailing_ones ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has enumerated type" } */ + __builtin_stdc_trailing_ones (0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has signed type" } */ + __builtin_stdc_first_leading_zero (0.0f); /* { dg-error "'__builtin_stdc_first_leading_zero' operand not an integral type" } */ + __builtin_stdc_first_leading_zero (0.0); /* { dg-error "'__builtin_stdc_first_leading_zero' operand not an integral type" } */ + __builtin_stdc_first_leading_zero (0.0L); /* { dg-error "'__builtin_stdc_first_leading_zero' operand not an integral type" } */ + __builtin_stdc_first_leading_zero ((V) {}); /* { dg-error "'__builtin_stdc_first_leading_zero' operand not an integral type" } */ + __builtin_stdc_first_leading_zero ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_first_leading_zero' operand not an integral type" } */ + __builtin_stdc_first_leading_zero (); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_leading_zero'" } */ + __builtin_stdc_first_leading_zero (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_leading_zero'" } */ + __builtin_stdc_first_leading_zero ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_first_leading_zero ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_first_leading_zero (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_first_leading_one (0.0f); /* { dg-error "'__builtin_stdc_first_leading_one' operand not an integral type" } */ + __builtin_stdc_first_leading_one (0.0); /* { dg-error "'__builtin_stdc_first_leading_one' operand not an integral type" } */ + __builtin_stdc_first_leading_one (0.0L); /* { dg-error "'__builtin_stdc_first_leading_one' operand not an integral type" } */ + __builtin_stdc_first_leading_one ((V) {}); /* { dg-error "'__builtin_stdc_first_leading_one' operand not an integral type" } */ + __builtin_stdc_first_leading_one ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_first_leading_one' operand not an integral type" } */ + __builtin_stdc_first_leading_one (); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_leading_one'" } */ + __builtin_stdc_first_leading_one (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_leading_one'" } */ + __builtin_stdc_first_leading_one ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_first_leading_one ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_first_leading_one (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_first_trailing_zero (0.0f); /* { dg-error "'__builtin_stdc_first_trailing_zero' operand not an integral type" } */ + __builtin_stdc_first_trailing_zero (0.0); /* { dg-error "'__builtin_stdc_first_trailing_zero' operand not an integral type" } */ + __builtin_stdc_first_trailing_zero (0.0L); /* { dg-error "'__builtin_stdc_first_trailing_zero' operand not an integral type" } */ + __builtin_stdc_first_trailing_zero ((V) {}); /* { dg-error "'__builtin_stdc_first_trailing_zero' operand not an integral type" } */ + __builtin_stdc_first_trailing_zero ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_first_trailing_zero' operand not an integral type" } */ + __builtin_stdc_first_trailing_zero (); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_trailing_zero'" } */ + __builtin_stdc_first_trailing_zero (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_trailing_zero'" } */ + __builtin_stdc_first_trailing_zero ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has boolean type" } */ + __builtin_stdc_first_trailing_zero ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has enumerated type" } */ + __builtin_stdc_first_trailing_zero (0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has signed type" } */ + __builtin_stdc_first_trailing_one (0.0f); /* { dg-error "'__builtin_stdc_first_trailing_one' operand not an integral type" } */ + __builtin_stdc_first_trailing_one (0.0); /* { dg-error "'__builtin_stdc_first_trailing_one' operand not an integral type" } */ + __builtin_stdc_first_trailing_one (0.0L); /* { dg-error "'__builtin_stdc_first_trailing_one' operand not an integral type" } */ + __builtin_stdc_first_trailing_one ((V) {}); /* { dg-error "'__builtin_stdc_first_trailing_one' operand not an integral type" } */ + __builtin_stdc_first_trailing_one ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_first_trailing_one' operand not an integral type" } */ + __builtin_stdc_first_trailing_one (); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_trailing_one'" } */ + __builtin_stdc_first_trailing_one (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_first_trailing_one'" } */ + __builtin_stdc_first_trailing_one ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has boolean type" } */ + __builtin_stdc_first_trailing_one ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has enumerated type" } */ + __builtin_stdc_first_trailing_one (0); /* { dg-error "argument 1 in call to function '__builtin_ctzg' has signed type" } */ + __builtin_stdc_count_zeros (0.0f); /* { dg-error "'__builtin_stdc_count_zeros' operand not an integral type" } */ + __builtin_stdc_count_zeros (0.0); /* { dg-error "'__builtin_stdc_count_zeros' operand not an integral type" } */ + __builtin_stdc_count_zeros (0.0L); /* { dg-error "'__builtin_stdc_count_zeros' operand not an integral type" } */ + __builtin_stdc_count_zeros ((V) {}); /* { dg-error "'__builtin_stdc_count_zeros' operand not an integral type" } */ + __builtin_stdc_count_zeros ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_count_zeros' operand not an integral type" } */ + __builtin_stdc_count_zeros (); /* { dg-error "wrong number of arguments to '__builtin_stdc_count_zeros'" } */ + __builtin_stdc_count_zeros (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_count_zeros'" } */ + __builtin_stdc_count_zeros ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has boolean type" } */ + __builtin_stdc_count_zeros ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has enumerated type" } */ + __builtin_stdc_count_zeros (0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has signed type" } */ + __builtin_stdc_count_ones (0.0f); /* { dg-error "'__builtin_stdc_count_ones' operand not an integral type" } */ + __builtin_stdc_count_ones (0.0); /* { dg-error "'__builtin_stdc_count_ones' operand not an integral type" } */ + __builtin_stdc_count_ones (0.0L); /* { dg-error "'__builtin_stdc_count_ones' operand not an integral type" } */ + __builtin_stdc_count_ones ((V) {}); /* { dg-error "'__builtin_stdc_count_ones' operand not an integral type" } */ + __builtin_stdc_count_ones ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_count_ones' operand not an integral type" } */ + __builtin_stdc_count_ones (); /* { dg-error "wrong number of arguments to '__builtin_stdc_count_ones'" } */ + __builtin_stdc_count_ones (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_count_ones'" } */ + __builtin_stdc_count_ones ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has boolean type" } */ + __builtin_stdc_count_ones ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has enumerated type" } */ + __builtin_stdc_count_ones (0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has signed type" } */ + __builtin_stdc_has_single_bit (0.0f); /* { dg-error "'__builtin_stdc_has_single_bit' operand not an integral type" } */ + __builtin_stdc_has_single_bit (0.0); /* { dg-error "'__builtin_stdc_has_single_bit' operand not an integral type" } */ + __builtin_stdc_has_single_bit (0.0L); /* { dg-error "'__builtin_stdc_has_single_bit' operand not an integral type" } */ + __builtin_stdc_has_single_bit ((V) {}); /* { dg-error "'__builtin_stdc_has_single_bit' operand not an integral type" } */ + __builtin_stdc_has_single_bit ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_has_single_bit' operand not an integral type" } */ + __builtin_stdc_has_single_bit (); /* { dg-error "wrong number of arguments to '__builtin_stdc_has_single_bit'" } */ + __builtin_stdc_has_single_bit (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_has_single_bit'" } */ + __builtin_stdc_has_single_bit ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has boolean type" } */ + __builtin_stdc_has_single_bit ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has enumerated type" } */ + __builtin_stdc_has_single_bit (0); /* { dg-error "argument 1 in call to function '__builtin_popcountg' has signed type" } */ + __builtin_stdc_bit_width (0.0f); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (0.0); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (0.0L); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width ((V) {}); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_width' operand not an integral type" } */ + __builtin_stdc_bit_width (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_width'" } */ + __builtin_stdc_bit_width (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_width'" } */ + __builtin_stdc_bit_width ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_width ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_width (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_bit_floor (0.0f); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (0.0); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (0.0L); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor ((V) {}); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_floor' operand not an integral type" } */ + __builtin_stdc_bit_floor (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_floor'" } */ + __builtin_stdc_bit_floor (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_floor'" } */ + __builtin_stdc_bit_floor ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_floor ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_floor (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ + __builtin_stdc_bit_ceil (0.0f); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (0.0); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (0.0L); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil ((V) {}); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil ((struct S) { 0 }); /* { dg-error "'__builtin_stdc_bit_ceil' operand not an integral type" } */ + __builtin_stdc_bit_ceil (); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_ceil'" } */ + __builtin_stdc_bit_ceil (0U, 0U); /* { dg-error "wrong number of arguments to '__builtin_stdc_bit_ceil'" } */ + __builtin_stdc_bit_ceil ((_Bool) 0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has boolean type" } */ + __builtin_stdc_bit_ceil ((enum E) E0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has enumerated type" } */ + __builtin_stdc_bit_ceil (0); /* { dg-error "argument 1 in call to function '__builtin_clzg' has signed type" } */ +} diff --git a/gcc/testsuite/gcc.dg/has-feature.c b/gcc/testsuite/gcc.dg/has-feature.c new file mode 100644 index 0000000..2fd0b4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/has-feature.c @@ -0,0 +1,62 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* Test __has_{feature,extension} for C language features. */ + +#if !__has_extension (c_alignas) || !__has_extension (c_alignof) +#error +#endif + +#if !__has_extension (c_atomic) || !__has_extension (c_generic_selections) +#error +#endif + +#if !__has_extension (c_static_assert) || !__has_extension (c_thread_local) +#error +#endif + +#if !__has_extension (cxx_binary_literals) +#error +#endif + +#if __STDC_VERSION__ >= 201112L +/* Have C11 features. */ +#if !__has_feature (c_alignas) || !__has_feature (c_alignof) +#error +#endif + +#if !__has_feature (c_atomic) || !__has_feature (c_generic_selections) +#error +#endif + +#if !__has_feature (c_static_assert) || !__has_feature (c_thread_local) +#error +#endif + +#else +/* Don't have C11 features. */ +#if __has_feature (c_alignas) || __has_feature (c_alignof) +#error +#endif + +#if __has_feature (c_atomic) || __has_feature (c_generic_selections) +#error +#endif + +#if __has_feature (c_static_assert) || __has_feature (c_thread_local) +#error +#endif + +#endif + +#if __STDC_VERSION__ >= 202000L +/* Have C2x features. */ +#if !__has_feature (cxx_binary_literals) +#error +#endif + +#else +/* Don't have C2x features. */ +#if __has_feature (cxx_binary_literals) +#error +#endif +#endif diff --git a/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c b/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c index 4032ad1..155a682 100644 --- a/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c +++ b/gcc/testsuite/gcc.dg/ipa/fopt-info-inline-1.c @@ -1,4 +1,4 @@ -/* { dg-options "-O3 -fopt-info-inline-optimized-missed" } */ +/* { dg-options "-O3 -fopt-info-inline-optimized-missed -fno-ipa-vrp" } */ static int foo (int a) { diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c b/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c index fad0891..cbda685 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-icf-25.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-ipa-icf-optimized-all" } */ +/* { dg-options "-O2 -fdump-ipa-icf-optimized-all -fno-ipa-vrp" } */ static int zip(); static int zap(); diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c b/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c index 57c5262..a8824d0 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-icf-38.c @@ -1,6 +1,6 @@ /* { dg-do link } */ /* { dg-require-alias "" } */ -/* { dg-options "-O2 -fdump-ipa-icf-optimized -flto -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-ipa-icf-optimized -flto -fdump-tree-optimized -fno-ipa-vrp" } */ /* { dg-require-effective-target lto } */ /* { dg-additional-sources "ipa-icf-38a.c" }*/ diff --git a/gcc/testsuite/gcc.dg/ipa/pure-const-1.c b/gcc/testsuite/gcc.dg/ipa/pure-const-1.c index dd58457..10b5727 100644 --- a/gcc/testsuite/gcc.dg/ipa/pure-const-1.c +++ b/gcc/testsuite/gcc.dg/ipa/pure-const-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { nonpic || pie_enabled } } } */ -/* { dg-options "-O3 -fdump-tree-local-pure-const1 -fdump-ipa-pure-const -fdump-tree-optimized -fno-early-inlining -fgnu89-inline" } */ +/* { dg-options "-O3 -fno-ipa-vrp -fdump-tree-local-pure-const1 -fdump-ipa-pure-const -fdump-tree-optimized -fno-early-inlining -fgnu89-inline" } */ void abort (void); int error_code; static int val; diff --git a/gcc/testsuite/gcc.dg/ipa/remref-0.c b/gcc/testsuite/gcc.dg/ipa/remref-0.c index 6073c02..497136e 100644 --- a/gcc/testsuite/gcc.dg/ipa/remref-0.c +++ b/gcc/testsuite/gcc.dg/ipa/remref-0.c @@ -3,7 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-O3 -fno-early-inlining -fno-ipa-sra -fno-ipa-cp -fdump-ipa-inline -fdump-tree-optimized" } */ -extern int __attribute__ ((noinline, noclone, used)) +extern int __attribute__ ((noinline, noclone, used, noipa)) stuff (int i) { return 0; diff --git a/gcc/testsuite/gcc.dg/nonnull-7.c b/gcc/testsuite/gcc.dg/nonnull-7.c new file mode 100644 index 0000000..d66a609 --- /dev/null +++ b/gcc/testsuite/gcc.dg/nonnull-7.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target nonpic } } + { dg-options "-O2 -Wsuggest-attribute=returns_nonnull" } */ + +int *q; +int *test() /* { dg-warning "candidate for attribute .returns_nonnull." } */ +{ + if (!q) + __builtin_unreachable (); + return q; +} diff --git a/gcc/testsuite/gcc.dg/pch/pr112319.c b/gcc/testsuite/gcc.dg/pch/pr112319.c new file mode 100644 index 0000000..0438814 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pch/pr112319.c @@ -0,0 +1,5 @@ +/* { dg-additional-options "-Wpragmas -save-temps" } */ +#include "pr112319.h" +#pragma GCC diagnostic error "-Wpragmas" +#pragma GCC diagnostic ignored "oops" /* { dg-error "oops" } */ +/* { dg-regexp {[^[:space:]]*: some warnings being treated as errors} } */ diff --git a/gcc/testsuite/gcc.dg/pch/pr112319.hs b/gcc/testsuite/gcc.dg/pch/pr112319.hs new file mode 100644 index 0000000..3b6178b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pch/pr112319.hs @@ -0,0 +1 @@ +/* This space intentionally left blank. */ diff --git a/gcc/testsuite/gcc.dg/pr109977.c b/gcc/testsuite/gcc.dg/pr109977.c new file mode 100644 index 0000000..03d9a33 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109977.c @@ -0,0 +1,16 @@ +/* PR target/109977 */ +/* { dg-do compile } */ +/* { dg-options "-Og" } */ + +typedef double __attribute__((__vector_size__ (8))) V; +typedef double __attribute__((__vector_size__ (16))) W; +V v; +int i; +extern void bar (void *); + +void +foo (void) +{ + W w = __builtin_shufflevector (v, (W) { }, 0, 0); + bar (&w); +} diff --git a/gcc/testsuite/gcc.dg/pr110279-1.c b/gcc/testsuite/gcc.dg/pr110279-1.c new file mode 100644 index 0000000..f25b6ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr110279-1.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast --param avoid-fma-max-bits=512 --param tree-reassoc-width=4 -fdump-tree-widening_mul-details" } */ +/* { dg-additional-options "-march=armv8.2-a" { target aarch64-*-* } } */ + +#define LOOP_COUNT 800000000 +typedef double data_e; + +/* Check that FMAs with backedge dependency are avoided. Otherwise there won't + be FMA generated with "--param avoid-fma-max-bits=512". */ + +data_e +foo1 (data_e a, data_e b, data_e c, data_e d) +{ + data_e result = 0; + + for (int ic = 0; ic < LOOP_COUNT; ic++) + { + result += (a * b + c * d); + + a -= 0.1; + b += 0.9; + c *= 1.02; + d *= 0.61; + } + + return result; +} + +data_e +foo2 (data_e a, data_e b, data_e c, data_e d) +{ + data_e result = 0; + + for (int ic = 0; ic < LOOP_COUNT; ic++) + { + result = a * b + result + c * d; + + a -= 0.1; + b += 0.9; + c *= 1.02; + d *= 0.61; + } + + return result; +} + +data_e +foo3 (data_e a, data_e b, data_e c, data_e d) +{ + data_e result = 0; + + for (int ic = 0; ic < LOOP_COUNT; ic++) + { + result = result + a * b + c * d; + + a -= 0.1; + b += 0.9; + c *= 1.02; + d *= 0.61; + } + + return result; +} + +/* { dg-final { scan-tree-dump-times "Generated FMA" 3 "widening_mul"} } */
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/pr112618.c b/gcc/testsuite/gcc.dg/pr112618.c new file mode 100644 index 0000000..897e6a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112618.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int m, *p; + +__attribute__ ((simd)) int +bar (int x) +{ + if (x) + { + if (m < 1) + for (m = 0; m < 1; ++m) + ++x; + p = &x; + for (;;) + ++m; + } + return 0; +} + +__attribute__ ((simd)) int +foo (int x) +{ + bar (x); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr112622.c b/gcc/testsuite/gcc.dg/pr112622.c new file mode 100644 index 0000000..c73587c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112622.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ + +typedef __attribute__((__vector_size__(4))) float V; + +V v = (float)-v; /* { dg-error "vector value used" } */ diff --git a/gcc/testsuite/gcc.dg/pr112673.c b/gcc/testsuite/gcc.dg/pr112673.c new file mode 100644 index 0000000..531f277 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr112673.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/112673 */ +/* { dg-do compile { target bitint575 } } */ +/* { dg-options "-O3" } */ +/* { dg-additional-options "-mavx2" { target i?86-*-* x86_64-*-* } } */ + +int +foo (_BitInt(256) x) +{ + return __builtin_ctzg ((unsigned _BitInt(512)) x); +} diff --git a/gcc/testsuite/gcc.dg/simd-2.c b/gcc/testsuite/gcc.dg/simd-2.c index d24e076..411bb49 100644 --- a/gcc/testsuite/gcc.dg/simd-2.c +++ b/gcc/testsuite/gcc.dg/simd-2.c @@ -33,10 +33,10 @@ hanneke () foo = a; /* { dg-error "incompatible types when assigning" } */ /* Casted assignment between scalar and SIMD of same size. */ - foo = (typeof (foo)) foo2; /* { dg-error "aggregate value used where a floating-point was expected" } */ + foo = (typeof (foo)) foo2; /* { dg-error "vector value used where a floating-point was expected" } */ /* Casted assignment between scalar and SIMD of different size. */ - foo1 = (typeof (foo1)) foo2; /* { dg-error "aggregate value used where a floating-point was expected" } */ + foo1 = (typeof (foo1)) foo2; /* { dg-error "vector value used where a floating-point was expected" } */ /* Operators on compatible SIMD types. */ a += b + b; diff --git a/gcc/testsuite/gcc.dg/torture/addieq.c b/gcc/testsuite/gcc.dg/torture/addieq.c new file mode 100644 index 0000000..5fea38e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addieq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +int +main (void) +{ + if (addieq (-1, -1, 12, 23) != 35) + return 1; + if (addieq (-1, 3, 12, 23) != 12) + return 1; + if (addieq (1, 3, 12, 23) != 12) + return 1; + if (addieq (3, 3, 12, 23) != 35) + return 1; + if (addieq (5, 3, 12, 23) != 12) + return 1; + if (addieq (3, -1, 12, 23) != 12) + return 1; + if (addieq (3, 1, 12, 23) != 12) + return 1; + if (addieq (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addifeq.c b/gcc/testsuite/gcc.dg/torture/addifeq.c new file mode 100644 index 0000000..b3d9973 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addifeq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +int +main (void) +{ + if (addifeq (-1.0, -1.0, 12, 23) != 35) + return 1; + if (addifeq (-1.0, 3.0, 12, 23) != 12) + return 1; + if (addifeq (1.0, 3.0, 12, 23) != 12) + return 1; + if (addifeq (3.0, 3.0, 12, 23) != 35) + return 1; + if (addifeq (5.0, 3.0, 12, 23) != 12) + return 1; + if (addifeq (3.0, -1.0, 12, 23) != 12) + return 1; + if (addifeq (3.0, 1.0, 12, 23) != 12) + return 1; + if (addifeq (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addifge.c b/gcc/testsuite/gcc.dg/torture/addifge.c new file mode 100644 index 0000000..b719a3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addifge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addifge (-1.0, -1.0, 12, 23) != 35) + return 1; + if (addifge (-1.0, 3.0, 12, 23) != 12) + return 1; + if (addifge (1.0, 3.0, 12, 23) != 12) + return 1; + if (addifge (3.0, 3.0, 12, 23) != 35) + return 1; + if (addifge (5.0, 3.0, 12, 23) != 35) + return 1; + if (addifge (3.0, -1.0, 12, 23) != 35) + return 1; + if (addifge (3.0, 1.0, 12, 23) != 35) + return 1; + if (addifge (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addifgt.c b/gcc/testsuite/gcc.dg/torture/addifgt.c new file mode 100644 index 0000000..5ad591a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addifgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addifgt (-1.0, -1.0, 12, 23) != 12) + return 1; + if (addifgt (-1.0, 3.0, 12, 23) != 12) + return 1; + if (addifgt (1.0, 3.0, 12, 23) != 12) + return 1; + if (addifgt (3.0, 3.0, 12, 23) != 12) + return 1; + if (addifgt (5.0, 3.0, 12, 23) != 35) + return 1; + if (addifgt (3.0, -1.0, 12, 23) != 35) + return 1; + if (addifgt (3.0, 1.0, 12, 23) != 35) + return 1; + if (addifgt (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addifle.c b/gcc/testsuite/gcc.dg/torture/addifle.c new file mode 100644 index 0000000..7353f40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addifle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addifle (-1.0, -1.0, 12, 23) != 35) + return 1; + if (addifle (-1.0, 3.0, 12, 23) != 35) + return 1; + if (addifle (1.0, 3.0, 12, 23) != 35) + return 1; + if (addifle (3.0, 3.0, 12, 23) != 35) + return 1; + if (addifle (5.0, 3.0, 12, 23) != 12) + return 1; + if (addifle (3.0, -1.0, 12, 23) != 12) + return 1; + if (addifle (3.0, 1.0, 12, 23) != 12) + return 1; + if (addifle (3.0, 5.0, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addiflt.c b/gcc/testsuite/gcc.dg/torture/addiflt.c new file mode 100644 index 0000000..0bdd6d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addiflt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addiflt (-1.0, -1.0, 12, 23) != 12) + return 1; + if (addiflt (-1.0, 3.0, 12, 23) != 35) + return 1; + if (addiflt (1.0, 3.0, 12, 23) != 35) + return 1; + if (addiflt (3.0, 3.0, 12, 23) != 12) + return 1; + if (addiflt (5.0, 3.0, 12, 23) != 12) + return 1; + if (addiflt (3.0, -1.0, 12, 23) != 12) + return 1; + if (addiflt (3.0, 1.0, 12, 23) != 12) + return 1; + if (addiflt (3.0, 5.0, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addifne.c b/gcc/testsuite/gcc.dg/torture/addifne.c new file mode 100644 index 0000000..3e53709 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addifne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +int +main (void) +{ + if (addifne (-1.0, -1.0, 12, 23) != 12) + return 1; + if (addifne (-1.0, 3.0, 12, 23) != 35) + return 1; + if (addifne (1.0, 3.0, 12, 23) != 35) + return 1; + if (addifne (3.0, 3.0, 12, 23) != 12) + return 1; + if (addifne (5.0, 3.0, 12, 23) != 35) + return 1; + if (addifne (3.0, -1.0, 12, 23) != 35) + return 1; + if (addifne (3.0, 1.0, 12, 23) != 35) + return 1; + if (addifne (3.0, 5.0, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addige.c b/gcc/testsuite/gcc.dg/torture/addige.c new file mode 100644 index 0000000..79b4528 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addige.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addige (-1, -1, 12, 23) != 35) + return 1; + if (addige (-1, 3, 12, 23) != 12) + return 1; + if (addige (1, 3, 12, 23) != 12) + return 1; + if (addige (3, 3, 12, 23) != 35) + return 1; + if (addige (5, 3, 12, 23) != 35) + return 1; + if (addige (3, -1, 12, 23) != 35) + return 1; + if (addige (3, 1, 12, 23) != 35) + return 1; + if (addige (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addigeu.c b/gcc/testsuite/gcc.dg/torture/addigeu.c new file mode 100644 index 0000000..59bb615 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addigeu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +addigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addigeu (-1, -1, 12, 23) != 35) + return 1; + if (addigeu (-1, 3, 12, 23) != 35) + return 1; + if (addigeu (1, 3, 12, 23) != 12) + return 1; + if (addigeu (3, 3, 12, 23) != 35) + return 1; + if (addigeu (5, 3, 12, 23) != 35) + return 1; + if (addigeu (3, -1, 12, 23) != 12) + return 1; + if (addigeu (3, 1, 12, 23) != 35) + return 1; + if (addigeu (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addigt.c b/gcc/testsuite/gcc.dg/torture/addigt.c new file mode 100644 index 0000000..8c90e5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addigt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addigt (-1, -1, 12, 23) != 12) + return 1; + if (addigt (-1, 3, 12, 23) != 12) + return 1; + if (addigt (1, 3, 12, 23) != 12) + return 1; + if (addigt (3, 3, 12, 23) != 12) + return 1; + if (addigt (5, 3, 12, 23) != 35) + return 1; + if (addigt (3, -1, 12, 23) != 35) + return 1; + if (addigt (3, 1, 12, 23) != 35) + return 1; + if (addigt (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addigtu.c b/gcc/testsuite/gcc.dg/torture/addigtu.c new file mode 100644 index 0000000..1837ad6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addigtu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +addigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addigtu (-1, -1, 12, 23) != 12) + return 1; + if (addigtu (-1, 3, 12, 23) != 35) + return 1; + if (addigtu (1, 3, 12, 23) != 12) + return 1; + if (addigtu (3, 3, 12, 23) != 12) + return 1; + if (addigtu (5, 3, 12, 23) != 35) + return 1; + if (addigtu (3, -1, 12, 23) != 12) + return 1; + if (addigtu (3, 1, 12, 23) != 35) + return 1; + if (addigtu (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addile.c b/gcc/testsuite/gcc.dg/torture/addile.c new file mode 100644 index 0000000..9e436b9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addile.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addile (-1, -1, 12, 23) != 35) + return 1; + if (addile (-1, 3, 12, 23) != 35) + return 1; + if (addile (1, 3, 12, 23) != 35) + return 1; + if (addile (3, 3, 12, 23) != 35) + return 1; + if (addile (5, 3, 12, 23) != 12) + return 1; + if (addile (3, -1, 12, 23) != 12) + return 1; + if (addile (3, 1, 12, 23) != 12) + return 1; + if (addile (3, 5, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addileu.c b/gcc/testsuite/gcc.dg/torture/addileu.c new file mode 100644 index 0000000..a70bacb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addileu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +addileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addileu (-1, -1, 12, 23) != 35) + return 1; + if (addileu (-1, 3, 12, 23) != 12) + return 1; + if (addileu (1, 3, 12, 23) != 35) + return 1; + if (addileu (3, 3, 12, 23) != 35) + return 1; + if (addileu (5, 3, 12, 23) != 12) + return 1; + if (addileu (3, -1, 12, 23) != 35) + return 1; + if (addileu (3, 1, 12, 23) != 12) + return 1; + if (addileu (3, 5, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addilt.c b/gcc/testsuite/gcc.dg/torture/addilt.c new file mode 100644 index 0000000..1573915 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addilt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addilt (-1, -1, 12, 23) != 12) + return 1; + if (addilt (-1, 3, 12, 23) != 35) + return 1; + if (addilt (1, 3, 12, 23) != 35) + return 1; + if (addilt (3, 3, 12, 23) != 12) + return 1; + if (addilt (5, 3, 12, 23) != 12) + return 1; + if (addilt (3, -1, 12, 23) != 12) + return 1; + if (addilt (3, 1, 12, 23) != 12) + return 1; + if (addilt (3, 5, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addiltu.c b/gcc/testsuite/gcc.dg/torture/addiltu.c new file mode 100644 index 0000000..3db7065 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addiltu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +addiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addiltu (-1, -1, 12, 23) != 12) + return 1; + if (addiltu (-1, 3, 12, 23) != 12) + return 1; + if (addiltu (1, 3, 12, 23) != 35) + return 1; + if (addiltu (3, 3, 12, 23) != 12) + return 1; + if (addiltu (5, 3, 12, 23) != 12) + return 1; + if (addiltu (3, -1, 12, 23) != 35) + return 1; + if (addiltu (3, 1, 12, 23) != 12) + return 1; + if (addiltu (3, 5, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addine.c b/gcc/testsuite/gcc.dg/torture/addine.c new file mode 100644 index 0000000..505d815 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addine.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +addine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +int +main (void) +{ + if (addine (-1, -1, 12, 23) != 12) + return 1; + if (addine (-1, 3, 12, 23) != 35) + return 1; + if (addine (1, 3, 12, 23) != 35) + return 1; + if (addine (3, 3, 12, 23) != 12) + return 1; + if (addine (5, 3, 12, 23) != 35) + return 1; + if (addine (3, -1, 12, 23) != 35) + return 1; + if (addine (3, 1, 12, 23) != 35) + return 1; + if (addine (3, 5, 12, 23) != 35) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addleq.c b/gcc/testsuite/gcc.dg/torture/addleq.c new file mode 100644 index 0000000..02ac6d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addleq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addleq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +int +main (void) +{ + if (addleq (-1L, -1L, 12L, 23L) != 35L) + return 1; + if (addleq (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (addleq (1L, 3L, 12L, 23L) != 12L) + return 1; + if (addleq (3L, 3L, 12L, 23L) != 35L) + return 1; + if (addleq (5L, 3L, 12L, 23L) != 12L) + return 1; + if (addleq (3L, -1L, 12L, 23L) != 12L) + return 1; + if (addleq (3L, 1L, 12L, 23L) != 12L) + return 1; + if (addleq (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlfeq.c b/gcc/testsuite/gcc.dg/torture/addlfeq.c new file mode 100644 index 0000000..ca95f78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlfeq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlfeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +int +main (void) +{ + if (addlfeq (-1.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfeq (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfeq (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfeq (3.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfeq (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfeq (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlfeq (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (addlfeq (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlfge.c b/gcc/testsuite/gcc.dg/torture/addlfge.c new file mode 100644 index 0000000..b63de69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlfge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlfge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addlfge (-1.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfge (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfge (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfge (3.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfge (5.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfge (3.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfge (3.0, 1.0, 12L, 23L) != 35L) + return 1; + if (addlfge (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlfgt.c b/gcc/testsuite/gcc.dg/torture/addlfgt.c new file mode 100644 index 0000000..1077cc0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlfgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlfgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addlfgt (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlfgt (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfgt (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfgt (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfgt (5.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfgt (3.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfgt (3.0, 1.0, 12L, 23L) != 35L) + return 1; + if (addlfgt (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlfle.c b/gcc/testsuite/gcc.dg/torture/addlfle.c new file mode 100644 index 0000000..0fd8128 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlfle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlfle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addlfle (-1.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfle (-1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfle (1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfle (3.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfle (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfle (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlfle (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (addlfle (3.0, 5.0, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlflt.c b/gcc/testsuite/gcc.dg/torture/addlflt.c new file mode 100644 index 0000000..cc4cb45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlflt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addlflt (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlflt (-1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlflt (1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlflt (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlflt (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlflt (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlflt (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (addlflt (3.0, 5.0, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlfne.c b/gcc/testsuite/gcc.dg/torture/addlfne.c new file mode 100644 index 0000000..f8018dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlfne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlfne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +int +main (void) +{ + if (addlfne (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (addlfne (-1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfne (1.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfne (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (addlfne (5.0, 3.0, 12L, 23L) != 35L) + return 1; + if (addlfne (3.0, -1.0, 12L, 23L) != 35L) + return 1; + if (addlfne (3.0, 1.0, 12L, 23L) != 35L) + return 1; + if (addlfne (3.0, 5.0, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlge.c b/gcc/testsuite/gcc.dg/torture/addlge.c new file mode 100644 index 0000000..f23773e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlge (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addlge (-1L, -1L, 12L, 23L) != 35L) + return 1; + if (addlge (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlge (1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlge (3L, 3L, 12L, 23L) != 35L) + return 1; + if (addlge (5L, 3L, 12L, 23L) != 35L) + return 1; + if (addlge (3L, -1L, 12L, 23L) != 35L) + return 1; + if (addlge (3L, 1L, 12L, 23L) != 35L) + return 1; + if (addlge (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlgeu.c b/gcc/testsuite/gcc.dg/torture/addlgeu.c new file mode 100644 index 0000000..254bb57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlgeu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +addlgeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +int +main (void) +{ + if (addlgeu (-1L, -1L, 12L, 23L) != 35L) + return 1; + if (addlgeu (-1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgeu (1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgeu (3L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgeu (5L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgeu (3L, -1L, 12L, 23L) != 12L) + return 1; + if (addlgeu (3L, 1L, 12L, 23L) != 35L) + return 1; + if (addlgeu (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlgt.c b/gcc/testsuite/gcc.dg/torture/addlgt.c new file mode 100644 index 0000000..0bd0fe1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlgt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addlgt (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (addlgt (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgt (1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgt (3L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgt (5L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgt (3L, -1L, 12L, 23L) != 35L) + return 1; + if (addlgt (3L, 1L, 12L, 23L) != 35L) + return 1; + if (addlgt (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlgtu.c b/gcc/testsuite/gcc.dg/torture/addlgtu.c new file mode 100644 index 0000000..20e7e02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlgtu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +addlgtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +int +main (void) +{ + if (addlgtu (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (addlgtu (-1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgtu (1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgtu (3L, 3L, 12L, 23L) != 12L) + return 1; + if (addlgtu (5L, 3L, 12L, 23L) != 35L) + return 1; + if (addlgtu (3L, -1L, 12L, 23L) != 12L) + return 1; + if (addlgtu (3L, 1L, 12L, 23L) != 35L) + return 1; + if (addlgtu (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlle.c b/gcc/testsuite/gcc.dg/torture/addlle.c new file mode 100644 index 0000000..108e072 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlle (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addlle (-1L, -1L, 12L, 23L) != 35L) + return 1; + if (addlle (-1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlle (1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlle (3L, 3L, 12L, 23L) != 35L) + return 1; + if (addlle (5L, 3L, 12L, 23L) != 12L) + return 1; + if (addlle (3L, -1L, 12L, 23L) != 12L) + return 1; + if (addlle (3L, 1L, 12L, 23L) != 12L) + return 1; + if (addlle (3L, 5L, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlleu.c b/gcc/testsuite/gcc.dg/torture/addlleu.c new file mode 100644 index 0000000..b7542cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlleu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +addlleu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +int +main (void) +{ + if (addlleu (-1L, -1L, 12L, 23L) != 35L) + return 1; + if (addlleu (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlleu (1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlleu (3L, 3L, 12L, 23L) != 35L) + return 1; + if (addlleu (5L, 3L, 12L, 23L) != 12L) + return 1; + if (addlleu (3L, -1L, 12L, 23L) != 35L) + return 1; + if (addlleu (3L, 1L, 12L, 23L) != 12L) + return 1; + if (addlleu (3L, 5L, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addllt.c b/gcc/testsuite/gcc.dg/torture/addllt.c new file mode 100644 index 0000000..b76ef8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addllt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addllt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addllt (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (addllt (-1L, 3L, 12L, 23L) != 35L) + return 1; + if (addllt (1L, 3L, 12L, 23L) != 35L) + return 1; + if (addllt (3L, 3L, 12L, 23L) != 12L) + return 1; + if (addllt (5L, 3L, 12L, 23L) != 12L) + return 1; + if (addllt (3L, -1L, 12L, 23L) != 12L) + return 1; + if (addllt (3L, 1L, 12L, 23L) != 12L) + return 1; + if (addllt (3L, 5L, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlltu.c b/gcc/testsuite/gcc.dg/torture/addlltu.c new file mode 100644 index 0000000..e4c1ad7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlltu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +addlltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +int +main (void) +{ + if (addlltu (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (addlltu (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (addlltu (1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlltu (3L, 3L, 12L, 23L) != 12L) + return 1; + if (addlltu (5L, 3L, 12L, 23L) != 12L) + return 1; + if (addlltu (3L, -1L, 12L, 23L) != 35L) + return 1; + if (addlltu (3L, 1L, 12L, 23L) != 12L) + return 1; + if (addlltu (3L, 5L, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/addlne.c b/gcc/testsuite/gcc.dg/torture/addlne.c new file mode 100644 index 0000000..9be07ab --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/addlne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +addlne (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +int +main (void) +{ + if (addlne (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (addlne (-1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlne (1L, 3L, 12L, 23L) != 35L) + return 1; + if (addlne (3L, 3L, 12L, 23L) != 12L) + return 1; + if (addlne (5L, 3L, 12L, 23L) != 35L) + return 1; + if (addlne (3L, -1L, 12L, 23L) != 35L) + return 1; + if (addlne (3L, 1L, 12L, 23L) != 35L) + return 1; + if (addlne (3L, 5L, 12L, 23L) != 35L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movieq.c b/gcc/testsuite/gcc.dg/torture/movieq.c new file mode 100644 index 0000000..966dd5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movieq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +int +main (void) +{ + if (movieq (-1, -1, 12, 23) != 12) + return 1; + if (movieq (-1, 3, 12, 23) != 23) + return 1; + if (movieq (1, 3, 12, 23) != 23) + return 1; + if (movieq (3, 3, 12, 23) != 12) + return 1; + if (movieq (5, 3, 12, 23) != 23) + return 1; + if (movieq (3, -1, 12, 23) != 23) + return 1; + if (movieq (3, 1, 12, 23) != 23) + return 1; + if (movieq (3, 5, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movifeq.c b/gcc/testsuite/gcc.dg/torture/movifeq.c new file mode 100644 index 0000000..7f143e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movifeq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +int +main (void) +{ + if (movifeq (-1.0, -1.0, 12, 23) != 12) + return 1; + if (movifeq (-1.0, 3.0, 12, 23) != 23) + return 1; + if (movifeq (1.0, 3.0, 12, 23) != 23) + return 1; + if (movifeq (3.0, 3.0, 12, 23) != 12) + return 1; + if (movifeq (5.0, 3.0, 12, 23) != 23) + return 1; + if (movifeq (3.0, -1.0, 12, 23) != 23) + return 1; + if (movifeq (3.0, 1.0, 12, 23) != 23) + return 1; + if (movifeq (3.0, 5.0, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movifge.c b/gcc/testsuite/gcc.dg/torture/movifge.c new file mode 100644 index 0000000..af19043 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movifge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movifge (-1.0, -1.0, 12, 23) != 12) + return 1; + if (movifge (-1.0, 3.0, 12, 23) != 23) + return 1; + if (movifge (1.0, 3.0, 12, 23) != 23) + return 1; + if (movifge (3.0, 3.0, 12, 23) != 12) + return 1; + if (movifge (5.0, 3.0, 12, 23) != 12) + return 1; + if (movifge (3.0, -1.0, 12, 23) != 12) + return 1; + if (movifge (3.0, 1.0, 12, 23) != 12) + return 1; + if (movifge (3.0, 5.0, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movifgt.c b/gcc/testsuite/gcc.dg/torture/movifgt.c new file mode 100644 index 0000000..bf8563f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movifgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movifgt (-1.0, -1.0, 12, 23) != 23) + return 1; + if (movifgt (-1.0, 3.0, 12, 23) != 23) + return 1; + if (movifgt (1.0, 3.0, 12, 23) != 23) + return 1; + if (movifgt (3.0, 3.0, 12, 23) != 23) + return 1; + if (movifgt (5.0, 3.0, 12, 23) != 12) + return 1; + if (movifgt (3.0, -1.0, 12, 23) != 12) + return 1; + if (movifgt (3.0, 1.0, 12, 23) != 12) + return 1; + if (movifgt (3.0, 5.0, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movifle.c b/gcc/testsuite/gcc.dg/torture/movifle.c new file mode 100644 index 0000000..c925804 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movifle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movifle (-1.0, -1.0, 12, 23) != 12) + return 1; + if (movifle (-1.0, 3.0, 12, 23) != 12) + return 1; + if (movifle (1.0, 3.0, 12, 23) != 12) + return 1; + if (movifle (3.0, 3.0, 12, 23) != 12) + return 1; + if (movifle (5.0, 3.0, 12, 23) != 23) + return 1; + if (movifle (3.0, -1.0, 12, 23) != 23) + return 1; + if (movifle (3.0, 1.0, 12, 23) != 23) + return 1; + if (movifle (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/moviflt.c b/gcc/testsuite/gcc.dg/torture/moviflt.c new file mode 100644 index 0000000..25f3ad4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/moviflt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +moviflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (moviflt (-1.0, -1.0, 12, 23) != 23) + return 1; + if (moviflt (-1.0, 3.0, 12, 23) != 12) + return 1; + if (moviflt (1.0, 3.0, 12, 23) != 12) + return 1; + if (moviflt (3.0, 3.0, 12, 23) != 23) + return 1; + if (moviflt (5.0, 3.0, 12, 23) != 23) + return 1; + if (moviflt (3.0, -1.0, 12, 23) != 23) + return 1; + if (moviflt (3.0, 1.0, 12, 23) != 23) + return 1; + if (moviflt (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movifne.c b/gcc/testsuite/gcc.dg/torture/movifne.c new file mode 100644 index 0000000..6e76df3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movifne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +int +main (void) +{ + if (movifne (-1.0, -1.0, 12, 23) != 23) + return 1; + if (movifne (-1.0, 3.0, 12, 23) != 12) + return 1; + if (movifne (1.0, 3.0, 12, 23) != 12) + return 1; + if (movifne (3.0, 3.0, 12, 23) != 23) + return 1; + if (movifne (5.0, 3.0, 12, 23) != 12) + return 1; + if (movifne (3.0, -1.0, 12, 23) != 12) + return 1; + if (movifne (3.0, 1.0, 12, 23) != 12) + return 1; + if (movifne (3.0, 5.0, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movige.c b/gcc/testsuite/gcc.dg/torture/movige.c new file mode 100644 index 0000000..b4149b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movige.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movige (-1, -1, 12, 23) != 12) + return 1; + if (movige (-1, 3, 12, 23) != 23) + return 1; + if (movige (1, 3, 12, 23) != 23) + return 1; + if (movige (3, 3, 12, 23) != 12) + return 1; + if (movige (5, 3, 12, 23) != 12) + return 1; + if (movige (3, -1, 12, 23) != 12) + return 1; + if (movige (3, 1, 12, 23) != 12) + return 1; + if (movige (3, 5, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movigeu.c b/gcc/testsuite/gcc.dg/torture/movigeu.c new file mode 100644 index 0000000..14df122 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movigeu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +movigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movigeu (-1, -1, 12, 23) != 12) + return 1; + if (movigeu (-1, 3, 12, 23) != 12) + return 1; + if (movigeu (1, 3, 12, 23) != 23) + return 1; + if (movigeu (3, 3, 12, 23) != 12) + return 1; + if (movigeu (5, 3, 12, 23) != 12) + return 1; + if (movigeu (3, -1, 12, 23) != 23) + return 1; + if (movigeu (3, 1, 12, 23) != 12) + return 1; + if (movigeu (3, 5, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movigt.c b/gcc/testsuite/gcc.dg/torture/movigt.c new file mode 100644 index 0000000..9684013 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movigt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movigt (-1, -1, 12, 23) != 23) + return 1; + if (movigt (-1, 3, 12, 23) != 23) + return 1; + if (movigt (1, 3, 12, 23) != 23) + return 1; + if (movigt (3, 3, 12, 23) != 23) + return 1; + if (movigt (5, 3, 12, 23) != 12) + return 1; + if (movigt (3, -1, 12, 23) != 12) + return 1; + if (movigt (3, 1, 12, 23) != 12) + return 1; + if (movigt (3, 5, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movigtu.c b/gcc/testsuite/gcc.dg/torture/movigtu.c new file mode 100644 index 0000000..d620e8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movigtu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +movigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movigtu (-1, -1, 12, 23) != 23) + return 1; + if (movigtu (-1, 3, 12, 23) != 12) + return 1; + if (movigtu (1, 3, 12, 23) != 23) + return 1; + if (movigtu (3, 3, 12, 23) != 23) + return 1; + if (movigtu (5, 3, 12, 23) != 12) + return 1; + if (movigtu (3, -1, 12, 23) != 23) + return 1; + if (movigtu (3, 1, 12, 23) != 12) + return 1; + if (movigtu (3, 5, 12, 23) != 23) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movile.c b/gcc/testsuite/gcc.dg/torture/movile.c new file mode 100644 index 0000000..c637d4f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movile.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movile (-1, -1, 12, 23) != 12) + return 1; + if (movile (-1, 3, 12, 23) != 12) + return 1; + if (movile (1, 3, 12, 23) != 12) + return 1; + if (movile (3, 3, 12, 23) != 12) + return 1; + if (movile (5, 3, 12, 23) != 23) + return 1; + if (movile (3, -1, 12, 23) != 23) + return 1; + if (movile (3, 1, 12, 23) != 23) + return 1; + if (movile (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movileu.c b/gcc/testsuite/gcc.dg/torture/movileu.c new file mode 100644 index 0000000..ead6555 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movileu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +movileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movileu (-1, -1, 12, 23) != 12) + return 1; + if (movileu (-1, 3, 12, 23) != 23) + return 1; + if (movileu (1, 3, 12, 23) != 12) + return 1; + if (movileu (3, 3, 12, 23) != 12) + return 1; + if (movileu (5, 3, 12, 23) != 23) + return 1; + if (movileu (3, -1, 12, 23) != 12) + return 1; + if (movileu (3, 1, 12, 23) != 23) + return 1; + if (movileu (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movilt.c b/gcc/testsuite/gcc.dg/torture/movilt.c new file mode 100644 index 0000000..3ff3b7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movilt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (movilt (-1, -1, 12, 23) != 23) + return 1; + if (movilt (-1, 3, 12, 23) != 12) + return 1; + if (movilt (1, 3, 12, 23) != 12) + return 1; + if (movilt (3, 3, 12, 23) != 23) + return 1; + if (movilt (5, 3, 12, 23) != 23) + return 1; + if (movilt (3, -1, 12, 23) != 23) + return 1; + if (movilt (3, 1, 12, 23) != 23) + return 1; + if (movilt (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/moviltu.c b/gcc/testsuite/gcc.dg/torture/moviltu.c new file mode 100644 index 0000000..9679e37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/moviltu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned int int_t; + +__attribute__ ((noinline)) int_t +moviltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (moviltu (-1, -1, 12, 23) != 23) + return 1; + if (moviltu (-1, 3, 12, 23) != 23) + return 1; + if (moviltu (1, 3, 12, 23) != 12) + return 1; + if (moviltu (3, 3, 12, 23) != 23) + return 1; + if (moviltu (5, 3, 12, 23) != 23) + return 1; + if (moviltu (3, -1, 12, 23) != 12) + return 1; + if (moviltu (3, 1, 12, 23) != 23) + return 1; + if (moviltu (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movine.c b/gcc/testsuite/gcc.dg/torture/movine.c new file mode 100644 index 0000000..fc6f9b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movine.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef int int_t; + +__attribute__ ((noinline)) int_t +movine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +int +main (void) +{ + if (movine (-1, -1, 12, 23) != 23) + return 1; + if (movine (-1, 3, 12, 23) != 12) + return 1; + if (movine (1, 3, 12, 23) != 12) + return 1; + if (movine (3, 3, 12, 23) != 23) + return 1; + if (movine (5, 3, 12, 23) != 12) + return 1; + if (movine (3, -1, 12, 23) != 12) + return 1; + if (movine (3, 1, 12, 23) != 12) + return 1; + if (movine (3, 5, 12, 23) != 12) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movleq.c b/gcc/testsuite/gcc.dg/torture/movleq.c new file mode 100644 index 0000000..2c773fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movleq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movleq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +int +main (void) +{ + if (movleq (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (movleq (-1L, 3L, 12L, 23L) != 23L) + return 1; + if (movleq (1L, 3L, 12L, 23L) != 23L) + return 1; + if (movleq (3L, 3L, 12L, 23L) != 12L) + return 1; + if (movleq (5L, 3L, 12L, 23L) != 23L) + return 1; + if (movleq (3L, -1L, 12L, 23L) != 23L) + return 1; + if (movleq (3L, 1L, 12L, 23L) != 23L) + return 1; + if (movleq (3L, 5L, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlfeq.c b/gcc/testsuite/gcc.dg/torture/movlfeq.c new file mode 100644 index 0000000..96c3efc --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlfeq.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlfeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +int +main (void) +{ + if (movlfeq (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfeq (-1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfeq (1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfeq (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfeq (5.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfeq (3.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlfeq (3.0, 1.0, 12L, 23L) != 23L) + return 1; + if (movlfeq (3.0, 5.0, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlfge.c b/gcc/testsuite/gcc.dg/torture/movlfge.c new file mode 100644 index 0000000..118c0a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlfge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlfge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movlfge (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfge (-1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfge (1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfge (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfge (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfge (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfge (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (movlfge (3.0, 5.0, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlfgt.c b/gcc/testsuite/gcc.dg/torture/movlfgt.c new file mode 100644 index 0000000..48ab58b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlfgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlfgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movlfgt (-1.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlfgt (-1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfgt (1.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfgt (3.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfgt (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfgt (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfgt (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (movlfgt (3.0, 5.0, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlfle.c b/gcc/testsuite/gcc.dg/torture/movlfle.c new file mode 100644 index 0000000..940a7e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlfle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlfle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movlfle (-1.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfle (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfle (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfle (3.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfle (5.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfle (3.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlfle (3.0, 1.0, 12L, 23L) != 23L) + return 1; + if (movlfle (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlflt.c b/gcc/testsuite/gcc.dg/torture/movlflt.c new file mode 100644 index 0000000..fc7f102 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlflt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (movlflt (-1.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlflt (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlflt (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlflt (3.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlflt (5.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlflt (3.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlflt (3.0, 1.0, 12L, 23L) != 23L) + return 1; + if (movlflt (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlfne.c b/gcc/testsuite/gcc.dg/torture/movlfne.c new file mode 100644 index 0000000..088fa25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlfne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlfne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +int +main (void) +{ + if (movlfne (-1.0, -1.0, 12L, 23L) != 23L) + return 1; + if (movlfne (-1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfne (1.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfne (3.0, 3.0, 12L, 23L) != 23L) + return 1; + if (movlfne (5.0, 3.0, 12L, 23L) != 12L) + return 1; + if (movlfne (3.0, -1.0, 12L, 23L) != 12L) + return 1; + if (movlfne (3.0, 1.0, 12L, 23L) != 12L) + return 1; + if (movlfne (3.0, 5.0, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlge.c b/gcc/testsuite/gcc.dg/torture/movlge.c new file mode 100644 index 0000000..34798e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlge.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlge (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movlge (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (movlge (-1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlge (1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlge (3L, 3L, 12L, 23L) != 12L) + return 1; + if (movlge (5L, 3L, 12L, 23L) != 12L) + return 1; + if (movlge (3L, -1L, 12L, 23L) != 12L) + return 1; + if (movlge (3L, 1L, 12L, 23L) != 12L) + return 1; + if (movlge (3L, 5L, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlgeu.c b/gcc/testsuite/gcc.dg/torture/movlgeu.c new file mode 100644 index 0000000..2895556 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlgeu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +movlgeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +int +main (void) +{ + if (movlgeu (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (movlgeu (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgeu (1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgeu (3L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgeu (5L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgeu (3L, -1L, 12L, 23L) != 23L) + return 1; + if (movlgeu (3L, 1L, 12L, 23L) != 12L) + return 1; + if (movlgeu (3L, 5L, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlgt.c b/gcc/testsuite/gcc.dg/torture/movlgt.c new file mode 100644 index 0000000..ab6ce0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlgt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlgt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movlgt (-1L, -1L, 12L, 23L) != 23L) + return 1; + if (movlgt (-1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgt (1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgt (3L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgt (5L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgt (3L, -1L, 12L, 23L) != 12L) + return 1; + if (movlgt (3L, 1L, 12L, 23L) != 12L) + return 1; + if (movlgt (3L, 5L, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlgtu.c b/gcc/testsuite/gcc.dg/torture/movlgtu.c new file mode 100644 index 0000000..c43f04c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlgtu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +movlgtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +int +main (void) +{ + if (movlgtu (-1L, -1L, 12L, 23L) != 23L) + return 1; + if (movlgtu (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgtu (1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgtu (3L, 3L, 12L, 23L) != 23L) + return 1; + if (movlgtu (5L, 3L, 12L, 23L) != 12L) + return 1; + if (movlgtu (3L, -1L, 12L, 23L) != 23L) + return 1; + if (movlgtu (3L, 1L, 12L, 23L) != 12L) + return 1; + if (movlgtu (3L, 5L, 12L, 23L) != 23L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlle.c b/gcc/testsuite/gcc.dg/torture/movlle.c new file mode 100644 index 0000000..81a9d6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlle.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlle (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movlle (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (movlle (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlle (1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlle (3L, 3L, 12L, 23L) != 12L) + return 1; + if (movlle (5L, 3L, 12L, 23L) != 23L) + return 1; + if (movlle (3L, -1L, 12L, 23L) != 23L) + return 1; + if (movlle (3L, 1L, 12L, 23L) != 23L) + return 1; + if (movlle (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlleu.c b/gcc/testsuite/gcc.dg/torture/movlleu.c new file mode 100644 index 0000000..6d46fdb --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlleu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +movlleu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +int +main (void) +{ + if (movlleu (-1L, -1L, 12L, 23L) != 12L) + return 1; + if (movlleu (-1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlleu (1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlleu (3L, 3L, 12L, 23L) != 12L) + return 1; + if (movlleu (5L, 3L, 12L, 23L) != 23L) + return 1; + if (movlleu (3L, -1L, 12L, 23L) != 12L) + return 1; + if (movlleu (3L, 1L, 12L, 23L) != 23L) + return 1; + if (movlleu (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movllt.c b/gcc/testsuite/gcc.dg/torture/movllt.c new file mode 100644 index 0000000..ee32669 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movllt.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movllt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (movllt (-1L, -1L, 12L, 23L) != 23L) + return 1; + if (movllt (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (movllt (1L, 3L, 12L, 23L) != 12L) + return 1; + if (movllt (3L, 3L, 12L, 23L) != 23L) + return 1; + if (movllt (5L, 3L, 12L, 23L) != 23L) + return 1; + if (movllt (3L, -1L, 12L, 23L) != 23L) + return 1; + if (movllt (3L, 1L, 12L, 23L) != 23L) + return 1; + if (movllt (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlltu.c b/gcc/testsuite/gcc.dg/torture/movlltu.c new file mode 100644 index 0000000..0a854da --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlltu.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef unsigned long int_t; + +__attribute__ ((noinline)) int_t +movlltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +int +main (void) +{ + if (movlltu (-1L, -1L, 12L, 23L) != 23L) + return 1; + if (movlltu (-1L, 3L, 12L, 23L) != 23L) + return 1; + if (movlltu (1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlltu (3L, 3L, 12L, 23L) != 23L) + return 1; + if (movlltu (5L, 3L, 12L, 23L) != 23L) + return 1; + if (movlltu (3L, -1L, 12L, 23L) != 12L) + return 1; + if (movlltu (3L, 1L, 12L, 23L) != 23L) + return 1; + if (movlltu (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/movlne.c b/gcc/testsuite/gcc.dg/torture/movlne.c new file mode 100644 index 0000000..d8f81a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/movlne.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ + +typedef long int_t; + +__attribute__ ((noinline)) int_t +movlne (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +int +main (void) +{ + if (movlne (-1L, -1L, 12L, 23L) != 23L) + return 1; + if (movlne (-1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlne (1L, 3L, 12L, 23L) != 12L) + return 1; + if (movlne (3L, 3L, 12L, 23L) != 23L) + return 1; + if (movlne (5L, 3L, 12L, 23L) != 12L) + return 1; + if (movlne (3L, -1L, 12L, 23L) != 12L) + return 1; + if (movlne (3L, 1L, 12L, 23L) != 12L) + return 1; + if (movlne (3L, 5L, 12L, 23L) != 12L) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr111815.c b/gcc/testsuite/gcc.dg/torture/pr111815.c new file mode 100644 index 0000000..5e80b77 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr111815.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ + +char x[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +}; + +__attribute__ ((noinline)) char * +p (char *a, int o, int i) +{ + return a + ++o + (1 << ++i); +} + +int +main (void) +{ + if (*p (x, 0, 0) != 3) + return 1; + if (*p (x, 1, 2) != 10) + return 1; + if (*p (x, 2, 1) != 7) + return 1; + if (*p (x, 3, 3) != 20) + return 1; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr112281-1.c b/gcc/testsuite/gcc.dg/torture/pr112281-1.c new file mode 100644 index 0000000..711f566 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr112281-1.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-additional-options "-ftree-loop-distribution" } */ + +struct { + int : 8; + int a; +} b, d[4] = {{0}, {0}, {0}, {5}}; +int c, e; +int main() { + for (c = 2; c; c--) + for (e = 0; e < 2; e++) { + d[c] = b = d[c + 1]; + d[c + 1].a = 0; + } + if (b.a != 0) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr112281-2.c b/gcc/testsuite/gcc.dg/torture/pr112281-2.c new file mode 100644 index 0000000..d7671e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr112281-2.c @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-additional-options "-ftree-loop-distribution" } */ + +struct { + int : 8; + int a; +} b, d[4] = {{5}, {0}, {0}, {0}}; +int c, e; +int main() { + for (c = 0; c < 2; c++) + for (e = 0; e < 2; e++) { + d[c + 1] = b = d[c]; + d[c].a = 0; + } + if (b.a != 0) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr112344.c b/gcc/testsuite/gcc.dg/torture/pr112344.c new file mode 100644 index 0000000..c52d2c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr112344.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +int +main () +{ + long long b = 2036854775807LL; + signed char c = 3; + short d = 0; + int e = -2147483647 - 1, f; + for (f = 0; f < 7; f++) + while (e < 20) + { + e += 2; + d = c -= b; + } + if (d != 13) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr112639.c b/gcc/testsuite/gcc.dg/torture/pr112639.c new file mode 100644 index 0000000..9450d88 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr112639.c @@ -0,0 +1,34 @@ +/* PR middle-end/112639 */ +/* { dg-do run } */ + +unsigned long long b = 0; + +int +foo (void) +{ + return __builtin_clzg (b++, __SIZEOF_LONG_LONG__ * __CHAR_BIT__); +} + +int +bar (void) +{ + return __builtin_ctzg (b++, __SIZEOF_LONG_LONG__ * __CHAR_BIT__); +} + +int +main () +{ + if (foo () != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ || b != 1) + __builtin_abort (); + if (foo () != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1 || b != 2) + __builtin_abort (); + if (foo () != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 2 || b != 3) + __builtin_abort (); + b = 0; + if (bar () != __SIZEOF_LONG_LONG__ * __CHAR_BIT__ || b != 1) + __builtin_abort (); + if (bar () != 0 || b != 2) + __builtin_abort (); + if (bar () != 1 || b != 3) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c index 455f923..3f1d1e0 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-1.c @@ -1,4 +1,4 @@ -/* { dg-options "-O2 -fdump-ipa-profile" } */ +/* { dg-options "-O2 -fdump-ipa-profile -fno-ipa-vrp" } */ __attribute__ ((noinline)) int foo() diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c index e6eaeb9..eed0b1d 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c +++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-2.c @@ -1,4 +1,4 @@ -/* { dg-options "-O2 -fdump-ipa-profile" } */ +/* { dg-options "-O2 -fdump-ipa-profile -fno-ipa-vrp" } */ #include <unistd.h> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr109849.c b/gcc/testsuite/gcc.dg/tree-ssa/pr109849.c new file mode 100644 index 0000000..2d58e8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr109849.c @@ -0,0 +1,60 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sra" } */ + +struct D +{ + long a; + short b; +}; + +struct S { + struct D *b; + int c; + int s; +}; + +struct D * __attribute__((malloc)) some_realloc_function (int c); + +static void __attribute__((noinline)) +realloc_s (struct S *p) +{ + int s = p->c ? p->c * 2 : 16; + p->b = some_realloc_function (s); + p->s = s; + return; +} + +void modify (struct D *d); +int test (struct D *d); + +static struct D gd; + +int +foo (void) +{ + struct S stack; + + stack.c = 1; + stack.s = 0; + realloc_s (&stack); + stack.b[0] = gd; + stack.c = 1; + + while (stack.c) + { + struct D d = stack.b[--stack.c]; + if (test (&d)) + { + for (int i = 0; i < 8; i++) + { + if (stack.s <= stack.c + 1) + realloc_s (&stack); + modify(&d); + stack.b[stack.c++] = d; + } + } + } + return 0; +} + +/* { dg-final { scan-tree-dump "Created a replacement for stack offset" "sra"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c b/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c index c68a6f9..dd5022f3 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110269.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-ccp2 -fdump-tree-optimized" } */ +/* { dg-options "-O2 -fdump-tree-ccp2 -fdump-tree-optimized -fno-ipa-vrp" } */ void foo(void); static int a = 1, c; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112706.c b/gcc/testsuite/gcc.dg/tree-ssa/pr112706.c new file mode 100644 index 0000000..217730b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112706.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +int *ptr; +void link_error (); +void +test () +{ + int *ptr1 = ptr + 10; + int *ptr2 = ptr + 20; + if (ptr1 == ptr2) + link_error (); +} + +/* { dg-final { scan-tree-dump-not "if" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c index f05076c..3a7c03b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fdelete-null-pointer-checks -fno-thread-jumps" } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fdelete-null-pointer-checks -fno-thread-jumps -fno-ipa-vrp" } */ typedef struct { int code; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c b/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c new file mode 100644 index 0000000..9729448 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/return-value-range-1.c @@ -0,0 +1,22 @@ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-evrp-details" } */ +__attribute__ ((__noinline__)) +int a(signed char c) +{ + return c; +} +void link_error (); + +void +test(int d) +{ + if (a(d) > 200) + link_error (); +} +int +main(int argc, char **argv) +{ + test(argc); + return 0; +} +/* { dg-final { scan-tree-dump-times "Recording return range" 2 "evrp"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c index ac8c8d4..beea9ae 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c @@ -40,4 +40,5 @@ __BB(6): } -/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" { xfail ia32 } } } */ +/* Not all 32-bit systems fail this, but several do. */ +/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" { xfail ilp32 } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c index 57cb021..a97f75f 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c @@ -45,4 +45,5 @@ __BB(6): } -/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" } } */ +/* Not all 32-bit systems fail this, but several do. */ +/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" { xfail ilp32 } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c index c911a92..08f4260 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c @@ -40,4 +40,5 @@ __BB(6): } -/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" { xfail ia32 } } } */ +/* Not all 32-bit systems fail this, but several do. */ +/* { dg-final { scan-tree-dump-times "&a" 1 "ivopts" { xfail ilp32 } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-longjmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-longjmp-1.c new file mode 100644 index 0000000..fa19e76 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-longjmp-1.c @@ -0,0 +1,87 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-sra" } */ +/* { dg-require-effective-target indirect_jumps } */ + +#include <setjmp.h> + +struct S { + long *b; + int c; + int s; +}; + +static jmp_buf the_jmpbuf; +volatile short vs = 0; +long buf[16]; +long * volatile pbuf = (long *) &buf; + +static void __attribute__((noinline)) +crazy_alloc_s (struct S *p) +{ + int s = p->c ? p->c * 2 : 16; + + long *b = pbuf; + if (!b || s > 16) + { + p->s = -p->s; + vs = 127; + longjmp (the_jmpbuf, 1); + } + + __builtin_memcpy (b, p->b, p->c); + p->b = b; + p->s = s; + pbuf = 0; + return; +} + +long __attribute__((noipa)) +process (long v) +{ + return v + 1; +} + +void +foo (void) +{ + struct S stack; + + if (setjmp (the_jmpbuf)) + return; + + stack.c = 0; + crazy_alloc_s (&stack); + stack.b[0] = 1; + stack.c = 1; + + while (stack.c) + { + long l = stack.b[--stack.c]; + + if (l > 0) + { + for (int i = 0; i < 4; i++) + { + if (stack.s <= stack.c + 1) + crazy_alloc_s (&stack); + l = process (l); + stack.b[stack.c++] = l; + } + } + } + + return; +} + +int main (int argc, char **argv) +{ + vs = 0; + pbuf = (long *) &buf; + foo (); + if (vs != 127) + __builtin_abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-not "Created a replacement for stack offset" "sra"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c index 7f38e8d..f7ba16c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fno-thread-jumps" } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining -fno-thread-jumps -fno-ipa-vrp" } */ inline int ten() diff --git a/gcc/testsuite/gcc.dg/ubsan/has-feature-ubsan.c b/gcc/testsuite/gcc.dg/ubsan/has-feature-ubsan.c new file mode 100644 index 0000000..e5da1cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/has-feature-ubsan.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ +#define FEAT(x) (__has_feature (x) && __has_extension (x)) +#if !FEAT (undefined_behavior_sanitizer) +#error +#endif diff --git a/gcc/testsuite/gcc.dg/uninit-pred-9_b.c b/gcc/testsuite/gcc.dg/uninit-pred-9_b.c index 3c83d50..1877d5d 100644 --- a/gcc/testsuite/gcc.dg/uninit-pred-9_b.c +++ b/gcc/testsuite/gcc.dg/uninit-pred-9_b.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-Wuninitialized -O2" } */ +/* The param shuts up a bogus uninitialized warning at line 21. */ +/* { dg-options "-Wuninitialized -O2 --param=logical-op-non-short-circuit=0" } */ int g; void bar(); @@ -17,10 +18,10 @@ int foo (int n, int l, int m, int r) if (l > 100) if ( (n <= 9) && (m < 100) && (r < 19) ) - blah(v); /* { dg-bogus "uninitialized" "bogus warning" { xfail *-*-* } } */ + blah(v); /* { dg-bogus "uninitialized" "bogus warning" } */ if ( (n <= 8) && (m < 99) && (r < 19) ) - blah(v); /* { dg-bogus "uninitialized" "pr101674" { xfail mmix-*-* } } */ + blah(v); /* { dg-bogus "uninitialized" "pr101674" } */ return 0; } diff --git a/gcc/testsuite/gcc.dg/vla-1.c b/gcc/testsuite/gcc.dg/vla-1.c index 902166c..d16e73d 100644 --- a/gcc/testsuite/gcc.dg/vla-1.c +++ b/gcc/testsuite/gcc.dg/vla-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-g -O3 -fdump-tree-optimized -fvar-tracking-assignments -fno-selective-scheduling -fno-selective-scheduling2" } */ +/* { dg-options "-g -O3 -fdump-tree-optimized -fvar-tracking-assignments -fno-selective-scheduling -fno-selective-scheduling2 -fno-ipa-vrp" } */ int __attribute__((noinline)) f1 (int i) diff --git a/gcc/testsuite/gcc.misc-tests/help.exp b/gcc/testsuite/gcc.misc-tests/help.exp index 52b9cb0..15d618a 100644 --- a/gcc/testsuite/gcc.misc-tests/help.exp +++ b/gcc/testsuite/gcc.misc-tests/help.exp @@ -151,6 +151,8 @@ foreach cls { "ada" "c" "c++" "d" "fortran" "go" \ # Listing only excludes gives empty results. check_for_options c "--help=^joined,^separate" "" "" "" +check_for_options c "--help=hardened" "The following options are enabled by -fhardened" "" "" + if [ info exists prev_columns ] { # Reset the enviroment variable to its oriuginal value. set env(COLUMNS) $prev_columns diff --git a/gcc/testsuite/gcc.misc-tests/linkage-y.c b/gcc/testsuite/gcc.misc-tests/linkage-y.c index eaffa5e..4235325 100644 --- a/gcc/testsuite/gcc.misc-tests/linkage-y.c +++ b/gcc/testsuite/gcc.misc-tests/linkage-y.c @@ -1,8 +1,11 @@ /* 920717-y.c */ extern const char s[]; +extern int puts(const char *); +int main() { puts(s); + return 0; } diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c index b746daf..39d9142 100644 --- a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_1.c @@ -127,12 +127,12 @@ bfloat16x4_t footest (bfloat16x4_t vector0) (void) glob_bfloat_vec; (bfloat16x4_t) glob_bfloat_vec; - (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (bfloat16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'int' which has different size} } */ - (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (float16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (int32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Int32x4_t' which has different size} } */ (float32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__Float32x4_t' which has different size} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c index 779bb52..c320b00 100644 --- a/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c +++ b/gcc/testsuite/gcc.target/aarch64/bfloat16_vector_typecheck_2.c @@ -126,12 +126,12 @@ bfloat16x8_t footest (bfloat16x8_t vector0) (void) glob_bfloat_vec; (bfloat16x8_t) glob_bfloat_vec; - (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (bfloat16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'int' which has different size} } */ - (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (float16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (int32x4_t) glob_bfloat_vec; (float32x4_t) glob_bfloat_vec; diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_1.c b/gcc/testsuite/gcc.target/aarch64/ccmp_1.c index fd38b2c..9b68c07 100644 --- a/gcc/testsuite/gcc.target/aarch64/ccmp_1.c +++ b/gcc/testsuite/gcc.target/aarch64/ccmp_1.c @@ -86,8 +86,8 @@ f13 (int a, int b) /* { dg-final { scan-assembler "cmp\t(.)+35" } } */ /* { dg-final { scan-assembler-times "\tcmp\tw\[0-9\]+, 0" 4 } } */ -/* { dg-final { scan-assembler-times "fcmpe\t(.)+0\\.0" 2 } } */ -/* { dg-final { scan-assembler-times "fcmp\t(.)+0\\.0" 2 } } */ +/* { dg-final { scan-assembler-times "fcmpe\t(?:.)+0\\.0" 1 } } */ +/* { dg-final { scan-assembler-times "fcmp\t(?:.)+0\\.0" 1 } } */ /* { dg-final { scan-assembler "adds\t" } } */ /* { dg-final { scan-assembler-times "\tccmp\t" 11 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/movk.c b/gcc/testsuite/gcc.target/aarch64/movk.c index e6e4e3a..1fa1154 100644 --- a/gcc/testsuite/gcc.target/aarch64/movk.c +++ b/gcc/testsuite/gcc.target/aarch64/movk.c @@ -1,8 +1,11 @@ /* { dg-do run } */ -/* { dg-options "-O2 --save-temps -fno-inline" } */ +/* { dg-options "-O2 --save-temps" } */ extern void abort (void); +/* Note GCC can optimize this to -346565474575675 even without inlining so + mark it for noipa. */ +[[gnu::noipa]] long long int dummy_number_generator () { diff --git a/gcc/testsuite/gcc.target/aarch64/pr112406-2.c b/gcc/testsuite/gcc.target/aarch64/pr112406-2.c new file mode 100644 index 0000000..bb6e9cf --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr112406-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target { aarch64*-*-* } } } */ +/* { dg-options "-march=armv8-a+sve -Ofast" } */ + +double MADPictureC1; +extern int PictureRejected[]; +int PictureMAD_0, MADModelEstimator_n_windowSize_i, MADModelEstimator_n_windowSize_oneSampleQ; + +void MADModelEstimator_n_windowSize() { + int estimateX2 = 0; + for (; MADModelEstimator_n_windowSize_i; MADModelEstimator_n_windowSize_i++) { + if (MADModelEstimator_n_windowSize_oneSampleQ && + !PictureRejected[MADModelEstimator_n_windowSize_i]) + estimateX2 = 1; + if (!PictureRejected[MADModelEstimator_n_windowSize_i]) + MADPictureC1 += PictureMAD_0; + } + if (estimateX2) + for (;;) + ; +} diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmovl_high_1.c b/gcc/testsuite/gcc.target/aarch64/simd/vmovl_high_1.c index d45bb83..a2d09ea 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd/vmovl_high_1.c +++ b/gcc/testsuite/gcc.target/aarch64/simd/vmovl_high_1.c @@ -22,11 +22,11 @@ FUNC (int32x4_t, int64x2_t, s32) /* { dg-final { scan-assembler-times {sxtl2\tv0\.2d, v0\.4s} 1} } */ FUNC (uint8x16_t, uint16x8_t, u8) -/* { dg-final { scan-assembler-times {uxtl2\tv0\.8h, v0\.16b} 1} } */ +/* { dg-final { scan-assembler-times {zip2\tv0\.16b, v0\.16b} 1} } */ FUNC (uint16x8_t, uint32x4_t, u16) -/* { dg-final { scan-assembler-times {uxtl2\tv0\.4s, v0\.8h} 1} } */ +/* { dg-final { scan-assembler-times {zip2\tv0\.8h, v0\.8h} 1} } */ FUNC (uint32x4_t, uint64x2_t, u32) -/* { dg-final { scan-assembler-times {uxtl2\tv0\.2d, v0\.4s} 1} } */ +/* { dg-final { scan-assembler-times {zip2\tv0\.4s, v0\.4s} 1} } */ diff --git a/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x b/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x index 8968a64..869e748 100644 --- a/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x +++ b/gcc/testsuite/gcc.target/aarch64/simd/vmulx.x @@ -33,13 +33,13 @@ while (0) \ /* Functions used to return values that won't be optimised away. */ -float32_t __attribute__ ((noinline)) +float32_t __attribute__ ((noipa)) foo32 () { return 1.0; } -float64_t __attribute__ ((noinline)) +float64_t __attribute__ ((noipa)) foo64 () { return 1.0; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_asrd_1.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_asrd_1.c index aac06bd..96e9935 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/cond_asrd_1.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_asrd_1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256" } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256 --param=aarch64-autovec-preference=2" } */ #include <stdint.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_4.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_4.c index f627891..6f969a8 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_4.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_cnot_4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256" } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256 --param=aarch64-autovec-preference=2" } */ #include <stdint.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_5.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_5.c index 03a6636..e6ec515 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_5.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_unary_5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256" } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256 --param=aarch64-autovec-preference=2" } */ #include <stdint.h> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_uxt_5.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_uxt_5.c index 9a2bd8f..7ed3592 100644 --- a/gcc/testsuite/gcc.target/aarch64/sve/cond_uxt_5.c +++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_uxt_5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256" } */ +/* { dg-options "-O2 -ftree-vectorize -moverride=sve_width=256 --param=aarch64-autovec-preference=2" } */ #include <stdint.h> diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_13.c b/gcc/testsuite/gcc.target/aarch64/target_attr_13.c index d5bee3a..4bdb167 100644 --- a/gcc/testsuite/gcc.target/aarch64/target_attr_13.c +++ b/gcc/testsuite/gcc.target/aarch64/target_attr_13.c @@ -1,5 +1,5 @@ /* { dg-do assemble } */ -/* { dg-options "-O2 -march=armv8-a+crc+crypto -mcpu=generic" } */ +/* { dg-options "-O2 -mcpu=generic+crypto" } */ #include "arm_acle.h" diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c index 069a001..e6f31ba 100644 --- a/gcc/testsuite/gcc.target/aarch64/target_attr_15.c +++ b/gcc/testsuite/gcc.target/aarch64/target_attr_15.c @@ -1,5 +1,5 @@ /* { dg-do assemble } */ -/* { dg-options "-march=armv8-a+crypto -mcpu=generic -save-temps" } */ +/* { dg-options "-mcpu=generic+crypto -save-temps" } */ /* Check that "+nothing" clears the ISA flags. */ diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-1.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-1.c new file mode 100755 index 0000000..68fa9a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-1.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN unsigned +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tzip1\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tzip2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tuxtl\t} } } */ +/* { dg-final { scan-assembler-not {\tuxtl2\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-2.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-2.c new file mode 100755 index 0000000..af8a890 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-2.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN unsigned +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tzip1\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tzip2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tuxtl\t} } } */ +/* { dg-final { scan-assembler-not {\tuxtl2\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-3.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-3.c new file mode 100755 index 0000000..cdae6d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-3.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN unsigned +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-times {\tzip1\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tzip2\t} 1 } } */ +/* { dg-final { scan-assembler-not {\tuxtl\t} } } */ +/* { dg-final { scan-assembler-not {\tuxtl2\t} } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-4.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-4.c new file mode 100755 index 0000000..67944f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-4.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN signed +#define TYPE1 char +#define TYPE2 short + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-not {\tzip1\t} } } */ +/* { dg-final { scan-assembler-not {\tzip2\t} } } */ +/* { dg-final { scan-assembler-times {\tsxtl\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tsxtl2\t} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-5.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-5.c new file mode 100755 index 0000000..e691c4f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-5.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN signed +#define TYPE1 short +#define TYPE2 int + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-not {\tzip1\t} } } */ +/* { dg-final { scan-assembler-not {\tzip2\t} } } */ +/* { dg-final { scan-assembler-times {\tsxtl\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tsxtl2\t} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/uxtl-combine-6.c b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-6.c new file mode 100755 index 0000000..9383f7e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/uxtl-combine-6.c @@ -0,0 +1,20 @@ +/* { dg-do assemble } */ +/* { dg-options "-O3 --save-temps --param=vect-epilogues-nomask=0" } */ + +#pragma GCC target "+nosve" + +#define SIGN signed +#define TYPE1 int +#define TYPE2 long long + +void d2 (SIGN TYPE2 * restrict a, SIGN TYPE1 *b, int n) +{ + for (int i = 0; i < (n & -8); i++) + a[i] = b[i]; +} + +/* { dg-final { scan-assembler-not {\tzip1\t} } } */ +/* { dg-final { scan-assembler-not {\tzip2\t} } } */ +/* { dg-final { scan-assembler-times {\tsxtl\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tsxtl2\t} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_1.c b/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_1.c index f3c350b..b677180 100644 --- a/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_1.c +++ b/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_1.c @@ -130,12 +130,12 @@ bfloat16x4_t footest (bfloat16x4_t vector0) (void) glob_bfloat_vec; (bfloat16x4_t) glob_bfloat_vec; - (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (bfloat16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x4_t' to type 'int' which has different size} } */ - (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (float16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (int32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__simd128_int32_t' which has different size} } */ (float32x4_t) glob_bfloat_vec; /* { dg-error {cannot convert a value of type 'bfloat16x4_t' to vector type '__simd128_float32_t' which has different size} } */ diff --git a/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_2.c b/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_2.c index de0ade5..3c18dc5 100644 --- a/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_2.c +++ b/gcc/testsuite/gcc.target/arm/bfloat16_vector_typecheck_2.c @@ -122,12 +122,12 @@ bfloat16x8_t footest (bfloat16x8_t vector0) (void) glob_bfloat_vec; (bfloat16x8_t) glob_bfloat_vec; - (bfloat16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (bfloat16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type 'bfloat16x8_t' to type 'int' which has different size} } */ - (float16_t) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (float16_t) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (int32x4_t) glob_bfloat_vec; (float32x4_t) glob_bfloat_vec; diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f16.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f16.c index 1fa02f0..e4b4060 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f16.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f16.c @@ -18,7 +18,7 @@ extern "C" { void foo (float16_t *base, float16x8_t value) { - return vst1q_f16 (base, value); + vst1q_f16 (base, value); } @@ -31,7 +31,7 @@ foo (float16_t *base, float16x8_t value) void foo1 (float16_t *base, float16x8_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f32.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f32.c index 67cc3ae..8f42323c 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f32.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_f32.c @@ -18,7 +18,7 @@ extern "C" { void foo (float32_t *base, float32x4_t value) { - return vst1q_f32 (base, value); + vst1q_f32 (base, value); } @@ -31,7 +31,7 @@ foo (float32_t *base, float32x4_t value) void foo1 (float32_t *base, float32x4_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s16.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s16.c index 052959b..891ac41 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s16.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s16.c @@ -18,7 +18,7 @@ extern "C" { void foo (int16_t *base, int16x8_t value) { - return vst1q_s16 (base, value); + vst1q_s16 (base, value); } @@ -31,7 +31,7 @@ foo (int16_t *base, int16x8_t value) void foo1 (int16_t *base, int16x8_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s32.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s32.c index 444ad07..a28d1eb 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s32.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s32.c @@ -18,7 +18,7 @@ extern "C" { void foo (int32_t *base, int32x4_t value) { - return vst1q_s32 (base, value); + vst1q_s32 (base, value); } @@ -31,7 +31,7 @@ foo (int32_t *base, int32x4_t value) void foo1 (int32_t *base, int32x4_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s8.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s8.c index 684ff0a..81c141a 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s8.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_s8.c @@ -18,7 +18,7 @@ extern "C" { void foo (int8_t *base, int8x16_t value) { - return vst1q_s8 (base, value); + vst1q_s8 (base, value); } @@ -31,7 +31,7 @@ foo (int8_t *base, int8x16_t value) void foo1 (int8_t *base, int8x16_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u16.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u16.c index 1fea2de..b8ce7fb 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u16.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u16.c @@ -18,7 +18,7 @@ extern "C" { void foo (uint16_t *base, uint16x8_t value) { - return vst1q_u16 (base, value); + vst1q_u16 (base, value); } @@ -31,7 +31,7 @@ foo (uint16_t *base, uint16x8_t value) void foo1 (uint16_t *base, uint16x8_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u32.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u32.c index 64c43c5..1dbb555 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u32.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u32.c @@ -18,7 +18,7 @@ extern "C" { void foo (uint32_t *base, uint32x4_t value) { - return vst1q_u32 (base, value); + vst1q_u32 (base, value); } @@ -31,7 +31,7 @@ foo (uint32_t *base, uint32x4_t value) void foo1 (uint32_t *base, uint32x4_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u8.c b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u8.c index 5517611..ab22be8 100644 --- a/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u8.c +++ b/gcc/testsuite/gcc.target/arm/mve/intrinsics/vst1q_u8.c @@ -18,7 +18,7 @@ extern "C" { void foo (uint8_t *base, uint8x16_t value) { - return vst1q_u8 (base, value); + vst1q_u8 (base, value); } @@ -31,7 +31,7 @@ foo (uint8_t *base, uint8x16_t value) void foo1 (uint8_t *base, uint8x16_t value) { - return vst1q (base, value); + vst1q (base, value); } #ifdef __cplusplus diff --git a/gcc/testsuite/gcc.target/arm/pr53447-5.c b/gcc/testsuite/gcc.target/arm/pr53447-5.c index da91811..e428361 100644 --- a/gcc/testsuite/gcc.target/arm/pr53447-5.c +++ b/gcc/testsuite/gcc.target/arm/pr53447-5.c @@ -15,8 +15,6 @@ void foo(long long* p) p[9] -= p[10]; } -/* We accept neon instructions vldr.64 and vstr.64 as well. - Note: DejaGnu counts patterns with alternatives twice, - so actually there are only 10 loads and 9 stores. */ -/* { dg-final { scan-assembler-times "(ldrd|vldr\\.64)" 20 } } */ -/* { dg-final { scan-assembler-times "(strd|vstr\\.64)" 18 } } */ +/* We accept neon instructions vldr.64 and vstr.64 as well. */ +/* { dg-final { scan-assembler-times "(?:ldrd|vldr\\.64)" 10 } } */ +/* { dg-final { scan-assembler-times "(?:strd|vstr\\.64)" 9 } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-bind.c b/gcc/testsuite/gcc.target/bpf/helper-bind.c index 8dfde24..53514ba 100644 --- a/gcc/testsuite/gcc.target/bpf/helper-bind.c +++ b/gcc/testsuite/gcc.target/bpf/helper-bind.c @@ -2,7 +2,9 @@ /* { dg-options "-std=gnu99" } */ #include <stdint.h> -#include <bpf-helpers.h> + +int bpf_bind (void *ctx, void *addr, int addr_len) + __attribute__((kernel_helper(64))); void foo () diff --git a/gcc/testsuite/gcc.target/bpf/helper-bpf-redirect.c b/gcc/testsuite/gcc.target/bpf/helper-bpf-redirect.c deleted file mode 100644 index 9937d5a..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-bpf-redirect.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - uint32_t ifindex; - uint64_t flags; - - ret = bpf_redirect (ifindex, flags); -} - -/* { dg-final { scan-assembler "call\t23" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-clone-redirect.c b/gcc/testsuite/gcc.target/bpf/helper-clone-redirect.c deleted file mode 100644 index e38adbc..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-clone-redirect.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t ifindex; - uint64_t flags; - - ret = bpf_clone_redirect (skb, ifindex, flags); -} - -/* { dg-final { scan-assembler "call\t13" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-csum-diff.c b/gcc/testsuite/gcc.target/bpf/helper-csum-diff.c deleted file mode 100644 index a1c8bf5..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-csum-diff.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int64_t ret; - int32_t *to, *from; - uint64_t to_size, from_size; - int seed; - - ret = bpf_csum_diff (from, from_size, to, to_size, seed); -} - -/* { dg-final { scan-assembler "call\t28" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-csum-update.c b/gcc/testsuite/gcc.target/bpf/helper-csum-update.c deleted file mode 100644 index 4f65033..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-csum-update.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int64_t ret; - void *skb; - int csum; - - ret = bpf_csum_update (skb, csum); -} - -/* { dg-final { scan-assembler "call\t40" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-current-task-under-cgroup.c b/gcc/testsuite/gcc.target/bpf/helper-current-task-under-cgroup.c deleted file mode 100644 index 5b05378..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-current-task-under-cgroup.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *map; - uint32_t index; - - ret = bpf_current_task_under_cgroup (map, index); -} - -/* { dg-final { scan-assembler "call\t37" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-fib-lookup.c b/gcc/testsuite/gcc.target/bpf/helper-fib-lookup.c deleted file mode 100644 index 8290234..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-fib-lookup.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *params; - int plen; - uint32_t flags; - - ret = bpf_fib_lookup (ctx, params, plen, flags); -} - -/* { dg-final { scan-assembler "call\t69" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-cgroup-classid.c b/gcc/testsuite/gcc.target/bpf/helper-get-cgroup-classid.c deleted file mode 100644 index 5d85a89..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-cgroup-classid.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - void *skb; - - ret = bpf_get_cgroup_classid (skb); -} - -/* { dg-final { scan-assembler "call\t17" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-current-cgroup-id.c b/gcc/testsuite/gcc.target/bpf/helper-get-current-cgroup-id.c deleted file mode 100644 index 6f55e51..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-current-cgroup-id.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - - ret = bpf_get_current_cgroup_id (); -} - -/* { dg-final { scan-assembler "call\t80" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-current-comm.c b/gcc/testsuite/gcc.target/bpf/helper-get-current-comm.c deleted file mode 100644 index 1e25cd1..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-current-comm.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *buf; - uint32_t size_of_buf; - - ret = bpf_get_current_comm (buf, size_of_buf); -} - -/* { dg-final { scan-assembler "call\t16" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-current-pid-tgid.c b/gcc/testsuite/gcc.target/bpf/helper-get-current-pid-tgid.c deleted file mode 100644 index 1dd7a1e..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-current-pid-tgid.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - - ret = bpf_get_current_pid_tgid (); -} - -/* { dg-final { scan-assembler "call\t14" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-current-task.c b/gcc/testsuite/gcc.target/bpf/helper-get-current-task.c deleted file mode 100644 index 79344d1..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-current-task.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - - ret = bpf_get_current_task (); -} - -/* { dg-final { scan-assembler "call\t35" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-current-uid-gid.c b/gcc/testsuite/gcc.target/bpf/helper-get-current-uid-gid.c deleted file mode 100644 index b3e7261..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-current-uid-gid.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - - ret = bpf_get_current_uid_gid (); -} - -/* { dg-final { scan-assembler "call\t15" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-hash-recalc.c b/gcc/testsuite/gcc.target/bpf/helper-get-hash-recalc.c deleted file mode 100644 index e9d87ae..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-hash-recalc.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - void *skb; - - ret = bpf_get_hash_recalc (skb); -} - -/* { dg-final { scan-assembler "call\t34" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-listener-sock.c b/gcc/testsuite/gcc.target/bpf/helper-get-listener-sock.c deleted file mode 100644 index 500ba78..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-listener-sock.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret, *sk; - - ret = bpf_get_listener_sock (sk); -} - -/* { dg-final { scan-assembler "call\t98" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-local-storage.c b/gcc/testsuite/gcc.target/bpf/helper-get-local-storage.c deleted file mode 100644 index 616342c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-local-storage.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret, *map; - uint64_t flags; - - ret = bpf_get_local_storage (map, flags); -} - -/* { dg-final { scan-assembler "call\t81" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-numa-node-id.c b/gcc/testsuite/gcc.target/bpf/helper-get-numa-node-id.c deleted file mode 100644 index e6477a5..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-numa-node-id.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - - ret = bpf_get_numa_node_id (); -} - -/* { dg-final { scan-assembler "call\t42" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-prandom-u32.c b/gcc/testsuite/gcc.target/bpf/helper-get-prandom-u32.c deleted file mode 100644 index f30cafd..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-prandom-u32.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - - ret = bpf_get_prandom_u32 (); -} - -/* { dg-final { scan-assembler "call\t7" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-route-realm.c b/gcc/testsuite/gcc.target/bpf/helper-get-route-realm.c deleted file mode 100644 index b779430..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-route-realm.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - void *skb; - - ret = bpf_get_route_realm (skb); -} - -/* { dg-final { scan-assembler "call\t24" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-smp-processor-id.c b/gcc/testsuite/gcc.target/bpf/helper-get-smp-processor-id.c deleted file mode 100644 index 7d0e986..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-smp-processor-id.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - - ret = bpf_get_smp_processor_id (); -} - -/* { dg-final { scan-assembler "call\t8" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-socket-cookie.c b/gcc/testsuite/gcc.target/bpf/helper-get-socket-cookie.c deleted file mode 100644 index e6c5385..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-socket-cookie.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - void *skb; - - ret = bpf_get_socket_cookie (skb); -} - -/* { dg-final { scan-assembler "call\t46" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-socket-uid.c b/gcc/testsuite/gcc.target/bpf/helper-get-socket-uid.c deleted file mode 100644 index c1eaa2b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-socket-uid.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - void *skb; - - ret = bpf_get_socket_uid (skb); -} - -/* { dg-final { scan-assembler "call\t47" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-stack.c b/gcc/testsuite/gcc.target/bpf/helper-get-stack.c deleted file mode 100644 index cc3f6a0..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-stack.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *regs, *buf; - uint32_t size; - uint64_t flags; - - ret = bpf_get_stack (regs, buf, size, flags); -} - -/* { dg-final { scan-assembler "call\t67" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-get-stackid.c b/gcc/testsuite/gcc.target/bpf/helper-get-stackid.c deleted file mode 100644 index cc3ecb0..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-get-stackid.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *map; - uint64_t flags; - - ret = bpf_get_stackid (ctx, map, flags); -} - -/* { dg-final { scan-assembler "call\t27" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-getsockopt.c b/gcc/testsuite/gcc.target/bpf/helper-getsockopt.c deleted file mode 100644 index 3f71b6b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-getsockopt.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *bpf_socket; - int level, optname, optlen; - char *optval; - - ret = bpf_getsockopt (bpf_socket, level, - optname, optval, optlen); -} - -/* { dg-final { scan-assembler "call\t57" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-ktime-get-ns.c b/gcc/testsuite/gcc.target/bpf/helper-ktime-get-ns.c deleted file mode 100644 index 77f1661..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-ktime-get-ns.c +++ /dev/null @@ -1,14 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - ret = bpf_ktime_get_ns (); -} - -/* { dg-final { scan-assembler "call\t5" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-l3-csum-replace.c b/gcc/testsuite/gcc.target/bpf/helper-l3-csum-replace.c deleted file mode 100644 index c3f1b78..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-l3-csum-replace.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t offset; - uint64_t from, to, size; - - ret = bpf_l3_csum_replace (skb, offset, from, to, size); -} - -/* { dg-final { scan-assembler "call\t10" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-l4-csum-replace.c b/gcc/testsuite/gcc.target/bpf/helper-l4-csum-replace.c deleted file mode 100644 index fd54f0b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-l4-csum-replace.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t offset; - uint64_t from, to, size; - - ret = bpf_l4_csum_replace (skb, offset, from, to, size); -} - -/* { dg-final { scan-assembler "call\t11" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-lwt-push-encap.c b/gcc/testsuite/gcc.target/bpf/helper-lwt-push-encap.c deleted file mode 100644 index c6d82cc..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-lwt-push-encap.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *hdr; - uint32_t type, len; - - ret = bpf_lwt_push_encap (skb, type, hdr, len); -} - -/* { dg-final { scan-assembler "call\t73" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-action.c b/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-action.c deleted file mode 100644 index 2fc7e48..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-action.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *param; - uint32_t action, param_len; - - ret = bpf_lwt_seg6_action (skb, action, - param, param_len); -} - -/* { dg-final { scan-assembler "call\t76" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-adjust-srh.c b/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-adjust-srh.c deleted file mode 100644 index 762ab41..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-adjust-srh.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t offset, delta; - - ret = bpf_lwt_seg6_adjust_srh (skb, offset, delta); -} - -/* { dg-final { scan-assembler "call\t75" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-store-bytes.c b/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-store-bytes.c deleted file mode 100644 index 80a1f12..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-lwt-seg6-store-bytes.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *from; - uint32_t offset, len; - - ret = bpf_lwt_seg6_store_bytes (skb, offset, from, len); -} - -/* { dg-final { scan-assembler "call\t74" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-delete-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-delete-elem.c deleted file mode 100644 index 0200b15..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-delete-elem.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - char *key = 0; - - ret = bpf_map_delete_elem (map (), key); -} - -/* { dg-final { scan-assembler "call\t3" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-lookup-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-lookup-elem.c deleted file mode 100644 index 1d443a0..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-lookup-elem.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - char *key = 0, *value = 0; - value = bpf_map_lookup_elem (map (), key); -} - -/* { dg-final { scan-assembler "call\t1" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-peek-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-peek-elem.c deleted file mode 100644 index de833f2..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-peek-elem.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - char *value = 0; - - ret = bpf_map_peek_elem (map (), value); -} - -/* { dg-final { scan-assembler "call\t89" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-pop-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-pop-elem.c deleted file mode 100644 index 7d76f85..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-pop-elem.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - char *value = 0; - - ret = bpf_map_pop_elem (map (), value); -} - -/* { dg-final { scan-assembler "call\t88" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-push-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-push-elem.c deleted file mode 100644 index b4b2a8e..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-push-elem.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - char *value = 0; - long long flags = 0; - - ret = bpf_map_push_elem (map (), value, flags); -} - -/* { dg-final { scan-assembler "call\t87" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-map-update-elem.c b/gcc/testsuite/gcc.target/bpf/helper-map-update-elem.c deleted file mode 100644 index 6cceafe..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-map-update-elem.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - long long flags = 0; - char *key = 0, *value = 0; - - ret = bpf_map_update_elem (map (), key, value, flags); -} - -/* { dg-final { scan-assembler "call\t2" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-apply-bytes.c b/gcc/testsuite/gcc.target/bpf/helper-msg-apply-bytes.c deleted file mode 100644 index e72035c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-apply-bytes.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *msg; - uint32_t bytes; - - ret = bpf_msg_apply_bytes (msg, bytes); -} - -/* { dg-final { scan-assembler "call\t61" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-cork-bytes.c b/gcc/testsuite/gcc.target/bpf/helper-msg-cork-bytes.c deleted file mode 100644 index 350c2bf..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-cork-bytes.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *msg; - uint32_t bytes; - - ret = bpf_msg_cork_bytes (msg, bytes); -} - -/* { dg-final { scan-assembler "call\t62" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-pop-data.c b/gcc/testsuite/gcc.target/bpf/helper-msg-pop-data.c deleted file mode 100644 index 5679044..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-pop-data.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t start, pop; - uint64_t flags; - - ret = bpf_msg_pop_data (skb, start, pop, flags); -} - -/* { dg-final { scan-assembler "call\t91" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-pull-data.c b/gcc/testsuite/gcc.target/bpf/helper-msg-pull-data.c deleted file mode 100644 index 98d343b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-pull-data.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *msg; - int len; - - ret = bpf_msg_pull_data (msg, len); -} - -/* { dg-final { scan-assembler "call\t63" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-push-data.c b/gcc/testsuite/gcc.target/bpf/helper-msg-push-data.c deleted file mode 100644 index 40b9361..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-push-data.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t start, len; - uint64_t flags; - - ret = bpf_msg_push_data (skb, start, len, flags); -} - -/* { dg-final { scan-assembler "call\t90" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-hash.c b/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-hash.c deleted file mode 100644 index 6ac680c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-hash.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *msg, *map, *key; - uint64_t flags; - - ret = bpf_msg_redirect_hash (msg, map, key, - flags); -} - -/* { dg-final { scan-assembler "call\t71" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-map.c b/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-map.c deleted file mode 100644 index ed7652b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-msg-redirect-map.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *msg, *map; - uint64_t key; - uint64_t flags; - - ret = bpf_msg_redirect_map (msg, map, key, flags); -} - -/* { dg-final { scan-assembler "call\t60" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-override-return.c b/gcc/testsuite/gcc.target/bpf/helper-override-return.c deleted file mode 100644 index 5036686..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-override-return.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *regs; - uint64_t rc; - - ret = bpf_override_return (regs, rc); -} - -/* { dg-final { scan-assembler "call\t58" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-perf-event-output.c b/gcc/testsuite/gcc.target/bpf/helper-perf-event-output.c deleted file mode 100644 index 24ed565..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-perf-event-output.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *map; - uint64_t flags; - void *data; - uint64_t size; - - ret = bpf_perf_event_output (ctx, map, flags, data, size); -} - -/* { dg-final { scan-assembler "call\t25" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-perf-event-read-value.c b/gcc/testsuite/gcc.target/bpf/helper-perf-event-read-value.c deleted file mode 100644 index 6e6184f..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-perf-event-read-value.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *map, *buf; - uint64_t flags; - uint64_t buf_size; - - ret = bpf_perf_event_read_value (map, flags, buf, buf_size); -} - -/* { dg-final { scan-assembler "call\t55" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-perf-event-read.c b/gcc/testsuite/gcc.target/bpf/helper-perf-event-read.c deleted file mode 100644 index 674058d..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-perf-event-read.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - void *map; - uint64_t flags; - - ret = bpf_perf_event_read (map, flags); -} - -/* { dg-final { scan-assembler "call\t22" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-perf-prog-read-value.c b/gcc/testsuite/gcc.target/bpf/helper-perf-prog-read-value.c deleted file mode 100644 index 341a541..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-perf-prog-read-value.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *buf; - uint64_t buf_size; - - ret = bpf_perf_prog_read_value (ctx, buf, buf_size); -} - -/* { dg-final { scan-assembler "call\t56" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-probe-read-str.c b/gcc/testsuite/gcc.target/bpf/helper-probe-read-str.c deleted file mode 100644 index 02d1a07..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-probe-read-str.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - int size; - void *dst; - const void *unsafe_ptr; - - ret = bpf_probe_read_str (dst, size, unsafe_ptr); -} - -/* { dg-final { scan-assembler "call\t45" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-probe-read.c b/gcc/testsuite/gcc.target/bpf/helper-probe-read.c deleted file mode 100644 index 64261c5..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-probe-read.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *src, *dst; - uint32_t size; - - ret = bpf_probe_read (dst, size, src); -} - -/* { dg-final { scan-assembler "call\t4" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-probe-write-user.c b/gcc/testsuite/gcc.target/bpf/helper-probe-write-user.c deleted file mode 100644 index 127ae61..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-probe-write-user.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *dst, *src; - uint32_t len; - - ret = bpf_probe_write_user (dst, src, len); -} - -/* { dg-final { scan-assembler "call\t36" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-rc-keydown.c b/gcc/testsuite/gcc.target/bpf/helper-rc-keydown.c deleted file mode 100644 index dd90423..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-rc-keydown.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx; - uint32_t protocol, toggle; - uint64_t scancode; - - ret = bpf_rc_keydown (ctx, protocol, scancode, toggle); -} - -/* { dg-final { scan-assembler "call\t78" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-rc-pointer-rel.c b/gcc/testsuite/gcc.target/bpf/helper-rc-pointer-rel.c deleted file mode 100644 index ca0a5c4..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-rc-pointer-rel.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx; - int32_t rel_x, rel_y; - - ret = bpf_rc_pointer_rel (ctx, rel_x, rel_y); -} - -/* { dg-final { scan-assembler "call\t92" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-rc-repeat.c b/gcc/testsuite/gcc.target/bpf/helper-rc-repeat.c deleted file mode 100644 index 79d3b5c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-rc-repeat.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx; - - ret = bpf_rc_repeat (ctx); -} - -/* { dg-final { scan-assembler "call\t77" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-redirect-map.c b/gcc/testsuite/gcc.target/bpf/helper-redirect-map.c deleted file mode 100644 index 50b3e81..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-redirect-map.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *map; - uint32_t key; - uint64_t flags; - - ret = bpf_redirect_map (map, key, flags); -} - -/* { dg-final { scan-assembler "call\t51" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-set-hash-invalid.c b/gcc/testsuite/gcc.target/bpf/helper-set-hash-invalid.c deleted file mode 100644 index adbc41b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-set-hash-invalid.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *skb; - - bpf_set_hash_invalid (skb); -} - -/* { dg-final { scan-assembler "call\t41" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-set-hash.c b/gcc/testsuite/gcc.target/bpf/helper-set-hash.c deleted file mode 100644 index cafe539..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-set-hash.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint32_t ret; - void *skb; - uint32_t hash; - - ret = bpf_set_hash (skb, hash); -} - -/* { dg-final { scan-assembler "call\t48" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-setsockopt.c b/gcc/testsuite/gcc.target/bpf/helper-setsockopt.c deleted file mode 100644 index 930b8b2..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-setsockopt.c +++ /dev/null @@ -1,20 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *bpf_socket; - int level; - int optname; - void *optval; - int optlen; - - ret = bpf_setsockopt (bpf_socket, level, optname, optval, optlen); -} - -/* { dg-final { scan-assembler "call\t49" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-fullsock.c b/gcc/testsuite/gcc.target/bpf/helper-sk-fullsock.c deleted file mode 100644 index 9e66e94..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-fullsock.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret, *sk; - - ret = bpf_sk_fullsock (sk); -} - -/* { dg-final { scan-assembler "call\t95" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-tcp.c b/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-tcp.c deleted file mode 100644 index 9d48c4c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-tcp.c +++ /dev/null @@ -1,21 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret; - void *ctx, *tuple; - uint32_t tuple_size; - uint64_t netns, flags; - - ret = bpf_sk_lookup_tcp (ctx, - tuple, - tuple_size, - netns, flags); -} - -/* { dg-final { scan-assembler "call\t84" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-upd.c b/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-upd.c deleted file mode 100644 index f41fd32..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-lookup-upd.c +++ /dev/null @@ -1,21 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret; - void *ctx, *tuple; - uint32_t tuple_size; - uint64_t netns, flags; - - ret = bpf_sk_lookup_udp (ctx, - tuple, - tuple_size, - netns, flags); -} - -/* { dg-final { scan-assembler "call\t85" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-hash.c b/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-hash.c deleted file mode 100644 index f449b5b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-hash.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *map, *key; - uint64_t flags; - - ret = bpf_sk_redirect_hash (skb, map, key, flags); -} - -/* { dg-final { scan-assembler "call\t72" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-map.c b/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-map.c deleted file mode 100644 index 42aab8a..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-redirect-map.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *map; - uint32_t key; - uint64_t flags; - - ret = bpf_sk_redirect_map (ctx, map, key, flags); -} - -/* { dg-final { scan-assembler "call\t52" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-release.c b/gcc/testsuite/gcc.target/bpf/helper-sk-release.c deleted file mode 100644 index b01412c..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-release.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *sock; - - ret = bpf_sk_release (sock); -} - -/* { dg-final { scan-assembler "call\t86" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-select-reuseport.c b/gcc/testsuite/gcc.target/bpf/helper-sk-select-reuseport.c deleted file mode 100644 index b1a2802..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-select-reuseport.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *reuse, *map, *key; - uint64_t flags; - - ret = bpf_sk_select_reuseport (reuse, map, - key, flags); -} - -/* { dg-final { scan-assembler "call\t82" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-storage-delete.c b/gcc/testsuite/gcc.target/bpf/helper-sk-storage-delete.c deleted file mode 100644 index ea36a3d6..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-storage-delete.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *map, *sk; - - ret = bpf_sk_storage_delete (map, sk); -} - -/* { dg-final { scan-assembler "call\t108" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sk-storage-get.c b/gcc/testsuite/gcc.target/bpf/helper-sk-storage-get.c deleted file mode 100644 index 1ea0e7b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sk-storage-get.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret; - void *map, *sk, *value; - uint64_t flags; - - ret = bpf_sk_storage_get (map, sk, value, flags); -} - -/* { dg-final { scan-assembler "call\t107" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-adjust-room.c b/gcc/testsuite/gcc.target/bpf/helper-skb-adjust-room.c deleted file mode 100644 index 3bce73f..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-adjust-room.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - int32_t len_diff; - uint32_t mode; - uint64_t flags; - - ret = bpf_skb_adjust_room (skb, len_diff, mode, flags); -} - -/* { dg-final { scan-assembler "call\t50" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/skb-ancestor-cgroup-id.c b/gcc/testsuite/gcc.target/bpf/helper-skb-ancestor-cgroup-id.c index 13ccf36..693f390 100644 --- a/gcc/testsuite/gcc.target/bpf/skb-ancestor-cgroup-id.c +++ b/gcc/testsuite/gcc.target/bpf/helper-skb-ancestor-cgroup-id.c @@ -1,8 +1,10 @@ /* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ +/* { dg-options "-std=gnu99 -O2" } */ #include <stdint.h> -#include <bpf-helpers.h> + +struct __sk_buff; +static uint64_t (*bpf_skb_ancestor_cgroup_id)(struct __sk_buff *skb, int ancestor_level) = (void *) 83; void foo () diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-cgroup-id.c b/gcc/testsuite/gcc.target/bpf/helper-skb-cgroup-id.c deleted file mode 100644 index 5085c75..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-cgroup-id.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - uint64_t ret; - void *skb; - - ret = bpf_skb_cgroup_id (skb); -} - -/* { dg-final { scan-assembler "call\t79" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-change-head.c b/gcc/testsuite/gcc.target/bpf/helper-skb-change-head.c deleted file mode 100644 index 281104b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-change-head.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t len; - uint64_t flags; - - ret = bpf_skb_change_head (skb, len, flags); -} - -/* { dg-final { scan-assembler "call\t43" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-change-proto.c b/gcc/testsuite/gcc.target/bpf/helper-skb-change-proto.c deleted file mode 100644 index a41d197..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-change-proto.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - int16_t proto; - uint64_t flags; - - ret = bpf_skb_change_proto (skb, proto, flags); -} - -/* { dg-final { scan-assembler "call\t31" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-change-tail.c b/gcc/testsuite/gcc.target/bpf/helper-skb-change-tail.c deleted file mode 100644 index 2bfc5979..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-change-tail.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t len; - uint64_t flags; - - ret = bpf_skb_change_tail (skb, len, flags); -} - -/* { dg-final { scan-assembler "call\t38" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-change-type.c b/gcc/testsuite/gcc.target/bpf/helper-skb-change-type.c deleted file mode 100644 index 46a9421..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-change-type.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t type; - - ret = bpf_skb_change_type (skb, type); -} - -/* { dg-final { scan-assembler "call\t32" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-ecn-set-ce.c b/gcc/testsuite/gcc.target/bpf/helper-skb-ecn-set-ce.c deleted file mode 100644 index c028ec1..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-ecn-set-ce.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - - ret = bpf_skb_ecn_set_ce (skb); -} - -/* { dg-final { scan-assembler "call\t97" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-key.c b/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-key.c deleted file mode 100644 index aad8472..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-key.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *key; - uint32_t size; - uint64_t flags; - - ret = bpf_skb_get_tunnel_key (skb, key, size, flags); -} - -/* { dg-final { scan-assembler "call\t20" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-opt.c b/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-opt.c deleted file mode 100644 index 0b39ad7..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-get-tunnel-opt.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint8_t *opt; - uint32_t size; - - ret = bpf_skb_get_tunnel_opt (skb, opt, size); -} - -/* { dg-final { scan-assembler "call\t29" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-get-xfrm-state.c b/gcc/testsuite/gcc.target/bpf/helper-skb-get-xfrm-state.c deleted file mode 100644 index de83d91..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-get-xfrm-state.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *xfrm_state; - uint32_t index, size; - uint64_t flags; - - ret = bpf_skb_get_xfrm_state (skb, index, - xfrm_state, size, flags); -} - -/* { dg-final { scan-assembler "call\t66" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes-relative.c b/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes-relative.c deleted file mode 100644 index cd8c2c2..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes-relative.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *to; - uint32_t offset, len, start_header; - - ret = bpf_skb_load_bytes_relative (skb, offset, - to, len, - start_header); -} - -/* { dg-final { scan-assembler "call\t68" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes.c b/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes.c deleted file mode 100644 index 1e4612a..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-load-bytes.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *to; - uint32_t offset, len; - - ret = bpf_skb_load_bytes (skb, offset, to, len); -} - -/* { dg-final { scan-assembler "call\t26" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-pull-data.c b/gcc/testsuite/gcc.target/bpf/helper-skb-pull-data.c deleted file mode 100644 index 579d856..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-pull-data.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t len; - - ret = bpf_skb_pull_data (skb, len); -} - -/* { dg-final { scan-assembler "call\t39" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-key.c b/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-key.c deleted file mode 100644 index 85754fd..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-key.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *key; - uint32_t size; - uint64_t flags; - - ret = bpf_skb_set_tunnel_key (skb, key, size, flags); -} - -/* { dg-final { scan-assembler "call\t21" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-opt.c b/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-opt.c deleted file mode 100644 index 591eb48..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-set-tunnel-opt.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint8_t *opt; - uint32_t size; - - ret = bpf_skb_set_tunnel_opt (skb, opt, size); -} - -/* { dg-final { scan-assembler "call\t30" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-store-bytes.c b/gcc/testsuite/gcc.target/bpf/helper-skb-store-bytes.c deleted file mode 100644 index 17f8e02..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-store-bytes.c +++ /dev/null @@ -1,20 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - uint32_t offset; - void *from; - uint32_t len; - uint64_t flags; - - ret = bpf_skb_store_bytes (skb, offset, from, len, flags); -} - -/* { dg-final { scan-assembler "call\t9" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-under-cgroup.c b/gcc/testsuite/gcc.target/bpf/helper-skb-under-cgroup.c deleted file mode 100644 index 72adfcd..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-under-cgroup.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb, *map; - uint32_t index; - - ret = bpf_skb_under_cgroup (skb, map, index); -} - -/* { dg-final { scan-assembler "call\t33" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-pop.c b/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-pop.c deleted file mode 100644 index 4d5b347..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-pop.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - - ret = bpf_skb_vlan_pop (skb); -} - -/* { dg-final { scan-assembler "call\t19" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-push.c b/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-push.c deleted file mode 100644 index 1a43bd4..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skb-vlan-push.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skb; - int16_t vlan_proto; - uint16_t vlan_tci; - - ret = bpf_skb_vlan_push (skb, vlan_proto, vlan_tci); -} - -/* { dg-final { scan-assembler "call\t18" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-skc-lookup-tcp.c b/gcc/testsuite/gcc.target/bpf/helper-skc-lookup-tcp.c deleted file mode 100644 index 8ed2d46..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-skc-lookup-tcp.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret; - void *ctx, *tuple; - uint32_t tuple_size; - uint64_t netns, flags; - - ret = bpf_skc_lookup_tcp (ctx, tuple, - tuple_size, netns, flags); -} - -/* { dg-final { scan-assembler "call\t99" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sock-hash-update.c b/gcc/testsuite/gcc.target/bpf/helper-sock-hash-update.c deleted file mode 100644 index 81ff4dd..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sock-hash-update.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skops, *map, *key; - uint64_t flags; - - ret = bpf_sock_hash_update (skops, map, key, - flags); -} - -/* { dg-final { scan-assembler "call\t70" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sock-map-update.c b/gcc/testsuite/gcc.target/bpf/helper-sock-map-update.c deleted file mode 100644 index b263583..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sock-map-update.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *skops, *map, *key; - uint64_t flags; - - ret = bpf_sock_map_update (skops, map, key, flags); -} - -/* { dg-final { scan-assembler "call\t53" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sock-ops-cb-flags-set.c b/gcc/testsuite/gcc.target/bpf/helper-sock-ops-cb-flags-set.c deleted file mode 100644 index 7a98fa9..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sock-ops-cb-flags-set.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *bpf_sock; - int argval; - - ret = bpf_sock_ops_cb_flags_set (bpf_sock, argval); -} - -/* { dg-final { scan-assembler "call\t59" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-spin-lock.c b/gcc/testsuite/gcc.target/bpf/helper-spin-lock.c deleted file mode 100644 index 8358e88f..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-spin-lock.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *lock; - - bpf_spin_lock (lock); -} - -/* { dg-final { scan-assembler "call\t93" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-spin-unlock.c b/gcc/testsuite/gcc.target/bpf/helper-spin-unlock.c deleted file mode 100644 index 400695f..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-spin-unlock.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *lock; - - bpf_spin_unlock (lock); -} - -/* { dg-final { scan-assembler "call\t94" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-strtol.c b/gcc/testsuite/gcc.target/bpf/helper-strtol.c deleted file mode 100644 index d98a0a7..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-strtol.c +++ /dev/null @@ -1,20 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *buf; - long res; - uint64_t flags; - size_t buf_len; - - ret = bpf_strtol (buf, buf_len, flags, &res); -} - -/* { dg-final { scan-assembler "call\t105" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-strtoul.c b/gcc/testsuite/gcc.target/bpf/helper-strtoul.c deleted file mode 100644 index f68abf2..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-strtoul.c +++ /dev/null @@ -1,20 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *buf; - unsigned long res; - uint64_t flags; - size_t buf_len; - - ret = bpf_strtoul (buf, buf_len, flags, &res); -} - -/* { dg-final { scan-assembler "call\t106" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-current-value.c b/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-current-value.c deleted file mode 100644 index a1f6529..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-current-value.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *buf; - size_t buf_len; - - ret = bpf_sysctl_get_current_value (ctx, buf, buf_len); -} - -/* { dg-final { scan-assembler "call\t102" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-name.c b/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-name.c deleted file mode 100644 index ca9c42b..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-name.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *buf; - size_t buf_len; - uint64_t flags; - - ret = bpf_sysctl_get_name (ctx, buf, buf_len, flags); -} - -/* { dg-final { scan-assembler "call\t101" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-new-value.c b/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-new-value.c deleted file mode 100644 index d22b214..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sysctl-get-new-value.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *buf; - size_t buf_len; - - ret = bpf_sysctl_get_new_value (ctx, buf, buf_len); -} - -/* { dg-final { scan-assembler "call\t103" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-sysctl-set-new-value.c b/gcc/testsuite/gcc.target/bpf/helper-sysctl-set-new-value.c deleted file mode 100644 index 78004c2..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-sysctl-set-new-value.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <stddef.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *buf; - size_t buf_len; - - ret = bpf_sysctl_set_new_value (ctx, buf, buf_len); -} - -/* { dg-final { scan-assembler "call\t104" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-tail-call.c b/gcc/testsuite/gcc.target/bpf/helper-tail-call.c deleted file mode 100644 index 0f35b00..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-tail-call.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *ctx, *prog_array_map; - uint32_t index; - - ret = bpf_tail_call (ctx, prog_array_map, index); -} - -/* { dg-final { scan-assembler "call\t12" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-tcp-check-syncookie.c b/gcc/testsuite/gcc.target/bpf/helper-tcp-check-syncookie.c deleted file mode 100644 index 06210bb..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-tcp-check-syncookie.c +++ /dev/null @@ -1,19 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *sk, *iph, *th; - uint32_t iph_len, th_len; - - ret = bpf_tcp_check_syncookie (sk, iph, - iph_len, - th, th_len); -} - -/* { dg-final { scan-assembler "call\t100" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-tcp-sock.c b/gcc/testsuite/gcc.target/bpf/helper-tcp-sock.c deleted file mode 100644 index cd6d995..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-tcp-sock.c +++ /dev/null @@ -1,15 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - void *ret, *sk; - - ret = bpf_tcp_sock (sk); -} - -/* { dg-final { scan-assembler "call\t96" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-trace-printk.c b/gcc/testsuite/gcc.target/bpf/helper-trace-printk.c deleted file mode 100644 index 135ae29..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-trace-printk.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <bpf-helpers.h> - -char *map () { return 0; } - -void -foo () -{ - int ret; - - ret = bpf_trace_printk ("foo %d %d", sizeof ("foo %d %d"), 10, 20); -} - -/* { dg-final { scan-assembler "call\t6" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-head.c b/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-head.c deleted file mode 100644 index ac6fef4..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-head.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *xdp_md; - int delta; - - ret = bpf_xdp_adjust_head (xdp_md, delta); -} - -/* { dg-final { scan-assembler "call\t44" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-meta.c b/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-meta.c deleted file mode 100644 index 1379350..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-meta.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-std=gnu99" } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *xdp_md; - int delta; - - ret = bpf_xdp_adjust_meta (xdp_md, delta); -} - -/* { dg-final { scan-assembler "call\t54" } } */ diff --git a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-tail.c b/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-tail.c deleted file mode 100644 index db55168..0000000 --- a/gcc/testsuite/gcc.target/bpf/helper-xdp-adjust-tail.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ - -#include <stdint.h> -#include <bpf-helpers.h> - -void -foo () -{ - int ret; - void *xdp_md; - int delta; - - ret = bpf_xdp_adjust_tail (xdp_md, delta); -} - -/* { dg-final { scan-assembler "call\t65" } } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-interrupt-1.c b/gcc/testsuite/gcc.target/i386/apx-interrupt-1.c index 5f732d3..ffcb8fc 100644 --- a/gcc/testsuite/gcc.target/i386/apx-interrupt-1.c +++ b/gcc/testsuite/gcc.target/i386/apx-interrupt-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-mapxf -m64 -O2 -mgeneral-regs-only -mno-cld -mno-push-args -maccumulate-outgoing-args" } */ +/* { dg-options "-mapx-features=egpr -m64 -O2 -mgeneral-regs-only -mno-cld -mno-push-args -maccumulate-outgoing-args" } */ /* { dg-skip-if "does not emit .cfi_xxx" "*-*-darwin*" } */ extern void foo (void *) __attribute__ ((interrupt)); diff --git a/gcc/testsuite/gcc.target/i386/apx-ppx-1.c b/gcc/testsuite/gcc.target/i386/apx-ppx-1.c new file mode 100644 index 0000000..e9a5953 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/apx-ppx-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -mapx-features=egpr,push2pop2,ppx" } */ + +#include "apx-push2pop2-1.c" + +/* { dg-final { scan-assembler "pushp" } } */ +/* { dg-final { scan-assembler "popp" } } */ +/* { dg-final { scan-assembler "push2p" } } */ +/* { dg-final { scan-assembler "pop2p" } } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-push2pop2-1.c b/gcc/testsuite/gcc.target/i386/apx-push2pop2-1.c index 089941d..d78c96d 100644 --- a/gcc/testsuite/gcc.target/i386/apx-push2pop2-1.c +++ b/gcc/testsuite/gcc.target/i386/apx-push2pop2-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -mapxf" } */ +/* { dg-options "-O2 -mapx-features=push2pop2" } */ /* { dg-skip-if "does not emit .cfi_xxx" "*-*-darwin*" } */ extern int bar (int); @@ -24,11 +24,11 @@ void foo () /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 16" 2 } } */ /* { dg-final { scan-assembler-times "pushq\[^\n\r]*%r15(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 15, -16(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r14\[^\n\r]*%r13\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r13\[^\n\r]*%r14\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 32" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 14, -24(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 13, -32(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r12\[^\n\r]*%rbp\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%rbp\[^\n\r]*%r12\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 48" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 12, -40(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 6, -48(?:\n|\[ \\t\]+#)" 1 } } */ @@ -36,10 +36,10 @@ void foo () /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 56" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 3, -56(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "popq\[^\n\r]*rbx(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%rbp\[^\n\r]*%r12\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r12\[^\n\r]*%rbp\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 12(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 6(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r13\[^\n\r]*%r14\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r14\[^\n\r]*%r13\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 14(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 13(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "popq\[^\n\r]*%r15(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-push2pop2_force_drap-1.c b/gcc/testsuite/gcc.target/i386/apx-push2pop2_force_drap-1.c index 656ca91..3cac7b1 100644 --- a/gcc/testsuite/gcc.target/i386/apx-push2pop2_force_drap-1.c +++ b/gcc/testsuite/gcc.target/i386/apx-push2pop2_force_drap-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -mapxf -mforce-drap" } */ +/* { dg-options "-O2 -mapx-features=push2pop2 -mforce-drap" } */ /* { dg-skip-if "does not emit .cfi_xxx" "*-*-darwin*" } */ #include "apx-push2pop2-1.c" @@ -8,11 +8,11 @@ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 16" 2 } } */ /* { dg-final { scan-assembler-times "pushq\[^\n\r]*%r15(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 15, -16(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r14\[^\n\r]*%r13\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r13\[^\n\r]*%r14\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 32" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 14, -24(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 13, -32(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%r12\[^\n\r]*%rbp\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "push2\[\\t \]*\[^\n\r]*%rbp\[^\n\r]*%r12\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 48" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 12, -40(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 6, -48(?:\n|\[ \\t\]+#)" 1 } } */ @@ -20,10 +20,10 @@ /* { dg-final { scan-assembler-times ".cfi_def_cfa_offset 56" 2 } } */ /* { dg-final { scan-assembler-times ".cfi_offset 3, -56(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "popq\[^\n\r]*rbx(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%rbp\[^\n\r]*%r12\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r12\[^\n\r]*%rbp\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 12(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 6(?:\n|\[ \\t\]+#)" 1 } } */ -/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r13\[^\n\r]*%r14\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ +/* { dg-final { scan-assembler-times "pop2\[\\t \]*\[^\n\r]*%r14\[^\n\r]*%r13\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 14(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times ".cfi_restore 13(?:\n|\[ \\t\]+#)" 1 } } */ /* { dg-final { scan-assembler-times "popq\[^\n\r]*%r15(?:\n|\[ \\t\]+#)" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/apx-push2pop2_interrupt-1.c b/gcc/testsuite/gcc.target/i386/apx-push2pop2_interrupt-1.c index 747f7aa..a5b4689 100644 --- a/gcc/testsuite/gcc.target/i386/apx-push2pop2_interrupt-1.c +++ b/gcc/testsuite/gcc.target/i386/apx-push2pop2_interrupt-1.c @@ -1,5 +1,5 @@ /* { dg-do compile { target { ! ia32 } } } */ -/* { dg-options "-O2 -mapxf -mgeneral-regs-only -mno-cld -mno-push-args -maccumulate-outgoing-args" } */ +/* { dg-options "-O2 -mapx-features=egpr,push2pop2 -mgeneral-regs-only -mno-cld -mno-push-args -maccumulate-outgoing-args" } */ extern void foo (void *) __attribute__ ((interrupt)); diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-1.c b/gcc/testsuite/gcc.target/i386/avx10_1-1.c new file mode 100644 index 0000000..cfd9662 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -march=x86-64 -mavx10.1" } */ + +#include <immintrin.h> + +void +f1 () +{ + register __m256d a __asm ("ymm17"); + register __m256d b __asm ("ymm16"); + a = _mm256_add_pd (a, b); + asm volatile ("" : "+v" (a)); +} + +void +f2 () +{ + register __m128d a __asm ("xmm17"); + register __m128d b __asm ("xmm16"); + a = _mm_add_pd (a, b); + asm volatile ("" : "+v" (a)); +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-10.c b/gcc/testsuite/gcc.target/i386/avx10_1-10.c new file mode 100644 index 0000000..0db5240 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-10.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512 -mavx512f -mno-evex512" } */ +/* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" "" { target *-*-* } 0 } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-11.c b/gcc/testsuite/gcc.target/i386/avx10_1-11.c new file mode 100644 index 0000000..c0ad4fc --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-11.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512 -mno-avx512f" } */ +/* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" "" { target *-*-* } 0 } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-12.c b/gcc/testsuite/gcc.target/i386/avx10_1-12.c new file mode 100644 index 0000000..61f0e4d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-12.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mno-avx10.1-512 -mavx512f" } */ +/* { dg-warning "'-mno-avx10.1, -mno-avx10.1-256, -mno-avx10.1-512' cannot disable AVX512 instructions when '-mavx512XXX'" "" { target *-*-* } 0 } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-13.c b/gcc/testsuite/gcc.target/i386/avx10_1-13.c new file mode 100644 index 0000000..8a11119 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-13.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx512f"))) __m512d +foo () +{ /* { dg-warning "Vector size conflicts between AVX10.1 and AVX512, using 512 as max vector size" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-14.c b/gcc/testsuite/gcc.target/i386/avx10_1-14.c new file mode 100644 index 0000000..03222a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-14.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx512f" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx10.1"))) __m512d +foo () +{ /* { dg-warning "Vector size conflicts between AVX10.1 and AVX512, using 512 as max vector size" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-15.c b/gcc/testsuite/gcc.target/i386/avx10_1-15.c new file mode 100644 index 0000000..d1731f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-15.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx512f,no-evex512"))) __m512d +foo () +{ /* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-16.c b/gcc/testsuite/gcc.target/i386/avx10_1-16.c new file mode 100644 index 0000000..f5f3ff8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-16.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx512f -mno-evex512" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx10.1-512"))) __m512d +foo () +{ /* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-17.c b/gcc/testsuite/gcc.target/i386/avx10_1-17.c new file mode 100644 index 0000000..a19230f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-17.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx512f" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("no-avx10.1"))) __m512d +foo () +{ /* { dg-warning "'-mno-avx10.1, -mno-avx10.1-256, -mno-avx10.1-512' cannot disable AVX512 instructions when '-mavx512XXX'" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-18.c b/gcc/testsuite/gcc.target/i386/avx10_1-18.c new file mode 100644 index 0000000..c50fd2b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-18.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("no-avx512f"))) __m512d +foo () +{ /* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-19.c b/gcc/testsuite/gcc.target/i386/avx10_1-19.c new file mode 100644 index 0000000..7aacc15 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-19.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mno-avx10.1-512" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx512f"))) __m512d +foo () +{ /* { dg-warning "'-mno-avx10.1, -mno-avx10.1-256, -mno-avx10.1-512' cannot disable AVX512 instructions when '-mavx512XXX'" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-2.c b/gcc/testsuite/gcc.target/i386/avx10_1-2.c new file mode 100644 index 0000000..0b3991d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__m512d +foo () +{ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-20.c b/gcc/testsuite/gcc.target/i386/avx10_1-20.c new file mode 100644 index 0000000..d63c6b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-20.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mno-avx512f" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx10.1-512"))) __m512d +foo () +{ /* { dg-warning "'-mno-evex512' or '-mno-avx512XXX' cannot disable AVX10 instructions when AVX10.1-512 is available" } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-21.c b/gcc/testsuite/gcc.target/i386/avx10_1-21.c new file mode 100644 index 0000000..27a7265 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-21.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1 -mevex512 -Wno-psabi" } */ +/* { dg-warning "Using '-mevex512' without any AVX512 features enabled together with AVX10.1 only will not enable any AVX512 or AVX10.1-512 features, using 256 as max vector size" "" { target *-*-* } 0 } */ +/* { dg-final { scan-assembler-not "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-22.c b/gcc/testsuite/gcc.target/i386/avx10_1-22.c new file mode 100644 index 0000000..7962622 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-22.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1 -Wno-psabi" } */ +/* { dg-final { scan-assembler-not "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("evex512"))) __m512d +foo () +{ /* { dg-warning "Using '-mevex512' without any AVX512 features enabled together with AVX10.1 only will not enable any AVX512 or AVX10.1-512 features, using 256 as max vector size" "" { target *-*-* } 0 } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-23.c b/gcc/testsuite/gcc.target/i386/avx10_1-23.c new file mode 100644 index 0000000..6e8d64d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-23.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mevex512 -Wno-psabi" } */ +/* { dg-final { scan-assembler-not "%zmm" } } */ + +typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__)); + +__attribute__ ((target ("avx10.1"))) __m512d +foo () +{ /* { dg-warning "Using '-mevex512' without any AVX512 features enabled together with AVX10.1 only will not enable any AVX512 or AVX10.1-512 features, using 256 as max vector size" "" { target *-*-* } 0 } */ + __m512d a, b; + a = a + b; + return a; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-3.c b/gcc/testsuite/gcc.target/i386/avx10_1-3.c new file mode 100644 index 0000000..3be988a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -mavx10.1" } */ + +#include <immintrin.h> + +int +foo (int c) +{ + register int a __asm ("k7") = c; + int b = foo (a); + asm volatile ("" : "+k" (b)); + return b; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-4.c b/gcc/testsuite/gcc.target/i386/avx10_1-4.c new file mode 100644 index 0000000..68cbf19 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -mavx10.1-512" } */ + +#include <immintrin.h> + +long long +foo (long long c) +{ + register long long a __asm ("k7") = c; + long long b = foo (a); + asm volatile ("" : "+k" (b)); + return b; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-5.c b/gcc/testsuite/gcc.target/i386/avx10_1-5.c new file mode 100644 index 0000000..20b78ea --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-5.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -march=x86-64 -mavx10.1 -Wno-psabi" } */ +/* { dg-final { scan-assembler-not ".%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-6.c b/gcc/testsuite/gcc.target/i386/avx10_1-6.c new file mode 100644 index 0000000..827c80c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-6.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64 -mavx10.1" } */ + +#include <immintrin.h> + +long long +foo (long long c) +{ + register long long a __asm ("k7") = c; + long long b = foo (a); + asm volatile ("" : "+k" (b)); /* { dg-error "inconsistent operand constraints in an 'asm'" } */ + return b; +} diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-7.c b/gcc/testsuite/gcc.target/i386/avx10_1-7.c new file mode 100644 index 0000000..afce290 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-7.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-512 -mavx512f" } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-8.c b/gcc/testsuite/gcc.target/i386/avx10_1-8.c new file mode 100644 index 0000000..69b6c6a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-8.c @@ -0,0 +1,4 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-march=x86-64 -mavx10.1 -mavx512f -mno-evex512" } */ + +#include "avx10_1-1.c" diff --git a/gcc/testsuite/gcc.target/i386/avx10_1-9.c b/gcc/testsuite/gcc.target/i386/avx10_1-9.c new file mode 100644 index 0000000..8e83827 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/avx10_1-9.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=x86-64 -mavx10.1-256 -mavx512f" } */ +/* { dg-warning "Vector size conflicts between AVX10.1 and AVX512, using 512 as max vector size" "" { target *-*-* } 0 } */ +/* { dg-final { scan-assembler "%zmm" } } */ + +#include "avx10_1-2.c" diff --git a/gcc/testsuite/gcc.target/i386/bmi2-pr112518.c b/gcc/testsuite/gcc.target/i386/bmi2-pr112518.c new file mode 100644 index 0000000..6aea13f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/bmi2-pr112518.c @@ -0,0 +1,25 @@ +/* PR target/112518 */ +/* { dg-do run { target { bmi2 && int128 } } } */ +/* { dg-options "-Os -mbmi2" } */ + +#include "bmi2-check.h" + +unsigned u; +int g; + +unsigned long long +foo (int i) +{ + unsigned long long x = u; + g = __builtin_mul_overflow_p (u, ((unsigned __int128) 4292468825) << 64 | 150, 0); + x |= g % i; + return x; +} + +static __attribute__((noipa)) void +bmi2_test () +{ + unsigned long long x = foo (3); + if (x) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/cf_check-6.c b/gcc/testsuite/gcc.target/i386/cf_check-6.c new file mode 100644 index 0000000..71ebdd7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/cf_check-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ +/* { dg-options "-O2 -fhardened -mno-manual-endbr" } */ +/* { dg-final { scan-assembler-times {\mendbr} 1 } } */ +/* Test that -fhardened enables CET. */ + +extern void bar (void) __attribute__((__cf_check__)); + +void +foo (void) +{ + bar (); +} diff --git a/gcc/testsuite/gcc.target/i386/pr112325-1.c b/gcc/testsuite/gcc.target/i386/pr112325-1.c new file mode 100644 index 0000000..56e20c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112325-1.c @@ -0,0 +1,116 @@ +/* { dg-do compile } */ +/* { dg-options "-mavx512vl -mavx512bw -O2 -mtune=generic -mprefer-vector-width=512 -fdump-tree-slp2" } */ +/* { dg-final { scan-tree-dump-times ".REDUC_PLUS" 3 "slp2" } } */ +/* { dg-final { scan-tree-dump-times ".REDUC_IOR" 4 "slp2" } } */ + +int +__attribute__((noipa)) +plus_v4si (int* a) +{ + int sum = 0; + sum += a[0]; + sum += a[1]; + sum += a[2]; + sum += a[3]; + return sum; +} + +short +__attribute__((noipa)) +plus_v8hi (short* a) +{ + short sum = 0; + sum += a[0]; + sum += a[1]; + sum += a[2]; + sum += a[3]; + sum += a[4]; + sum += a[5]; + sum += a[6]; + sum += a[7]; + return sum; +} + +long long +__attribute__((noipa)) +plus_v8di (long long* a) +{ + long long sum = 0; + sum += a[0]; + sum += a[1]; + sum += a[2]; + sum += a[3]; + sum += a[4]; + sum += a[5]; + sum += a[6]; + sum += a[7]; + return sum; +} + +int +__attribute__((noipa)) +ior_v4si (int* a) +{ + int sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + return sum; +} + +short +__attribute__((noipa)) +ior_v8hi (short* a) +{ + short sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + sum |= a[4]; + sum |= a[5]; + sum |= a[6]; + sum |= a[7]; + return sum; +} + +long long +__attribute__((noipa)) +ior_v8di (long long* a) +{ + long long sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + sum |= a[4]; + sum |= a[5]; + sum |= a[6]; + sum |= a[7]; + return sum; +} + +char +__attribute__((noipa)) +ior_v16qi (char* a) +{ + char sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + sum |= a[4]; + sum |= a[5]; + sum |= a[6]; + sum |= a[7]; + sum |= a[8]; + sum |= a[9]; + sum |= a[10]; + sum |= a[11]; + sum |= a[12]; + sum |= a[13]; + sum |= a[14]; + sum |= a[15]; + return sum; +} diff --git a/gcc/testsuite/gcc.target/i386/pr112325-2.c b/gcc/testsuite/gcc.target/i386/pr112325-2.c new file mode 100644 index 0000000..650006b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112325-2.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -msse2" } */ +/* { dg-require-effective-target sse2 } */ + +#include "sse2-check.h" +#include "pr112325-1.c" + +static void +sse2_test (void) +{ + int d[4] = { 3, 11, 22, 89}; + short w[8] = { 3, 11, 22, 89, 4, 9, 13, 7}; + char b[16] = { 3, 11, 22, 89, 4, 9, 13, 7, 2, 6, 5, 111, 163, 88, 11, 235}; + long long q[8] = { 3, 11, 22, 89, 4, 9, 13, 7}; + + /* if (plus_v4si (d) != 125) */ + /* __builtin_abort (); */ + + /* if (plus_v8hi (w) != 158) */ + /* __builtin_abort (); */ + + /* if (plus_v8di (q) != 158) */ + /* __builtin_abort (); */ + + /* if (ior_v4si (d) != 95) */ + /* __builtin_abort (); */ + + /* if (ior_v8hi (w) != 95) */ + /* __builtin_abort (); */ + + /* if (ior_v16qi (b) != (char)255) */ + /* __builtin_abort (); */ + + if (ior_v8di (q) != 95) + __builtin_abort (); + + return; +} diff --git a/gcc/testsuite/gcc.target/i386/pr112325-mmx-1.c b/gcc/testsuite/gcc.target/i386/pr112325-mmx-1.c new file mode 100644 index 0000000..887249f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112325-mmx-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-msse2 -O2 -fdump-tree-slp2" } */ +/* { dg-final { scan-tree-dump-times ".REDUC_IOR" 3 "slp2" } } */ + +short +foo1 (short* a) +{ + short sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + return sum; +} + +char +foo2 (char* a) +{ + char sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + sum |= a[4]; + sum |= a[5]; + sum |= a[6]; + sum |= a[7]; + return sum; +} + +char +foo3 (char* a) +{ + char sum = 0; + sum |= a[0]; + sum |= a[1]; + sum |= a[2]; + sum |= a[3]; + return sum; +} diff --git a/gcc/testsuite/gcc.target/i386/pr112605-1.c b/gcc/testsuite/gcc.target/i386/pr112605-1.c new file mode 100644 index 0000000..57b9190 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112605-1.c @@ -0,0 +1,7 @@ +/* PR target/112605 */ +/* { dg-do compile } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-fsplit-stack -fpic -mforce-indirect-call" } */ + +#include "pr112605.c" diff --git a/gcc/testsuite/gcc.target/i386/pr112605-2.c b/gcc/testsuite/gcc.target/i386/pr112605-2.c new file mode 100644 index 0000000..7db9aba --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112605-2.c @@ -0,0 +1,7 @@ +/* PR target/112605 */ +/* { dg-do compile { target lp64 } } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-fsplit-stack -fpic -mcmodel=large -mforce-indirect-call " } */ + +#include "pr112605.c" diff --git a/gcc/testsuite/gcc.target/i386/pr112605.c b/gcc/testsuite/gcc.target/i386/pr112605.c new file mode 100644 index 0000000..da50a0f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112605.c @@ -0,0 +1,24 @@ +/* PR target/112605 */ +/* { dg-do compile } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-options "-fsplit-stack -mforce-indirect-call" } */ + +int x; +int y; + +void __attribute__((noinline)) f1(void) +{ + x++; +} + +static __attribute__((noinline)) void f3(void) +{ + y++; +} + +void f2() +{ + f1(); + f3(); + f1(); +} diff --git a/gcc/testsuite/gcc.target/i386/pr112623.c b/gcc/testsuite/gcc.target/i386/pr112623.c new file mode 100644 index 0000000..c4ebace --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112623.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O -mavx512vl -mavx512fp16" } */ + +typedef __bf16 __attribute__((__vector_size__ (16))) BF; +typedef float __attribute__((__vector_size__ (32))) F; + +BF +foo (F f) +{ + return __builtin_convertvector (f, BF); +} diff --git a/gcc/testsuite/gcc.target/i386/pr112672.c b/gcc/testsuite/gcc.target/i386/pr112672.c new file mode 100644 index 0000000..583e9fd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112672.c @@ -0,0 +1,23 @@ +/* PR target/112672 */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +typedef unsigned short u16; + +u16 g = 254; + +static inline u16 +foo (u16 u) +{ + u *= g; + return u + __builtin_parityl (u); +} + +int +main (void) +{ + u16 x = foo (4); + if (x != 4 * 254 + 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr112686.c b/gcc/testsuite/gcc.target/i386/pr112686.c new file mode 100644 index 0000000..4f452d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112686.c @@ -0,0 +1,6 @@ +/* PR target/112686 */ +/* { dg-do compile { target lp64 } } */ +/* { dg-require-effective-target split_stack } */ +/* { dg-options "-fsplit-stack -mcmodel=large" } */ + +void foo (void) {} diff --git a/gcc/testsuite/gcc.target/i386/pr90693.c b/gcc/testsuite/gcc.target/i386/pr90693.c new file mode 100644 index 0000000..1659f26 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr90693.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/90693 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-abm -mno-popcnt -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "POPCOUNT \\\(" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__builtin_popcount(ll)? \\\(" "optimized" } } */ + +int +foo (unsigned int x) +{ + return __builtin_popcount (x) == 1; +} + +int +bar (unsigned int x) +{ + return (x ^ (x - 1)) > x - 1; +} + +int +baz (unsigned long long x) +{ + return __builtin_popcountll (x) == 1; +} + +int +qux (unsigned long long x) +{ + return (x ^ (x - 1)) > x - 1; +} diff --git a/gcc/testsuite/gcc.target/i386/sse4-pr112681.c b/gcc/testsuite/gcc.target/i386/sse4-pr112681.c new file mode 100644 index 0000000..6c91087 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse4-pr112681.c @@ -0,0 +1,11 @@ +/* PR target/112681 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse4 -mno-avx" } */ + +struct S { void *c; char d[16]; } a, b; + +int +foo (void) +{ + return __builtin_memcmp (a.d, b.d, sizeof (a.d)) != 0; +} diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c index 8bc3f4a..5d19dcb 100644 --- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c +++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c @@ -123,12 +123,12 @@ __m128bf16 footest (__m128bf16 vector0) (void) glob_bfloat_vec; (__m128bf16) glob_bfloat_vec; - (__bf16) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (__bf16) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type '__m128bf16' {aka '__vector\(8\) __bf16'} to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type '__m128bf16' {aka '__vector\(8\) __bf16'} to type 'int' which has different size} } */ - (_Float16) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (_Float16) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (__v8si) glob_bfloat_vec; /* { dg-error {cannot convert a value of type '__m128bf16' {aka '__vector\(8\) __bf16'} to vector type '__vector\(8\) int' which has different size} } */ (__m256) glob_bfloat_vec; /* { dg-error {cannot convert a value of type '__m128bf16' {aka '__vector\(8\) __bf16'} to vector type '__vector\(8\) float' which has different size} } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c index 2a8a535..d4e6fc8 100644 --- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c +++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c @@ -116,12 +116,12 @@ __m256bf16 footest (__m256bf16 vector0) (void) glob_bfloat_vec; (__m256bf16) glob_bfloat_vec; - (__bf16) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (__bf16) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (short) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type '__m256bf16' {aka '__vector\(16\) __bf16'} to type 'short int' which has different size} } */ (int) glob_bfloat_vec; /* { dg-error {cannot convert a vector of type '__m256bf16' {aka '__vector\(16\) __bf16'} to type 'int' which has different size} } */ - (_Float16) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (float) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ - (double) glob_bfloat_vec; /* { dg-error {aggregate value used where a floating-point was expected} } */ + (_Float16) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (float) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ + (double) glob_bfloat_vec; /* { dg-error {vector value used where a floating-point was expected} } */ (__v8si) glob_bfloat_vec; (__m256) glob_bfloat_vec; diff --git a/gcc/testsuite/gcc.target/loongarch/imm-load1.c b/gcc/testsuite/gcc.target/loongarch/imm-load1.c index 2ff0297..f64cc29 100644 --- a/gcc/testsuite/gcc.target/loongarch/imm-load1.c +++ b/gcc/testsuite/gcc.target/loongarch/imm-load1.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-mabi=lp64d -O2" } */ -/* { dg-final { scan-assembler "test:.*lu52i\.d.*\n\taddi\.w.*\n\.L2:" } } */ +/* { dg-final { scan-assembler-not "test:.*lu52i\.d.*\n\taddi\.w.*\n\.L2:" } } */ +/* { dg-final { scan-assembler "test:.*lu12i\.w.*\n\tbstrins\.d.*\n\.L2:" } } */ extern long long b[10]; diff --git a/gcc/testsuite/gcc.target/loongarch/vect-shuf-fp.c b/gcc/testsuite/gcc.target/loongarch/vect-shuf-fp.c new file mode 100644 index 0000000..7acc211 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vect-shuf-fp.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-mlasx -O3" } */ +/* { dg-final { scan-assembler "vshuf\.w" } } */ + +#define V __attribute__ ((vector_size (16))) + +int a V; +float b V; +float c V; +float d V; + +void +test (void) +{ + d = __builtin_shuffle (b, c, a); +} diff --git a/gcc/testsuite/gcc.target/riscv/adddibeq.c b/gcc/testsuite/gcc.target/riscv/adddibeq.c new file mode 100644 index 0000000..624c56e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibfeq.c b/gcc/testsuite/gcc.target/riscv/adddibfeq.c new file mode 100644 index 0000000..403200f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibfeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branched assembly like: + + feq.d a5,fa0,fa1 + beq a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibfge.c b/gcc/testsuite/gcc.target/riscv/adddibfge.c new file mode 100644 index 0000000..82fce9c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibfge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + fge.d a5,fa0,fa1 + beq a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibfgt.c b/gcc/testsuite/gcc.target/riscv/adddibfgt.c new file mode 100644 index 0000000..0263154 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibfgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + fgt.d a5,fa0,fa1 + beq a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibfle.c b/gcc/testsuite/gcc.target/riscv/adddibfle.c new file mode 100644 index 0000000..6fd65f1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibfle.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + fle.d a5,fa0,fa1 + beq a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibflt.c b/gcc/testsuite/gcc.target/riscv/adddibflt.c new file mode 100644 index 0000000..bfee522 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibflt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + flt.d a5,fa0,fa1 + beq a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibfne.c b/gcc/testsuite/gcc.target/riscv/adddibfne.c new file mode 100644 index 0000000..73ade4d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibfne.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branched assembly like: + + feq.d a5,fa0,fa1 + bne a5,zero,.L2 + add a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibge.c b/gcc/testsuite/gcc.target/riscv/adddibge.c new file mode 100644 index 0000000..017b69f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibgeu.c b/gcc/testsuite/gcc.target/riscv/adddibgeu.c new file mode 100644 index 0000000..ed17898 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibgeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibgt.c b/gcc/testsuite/gcc.target/riscv/adddibgt.c new file mode 100644 index 0000000..201852f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibgtu.c b/gcc/testsuite/gcc.target/riscv/adddibgtu.c new file mode 100644 index 0000000..60850c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibgtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddible.c b/gcc/testsuite/gcc.target/riscv/adddible.c new file mode 100644 index 0000000..5bed30c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddible.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibleu.c b/gcc/testsuite/gcc.target/riscv/adddibleu.c new file mode 100644 index 0000000..3d16d09 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibleu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddiblt.c b/gcc/testsuite/gcc.target/riscv/adddiblt.c new file mode 100644 index 0000000..8ab979d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddiblt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibltu.c b/gcc/testsuite/gcc.target/riscv/adddibltu.c new file mode 100644 index 0000000..858e70f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + add a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddibne.c b/gcc/testsuite/gcc.target/riscv/adddibne.c new file mode 100644 index 0000000..e5dfee5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddibne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + add a0,a2,a3 + ret +.L3: + mv a0,a2 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddieq.c b/gcc/testsuite/gcc.target/riscv/adddieq.c new file mode 100644 index 0000000..6195bf5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddieq.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + seqz a1,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddifeq.c b/gcc/testsuite/gcc.target/riscv/adddifeq.c new file mode 100644 index 0000000..07c3f66 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddifeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg a5,a5 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddifge.c b/gcc/testsuite/gcc.target/riscv/adddifge.c new file mode 100644 index 0000000..7c4307c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddifge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + neg a5,a5 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddifgt.c b/gcc/testsuite/gcc.target/riscv/adddifgt.c new file mode 100644 index 0000000..f4774c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddifgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + neg a5,a5 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddifle.c b/gcc/testsuite/gcc.target/riscv/adddifle.c new file mode 100644 index 0000000..20a2736 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddifle.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + neg a5,a5 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddiflt.c b/gcc/testsuite/gcc.target/riscv/adddiflt.c new file mode 100644 index 0000000..18221f6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddiflt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + neg a5,a5 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddifne.c b/gcc/testsuite/gcc.target/riscv/adddifne.c new file mode 100644 index 0000000..58fcb40 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddifne.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + addi a5,a5,-1 + and a5,a5,a1 + add a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddige.c b/gcc/testsuite/gcc.target/riscv/adddige.c new file mode 100644 index 0000000..85e4224 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddige.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + addi a1,a1,-1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddigeu.c b/gcc/testsuite/gcc.target/riscv/adddigeu.c new file mode 100644 index 0000000..f96714b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddigeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + addi a1,a1,-1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddigt.c b/gcc/testsuite/gcc.target/riscv/adddigt.c new file mode 100644 index 0000000..047cbd4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddigt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddigtu.c b/gcc/testsuite/gcc.target/riscv/adddigtu.c new file mode 100644 index 0000000..10126369a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddigtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddile.c b/gcc/testsuite/gcc.target/riscv/adddile.c new file mode 100644 index 0000000..e69b195 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddile.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + addi a1,a1,-1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddileu.c b/gcc/testsuite/gcc.target/riscv/adddileu.c new file mode 100644 index 0000000..1e3bbd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddileu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + addi a1,a1,-1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddilt.c b/gcc/testsuite/gcc.target/riscv/adddilt.c new file mode 100644 index 0000000..647263a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddilt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddiltu.c b/gcc/testsuite/gcc.target/riscv/adddiltu.c new file mode 100644 index 0000000..4a511b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddiltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +adddiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/adddine.c b/gcc/testsuite/gcc.target/riscv/adddine.c new file mode 100644 index 0000000..00ff875 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/adddine.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +adddine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + snez a1,a1 + neg a1,a1 + and a1,a1,a3 + add a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibeq.c b/gcc/testsuite/gcc.target/riscv/addsibeq.c new file mode 100644 index 0000000..c1e810d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + addw a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sub|subw)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibfeq.c b/gcc/testsuite/gcc.target/riscv/addsibfeq.c new file mode 100644 index 0000000..27d13a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibfeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branched assembly like: + + feq.d a5,fa0,fa1 + beq a5,zero,.L2 + add[w] a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibfge.c b/gcc/testsuite/gcc.target/riscv/addsibfge.c new file mode 100644 index 0000000..501f756 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibfge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + fge.d a5,fa0,fa1 + beq a5,zero,.L2 + add[w] a0,a0,a1 +.L2: + */ + +/* { /* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibfgt.c b/gcc/testsuite/gcc.target/riscv/addsibfgt.c new file mode 100644 index 0000000..fff809b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibfgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + fgt.d a5,fa0,fa1 + beq a5,zero,.L2 + add[w] a0,a0,a1 +.L2: + */ + +/* { /* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibfle.c b/gcc/testsuite/gcc.target/riscv/addsibfle.c new file mode 100644 index 0000000..abcad61 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibfle.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + fle.d a5,fa0,fa1 + beq a5,zero,.L2 + addw a0,a0,a1 +.L2: + */ + +/* { /* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibflt.c b/gcc/testsuite/gcc.target/riscv/addsibflt.c new file mode 100644 index 0000000..2a82c28 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibflt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + flt.d a5,fa0,fa1 + beq a5,zero,.L2 + addw a0,a0,a1 +.L2: + */ + +/* { /* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibfne.c b/gcc/testsuite/gcc.target/riscv/addsibfne.c new file mode 100644 index 0000000..94da071 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibfne.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=2 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branched assembly like: + + feq.d a5,fa0,fa1 + bne a5,zero,.L2 + add[w] a0,a0,a1 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibge.c b/gcc/testsuite/gcc.target/riscv/addsibge.c new file mode 100644 index 0000000..3f67d16 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibgeu.c b/gcc/testsuite/gcc.target/riscv/addsibgeu.c new file mode 100644 index 0000000..b6df531 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibgeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibgt.c b/gcc/testsuite/gcc.target/riscv/addsibgt.c new file mode 100644 index 0000000..86fcd6d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibgtu.c b/gcc/testsuite/gcc.target/riscv/addsibgtu.c new file mode 100644 index 0000000..63ebe65 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibgtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsible.c b/gcc/testsuite/gcc.target/riscv/addsible.c new file mode 100644 index 0000000..164d9c0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsible.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibleu.c b/gcc/testsuite/gcc.target/riscv/addsibleu.c new file mode 100644 index 0000000..b02170b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibleu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsiblt.c b/gcc/testsuite/gcc.target/riscv/addsiblt.c new file mode 100644 index 0000000..a7911fd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsiblt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibltu.c b/gcc/testsuite/gcc.target/riscv/addsibltu.c new file mode 100644 index 0000000..69ee2a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + add[w] a2,a2,a3 +.L2: + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsibne.c b/gcc/testsuite/gcc.target/riscv/addsibne.c new file mode 100644 index 0000000..929e057 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsibne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + add[w] a0,a2,a3 + ret +.L3: + mv a0,a2 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sub|subw)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsieq.c b/gcc/testsuite/gcc.target/riscv/addsieq.c new file mode 100644 index 0000000..c5797a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsieq.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branchless assembly like: + + sub[w] a1,a0,a1 + seqz a1,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sub|subw)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsifeq.c b/gcc/testsuite/gcc.target/riscv/addsifeq.c new file mode 100644 index 0000000..fe93f41 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsifeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y + z : y; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg[w] a5,a5 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsifge.c b/gcc/testsuite/gcc.target/riscv/addsifge.c new file mode 100644 index 0000000..a0d31b2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsifge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + neg[w] a5,a5 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { /* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsifgt.c b/gcc/testsuite/gcc.target/riscv/addsifgt.c new file mode 100644 index 0000000..f61efb5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsifgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + neg[w] a5,a5 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { /* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsifle.c b/gcc/testsuite/gcc.target/riscv/addsifle.c new file mode 100644 index 0000000..a9a86bb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsifle.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + neg[w] a5,a5 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { /* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsiflt.c b/gcc/testsuite/gcc.target/riscv/addsiflt.c new file mode 100644 index 0000000..f68bd2d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsiflt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -ffinite-math-only -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + neg[w] a5,a5 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { /* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fgt\\.d|fle\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsifne.c b/gcc/testsuite/gcc.target/riscv/addsifne.c new file mode 100644 index 0000000..9875d62 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsifne.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=3 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + addi[w] a5,a5,-1 + and a5,a5,a1 + add[w] a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsige.c b/gcc/testsuite/gcc.target/riscv/addsige.c new file mode 100644 index 0000000..461f2ad --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsige.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + addi[w] a1,a1,-1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsigeu.c b/gcc/testsuite/gcc.target/riscv/addsigeu.c new file mode 100644 index 0000000..3afcc33 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsigeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + addi[w] a1,a1,-1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsigt.c b/gcc/testsuite/gcc.target/riscv/addsigt.c new file mode 100644 index 0000000..247626a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsigt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsigtu.c b/gcc/testsuite/gcc.target/riscv/addsigtu.c new file mode 100644 index 0000000..c6948b4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsigtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsile.c b/gcc/testsuite/gcc.target/riscv/addsile.c new file mode 100644 index 0000000..5072521 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsile.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + addi[w] a1,a1,-1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsileu.c b/gcc/testsuite/gcc.target/riscv/addsileu.c new file mode 100644 index 0000000..2758a9e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsileu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y + z : y; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + addi[w] a1,a1,-1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsilt.c b/gcc/testsuite/gcc.target/riscv/addsilt.c new file mode 100644 index 0000000..bad08e7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsilt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsiltu.c b/gcc/testsuite/gcc.target/riscv/addsiltu.c new file mode 100644 index 0000000..0cee92f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsiltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +addsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y + z : y; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/addsine.c b/gcc/testsuite/gcc.target/riscv/addsine.c new file mode 100644 index 0000000..4d45b83 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/addsine.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +addsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y + z : y; +} + +/* Expect branchless assembly like: + + sub[w] a1,a0,a1 + snez a1,a1 + neg[w] a1,a1 + and a1,a1,a3 + add[w] a0,a1,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_addcc" 1 "ce1" { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:sub|subw)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 { xfail rv64 } } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" { xfail rv64 } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibeq-thead.c b/gcc/testsuite/gcc.target/riscv/movdibeq-thead.c new file mode 100644 index 0000000..26737ee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibeq-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibeq-ventana.c new file mode 100644 index 0000000..c48e57e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibeq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibeq-zicond.c new file mode 100644 index 0000000..6f61731 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibeq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibeq.c b/gcc/testsuite/gcc.target/riscv/movdibeq.c new file mode 100644 index 0000000..8359eca --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibfeq-ventana.c new file mode 100644 index 0000000..e43b642 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfeq-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibfeq-zicond.c new file mode 100644 index 0000000..ea4ff14 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfeq-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfeq.c b/gcc/testsuite/gcc.target/riscv/movdibfeq.c new file mode 100644 index 0000000..03c934b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfeq.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfge-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibfge-ventana.c new file mode 100644 index 0000000..b80f5c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfge-ventana.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfge-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibfge-zicond.c new file mode 100644 index 0000000..ed72259 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfge-zicond.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfge.c b/gcc/testsuite/gcc.target/riscv/movdibfge.c new file mode 100644 index 0000000..68dacb6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfge.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibfgt-ventana.c new file mode 100644 index 0000000..fd392ec --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfgt-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibfgt-zicond.c new file mode 100644 index 0000000..158ad9e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfgt-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfgt.c b/gcc/testsuite/gcc.target/riscv/movdibfgt.c new file mode 100644 index 0000000..dbd60d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfgt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfle-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibfle-ventana.c new file mode 100644 index 0000000..bc9d719 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfle-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfle-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibfle-zicond.c new file mode 100644 index 0000000..ac9f159 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfle-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfle.c b/gcc/testsuite/gcc.target/riscv/movdibfle.c new file mode 100644 index 0000000..42d5401 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfle.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibflt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibflt-ventana.c new file mode 100644 index 0000000..3a26107 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibflt-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibflt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibflt-zicond.c new file mode 100644 index 0000000..a8e362b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibflt-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibflt.c b/gcc/testsuite/gcc.target/riscv/movdibflt.c new file mode 100644 index 0000000..08935ff --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibflt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfne-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibfne-ventana.c new file mode 100644 index 0000000..634872a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfne-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfne-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibfne-zicond.c new file mode 100644 index 0000000..24db9fa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfne-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibfne.c b/gcc/testsuite/gcc.target/riscv/movdibfne.c new file mode 100644 index 0000000..1b71ad9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibfne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibge-thead.c b/gcc/testsuite/gcc.target/riscv/movdibge-thead.c new file mode 100644 index 0000000..4c05937 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibge-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibge-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibge-ventana.c new file mode 100644 index 0000000..c0190e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibge-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibge-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibge-zicond.c new file mode 100644 index 0000000..c4bd650 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibge-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibge.c b/gcc/testsuite/gcc.target/riscv/movdibge.c new file mode 100644 index 0000000..e991835 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgeu-thead.c b/gcc/testsuite/gcc.target/riscv/movdibgeu-thead.c new file mode 100644 index 0000000..c846160 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgeu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgeu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibgeu-ventana.c new file mode 100644 index 0000000..584bf26 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgeu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgeu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibgeu-zicond.c new file mode 100644 index 0000000..e6ea9d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgeu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgeu.c b/gcc/testsuite/gcc.target/riscv/movdibgeu.c new file mode 100644 index 0000000..b0e3e3d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgt-thead.c b/gcc/testsuite/gcc.target/riscv/movdibgt-thead.c new file mode 100644 index 0000000..cc22ff6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgt-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibgt-ventana.c new file mode 100644 index 0000000..00b954c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibgt-zicond.c new file mode 100644 index 0000000..1a1445f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgt.c b/gcc/testsuite/gcc.target/riscv/movdibgt.c new file mode 100644 index 0000000..9890c6a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgtu-thead.c b/gcc/testsuite/gcc.target/riscv/movdibgtu-thead.c new file mode 100644 index 0000000..e616c15 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgtu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgtu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibgtu-ventana.c new file mode 100644 index 0000000..ea4548d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgtu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgtu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibgtu-zicond.c new file mode 100644 index 0000000..19198f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgtu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibgtu.c b/gcc/testsuite/gcc.target/riscv/movdibgtu.c new file mode 100644 index 0000000..7fa25c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibgtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdible-thead.c b/gcc/testsuite/gcc.target/riscv/movdible-thead.c new file mode 100644 index 0000000..16415d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdible-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdible-ventana.c b/gcc/testsuite/gcc.target/riscv/movdible-ventana.c new file mode 100644 index 0000000..2d1a49e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdible-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdible-zicond.c b/gcc/testsuite/gcc.target/riscv/movdible-zicond.c new file mode 100644 index 0000000..ec26a36 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdible-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdible.c b/gcc/testsuite/gcc.target/riscv/movdible.c new file mode 100644 index 0000000..23de185 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdible.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibleu-thead.c b/gcc/testsuite/gcc.target/riscv/movdibleu-thead.c new file mode 100644 index 0000000..37781af --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibleu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibleu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibleu-ventana.c new file mode 100644 index 0000000..3e10d7b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibleu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibleu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibleu-zicond.c new file mode 100644 index 0000000..bc1fb68 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibleu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibleu.c b/gcc/testsuite/gcc.target/riscv/movdibleu.c new file mode 100644 index 0000000..032e93b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibleu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiblt-thead.c b/gcc/testsuite/gcc.target/riscv/movdiblt-thead.c new file mode 100644 index 0000000..43a772e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiblt-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiblt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdiblt-ventana.c new file mode 100644 index 0000000..0636f90 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiblt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiblt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdiblt-zicond.c new file mode 100644 index 0000000..3c82f0b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiblt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiblt.c b/gcc/testsuite/gcc.target/riscv/movdiblt.c new file mode 100644 index 0000000..0b7a40c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiblt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibltu-thead.c b/gcc/testsuite/gcc.target/riscv/movdibltu-thead.c new file mode 100644 index 0000000..ec44b1a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibltu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibltu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibltu-ventana.c new file mode 100644 index 0000000..c92a494 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibltu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibltu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibltu-zicond.c new file mode 100644 index 0000000..68bdccf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibltu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibltu.c b/gcc/testsuite/gcc.target/riscv/movdibltu.c new file mode 100644 index 0000000..277d08e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibne-thead.c b/gcc/testsuite/gcc.target/riscv/movdibne-thead.c new file mode 100644 index 0000000..8edcfd5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibne-thead.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" { xfail "*-*-*" } } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibne-ventana.c b/gcc/testsuite/gcc.target/riscv/movdibne-ventana.c new file mode 100644 index 0000000..5752f14 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibne-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibne-zicond.c b/gcc/testsuite/gcc.target/riscv/movdibne-zicond.c new file mode 100644 index 0000000..1c97a3c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibne-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdibne.c b/gcc/testsuite/gcc.target/riscv/movdibne.c new file mode 100644 index 0000000..f3b6715 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdibne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdieq-sfb.c b/gcc/testsuite/gcc.target/riscv/movdieq-sfb.c new file mode 100644 index 0000000..aed11b0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdieq-sfb.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect short forward branch assembly like: + + bne a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdieq-thead.c b/gcc/testsuite/gcc.target/riscv/movdieq-thead.c new file mode 100644 index 0000000..2109a72 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdieq-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdieq-ventana.c b/gcc/testsuite/gcc.target/riscv/movdieq-ventana.c new file mode 100644 index 0000000..bca40ce --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdieq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdieq-zicond.c b/gcc/testsuite/gcc.target/riscv/movdieq-zicond.c new file mode 100644 index 0000000..3222c87 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdieq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdieq.c b/gcc/testsuite/gcc.target/riscv/movdieq.c new file mode 100644 index 0000000..9878341 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdieq.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=7 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a5,a0,a1 + snez a5,a5 + neg a5,a5 + and a3,a5,a3 + not a5,a5 + and a5,a5,a2 + or a0,a3,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifeq-sfb.c b/gcc/testsuite/gcc.target/riscv/movdifeq-sfb.c new file mode 100644 index 0000000..fe5a79a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifeq-sfb.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect short forward branch assembly like: + + feq.d a5,fa0,fa1 + beq a5,zero,1f # movcc + mv a1,a0 +1: + mv a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifeq-thead.c b/gcc/testsuite/gcc.target/riscv/movdifeq-thead.c new file mode 100644 index 0000000..487e3eb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifeq-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movdifeq-ventana.c new file mode 100644 index 0000000..6d6c801 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifeq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + vt.maskcn a1,a1,a5 + vt.maskc a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movdifeq-zicond.c new file mode 100644 index 0000000..15bd6e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifeq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + czero.nez a1,a1,a5 + czero.eqz a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifeq.c b/gcc/testsuite/gcc.target/riscv/movdifeq.c new file mode 100644 index 0000000..de6e17e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifeq.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifge-sfb.c b/gcc/testsuite/gcc.target/riscv/movdifge-sfb.c new file mode 100644 index 0000000..b5eb0f4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifge-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + fge.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifge-thead.c b/gcc/testsuite/gcc.target/riscv/movdifge-thead.c new file mode 100644 index 0000000..6fb210c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifge-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifge-ventana.c b/gcc/testsuite/gcc.target/riscv/movdifge-ventana.c new file mode 100644 index 0000000..be33171 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifge-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifge-zicond.c b/gcc/testsuite/gcc.target/riscv/movdifge-zicond.c new file mode 100644 index 0000000..0c6a10f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifge-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifge.c b/gcc/testsuite/gcc.target/riscv/movdifge.c new file mode 100644 index 0000000..3193aae --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifge.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifgt-sfb.c b/gcc/testsuite/gcc.target/riscv/movdifgt-sfb.c new file mode 100644 index 0000000..0fc5a1c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifgt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + fgt.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifgt-thead.c b/gcc/testsuite/gcc.target/riscv/movdifgt-thead.c new file mode 100644 index 0000000..1eece07 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifgt-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdifgt-ventana.c new file mode 100644 index 0000000..7df01a6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifgt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdifgt-zicond.c new file mode 100644 index 0000000..6b18e8f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifgt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifgt.c b/gcc/testsuite/gcc.target/riscv/movdifgt.c new file mode 100644 index 0000000..466b4ab --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifgt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifle-sfb.c b/gcc/testsuite/gcc.target/riscv/movdifle-sfb.c new file mode 100644 index 0000000..475c7f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifle-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + fle.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifle-thead.c b/gcc/testsuite/gcc.target/riscv/movdifle-thead.c new file mode 100644 index 0000000..9ee0dbb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifle-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifle-ventana.c b/gcc/testsuite/gcc.target/riscv/movdifle-ventana.c new file mode 100644 index 0000000..d6f67ae --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifle-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifle-zicond.c b/gcc/testsuite/gcc.target/riscv/movdifle-zicond.c new file mode 100644 index 0000000..c1f13b7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifle-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifle.c b/gcc/testsuite/gcc.target/riscv/movdifle.c new file mode 100644 index 0000000..579f14d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifle.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiflt-sfb.c b/gcc/testsuite/gcc.target/riscv/movdiflt-sfb.c new file mode 100644 index 0000000..c116fe3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiflt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + flt.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiflt-thead.c b/gcc/testsuite/gcc.target/riscv/movdiflt-thead.c new file mode 100644 index 0000000..f4f210c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiflt-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiflt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdiflt-ventana.c new file mode 100644 index 0000000..049b77c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiflt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiflt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdiflt-zicond.c new file mode 100644 index 0000000..6a1d7ce --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiflt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiflt.c b/gcc/testsuite/gcc.target/riscv/movdiflt.c new file mode 100644 index 0000000..280eaa4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiflt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifne-sfb.c b/gcc/testsuite/gcc.target/riscv/movdifne-sfb.c new file mode 100644 index 0000000..4d0b64c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifne-sfb.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect short forward branch assembly like: + + feq.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a1,a0 +1: + mv a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifne-thead.c b/gcc/testsuite/gcc.target/riscv/movdifne-thead.c new file mode 100644 index 0000000..54f82d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifne-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + th.mvnez a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifne-ventana.c b/gcc/testsuite/gcc.target/riscv/movdifne-ventana.c new file mode 100644 index 0000000..ae95b6b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifne-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + vt.maskc a1,a1,a5 + vt.maskcn a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifne-zicond.c b/gcc/testsuite/gcc.target/riscv/movdifne-zicond.c new file mode 100644 index 0000000..b296d94 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifne-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + czero.eqz a1,a1,a5 + czero.nez a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdifne.c b/gcc/testsuite/gcc.target/riscv/movdifne.c new file mode 100644 index 0000000..e06bb14 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdifne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg a5,a5 + and a1,a5,a1 + not a5,a5 + and a0,a5,a0 + or a0,a1,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdige-sfb.c b/gcc/testsuite/gcc.target/riscv/movdige-sfb.c new file mode 100644 index 0000000..bcbc263 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdige-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + blt a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdige-thead.c b/gcc/testsuite/gcc.target/riscv/movdige-thead.c new file mode 100644 index 0000000..5ade711 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdige-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdige-ventana.c b/gcc/testsuite/gcc.target/riscv/movdige-ventana.c new file mode 100644 index 0000000..ea60c88 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdige-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdige-zicond.c b/gcc/testsuite/gcc.target/riscv/movdige-zicond.c new file mode 100644 index 0000000..958ebe7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdige-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdige.c b/gcc/testsuite/gcc.target/riscv/movdige.c new file mode 100644 index 0000000..f24f4a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdige.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigeu-sfb.c b/gcc/testsuite/gcc.target/riscv/movdigeu-sfb.c new file mode 100644 index 0000000..fd5abf0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigeu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bltu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigeu-thead.c b/gcc/testsuite/gcc.target/riscv/movdigeu-thead.c new file mode 100644 index 0000000..6fa48f1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigeu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigeu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdigeu-ventana.c new file mode 100644 index 0000000..a89151b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigeu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigeu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdigeu-zicond.c new file mode 100644 index 0000000..2dbd655 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigeu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigeu.c b/gcc/testsuite/gcc.target/riscv/movdigeu.c new file mode 100644 index 0000000..ae2f957 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigeu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigt-sfb.c b/gcc/testsuite/gcc.target/riscv/movdigt-sfb.c new file mode 100644 index 0000000..f3c4186 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + ble a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigt-thead.c b/gcc/testsuite/gcc.target/riscv/movdigt-thead.c new file mode 100644 index 0000000..d687dd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigt-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdigt-ventana.c new file mode 100644 index 0000000..8206f3b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdigt-zicond.c new file mode 100644 index 0000000..632d007 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigt.c b/gcc/testsuite/gcc.target/riscv/movdigt.c new file mode 100644 index 0000000..83e5244 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigtu-sfb.c b/gcc/testsuite/gcc.target/riscv/movdigtu-sfb.c new file mode 100644 index 0000000..a788107 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigtu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + bleu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigtu-thead.c b/gcc/testsuite/gcc.target/riscv/movdigtu-thead.c new file mode 100644 index 0000000..3fb471a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigtu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigtu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdigtu-ventana.c new file mode 100644 index 0000000..d34314d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigtu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigtu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdigtu-zicond.c new file mode 100644 index 0000000..61a0c14 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigtu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdigtu.c b/gcc/testsuite/gcc.target/riscv/movdigtu.c new file mode 100644 index 0000000..184b384 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdigtu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdile-sfb.c b/gcc/testsuite/gcc.target/riscv/movdile-sfb.c new file mode 100644 index 0000000..3758764 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdile-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgt a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|bgt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdile-thead.c b/gcc/testsuite/gcc.target/riscv/movdile-thead.c new file mode 100644 index 0000000..6ba8d8d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdile-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdile-ventana.c b/gcc/testsuite/gcc.target/riscv/movdile-ventana.c new file mode 100644 index 0000000..dee7bf7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdile-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdile-zicond.c b/gcc/testsuite/gcc.target/riscv/movdile-zicond.c new file mode 100644 index 0000000..a3989a3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdile-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdile.c b/gcc/testsuite/gcc.target/riscv/movdile.c new file mode 100644 index 0000000..a1b7a57 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdile.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdileu-sfb.c b/gcc/testsuite/gcc.target/riscv/movdileu-sfb.c new file mode 100644 index 0000000..312b52c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdileu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgtu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdileu-thead.c b/gcc/testsuite/gcc.target/riscv/movdileu-thead.c new file mode 100644 index 0000000..3661165 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdileu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdileu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdileu-ventana.c new file mode 100644 index 0000000..c50cb43 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdileu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdileu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdileu-zicond.c new file mode 100644 index 0000000..018babe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdileu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdileu.c b/gcc/testsuite/gcc.target/riscv/movdileu.c new file mode 100644 index 0000000..4eb8267 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdileu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdilt-sfb.c b/gcc/testsuite/gcc.target/riscv/movdilt-sfb.c new file mode 100644 index 0000000..f37b35b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdilt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + bge a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdilt-thead.c b/gcc/testsuite/gcc.target/riscv/movdilt-thead.c new file mode 100644 index 0000000..7ae6357 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdilt-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdilt-ventana.c b/gcc/testsuite/gcc.target/riscv/movdilt-ventana.c new file mode 100644 index 0000000..9d98d93 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdilt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdilt-zicond.c b/gcc/testsuite/gcc.target/riscv/movdilt-zicond.c new file mode 100644 index 0000000..79bfefe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdilt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdilt.c b/gcc/testsuite/gcc.target/riscv/movdilt.c new file mode 100644 index 0000000..0ba8da0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdilt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiltu-sfb.c b/gcc/testsuite/gcc.target/riscv/movdiltu-sfb.c new file mode 100644 index 0000000..fa799df --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiltu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgeu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiltu-thead.c b/gcc/testsuite/gcc.target/riscv/movdiltu-thead.c new file mode 100644 index 0000000..345c88b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiltu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiltu-ventana.c b/gcc/testsuite/gcc.target/riscv/movdiltu-ventana.c new file mode 100644 index 0000000..23f2572 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiltu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiltu-zicond.c b/gcc/testsuite/gcc.target/riscv/movdiltu-zicond.c new file mode 100644 index 0000000..641bfb1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiltu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdiltu.c b/gcc/testsuite/gcc.target/riscv/movdiltu.c new file mode 100644 index 0000000..0bbc006 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdiltu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (DI))) int_t; + +int_t +movdiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdine-sfb.c b/gcc/testsuite/gcc.target/riscv/movdine-sfb.c new file mode 100644 index 0000000..40aec9c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdine-sfb.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect short forward branch assembly like: + + beq a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdine-thead.c b/gcc/testsuite/gcc.target/riscv/movdine-thead.c new file mode 100644 index 0000000..2ea8388 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdine-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + th.mveqz a2,a3,a1 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdine-ventana.c b/gcc/testsuite/gcc.target/riscv/movdine-ventana.c new file mode 100644 index 0000000..0713bac --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdine-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdine-zicond.c b/gcc/testsuite/gcc.target/riscv/movdine-zicond.c new file mode 100644 index 0000000..825003b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdine-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movdine.c b/gcc/testsuite/gcc.target/riscv/movdine.c new file mode 100644 index 0000000..0180d05 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movdine.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (DI))) int_t; + +int_t +movdine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a5,a0,a1 + seqz a5,a5 + neg a5,a5 + and a3,a5,a3 + not a5,a5 + and a5,a5,a2 + or a0,a3,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibeq-thead.c b/gcc/testsuite/gcc.target/riscv/movsibeq-thead.c new file mode 100644 index 0000000..ac8496d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibeq-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibeq-ventana.c new file mode 100644 index 0000000..f9f69c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibeq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibeq-zicond.c new file mode 100644 index 0000000..d2cc9a0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibeq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibeq.c b/gcc/testsuite/gcc.target/riscv/movsibeq.c new file mode 100644 index 0000000..8f499de --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibeq.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + bne a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibfeq-ventana.c new file mode 100644 index 0000000..44ecadc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfeq-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibfeq-zicond.c new file mode 100644 index 0000000..addbb2e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfeq-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfeq.c b/gcc/testsuite/gcc.target/riscv/movsibfeq.c new file mode 100644 index 0000000..27b1014 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfeq.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfge-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibfge-ventana.c new file mode 100644 index 0000000..e285102 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfge-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfge-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibfge-zicond.c new file mode 100644 index 0000000..f696b33 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfge-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfge.c b/gcc/testsuite/gcc.target/riscv/movsibfge.c new file mode 100644 index 0000000..fdfdf20 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfge.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + fge.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibfgt-ventana.c new file mode 100644 index 0000000..f26577b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfgt-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibfgt-zicond.c new file mode 100644 index 0000000..4d1de86 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfgt-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfgt.c b/gcc/testsuite/gcc.target/riscv/movsibfgt.c new file mode 100644 index 0000000..20c55fc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfgt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + fgt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfle-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibfle-ventana.c new file mode 100644 index 0000000..a52721e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfle-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfle-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibfle-zicond.c new file mode 100644 index 0000000..b22292f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfle-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfle.c b/gcc/testsuite/gcc.target/riscv/movsibfle.c new file mode 100644 index 0000000..9e428ac --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfle.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + fle.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibflt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibflt-ventana.c new file mode 100644 index 0000000..5c40cb6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibflt-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibflt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibflt-zicond.c new file mode 100644 index 0000000..502a8e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibflt-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibflt.c b/gcc/testsuite/gcc.target/riscv/movsibflt.c new file mode 100644 index 0000000..6a5f9fb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibflt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + flt.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + beq a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfne-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibfne-ventana.c new file mode 100644 index 0000000..0f52852 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfne-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfne-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibfne-zicond.c new file mode 100644 index 0000000..5f8df56 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfne-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibfne.c b/gcc/testsuite/gcc.target/riscv/movsibfne.c new file mode 100644 index 0000000..88f1469 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibfne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=4 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + feq.d a4,fa0,fa1 + mv a5,a0 + mv a0,a1 + bne a4,zero,.L2 + mv a0,a5 +.L2: + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibge-thead.c b/gcc/testsuite/gcc.target/riscv/movsibge-thead.c new file mode 100644 index 0000000..3dd9119 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibge-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibge-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibge-ventana.c new file mode 100644 index 0000000..e40abbe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibge-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibge-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibge-zicond.c new file mode 100644 index 0000000..c7b62b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibge-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibge.c b/gcc/testsuite/gcc.target/riscv/movsibge.c new file mode 100644 index 0000000..6153d7f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibge.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + blt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgeu-thead.c b/gcc/testsuite/gcc.target/riscv/movsibgeu-thead.c new file mode 100644 index 0000000..4d850f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgeu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgeu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibgeu-ventana.c new file mode 100644 index 0000000..be7fa13 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgeu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgeu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibgeu-zicond.c new file mode 100644 index 0000000..6f8dacb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgeu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgeu.c b/gcc/testsuite/gcc.target/riscv/movsibgeu.c new file mode 100644 index 0000000..8d5363b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgeu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branched assembly like: + + bltu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgt-thead.c b/gcc/testsuite/gcc.target/riscv/movsibgt-thead.c new file mode 100644 index 0000000..7143c0d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgt-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibgt-ventana.c new file mode 100644 index 0000000..6664ff0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibgt-zicond.c new file mode 100644 index 0000000..09b82d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgt.c b/gcc/testsuite/gcc.target/riscv/movsibgt.c new file mode 100644 index 0000000..4851c6f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + ble a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgtu-thead.c b/gcc/testsuite/gcc.target/riscv/movsibgtu-thead.c new file mode 100644 index 0000000..21e418e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgtu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgtu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibgtu-ventana.c new file mode 100644 index 0000000..0716ba8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgtu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgtu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibgtu-zicond.c new file mode 100644 index 0000000..a8018cd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgtu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibgtu.c b/gcc/testsuite/gcc.target/riscv/movsibgtu.c new file mode 100644 index 0000000..bd9329d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibgtu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branched assembly like: + + bleu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsible-thead.c b/gcc/testsuite/gcc.target/riscv/movsible-thead.c new file mode 100644 index 0000000..abcdbdf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsible-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsible-ventana.c b/gcc/testsuite/gcc.target/riscv/movsible-ventana.c new file mode 100644 index 0000000..c49f12f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsible-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsible-zicond.c b/gcc/testsuite/gcc.target/riscv/movsible-zicond.c new file mode 100644 index 0000000..bb5fe35 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsible-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsible.c b/gcc/testsuite/gcc.target/riscv/movsible.c new file mode 100644 index 0000000..de2fca4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsible.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgt a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibleu-thead.c b/gcc/testsuite/gcc.target/riscv/movsibleu-thead.c new file mode 100644 index 0000000..1ddb03c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibleu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibleu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibleu-ventana.c new file mode 100644 index 0000000..8096888 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibleu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibleu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibleu-zicond.c new file mode 100644 index 0000000..2ded825 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibleu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibleu.c b/gcc/testsuite/gcc.target/riscv/movsibleu.c new file mode 100644 index 0000000..1787614 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibleu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branched assembly like: + + bgtu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiblt-thead.c b/gcc/testsuite/gcc.target/riscv/movsiblt-thead.c new file mode 100644 index 0000000..1459d37 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiblt-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiblt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsiblt-ventana.c new file mode 100644 index 0000000..47b611d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiblt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiblt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsiblt-zicond.c new file mode 100644 index 0000000..59e6b84 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiblt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiblt.c b/gcc/testsuite/gcc.target/riscv/movsiblt.c new file mode 100644 index 0000000..458c9f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiblt.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bge a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibltu-thead.c b/gcc/testsuite/gcc.target/riscv/movsibltu-thead.c new file mode 100644 index 0000000..89a0fab --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibltu-thead.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibltu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibltu-ventana.c new file mode 100644 index 0000000..8f45f02 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibltu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibltu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibltu-zicond.c new file mode 100644 index 0000000..0abb111 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibltu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibltu.c b/gcc/testsuite/gcc.target/riscv/movsibltu.c new file mode 100644 index 0000000..973beaa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibltu.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branched assembly like: + + bgeu a0,a1,.L2 + mv a3,a2 +.L2: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibne-thead.c b/gcc/testsuite/gcc.target/riscv/movsibne-thead.c new file mode 100644 index 0000000..a76744c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibne-thead.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" { xfail "*-*-*" } } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\s(?:th\\.mveqz|th\\.mvnez)\\s" { xfail "*-*-*" } } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibne-ventana.c b/gcc/testsuite/gcc.target/riscv/movsibne-ventana.c new file mode 100644 index 0000000..cc1961a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibne-ventana.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskc\\s" } } */ +/* { dg-final { scan-assembler-not "\\svt\\.maskcn\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibne-zicond.c b/gcc/testsuite/gcc.target/riscv/movsibne-zicond.c new file mode 100644 index 0000000..0bc2e26 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibne-zicond.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.eqz\\s" } } */ +/* { dg-final { scan-assembler-not "\\sczero\\.nez\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsibne.c b/gcc/testsuite/gcc.target/riscv/movsibne.c new file mode 100644 index 0000000..5b3e6ee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsibne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branched assembly like: + + beq a0,a1,.L3 + mv a0,a2 + ret +.L3: + mv a0,a3 + ret + */ + +/* { dg-final { scan-rtl-dump-not "Conversion succeeded on pass \[0-9\]+\\." "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\ssub\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsieq-sfb.c b/gcc/testsuite/gcc.target/riscv/movsieq-sfb.c new file mode 100644 index 0000000..8525f6a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsieq-sfb.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect short forward branch assembly like: + + bne a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsieq-thead.c b/gcc/testsuite/gcc.target/riscv/movsieq-thead.c new file mode 100644 index 0000000..35a1e91 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsieq-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsieq-ventana.c b/gcc/testsuite/gcc.target/riscv/movsieq-ventana.c new file mode 100644 index 0000000..65be52f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsieq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsieq-zicond.c b/gcc/testsuite/gcc.target/riscv/movsieq-zicond.c new file mode 100644 index 0000000..afa14c3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsieq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsieq.c b/gcc/testsuite/gcc.target/riscv/movsieq.c new file mode 100644 index 0000000..7d7e99d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsieq.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=7 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=7 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsieq (int_t w, int_t x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + sub a5,a0,a1 + snez a5,a5 + neg a5,a5 + and a3,a5,a3 + not a5,a5 + and a5,a5,a2 + or a0,a3,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifeq-sfb.c b/gcc/testsuite/gcc.target/riscv/movsifeq-sfb.c new file mode 100644 index 0000000..1f20bb4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifeq-sfb.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect short forward branch assembly like: + + feq.d a5,fa0,fa1 + beq a5,zero,1f # movcc + mv a1,a0 +1: + mv a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifeq-thead.c b/gcc/testsuite/gcc.target/riscv/movsifeq-thead.c new file mode 100644 index 0000000..e2e69e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifeq-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifeq-ventana.c b/gcc/testsuite/gcc.target/riscv/movsifeq-ventana.c new file mode 100644 index 0000000..9fb29aa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifeq-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + vt.maskcn a1,a1,a5 + vt.maskc a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifeq-zicond.c b/gcc/testsuite/gcc.target/riscv/movsifeq-zicond.c new file mode 100644 index 0000000..d967d32 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifeq-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + czero.nez a1,a1,a5 + czero.eqz a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifeq.c b/gcc/testsuite/gcc.target/riscv/movsifeq.c new file mode 100644 index 0000000..a4c0c67 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifeq.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifeq (double w, double x, int_t y, int_t z) +{ + return w == x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifge-sfb.c b/gcc/testsuite/gcc.target/riscv/movsifge-sfb.c new file mode 100644 index 0000000..c9f0e2d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifge-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + fge.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifge-thead.c b/gcc/testsuite/gcc.target/riscv/movsifge-thead.c new file mode 100644 index 0000000..893a522a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifge-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifge-ventana.c b/gcc/testsuite/gcc.target/riscv/movsifge-ventana.c new file mode 100644 index 0000000..26e55b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifge-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifge-zicond.c b/gcc/testsuite/gcc.target/riscv/movsifge-zicond.c new file mode 100644 index 0000000..e38aa80 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifge-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifge.c b/gcc/testsuite/gcc.target/riscv/movsifge.c new file mode 100644 index 0000000..c3f170e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifge.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifge (double w, double x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + fge.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifgt-sfb.c b/gcc/testsuite/gcc.target/riscv/movsifgt-sfb.c new file mode 100644 index 0000000..47ea2c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifgt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + fgt.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifgt-thead.c b/gcc/testsuite/gcc.target/riscv/movsifgt-thead.c new file mode 100644 index 0000000..0ec4e57 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifgt-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifgt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsifgt-ventana.c new file mode 100644 index 0000000..8896266 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifgt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifgt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsifgt-zicond.c new file mode 100644 index 0000000..bada72f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifgt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifgt.c b/gcc/testsuite/gcc.target/riscv/movsifgt.c new file mode 100644 index 0000000..68aca07 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifgt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifgt (double w, double x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + fgt.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifle-sfb.c b/gcc/testsuite/gcc.target/riscv/movsifle-sfb.c new file mode 100644 index 0000000..7cb9167 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifle-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + fle.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifle-thead.c b/gcc/testsuite/gcc.target/riscv/movsifle-thead.c new file mode 100644 index 0000000..b05a02a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifle-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifle-ventana.c b/gcc/testsuite/gcc.target/riscv/movsifle-ventana.c new file mode 100644 index 0000000..24b49d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifle-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifle-zicond.c b/gcc/testsuite/gcc.target/riscv/movsifle-zicond.c new file mode 100644 index 0000000..5aad910 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifle-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifle.c b/gcc/testsuite/gcc.target/riscv/movsifle.c new file mode 100644 index 0000000..3b1b06c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifle.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifle (double w, double x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + fle.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fge\\.d|fle\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiflt-sfb.c b/gcc/testsuite/gcc.target/riscv/movsiflt-sfb.c new file mode 100644 index 0000000..110e38a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiflt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + flt.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a0,a1 +1: + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiflt-thead.c b/gcc/testsuite/gcc.target/riscv/movsiflt-thead.c new file mode 100644 index 0000000..124c408 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiflt-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + th.mveqz a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiflt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsiflt-ventana.c new file mode 100644 index 0000000..911a502 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiflt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + vt.maskc a0,a0,a5 + vt.maskcn a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiflt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsiflt-zicond.c new file mode 100644 index 0000000..7db2b99 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiflt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + czero.eqz a0,a0,a5 + czero.nez a5,a1,a5 + or a0,a5,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiflt.c b/gcc/testsuite/gcc.target/riscv/movsiflt.c new file mode 100644 index 0000000..a74d859 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiflt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsiflt (double w, double x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + flt.d a5,fa0,fa1 + neg a5,a5 + and a0,a5,a0 + not a5,a5 + and a5,a5,a1 + or a0,a0,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through" "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:fgt\\.d|flt\\.d)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifne-sfb.c b/gcc/testsuite/gcc.target/riscv/movsifne-sfb.c new file mode 100644 index 0000000..e08a0e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifne-sfb.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect short forward branch assembly like: + + feq.d a5,fa0,fa1 + bne a5,zero,1f # movcc + mv a1,a0 +1: + mv a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifne-thead.c b/gcc/testsuite/gcc.target/riscv/movsifne-thead.c new file mode 100644 index 0000000..19a3950 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifne-thead.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + th.mvnez a0,a1,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifne-ventana.c b/gcc/testsuite/gcc.target/riscv/movsifne-ventana.c new file mode 100644 index 0000000..6c038fa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifne-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + vt.maskc a1,a1,a5 + vt.maskcn a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifne-zicond.c b/gcc/testsuite/gcc.target/riscv/movsifne-zicond.c new file mode 100644 index 0000000..2148f4b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifne-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + czero.eqz a1,a1,a5 + czero.nez a0,a0,a5 + or a0,a0,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsifne.c b/gcc/testsuite/gcc.target/riscv/movsifne.c new file mode 100644 index 0000000..f73f6f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsifne.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=5 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsifne (double w, double x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + feq.d a5,fa0,fa1 + neg a5,a5 + and a1,a5,a1 + not a5,a5 + and a0,a5,a0 + or a0,a1,a0 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\sfeq\\.d\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsige-sfb.c b/gcc/testsuite/gcc.target/riscv/movsige-sfb.c new file mode 100644 index 0000000..cc9f2b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsige-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + blt a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsige-thead.c b/gcc/testsuite/gcc.target/riscv/movsige-thead.c new file mode 100644 index 0000000..87ce0df --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsige-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsige-ventana.c b/gcc/testsuite/gcc.target/riscv/movsige-ventana.c new file mode 100644 index 0000000..8222e10 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsige-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsige-zicond.c b/gcc/testsuite/gcc.target/riscv/movsige-zicond.c new file mode 100644 index 0000000..4a8c09d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsige-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsige.c b/gcc/testsuite/gcc.target/riscv/movsige.c new file mode 100644 index 0000000..aabd182 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsige.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsige (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigeu-sfb.c b/gcc/testsuite/gcc.target/riscv/movsigeu-sfb.c new file mode 100644 index 0000000..20bbf51 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigeu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bltu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigeu-thead.c b/gcc/testsuite/gcc.target/riscv/movsigeu-thead.c new file mode 100644 index 0000000..d2f51ad --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigeu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigeu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsigeu-ventana.c new file mode 100644 index 0000000..448b807 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigeu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigeu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsigeu-zicond.c new file mode 100644 index 0000000..6c2ba09 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigeu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigeu.c b/gcc/testsuite/gcc.target/riscv/movsigeu.c new file mode 100644 index 0000000..2828e39 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigeu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigeu (int_t w, int_t x, int_t y, int_t z) +{ + return w >= x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigt-sfb.c b/gcc/testsuite/gcc.target/riscv/movsigt-sfb.c new file mode 100644 index 0000000..c494292 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + ble a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgt|ble)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigt-thead.c b/gcc/testsuite/gcc.target/riscv/movsigt-thead.c new file mode 100644 index 0000000..e99b79f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigt-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsigt-ventana.c new file mode 100644 index 0000000..750366d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsigt-zicond.c new file mode 100644 index 0000000..a117bc8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigt.c b/gcc/testsuite/gcc.target/riscv/movsigt.c new file mode 100644 index 0000000..5f4af28 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsigt (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigtu-sfb.c b/gcc/testsuite/gcc.target/riscv/movsigtu-sfb.c new file mode 100644 index 0000000..bfe4a5b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigtu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect short forward branch assembly like: + + bleu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigtu-thead.c b/gcc/testsuite/gcc.target/riscv/movsigtu-thead.c new file mode 100644 index 0000000..33770e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigtu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigtu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsigtu-ventana.c new file mode 100644 index 0000000..73a8c53 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigtu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigtu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsigtu-zicond.c new file mode 100644 index 0000000..a42578d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigtu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsigtu.c b/gcc/testsuite/gcc.target/riscv/movsigtu.c new file mode 100644 index 0000000..24ee2c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsigtu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsigtu (int_t w, int_t x, int_t y, int_t z) +{ + return w > x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsile-sfb.c b/gcc/testsuite/gcc.target/riscv/movsile-sfb.c new file mode 100644 index 0000000..82a6995 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsile-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgt a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsile-thead.c b/gcc/testsuite/gcc.target/riscv/movsile-thead.c new file mode 100644 index 0000000..6e724a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsile-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsile-ventana.c b/gcc/testsuite/gcc.target/riscv/movsile-ventana.c new file mode 100644 index 0000000..96bbe92 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsile-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsile-zicond.c b/gcc/testsuite/gcc.target/riscv/movsile-zicond.c new file mode 100644 index 0000000..33f9ebd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsile-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsile.c b/gcc/testsuite/gcc.target/riscv/movsile.c new file mode 100644 index 0000000..8e9fe6a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsile.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsile (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsileu-sfb.c b/gcc/testsuite/gcc.target/riscv/movsileu-sfb.c new file mode 100644 index 0000000..e8b7c45 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsileu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgtu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsileu-thead.c b/gcc/testsuite/gcc.target/riscv/movsileu-thead.c new file mode 100644 index 0000000..fb72753 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsileu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a0,a0,a1 + th.mvnez a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsileu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsileu-ventana.c new file mode 100644 index 0000000..ff64c38 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsileu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + vt.maskc a3,a3,a1 + vt.maskcn a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsileu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsileu-zicond.c new file mode 100644 index 0000000..29e4fc4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsileu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + czero.eqz a3,a3,a1 + czero.nez a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsileu.c b/gcc/testsuite/gcc.target/riscv/movsileu.c new file mode 100644 index 0000000..a0b733e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsileu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsileu (int_t w, int_t x, int_t y, int_t z) +{ + return w <= x ? y : z; +} + +/* Expect branchless assembly like: + + sgtu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsilt-sfb.c b/gcc/testsuite/gcc.target/riscv/movsilt-sfb.c new file mode 100644 index 0000000..822c778 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsilt-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + bge a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bge|bgt|ble|blt)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgt|slt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsilt-thead.c b/gcc/testsuite/gcc.target/riscv/movsilt-thead.c new file mode 100644 index 0000000..ca957b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsilt-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsilt-ventana.c b/gcc/testsuite/gcc.target/riscv/movsilt-ventana.c new file mode 100644 index 0000000..63df590 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsilt-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsilt-zicond.c b/gcc/testsuite/gcc.target/riscv/movsilt-zicond.c new file mode 100644 index 0000000..11ce70f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsilt-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsilt.c b/gcc/testsuite/gcc.target/riscv/movsilt.c new file mode 100644 index 0000000..109f67e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsilt.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsilt (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + slt a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgt|slt)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bge|bgt|ble|blt)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiltu-sfb.c b/gcc/testsuite/gcc.target/riscv/movsiltu-sfb.c new file mode 100644 index 0000000..5fd441c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiltu-sfb.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect short forward branch assembly like: + + bgeu a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:bgeu|bgtu|bleu|bltu)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:sgtu|sltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiltu-thead.c b/gcc/testsuite/gcc.target/riscv/movsiltu-thead.c new file mode 100644 index 0000000..680f673 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiltu-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a0,a0,a1 + th.mveqz a2,a3,a0 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiltu-ventana.c b/gcc/testsuite/gcc.target/riscv/movsiltu-ventana.c new file mode 100644 index 0000000..05ee813 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiltu-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiltu-zicond.c b/gcc/testsuite/gcc.target/riscv/movsiltu-zicond.c new file mode 100644 index 0000000..79e7850 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiltu-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=4 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsiltu.c b/gcc/testsuite/gcc.target/riscv/movsiltu.c new file mode 100644 index 0000000..a7d4caf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsiltu.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef unsigned int __attribute__ ((mode (SI))) int_t; + +int_t +movsiltu (int_t w, int_t x, int_t y, int_t z) +{ + return w < x ? y : z; +} + +/* Expect branchless assembly like: + + sltu a1,a0,a1 + neg a1,a1 + and a3,a1,a3 + not a1,a1 + and a1,a1,a2 + or a0,a3,a1 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:sgtu|sltu)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:bgeu|bgtu|bleu|bltu)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsine-sfb.c b/gcc/testsuite/gcc.target/riscv/movsine-sfb.c new file mode 100644 index 0000000..f7ac7c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsine-sfb.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-7-series -mbranch-cost=1 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect short forward branch assembly like: + + beq a0,a1,1f # movcc + mv a3,a2 +1: + mv a0,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\s(?:beq|bne)\\s\[^\\s\]+\\s# movcc\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsine-thead.c b/gcc/testsuite/gcc.target/riscv/movsine-thead.c new file mode 100644 index 0000000..fc0d1e7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsine-thead.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xtheadcondmov -mtune=thead-c906 -mbranch-cost=2 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + th.mveqz a2,a3,a1 + mv a0,a2 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:th\\.mveqz|th\\.mvnez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsine-ventana.c b/gcc/testsuite/gcc.target/riscv/movsine-ventana.c new file mode 100644 index 0000000..c9a2538 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsine-ventana.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_xventanacondops -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + vt.maskcn a3,a3,a1 + vt.maskc a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskc\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\svt\\.maskcn\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsine-zicond.c b/gcc/testsuite/gcc.target/riscv/movsine-zicond.c new file mode 100644 index 0000000..326c32c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsine-zicond.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mtune=rocket -mbranch-cost=3 -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a1,a0,a1 + czero.nez a3,a3,a1 + czero.eqz a1,a2,a1 + or a0,a1,a3 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.eqz\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sczero\\.nez\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:seqz|snez)\\s" } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/movsine.c b/gcc/testsuite/gcc.target/riscv/movsine.c new file mode 100644 index 0000000..60dee08 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/movsine.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-Os" "-Oz" } } */ +/* { dg-options "-march=rv64gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc -mtune=sifive-5-series -mbranch-cost=6 -mmovcc -fdump-rtl-ce1" { target { rv32 } } } */ + +typedef int __attribute__ ((mode (SI))) int_t; + +int_t +movsine (int_t w, int_t x, int_t y, int_t z) +{ + return w != x ? y : z; +} + +/* Expect branchless assembly like: + + sub a5,a0,a1 + seqz a5,a5 + neg a5,a5 + and a3,a5,a3 + not a5,a5 + and a5,a5,a2 + or a0,a3,a5 + */ + +/* { dg-final { scan-rtl-dump-times "Conversion succeeded on pass 1\\." 1 "ce1" } } */ +/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_try_cmove" 1 "ce1" } } */ +/* { dg-final { scan-assembler-times "\\ssub\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\s(?:seqz|snez)\\s" 1 } } */ +/* { dg-final { scan-assembler-not "\\s(?:beq|bne)\\s" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/predef-1.c b/gcc/testsuite/gcc.target/riscv/predef-1.c index 9dddc18..250812a 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-1.c +++ b/gcc/testsuite/gcc.target/riscv/predef-1.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-2.c b/gcc/testsuite/gcc.target/riscv/predef-2.c index 755fe4e..fa5bdea 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-2.c +++ b/gcc/testsuite/gcc.target/riscv/predef-2.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if !defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-3.c b/gcc/testsuite/gcc.target/riscv/predef-3.c index 5136453..868b561 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-3.c +++ b/gcc/testsuite/gcc.target/riscv/predef-3.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if !defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-4.c b/gcc/testsuite/gcc.target/riscv/predef-4.c index 76b6fee..ba8b5c7 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-4.c +++ b/gcc/testsuite/gcc.target/riscv/predef-4.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if !defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-5.c b/gcc/testsuite/gcc.target/riscv/predef-5.c index 54a5150..560d6ea 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-5.c +++ b/gcc/testsuite/gcc.target/riscv/predef-5.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-6.c b/gcc/testsuite/gcc.target/riscv/predef-6.c index f61709f..8987b72 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-6.c +++ b/gcc/testsuite/gcc.target/riscv/predef-6.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if !defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-7.c b/gcc/testsuite/gcc.target/riscv/predef-7.c index 4121755..833e2be 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-7.c +++ b/gcc/testsuite/gcc.target/riscv/predef-7.c @@ -13,6 +13,9 @@ int main () { #if !defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-8.c b/gcc/testsuite/gcc.target/riscv/predef-8.c index 982056a..8fa8b42 100644 --- a/gcc/testsuite/gcc.target/riscv/predef-8.c +++ b/gcc/testsuite/gcc.target/riscv/predef-8.c @@ -13,6 +13,9 @@ int main () { #if defined(__riscv_32e) #error "__riscv_32e" #endif +#if defined(__riscv_64e) +#error "__riscv_64e" +#endif #if defined(__riscv_atomic) #error "__riscv_atomic" diff --git a/gcc/testsuite/gcc.target/riscv/predef-9.c b/gcc/testsuite/gcc.target/riscv/predef-9.c new file mode 100644 index 0000000..cc3abc9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/predef-9.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64em -mabi=lp64e -mno-div -mcmodel=medlow" } */ + +int main () { +#if !defined(__riscv) +#error "__riscv" +#endif + +#if defined(__riscv_compressed) +#error "__riscv_compressed" +#endif + +#if defined(__riscv_32e) +#error "__riscv_32e" +#endif +#if !defined(__riscv_64e) +#error "__riscv_64e" +#endif + +#if defined(__riscv_atomic) +#error "__riscv_atomic" +#endif + +#if !defined(__riscv_mul) +#error "__riscv_mul" +#endif +#if defined(__riscv_div) +#error "__riscv_div" +#endif +#if defined(__riscv_muldiv) +#error "__riscv_muldiv" +#endif + +#if __riscv_xlen != 64 +#error "__riscv_xlen" +#endif + +#if defined(__riscv_fdiv) +#error "__riscv_fdiv" +#endif +#if defined(__riscv_fsqrt) +#error "__riscv_fsqrt" +#endif + +#if !defined(__riscv_abi_rve) +#error "__riscv_abi_rve" +#endif +#if !defined(__riscv_float_abi_soft) +#error "__riscv_float_abi_soft" +#endif +#if defined(__riscv_float_abi_single) +#error "__riscv_float_abi_single" +#endif +#if defined(__riscv_float_abi_double) +#error "__riscv_float_abi_double" +#endif + +#if !defined(__riscv_cmodel_medlow) +#error "__riscv_cmodel_medlow" +#endif +#if defined(__riscv_cmodel_medany) +#error "__riscv_cmodel_medlow" +#endif + + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-1.c new file mode 100644 index 0000000..8ae5106 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t +#define INDEX16 uint16_t +#define INDEX32 uint32_t +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-10.c new file mode 100644 index 0000000..d705c92 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-10.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-11.c new file mode 100644 index 0000000..4e183cd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-11.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define TEST_LOOP(DATA_TYPE) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict *src) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += *src[i]; \ + } + +#define TEST_ALL(T) \ + T (int8_t) \ + T (uint8_t) \ + T (int16_t) \ + T (uint16_t) \ + T (_Float16) \ + T (int32_t) \ + T (uint32_t) \ + T (float) \ + T (int64_t) \ + T (uint64_t) \ + T (double) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-12.c index 6277682..6277682 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-12.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-12.c diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-2.c new file mode 100644 index 0000000..e4e42fe --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-2.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t +#define INDEX16 int16_t +#define INDEX32 int32_t +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-3.c new file mode 100644 index 0000000..e385fee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-3.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-4.c new file mode 100644 index 0000000..e5cb19d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-4.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-5.c new file mode 100644 index 0000000..a437e73 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-5.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 uint16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-6.c new file mode 100644 index 0000000..487dca9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-6.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 int16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-7.c new file mode 100644 index 0000000..ff91929 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-7.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 uint32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-8.c new file mode 100644 index 0000000..81df57f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-8.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 int32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-9.c new file mode 100644 index 0000000..238b6bc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_32-9.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-1.c index 3b26bf1..eabe012 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-10.c index 63949cb..ba4bc78 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-11.c index 8dc1da3..e75b694 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-11.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-11.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-12.c new file mode 100644 index 0000000..d8daf3f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-12.c @@ -0,0 +1,110 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-vect-cost-model -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define TEST_LOOP(DATA_TYPE, INDEX_TYPE) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE##_##INDEX_TYPE (DATA_TYPE *restrict y, DATA_TYPE *restrict x, \ + INDEX_TYPE *restrict index) \ + { \ + for (int i = 0; i < 100; ++i) \ + { \ + y[i * 2] = x[index[i * 2]] + 1; \ + y[i * 2 + 1] = x[index[i * 2 + 1]] + 2; \ + } \ + } + +TEST_LOOP (int8_t, int8_t) +TEST_LOOP (uint8_t, int8_t) +TEST_LOOP (int16_t, int8_t) +TEST_LOOP (uint16_t, int8_t) +TEST_LOOP (int32_t, int8_t) +TEST_LOOP (uint32_t, int8_t) +TEST_LOOP (int64_t, int8_t) +TEST_LOOP (uint64_t, int8_t) +TEST_LOOP (_Float16, int8_t) +TEST_LOOP (float, int8_t) +TEST_LOOP (double, int8_t) +TEST_LOOP (int8_t, int16_t) +TEST_LOOP (uint8_t, int16_t) +TEST_LOOP (int16_t, int16_t) +TEST_LOOP (uint16_t, int16_t) +TEST_LOOP (int32_t, int16_t) +TEST_LOOP (uint32_t, int16_t) +TEST_LOOP (int64_t, int16_t) +TEST_LOOP (uint64_t, int16_t) +TEST_LOOP (_Float16, int16_t) +TEST_LOOP (float, int16_t) +TEST_LOOP (double, int16_t) +TEST_LOOP (int8_t, int32_t) +TEST_LOOP (uint8_t, int32_t) +TEST_LOOP (int16_t, int32_t) +TEST_LOOP (uint16_t, int32_t) +TEST_LOOP (int32_t, int32_t) +TEST_LOOP (uint32_t, int32_t) +TEST_LOOP (int64_t, int32_t) +TEST_LOOP (uint64_t, int32_t) +TEST_LOOP (_Float16, int32_t) +TEST_LOOP (float, int32_t) +TEST_LOOP (double, int32_t) +TEST_LOOP (int8_t, int64_t) +TEST_LOOP (uint8_t, int64_t) +TEST_LOOP (int16_t, int64_t) +TEST_LOOP (uint16_t, int64_t) +TEST_LOOP (int32_t, int64_t) +TEST_LOOP (uint32_t, int64_t) +TEST_LOOP (int64_t, int64_t) +TEST_LOOP (uint64_t, int64_t) +TEST_LOOP (_Float16, int64_t) +TEST_LOOP (float, int64_t) +TEST_LOOP (double, int64_t) +TEST_LOOP (int8_t, uint8_t) +TEST_LOOP (uint8_t, uint8_t) +TEST_LOOP (int16_t, uint8_t) +TEST_LOOP (uint16_t, uint8_t) +TEST_LOOP (int32_t, uint8_t) +TEST_LOOP (uint32_t, uint8_t) +TEST_LOOP (int64_t, uint8_t) +TEST_LOOP (uint64_t, uint8_t) +TEST_LOOP (_Float16, uint8_t) +TEST_LOOP (float, uint8_t) +TEST_LOOP (double, uint8_t) +TEST_LOOP (int8_t, uint16_t) +TEST_LOOP (uint8_t, uint16_t) +TEST_LOOP (int16_t, uint16_t) +TEST_LOOP (uint16_t, uint16_t) +TEST_LOOP (int32_t, uint16_t) +TEST_LOOP (uint32_t, uint16_t) +TEST_LOOP (int64_t, uint16_t) +TEST_LOOP (uint64_t, uint16_t) +TEST_LOOP (_Float16, uint16_t) +TEST_LOOP (float, uint16_t) +TEST_LOOP (double, uint16_t) +TEST_LOOP (int8_t, uint32_t) +TEST_LOOP (uint8_t, uint32_t) +TEST_LOOP (int16_t, uint32_t) +TEST_LOOP (uint16_t, uint32_t) +TEST_LOOP (int32_t, uint32_t) +TEST_LOOP (uint32_t, uint32_t) +TEST_LOOP (int64_t, uint32_t) +TEST_LOOP (uint64_t, uint32_t) +TEST_LOOP (_Float16, uint32_t) +TEST_LOOP (float, uint32_t) +TEST_LOOP (double, uint32_t) +TEST_LOOP (int8_t, uint64_t) +TEST_LOOP (uint8_t, uint64_t) +TEST_LOOP (int16_t, uint64_t) +TEST_LOOP (uint16_t, uint64_t) +TEST_LOOP (int32_t, uint64_t) +TEST_LOOP (uint32_t, uint64_t) +TEST_LOOP (int64_t, uint64_t) +TEST_LOOP (uint64_t, uint64_t) +TEST_LOOP (_Float16, uint64_t) +TEST_LOOP (float, uint64_t) +TEST_LOOP (double, uint64_t) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 88 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-2.c index 89e4b40..3389bc4 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-3.c index 02fd37c..b23603a 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-4.c index af6a76a..0247103 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-5.c index bd9a449..19ff214 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-6.c index 6d776af..fd7684b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-7.c index 040300a..9800b93 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-8.c index 9223bf0..4f84fe1 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-9.c index 2e06fe6..41a7ae5 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_64-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-1.c index 232873c..3ca1b0c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-1.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-1.c" +#include "gather_load_64-1.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-10.c index 9696a21..ef1517a 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-10.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-10.c" +#include "gather_load_64-10.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-11.c index 459a1a8..c435584 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-11.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-11.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-11.c" +#include "gather_load_64-11.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-12.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-12.c index 1cbf507..d48d529 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-12.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-12.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-12.c" +#include "gather_load_64-12.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-2.c index 93a07e0..b1290ec 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-2.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-2.c" +#include "gather_load_64-2.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-3.c index f318a43..8b86870 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-3.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-3.c" +#include "gather_load_64-3.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-4.c index a210cdf..2085474 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-4.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-4.c" +#include "gather_load_64-4.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-5.c index ade9175..ad91813 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-5.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-5.c" +#include "gather_load_64-5.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-6.c index f5bdece..53b3254 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-6.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-6.c" +#include "gather_load_64-6.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-7.c index 47a1783..8e135a7 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-7.c @@ -5,7 +5,7 @@ compiles properly. */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "gather_load-7.c" +#include "gather_load_64-7.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-8.c index 1ce18040..8f13ec6 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-8.c @@ -5,7 +5,7 @@ compiles properly. */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "gather_load-8.c" +#include "gather_load_64-8.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-9.c index 3c08c63..2e17075 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/gather_load_run-9.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "gather_load-9.c" +#include "gather_load_64-9.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-1.c index abab3b9..c0b5833 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-1.c @@ -37,3 +37,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-10.c index 61ab1fb..9e4fcee 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-10.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-11.c index e574181..e574181 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-11.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-11.c diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-2.c index cc5f52e..aadc020 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-2.c @@ -37,3 +37,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-3.c index 311e25e..b547dd6 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-3.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-4.c index 9223df9..ac60125 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-4.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-5.c index 9ec7e60..f003a17 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-5.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-6.c index ff18009..d1d9581 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-6.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-7.c index fd05df7..c8b5cea 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-7.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-8.c index a58c1c2..dfb8a93 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-8.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-9.c index 36947db..32ddba6 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_32-9.c @@ -34,3 +34,5 @@ TEST_ALL (TEST_LOOP) /* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ /* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-1.c new file mode 100644 index 0000000..154c535 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t +#define INDEX16 uint16_t +#define INDEX32 uint32_t +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-10.c new file mode 100644 index 0000000..c0fe926 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-10.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-11.c new file mode 100644 index 0000000..2a38273 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-11.c @@ -0,0 +1,114 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define TEST_LOOP(DATA_TYPE, INDEX_TYPE) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE##_##INDEX_TYPE (DATA_TYPE *restrict y, DATA_TYPE *restrict x, \ + INDEX_TYPE *restrict index, \ + INDEX_TYPE *restrict cond) \ + { \ + for (int i = 0; i < 100; ++i) \ + { \ + if (cond[i * 2]) \ + y[i * 2] = x[index[i * 2]] + 1; \ + if (cond[i * 2 + 1]) \ + y[i * 2 + 1] = x[index[i * 2 + 1]] + 2; \ + } \ + } + +TEST_LOOP (int8_t, int8_t) +TEST_LOOP (uint8_t, int8_t) +TEST_LOOP (int16_t, int8_t) +TEST_LOOP (uint16_t, int8_t) +TEST_LOOP (int32_t, int8_t) +TEST_LOOP (uint32_t, int8_t) +TEST_LOOP (int64_t, int8_t) +TEST_LOOP (uint64_t, int8_t) +TEST_LOOP (_Float16, int8_t) +TEST_LOOP (float, int8_t) +TEST_LOOP (double, int8_t) +TEST_LOOP (int8_t, int16_t) +TEST_LOOP (uint8_t, int16_t) +TEST_LOOP (int16_t, int16_t) +TEST_LOOP (uint16_t, int16_t) +TEST_LOOP (int32_t, int16_t) +TEST_LOOP (uint32_t, int16_t) +TEST_LOOP (int64_t, int16_t) +TEST_LOOP (uint64_t, int16_t) +TEST_LOOP (_Float16, int16_t) +TEST_LOOP (float, int16_t) +TEST_LOOP (double, int16_t) +TEST_LOOP (int8_t, int32_t) +TEST_LOOP (uint8_t, int32_t) +TEST_LOOP (int16_t, int32_t) +TEST_LOOP (uint16_t, int32_t) +TEST_LOOP (int32_t, int32_t) +TEST_LOOP (uint32_t, int32_t) +TEST_LOOP (int64_t, int32_t) +TEST_LOOP (uint64_t, int32_t) +TEST_LOOP (_Float16, int32_t) +TEST_LOOP (float, int32_t) +TEST_LOOP (double, int32_t) +TEST_LOOP (int8_t, int64_t) +TEST_LOOP (uint8_t, int64_t) +TEST_LOOP (int16_t, int64_t) +TEST_LOOP (uint16_t, int64_t) +TEST_LOOP (int32_t, int64_t) +TEST_LOOP (uint32_t, int64_t) +TEST_LOOP (int64_t, int64_t) +TEST_LOOP (uint64_t, int64_t) +TEST_LOOP (_Float16, int64_t) +TEST_LOOP (float, int64_t) +TEST_LOOP (double, int64_t) +TEST_LOOP (int8_t, uint8_t) +TEST_LOOP (uint8_t, uint8_t) +TEST_LOOP (int16_t, uint8_t) +TEST_LOOP (uint16_t, uint8_t) +TEST_LOOP (int32_t, uint8_t) +TEST_LOOP (uint32_t, uint8_t) +TEST_LOOP (int64_t, uint8_t) +TEST_LOOP (uint64_t, uint8_t) +TEST_LOOP (_Float16, uint8_t) +TEST_LOOP (float, uint8_t) +TEST_LOOP (double, uint8_t) +TEST_LOOP (int8_t, uint16_t) +TEST_LOOP (uint8_t, uint16_t) +TEST_LOOP (int16_t, uint16_t) +TEST_LOOP (uint16_t, uint16_t) +TEST_LOOP (int32_t, uint16_t) +TEST_LOOP (uint32_t, uint16_t) +TEST_LOOP (int64_t, uint16_t) +TEST_LOOP (uint64_t, uint16_t) +TEST_LOOP (_Float16, uint16_t) +TEST_LOOP (float, uint16_t) +TEST_LOOP (double, uint16_t) +TEST_LOOP (int8_t, uint32_t) +TEST_LOOP (uint8_t, uint32_t) +TEST_LOOP (int16_t, uint32_t) +TEST_LOOP (uint16_t, uint32_t) +TEST_LOOP (int32_t, uint32_t) +TEST_LOOP (uint32_t, uint32_t) +TEST_LOOP (int64_t, uint32_t) +TEST_LOOP (uint64_t, uint32_t) +TEST_LOOP (_Float16, uint32_t) +TEST_LOOP (float, uint32_t) +TEST_LOOP (double, uint32_t) +TEST_LOOP (int8_t, uint64_t) +TEST_LOOP (uint8_t, uint64_t) +TEST_LOOP (int16_t, uint64_t) +TEST_LOOP (uint16_t, uint64_t) +TEST_LOOP (int32_t, uint64_t) +TEST_LOOP (uint32_t, uint64_t) +TEST_LOOP (int64_t, uint64_t) +TEST_LOOP (uint64_t, uint64_t) +TEST_LOOP (_Float16, uint64_t) +TEST_LOOP (float, uint64_t) +TEST_LOOP (double, uint64_t) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 88 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-assembler-not {vlse64\.v\s+v[0-9]+,\s*0\([a-x0-9]+\),\s*zero} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-2.c new file mode 100644 index 0000000..b586d64 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-2.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t +#define INDEX16 int16_t +#define INDEX32 int32_t +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-3.c new file mode 100644 index 0000000..11818a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-3.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-4.c new file mode 100644 index 0000000..3660198 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-4.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-5.c new file mode 100644 index 0000000..3058974 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-5.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 uint16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-6.c new file mode 100644 index 0000000..a8cc99a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-6.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 int16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-7.c new file mode 100644 index 0000000..9639235 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-7.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 uint32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-8.c new file mode 100644 index 0000000..a2526ea --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-8.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 int32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-9.c new file mode 100644 index 0000000..0eb5744 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_64-9.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fno-schedule-insns -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[i] += src[indices[i]]; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.GATHER_LOAD" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_GATHER_LOAD" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-1.c index fb34285..913d2f7 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-1.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-1.c" +#include "mask_gather_load_64-1.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-10.c index 531f298..3336a18 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-10.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-10.c" +#include "mask_gather_load_64-10.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-11.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-11.c index 0ce20a8..eba0be9 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-11.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-11.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "mask_gather_load-11.c" +#include "mask_gather_load_64-11.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-2.c index 8bb78aea..50a9490 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-2.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-2.c" +#include "mask_gather_load_64-2.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-3.c index 0472ed0..ba93eb8 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-3.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-3.c" +#include "mask_gather_load_64-3.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-4.c index 4fab81a..d96fc13 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-4.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-4.c" +#include "mask_gather_load_64-4.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-5.c index 8db1ea1..05fdae3 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-5.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-5.c" +#include "mask_gather_load_64-5.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-6.c index d58bc80..175ce08 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-6.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-6.c" +#include "mask_gather_load_64-6.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-7.c index cc49571..5a82541 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-7.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "mask_gather_load-7.c" +#include "mask_gather_load_64-7.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-8.c index 4745985..4195f26 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-8.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "mask_gather_load-8.c" +#include "mask_gather_load_64-8.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-9.c index 32924f0..686d0a5 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_gather_load_run-9.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_gather_load-9.c" +#include "mask_gather_load_64-9.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-1.c new file mode 100644 index 0000000..39e09f4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t +#define INDEX16 uint16_t +#define INDEX32 uint32_t +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-10.c new file mode 100644 index 0000000..b1a2344 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-10.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-2.c new file mode 100644 index 0000000..b522193 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-2.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t +#define INDEX16 int16_t +#define INDEX32 int32_t +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-3.c new file mode 100644 index 0000000..4706d0f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-3.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-4.c new file mode 100644 index 0000000..aec7a93 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-4.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-5.c new file mode 100644 index 0000000..286e2db --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-5.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 uint16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-6.c new file mode 100644 index 0000000..7674e2a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-6.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 int16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-7.c new file mode 100644 index 0000000..1738f73 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-7.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 uint32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-8.c new file mode 100644 index 0000000..d819a1a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-8.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 int32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-9.c new file mode 100644 index 0000000..ee453e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_32-9.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* For some reason we exceed + the default code model's +-2 GiB limits. We should investigate why and + add a proper description here. For now just make sure the test case + compiles properly. */ +/* { dg-additional-options "-mcmodel=medany" } */ + +#include <stdint-gcc.h> + +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices, INDEX##BITS *restrict cond) \ + { \ + for (int i = 0; i < 128; ++i) \ + if (cond[i]) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-1.c index 0099ed3..27c982a 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-10.c index 089ec48..93f3369 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-2.c index 57a1ace..cbb2250 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-3.c index ba89eb3..93a8405 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-4.c index 2d6499f..c5816e0 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-5.c index f55db71..c140d05 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-6.c index a7ec279..41a03d3 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-7.c index b7bd3f4..f29ae25 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-8.c index f2ab865..8d72d98 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-9.c index 42ce1c5..dfd9412 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_64-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ /* For some reason we exceed the default code model's +-2 GiB limits. We should investigate why and add a proper description here. For now just make sure the test case diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-1.c index cf89555..077bf82 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-1.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-1.c" +#include "mask_scatter_store_64-1.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-10.c index 6e5dc5d..a1e8df1 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-10.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-10.c" +#include "mask_scatter_store_64-10.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-2.c index 197b443..5ee2717 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-2.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-2.c" +#include "mask_scatter_store_64-2.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-3.c index 81059e4..b77fb63 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-3.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-3.c" +#include "mask_scatter_store_64-3.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-4.c index a50b6d2..0a8b4a5 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-4.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-4.c" +#include "mask_scatter_store_64-4.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-5.c index 645e3a5..8eca62b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-5.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-5.c" +#include "mask_scatter_store_64-5.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-6.c index 52032ba..4bcaf42 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-6.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-6.c" +#include "mask_scatter_store_64-6.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-7.c index 38b0595..7e4b1d8 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-7.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "mask_scatter_store-7.c" +#include "mask_scatter_store_64-7.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-8.c index fcb3110..0189aa8 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-8.c @@ -5,7 +5,7 @@ compiles properly. */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "mask_scatter_store-8.c" +#include "mask_scatter_store_64-8.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-9.c index c120e68..e2a3a8c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/mask_scatter_store_run-9.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "mask_scatter_store-9.c" +#include "mask_scatter_store_64-9.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-1.c new file mode 100644 index 0000000..4ad244b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t +#define INDEX16 uint16_t +#define INDEX32 uint32_t +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-10.c new file mode 100644 index 0000000..a44cbc1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-10.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 int64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-2.c new file mode 100644 index 0000000..35e9701 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-2.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 uint8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-4.c new file mode 100644 index 0000000..fb72b09 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-4.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX8 int8_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 8) \ + T (uint8_t, 8) \ + T (int16_t, 8) \ + T (uint16_t, 8) \ + T (_Float16, 8) \ + T (int32_t, 8) \ + T (uint32_t, 8) \ + T (float, 8) \ + T (int64_t, 8) \ + T (uint64_t, 8) \ + T (double, 8) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-5.c new file mode 100644 index 0000000..7b562bd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-5.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 uint16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-6.c new file mode 100644 index 0000000..67ea0e0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-6.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX16 int16_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 16) \ + T (uint8_t, 16) \ + T (int16_t, 16) \ + T (uint16_t, 16) \ + T (_Float16, 16) \ + T (int32_t, 16) \ + T (uint32_t, 16) \ + T (float, 16) \ + T (int64_t, 16) \ + T (uint64_t, 16) \ + T (double, 16) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-7.c new file mode 100644 index 0000000..76f8485 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-7.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 uint32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-8.c new file mode 100644 index 0000000..e6e4901 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-8.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX32 int32_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 32) \ + T (uint8_t, 32) \ + T (int16_t, 32) \ + T (uint16_t, 32) \ + T (_Float16, 32) \ + T (int32_t, 32) \ + T (uint32_t, 32) \ + T (float, 32) \ + T (int64_t, 32) \ + T (uint64_t, 32) \ + T (double, 32) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-9.c new file mode 100644 index 0000000..81eb935 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_32-9.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ + +#include <stdint-gcc.h> + +#define INDEX64 uint64_t + +#define TEST_LOOP(DATA_TYPE, BITS) \ + void __attribute__ ((noinline, noclone)) \ + f_##DATA_TYPE (DATA_TYPE *restrict dest, DATA_TYPE *restrict src, \ + INDEX##BITS *restrict indices) \ + { \ + for (int i = 0; i < 128; ++i) \ + dest[indices[i]] = src[i] + 1; \ + } + +#define TEST_ALL(T) \ + T (int8_t, 64) \ + T (uint8_t, 64) \ + T (int16_t, 64) \ + T (uint16_t, 64) \ + T (_Float16, 64) \ + T (int32_t, 64) \ + T (uint32_t, 64) \ + T (float, 64) \ + T (int64_t, 64) \ + T (uint64_t, 64) \ + T (double, 64) + +TEST_ALL (TEST_LOOP) + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 11 "vect" } } */ +/* { dg-final { scan-tree-dump " \.MASK_LEN_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-tree-dump-not " \.MASK_SCATTER_STORE" "vect" } } */ +/* { dg-final { scan-assembler-not {vluxei64\.v} } } */ +/* { dg-final { scan-assembler-not {vsuxei64\.v} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-1.c index 28c4bae..343a365 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-10.c index 2cd3e72..76b0b07 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-2.c index ee44f41..7eb8819 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-3.c index 899b05f..47e8ce3 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-3.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-4.c index ff6d90c..5c51741 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-4.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-5.c index 212bd2d..cc0b2fe 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-5.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-6.c index 4b6b39d..3408cbd 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-7.c index 2415c69..f45c9bc 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-7.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-8.c index 4c2fcb1..64fe305 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-8.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-9.c index 0f4f94c..bd1538d 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_64-9.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-additional-options "-march=rv32gcv_zvfh -mabi=ilp32d -fdump-tree-vect-details" } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d -fdump-tree-vect-details" } */ #include <stdint-gcc.h> diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-1.c index 91edba7..ec1e020 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-1.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-1.c" +#include "scatter_store_64-1.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-10.c index 40e34c6..d61a37a 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-10.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-10.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-10.c" +#include "scatter_store_64-10.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-2.c index 721c6f6..c1c3200 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-2.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "scatter_store-2.c" +#include "scatter_store_64-2.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-3.c index 8d268a6..8234f84 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-3.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-3.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-3.c" +#include "scatter_store_64-3.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-4.c index 3931a81..b137e1d 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-4.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-4.c" +#include "scatter_store_64-4.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-5.c index ff30630..1290f87 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-5.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-5.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-5.c" +#include "scatter_store_64-5.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-6.c index a30c47d..79b1ea7 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-6.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-6.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ -#include "scatter_store-6.c" +#include "scatter_store_64-6.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-7.c index 94ab404..c204e7c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-7.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-7.c @@ -5,7 +5,7 @@ compiles properly. */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "scatter_store-7.c" +#include "scatter_store_64-7.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-8.c index 16c1e17..1dafaba 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-8.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-8.c @@ -5,7 +5,7 @@ compiles properly. */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "scatter_store-8.c" +#include "scatter_store_64-8.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-9.c index a91b500..1b37cac 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/gather-scatter/scatter_store_run-9.c @@ -1,7 +1,7 @@ /* { dg-do run { target { riscv_v } } } */ /* { dg-additional-options "-mcmodel=medany" } */ -#include "scatter_store-9.c" +#include "scatter_store_64-9.c" #include <assert.h> int diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/post-ra-avl.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/post-ra-avl.c new file mode 100644 index 0000000..f3d12ba --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/post-ra-avl.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d --param=riscv-autovec-preference=fixed-vlmax" } */ + +int a, b, c, e; +short d[7][7] = {}; +int foo() { + short f; + c = 0; + for (; c <= 6; c++) { + e |= d[c][c] & 1; + b &= f & 3; + } + return a; +} + +/* { dg-final { scan-assembler-times {vsetvli\s+[a-x0-9]+,\s*zero} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112438.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112438.c index 51f90df..d6770af 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112438.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112438.c @@ -31,3 +31,4 @@ float * __restrict out, float x) } /* We don't want to see vect_vec_iv_.21_25 + { POLY_INT_CST [4, 4], ... }. */ +/* { dg-final { scan-tree-dump-not "\\+ \{ POLY_INT_CST" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112597-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112597-1.c new file mode 100644 index 0000000..73aa3ee2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112597-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv_zvl256b -mabi=ilp32d -O3 --param riscv-autovec-preference=fixed-vlmax" } */ + +#include <stdint-gcc.h> + +typedef int64_t vnx2di __attribute__ ((vector_size (16))); + +__attribute__ ((noipa)) void +f_vnx2di (int64_t a, int64_t b, int64_t *out) +{ + vnx2di v = {a, b}; + *(vnx2di *) out = v; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c new file mode 100644 index 0000000..a1d7e5b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-1.c @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv_zvfh_zfh_zvl512b -mabi=ilp32d -O3 --param=riscv-autovec-lmul=m8 -O3 -fno-vect-cost-model -ffast-math" } */ + +#include <stdint-gcc.h> +#define TEST_UNARY_CALL_CVT(TYPE_IN, TYPE_OUT, CALL) \ + void test_##TYPE_IN##_##TYPE_OUT##_##CALL ( \ + TYPE_OUT *out, TYPE_IN *in, unsigned count) \ + { \ + for (unsigned i = 0; i < count; i++) \ + out[i] = CALL (in[i]); \ + } +#define TEST_ASSERT(TYPE) \ + void test_##TYPE##_assert (TYPE *out, TYPE *ref, unsigned size) \ + { \ + for (unsigned i = 0; i < size; i++) \ + { \ + if (out[i] != ref[i]) \ + __builtin_abort (); \ + } \ + } +#define TEST_INIT_CVT(TYPE_IN, VAL_IN, TYPE_REF, VAL_REF, NUM) \ + void test_##TYPE_IN##_##TYPE_REF##_init_##NUM ( \ + TYPE_IN *in, TYPE_REF *ref, unsigned size) \ + { \ + for (unsigned i = 0; i < size; i++) \ + { \ + in[i] = VAL_IN; \ + ref[i] = VAL_REF; \ + } \ + } +#define RUN_TEST_CVT(TYPE_IN, TYPE_OUT, NUM, CALL, IN, OUT, REF, SIZE) \ + test_##TYPE_IN##_##TYPE_OUT##_init_##NUM (IN, REF, SIZE); \ + test_##TYPE_IN##_##TYPE_OUT##_##CALL (OUT, IN, SIZE); \ + test_##TYPE_OUT##_assert (OUT, REF, SIZE); + +#define ARRAY_SIZE 128 + +float in[ARRAY_SIZE]; +int64_t out[ARRAY_SIZE]; +int64_t ref[ARRAY_SIZE]; + +TEST_UNARY_CALL_CVT (float, int64_t, __builtin_llceilf) + +TEST_ASSERT (int64_t) + + +TEST_INIT_CVT (float, 9223372036854775808.0, int64_t, 0x7fffffffffffffff, 26) +TEST_INIT_CVT (float, __builtin_inf (), int64_t, __builtin_llceilf (__builtin_inf ()), 29) + +int64_t +main () +{ + RUN_TEST_CVT (float, int64_t, 26, __builtin_llceilf, in, out, ref, ARRAY_SIZE); + RUN_TEST_CVT (float, int64_t, 29, __builtin_llceilf, in, out, ref, ARRAY_SIZE); + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-2.c new file mode 100644 index 0000000..d32e8ba --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvfh_zfh_zvl512b -mabi=lp64d -O3 --param=riscv-autovec-lmul=m8" } */ + +#include <stdint-gcc.h> + +void +f (uint8_t *restrict a, uint8_t *restrict b, int n) +{ + for (int i = 0; i < n; ++i) + { + a[i * 8] = b[i * 8 + 3] + 1; + a[i * 8 + 1] = b[i * 8 + 2] + 2; + a[i * 8 + 2] = b[i * 8 + 1] + 3; + a[i * 8 + 3] = b[i * 8 + 0] + 4; + a[i * 8 + 4] = b[i * 8 + 7] + 5; + a[i * 8 + 5] = b[i * 8 + 6] + 6; + a[i * 8 + 6] = b[i * 8 + 5] + 7; + a[i * 8 + 7] = b[i * 8 + 4] + 8; + } +} + +/* We don't want EEW8 LMUL8 vrgather.vv. */ +/* { dg-final { scan-assembler-not {vrgather\.vv} } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-3.c new file mode 100644 index 0000000..231a068 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112598-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv_zvfh_zfh_zvl512b -mabi=ilp32d -O3 -ftree-vectorize -std=c99 -fno-vect-cost-model" } */ + +#include <stdint-gcc.h> +#define TYPE uint64_t +#define ITYPE int64_t + +void __attribute__ ((noinline, noclone)) +foo (TYPE *__restrict a, TYPE *__restrict b, TYPE *__restrict c, + TYPE *__restrict d, ITYPE n) +{ + for (ITYPE i = 0; i < n; ++i) + { + d[i * 3] = a[i]; + d[i * 3 + 1] = b[i]; + d[i * 3 + 2] = c[i]; + } +} + +/* We don't want vcompress.vv. */ +/* { dg-final { scan-assembler-not {vcompress\.vv} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-1.c new file mode 100644 index 0000000..911b692 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvfh_zfh_zvl1024b -mabi=lp64d -O3 --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "riscv_vector.h" + +typedef int64_t v1024b __attribute__ ((vector_size (128))); + +void foo (void *out, void *in, int64_t a, int64_t b) +{ + v1024b v = {a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a}; + v1024b v2 = {b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b}; + v1024b index = *(v1024b*)in; + v1024b v3 = __builtin_shuffle (v, v2, index); + __riscv_vse64_v_i64m1 (out, (vint64m1_t)v3, 10); +} + +/* { dg-final { scan-assembler {vsetivli\s+zero,\s*16} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-2.c new file mode 100644 index 0000000..fd87565 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-2.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvl1024b -mabi=lp64d -O3" } */ + +struct s { struct s *n; } *p; +struct s ss; +#define MAX 10 +struct s sss[MAX]; +int count = 0; + +int look( struct s *p, struct s **pp ) +{ + for ( ; p; p = p->n ) + ; + *pp = p; + count++; + return( 1 ); +} + +void sub( struct s *p, struct s **pp ) +{ + for ( ; look( p, pp ); ) { + if ( p ) + p = p->n; + else + break; + } +} + +int +foo(void) +{ + struct s *pp; + struct s *next; + int i; + + p = &ss; + next = p; + for ( i = 0; i < MAX; i++ ) { + next->n = &sss[i]; + next = next->n; + } + next->n = 0; + + sub( p, &pp ); + if (count != MAX+2) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-assembler-not {vrgather} } } */ +/* { dg-final { scan-assembler-times {vslide1up\.vx} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-3.c new file mode 100644 index 0000000..0954fe2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112599-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv_zvfh_zfh_zvl1024b -mabi=lp64d -O3 --param=riscv-autovec-preference=fixed-vlmax" } */ + +#include "riscv_vector.h" + +typedef int64_t v1024b __attribute__ ((vector_size (128))); + +void foo (void *out, void *in, int64_t a, int64_t b, int64_t c, int64_t d, int64_t e) +{ + v1024b v = {a,a,a,a,a,a,a,a,a,a,a,a,b,c,d,e}; + __riscv_vse64_v_i64m1 (out, (vint64m1_t)v, 12); +} + +/* { dg-final { scan-assembler {vsetivli\s+zero,\s*16} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112694-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112694-1.c new file mode 100644 index 0000000..8c7f7a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr112694-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zve64d_zvfh_zfh -mabi=ilp32d -mcmodel=medany -fdiagnostics-plain-output -ftree-vectorize -O2 --param riscv-autovec-lmul=m1 -std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=fixed-vlmax -ffast-math" } */ + +#include <stdint-gcc.h> + +#define TEST_TYPE(TYPE) \ + __attribute__((noipa)) \ + void vmul_##TYPE (TYPE *dst, TYPE *a, TYPE *b, int n) \ + { \ + for (int i = 0; i < n; i++) \ + dst[i] = a[i] * b[i]; \ + } + +#define TEST_ALL() \ + TEST_TYPE(_Float16) \ + +TEST_ALL() + +#include <assert.h> + +#define SZ 512 + +#define RUN(TYPE, VAL) \ + TYPE a##TYPE[SZ]; \ + TYPE b##TYPE[SZ]; \ + for (int i = 0; i < SZ; i++) \ + { \ + a##TYPE[i] = 2; \ + b##TYPE[i] = VAL; \ + } \ + vmul_##TYPE (a##TYPE, a##TYPE, b##TYPE, SZ); \ + for (int i = 0; i < SZ; i++) \ + assert (a##TYPE[i] == 2 * VAL); + +#define RUN_ALL() \ + RUN(_Float16, 4) \ + +int main () +{ + RUN_ALL() +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc_run-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc_run-9.c index a0d5904..0f95e61 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc_run-9.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/reduc_run-9.c @@ -1,5 +1,4 @@ /* { dg-do run { target { riscv_v } } } */ -/* { dg-additional-options "--param=riscv-autovec-preference=scalable -ffast-math -fno-vect-cost-model" } */ #define N 0x1100 @@ -14,8 +13,8 @@ main (void) if (add_loop (x, 0, 33) != 33 || add_loop (x, 11, 30) != 4078 - || add_loop (x, 0x100, 45) != 45001773 - || add_loop (x, 0x11f, 300) != 63369900) + || add_loop (x, 0x100, 45) != 45001776 + || add_loop (x, 0x11f, 300) != 63369904) __builtin_abort (); return 0; diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/popcount.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/popcount.c index 585a522..ca1319c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/popcount.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/unop/popcount.c @@ -1461,4 +1461,12 @@ main () RUN_ALL () } -/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 229 "vect" } } */ +/* TODO: Due to an over-zealous check in tree-vect-patterns we do not vectorize + e.g. + uint64_t dst[]; + uint32_t src[]; + dst[i] = __builtin_popcountll (src[i]); + even though we could. Therefore, for now, adjust the following checks. + This difference was exposed in r14-5557-g6dd4c703be17fa. */ +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 229 "vect" { target { { rv64 } && { ! riscv_zbb } } } } } */ +/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 250 "vect" { target { { rv32 } || { riscv_zbb } } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/perm-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/perm-4.c index b235ec7..7ab3104 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/perm-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls-vlmax/perm-4.c @@ -55,7 +55,7 @@ TEST_ALL (PERMUTE) -/* { dg-final { scan-assembler-times {vrgather\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 18 } } */ +/* { dg-final { scan-assembler-times {vrgather\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 19 } } */ /* { dg-final { scan-assembler-times {vrgatherei16\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 12 } } */ -/* { dg-final { scan-assembler-times {vrsub\.vi} 23 } } */ +/* { dg-final { scan-assembler-times {vrsub\.vi} 24 } } */ /* { dg-final { scan-assembler-times {vrsub\.vx} 7 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/perm-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/perm-4.c index d2d4938..4d6862c 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/perm-4.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/perm-4.c @@ -3,7 +3,7 @@ #include "../vls-vlmax/perm-4.c" -/* { dg-final { scan-assembler-times {vrgather\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 18 } } */ +/* { dg-final { scan-assembler-times {vrgather\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 19 } } */ /* { dg-final { scan-assembler-times {vrgatherei16\.vv\tv[0-9]+,\s*v[0-9]+,\s*v[0-9]+} 12 } } */ -/* { dg-final { scan-assembler-times {vrsub\.vi} 23 } } */ +/* { dg-final { scan-assembler-times {vrsub\.vi} 24 } } */ /* { dg-final { scan-assembler-times {vrsub\.vx} 7 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-1.c new file mode 100644 index 0000000..ae49706 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32d -mmemcpy-strategy=libcall" } */ + +#include "cpymem-strategy.h" + +/* { dg-final { scan-assembler-times {call\tmemcpy} 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-2.c new file mode 100644 index 0000000..73ffc57 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-2.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv32gcv -mabi=ilp32d -mmemcpy-strategy=scalar" } */ + +#include "cpymem-strategy.h" + +/* { dg-final { scan-assembler-times {call\tmemcpy} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-3.c new file mode 100644 index 0000000..44f5f78 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-3.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32d -mmemcpy-strategy=vector" } */ + +#include "cpymem-strategy.h" + +/* { dg-final { scan-assembler-times {v[ls]+e[0-9]+\.v\tv[0-9]+\,0\([a-z0-9]+\)} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-4.c new file mode 100644 index 0000000..8056895 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-4.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32d -mmemcpy-strategy=auto" } */ + +#include "cpymem-strategy.h" + +/* { dg-final { scan-assembler-times {v[ls]+e[0-9]+\.v\tv[0-9]+\,0\([a-z0-9]+\)} 4 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-5.c new file mode 100644 index 0000000..82ecab0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy-5.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc -mabi=ilp32d -mmemcpy-strategy=vector" } */ + +#include "cpymem-strategy.h" + +/* { dg-final { scan-assembler-times {call\tmemcpy} 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy.h b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy.h new file mode 100644 index 0000000..700d224 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/cpymem-strategy.h @@ -0,0 +1,12 @@ +typedef struct { unsigned char a[56]; } a56; +typedef struct { int b[32]; } b32; + +void f1 (a56 *v1, a56 *v2) +{ + *v1 = *v2; +} + +void f2 (b32 *v1, b32 *v2) +{ + *v1 = *v2; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-0.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-0.c new file mode 100644 index 0000000..a61e94a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-0.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m1_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m1(arr, 32); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-1.c new file mode 100644 index 0000000..46efd73 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m2_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m2(arr, 32); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[09]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-10.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-10.c new file mode 100644 index 0000000..8bebac2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-10.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vbool4_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vlm_v_b4(arr, 32); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-2.c new file mode 100644 index 0000000..47e4243 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m1_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m1(arr, 16); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-3.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-3.c new file mode 100644 index 0000000..5331e54 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m2_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m2(arr, 8); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[09]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-4.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-4.c new file mode 100644 index 0000000..0c728f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8mf2_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8mf2(arr, 32); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-5.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-5.c new file mode 100644 index 0000000..ccfc40c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-5.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m2_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m2(arr, 4); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[09]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-6.c new file mode 100644 index 0000000..ce7ddbb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-6.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vuint8m8_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + return __riscv_vle8_v_u8m8(arr, 32); +} + +/* { dg-final { scan-assembler-times {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} 1 } } */ +/* { dg-final { scan-assembler-times {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-7.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-7.c new file mode 100644 index 0000000..ac0100a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-7.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vbool8_t test () { + uint8_t arr[32] = { + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + 1, 2, 7, 1, 3, 4, 5, 3, + 1, 0, 1, 2, 4, 4, 9, 9, + }; + + vuint8m1_t varr = __riscv_vle8_v_u8m1(arr, 32); + vuint8m1_t vand_m = __riscv_vand_vx_u8m1(varr, 1, 32); + + return __riscv_vreinterpret_v_u8m1_b8(vand_m); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-8.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-8.c new file mode 100644 index 0000000..b7ebef8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-8.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vfloat32m1_t test () { + float arr[32] = { + 1.0, 2.2, 7.8, 1.2, 3.3, 4.7, 5.5, 3.3, + 1.0, 0.2, 1.8, 2.2, 4.3, 4.7, 9.5, 9.3, + 1.0, 2.2, 7.8, 1.2, 3.3, 4.7, 5.5, 3.3, + 1.0, 0.2, 1.8, 2.2, 4.3, 4.7, 9.5, 9.3, + }; + + return __riscv_vle32_v_f32m1(arr, 32); +} + +/* { dg-final { scan-assembler-not {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ +/* { dg-final { scan-assembler-not {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-9.c new file mode 100644 index 0000000..21fed06 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr111720-9.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -ftree-vectorize --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */ + +#include "riscv_vector.h" + +vfloat64m8_t test () { + double arr[8] = { + 1.0, 2.2, 7.8, 1.2, 3.3, 4.7, 5.5, 3.3, + }; + + return __riscv_vle64_v_f64m8(arr, 4); +} + +/* { dg-final { scan-assembler-times {vle[0-9]+\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} 1 } } */ +/* { dg-final { scan-assembler-times {vs[0-9]+r\.v\s+v[0-9]+,\s*[0-9]+\(sp\)} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c index 11adf6b..8f352db 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vf_avl-1.c @@ -12,4 +12,4 @@ f_vnx2qi (int8_t a, int8_t b, int8_t *out) *(vnx2qi *) out = v; } -/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*2,\s*e8,\s*mf8,\s*t[au],\s*m[au]} 1 } } */ +/* { dg-final { scan-assembler {vsetivli\s+zero,\s*2,\s*e8,\s*mf8,\s*t[au],\s*m[au]} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp index 237a20e..1d5041b 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp +++ b/gcc/testsuite/gcc.target/riscv/rvv/rvv.exp @@ -30,18 +30,11 @@ if ![info exists DEFAULT_CFLAGS] then { set DEFAULT_CFLAGS " -ansi -pedantic-errors" } -set gcc_march "rv64gcv_zfh" -set gcc_mabi "lp64d" -if [istarget riscv32-*-*] then { - set gcc_march "rv32gcv_zfh" - set gcc_mabi "ilp32d" -} - # Initialize `dg'. dg-init # Main loop. -set CFLAGS "$DEFAULT_CFLAGS -march=$gcc_march -mabi=$gcc_mabi -O3" +set CFLAGS "$DEFAULT_CFLAGS -O3" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/base/*.\[cS\]]] \ "" $CFLAGS gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vsetvl/*.\[cS\]]] \ diff --git a/gcc/testsuite/gcc.target/riscv/smax-ieee.c b/gcc/testsuite/gcc.target/riscv/smax-ieee.c index 2dbccef..775e515 100644 --- a/gcc/testsuite/gcc.target/riscv/smax-ieee.c +++ b/gcc/testsuite/gcc.target/riscv/smax-ieee.c @@ -10,4 +10,4 @@ smax (double x, double y) /* { dg-final { scan-assembler-not "\t(call|tail)\tfmax\t" } } */ /* { dg-final { scan-assembler-not "\tfmax\\.d\t" } } */ -/* { dg-final { scan-assembler "\tfge\\.d\t" } } */ +/* { dg-final { scan-assembler "\t(fge\\.d|flt\\.d)\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c b/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c index 31b9bfa..c794bc3 100644 --- a/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c +++ b/gcc/testsuite/gcc.target/riscv/smaxf-ieee.c @@ -10,4 +10,4 @@ smaxf (float x, float y) /* { dg-final { scan-assembler-not "\t(call|tail)\tfmaxf\t" } } */ /* { dg-final { scan-assembler-not "\tfmax\\.s\t" } } */ -/* { dg-final { scan-assembler "\tfge\\.s\t" } } */ +/* { dg-final { scan-assembler "\t(fge\\.s|flt\\.s)\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/smin-ieee.c b/gcc/testsuite/gcc.target/riscv/smin-ieee.c index ea36c2d..28cedd3 100644 --- a/gcc/testsuite/gcc.target/riscv/smin-ieee.c +++ b/gcc/testsuite/gcc.target/riscv/smin-ieee.c @@ -10,4 +10,4 @@ smin (double x, double y) /* { dg-final { scan-assembler-not "\t(call|tail)\tfmin\t" } } */ /* { dg-final { scan-assembler-not "\tfmin\\.d\t" } } */ -/* { dg-final { scan-assembler "\tfle\\.d\t" } } */ +/* { dg-final { scan-assembler "\t(fgt\\.d|fle\\.d)\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/sminf-ieee.c b/gcc/testsuite/gcc.target/riscv/sminf-ieee.c index 427617a..18d4858 100644 --- a/gcc/testsuite/gcc.target/riscv/sminf-ieee.c +++ b/gcc/testsuite/gcc.target/riscv/sminf-ieee.c @@ -10,4 +10,4 @@ sminf (float x, float y) /* { dg-final { scan-assembler-not "\t(call|tail)\tfminf\t" } } */ /* { dg-final { scan-assembler-not "\tfmin\\.s\t" } } */ -/* { dg-final { scan-assembler "\tfle\\.s\t" } } */ +/* { dg-final { scan-assembler "\t(fgt\\.s|fle\\.s)\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c b/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c index 8c5d8c7..81d826d 100644 --- a/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c +++ b/gcc/testsuite/gcc.target/riscv/zbs-bext-02.c @@ -15,4 +15,4 @@ foo(const long long B, int a) /* { dg-final { scan-assembler-times "bext\t" 1 } } */ /* { dg-final { scan-assembler-not {\mbset} } } */ -/* { dg-final { scan-assembler-not {\mand} } } */ +/* { dg-final { scan-assembler-not {\msll} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c index e806f6f..4015220 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=3" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=3" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_imm_return_imm_imm_00(long a, long b) { diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c index f976d60..dd3665c4 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=3" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=3" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_imm_return_imm_reg_00(long a, long b) { diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c index 90e9119..19ca4a4 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=4" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=4" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_imm_return_reg_reg_00(long a, long b, long c) { diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c index 8ad97ab..e670d1d 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=3" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=3" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_reg_return_imm_imm_00(long a, long b, long c) { diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c index 5199ba7..e25487c 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=3" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=3" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_reg_return_imm_reg_00(long a, long b, long c) { diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c index eecb956..765c0e0 100644 --- a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c +++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ -/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -mbranch-cost=4" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f -mbranch-cost=4" { target { rv32 } } } */ /* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Os" "-Oz"} } */ long primitiveSemantics_compare_reg_return_reg_reg_00(long a, long b, long c, diff --git a/gcc/testsuite/gcc.target/s390/ccor.c b/gcc/testsuite/gcc.target/s390/ccor.c new file mode 100644 index 0000000..31f30f6 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/ccor.c @@ -0,0 +1,88 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=zEC12 -mzarch" } */ + +#define GENFUN1(C) \ + int foo_ ##C(int x) \ + { \ + int cc; \ + asm volatile ("ahi %[x],42\n" \ + : [x] "+d"(x), "=@cc" (cc)); \ + return cc == C ? 42 : 0; \ + } + +#define GENFUN2(C1,C2) \ + int foo_ ##C1##C2(int x) \ + { \ + int cc; \ + asm volatile ("ahi %[x],42\n" \ + : [x] "+d"(x), "=@cc" (cc)); \ + return cc == C1 || cc == C2 ? 42 : 0; \ + } + +#define GENFUN3(C1,C2,C3) \ + int foo_ ##C1##C2##C3(int x) \ + { \ + int cc; \ + asm volatile ("ahi %[x],42\n" \ + : [x] "+d"(x), "=@cc" (cc)); \ + return cc == C1 || cc == C2 || cc == C3 ? 42 : 0; \ + } + +GENFUN1(0) + +/* { dg-final { scan-assembler {locrne} } } */ + +GENFUN1(1) + +/* { dg-final { scan-assembler {locrnl} } } */ + +GENFUN1(2) + +/* { dg-final { scan-assembler {locrnh} } } */ + +GENFUN1(3) + +/* { dg-final { scan-assembler {locrno} } } */ + +GENFUN2(0,1) + +/* { dg-final { scan-assembler {locrnle} } } */ + +GENFUN2(0,2) + +/* { dg-final { scan-assembler {locrhe} } } */ + +GENFUN2(0,3) + +/* currently unoptimized */ + +GENFUN2(1,2) + +/* { dg-final { scan-assembler {locrnlh} } } */ + +GENFUN2(1,3) + +/* { dg-final { scan-assembler {locrnhe} } } */ + +GENFUN2(2,3) + +/* { dg-final { scan-assembler {locrle} } } */ + +GENFUN3(0,1,2) + +/* { dg-final { scan-assembler {locrh} } } */ + +GENFUN3(0,1,3) + +/* currently unoptimized */ + +GENFUN3(0,2,3) + +/* currently unoptimized */ + +GENFUN3(1,2,3) + +/* { dg-final { scan-assembler {locre} } } */ + +/* for the unoptimized cases, we get an ipm */ +/* { dg-final { scan-assembler-times {ipm} 3 } } */ diff --git a/gcc/testsuite/gcc.target/s390/int128load.c b/gcc/testsuite/gcc.target/s390/int128load.c new file mode 100644 index 0000000..3eb335c --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/int128load.c @@ -0,0 +1,14 @@ +/* Check that int128 loads and stores are split. */ + +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O3 -mzarch -march=zEC12" } */ + +__int128 global; + +void f(__int128 x) +{ + global = x; +} + +/* { dg-final { scan-assembler-times "lg\t" 2 } } */ +/* { dg-final { scan-assembler-times "stg\t" 2 } } */ diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp16-convert.c b/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp16-convert.c index 5ed7e05..7d7c13e 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp16-convert.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp16-convert.c @@ -10,10 +10,10 @@ main () vector float fp1 = (vector float){ 1.0f, 2.0f, 3.0f, 4.0f }; vector float fp2 = (vector float){ 5.0f, 6.0f, 7.0f, 8.0f }; - vector short int tmp1 = vec_round_from_fp32 (fp1, fp2, 0); + vector unsigned short int tmp1 = vec_round_from_fp32 (fp1, fp2, 0); - vector short int tmp2 = vec_convert_to_fp16 (tmp1, 0); - vector short int tmp3 = vec_convert_from_fp16 (tmp2, 0); + vector unsigned short int tmp2 = vec_convert_to_fp16 (tmp1, 0); + vector unsigned short int tmp3 = vec_convert_from_fp16 (tmp2, 0); vector float fp1_ret = vec_extend_to_fp32_hi (tmp3, 0); vector float fp2_ret = vec_extend_to_fp32_lo (tmp3, 0); diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp32-convert-1.c b/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp32-convert-1.c index 321488a..6dcfad4 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp32-convert-1.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-nnpa-fp32-convert-1.c @@ -9,7 +9,7 @@ main () { vector float fp1 = (vector float){ 1.0f, 2.0f, 3.0f, 4.0f }; vector float fp2 = (vector float){ 5.0f, 6.0f, 7.0f, 8.0f }; - vector short int conv = vec_round_from_fp32 (fp1, fp2, 0); + vector unsigned short int conv = vec_round_from_fp32 (fp1, fp2, 0); vector float fp1_ret = vec_extend_to_fp32_hi (conv, 0); vector float fp2_ret = vec_extend_to_fp32_lo (conv, 0); diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_convert_from_fp16.c b/gcc/testsuite/gcc.target/s390/zvector/vec_convert_from_fp16.c index fc7ccf0..86fad2c 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec_convert_from_fp16.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_convert_from_fp16.c @@ -3,8 +3,8 @@ #include <vecintrin.h> -vector short int -test_vec_convert_from_fp16 (vector short int a) +vector unsigned short int +test_vec_convert_from_fp16 (vector unsigned short int a) { return vec_convert_from_fp16 (a, 0); } diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_convert_to_fp16.c b/gcc/testsuite/gcc.target/s390/zvector/vec_convert_to_fp16.c index 7232643..eda2952 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec_convert_to_fp16.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_convert_to_fp16.c @@ -3,8 +3,8 @@ #include <vecintrin.h> -vector short int -test_vec_convert_to_fp16 (vector short int a) +vector unsigned short int +test_vec_convert_to_fp16 (vector unsigned short int a) { return vec_convert_to_fp16 (a, 0); } diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_hi.c b/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_hi.c index feb5e78..feedef8 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_hi.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_hi.c @@ -4,7 +4,7 @@ #include <vecintrin.h> vector float -test_vec_extend_to_fp32_hi (vector short int a) +test_vec_extend_to_fp32_hi (vector unsigned short int a) { return vec_extend_to_fp32_hi (a, 0); } diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_lo.c b/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_lo.c index 179de17..dbdf530 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_lo.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_extend_to_fp32_lo.c @@ -4,7 +4,7 @@ #include <vecintrin.h> vector float -test_vec_extend_to_fp32_lo (vector short int a) +test_vec_extend_to_fp32_lo (vector unsigned short int a) { return vec_extend_to_fp32_lo (a, 0); } diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_round_from_fp32.c b/gcc/testsuite/gcc.target/s390/zvector/vec_round_from_fp32.c index 83924522..617a820 100644 --- a/gcc/testsuite/gcc.target/s390/zvector/vec_round_from_fp32.c +++ b/gcc/testsuite/gcc.target/s390/zvector/vec_round_from_fp32.c @@ -3,7 +3,7 @@ #include <vecintrin.h> -vector short int +vector unsigned short int test_vec_round_from_fp32 (vector float hi, vector float lo) { return vec_round_from_fp32 (hi, lo, 0); diff --git a/gcc/testsuite/gdc.dg/asm1.d b/gcc/testsuite/gdc.dg/asm1.d index 1b249ee..1593eb6 100644 --- a/gcc/testsuite/gdc.dg/asm1.d +++ b/gcc/testsuite/gdc.dg/asm1.d @@ -58,7 +58,7 @@ void semantic1() void semantic2a(X...)(X expr) { alias X[0] var1; - asm { "%0" : "=m" (var1); } // { dg-error "double' is a 'double' definition and cannot be modified" } + asm { "%0" : "=m" (var1); } // { dg-error "cannot modify type 'double'" } } void semantic2() diff --git a/gcc/testsuite/gdc.test/compilable/issue16020.d b/gcc/testsuite/gdc.test/compilable/issue16020.d index cfd078c..38a5d62 100644 --- a/gcc/testsuite/gdc.test/compilable/issue16020.d +++ b/gcc/testsuite/gdc.test/compilable/issue16020.d @@ -1,3 +1,4 @@ +// function type aliases module issue16020; alias F1 = const(int)(); const(int) f1(){return 42;} @@ -36,4 +37,8 @@ alias Specialized = FunTemplate!int; alias Compared = void(int); static assert(is(Specialized == Compared)); -void main() {} +// type suffixes +alias FT = const(int)*(); +static assert(is(FT* == const(int)* function())); +alias FT2 = int*[2]() pure; +static assert(is(FT2* == int*[2] function() pure)); diff --git a/gcc/testsuite/gdc.test/compilable/nogc.d b/gcc/testsuite/gdc.test/compilable/nogc.d index 88cf122..959adc4 100644 --- a/gcc/testsuite/gdc.test/compilable/nogc.d +++ b/gcc/testsuite/gdc.test/compilable/nogc.d @@ -119,3 +119,12 @@ void f(bool cond, string s) @nogc { alias Unused2 = typeof(&inner); // (Does not) INFERS GC (anymore) enum Unused3 = __traits(compiles , &inner); } + +// https://issues.dlang.org/show_bug.cgi?id=24072 + +version (D_SIMD) void f24072() @nogc +{ + alias int4 = __vector(int[4]); + int4 b = cast(int4)[1, 2, 3, 4]; + int4 c = cast(int4)[1, 2]; +} diff --git a/gcc/testsuite/gdc.test/compilable/previewin.d b/gcc/testsuite/gdc.test/compilable/previewin.d index 8926fbd..558005c 100644 --- a/gcc/testsuite/gdc.test/compilable/previewin.d +++ b/gcc/testsuite/gdc.test/compilable/previewin.d @@ -79,14 +79,11 @@ version (Win64) { void checkReal(in real p) { - // ref for x87 real, value for double-precision real - static assert(__traits(isRef, p) == (real.sizeof > 8)); } struct RGB { ubyte r, g, b; } void checkNonPowerOf2(in RGB p) { - static assert(__traits(isRef, p)); } } else version (X86_64) // Posix x86_64 @@ -94,7 +91,6 @@ else version (X86_64) // Posix x86_64 struct Empty {} // 1 dummy byte passed on the stack void checkEmptyStruct(in Empty p) { - static assert(!__traits(isRef, p)); } static if (is(__vector(double[4]))) @@ -102,7 +98,6 @@ else version (X86_64) // Posix x86_64 struct AvxVectorWrapper { __vector(double[4]) a; } // 256 bits void checkAvxVector(in AvxVectorWrapper p) { - static assert(!__traits(isRef, p)); } } } @@ -111,6 +106,5 @@ else version (AArch64) alias HVA = __vector(float[4])[4]; // can be passed in 4 vector registers void checkHVA(in HVA p) { - static assert(!__traits(isRef, p)); } } diff --git a/gcc/testsuite/gdc.test/fail_compilation/b20011.d b/gcc/testsuite/gdc.test/fail_compilation/b20011.d index 7baad47..3ddcdaa 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/b20011.d +++ b/gcc/testsuite/gdc.test/fail_compilation/b20011.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/b20011.d(25): Error: `S1(cast(ubyte)0u).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(28): Error: `S2(null).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(29): Error: `S2(null).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(32): Error: `U1(cast(ubyte)0u, ).m2` is not an lvalue and cannot be modified +fail_compilation/b20011.d(25): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue +fail_compilation/b20011.d(28): Error: cannot modify expression `S2(null).member` because it is not an lvalue +fail_compilation/b20011.d(29): Error: cannot modify expression `S2(null).member` because it is not an lvalue +fail_compilation/b20011.d(32): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue fail_compilation/b20011.d(37): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)` fail_compilation/b20011.d(37): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p` fail_compilation/b20011.d(38): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)` diff --git a/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d new file mode 100644 index 0000000..ae37023 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/const_ctor.d @@ -0,0 +1,26 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/const_ctor.d(23): Error: `const` copy constructor `const_ctor.S1.this` cannot construct a mutable object +fail_compilation/const_ctor.d(25): Error: `const` constructor `const_ctor.S2.this` cannot construct a mutable object +--- +*/ + +struct S1 +{ + this(ref const S1 s) const {} + int* i; +} +struct S2 +{ + this(int) const {} + int* i; +} + +void main() +{ + const(S1) s1; + S1 m1 = s1; + + S2 s2 = S2(5); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d b/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d new file mode 100644 index 0000000..337ded0 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/ctor_attr.d @@ -0,0 +1,29 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` can construct a mutable object with argument types `(int)` +fail_compilation/ctor_attr.d(16): Candidates are: `ctor_attr.S.this(int x) const` +fail_compilation/ctor_attr.d(18): `ctor_attr.S.this(string x)` +fail_compilation/ctor_attr.d(17): `this()(int x) shared` +fail_compilation/ctor_attr.d(28): Error: none of the overloads of `foo` are callable using a mutable object with argument types `(int)` +fail_compilation/ctor_attr.d(20): Candidates are: `ctor_attr.S.foo(int x) immutable` +fail_compilation/ctor_attr.d(21): `ctor_attr.S.foo(string x)` +--- +*/ + +struct S +{ + this(int x) const {} + this()(int x) shared {} + this(string x) {} + + void foo(int x) immutable {} + void foo(string x) {} +} + +void f() +{ + auto s = S(1); + S t; + t.foo(1); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10415.d b/gcc/testsuite/gdc.test/fail_compilation/diag10415.d index 207f6a4..7444432 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10415.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10415.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/diag10415.d(36): Error: none of the overloads of `x` are callable using argument types `(int) const` -fail_compilation/diag10415.d(13): Candidates are: `diag10415.C.x()` +fail_compilation/diag10415.d(13): Candidates are: `diag10415.C.x() const` fail_compilation/diag10415.d(18): `diag10415.C.x(int __param_0)` fail_compilation/diag10415.d(39): Error: d.x is not an lvalue --- diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d index 3e15497..2c93841 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10862.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10862.d @@ -26,10 +26,10 @@ fail_compilation/diag10862.d-mixin-78(78): Error: assignment cannot be used as a fail_compilation/diag10862.d-mixin-79(79): Error: assignment cannot be used as a condition, perhaps `==` was meant? fail_compilation/diag10862.d-mixin-80(80): Error: using the result of a comma expression is not allowed fail_compilation/diag10862.d-mixin-80(80): Error: assignment cannot be used as a condition, perhaps `==` was meant? -fail_compilation/diag10862.d-mixin-83(83): Error: `a + b` is not an lvalue and cannot be modified +fail_compilation/diag10862.d-mixin-83(83): Error: cannot modify expression `a + b` because it is not an lvalue fail_compilation/diag10862.d-mixin-84(84): Error: undefined identifier `c` fail_compilation/diag10862.d(86): Error: undefined identifier `semanticError` -fail_compilation/diag10862.d(93): Error: lazy variable `bar` cannot be modified +fail_compilation/diag10862.d(93): Error: cannot modify lazy variable `bar` fail_compilation/diag10862.d(95): Error: template instance `diag10862.test3.foo!int` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag10926.d b/gcc/testsuite/gdc.test/fail_compilation/diag10926.d index f98a5b2..9bad633 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag10926.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag10926.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/diag10926.d(11): Error: `cast(const(int)[])c` is not an lvalue and cannot be modified +fail_compilation/diag10926.d(11): Error: cannot modify expression `cast(const(int)[])c` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag14102.d b/gcc/testsuite/gdc.test/fail_compilation/diag14102.d index e93d40b..b88dd78 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag14102.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag14102.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/diag14102.d(14): Error: `-x` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(15): Error: `-(x -= 1)` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(16): Error: `-(x -= 1 -= 1)` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(17): Error: `-(x -= 1 -= 1 -= 1)` is not an lvalue and cannot be modified +fail_compilation/diag14102.d(14): Error: cannot modify expression `-x` because it is not an lvalue +fail_compilation/diag14102.d(15): Error: cannot modify expression `-(x -= 1)` because it is not an lvalue +fail_compilation/diag14102.d(16): Error: cannot modify expression `-(x -= 1 -= 1)` because it is not an lvalue +fail_compilation/diag14102.d(17): Error: cannot modify expression `-(x -= 1 -= 1 -= 1)` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag4596.d b/gcc/testsuite/gdc.test/fail_compilation/diag4596.d index f6b49d6..d43342b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag4596.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag4596.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/diag4596.d(15): Error: `this` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(15): Error: cannot modify expression `this` because it is not an lvalue fail_compilation/diag4596.d(16): Error: conditional expression `1 ? this : this` is not a modifiable lvalue -fail_compilation/diag4596.d(18): Error: `super` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(18): Error: cannot modify expression `super` because it is not an lvalue fail_compilation/diag4596.d(19): Error: conditional expression `1 ? super : super` is not a modifiable lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d index a55ef73..626fb82 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/diag8101b.d @@ -6,7 +6,7 @@ fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __ fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` fail_compilation/diag8101b.d(30): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` fail_compilation/diag8101b.d(30): cannot pass argument `1.0` of type `double` to parameter `int __param_0` -fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object +fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object with argument types `(int)` fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` fail_compilation/diag8101b.d(35): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object diff --git a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d b/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d deleted file mode 100644 index 77ab520..0000000 --- a/gcc/testsuite/gdc.test/fail_compilation/dip1000_deprecation.d +++ /dev/null @@ -1,56 +0,0 @@ -/* -REQUIRED_ARGS: -de -TEST_OUTPUT: ---- -fail_compilation/dip1000_deprecation.d(17): Deprecation: `@safe` function `main` calling `inferred` -fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned -fail_compilation/dip1000_deprecation.d(19): Deprecation: `@safe` function `main` calling `inferredC` -fail_compilation/dip1000_deprecation.d(36): which calls `dip1000_deprecation.inferred` -fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned ---- -*/ - -void main() @safe -{ - cast(void)inferred(); - cast(void)inferredB(); // no deprecation, trusted - cast(void)inferredC(); // nested deprecation -} - -auto inferred() -{ - scope int* x0; - return x0; -} - -auto inferredB() @trusted -{ - scope int* x1; - return x1; -} - -auto inferredC() -{ - return inferred(); // no deprecation, inferredC is not explicit `@safe` -} - -@safe: - -struct S -{ - int* ptr; - int* incorrectReturnRef() scope return @trusted {return ptr;} -} - -S createS() { return S.init; } - -int* escape(int i) -{ - if (i) return S().incorrectReturnRef(); - if (i) return createS().incorrectReturnRef(); - - S s; - return s.incorrectReturnRef(); -} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail10299.d b/gcc/testsuite/gdc.test/fail_compilation/fail10299.d index f0eaeba..d9cfb04 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail10299.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail10299.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10299.d(11): Error: `foo!string` is not an lvalue and cannot be modified +fail_compilation/fail10299.d(11): Error: cannot take address of expression `foo!string` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13116.d b/gcc/testsuite/gdc.test/fail_compilation/fail13116.d index ac520d7..156da43 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail13116.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail13116.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail13116.d(14): Error: `this` is not an lvalue and cannot be modified -fail_compilation/fail13116.d(23): Error: `super` is not an lvalue and cannot be modified +fail_compilation/fail13116.d(14): Error: cannot `ref` return expression `this` because it is not an lvalue +fail_compilation/fail13116.d(23): Error: cannot `ref` return expression `super` because it is not an lvalue --- */ struct S diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d b/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d index e3f990c..6307e90 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail13336a.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail13336a.d(28): Error: `choose(true)` is not an lvalue and cannot be modified +fail_compilation/fail13336a.d(28): Error: cannot modify expression `choose(true)` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d b/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d index b8fb12d..f8959a2 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail13336b.d @@ -6,8 +6,8 @@ double sy; /* TEST_OUTPUT: --- -fail_compilation/fail13336b.d(16): Error: `cast(double)sx` is not an lvalue and cannot be modified -fail_compilation/fail13336b.d(24): Error: `cast(double)sx` is not an lvalue and cannot be modified +fail_compilation/fail13336b.d(16): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue +fail_compilation/fail13336b.d(24): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue --- */ ref f1(bool f) diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail17491.d b/gcc/testsuite/gdc.test/fail_compilation/fail17491.d index 0fb9708..718948c 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail17491.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail17491.d @@ -1,13 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/fail17491.d(22): Error: `(S17491).init` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(23): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(25): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(26): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(31): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(32): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(34): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(35): Error: `S17491(0).field` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(22): Error: cannot modify expression `(S17491).init` because it is not an lvalue +fail_compilation/fail17491.d(23): Error: cannot take address of expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(25): Error: cannot modify expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(26): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(31): Error: cannot modify expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(32): Error: cannot take address of expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(34): Error: cannot modify expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(35): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue --- */ // https://issues.dlang.org/show_bug.cgi?id=17491 diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail212.d b/gcc/testsuite/gdc.test/fail_compilation/fail212.d index 5f30863..780cd82 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail212.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail212.d @@ -1,10 +1,14 @@ /* TEST_OUTPUT: --- -fail_compilation/fail212.d(14): Error: function `fail212.S.bar` without `this` cannot be `const` +fail_compilation/fail212.d(10): Error: function `fail212.baz` without `this` cannot be `const` +fail_compilation/fail212.d(10): did you mean to use `const(int)` as the return type? +fail_compilation/fail212.d(18): Error: function `fail212.S.bar` without `this` cannot be `const` --- */ +const int baz(); + struct S { void foo() const diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d index 2e170d0..0b4117d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail21243.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail21243.d @@ -1,16 +1,12 @@ /+ TEST_OUTPUT: --- -fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto` -fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int` -fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)` -fail_compilation/fail21243.d(16): Error: declaration expected, not `)` -fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values -fail_compilation/fail21243.d(18): Error: basic type expected, not `(` -fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`) -fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases -fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration, not `=>` -fail_compilation/fail21243.d(18): Error: declaration expected, not `=>` -fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(12): Error: found `(` when expecting `ref` and function literal following `auto` +fail_compilation/fail21243.d(12): Error: semicolon expected following auto declaration, not `int` +fail_compilation/fail21243.d(12): Error: semicolon needed to end declaration of `x` instead of `)` +fail_compilation/fail21243.d(12): Error: declaration expected, not `)` +fail_compilation/fail21243.d(13): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(14): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(15): Error: `auto` can only be used as part of `auto ref` for function literal return values --- +/ auto a = auto (int x) => x; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail217.d b/gcc/testsuite/gdc.test/fail_compilation/fail217.d index 11ad76f..ecae1a3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail217.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail217.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail217.d(22): Error: mutable method `fail217.Message.this` is not callable using a `immutable` object +fail_compilation/fail217.d(22): Error: mutable constructor `fail217.Message.this` cannot construct a `immutable` object fail_compilation/fail217.d(13): Consider adding `const` or `inout` here --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail24224.d b/gcc/testsuite/gdc.test/fail_compilation/fail24224.d new file mode 100644 index 0000000..db87f53 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/fail24224.d @@ -0,0 +1,22 @@ +/+ +TEST_OUTPUT: +--- +fail_compilation/fail24224.d(19): Error: struct / class type expected as argument to __traits(initSymbol) instead of `ES` +fail_compilation/fail24224.d(20): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EU` +fail_compilation/fail24224.d(21): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EC` +--- ++/ +struct S {} +union U {} +class C {} + +enum ES : S { a = S.init } +enum EU : U { a = U.init } +enum EC : C { a = C.init } + +void test() +{ + auto init1 = __traits(initSymbol, ES); + auto init2 = __traits(initSymbol, EU); + auto init3 = __traits(initSymbol, EC); +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail6795.d b/gcc/testsuite/gdc.test/fail_compilation/fail6795.d index 584a467..26d4429 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail6795.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail6795.d @@ -2,12 +2,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail6795.d(19): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(20): Error: `[0:0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(22): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(23): Error: `[0:0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(25): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(26): Error: `[0:0][0]` is not an lvalue and cannot be modified +fail_compilation/fail6795.d(19): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(20): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(22): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(23): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(25): Error: cannot take address of expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(26): Error: cannot take address of expression `[0:0][0]` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d index 38f47ba..920956b 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424d.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424d.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424d.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424d diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d index e92b469..ddf9d1a 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424e.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424e.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424e.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424e diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d index 1af14f8..2f7f8f3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424f.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424f.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424f.d(10): Error: template `this.g()() shared` has no value --- */ struct S7424f diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d b/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d index 6352166..4e922d6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7424i.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424i.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424i.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424g diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d index 76a92c2..a106a56 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603a.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603a.d(7): Error: cannot modify constant `true` +fail_compilation/fail7603a.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true` --- */ void test(ref bool val = true) { } diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d index 9b84d3f..a652422 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603b.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603b.d(7): Error: cannot modify constant `true` +fail_compilation/fail7603b.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true` --- */ void test(out bool val = true) { } diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d b/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d index 25a7399..3d030fc 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail7603c.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603c.d(8): Error: cannot modify constant `3` +fail_compilation/fail7603c.d(8): Error: cannot create default argument for `ref` / `out` parameter from constant `3` --- */ enum x = 3; diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9537.d b/gcc/testsuite/gdc.test/fail_compilation/fail9537.d index e08badf..4d593e3 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail9537.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail9537.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9537.d(26): Error: `foo(tuple(1, 2))` is not an lvalue and cannot be modified +fail_compilation/fail9537.d(26): Error: cannot take address of expression `foo(tuple(1, 2))` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9773.d b/gcc/testsuite/gdc.test/fail_compilation/fail9773.d index b49ffe1..26447a7 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail9773.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail9773.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9773.d(7): Error: `""` is not an lvalue and cannot be modified +fail_compilation/fail9773.d(7): Error: cannot create default argument for `ref` / `out` parameter from expression `""` because it is not an lvalue --- */ void f(ref string a = "") diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail9891.d b/gcc/testsuite/gdc.test/fail_compilation/fail9891.d index 791e734..0c2384f 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail9891.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail9891.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n` fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n` -fail_compilation/fail9891.d(23): Error: `prop()` is not an lvalue and cannot be modified +fail_compilation/fail9891.d(23): Error: cannot create default argument for `ref` / `out` parameter from expression `prop()` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d index c3c735e..0db6a45 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_arrayop2.d @@ -207,21 +207,21 @@ fail_compilation/fail_arrayop2.d(265): Error: array operation `[1] * 6` without fail_compilation/fail_arrayop2.d(268): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'` without destination memory not allowed fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(275): Error: `([1] * 6)[0..2]` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(275): Error: cannot take address of expression `([1] * 6)[0..2]` because it is not an lvalue fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]` fail_compilation/fail_arrayop2.d(281): Error: the `delete` keyword is obsolete fail_compilation/fail_arrayop2.d(281): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(290): Error: `[1] * 6` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(290): Error: cannot modify expression `[1] * 6` because it is not an lvalue fail_compilation/fail_arrayop2.d(291): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(294): Error: `[1] * 6` is not an lvalue and cannot be modified -fail_compilation/fail_arrayop2.d(295): Error: `([1] * 6)[]` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(294): Error: cannot modify expression `[1] * 6` because it is not an lvalue +fail_compilation/fail_arrayop2.d(295): Error: cannot modify expression `([1] * 6)[]` because it is not an lvalue fail_compilation/fail_arrayop2.d(298): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(299): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(300): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(303): Error: `[1] * 6` is not an lvalue and cannot be modified -fail_compilation/fail_arrayop2.d(304): Error: `[1] * 6` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(303): Error: cannot modify expression `[1] * 6` because it is not an lvalue +fail_compilation/fail_arrayop2.d(304): Error: cannot modify expression `[1] * 6` because it is not an lvalue fail_compilation/fail_arrayop2.d(307): Error: `[1] * 6` is not of integral type, it is a `int[]` fail_compilation/fail_arrayop2.d(308): Error: `[1] * 6` is not of integral type, it is a `int[]` fail_compilation/fail_arrayop2.d(309): Error: `[1] * 6` is not of integral type, it is a `int[]` diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d index a9e5429..9851ffc 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d +++ b/gcc/testsuite/gdc.test/fail_compilation/fail_scope.d @@ -1,10 +1,6 @@ /* TEST_OUTPUT: --- -fail_compilation/fail_scope.d(28): Deprecation: scope parameter `da` may not be returned -fail_compilation/fail_scope.d(30): Deprecation: scope parameter `o` may not be returned -fail_compilation/fail_scope.d(31): Deprecation: scope parameter `dg` may not be returned -fail_compilation/fail_scope.d(38): Deprecation: scope parameter `p` may not be returned fail_compilation/fail_scope.d(43): Error: returning `cast(char[])string` escapes a reference to local variable `string` fail_compilation/fail_scope.d(61): Error: returning `s.bar()` escapes a reference to local variable `s` fail_compilation/fail_scope.d(72): Error: `fail_scope.foo8` called with argument types `(int)` matches both: @@ -23,6 +19,10 @@ fail_compilation/fail_scope.d(135): Error: returning `foo16226(i)` escapes a ref //fail_compilation/fail_scope.d(40): Error: scope variable `p` may not be returned */ + + + + alias int delegate() dg_t; int[] checkEscapeScope1(scope int[] da) { return da; } diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice10419.d b/gcc/testsuite/gdc.test/fail_compilation/ice10419.d index 827f045..fed8c60 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice10419.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice10419.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice10419.d(12): Error: `arr().length` is not an lvalue and cannot be modified +fail_compilation/ice10419.d(12): Error: cannot modify expression `arr().length` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice12841.d b/gcc/testsuite/gdc.test/fail_compilation/ice12841.d index c5894d2..343624d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice12841.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice12841.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12841.d(23): Error: `taskPool().amap(Args...)(Args args)` is not an lvalue and cannot be modified -fail_compilation/ice12841.d(24): Error: `amap(Args...)(Args args)` is not an lvalue and cannot be modified +fail_compilation/ice12841.d(23): Error: cannot take address of expression `taskPool().amap(Args...)(Args args)` because it is not an lvalue +fail_compilation/ice12841.d(24): Error: cannot take address of template `amap(Args...)(Args args)`, perhaps instantiate it first --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice13459.d b/gcc/testsuite/gdc.test/fail_compilation/ice13459.d index d34fc60..6998e68 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice13459.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice13459.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/ice13459.d(12): Error: undefined identifier `B` fail_compilation/ice13459.d(18): Error: none of the overloads of `opSlice` are callable using argument types `(int, int)` -fail_compilation/ice13459.d(11): Candidate is: `ice13459.A.opSlice()` +fail_compilation/ice13459.d(11): Candidate is: `ice13459.A.opSlice() const` --- */ struct A diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice20264.d b/gcc/testsuite/gdc.test/fail_compilation/ice20264.d index 0d697e2..df6667d 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice20264.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice20264.d @@ -2,7 +2,7 @@ DISABLED: freebsd32 linux32 osx32 win32 TEST_OUTPUT: --- -fail_compilation/ice20264.d(12): Error: `cast(__vector(float[4]))a` is not an lvalue and cannot be modified +fail_compilation/ice20264.d(12): Error: cannot modify expression `cast(__vector(float[4]))a` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d index 47fd44c..c9ab014 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/ice9284.d +++ b/gcc/testsuite/gdc.test/fail_compilation/ice9284.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/ice9284.d(14): Error: template `ice9284.C.__ctor` is not callable using argument types `!()(int)` -fail_compilation/ice9284.d(12): Candidate is: `__ctor()(string)` +fail_compilation/ice9284.d(12): Candidate is: `this()(string)` fail_compilation/ice9284.d(20): Error: template instance `ice9284.C.__ctor!()` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d b/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d new file mode 100644 index 0000000..408e402 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/immutable_ctor.d @@ -0,0 +1,19 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/immutable_ctor.d(18): Error: `immutable` copy constructor `immutable_ctor.S1.this` cannot construct a mutable object +--- +*/ + +struct S1 +{ + this(ref const S1 s) immutable { + } + int i; +} + +void main() +{ + const(S1) s1; + S1 ms1 = s1; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d index fe4ad78..79eda2e 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/issue16020.d +++ b/gcc/testsuite/gdc.test/fail_compilation/issue16020.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations -fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration, not `(` -fail_compilation/issue16020.d(13): Error: declaration expected, not `(` +fail_compilation/issue16020.d(13): Error: user-defined attributes not allowed for `alias` declarations +fail_compilation/issue16020.d(14): Error: semicolon expected to close `alias` declaration, not `(` +fail_compilation/issue16020.d(14): Error: declaration expected, not `(` +fail_compilation/issue16020.d(15): Deprecation: storage class `final` has no effect in type aliases --- */ module issue16020; @@ -11,3 +12,4 @@ module issue16020; struct UDA{} alias Fun = @UDA void(); alias FunTemplate = void(T)(T t); +alias F2 = final int(); diff --git a/gcc/testsuite/gdc.test/fail_compilation/issue20704.d b/gcc/testsuite/gdc.test/fail_compilation/issue20704.d index 1e1f2e6..ba91b06 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/issue20704.d +++ b/gcc/testsuite/gdc.test/fail_compilation/issue20704.d @@ -1,12 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/issue20704.d(17): Error: cannot modify constant `0` +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from constant `0` fail_compilation/issue20704.d(28): Error: template instance `issue20704.f2!int` error instantiating -fail_compilation/issue20704.d(19): Error: cannot modify constant `0` +fail_compilation/issue20704.d(19): Error: cannot create default argument for `ref` / `out` parameter from constant `0` fail_compilation/issue20704.d(30): Error: template instance `issue20704.f4!int` error instantiating -fail_compilation/issue20704.d(17): Error: `S(0)` is not an lvalue and cannot be modified +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `S(0)` because it is not an lvalue fail_compilation/issue20704.d(36): Error: template instance `issue20704.f2!(S)` error instantiating -fail_compilation/issue20704.d(17): Error: `null` is not an lvalue and cannot be modified +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `null` because it is not an lvalue fail_compilation/issue20704.d(38): Error: template instance `issue20704.f2!(C)` error instantiating --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test16381.d b/gcc/testsuite/gdc.test/fail_compilation/test16381.d index fd92798..5847e04 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test16381.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test16381.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -m64 TEST_OUTPUT: --- -fail_compilation/test16381.d(15): Error: `foo()` is not an lvalue and cannot be modified +fail_compilation/test16381.d(15): Error: cannot take address of expression `foo()` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test22048.d b/gcc/testsuite/gdc.test/fail_compilation/test22048.d index e056068..72b9154 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test22048.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test22048.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/test22048.d(10): Error: unexpected identifier `p` in declarator +fail_compilation/test22048.d(10): Error: unexpected identifier `p` after `int` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24157.d b/gcc/testsuite/gdc.test/fail_compilation/test24157.d index 5022014..d78c9b6 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/test24157.d +++ b/gcc/testsuite/gdc.test/fail_compilation/test24157.d @@ -3,8 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/test24157.d(23): Error: `p.self()` is not an lvalue and cannot be modified -fail_compilation/test24157.d(27): Error: `p.unshared()` is not an lvalue and cannot be modified +fail_compilation/test24157.d(23): Error: cannot take address of expression `p.self()` because it is not an lvalue +fail_compilation/test24157.d(27): Error: cannot take address of expression `p.unshared()` because it is not an lvalue --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test24159.d b/gcc/testsuite/gdc.test/fail_compilation/test24159.d new file mode 100644 index 0000000..35c7f36 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test24159.d @@ -0,0 +1,14 @@ +// https://issues.dlang.org/show_bug.cgi?id=24159 +// REQUIRED_ARGS: -betterC +/* +TEST_OUTPUT: +--- +fail_compilation/test24159.d(13): Error: appending to array in `x ~= 3` requires the GC which is not available with -betterC +--- +*/ + +extern(C) void main() +{ + int[] x = null; + x ~= 3; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d index 50cebab..1173d14 100644 --- a/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d +++ b/gcc/testsuite/gdc.test/fail_compilation/testrvaluecpctor.d @@ -5,9 +5,9 @@ TEST_OUTPUT: --- fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo` fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo` -fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `__ctor` are callable using a `immutable` object +fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct a `immutable` object with argument types `(immutable(Foo!int))` fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)` -fail_compilation/testrvaluecpctor.d(16): `__ctor(Rhs, this This)(scope Rhs rhs)` +fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)` --- */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d b/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d new file mode 100644 index 0000000..e911dff --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/tolvalue.d @@ -0,0 +1,48 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/tolvalue.d(28): Error: cannot take address of template `templateFunc(T)()`, perhaps instantiate it first +fail_compilation/tolvalue.d(29): Error: cannot take address of type `int` +fail_compilation/tolvalue.d(30): Error: cannot take address of constant `3` +fail_compilation/tolvalue.d(31): Error: cannot take address of operator `$` +fail_compilation/tolvalue.d(32): Error: cannot take address of compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(33): Error: cannot take address of manifest constant `f` +fail_compilation/tolvalue.d(38): Error: cannot create default argument for `ref` / `out` parameter from constant `3` +fail_compilation/tolvalue.d(39): Error: cannot create default argument for `ref` / `out` parameter from compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(40): Error: cannot create default argument for `ref` / `out` parameter from manifest constant `f` +fail_compilation/tolvalue.d(45): Error: cannot modify constant `3` +fail_compilation/tolvalue.d(46): Error: cannot modify compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(47): Error: cannot modify manifest constant `f` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24238 + +void templateFunc(T)() {} +alias intAlias = int; +enum E { f } + +void addr() +{ + int[] a; + auto x0 = &templateFunc; + auto x1 = &intAlias; + auto x2 = &3; + auto x3 = a[&$]; + auto x4 = &__ctfe; + auto x6 = &E.f; +} + +void refArg() +{ + void f0(ref int = 3) {} + void f1(ref bool = __ctfe) {} + void f3(ref E = E.f) {} +} + +void inc(int lz) +{ + 3++; + __ctfe++; + E.f++; +} diff --git a/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d b/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d new file mode 100644 index 0000000..e8a8d48 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/vector_cast.d @@ -0,0 +1,13 @@ +/** +REQUIRED_ARGS: -m64 +TEST_OUTPUT: +--- +fail_compilation/vector_cast.d(11): Error: cannot cast expression `a` of type `int[3]` to `__vector(int[4])` +fail_compilation/vector_cast.d(13): Error: cannot cast expression `a` of type `int[5]` to `__vector(int[4])` +--- +*/ + +alias int4 = __vector(int[4]); +int4 convtest3(int[3] a) { return cast(int4) a; } +int4 convtest4(int[4] a) { return cast(int4) a; } +int4 convtest5(int[5] a) { return cast(int4) a; } diff --git a/gcc/testsuite/gdc.test/runnable/previewin.d b/gcc/testsuite/gdc.test/runnable/previewin.d index 117070df..50f22ee 100644 --- a/gcc/testsuite/gdc.test/runnable/previewin.d +++ b/gcc/testsuite/gdc.test/runnable/previewin.d @@ -154,27 +154,25 @@ struct WithDtor @safe pure nothrow @nogc: // By value -void testin1(in uint p) { static assert(!__traits(isRef, p)); } +void testin1(in uint p) { } // By ref because of size -void testin2(in ulong[64] p) { static assert(__traits(isRef, p)); } +void testin2(in ulong[64] p) { } // By value or ref depending on size (or structs always passed by reference) -void testin3(in ValueT p) { static assert(!__traits(isRef, p) || true); } -void testin3(in RefT p) { static assert(__traits(isRef, p)); } +void testin3(in ValueT p) { } +void testin3(in RefT p) { } // By ref because of size (or arrays always passed by reference) -void testin4(in ValueT[64] p) { static assert(__traits(isRef, p)); } -void testin4(in RefT[4] p) { static assert(__traits(isRef, p)); } +void testin4(in ValueT[64] p) { } +void testin4(in RefT[4] p) { } // By ref because of non-copyability -void testin5(in NonCopyable noncopy) { static assert(__traits(isRef, noncopy)); } -static assert(testin5.mangleof == "_D9previewin7testin5FNaNbNiNfIKSQBe11NonCopyableZv"); // incl. `ref` +void testin5(in NonCopyable noncopy) { } // By ref because of postblit -void testin6(in WithPostblit withpostblit) { static assert(__traits(isRef, withpostblit)); } +void testin6(in WithPostblit withpostblit) { } // By ref because of copy ctor -void testin7(in WithCopyCtor withcopy) { static assert(__traits(isRef, withcopy)); } +void testin7(in WithCopyCtor withcopy) { } // By ref because of dtor void testin8(in WithDtor withdtor, scope bool* isTestOver) { - static assert(__traits(isRef, withdtor)); if (isTestOver) *isTestOver = true; } diff --git a/gcc/testsuite/gdc.test/runnable/staticaa.d b/gcc/testsuite/gdc.test/runnable/staticaa.d index 17a2ecb..606b70e 100644 --- a/gcc/testsuite/gdc.test/runnable/staticaa.d +++ b/gcc/testsuite/gdc.test/runnable/staticaa.d @@ -56,7 +56,7 @@ struct Key { int v; bool opEquals(ref const Key o) const { return v == o.v; } - size_t toHash() const { return v; } + size_t toHash() const nothrow { return v; } } Destructing[Key] dAa = [Key(1): Destructing(10), Key(2): Destructing(20)]; @@ -142,6 +142,18 @@ void testImmutable() ///////////////////////////////////////////// +// https://issues.dlang.org/show_bug.cgi?id=24209 +void testLocalStatic() @trusted +{ + static int[int] aa0 = [1: 2]; + __gshared string[string] aa1 = null; + + assert(aa0[1] == 2); + assert(aa1.length == 0); +} + +///////////////////////////////////////////// + void main() { testSimple(); @@ -150,4 +162,5 @@ void main() testStructInit(); testClassInit(); testImmutable(); + testLocalStatic(); } diff --git a/gcc/testsuite/gdc.test/runnable/test24184.d b/gcc/testsuite/gdc.test/runnable/test24184.d new file mode 100644 index 0000000..736824fc --- /dev/null +++ b/gcc/testsuite/gdc.test/runnable/test24184.d @@ -0,0 +1,30 @@ +// https://issues.dlang.org/show_bug.cgi?id=24184 + +void stage3(alias abc)(ubyte[]) +{ + bool skipSpaces() + { + abc(); + return false; + } + skipSpaces; +} +ubyte[] singleThreadJsonImpl(alias xxx)(ubyte[] table) +{ + align(64) ubyte[] vector; + + ubyte[] abc() { return vector; } + + stage3!(abc)(table); + + return table; +} +ubyte[] singleThreadJsonText() +{ + bool xxx() { return true; } + + return singleThreadJsonImpl!(xxx)([]); +} +void deserializeJson() { singleThreadJsonText(); } + +void main() { deserializeJson(); } diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_10.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_10.f90 index 6a3cc94..f22d43a 100644 --- a/gcc/testsuite/gfortran.dg/assumed_rank_10.f90 +++ b/gcc/testsuite/gfortran.dg/assumed_rank_10.f90 @@ -50,9 +50,9 @@ program test is_present = .false. - call fpa(null(), null()) ! No copy back - call fpi(null(), null()) ! No copy back - call fno(null(), null()) ! No copy back + call fpa(null(iip), null(jjp)) ! No copy back + call fpi(null(iip), null(jjp)) ! No copy back + call fno(null(iip), null(jjp)) ! No copy back call fno() ! No copy back diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_8.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_8.f90 index 5873296..34ff42c 100644 --- a/gcc/testsuite/gfortran.dg/assumed_rank_8.f90 +++ b/gcc/testsuite/gfortran.dg/assumed_rank_8.f90 @@ -22,13 +22,13 @@ program main call f (ii) call f (489) call f () - call f (null()) + call f (null(kk)) call f (kk) if (j /= 2) STOP 1 j = 0 nullify (ll) - call g (null()) + call g (null(ll)) call g (ll) call g (ii) if (j /= 1) STOP 2 diff --git a/gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 b/gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 new file mode 100644 index 0000000..8a3625e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/depobj-3.f90 @@ -0,0 +1,18 @@ +! { dg-do compile { target { fortran_integer_16 || ilp32 } } } +! omp_depend_kind = 2*intptr_t --> 16 (128 bit) on 64bit-pointer systems +! --> 8 (128 bit) on 32bit-pointer systems +subroutine f1 + !use omp_lib ! N/A in gcc/testsuite + use iso_c_binding, only: c_intptr_t + implicit none + integer, parameter :: omp_depend_kind = 2*c_intptr_t + integer :: a, b + integer(kind=omp_depend_kind) :: depobj, depobj1(5), depobj2 + + !$omp depobj(depobj) destroy + + !$omp depobj(depobj) destroy( depobj) + + !$omp depobj(depobj) destroy( depobj2) ! { dg-warning "The same depend object should be used as DEPOBJ argument at .1. and as DESTROY argument at .2." } + !$omp depobj(depobj) destroy( a) ! { dg-warning "The same depend object should be used as DEPOBJ argument at .1. and as DESTROY argument at .2." } +end diff --git a/gcc/testsuite/gfortran.dg/pr111880.f90 b/gcc/testsuite/gfortran.dg/pr111880.f90 new file mode 100644 index 0000000..c0cd98a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr111880.f90 @@ -0,0 +1,22 @@ +! { dg-do compile } +! { dg-options "-std=f2018" } +! PR fortran/111880 - redundant warning of obsolescent COMMON with submodule + +module third_party_module + integer :: some_param + common /not_my_code/ some_param ! { dg-warning "COMMON block" } +end module third_party_module + +module foo + use third_party_module + interface + module subroutine bar() + end subroutine bar + end interface +end module foo + +submodule (foo) foo_submod ! We do not need a warning here! +contains + module procedure bar + end procedure bar +end submodule foo_submod diff --git a/gcc/testsuite/gfortran.dg/pr112406.f90 b/gcc/testsuite/gfortran.dg/pr112406.f90 new file mode 100644 index 0000000..27e96df --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr112406.f90 @@ -0,0 +1,21 @@ +! { dg-do compile { target { aarch64-*-* || riscv*-*-* } } } +! { dg-options "-Ofast -w -fprofile-generate" } +! { dg-additional-options "-march=rv64gcv -mabi=lp64d" { target riscv*-*-* } } +! { dg-additional-options "-march=armv8-a+sve" { target aarch64-*-* } } + +module brute_force + integer, parameter :: r=9 + integer sudoku1(1, r) + contains +subroutine brute +integer l(r), u(r) + where(sudoku1(1, :) /= 1) + l = 1 + u = 1 + end where +do i1 = 1, u(1) + do + end do + end do +end +end diff --git a/gcc/testsuite/gfortran.dg/pr43984.f90 b/gcc/testsuite/gfortran.dg/pr43984.f90 index 130d114..dce26b0 100644 --- a/gcc/testsuite/gfortran.dg/pr43984.f90 +++ b/gcc/testsuite/gfortran.dg/pr43984.f90 @@ -1,5 +1,5 @@ ! { dg-do compile } -! { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre" } +! { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre -fno-tree-sra" } module test type shell1quartet_type diff --git a/gcc/testsuite/gfortran.dg/system_clock_1.f90 b/gcc/testsuite/gfortran.dg/system_clock_1.f90 index 41027de..0cb0145 100644 --- a/gcc/testsuite/gfortran.dg/system_clock_1.f90 +++ b/gcc/testsuite/gfortran.dg/system_clock_1.f90 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options "-std=f2003" } integer :: i, j, k integer(kind=8) :: i8, j8, k8 diff --git a/gcc/testsuite/gfortran.dg/system_clock_3.f08 b/gcc/testsuite/gfortran.dg/system_clock_3.f08 index e52a51a..c12849b 100644 --- a/gcc/testsuite/gfortran.dg/system_clock_3.f08 +++ b/gcc/testsuite/gfortran.dg/system_clock_3.f08 @@ -1,4 +1,5 @@ ! { dg-do run } +! { dg-options "-std=f2008" } ! PR64432 program countem implicit none diff --git a/gcc/testsuite/gfortran.dg/system_clock_4.f90 b/gcc/testsuite/gfortran.dg/system_clock_4.f90 new file mode 100644 index 0000000..1bb42ef --- /dev/null +++ b/gcc/testsuite/gfortran.dg/system_clock_4.f90 @@ -0,0 +1,24 @@ +! { dg-do compile } +! { dg-options "-std=f2023" } +! PR fortran/112609 - F2023 restrictions on integer arguments to SYSTEM_CLOCK + +program p + implicit none + integer :: i, j, k + integer(2) :: i2, j2, k2 + integer(8) :: i8, j8, k8 + real :: x + + call system_clock(count=i2) ! { dg-error "kind smaller than default integer" } + call system_clock(count_rate=j2) ! { dg-error "kind smaller than default integer" } + call system_clock(count_max=k2) ! { dg-error "kind smaller than default integer" } + + call system_clock(count=i8,count_rate=x,count_max=k8) + call system_clock(count=i, count_rate=j8) ! { dg-error "different kind" } + call system_clock(count=i8,count_rate=j) ! { dg-error "different kind" } + call system_clock(count=i, count_max=k8) ! { dg-error "different kind" } + call system_clock(count=i8,count_max=k) ! { dg-error "different kind" } + call system_clock(count_rate=j, count_max=k8) ! { dg-error "different kind" } + call system_clock(count_rate=j8,count_max=k) ! { dg-error "different kind" } + call system_clock(i,x,k8) ! { dg-error "different kind" } +end diff --git a/gcc/testsuite/gfortran.dg/vect/pr107254.f90 b/gcc/testsuite/gfortran.dg/vect/pr107254.f90 index 85bcb5f..adce6be 100644 --- a/gcc/testsuite/gfortran.dg/vect/pr107254.f90 +++ b/gcc/testsuite/gfortran.dg/vect/pr107254.f90 @@ -1,5 +1,3 @@ -! { dg-do run } - subroutine dlartg( f, g, s, r ) implicit none double precision :: f, g, r, s diff --git a/gcc/testsuite/gfortran.dg/vect/pr85853.f90 b/gcc/testsuite/gfortran.dg/vect/pr85853.f90 index 68f4a00..4c0e3b8 100644 --- a/gcc/testsuite/gfortran.dg/vect/pr85853.f90 +++ b/gcc/testsuite/gfortran.dg/vect/pr85853.f90 @@ -1,5 +1,4 @@ ! Taken from execute/where_2.f90, but with special flags. -! { dg-do run } ! { dg-additional-options "-fno-tree-loop-vectorize" } ! Program to test the WHERE constructs diff --git a/gcc/testsuite/gfortran.dg/vect/vect-alias-check-1.F90 b/gcc/testsuite/gfortran.dg/vect/vect-alias-check-1.F90 index 3014ff9..85ae9b1 100644 --- a/gcc/testsuite/gfortran.dg/vect/vect-alias-check-1.F90 +++ b/gcc/testsuite/gfortran.dg/vect/vect-alias-check-1.F90 @@ -1,4 +1,3 @@ -! { dg-do run } ! { dg-additional-options "-fno-inline" } #define N 200 diff --git a/gcc/testsuite/gnat.dg/warn25.adb b/gcc/testsuite/gnat.dg/warn25.adb index e784870..cdf28ae 100644 --- a/gcc/testsuite/gnat.dg/warn25.adb +++ b/gcc/testsuite/gnat.dg/warn25.adb @@ -1,5 +1,6 @@ -- { dg-do compile } -- { dg-options "-gnatwa" } +-- { dg-xfail-if "expected regression" { *-*-* } } with Ada.Exceptions; procedure Warn25 is diff --git a/gcc/testsuite/lib/plugin-support.exp b/gcc/testsuite/lib/plugin-support.exp index 378881b..8accf13 100644 --- a/gcc/testsuite/lib/plugin-support.exp +++ b/gcc/testsuite/lib/plugin-support.exp @@ -85,7 +85,7 @@ proc plugin-test-execute { plugin_src plugin_tests } { set gcc_objdir "$objdir/../../.." set includes "-I. -I${srcdir} -I${gcc_srcdir}/gcc -I${gcc_objdir}/gcc \ -I${gcc_srcdir}/include -I${gcc_srcdir}/libcpp/include \ - $GMPINC -I${gcc_objdir}/intl" + $GMPINC -I${gcc_objdir}/gettext/intl" if { [ ishost *-*-darwin* ] } { # -mdynamic-no-pic is incompatible with -fPIC. diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 16b5198..d30e361 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -505,7 +505,7 @@ proc scan-assembler-times { args } { close $fd regsub -all {(^|\n)[[:space:]]*\.section[[:space:]]*\.gnu\.lto_(?:[^\n]*\n(?![[:space:]]*\.(section|text|data|bss)))*[^\n]*\n} $text {\1} text - set result_count [llength [regexp -inline -all -- $pattern $text]] + set result_count [regexp -all -- $pattern $text] if {$result_count == $times} { pass "$testcase scan-assembler-times $pp_pattern $times" } else { @@ -804,23 +804,34 @@ proc configure_check-function-bodies { config } { # Regexp for the start of a function definition (name in \1). if { [istarget nvptx*-*-*] } { - set up_config(start) {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$} + set up_config(start) { + {^// BEGIN(?: GLOBAL|) FUNCTION DEF: ([a-zA-Z_]\S+)$} + } + } elseif { [istarget *-*-darwin*] } { + set up_config(start) { + {^_([a-zA-Z_]\S+):$} + {^LFB[0-9]+:} + } } else { - set up_config(start) {^([a-zA-Z_]\S+):$} + set up_config(start) {{^([a-zA-Z_]\S+):$}} } # Regexp for the end of a function definition. if { [istarget nvptx*-*-*] } { set up_config(end) {^\}$} + } elseif { [istarget *-*-darwin*] } { + set up_config(end) {^LFE[0-9]+} } else { set up_config(end) {^\s*\.size} } - + # Regexp for lines that aren't interesting. if { [istarget nvptx*-*-*] } { # Skip lines beginning with '//' comments ('-fverbose-asm', for # example). set up_config(fluff) {^\s*(?://)} + } elseif { [istarget *-*-darwin*] } { + set up_config(fluff) {^\s*(?:\.|//|@)|^L[0-9ACESV]} } else { # Skip lines beginning with labels ('.L[...]:') or other directives # ('.align', '.cfi_startproc', '.quad [...]', '.text', etc.), '//' or @@ -852,11 +863,28 @@ proc parse_function_bodies { config filename result } { set fd [open $filename r] set in_function 0 while { [gets $fd line] >= 0 } { - if { [regexp $up_config(start) $line dummy function_name] } { - set in_function 1 - set function_body "" + if { $in_function == 0 } { + if { [regexp [lindex $up_config(start) 0] \ + $line dummy function_name] } { + set in_function 1 + set function_body "" + } + } elseif { $in_function < [llength $up_config(start)] } { + if { [regexp [lindex $up_config(start) $in_function] $line] } { + incr in_function + } else { + verbose "parse_function_bodies: skipped $function_name" + set in_function 0 + } } elseif { $in_function } { - if { [regexp $up_config(end) $line] } { + # We allow multiple function start labels, taking the last one seen + # as the function name. + if { [regexp [lindex $up_config(start) 0] \ + $line dummy maybe_function_name] } { + verbose "parse_function_bodies: overriding $function_name with $maybe_function_name" + set function_name $maybe_function_name + set in_function 1 + } elseif { [regexp $up_config(end) $line] } { verbose "parse_function_bodies: $function_name:\n$function_body" set up_result($function_name) $function_body set in_function 0 @@ -957,7 +985,6 @@ proc check-function-bodies { args } { set start_expected {^(\S+):$} configure_check-function-bodies config - set have_bodies 0 if { [is_remote host] } { remote_upload host "$filename" diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 8777e3b..87b2ae5 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1983,6 +1983,17 @@ proc check_effective_target_riscv_ztso { } { }] } +# Return 1 if the target arch supports the Zbb extension, 0 otherwise. +# Cache the result. + +proc check_effective_target_riscv_zbb { } { + return [check_no_compiler_messages riscv_ext_zbb assembly { + #ifndef __riscv_zbb + #error "Not __riscv_zbb" + #endif + }] +} + # Return 1 if we can execute code when using dg-add-options riscv_v proc check_effective_target_riscv_v_ok { } { @@ -3805,7 +3816,7 @@ proc check_effective_target___float128 { } { } proc add_options_for___float128 { flags } { - if { [istarget powerpc*-*-*] } { + if { [istarget powerpc*-*-linux*] } { return "$flags -mfloat128 -mvsx" } return "$flags" @@ -5592,7 +5603,7 @@ proc check_effective_target_arm_thumb1_movt_ok {} { proc check_effective_target_arm_thumb1_cbz_ok {} { if [check_effective_target_arm_thumb1_ok] { - return [check_no_compiler_messages arm_movt object { + return [check_no_compiler_messages arm_cbz object { int foo (void) { @@ -7178,7 +7189,7 @@ proc check_effective_target_powerpc_vsx_ok { } { return 0 } # Darwin doesn't have VSX, even if it's used with an assembler - # which recognises the insns. + # which recognises the insns. if { [istarget *-*-darwin*] } { return 0 } @@ -9257,7 +9268,8 @@ proc check_effective_target_vect_call_roundf { } { proc check_effective_target_vect_logical_reduc { } { return [expr { [check_effective_target_aarch64_sve] || [istarget amdgcn-*-*] - || [check_effective_target_riscv_v] }] + || [check_effective_target_riscv_v] + || [istarget i?86-*-*] || [istarget x86_64-*-*]}] } # Return 1 if the target supports the fold_extract_last optab. @@ -11090,7 +11102,7 @@ proc check_effective_target_gas { } { if { [ string first "GNU" $as_output ] >= 0 } { # Some Darwin versions have an assembler which is based on an old # version of GAS (and reports GNU assembler in its -v output) but - # but doesn't support many of the modern GAS features. + # but doesn't support many of the modern GAS features. if { [ string first "cctools" $as_output ] >= 0 } { set use_gas_saved 0 } else { @@ -11563,7 +11575,6 @@ proc check_vect_support_and_set_flags { } { set dg-do-what-default run } elseif [istarget riscv64-*-*] { if [check_effective_target_riscv_vector_hw] { - lappend DEFAULT_VECTCFLAGS "--param" "riscv-autovec-preference=scalable" lappend DEFAULT_VECTCFLAGS "--param" "riscv-vector-abi" set dg-do-what-default run } else { diff --git a/gcc/testsuite/obj-c++.dg/has-feature.mm b/gcc/testsuite/obj-c++.dg/has-feature.mm new file mode 100644 index 0000000..77c7617 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/has-feature.mm @@ -0,0 +1,21 @@ +// { dg-do compile } + +#define CXX11 (__cplusplus >= 201103L) + +#if !__has_feature (objc_instancetype) +#error +#endif + +#if !__has_feature (objc_default_synthesize_properties) +#error +#endif + +// C features should not be available. +#if __has_extension (c_alignas) || __has_feature (c_alignof) +#error +#endif + +// C++ features should be available (given the right standard). +#if __has_feature (cxx_constexpr) != CXX11 +#error +#endif diff --git a/gcc/testsuite/objc.dg/has-feature.m b/gcc/testsuite/objc.dg/has-feature.m new file mode 100644 index 0000000..168b0ce --- /dev/null +++ b/gcc/testsuite/objc.dg/has-feature.m @@ -0,0 +1,26 @@ +/* { dg-do compile } */ + +#define HAVE_C11 (__STDC_VERSION__ >= 201112L) + +#if !__has_feature (objc_instancetype) +#error +#endif + +#if !__has_feature (objc_default_synthesize_properties) +#error +#endif + +/* C features should be available as extensions. */ +#if !__has_extension (c_alignas) +#error +#endif + +/* And as features given the appropriate C standard. */ +#if __has_feature (c_alignas) != HAVE_C11 +#error +#endif + +/* Shouldn't have C++ features even as extensions. */ +#if __has_feature (cxx_constexpr) || __has_extension (cxx_constexpr) +#error +#endif diff --git a/gcc/toplev.cc b/gcc/toplev.cc index 8c3fcd3..85450d9 100644 --- a/gcc/toplev.cc +++ b/gcc/toplev.cc @@ -1568,6 +1568,13 @@ process_options () flag_associative_math = 0; } + if (flag_hardened && !HAVE_FHARDENED_SUPPORT) + { + warning_at (UNKNOWN_LOCATION, 0, + "%<-fhardened%> not supported for this target"); + flag_hardened = 0; + } + /* -fstack-clash-protection is not currently supported on targets where the stack grows up. */ if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD) @@ -1577,6 +1584,19 @@ process_options () "where the stack grows from lower to higher addresses"); flag_stack_clash_protection = 0; } + else if (flag_hardened) + { + if (!flag_stack_clash_protection + /* Don't enable -fstack-clash-protection when -fstack-check= + is used: it would result in confusing errors. */ + && flag_stack_check == NO_STACK_CHECK) + flag_stack_clash_protection = 1; + else if (flag_stack_check != NO_STACK_CHECK) + warning_at (UNKNOWN_LOCATION, OPT_Whardened, + "%<-fstack-clash-protection%> is not enabled by " + "%<-fhardened%> because %<-fstack-check%> was " + "specified on the command line"); + } /* We cannot support -fstack-check= and -fstack-clash-protection at the same time. */ @@ -1592,8 +1612,9 @@ process_options () target already uses a soft frame pointer, the transition is trivial. */ if (!FRAME_GROWS_DOWNWARD && flag_stack_protect) { - warning_at (UNKNOWN_LOCATION, 0, - "%<-fstack-protector%> not supported for this target"); + if (!flag_stack_protector_set_by_fhardened_p) + warning_at (UNKNOWN_LOCATION, 0, + "%<-fstack-protector%> not supported for this target"); flag_stack_protect = 0; } if (!flag_stack_protect) diff --git a/gcc/tree-chrec.cc b/gcc/tree-chrec.cc index 2f67581..e2864e8 100644 --- a/gcc/tree-chrec.cc +++ b/gcc/tree-chrec.cc @@ -613,32 +613,54 @@ chrec_apply (unsigned var, if (evolution_function_is_affine_p (chrec)) { tree chrecr = CHREC_RIGHT (chrec); + tree chrecl = CHREC_LEFT (chrec); if (CHREC_VARIABLE (chrec) != var) - res = build_polynomial_chrec - (CHREC_VARIABLE (chrec), - chrec_apply (var, CHREC_LEFT (chrec), x), - chrec_apply (var, chrecr, x)); + res = build_polynomial_chrec (CHREC_VARIABLE (chrec), + chrec_apply (var, chrecl, x), + chrec_apply (var, chrecr, x)); - /* "{a, +, b} (x)" -> "a + b*x". */ - else if (operand_equal_p (CHREC_LEFT (chrec), chrecr) + /* "{a, +, a}" (x-1) -> "a*x". */ + else if (operand_equal_p (chrecl, chrecr) && TREE_CODE (x) == PLUS_EXPR && integer_all_onesp (TREE_OPERAND (x, 1)) && !POINTER_TYPE_P (type) && TYPE_PRECISION (TREE_TYPE (x)) >= TYPE_PRECISION (type)) { - /* We know the number of iterations can't be negative. - So {a, +, a} (x-1) -> "a*x". */ + /* We know the number of iterations can't be negative. */ res = build_int_cst (TREE_TYPE (x), 1); res = chrec_fold_plus (TREE_TYPE (x), x, res); res = chrec_convert_rhs (type, res, NULL); res = chrec_fold_multiply (type, chrecr, res); } + /* "{a, +, b} (x)" -> "a + b*x". */ else { - res = chrec_convert_rhs (TREE_TYPE (chrecr), x, NULL); - res = chrec_fold_multiply (TREE_TYPE (chrecr), chrecr, res); - res = chrec_fold_plus (type, CHREC_LEFT (chrec), res); + /* The overall increment might not fit in a signed type so + use an unsigned computation to get at the final value + and avoid undefined signed overflow. */ + tree utype = TREE_TYPE (chrecr); + if (INTEGRAL_TYPE_P (utype) && !TYPE_OVERFLOW_WRAPS (utype)) + utype = unsigned_type_for (TREE_TYPE (chrecr)); + res = chrec_convert_rhs (utype, x, NULL); + res = chrec_fold_multiply (utype, + chrec_convert (utype, chrecr, NULL), + res); + /* When the resulting increment fits the original type + do the increment in it. */ + if (TREE_CODE (res) == INTEGER_CST + && int_fits_type_p (res, TREE_TYPE (chrecr))) + { + res = chrec_convert (TREE_TYPE (chrecr), res, NULL); + res = chrec_fold_plus (type, chrecl, res); + } + else + { + res = chrec_fold_plus (utype, + chrec_convert (utype, chrecl, NULL), + res); + res = chrec_convert (type, res, NULL); + } } } else if (TREE_CODE (x) == INTEGER_CST diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc index ffca535..95c1eea 100644 --- a/gcc/tree-loop-distribution.cc +++ b/gcc/tree-loop-distribution.cc @@ -2155,9 +2155,6 @@ loop_distribution::pg_add_dependence_edges (struct graph *rdg, int dir, } else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) { - if (DDR_REVERSED_P (ddr)) - this_dir = -this_dir; - /* Known dependences can still be unordered througout the iteration space, see gcc.dg/tree-ssa/ldist-16.c and gcc.dg/tree-ssa/pr94969.c. */ @@ -2170,7 +2167,20 @@ loop_distribution::pg_add_dependence_edges (struct graph *rdg, int dir, /* Else as the distance vector is lexicographic positive swap the dependence direction. */ else - this_dir = -this_dir; + { + if (DDR_REVERSED_P (ddr)) + this_dir = -this_dir; + this_dir = -this_dir; + + /* When then dependence distance of the innermost common + loop of the DRs is zero we have a conflict. */ + auto l1 = gimple_bb (DR_STMT (dr1))->loop_father; + auto l2 = gimple_bb (DR_STMT (dr2))->loop_father; + int idx = index_in_loop_nest (find_common_loop (l1, l2)->num, + DDR_LOOP_NEST (ddr)); + if (DDR_DIST_VECT (ddr, 0)[idx] == 0) + this_dir = 2; + } } else this_dir = 0; diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc index 7d3cb1e..9c8fdb8 100644 --- a/gcc/tree-profile.cc +++ b/gcc/tree-profile.cc @@ -281,10 +281,13 @@ gen_assign_counter_update (gimple_stmt_iterator *gsi, gcall *call, tree func, if (result) { tree result_type = TREE_TYPE (TREE_TYPE (func)); - tree tmp = make_temp_ssa_name (result_type, NULL, name); - gimple_set_lhs (call, tmp); + tree tmp1 = make_temp_ssa_name (result_type, NULL, name); + gimple_set_lhs (call, tmp1); gsi_insert_after (gsi, call, GSI_NEW_STMT); - gassign *assign = gimple_build_assign (result, tmp); + tree tmp2 = make_temp_ssa_name (TREE_TYPE (result), NULL, name); + gassign *assign = gimple_build_assign (tmp2, NOP_EXPR, tmp1); + gsi_insert_after (gsi, assign, GSI_NEW_STMT); + assign = gimple_build_assign (result, tmp2); gsi_insert_after (gsi, assign, GSI_NEW_STMT); } else @@ -304,18 +307,18 @@ gen_counter_update (gimple_stmt_iterator *gsi, tree counter, tree result, tree one = build_int_cst (type, 1); tree relaxed = build_int_cst (integer_type_node, MEMMODEL_RELAXED); - if (counter_update == COUNTER_UPDATE_ATOMIC_BUILTIN || - (result && counter_update == COUNTER_UPDATE_ATOMIC_SPLIT)) + if (counter_update == COUNTER_UPDATE_ATOMIC_BUILTIN + || (result && counter_update == COUNTER_UPDATE_ATOMIC_SPLIT)) { /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */ tree f = builtin_decl_explicit (TYPE_PRECISION (type) > 32 - ? BUILT_IN_ATOMIC_ADD_FETCH_8: - BUILT_IN_ATOMIC_ADD_FETCH_4); + ? BUILT_IN_ATOMIC_ADD_FETCH_8 + : BUILT_IN_ATOMIC_ADD_FETCH_4); gcall *call = gimple_build_call (f, 3, addr, one, relaxed); gen_assign_counter_update (gsi, call, f, result, name); } - else if (!result && (counter_update == COUNTER_UPDATE_ATOMIC_SPLIT || - counter_update == COUNTER_UPDATE_ATOMIC_PARTIAL)) + else if (!result && (counter_update == COUNTER_UPDATE_ATOMIC_SPLIT + || counter_update == COUNTER_UPDATE_ATOMIC_PARTIAL)) { /* low = __atomic_add_fetch_4 (addr, 1, MEMMODEL_RELAXED); high_inc = low == 0 ? 1 : 0; @@ -354,7 +357,7 @@ gen_counter_update (gimple_stmt_iterator *gsi, tree counter, tree result, tree tmp2 = make_temp_ssa_name (type, NULL, name); gassign *assign2 = gimple_build_assign (tmp2, PLUS_EXPR, tmp1, one); gsi_insert_after (gsi, assign2, GSI_NEW_STMT); - gassign *assign3 = gimple_build_assign (counter, tmp2); + gassign *assign3 = gimple_build_assign (unshare_expr (counter), tmp2); gsi_insert_after (gsi, assign3, GSI_NEW_STMT); if (result) { @@ -764,6 +767,7 @@ tree_profiling (void) = HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi; bool have_atomic_8 = HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi; + bool needs_split = gcov_type_size == 8 && !have_atomic_8 && have_atomic_4; if (!can_support_atomic) { if (gcov_type_size == 4) @@ -772,6 +776,9 @@ tree_profiling (void) can_support_atomic = have_atomic_8; } + if (flag_profile_update != PROFILE_UPDATE_SINGLE && needs_split) + counter_update = COUNTER_UPDATE_ATOMIC_PARTIAL; + if (flag_profile_update == PROFILE_UPDATE_ATOMIC && !can_support_atomic) { @@ -780,18 +787,16 @@ tree_profiling (void) flag_profile_update = PROFILE_UPDATE_SINGLE; } else if (flag_profile_update == PROFILE_UPDATE_PREFER_ATOMIC) - flag_profile_update = can_support_atomic - ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE; + flag_profile_update + = can_support_atomic ? PROFILE_UPDATE_ATOMIC : PROFILE_UPDATE_SINGLE; if (flag_profile_update == PROFILE_UPDATE_ATOMIC) { - if (gcov_type_size == 8 && !have_atomic_8 && have_atomic_4) + if (needs_split) counter_update = COUNTER_UPDATE_ATOMIC_SPLIT; else counter_update = COUNTER_UPDATE_ATOMIC_BUILTIN; } - else if (gcov_type_size == 8 && have_atomic_4) - counter_update = COUNTER_UPDATE_ATOMIC_PARTIAL; /* This is a small-ipa pass that gets called only once, from cgraphunit.cc:ipa_passes(). */ diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc index b985dee..3a0d5267 100644 --- a/gcc/tree-sra.cc +++ b/gcc/tree-sra.cc @@ -337,6 +337,9 @@ static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap; because this would produce non-constant expressions (e.g. Ada). */ static bitmap disqualified_constants; +/* Bitmap of candidates which are passed by reference in call arguments. */ +static bitmap passed_by_ref_in_call; + /* Obstack for creation of fancy names. */ static struct obstack name_obstack; @@ -717,6 +720,7 @@ sra_initialize (void) should_scalarize_away_bitmap = BITMAP_ALLOC (NULL); cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL); disqualified_constants = BITMAP_ALLOC (NULL); + passed_by_ref_in_call = BITMAP_ALLOC (NULL); gcc_obstack_init (&name_obstack); base_access_vec = new hash_map<tree, auto_vec<access_p> >; memset (&sra_stats, 0, sizeof (sra_stats)); @@ -733,6 +737,7 @@ sra_deinitialize (void) BITMAP_FREE (should_scalarize_away_bitmap); BITMAP_FREE (cannot_scalarize_away_bitmap); BITMAP_FREE (disqualified_constants); + BITMAP_FREE (passed_by_ref_in_call); access_pool.release (); assign_link_pool.release (); obstack_free (&name_obstack, NULL); @@ -905,9 +910,9 @@ create_access (tree expr, gimple *stmt, bool write) &reverse); /* For constant-pool entries, check we can substitute the constant value. */ - if (constant_decl_p (base)) + if (constant_decl_p (base) + && !bitmap_bit_p (disqualified_constants, DECL_UID (base))) { - gcc_assert (!bitmap_bit_p (disqualified_constants, DECL_UID (base))); if (expr != base && !is_gimple_reg_type (TREE_TYPE (expr)) && dump_file && (dump_flags & TDF_DETAILS)) @@ -1135,6 +1140,17 @@ sra_handled_bf_read_p (tree expr) static struct access * build_access_from_expr_1 (tree expr, gimple *stmt, bool write) { + /* We only allow ADDR_EXPRs in arguments of function calls and those must + have been dealt with in build_access_from_call_arg. Any other address + taking should have been caught by scan_visit_addr. */ + if (TREE_CODE (expr) == ADDR_EXPR) + { + tree base = get_base_address (TREE_OPERAND (expr, 0)); + gcc_assert (!DECL_P (base) + || !bitmap_bit_p (candidate_bitmap, DECL_UID (base))); + return NULL; + } + struct access *ret = NULL; bool partial_ref; @@ -1223,6 +1239,77 @@ build_access_from_expr (tree expr, gimple *stmt, bool write) return false; } +enum out_edge_check { SRA_OUTGOING_EDGES_UNCHECKED, SRA_OUTGOING_EDGES_OK, + SRA_OUTGOING_EDGES_FAIL }; + +/* Return true if STMT terminates BB and there is an abnormal edge going out of + the BB and remember the decision in OE_CHECK. */ + +static bool +abnormal_edge_after_stmt_p (gimple *stmt, enum out_edge_check *oe_check) +{ + if (*oe_check == SRA_OUTGOING_EDGES_OK) + return false; + if (*oe_check == SRA_OUTGOING_EDGES_FAIL) + return true; + if (stmt_ends_bb_p (stmt)) + { + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs) + if (e->flags & EDGE_ABNORMAL) + { + *oe_check = SRA_OUTGOING_EDGES_FAIL; + return true; + } + } + *oe_check = SRA_OUTGOING_EDGES_OK; + return false; +} + +/* Scan expression EXPR which is an argument of a call and create access + structures for all accesses to candidates for scalarization. Return true if + any access has been inserted. STMT must be the statement from which the + expression is taken. */ + +static bool +build_access_from_call_arg (tree expr, gimple *stmt, + enum out_edge_check *oe_check) +{ + if (TREE_CODE (expr) == ADDR_EXPR) + { + tree base = get_base_address (TREE_OPERAND (expr, 0)); + + if (abnormal_edge_after_stmt_p (stmt, oe_check)) + { + disqualify_base_of_expr (base, "May lead to need to add statements " + "to abnormal edge."); + return false; + } + + bool read = build_access_from_expr (base, stmt, false); + bool write = build_access_from_expr (base, stmt, true); + if (read || write) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Allowed ADDR_EXPR of "); + print_generic_expr (dump_file, base); + fprintf (dump_file, " because of "); + print_gimple_stmt (dump_file, stmt, 0); + fprintf (dump_file, "\n"); + } + bitmap_set_bit (passed_by_ref_in_call, DECL_UID (base)); + return true; + } + else + return false; + } + + return build_access_from_expr (expr, stmt, false); +} + + /* Return the single non-EH successor edge of BB or NULL if there is none or more than one. */ @@ -1364,16 +1451,18 @@ build_accesses_from_assign (gimple *stmt) return lacc || racc; } -/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine - GIMPLE_ASM operands with memory constrains which cannot be scalarized. */ +/* Callback of walk_stmt_load_store_addr_ops visit_addr used to detect taking + addresses of candidates a places which are not call arguments. Such + candidates are disqalified from SRA. This also applies to GIMPLE_ASM + operands with memory constrains which cannot be scalarized. */ static bool -asm_visit_addr (gimple *, tree op, tree, void *) +scan_visit_addr (gimple *, tree op, tree, void *) { op = get_base_address (op); if (op && DECL_P (op)) - disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand."); + disqualify_candidate (op, "Address taken in a non-call-argument context."); return false; } @@ -1390,12 +1479,20 @@ scan_function (void) FOR_EACH_BB_FN (bb, cfun) { gimple_stmt_iterator gsi; + for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + walk_stmt_load_store_addr_ops (gsi_stmt (gsi), NULL, NULL, NULL, + scan_visit_addr); + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); tree t; unsigned i; + if (gimple_code (stmt) != GIMPLE_CALL) + walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL, + scan_visit_addr); + switch (gimple_code (stmt)) { case GIMPLE_RETURN: @@ -1409,9 +1506,15 @@ scan_function (void) break; case GIMPLE_CALL: - for (i = 0; i < gimple_call_num_args (stmt); i++) - ret |= build_access_from_expr (gimple_call_arg (stmt, i), - stmt, false); + { + enum out_edge_check oe_check = SRA_OUTGOING_EDGES_UNCHECKED; + for (i = 0; i < gimple_call_num_args (stmt); i++) + ret |= build_access_from_call_arg (gimple_call_arg (stmt, i), + stmt, &oe_check); + if (gimple_call_chain(stmt)) + ret |= build_access_from_call_arg (gimple_call_chain(stmt), + stmt, &oe_check); + } t = gimple_call_lhs (stmt); if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL)) @@ -1428,8 +1531,6 @@ scan_function (void) case GIMPLE_ASM: { gasm *asm_stmt = as_a <gasm *> (stmt); - walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL, - asm_visit_addr); for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++) { t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i)); @@ -1920,10 +2021,19 @@ maybe_add_sra_candidate (tree var) reject (var, "not aggregate"); return false; } - /* Allow constant-pool entries that "need to live in memory". */ - if (needs_to_live_in_memory (var) && !constant_decl_p (var)) + + if ((is_global_var (var) + /* There are cases where non-addressable variables fail the + pt_solutions_check test, e.g in gcc.dg/uninit-40.c. */ + || (TREE_ADDRESSABLE (var) + && pt_solution_includes (&cfun->gimple_df->escaped, var)) + || (TREE_CODE (var) == RESULT_DECL + && !DECL_BY_REFERENCE (var) + && aggregate_value_p (var, current_function_decl))) + /* Allow constant-pool entries that "need to live in memory". */ + && !constant_decl_p (var)) { - reject (var, "needs to live in memory"); + reject (var, "needs to live in memory and escapes or global"); return false; } if (TREE_THIS_VOLATILE (var)) @@ -2122,6 +2232,23 @@ sort_and_splice_var_accesses (tree var) gcc_assert (access->offset >= low && access->offset + access->size <= high); + if (INTEGRAL_TYPE_P (access->type) + && TYPE_PRECISION (access->type) != access->size + && bitmap_bit_p (passed_by_ref_in_call, DECL_UID (access->base))) + { + /* This can lead to performance regressions because we can generate + excessive zero extensions. */ + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Won't scalarize "); + print_generic_expr (dump_file, access->base); + fprintf (dump_file, "(%d), it is passed by reference to a call " + "and there are accesses with precision not covering " + "their type size.", DECL_UID (access->base)); + } + return NULL; + } + grp_same_access_path = path_comparable_for_same_access (access->expr); j = i + 1; @@ -3774,12 +3901,18 @@ get_access_for_expr (tree expr) /* Replace the expression EXPR with a scalar replacement if there is one and generate other statements to do type conversion or subtree copying if - necessary. GSI is used to place newly created statements, WRITE is true if - the expression is being written to (it is on a LHS of a statement or output - in an assembly statement). */ + necessary. WRITE is true if the expression is being written to (it is on a + LHS of a statement or output in an assembly statement). STMT_GSI is used to + place newly created statements before the processed statement, REFRESH_GSI + is used to place them afterwards - unless the processed statement must end a + BB in which case it is placed on the outgoing non-EH edge. REFRESH_GSI and + is then used to continue iteration over the BB. If sra_modify_expr is + called only once with WRITE equal to true on a given statement, both + iterator parameters can point to the same one. */ static bool -sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) +sra_modify_expr (tree *expr, bool write, gimple_stmt_iterator *stmt_gsi, + gimple_stmt_iterator *refresh_gsi) { location_t loc; struct access *access; @@ -3806,12 +3939,12 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) type = TREE_TYPE (*expr); orig_expr = *expr; - loc = gimple_location (gsi_stmt (*gsi)); + loc = gimple_location (gsi_stmt (*stmt_gsi)); gimple_stmt_iterator alt_gsi = gsi_none (); - if (write && stmt_ends_bb_p (gsi_stmt (*gsi))) + if (write && stmt_ends_bb_p (gsi_stmt (*stmt_gsi))) { - alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi))); - gsi = &alt_gsi; + alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*stmt_gsi))); + refresh_gsi = &alt_gsi; } if (access->grp_to_be_replaced) @@ -3831,7 +3964,8 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) { tree ref; - ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false); + ref = build_ref_for_model (loc, orig_expr, 0, access, stmt_gsi, + false); if (partial_cplx_access) { @@ -3847,7 +3981,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) tree tmp = make_ssa_name (type); gassign *stmt = gimple_build_assign (tmp, t); /* This is always a read. */ - gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT); t = tmp; } *expr = t; @@ -3857,22 +3991,23 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) gassign *stmt; if (access->grp_partial_lhs) - ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE, - false, GSI_NEW_STMT); + ref = force_gimple_operand_gsi (refresh_gsi, ref, true, + NULL_TREE, false, GSI_NEW_STMT); stmt = gimple_build_assign (repl, ref); gimple_set_location (stmt, loc); - gsi_insert_after (gsi, stmt, GSI_NEW_STMT); + gsi_insert_after (refresh_gsi, stmt, GSI_NEW_STMT); } else { gassign *stmt; if (access->grp_partial_lhs) - repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE, - true, GSI_SAME_STMT); + repl = force_gimple_operand_gsi (stmt_gsi, repl, true, + NULL_TREE, true, + GSI_SAME_STMT); stmt = gimple_build_assign (ref, repl); gimple_set_location (stmt, loc); - gsi_insert_before (gsi, stmt, GSI_SAME_STMT); + gsi_insert_before (stmt_gsi, stmt, GSI_SAME_STMT); } } else @@ -3899,8 +4034,8 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) { gdebug *ds = gimple_build_debug_bind (get_access_replacement (access), NULL_TREE, - gsi_stmt (*gsi)); - gsi_insert_after (gsi, ds, GSI_NEW_STMT); + gsi_stmt (*stmt_gsi)); + gsi_insert_after (stmt_gsi, ds, GSI_NEW_STMT); } if (access->first_child && !TREE_READONLY (access->base)) @@ -3918,8 +4053,57 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write) start_offset = chunk_size = 0; generate_subtree_copies (access->first_child, orig_expr, access->offset, - start_offset, chunk_size, gsi, write, write, - loc); + start_offset, chunk_size, + write ? refresh_gsi : stmt_gsi, + write, write, loc); + } + return true; +} + +/* If EXPR, which must be a call argument, is an ADDR_EXPR, generate writes and + reads from its base before and after the call statement given in CALL_GSI + and return true if any copying took place. Otherwise call sra_modify_expr + on EXPR and return its value. FLAGS is what the gimple_call_arg_flags + return for the given parameter. */ + +static bool +sra_modify_call_arg (tree *expr, gimple_stmt_iterator *call_gsi, + gimple_stmt_iterator *refresh_gsi, int flags) +{ + if (TREE_CODE (*expr) != ADDR_EXPR) + return sra_modify_expr (expr, false, call_gsi, refresh_gsi); + + if (flags & EAF_UNUSED) + return false; + + tree base = get_base_address (TREE_OPERAND (*expr, 0)); + if (!DECL_P (base)) + return false; + struct access *access = get_access_for_expr (base); + if (!access) + return false; + + gimple *stmt = gsi_stmt (*call_gsi); + location_t loc = gimple_location (stmt); + generate_subtree_copies (access, base, 0, 0, 0, call_gsi, false, false, + loc); + + if (flags & EAF_NO_DIRECT_CLOBBER) + return true; + + if (!stmt_ends_bb_p (stmt)) + generate_subtree_copies (access, base, 0, 0, 0, refresh_gsi, true, + true, loc); + else + { + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, gsi_bb (*call_gsi)->succs) + { + gimple_stmt_iterator alt_gsi = gsi_start_edge (e); + generate_subtree_copies (access, base, 0, 0, 0, &alt_gsi, true, + true, loc); + } } return true; } @@ -4279,9 +4463,9 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi) || TREE_CODE (lhs) == BIT_FIELD_REF) { modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt), - gsi, false); + false, gsi, gsi); modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt), - gsi, true); + true, gsi, gsi); return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE; } @@ -4603,7 +4787,7 @@ sra_modify_function_body (void) case GIMPLE_RETURN: t = gimple_return_retval_ptr (as_a <greturn *> (stmt)); if (*t != NULL_TREE) - modified |= sra_modify_expr (t, &gsi, false); + modified |= sra_modify_expr (t, false, &gsi, &gsi); break; case GIMPLE_ASSIGN: @@ -4622,33 +4806,44 @@ sra_modify_function_body (void) } else { + gcall *call = as_a <gcall *> (stmt); + gimple_stmt_iterator call_gsi = gsi; + /* Operands must be processed before the lhs. */ - for (i = 0; i < gimple_call_num_args (stmt); i++) + for (i = 0; i < gimple_call_num_args (call); i++) { - t = gimple_call_arg_ptr (stmt, i); - modified |= sra_modify_expr (t, &gsi, false); + int flags = gimple_call_arg_flags (call, i); + t = gimple_call_arg_ptr (call, i); + modified |= sra_modify_call_arg (t, &call_gsi, &gsi, flags); } - - if (gimple_call_lhs (stmt)) + if (gimple_call_chain (call)) + { + t = gimple_call_chain_ptr (call); + int flags = gimple_call_static_chain_flags (call); + modified |= sra_modify_call_arg (t, &call_gsi, &gsi, + flags); + } + if (gimple_call_lhs (call)) { - t = gimple_call_lhs_ptr (stmt); - modified |= sra_modify_expr (t, &gsi, true); + t = gimple_call_lhs_ptr (call); + modified |= sra_modify_expr (t, true, &call_gsi, &gsi); } } break; case GIMPLE_ASM: { + gimple_stmt_iterator stmt_gsi = gsi; gasm *asm_stmt = as_a <gasm *> (stmt); for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++) { t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i)); - modified |= sra_modify_expr (t, &gsi, false); + modified |= sra_modify_expr (t, false, &stmt_gsi, &gsi); } for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++) { t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i)); - modified |= sra_modify_expr (t, &gsi, true); + modified |= sra_modify_expr (t, true, &stmt_gsi, &gsi); } } break; diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index d39dfc1..0fb21e5 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -47,6 +47,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-cfgcleanup.h" #include "cfganal.h" #include "optabs-tree.h" +#include "insn-config.h" +#include "recog.h" #include "tree-vector-builder.h" #include "vec-perm-indices.h" #include "internal-fn.h" @@ -2978,6 +2980,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) /* Only few targets implement direct conversion patterns so try some simple special cases via VEC_[UN]PACK[_FLOAT]_LO_EXPR. */ optab optab; + insn_code icode; tree halfvectype, dblvectype; enum tree_code unpack_op; @@ -3015,8 +3018,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) && (optab = optab_for_tree_code (unpack_op, dblvectype, optab_default)) - && (optab_handler (optab, TYPE_MODE (dblvectype)) - != CODE_FOR_nothing)) + && ((icode = optab_handler (optab, TYPE_MODE (dblvectype))) + != CODE_FOR_nothing) + && (insn_data[icode].operand[0].mode == TYPE_MODE (type))) { gimple_seq stmts = NULL; tree dbl; @@ -3054,8 +3058,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) && (optab = optab_for_tree_code (VEC_PACK_TRUNC_EXPR, halfvectype, optab_default)) - && (optab_handler (optab, TYPE_MODE (halfvectype)) - != CODE_FOR_nothing)) + && ((icode = optab_handler (optab, TYPE_MODE (halfvectype))) + != CODE_FOR_nothing) + && (insn_data[icode].operand[0].mode == TYPE_MODE (type))) { gimple_seq stmts = NULL; tree low = gimple_build (&stmts, BIT_FIELD_REF, halfvectype, diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 95eda43..bcc02ae 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -5154,6 +5154,81 @@ match_uaddc_usubc (gimple_stmt_iterator *gsi, gimple *stmt, tree_code code) return true; } +/* Replace .POPCOUNT (x) == 1 or .POPCOUNT (x) != 1 with + (x & (x - 1)) > x - 1 or (x & (x - 1)) <= x - 1 if .POPCOUNT + isn't a direct optab. */ + +static void +match_single_bit_test (gimple_stmt_iterator *gsi, gimple *stmt) +{ + tree clhs, crhs; + enum tree_code code; + if (gimple_code (stmt) == GIMPLE_COND) + { + clhs = gimple_cond_lhs (stmt); + crhs = gimple_cond_rhs (stmt); + code = gimple_cond_code (stmt); + } + else + { + clhs = gimple_assign_rhs1 (stmt); + crhs = gimple_assign_rhs2 (stmt); + code = gimple_assign_rhs_code (stmt); + } + if (code != EQ_EXPR && code != NE_EXPR) + return; + if (TREE_CODE (clhs) != SSA_NAME || !integer_onep (crhs)) + return; + gimple *call = SSA_NAME_DEF_STMT (clhs); + combined_fn cfn = gimple_call_combined_fn (call); + switch (cfn) + { + CASE_CFN_POPCOUNT: + break; + default: + return; + } + if (!has_single_use (clhs)) + return; + tree arg = gimple_call_arg (call, 0); + tree type = TREE_TYPE (arg); + if (!INTEGRAL_TYPE_P (type)) + return; + if (direct_internal_fn_supported_p (IFN_POPCOUNT, type, OPTIMIZE_FOR_BOTH)) + { + /* Tell expand_POPCOUNT the popcount result is only used in equality + comparison with one, so that it can decide based on rtx costs. */ + gimple *g = gimple_build_call_internal (IFN_POPCOUNT, 2, arg, + integer_one_node); + gimple_call_set_lhs (g, gimple_call_lhs (call)); + gimple_stmt_iterator gsi2 = gsi_for_stmt (call); + gsi_replace (&gsi2, g, true); + return; + } + tree argm1 = make_ssa_name (type); + gimple *g = gimple_build_assign (argm1, PLUS_EXPR, arg, + build_int_cst (type, -1)); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + g = gimple_build_assign (make_ssa_name (type), BIT_XOR_EXPR, arg, argm1); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + if (gcond *cond = dyn_cast <gcond *> (stmt)) + { + gimple_cond_set_lhs (cond, gimple_assign_lhs (g)); + gimple_cond_set_rhs (cond, argm1); + gimple_cond_set_code (cond, code == EQ_EXPR ? GT_EXPR : LE_EXPR); + } + else + { + gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (g)); + gimple_assign_set_rhs2 (stmt, argm1); + gimple_assign_set_rhs_code (stmt, code == EQ_EXPR ? GT_EXPR : LE_EXPR); + } + update_stmt (stmt); + gimple_stmt_iterator gsi2 = gsi_for_stmt (call); + gsi_remove (&gsi2, true); + release_defs (call); +} + /* Return true if target has support for divmod. */ static bool @@ -5807,6 +5882,11 @@ math_opts_dom_walker::after_dom_children (basic_block bb) match_uaddc_usubc (&gsi, stmt, code); break; + case EQ_EXPR: + case NE_EXPR: + match_single_bit_test (&gsi, stmt); + break; + default:; } } @@ -5872,7 +5952,10 @@ math_opts_dom_walker::after_dom_children (basic_block bb) } } else if (gimple_code (stmt) == GIMPLE_COND) - optimize_spaceship (as_a <gcond *> (stmt)); + { + match_single_bit_test (&gsi, stmt); + optimize_spaceship (as_a <gcond *> (stmt)); + } gsi_next (&gsi); } if (fma_state.m_deferring_p diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc index 26321aa..07fc8e2 100644 --- a/gcc/tree-ssa-reassoc.cc +++ b/gcc/tree-ssa-reassoc.cc @@ -5431,16 +5431,19 @@ get_required_cycles (int ops_num, int cpu_width) } /* Returns an optimal number of registers to use for computation of - given statements. */ + given statements. + + LHS is the result ssa name of OPS. */ static int -get_reassociation_width (int ops_num, enum tree_code opc, - machine_mode mode) +get_reassociation_width (vec<operand_entry *> *ops, tree lhs, + enum tree_code opc, machine_mode mode) { int param_width = param_tree_reassoc_width; int width; int width_min; int cycles_best; + int ops_num = ops->length (); if (param_width > 0) width = param_width; @@ -5471,6 +5474,61 @@ get_reassociation_width (int ops_num, enum tree_code opc, break; } + /* If there's loop dependent FMA result, return width=2 to avoid it. This is + better than skipping these FMA candidates in widening_mul. */ + if (width == 1 + && maybe_le (tree_to_poly_int64 (TYPE_SIZE (TREE_TYPE (lhs))), + param_avoid_fma_max_bits)) + { + /* Look for cross backedge dependency: + 1. LHS is a phi argument in the same basic block it is defined. + 2. And the result of the phi node is used in OPS. */ + basic_block bb = gimple_bb (SSA_NAME_DEF_STMT (lhs)); + + use_operand_p use_p; + imm_use_iterator iter; + FOR_EACH_IMM_USE_FAST (use_p, iter, lhs) + if (gphi *phi = dyn_cast<gphi *> (USE_STMT (use_p))) + { + if (gimple_phi_arg_edge (phi, phi_arg_index_from_use (use_p))->src + != bb) + continue; + tree phi_result = gimple_phi_result (phi); + operand_entry *oe; + unsigned int j; + FOR_EACH_VEC_ELT (*ops, j, oe) + { + if (TREE_CODE (oe->op) != SSA_NAME) + continue; + + /* Result of phi is operand of PLUS_EXPR. */ + if (oe->op == phi_result) + return 2; + + /* Check is result of phi is operand of MULT_EXPR. */ + gimple *def_stmt = SSA_NAME_DEF_STMT (oe->op); + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR) + { + tree rhs = gimple_assign_rhs1 (def_stmt); + if (TREE_CODE (rhs) == SSA_NAME) + { + if (rhs == phi_result) + return 2; + def_stmt = SSA_NAME_DEF_STMT (rhs); + } + } + if (is_gimple_assign (def_stmt) + && gimple_assign_rhs_code (def_stmt) == MULT_EXPR) + { + if (gimple_assign_rhs1 (def_stmt) == phi_result + || gimple_assign_rhs2 (def_stmt) == phi_result) + return 2; + } + } + } + } + return width; } @@ -7031,8 +7089,9 @@ reassociate_bb (basic_block bb) with initial linearization. */ if (!reassoc_insert_powi_p && ops.length () > 3 - && (width = get_reassociation_width (ops_num, rhs_code, - mode)) > 1) + && (width + = get_reassociation_width (&ops, lhs, rhs_code, mode)) + > 1) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, @@ -7049,7 +7108,13 @@ reassociate_bb (basic_block bb) to make sure the ones that get the double binary op are chosen wisely. */ int len = ops.length (); - if (len >= 3 && !has_fma) + if (len >= 3 + && (!has_fma + /* width > 1 means ranking ops results in better + parallelism. */ + || get_reassociation_width (&ops, lhs, rhs_code, + mode) + > 1)) swap_ops_for_binary_stmt (ops, len - 3); new_lhs = rewrite_expr_tree (stmt, rhs_code, 0, ops, diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index b7675d8..3df020d 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -2817,9 +2817,6 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, "can't determine vectorization factor.\n"); return ok; } - if (max_vf != MAX_VECTORIZATION_FACTOR - && maybe_lt (max_vf, LOOP_VINFO_VECT_FACTOR (loop_vinfo))) - return opt_result::failure_at (vect_location, "bad data dependence.\n"); /* Compute the scalar iteration cost. */ vect_compute_single_scalar_iteration_cost (loop_vinfo); @@ -2881,6 +2878,10 @@ start_over: LOOP_VINFO_INT_NITERS (loop_vinfo)); } + if (max_vf != MAX_VECTORIZATION_FACTOR + && maybe_lt (max_vf, LOOP_VINFO_VECT_FACTOR (loop_vinfo))) + return opt_result::failure_at (vect_location, "bad data dependence.\n"); + loop_vinfo->vector_costs = init_cost (loop_vinfo, false); /* Analyze the alignment of the data-refs in the loop. @@ -7070,7 +7071,7 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, op0 = ops[1 - reduc_index]; else { - op0 = ops[2]; + op0 = ops[2 + (1 - reduc_index)]; opmask = ops[0]; gcc_assert (!slp_node); } @@ -7384,7 +7385,6 @@ vectorizable_reduction (loop_vec_info loop_vinfo, stmt_vector_for_cost *cost_vec) { tree vectype_in = NULL_TREE; - tree vectype_op[3] = { NULL_TREE, NULL_TREE, NULL_TREE }; class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); enum vect_def_type cond_reduc_dt = vect_unknown_def_type; stmt_vec_info cond_stmt_vinfo = NULL; @@ -7616,6 +7616,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo, assumption is not true: we use reduc_index to record the index of the reduction variable. */ slp_tree *slp_op = XALLOCAVEC (slp_tree, op.num_ops); + tree *vectype_op = XALLOCAVEC (tree, op.num_ops); /* We need to skip an extra operand for COND_EXPRs with embedded comparison. */ unsigned opno_adjust = 0; @@ -8455,7 +8456,9 @@ vect_transform_reduction (loop_vec_info loop_vinfo, gcc_assert (code == IFN_COND_ADD || code == IFN_COND_SUB || code == IFN_COND_MUL || code == IFN_COND_AND || code == IFN_COND_IOR || code == IFN_COND_XOR); - gcc_assert (op.num_ops == 4 && (op.ops[1] == op.ops[3])); + gcc_assert (op.num_ops == 4 + && (op.ops[reduc_index] + == op.ops[internal_fn_else_index ((internal_fn) code)])); } bool masked_loop_p = LOOP_VINFO_FULLY_MASKED_P (loop_vinfo); @@ -8498,12 +8501,14 @@ vect_transform_reduction (loop_vec_info loop_vinfo, { /* For a conditional operation pass the truth type as mask vectype. */ - gcc_assert (single_defuse_cycle && reduc_index == 1); + gcc_assert (single_defuse_cycle + && (reduc_index == 1 || reduc_index == 2)); vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, ncopies, - op.ops[0], &vec_oprnds0, - truth_type_for (vectype_in), - NULL_TREE, &vec_oprnds1, NULL_TREE, - op.ops[2], &vec_oprnds2, NULL_TREE); + op.ops[0], &vec_oprnds0, truth_type_for (vectype_in), + reduc_index == 1 ? NULL_TREE : op.ops[1], + &vec_oprnds1, NULL_TREE, + reduc_index == 2 ? NULL_TREE : op.ops[2], + &vec_oprnds2, NULL_TREE); } /* For single def-use cycles get one copy of the vectorized reduction @@ -11361,7 +11366,16 @@ vect_transform_loop_stmt (loop_vec_info loop_vinfo, stmt_vec_info stmt_info, if (!STMT_VINFO_RELEVANT_P (stmt_info) && !STMT_VINFO_LIVE_P (stmt_info)) - return false; + { + if (is_gimple_call (stmt_info->stmt) + && gimple_call_internal_p (stmt_info->stmt, IFN_MASK_CALL)) + { + gcc_assert (!gimple_call_lhs (stmt_info->stmt)); + *seen_store = stmt_info; + return false; + } + return false; + } if (STMT_VINFO_VECTYPE (stmt_info)) { diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 7debe7f..696b70b 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -5830,7 +5830,8 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo, tree rhs1_op0 = NULL_TREE, rhs1_op1 = NULL_TREE; tree rhs1_op0_type = NULL_TREE, rhs1_op1_type = NULL_TREE; - /* Check for MASK_LOAD ans MASK_STORE calls requiring mask conversion. */ + /* Check for MASK_LOAD and MASK_STORE as well as COND_OP calls requiring mask + conversion. */ if (is_gimple_call (last_stmt) && gimple_call_internal_p (last_stmt)) { @@ -5842,6 +5843,7 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo, return NULL; bool store_p = internal_store_fn_p (ifn); + bool load_p = internal_store_fn_p (ifn); if (store_p) { int rhs_index = internal_fn_stored_value_index (ifn); @@ -5856,15 +5858,21 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo, vectype1 = get_vectype_for_scalar_type (vinfo, TREE_TYPE (lhs)); } + if (!vectype1) + return NULL; + tree mask_arg = gimple_call_arg (last_stmt, mask_argno); tree mask_arg_type = integer_type_for_mask (mask_arg, vinfo); - if (!mask_arg_type) - return NULL; - vectype2 = get_mask_type_for_scalar_type (vinfo, mask_arg_type); + if (mask_arg_type) + { + vectype2 = get_mask_type_for_scalar_type (vinfo, mask_arg_type); - if (!vectype1 || !vectype2 - || known_eq (TYPE_VECTOR_SUBPARTS (vectype1), - TYPE_VECTOR_SUBPARTS (vectype2))) + if (!vectype2 + || known_eq (TYPE_VECTOR_SUBPARTS (vectype1), + TYPE_VECTOR_SUBPARTS (vectype2))) + return NULL; + } + else if (store_p || load_p) return NULL; tmp = build_mask_conversion (vinfo, mask_arg, vectype1, stmt_vinfo); @@ -5883,7 +5891,9 @@ vect_recog_mask_conversion_pattern (vec_info *vinfo, lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL); gimple_call_set_lhs (pattern_stmt, lhs); } - gimple_call_set_nothrow (pattern_stmt, true); + + if (load_p || store_p) + gimple_call_set_nothrow (pattern_stmt, true); pattern_stmt_info = vinfo->add_stmt (pattern_stmt); if (STMT_VINFO_DATA_REF (stmt_vinfo)) diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 4a09b3c..6799b93 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -763,18 +763,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap, { tree type = TREE_TYPE (oprnd); dt = dts[i]; - if ((dt == vect_constant_def - || dt == vect_external_def) - && !GET_MODE_SIZE (vinfo->vector_mode).is_constant () - && TREE_CODE (type) != BOOLEAN_TYPE - && !can_duplicate_and_interleave_p (vinfo, stmts.length (), type)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "Build SLP failed: invalid type of def " - "for variable-length SLP %T\n", oprnd); - return -1; - } /* For the swapping logic below force vect_reduction_def for the reduction op in a SLP reduction group. */ @@ -2395,7 +2383,7 @@ out: /* Create SLP_TREE nodes for the definition node/s. */ FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info) { - slp_tree child; + slp_tree child = nullptr; unsigned int j; /* We're skipping certain operands from processing, for example @@ -2443,6 +2431,29 @@ out: if (oprnd_info->first_dt == vect_external_def || oprnd_info->first_dt == vect_constant_def) { + if (!GET_MODE_SIZE (vinfo->vector_mode).is_constant ()) + { + tree op0; + tree uniform_val = op0 = oprnd_info->ops[0]; + for (j = 1; j < oprnd_info->ops.length (); ++j) + if (!operand_equal_p (uniform_val, oprnd_info->ops[j])) + { + uniform_val = NULL_TREE; + break; + } + if (!uniform_val + && !can_duplicate_and_interleave_p (vinfo, + oprnd_info->ops.length (), + TREE_TYPE (op0))) + { + matches[j] = false; + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "Build SLP failed: invalid type of def " + "for variable-length SLP %T\n", op0); + goto fail; + } + } slp_tree invnode = vect_create_new_slp_node (oprnd_info->ops); SLP_TREE_DEF_TYPE (invnode) = oprnd_info->first_dt; oprnd_info->ops = vNULL; @@ -8157,6 +8168,7 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node) number_of_places_left_in_vector = nunits; constant_p = true; + tree uniform_elt = NULL_TREE; tree_vector_builder elts (vector_type, nunits, 1); elts.quick_grow (nunits); stmt_vec_info insert_after = NULL; @@ -8166,8 +8178,14 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node) for (i = group_size - 1; op_node->ops.iterate (i, &op); i--) { /* Create 'vect_ = {op0,op1,...,opn}'. */ - number_of_places_left_in_vector--; tree orig_op = op; + if (number_of_places_left_in_vector == nunits) + uniform_elt = op; + else if (uniform_elt && operand_equal_p (uniform_elt, op)) + op = elts[number_of_places_left_in_vector]; + else + uniform_elt = NULL_TREE; + number_of_places_left_in_vector--; if (!types_compatible_p (TREE_TYPE (vector_type), TREE_TYPE (op))) { if (CONSTANT_CLASS_P (op)) @@ -8236,9 +8254,13 @@ vect_create_constant_vectors (vec_info *vinfo, slp_tree op_node) if (number_of_places_left_in_vector == 0) { - if (constant_p - ? multiple_p (TYPE_VECTOR_SUBPARTS (vector_type), nunits) - : known_eq (TYPE_VECTOR_SUBPARTS (vector_type), nunits)) + auto type_nunits = TYPE_VECTOR_SUBPARTS (vector_type); + if (uniform_elt) + vec_cst = gimple_build_vector_from_val (&ctor_seq, vector_type, + elts[0]); + else if (constant_p + ? multiple_p (type_nunits, nunits) + : known_eq (type_nunits, nunits)) vec_cst = gimple_build_vector (&ctor_seq, &elts); else { diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 96e4a6cf..bf8c997 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -9188,7 +9188,8 @@ vectorizable_store (vec_info *vinfo, unsigned HOST_WIDE_INT factor = const_offset_nunits / const_nunits; vec_offset = vec_offsets[(vec_num * j + i) / factor]; - unsigned elt_offset = (j % factor) * const_nunits; + unsigned elt_offset + = ((vec_num * j + i) % factor) * const_nunits; tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset)); tree scale = size_int (gs_info.scale); align = get_object_alignment (DR_REF (first_dr_info->dr)); @@ -11150,7 +11151,8 @@ vectorizable_load (vec_info *vinfo, unsigned HOST_WIDE_INT factor = const_offset_nunits / const_nunits; vec_offset = vec_offsets[(vec_num * j + i) / factor]; - unsigned elt_offset = (j % factor) * const_nunits; + unsigned elt_offset + = ((vec_num * j + i) % factor) * const_nunits; tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset)); tree scale = size_int (gs_info.scale); align = get_object_alignment (DR_REF (first_dr_info->dr)); diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index 917fa87..82001ef 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -52,6 +52,12 @@ along with GCC; see the file COPYING3. If not see #include "gimple-fold.h" #include "tree-dfa.h" #include "tree-ssa-dce.h" +#include "alloc-pool.h" +#include "cgraph.h" +#include "symbol-summary.h" +#include "ipa-utils.h" +#include "ipa-prop.h" +#include "attribs.h" // This class is utilized by VRP and ranger to remove __builtin_unreachable // calls, and reflect any resulting global ranges. @@ -1081,6 +1087,51 @@ execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p, array_checker.check (); } + + if (Value_Range::supports_type_p (TREE_TYPE + (TREE_TYPE (current_function_decl))) + && flag_ipa_vrp + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))) + { + edge e; + edge_iterator ei; + bool found = false; + Value_Range return_range (TREE_TYPE (TREE_TYPE (current_function_decl))); + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) + if (greturn *ret = dyn_cast <greturn *> (*gsi_last_bb (e->src))) + { + tree retval = gimple_return_retval (ret); + if (!retval) + { + return_range.set_varying (TREE_TYPE (TREE_TYPE (current_function_decl))); + found = true; + continue; + } + Value_Range r (TREE_TYPE (retval)); + if (ranger->range_of_expr (r, retval, ret) + && !r.undefined_p () + && !r.varying_p ()) + { + if (!found) + return_range = r; + else + return_range.union_ (r); + } + else + return_range.set_varying (TREE_TYPE (retval)); + found = true; + } + if (found && !return_range.varying_p ()) + { + ipa_record_return_value_range (return_range); + if (POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))) + && return_range.nonzero_p () + && cgraph_node::get (current_function_decl) + ->add_detected_attribute ("returns_nonnull")) + warn_function_returns_nonnull (current_function_decl); + } + } + phi_analysis_finalize (); disable_ranger (fun); scev_finalize (); diff --git a/gcc/tree.cc b/gcc/tree.cc index a3d907a..e9f703e 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -12573,6 +12573,24 @@ try_catch_may_fallthru (const_tree stmt) if (block_may_fallthru (TREE_OPERAND (stmt, 0))) return true; + switch (TREE_CODE (TREE_OPERAND (stmt, 1))) + { + case CATCH_EXPR: + /* See below. */ + return block_may_fallthru (CATCH_BODY (TREE_OPERAND (stmt, 1))); + + case EH_FILTER_EXPR: + /* See below. */ + return block_may_fallthru (EH_FILTER_FAILURE (TREE_OPERAND (stmt, 1))); + + case STATEMENT_LIST: + break; + + default: + /* See below. */ + return false; + } + i = tsi_start (TREE_OPERAND (stmt, 1)); switch (TREE_CODE (tsi_stmt (i))) { diff --git a/gcc/typeclass.h b/gcc/typeclass.h index 4b162e1..2723c65 100644 --- a/gcc/typeclass.h +++ b/gcc/typeclass.h @@ -38,7 +38,7 @@ enum type_class record_type_class, union_type_class, array_type_class, string_type_class, lang_type_class, opaque_type_class, - bitint_type_class + bitint_type_class, vector_type_class }; #endif /* GCC_TYPECLASS_H */ diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 5247b80..d0ba0f6 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,29 @@ +2023-11-24 Alexander Monakov <amonakov@ispras.ru> + + * config.in: Regenerate. + * configure: Regenerate. + * configure.ac (ENABLE_VALGRIND_CHECKING): Delete. + (ENABLE_VALGRIND_ANNOTATIONS): Rename to + ENABLE_VALGRIND_WORKAROUNDS. Delete Valgrind header checks. + * lex.cc (new_buff): Adjust for renaming. + (_cpp_free_buff): Ditto. + +2023-11-20 Marc Poulhiès <dkm@kataplop.net> + + * macro.cc (parse_params): Fix typo in variadic. + (create_iso_definition): Likewise. + +2023-11-19 David Malcolm <dmalcolm@redhat.com> + + * Makefile.in (TAGS_SOURCES): Add "include/rich-location.h". + * include/cpplib.h (class rich_location): New forward decl. + * include/line-map.h (class range_label) + (enum range_display_kind, struct location_range) + (class semi_embedded_vec, class rich_location, class label_text) + (class range_label, class fixit_hint): Move to... + * include/rich-location.h: ...this new file. + * internal.h: Include "rich-location.h". + 2023-11-14 Jakub Jelinek <jakub@redhat.com> * makeucnid.cc (write_copyright): Update copyright year. diff --git a/libcpp/config.in b/libcpp/config.in index df4fd44..253ef03 100644 --- a/libcpp/config.in +++ b/libcpp/config.in @@ -24,12 +24,9 @@ language is requested. */ #undef ENABLE_NLS -/* Define to get calls to the valgrind runtime enabled. */ -#undef ENABLE_VALGRIND_ANNOTATIONS - -/* Define if you want to workaround valgrind (a memory checker) warnings about - possible memory leaks because of libcpp use of interior pointers. */ -#undef ENABLE_VALGRIND_CHECKING +/* Define if you want to workaround Valgrind warnings about possible memory + leaks because of libcpp use of interior pointers. */ +#undef ENABLE_VALGRIND_WORKAROUNDS /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA @@ -201,9 +198,6 @@ /* Define to 1 if you have the <locale.h> header file. */ #undef HAVE_LOCALE_H -/* Define if valgrind's memcheck.h header is installed. */ -#undef HAVE_MEMCHECK_H - /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H @@ -252,9 +246,6 @@ /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H -/* Define if valgrind's valgrind/memcheck.h header is installed. */ -#undef HAVE_VALGRIND_MEMCHECK_H - /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST diff --git a/libcpp/configure b/libcpp/configure index 452e4c1..8a38c05 100755 --- a/libcpp/configure +++ b/libcpp/configure @@ -9116,12 +9116,6 @@ $as_echo "#define ENABLE_ASSERT_CHECKING 1" >>confdefs.h fi -if test x$ac_valgrind_checking != x ; then - -$as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h - -fi - # Check whether --enable-canonical-system-headers was given. if test "${enable_canonical_system_headers+set}" = set; then : enableval=$enable_canonical_system_headers; @@ -9405,62 +9399,6 @@ case x$enable_languages in esac -ac_fn_c_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default" -if test "x$ac_cv_header_valgrind_h" = xyes; then : - have_valgrind_h=yes -else - have_valgrind_h=no -fi - - - -# It is certainly possible that there's valgrind but no valgrind.h. -# GCC relies on making annotations so we must have both. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5 -$as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <valgrind/memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - gcc_cv_header_valgrind_memcheck_h=yes -else - gcc_cv_header_valgrind_memcheck_h=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5 -$as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5 -$as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - gcc_cv_header_memcheck_h=yes -else - gcc_cv_header_memcheck_h=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5 -$as_echo "$gcc_cv_header_memcheck_h" >&6; } -if test $gcc_cv_header_valgrind_memcheck_h = yes; then - -$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h - -fi -if test $gcc_cv_header_memcheck_h = yes; then - -$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h - -fi - # Check whether --enable-valgrind-annotations was given. if test "${enable_valgrind_annotations+set}" = set; then : enableval=$enable_valgrind_annotations; @@ -9470,14 +9408,8 @@ fi if test x$enable_valgrind_annotations != xno \ || test x$ac_valgrind_checking != x; then - if (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - as_fn_error $? "*** valgrind annotations requested, but" "$LINENO" 5 - as_fn_error $? "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5 - fi -$as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h +$as_echo "#define ENABLE_VALGRIND_WORKAROUNDS 1" >>confdefs.h fi diff --git a/libcpp/configure.ac b/libcpp/configure.ac index b29b4d6..b883fec 100644 --- a/libcpp/configure.ac +++ b/libcpp/configure.ac @@ -185,12 +185,6 @@ if test x$ac_assert_checking != x ; then [Define if you want assertions enabled. This is a cheap check.]) fi -if test x$ac_valgrind_checking != x ; then - AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1, -[Define if you want to workaround valgrind (a memory checker) warnings about - possible memory leaks because of libcpp use of interior pointers.]) -fi - AC_ARG_ENABLE(canonical-system-headers, [ --enable-canonical-system-headers enable or disable system headers canonicalization], @@ -241,54 +235,15 @@ case x$enable_languages in esac AC_SUBST(CET_HOST_FLAGS) -dnl # This check AC_REQUIREs various stuff, so it *must not* be inside -dnl # an if statement. This was the source of very frustrating bugs -dnl # in converting to autoconf 2.5x! -AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no) - -# It is certainly possible that there's valgrind but no valgrind.h. -# GCC relies on making annotations so we must have both. -AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>) -AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <valgrind/memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif]])], - [gcc_cv_header_valgrind_memcheck_h=yes], - [gcc_cv_header_valgrind_memcheck_h=no]) -AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h) -AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>) -AC_PREPROC_IFELSE([AC_LANG_SOURCE( - [[#include <memcheck.h> -#ifndef VALGRIND_DISCARD -#error VALGRIND_DISCARD not defined -#endif]])], - [gcc_cv_header_memcheck_h=yes], - [gcc_cv_header_memcheck_h=no]) -AC_MSG_RESULT($gcc_cv_header_memcheck_h) -if test $gcc_cv_header_valgrind_memcheck_h = yes; then - AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1, - [Define if valgrind's valgrind/memcheck.h header is installed.]) -fi -if test $gcc_cv_header_memcheck_h = yes; then - AC_DEFINE(HAVE_MEMCHECK_H, 1, - [Define if valgrind's memcheck.h header is installed.]) -fi - AC_ARG_ENABLE(valgrind-annotations, [AS_HELP_STRING([--enable-valgrind-annotations], [enable valgrind runtime interaction])], [], [enable_valgrind_annotations=no]) if test x$enable_valgrind_annotations != xno \ || test x$ac_valgrind_checking != x; then - if (test $have_valgrind_h = no \ - && test $gcc_cv_header_memcheck_h = no \ - && test $gcc_cv_header_valgrind_memcheck_h = no); then - AC_MSG_ERROR([*** valgrind annotations requested, but]) - AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h]) - fi - AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1, -[Define to get calls to the valgrind runtime enabled.]) + AC_DEFINE(ENABLE_VALGRIND_WORKAROUNDS, 1, +[Define if you want to workaround Valgrind warnings about + possible memory leaks because of libcpp use of interior pointers.]) fi # Output. diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index bc7eed7..f52bc44 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -764,6 +764,9 @@ struct cpp_callbacks /* Callback to determine whether a built-in function is recognized. */ int (*has_builtin) (cpp_reader *); + /* Callback to determine whether a feature is available. */ + int (*has_feature) (cpp_reader *, bool); + /* Callback that can change a user lazy into normal macro. */ void (*user_lazy_macro) (cpp_reader *, cpp_macro *, unsigned); @@ -968,7 +971,9 @@ enum cpp_builtin_type BT_HAS_STD_ATTRIBUTE, /* `__has_c_attribute(x)' */ BT_HAS_BUILTIN, /* `__has_builtin(x)' */ BT_HAS_INCLUDE, /* `__has_include(x)' */ - BT_HAS_INCLUDE_NEXT /* `__has_include_next(x)' */ + BT_HAS_INCLUDE_NEXT, /* `__has_include_next(x)' */ + BT_HAS_FEATURE, /* `__has_feature(x)' */ + BT_HAS_EXTENSION /* `__has_extension(x)' */ }; #define CPP_HASHNODE(HNODE) ((cpp_hashnode *) (HNODE)) diff --git a/libcpp/init.cc b/libcpp/init.cc index 250a02a..5dfce4b 100644 --- a/libcpp/init.cc +++ b/libcpp/init.cc @@ -435,6 +435,8 @@ static const struct builtin_macro builtin_array[] = B("__has_builtin", BT_HAS_BUILTIN, true), B("__has_include", BT_HAS_INCLUDE, true), B("__has_include_next",BT_HAS_INCLUDE_NEXT, true), + B("__has_feature", BT_HAS_FEATURE, true), + B("__has_extension", BT_HAS_EXTENSION, true), /* Keep builtins not used for -traditional-cpp at the end, and update init_builtins() if any more are added. */ B("_Pragma", BT_PRAGMA, true), diff --git a/libcpp/lex.cc b/libcpp/lex.cc index 0b1b936..a5d2f31 100644 --- a/libcpp/lex.cc +++ b/libcpp/lex.cc @@ -4762,7 +4762,7 @@ new_buff (size_t len) len = MIN_BUFF_SIZE; len = CPP_ALIGN (len); -#ifdef ENABLE_VALGRIND_ANNOTATIONS +#ifdef ENABLE_VALGRIND_WORKAROUNDS /* Valgrind warns about uses of interior pointers, so put _cpp_buff struct first. */ size_t slen = CPP_ALIGN2 (sizeof (_cpp_buff), 2 * DEFAULT_ALIGNMENT); @@ -4859,7 +4859,7 @@ _cpp_free_buff (_cpp_buff *buff) for (; buff; buff = next) { next = buff->next; -#ifdef ENABLE_VALGRIND_ANNOTATIONS +#ifdef ENABLE_VALGRIND_WORKAROUNDS free (buff); #else free (buff->base); diff --git a/libcpp/macro.cc b/libcpp/macro.cc index a1a134a..6f24a9d 100644 --- a/libcpp/macro.cc +++ b/libcpp/macro.cc @@ -677,6 +677,12 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node, number = builtin_has_include (pfile, node, node->value.builtin == BT_HAS_INCLUDE_NEXT); break; + + case BT_HAS_FEATURE: + case BT_HAS_EXTENSION: + number = pfile->cb.has_feature (pfile, + node->value.builtin == BT_HAS_FEATURE); + break; } if (result == NULL) @@ -3431,7 +3437,7 @@ _cpp_unsave_parameters (cpp_reader *pfile, unsigned n) */ static bool -parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) +parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *variadic_ptr) { unsigned nparms = 0; bool ok = false; @@ -3462,7 +3468,7 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) }; unsigned ix = prev_ident; const unsigned char *as_text = NULL; - if (*varadic_ptr) + if (*variadic_ptr) ix = 4; else if (token->type == CPP_EOF) ix += 2; @@ -3473,7 +3479,7 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) goto out; case CPP_NAME: - if (prev_ident || *varadic_ptr) + if (prev_ident || *variadic_ptr) goto bad; prev_ident = true; @@ -3484,7 +3490,7 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) break; case CPP_CLOSE_PAREN: - if (prev_ident || !nparms || *varadic_ptr) + if (prev_ident || !nparms || *variadic_ptr) { ok = true; goto out; @@ -3492,15 +3498,15 @@ parse_params (cpp_reader *pfile, unsigned *n_ptr, bool *varadic_ptr) /* FALLTHRU */ case CPP_COMMA: - if (!prev_ident || *varadic_ptr) + if (!prev_ident || *variadic_ptr) goto bad; prev_ident = false; break; case CPP_ELLIPSIS: - if (*varadic_ptr) + if (*variadic_ptr) goto bad; - *varadic_ptr = true; + *variadic_ptr = true; if (!prev_ident) { /* An ISO bare ellipsis. */ @@ -3577,7 +3583,7 @@ create_iso_definition (cpp_reader *pfile) unsigned int num_extra_tokens = 0; unsigned nparms = 0; cpp_hashnode **params = NULL; - bool varadic = false; + bool variadic = false; bool ok = false; cpp_macro *macro = NULL; @@ -3594,7 +3600,7 @@ create_iso_definition (cpp_reader *pfile) else if (token->type == CPP_OPEN_PAREN) { /* An open-paren, get a parameter list. */ - if (!parse_params (pfile, &nparms, &varadic)) + if (!parse_params (pfile, &nparms, &variadic)) goto out; params = (cpp_hashnode **)_cpp_commit_buff @@ -3645,7 +3651,7 @@ create_iso_definition (cpp_reader *pfile) if (!token) { - macro->variadic = varadic; + macro->variadic = variadic; macro->paramc = nparms; macro->parm.params = params; macro->fun_like = true; diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index fdeb85f..d47e28e 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,23 @@ +2023-11-24 Richard Earnshaw <rearnsha@arm.com> + + * config.host (arm*-*-eabi* | arm*-*-rtems*): + Add arm/t-sync to the makefile rules. + * config/arm/lib1funcs.S (__sync_synchronize_none) + (__sync_synchronize_cp15dmb, __sync_synchronize_dmb) + (__sync_synchronize): New functions. + * config/arm/t-sync: New file. + * config/arm/sync-none.specs: Likewise. + * config/arm/sync-dmb.specs: Likewise. + * config/arm/sync-cp15dmb.specs: Likewise. + +2023-11-23 Jose E. Marchesi <jose.marchesi@oracle.com> + + * hardcfr.c (__hardcfr_check_fail): Mark as always_inline. + +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + * libgcov.h (GCOV_SUPPORTS_ATOMIC): Formatting fixes. + 2023-11-18 Sebastian Huber <sebastian.huber@embedded-brains.de> * libgcov.h (GCOV_SUPPORTS_ATOMIC): Always define it. diff --git a/libgcc/config.host b/libgcc/config.host index 6afe8e5..694e3e9 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -554,7 +554,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems*) tm_file="$tm_file arm/bpabi-lib.h" case ${host} in arm*-*-eabi* | arm*-*-rtems*) - tmake_file="${tmake_file} arm/t-bpabi t-crtfm" + tmake_file="${tmake_file} arm/t-bpabi arm/t-sync t-crtfm" extra_parts="crtbegin.o crtend.o crti.o crtn.o" ;; arm*-*-symbianelf*) diff --git a/libgcc/config/arm/lib1funcs.S b/libgcc/config/arm/lib1funcs.S index d02a57c..7888786 100644 --- a/libgcc/config/arm/lib1funcs.S +++ b/libgcc/config/arm/lib1funcs.S @@ -2147,6 +2147,78 @@ LSYM(Lchange_\register): SIZE (__gnu_thumb1_case_uhi) #endif +#ifdef L_sync_none + /* Null implementation of __sync_synchronize, for use when + it is known that the system is single threaded. */ + .text + .align 0 + FUNC_START sync_synchronize_none + bx lr + FUNC_END sync_synchronize_none +#endif + +#ifdef L_sync_dmb + /* Full memory barrier using DMB. Requires Armv7 (all profiles) + or armv6-m, or later. */ + .text + .align 0 +#if __ARM_ARCH_PROFILE == 'M' + .arch armv6-m +#else + .arch armv7-a +#endif + FUNC_START sync_synchronize_dmb + /* M-profile devices only support SY as the synchronization level, + but that's probably what we want here anyway. */ + dmb + RET + FUNC_END sync_synchronize_dmb +#endif + +#ifdef L_sync_cp15dmb +#ifndef NOT_ISA_TARGET_32BIT + /* Implementation of DMB using CP15 operations. This was first + defined in Armv6, but deprecated in Armv7 and can give + sub-optimal performance. */ + .text + .align 0 + ARM_FUNC_START sync_synchronize_cp15dmb + mcr p15, 0, r0, c7, c10, 5 + RET + FUNC_END sync_synchronize_cp15dmb +#endif +#endif + +#ifdef L_sync_synchronize + /* Generic version of the synchronization primitive. If we know + that DMB exists, then use it. Otherwise, arrange for a link + time warning explaining how to pick a suitable alternative. + We choose not to use CP15DMB because it is performance + deprecated. We only define this function if generating + ELF binaries as otherwise we can't rely on the warning being + generated. */ + +#ifdef __ELF__ + .text + .align 0 + FUNC_START sync_synchronize +#if __ARM_ARCH >= 7 || __ARM_ARCH_PROFILE == 'M' + dmb +#endif + RET + FUNC_END sync_synchronize +#if !(__ARM_ARCH >= 7 || __ARM_ARCH_PROFILE == 'M') + .section .gnu.warning.__sync_synchronize + .align 0 + .ascii "This implementation of __sync_synchronize is a stub with " + .ascii "no effect. Relink with\n" + .ascii " -specs=sync-{none,dmb,cp15dmb}.specs\n" + .ascii "to specify exactly which barrier format to use and avoid " + .ascii "this warning.\n\0" +#endif +#endif +#endif + #ifdef L_thumb1_case_si .text diff --git a/libgcc/config/arm/sync-cp15dmb.specs b/libgcc/config/arm/sync-cp15dmb.specs new file mode 100644 index 0000000..0bb64b9 --- /dev/null +++ b/libgcc/config/arm/sync-cp15dmb.specs @@ -0,0 +1,4 @@ +%rename link sync_sync_link + +*link: +--defsym=__sync_synchronize=__sync_synchronize_cp15dmb %(sync_sync_link) diff --git a/libgcc/config/arm/sync-dmb.specs b/libgcc/config/arm/sync-dmb.specs new file mode 100644 index 0000000..13e59bd --- /dev/null +++ b/libgcc/config/arm/sync-dmb.specs @@ -0,0 +1,4 @@ +%rename link sync_sync_link + +*link: +--defsym=__sync_synchronize=__sync_synchronize_dmb %(sync_sync_link) diff --git a/libgcc/config/arm/sync-none.specs b/libgcc/config/arm/sync-none.specs new file mode 100644 index 0000000..0aa4960 --- /dev/null +++ b/libgcc/config/arm/sync-none.specs @@ -0,0 +1,4 @@ +%rename link sync_sync_link + +*link: +--defsym=__sync_synchronize=__sync_synchronize_none %(sync_sync_link) diff --git a/libgcc/config/arm/t-sync b/libgcc/config/arm/t-sync new file mode 100644 index 0000000..5fd050e --- /dev/null +++ b/libgcc/config/arm/t-sync @@ -0,0 +1,13 @@ +LIB1ASMFUNCS += _sync_none _sync_dmb _sync_cp15dmb _sync_synchronize + +EXTRA_PARTS += sync-none.specs sync-dmb.specs sync-cp15dmb.specs + +sync-none.specs: $(srcdir)/config/arm/sync-none.specs + cp $< . + +sync-dmb.specs: $(srcdir)/config/arm/sync-dmb.specs + cp $< . + +sync-cp15dmb.specs: $(srcdir)/config/arm/sync-cp15dmb.specs + cp $< . + diff --git a/libgcc/hardcfr.c b/libgcc/hardcfr.c index 25ff067..376a362 100644 --- a/libgcc/hardcfr.c +++ b/libgcc/hardcfr.c @@ -206,6 +206,10 @@ __hardcfr_debug_cfg (size_t const blocks, enabled, it also forces __hardcfr_debug_cfg (above) to be compiled into an out-of-line function, that could be called from a debugger. */ + +#ifdef __BPF__ +__attribute__((__always_inline__)) +#endif static inline void __hardcfr_check_fail (size_t const blocks ATTRIBUTE_UNUSED, vword const *const visited ATTRIBUTE_UNUSED, diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h index d04c070..f5959a8 100644 --- a/libgcc/libgcov.h +++ b/libgcc/libgcov.h @@ -96,9 +96,9 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI))); #endif /* Detect whether target can support atomic update of profilers. */ -#if (__SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || \ - (__SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) || \ - defined (__LIBGCC_HAVE_LIBATOMIC) +#if (__SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) \ + || (__SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) \ + || defined (__LIBGCC_HAVE_LIBATOMIC) #define GCOV_SUPPORTS_ATOMIC 1 #else #define GCOV_SUPPORTS_ATOMIC 0 diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 8d2b812..d5a6ade 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,15 @@ +2023-11-24 Tobias Burnus <tobias@codesourcery.com> + + * libgomp.texi (5.2 Impl. Status): An argument to the destroy clause + is now supported. + +2023-11-22 Thomas Schwinge <thomas@codesourcery.com> + + * testsuite/libgomp.c/declare-variant-3.h (f30, f35, f53, f70) + (f75, f80, f): Add '__attribute__ ((noipa))'. + * testsuite/libgomp.c/declare-variant-4.h (gfx803, gfx900, gfx906) + (gfx908, gfx90a, f): Likewise. + 2023-11-15 Andrew Stubbs <ams@codesourcery.com> Andrew Jenner <andrew@codesourcery.com> diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 2f6227c..e5fe7af 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -387,7 +387,7 @@ to address of matching mapped list item per 5.1, Sect. 2.21.7.2 @tab N @tab @code{-Wall}). Unknown clauses are always rejected with an error.} @item Clauses on @code{end} directive can be on directive @tab Y @tab @item @code{destroy} clause with destroy-var argument on @code{depobj} - @tab N @tab + @tab Y @tab @item Deprecation of no-argument @code{destroy} clause on @code{depobj} @tab N @tab @item @code{linear} clause syntax changes and @code{step} modifier @tab Y @tab diff --git a/libgomp/testsuite/libgomp.c/declare-variant-3.h b/libgomp/testsuite/libgomp.c/declare-variant-3.h index 772fc20..646e15e 100644 --- a/libgomp/testsuite/libgomp.c/declare-variant-3.h +++ b/libgomp/testsuite/libgomp.c/declare-variant-3.h @@ -1,34 +1,41 @@ #pragma omp declare target + +__attribute__ ((noipa)) int f30 (void) { return 30; } +__attribute__ ((noipa)) int f35 (void) { return 35; } +__attribute__ ((noipa)) int f53 (void) { return 53; } +__attribute__ ((noipa)) int f70 (void) { return 70; } +__attribute__ ((noipa)) int f75 (void) { return 75; } +__attribute__ ((noipa)) int f80 (void) { @@ -41,6 +48,7 @@ f80 (void) #pragma omp declare variant (f70) match (device={isa("sm_70")}) #pragma omp declare variant (f75) match (device={isa("sm_75")}) #pragma omp declare variant (f80) match (device={isa("sm_80")}) +__attribute__ ((noipa)) int f (void) { diff --git a/libgomp/testsuite/libgomp.c/declare-variant-4.h b/libgomp/testsuite/libgomp.c/declare-variant-4.h index 2d7c1ef..47517b7 100644 --- a/libgomp/testsuite/libgomp.c/declare-variant-4.h +++ b/libgomp/testsuite/libgomp.c/declare-variant-4.h @@ -1,28 +1,34 @@ #pragma omp declare target + +__attribute__ ((noipa)) int gfx803 (void) { return 0x803; } +__attribute__ ((noipa)) int gfx900 (void) { return 0x900; } +__attribute__ ((noipa)) int gfx906 (void) { return 0x906; } +__attribute__ ((noipa)) int gfx908 (void) { return 0x908; } +__attribute__ ((noipa)) int gfx90a (void) { @@ -38,6 +44,7 @@ gfx90a (void) #pragma omp declare variant(gfx906) match(device = {isa("gfx906")}) #pragma omp declare variant(gfx908) match(device = {isa("gfx908")}) #pragma omp declare variant(gfx90a) match(device = {isa("gfx90a")}) +__attribute__ ((noipa)) int f (void) { diff --git a/libphobos/ChangeLog b/libphobos/ChangeLog index b28b9f4..6f437e4 100644 --- a/libphobos/ChangeLog +++ b/libphobos/ChangeLog @@ -1,3 +1,12 @@ +2023-11-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * libdruntime/MERGE: Merge upstream druntime ff57fec515. + * src/MERGE: Merge upstream phobos 17bafda79. + +2023-11-21 Iain Buclaw <ibuclaw@gdcproject.org> + + * src/MERGE: Merge upstream phobos fc06c514a. + 2023-11-02 Iain Buclaw <ibuclaw@gdcproject.org> * libdruntime/MERGE: Merge upstream druntime 643b1261bb. diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 235db4b..aa0062c 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -643b1261bba0757d97efa3ff1f63e461271eb000 +ff57fec51558013b25cadb7e83da9f4675915d56 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/libphobos/libdruntime/core/cpuid.d b/libphobos/libdruntime/core/cpuid.d index b79bd1d..9c57357 100644 --- a/libphobos/libdruntime/core/cpuid.d +++ b/libphobos/libdruntime/core/cpuid.d @@ -666,10 +666,12 @@ void getAMDcacheinfo() // to determine number of processors. void getCpuInfo0B() { - int level=0; int threadsPerCore; uint a, b, c, d; - do { + // I'm not sure about this. The docs state that there + // are 2 hyperthreads per core if HT is factory enabled. + for (int level = 0; level < 2; level++) + { version (GNU_OR_LDC) asm pure nothrow @nogc { "cpuid" : "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (0x0B), "c" (level); } else asm pure nothrow @nogc { @@ -681,19 +683,20 @@ void getCpuInfo0B() mov c, ECX; mov d, EDX; } - if (b!=0) { - // I'm not sure about this. The docs state that there - // are 2 hyperthreads per core if HT is factory enabled. - if (level==0) + if (b != 0) + { + if (level == 0) threadsPerCore = b & 0xFFFF; - else if (level==1) { + else if (level == 1) + { cpuFeatures.maxThreads = b & 0xFFFF; cpuFeatures.maxCores = cpuFeatures.maxThreads / threadsPerCore; } - } - ++level; - } while (a!=0 || b!=0); + // Got "invalid domain" returned from cpuid + if (a == 0 && b == 0) + break; + } } void cpuidX86() diff --git a/libphobos/libdruntime/core/internal/array/appending.d b/libphobos/libdruntime/core/internal/array/appending.d index bb24813..ba34727 100644 --- a/libphobos/libdruntime/core/internal/array/appending.d +++ b/libphobos/libdruntime/core/internal/array/appending.d @@ -14,56 +14,55 @@ private extern (C) byte[] _d_arrayappendcTX(const TypeInfo ti, ref return scope private enum isCopyingNothrow(T) = __traits(compiles, (ref T rhs) nothrow { T lhs = rhs; }); -/// Implementation of `_d_arrayappendcTX` and `_d_arrayappendcTXTrace` -template _d_arrayappendcTXImpl(Tarr : T[], T) +/** + * Extend an array `px` by `n` elements. + * Caller must initialize those elements. + * Params: + * px = the array that will be extended, taken as a reference + * n = how many new elements to extend it with + * Returns: + * The new value of `px` + * Bugs: + * This function template was ported from a much older runtime hook that bypassed safety, + * purity, and throwabilty checks. To prevent breaking existing code, this function template + * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + */ +ref Tarr _d_arrayappendcTX(Tarr : T[], T)(return ref scope Tarr px, size_t n) @trusted { - private enum errorMessage = "Cannot append to array if compiling without support for runtime type information!"; + // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718 + version (DigitalMars) pragma(inline, false); + version (D_TypeInfo) + { + auto ti = typeid(Tarr); + + // _d_arrayappendcTX takes the `px` as a ref byte[], but its length + // should still be the original length + auto pxx = (cast(byte*)px.ptr)[0 .. px.length]; + ._d_arrayappendcTX(ti, pxx, n); + px = (cast(T*)pxx.ptr)[0 .. pxx.length]; + + return px; + } + else + assert(0, "Cannot append to array if compiling without support for runtime type information!"); +} +version (D_ProfileGC) +{ /** - * Extend an array `px` by `n` elements. - * Caller must initialize those elements. - * Params: - * px = the array that will be extended, taken as a reference - * n = how many new elements to extend it with - * Returns: - * The new value of `px` - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. + * TraceGC wrapper around $(REF _d_arrayappendT, core,internal,array,appending). */ - ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow + ref Tarr _d_arrayappendcTXTrace(Tarr : T[], T)(string file, int line, string funcname, return ref scope Tarr px, size_t n) @trusted { - // needed for CTFE: https://github.com/dlang/druntime/pull/3870#issuecomment-1178800718 - version (DigitalMars) pragma(inline, false); version (D_TypeInfo) { - auto ti = typeid(Tarr); - - // _d_arrayappendcTX takes the `px` as a ref byte[], but its length - // should still be the original length - auto pxx = (cast(byte*)px.ptr)[0 .. px.length]; - ._d_arrayappendcTX(ti, pxx, n); - px = (cast(T*)pxx.ptr)[0 .. pxx.length]; + import core.internal.array.utils: TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(Tarr.stringof, "_d_arrayappendcTX")); - return px; + return _d_arrayappendcTX(px, n); } else - assert(0, errorMessage); - } - - version (D_ProfileGC) - { - import core.internal.array.utils : _d_HookTraceImpl; - - /** - * TraceGC wrapper around $(REF _d_arrayappendcTX, rt,array,appending,_d_arrayappendcTXImpl). - * Bugs: - * This function template was ported from a much older runtime hook that bypassed safety, - * purity, and throwabilty checks. To prevent breaking existing code, this function template - * is temporarily declared `@trusted pure` until the implementation can be brought up to modern D expectations. - */ - alias _d_arrayappendcTXTrace = _d_HookTraceImpl!(Tarr, _d_arrayappendcTX, errorMessage); + static assert(0, "Cannot append to array if compiling without support for runtime type information!"); } } @@ -78,7 +77,7 @@ ref Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y) @ enum hasPostblit = __traits(hasPostblit, T); auto length = x.length; - _d_arrayappendcTXImpl!Tarr._d_arrayappendcTX(x, y.length); + _d_arrayappendcTX(x, y.length); // Only call `copyEmplace` if `T` has a copy ctor and no postblit. static if (hasElaborateCopyConstructor!T && !hasPostblit) @@ -126,7 +125,7 @@ version (D_ProfileGC) return _d_arrayappendT(x, y); } else - assert(0, "Cannot append to array if compiling without support for runtime type information!"); + static assert(0, "Cannot append to array if compiling without support for runtime type information!"); } } diff --git a/libphobos/libdruntime/core/internal/array/construction.d b/libphobos/libdruntime/core/internal/array/construction.d index 54f8767..655acc8 100644 --- a/libphobos/libdruntime/core/internal/array/construction.d +++ b/libphobos/libdruntime/core/internal/array/construction.d @@ -486,3 +486,111 @@ version (D_ProfileGC) assert(0, "Cannot create new array if compiling without support for runtime type information!"); } } + +/** + * Create a new multi-dimensional array. Also initalize elements if their type has an initializer. + * Otherwise, not zero-initialize the array. + * + * --- + * void main() + * { + * S[][] s = new S[][](2, 3) + * + * // lowering: + * S[] s = _d_newarraymTX!(S[][], S)([2, 3]); + * } + * --- + * + * Params: + * dims = array length values for each dimension + * isShared = whether the array should be shared + * + * Returns: + * newly allocated array + */ +Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted +{ + debug(PRINTF) printf("_d_newarraymTX(dims.length = %d)\n", dims.length); + + if (dims.length == 0) + return null; + + alias UnqT = Unqual!(T); + + void[] __allocateInnerArray(size_t[] dims) + { + import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc; + + auto dim = dims[0]; + + debug(PRINTF) printf("__allocateInnerArray(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length); + if (dims.length == 1) + { + auto r = _d_newarrayT!UnqT(dim, isShared); + return *cast(void[]*)(&r); + } + + auto allocSize = (void[]).sizeof * dim; + auto info = __arrayAlloc!UnqT(allocSize); + __setArrayAllocLength!UnqT(info, allocSize, isShared); + auto p = __arrayStart(info)[0 .. dim]; + + foreach (i; 0..dim) + { + (cast(void[]*)p.ptr)[i] = __allocateInnerArray(dims[1..$]); + } + return p; + } + + auto result = __allocateInnerArray(dims); + debug(PRINTF) printf("result = %llx\n", result.ptr); + + return (cast(U*) result.ptr)[0 .. dims[0]]; +} + +unittest +{ + int[][] a = _d_newarraymTX!(int[][], int)([2, 3]); + + assert(a.length == 2); + for (size_t i = 0; i < a.length; i++) + { + assert(a[i].length == 3); + for (size_t j = 0; j < a[i].length; j++) + assert(a[i][j] == 0); + } +} + +unittest +{ + struct S { int x = 1; } + + S[][] a = _d_newarraymTX!(S[][], S)([2, 3]); + + assert(a.length == 2); + for (size_t i = 0; i < a.length; i++) + { + assert(a[i].length == 3); + for (size_t j = 0; j < a[i].length; j++) + assert(a[i][j].x == 1); + } +} + +version (D_ProfileGC) +{ + /** + * TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction). + */ + Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(string file, int line, string funcname, size_t[] dims, bool isShared=false) @trusted + { + version (D_TypeInfo) + { + import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(T.stringof, "_d_newarraymTX")); + + return _d_newarraymTX!(Tarr, T)(dims, isShared); + } + else + assert(0, "Cannot create new multi-dimensional array if compiling without support for runtime type information!"); + } +} diff --git a/libphobos/libdruntime/core/internal/atomic.d b/libphobos/libdruntime/core/internal/atomic.d index 5daab89..eebf94e 100644 --- a/libphobos/libdruntime/core/internal/atomic.d +++ b/libphobos/libdruntime/core/internal/atomic.d @@ -656,7 +656,7 @@ version (DigitalMars) asm pure nothrow @nogc @trusted { naked; - rep; nop; + pause; ret; } } @@ -665,8 +665,7 @@ version (DigitalMars) asm pure nothrow @nogc @trusted { naked; - // pause; // TODO: DMD should add this opcode to its inline asm - rep; nop; + pause; ret; } } diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d index 39cd30a..6f19412 100644 --- a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d +++ b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d @@ -3336,7 +3336,7 @@ Lmark: busyThreads.atomicOp!"+="(1); // main thread is busy - evStart.set(); + evStart.setIfInitialized(); debug(PARALLEL_PRINTF) printf("mark %lld roots\n", cast(ulong)(ptop - pbot)); @@ -3438,7 +3438,7 @@ Lmark: stopGC = true; while (atomicLoad(stoppedThreads) < startedThreads && !allThreadsDead) { - evStart.set(); + evStart.setIfInitialized(); evDone.wait(dur!"msecs"(1)); } @@ -3467,7 +3467,7 @@ Lmark: { evStart.wait(); pullFromScanStack(); - evDone.set(); + evDone.setIfInitialized(); } stoppedThreads.atomicOp!"+="(1); } diff --git a/libphobos/libdruntime/core/internal/newaa.d b/libphobos/libdruntime/core/internal/newaa.d index 314f255..2fd9365 100644 --- a/libphobos/libdruntime/core/internal/newaa.d +++ b/libphobos/libdruntime/core/internal/newaa.d @@ -50,6 +50,7 @@ struct Impl immutable uint valsz; immutable uint valoff; Flags flags; + size_t delegate(scope const void*) nothrow hashFn; enum Flags : ubyte { @@ -76,15 +77,19 @@ private size_t mix(size_t h) @safe pure nothrow @nogc struct Entry(K, V) { - /*const*/ K key; // this really should be const, but legacy issues. + // can make this const, because we aren't really going to use it aside from + // construction. + const K key; V value; } // create a binary-compatible AA structure that can be used directly as an // associative array. -AAShell makeAA(K, V)(V[K] src) +// NOTE: this must only be called during CTFE +AAShell makeAA(K, V)(V[K] src) @trusted { + assert(__ctfe, "makeAA Must only be called at compile time"); immutable srclen = src.length; assert(srclen <= uint.max); alias E = Entry!(K, V); @@ -96,6 +101,12 @@ AAShell makeAA(K, V)(V[K] src) while (srclen * GROW_DEN > dim * GROW_NUM) dim = dim * GROW_FAC; + // used during runtime. + size_t delegate(scope const void *) nothrow hashFn = (scope const void* val) { + auto x = cast(K*)val; + return hashOf(*x); + }; + Bucket[] buckets; // Allocate and fill the buckets if (__ctfe) @@ -140,5 +151,19 @@ AAShell makeAA(K, V)(V[K] src) } (); // return the new implementation return AAShell(new Impl(buckets, cast(uint)srclen, 0, typeid(E), firstUsed, - K.sizeof, V.sizeof, E.value.offsetof, flags)); + K.sizeof, V.sizeof, E.value.offsetof, flags, hashFn)); +} + +unittest +{ + static struct Foo + { + ubyte x; + double d; + } + static int[Foo] utaa = [Foo(1, 2.0) : 5]; + auto k = Foo(1, 2.0); + // verify that getHash doesn't match hashOf for Foo + assert(typeid(Foo).getHash(&k) != hashOf(k)); + assert(utaa[Foo(1, 2.0)] == 5); } diff --git a/libphobos/libdruntime/core/stdc/fenv.d b/libphobos/libdruntime/core/stdc/fenv.d index 288f9c2..0051ecd 100644 --- a/libphobos/libdruntime/core/stdc/fenv.d +++ b/libphobos/libdruntime/core/stdc/fenv.d @@ -797,7 +797,7 @@ else } else version (LoongArch64) { - // Define bits representing exceptions in the FPSR status word. + // Define bits representing exceptions in the Flags field in FCSR{0,2}. enum { FE_INEXACT = 0x010000, /// @@ -808,13 +808,13 @@ else FE_ALL_EXCEPT = 0x1f0000, /// } - // Define bits representing rounding modes in the FPCR Rmode field. + // Define bits representing rounding modes in the RM field in FCSR{0,3}. enum { FE_TONEAREST = 0x000, /// FE_TOWARDZERO = 0x100, /// - FE_DOWNWARD = 0x200, /// - FE_UPWARD = 0x300, /// + FE_UPWARD = 0x200, /// + FE_DOWNWARD = 0x300, /// } } else diff --git a/libphobos/libdruntime/core/stdc/stdarg.d b/libphobos/libdruntime/core/stdc/stdarg.d index 5b79813..0ba1ebe 100644 --- a/libphobos/libdruntime/core/stdc/stdarg.d +++ b/libphobos/libdruntime/core/stdc/stdarg.d @@ -257,6 +257,12 @@ T va_arg(T)(ref va_list ap) ap += T.sizeof.alignUp; return *p; } + else version (LoongArch64) + { + auto p = cast(T*) ap; + ap += T.sizeof.alignUp; + return *p; + } else version (MIPS_Any) { auto p = cast(T*) ap; diff --git a/libphobos/libdruntime/core/sync/event.d b/libphobos/libdruntime/core/sync/event.d index 3795106..048607f 100644 --- a/libphobos/libdruntime/core/sync/event.d +++ b/libphobos/libdruntime/core/sync/event.d @@ -61,7 +61,7 @@ struct ProcessFile group.create(&doProcess); buffer = std.file.read(filename); - event.set(); + event.setIfInitialized(); group.joinAll(); event.terminate(); } @@ -162,9 +162,13 @@ nothrow @nogc: } } + deprecated ("Use setIfInitialized() instead") void set() + { + setIfInitialized(); + } /// Set the event to "signaled", so that waiting clients are resumed - void set() + void setIfInitialized() { version (Windows) { @@ -302,7 +306,7 @@ private: // auto-reset, initial state false Event ev1 = Event(false, false); assert(!ev1.wait(1.dur!"msecs")); - ev1.set(); + ev1.setIfInitialized(); assert(ev1.wait()); assert(!ev1.wait(1.dur!"msecs")); @@ -336,7 +340,7 @@ unittest auto start = MonoTime.currTime; assert(numRunning == 0); - event.set(); + event.setIfInitialized(); group.joinAll(); assert(numRunning == numThreads); diff --git a/libphobos/libdruntime/core/sys/elf/package.d b/libphobos/libdruntime/core/sys/elf/package.d index b120ee5..60e05d9 100644 --- a/libphobos/libdruntime/core/sys/elf/package.d +++ b/libphobos/libdruntime/core/sys/elf/package.d @@ -339,6 +339,8 @@ enum EM_CSKY = 252; enum EM_NUM = 253; +enum EM_LOONGARCH = 258; + enum EM_ALPHA = 0x9026; enum EV_NONE = 0; diff --git a/libphobos/libdruntime/core/sys/linux/sys/auxv.d b/libphobos/libdruntime/core/sys/linux/sys/auxv.d index 5f098e9..1099fae 100644 --- a/libphobos/libdruntime/core/sys/linux/sys/auxv.d +++ b/libphobos/libdruntime/core/sys/linux/sys/auxv.d @@ -13,6 +13,7 @@ extern (C): version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; +version (LoongArch64) version = LoongArch_Any; version (PPC) version = PPC_Any; version (PPC64) version = PPC_Any; version (S390) version = IBMZ_Any; @@ -156,3 +157,19 @@ else version (IBMZ_Any) enum HWCAP_S390_TE = 1024; enum HWCAP_S390_VX = 2048; } +else version (LoongArch_Any) +{ + enum HWCAP_LOONGARCH_CPUCFG = 0x00000001; + enum HWCAP_LOONGARCH_LAM = 0x00000002; + enum HWCAP_LOONGARCH_UAL = 0x00000004; + enum HWCAP_LOONGARCH_FPU = 0x00000008; + enum HWCAP_LOONGARCH_LSX = 0x00000010; + enum HWCAP_LOONGARCH_LASX = 0x00000020; + enum HWCAP_LOONGARCH_CRC32 = 0x00000040; + enum HWCAP_LOONGARCH_COMPLEX = 0x00000080; + enum HWCAP_LOONGARCH_CRYPTO = 0x00000100; + enum HWCAP_LOONGARCH_LVZ = 0x00000200; + enum HWCAP_LOONGARCH_LBT_X86 = 0x00000400; + enum HWCAP_LOONGARCH_LBT_ARM = 0x00000800; + enum HWCAP_LOONGARCH_LBT_MIPS = 0x00001000; +} diff --git a/libphobos/libdruntime/core/sys/linux/sys/mman.d b/libphobos/libdruntime/core/sys/linux/sys/mman.d index 7ed78ef..e4765af 100644 --- a/libphobos/libdruntime/core/sys/linux/sys/mman.d +++ b/libphobos/libdruntime/core/sys/linux/sys/mman.d @@ -432,6 +432,7 @@ else version (MIPS_Any) MAP_HUGETLB = 0x80000, } } +// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/bits/mman-map-flags-generic.h else version (LoongArch64) { static if (_DEFAULT_SOURCE) enum diff --git a/libphobos/libdruntime/core/thread/fiber.d b/libphobos/libdruntime/core/thread/fiber.d index 65878bc..8bbd6e1 100644 --- a/libphobos/libdruntime/core/thread/fiber.d +++ b/libphobos/libdruntime/core/thread/fiber.d @@ -178,8 +178,12 @@ private } else version (LoongArch64) { - version = AsmLoongArch64_Posix; - version = AsmExternal; + version (Posix) + { + version = AsmLoongArch64_Posix; + version = AsmExternal; + version = AlignFiberStackTo16Byte; + } } version (Posix) @@ -1444,24 +1448,28 @@ private: } else version (AsmLoongArch64_Posix) { + // Like others, FP registers and return address ($r1) are kept + // below the saved stack top (tstack) to hide from GC scanning. + // fiber_switchContext expects newp sp to look like this: + // 10: $r21 (reserved) + // 9: $r22 (frame pointer) + // 8: $r23 + // ... + // 0: $r31 <-- newp tstack + // -1: $r1 (return address) [&fiber_entryPoint] + // -2: $f24 + // ... + // -9: $f31 + version (StackGrowsDown) {} - else static assert(0); + else + static assert(false, "Only full descending stacks supported on LoongArch64"); - // Like others, FP registers and return address (ra) are kept - // below the saved stack top (tstack) to hide from GC scanning. - // The newp stack should look like this on LoongArch64: - // 18: fp <- pstack - // ... - // 9: s0 <- newp tstack - // 8: ra [&fiber_entryPoint] - // 7: fs7 - // ... - // 1: fs1 - // 0: fs0 - pstack -= 10 * size_t.sizeof; // skip s0-s8 and fp - // set $ra - push( cast(size_t) &fiber_entryPoint ); - pstack += size_t.sizeof; + // Only need to set return address ($r1). Everything else is fine + // zero initialized. + pstack -= size_t.sizeof * 11; // skip past space reserved for $r21-$r31 + push (cast(size_t) &fiber_entryPoint); + pstack += size_t.sizeof; // adjust sp (newp) above lr } else version (AsmAArch64_Posix) { diff --git a/libphobos/libdruntime/core/vararg.d b/libphobos/libdruntime/core/vararg.d index 2c3e965..e6dd47d 100644 --- a/libphobos/libdruntime/core/vararg.d +++ b/libphobos/libdruntime/core/vararg.d @@ -129,6 +129,13 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) ap += tsize.alignUp; parmn[0..tsize] = p[0..tsize]; } + else version (LoongArch64) + { + const tsize = ti.tsize; + auto p = cast(void*) ap; + ap += tsize.alignUp; + parmn[0..tsize] = p[0..tsize]; + } else version (MIPS_Any) { const tsize = ti.tsize; diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d index 0111be0..5589c0a 100644 --- a/libphobos/libdruntime/object.d +++ b/libphobos/libdruntime/object.d @@ -642,7 +642,8 @@ class TypeInfo */ size_t getHash(scope const void* p) @trusted nothrow const { - return hashOf(p); + // by default, do not assume anything about the type + return 0; } /// Compares two instances for equality. @@ -2918,19 +2919,19 @@ alias AssociativeArray(Key, Value) = Value[Key]; * Params: * aa = The associative array. */ -void clear(Value, Key)(Value[Key] aa) +void clear(Value, Key)(Value[Key] aa) @trusted { _aaClear(*cast(AA *) &aa); } /** ditto */ -void clear(Value, Key)(Value[Key]* aa) +void clear(Value, Key)(Value[Key]* aa) @trusted { _aaClear(*cast(AA *) aa); } /// -@system unittest +@safe unittest { auto aa = ["k1": 2]; aa.clear; @@ -4666,11 +4667,13 @@ public import core.internal.array.appending : _d_arrayappendT; version (D_ProfileGC) { public import core.internal.array.appending : _d_arrayappendTTrace; + public import core.internal.array.appending : _d_arrayappendcTXTrace; public import core.internal.array.concatenation : _d_arraycatnTXTrace; public import core.lifetime : _d_newitemTTrace; public import core.internal.array.construction : _d_newarrayTTrace; + public import core.internal.array.construction : _d_newarraymTXTrace; } -public import core.internal.array.appending : _d_arrayappendcTXImpl; +public import core.internal.array.appending : _d_arrayappendcTX; public import core.internal.array.comparison : __cmp; public import core.internal.array.equality : __equals; public import core.internal.array.casting: __ArrayCast; @@ -4678,6 +4681,7 @@ public import core.internal.array.concatenation : _d_arraycatnTX; public import core.internal.array.construction : _d_arrayctor; public import core.internal.array.construction : _d_arraysetctor; public import core.internal.array.construction : _d_newarrayT; +public import core.internal.array.construction : _d_newarraymTX; public import core.internal.array.arrayassign : _d_arrayassign_l; public import core.internal.array.arrayassign : _d_arrayassign_r; public import core.internal.array.arrayassign : _d_arraysetassign; diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d index 4014862..36f2555 100644 --- a/libphobos/libdruntime/rt/aaA.d +++ b/libphobos/libdruntime/rt/aaA.d @@ -41,7 +41,7 @@ struct AA Impl* impl; alias impl this; - private @property bool empty() const pure nothrow @nogc + private @property bool empty() const pure nothrow @nogc @safe { return impl is null || !impl.length; } @@ -57,6 +57,7 @@ private: buckets = allocBuckets(sz); firstUsed = cast(uint) buckets.length; valoff = cast(uint) talign(keysz, ti.value.talign); + hashFn = &ti.key.getHash; import rt.lifetime : hasPostblit, unqualify; @@ -78,6 +79,10 @@ private: immutable uint valoff; Flags flags; + // function that calculates hash of a key. Set on creation + // the parameter is a pointer to the key. + size_t delegate(scope const void*) nothrow hashFn; + enum Flags : ubyte { none = 0x0, @@ -85,7 +90,7 @@ private: hasPointers = 0x2, } - @property size_t length() const pure nothrow @nogc + @property size_t length() const pure nothrow @nogc @safe { assert(used >= deleted); return used - deleted; @@ -156,7 +161,7 @@ private: GC.free(obuckets.ptr); // safe to free b/c impossible to reference } - void clear() pure nothrow + void clear() pure nothrow @trusted { import core.stdc.string : memset; // clear all data, but don't change bucket array length @@ -457,9 +462,9 @@ private size_t mix(size_t h) @safe pure nothrow @nogc return h; } -private size_t calcHash(scope const void* pkey, scope const TypeInfo keyti) nothrow +private size_t calcHash(scope const void *pkey, scope const Impl* impl) nothrow { - immutable hash = keyti.getHash(pkey); + immutable hash = impl.hashFn(pkey); // highest bit is set to distinguish empty/deleted from filled buckets return mix(hash) | HASH_FILLED_MARK; } @@ -550,7 +555,7 @@ extern (C) void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti, } // get hash and bucket for key - immutable hash = calcHash(pkey, ti.key); + immutable hash = calcHash(pkey, aa); // found a value => return it if (auto p = aa.findSlotLookup(hash, pkey, ti.key)) @@ -617,7 +622,7 @@ extern (C) inout(void)* _aaInX(inout AA aa, scope const TypeInfo keyti, scope co if (aa.empty) return null; - immutable hash = calcHash(pkey, keyti); + immutable hash = calcHash(pkey, aa); if (auto p = aa.findSlotLookup(hash, pkey, keyti)) return p.entry + aa.valoff; return null; @@ -629,7 +634,7 @@ extern (C) bool _aaDelX(AA aa, scope const TypeInfo keyti, scope const void* pke if (aa.empty) return false; - immutable hash = calcHash(pkey, keyti); + immutable hash = calcHash(pkey, aa); if (auto p = aa.findSlotLookup(hash, pkey, keyti)) { // clear entry @@ -648,7 +653,7 @@ extern (C) bool _aaDelX(AA aa, scope const TypeInfo keyti, scope const void* pke } /// Remove all elements from AA. -extern (C) void _aaClear(AA aa) pure nothrow +extern (C) void _aaClear(AA aa) pure nothrow @safe { if (!aa.empty) { @@ -778,7 +783,7 @@ extern (C) Impl* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void uint actualLength = 0; foreach (_; 0 .. length) { - immutable hash = calcHash(pkey, ti.key); + immutable hash = calcHash(pkey, aa); auto p = aa.findSlotLookup(hash, pkey, ti.key); if (p is null) diff --git a/libphobos/libdruntime/rt/lifetime.d b/libphobos/libdruntime/rt/lifetime.d index af3c6bb..8ce2d56 100644 --- a/libphobos/libdruntime/rt/lifetime.d +++ b/libphobos/libdruntime/rt/lifetime.d @@ -1041,98 +1041,6 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @ } } - -/* - * Helper for creating multi-dimensional arrays - */ -private void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims) -{ - debug(PRINTF) printf("_d_newarrayOpT(ndims = %d)\n", dims.length); - if (dims.length == 0) - return null; - - void[] foo(const TypeInfo ti, size_t[] dims) - { - auto tinext = unqualify(ti.next); - auto dim = dims[0]; - - debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length); - if (dims.length == 1) - { - auto r = op(ti, dim); - return *cast(void[]*)(&r); - } - - auto allocsize = (void[]).sizeof * dim; - auto info = __arrayAlloc(allocsize, ti, tinext); - auto isshared = typeid(ti) is typeid(TypeInfo_Shared); - __setArrayAllocLength(info, allocsize, isshared, tinext); - auto p = __arrayStart(info)[0 .. dim]; - - foreach (i; 0..dim) - { - (cast(void[]*)p.ptr)[i] = foo(tinext, dims[1..$]); - } - return p; - } - - auto result = foo(ti, dims); - debug(PRINTF) printf("result = %llx\n", result.ptr); - - return result; -} - - -/** -Create a new multi-dimensional array - -Has two variants: -- `_d_newarraymTX` which initializes to 0 -- `_d_newarraymiTX` which initializes elements based on `TypeInfo` - ---- -void main() -{ - new int[][](10, 20); - // _d_newarraymTX(typeid(float), [10, 20]); - - new float[][][](10, 20, 30); - // _d_newarraymiTX(typeid(float), [10, 20, 30]); -} ---- - -Params: - ti = `TypeInfo` of the array type - dims = array length values for each dimension - -Returns: - newly allocated array -*/ -extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) @weak -{ - debug(PRINTF) printf("_d_newarraymT(dims.length = %d)\n", dims.length); - - if (dims.length == 0) - return null; - else - { - return _d_newarrayOpT!(_d_newarrayT)(ti, dims); - } -} - -/// ditto -extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak -{ - debug(PRINTF) printf("_d_newarraymiT(dims.length = %d)\n", dims.length); - - if (dims.length == 0) - return null; - else - { - return _d_newarrayOpT!(_d_newarrayiT)(ti, dims); - } -} - /** Non-template version of $(REF _d_newitemT, core,lifetime) that does not perform initialization. Needed for $(REF allocEntry, rt,aaA). diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index 8c536ce..1b20d58 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -1c98326e787e504d9045004e593273ec99b13121 +17bafda797296e04f40f16a9660e5a9685392db4 The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/algorithm/iteration.d b/libphobos/src/std/algorithm/iteration.d index 0adb88b..ef11706 100644 --- a/libphobos/src/std/algorithm/iteration.d +++ b/libphobos/src/std/algorithm/iteration.d @@ -4809,26 +4809,41 @@ private template ReduceSeedType(E) /++ Implements the homonym function (also known as `accumulate`, $(D compress), `inject`, or `foldl`) present in various programming -languages of functional flavor. The call `fold!(fun)(range, seed)` -first assigns `seed` to an internal variable `result`, -also called the accumulator. Then, for each element `x` in $(D -range), `result = fun(result, x)` gets evaluated. Finally, $(D -result) is returned. The one-argument version `fold!(fun)(range)` +languages of functional flavor, iteratively calling one or more predicates. + +$(P Each predicate in `fun` must take two arguments:) +* An accumulator value +* An element of the range `r` +$(P Each predicate must return a value which implicitly converts to the +type of the accumulator.) + +$(P For a single predicate, +the call `fold!(fun)(range, seed)` will:) + +* Use `seed` to initialize an internal variable `result` (also called + the accumulator). +* For each element `e` in $(D range), evaluate `result = fun(result, e)`. +* Return $(D result). + +$(P The one-argument version `fold!(fun)(range)` works similarly, but it uses the first element of the range as the -seed (the range must be non-empty). +seed (the range must be non-empty) and iterates over the remaining +elements.) + +Multiple results are produced when using multiple predicates. Params: fun = the predicate function(s) to apply to the elements See_Also: - $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) + * $(HTTP en.wikipedia.org/wiki/Fold_(higher-order_function), Fold (higher-order function)) - $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers - precise summing of floating point numbers. + * $(LREF sum) is similar to `fold!((a, b) => a + b)` that offers + precise summing of floating point numbers. - This is functionally equivalent to $(LREF reduce) with the argument order - reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons) - for multiple seeds. + * `fold` is functionally equivalent to $(LREF reduce) with the argument order + reversed, and without the need to use $(REF_ALTTEXT `tuple`,tuple,std,typecons) + for multiple seeds. +/ template fold(fun...) if (fun.length >= 1) @@ -4836,20 +4851,21 @@ if (fun.length >= 1) /** Params: r = the $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to fold - seed = the initial value of the accumulator + seeds = the initial values of each accumulator (optional), one for each predicate Returns: - the accumulated `result` + Either the accumulated result for a single predicate, or a + $(REF_ALTTEXT `Tuple`,Tuple,std,typecons) of results. */ - auto fold(R, S...)(R r, S seed) + auto fold(R, S...)(R r, S seeds) { static if (S.length < 2) { - return reduce!fun(seed, r); + return reduce!fun(seeds, r); } else { import std.typecons : tuple; - return reduce!fun(tuple(seed), r); + return reduce!fun(tuple(seeds), r); } } } @@ -4860,10 +4876,10 @@ if (fun.length >= 1) immutable arr = [1, 2, 3, 4, 5]; // Sum all elements - assert(arr.fold!((a, b) => a + b) == 15); + assert(arr.fold!((a, e) => a + e) == 15); // Sum all elements with explicit seed - assert(arr.fold!((a, b) => a + b)(6) == 21); + assert(arr.fold!((a, e) => a + e)(6) == 21); import std.algorithm.comparison : min, max; import std.typecons : tuple; @@ -4875,10 +4891,10 @@ if (fun.length >= 1) assert(arr.fold!(min, max)(0, 7) == tuple(0, 7)); // Can be used in a UFCS chain - assert(arr.map!(a => a + 1).fold!((a, b) => a + b) == 20); + assert(arr.map!(a => a + 1).fold!((a, e) => a + e) == 20); // Return the last element of any range - assert(arr.fold!((a, b) => b) == 5); + assert(arr.fold!((a, e) => e) == 5); } @safe @nogc pure nothrow unittest diff --git a/libphobos/src/std/algorithm/searching.d b/libphobos/src/std/algorithm/searching.d index 37a08de..6897905 100644 --- a/libphobos/src/std/algorithm/searching.d +++ b/libphobos/src/std/algorithm/searching.d @@ -1547,27 +1547,95 @@ if (isInputRange!Range && !isInfinite!Range && // find /** +Finds an element `e` of an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) +where `pred(e)` is `true`. +$(P +$(PANEL +$(UL +$(LI `find` behaves similarly to `dropWhile` in other languages.) +$(LI To _find the *last* matching element in a +$(REF_ALTTEXT bidirectional, isBidirectionalRange, std,range,primitives) `haystack`, +call `find!pred(retro(haystack))`. See $(REF retro, std,range).) +))) + +Complexity: + `find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`. + +Params: + + pred = The predicate to match an element. + haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) + searched in. + +Returns: + `haystack` advanced such that the front element satisfies `pred`. + If no such element exists, returns an empty `haystack`. +*/ +InputRange find(alias pred, InputRange)(InputRange haystack) +if (isInputRange!InputRange) +{ + alias R = InputRange; + alias predFun = unaryFun!pred; + static if (isNarrowString!R) + { + import std.utf : decode; + + immutable len = haystack.length; + size_t i = 0, next = 0; + while (next < len) + { + if (predFun(decode(haystack, next))) + return haystack[i .. $]; + i = next; + } + return haystack[$ .. $]; + } + else + { + //standard range + for ( ; !haystack.empty; haystack.popFront() ) + { + if (predFun(haystack.front)) + break; + } + return haystack; + } +} + +/// +@safe unittest +{ + auto arr = [ 1, 2, 3, 4, 1 ]; + assert(find!("a > 2")(arr) == [ 3, 4, 1 ]); + + // with predicate alias + bool pred(int e) => e + 1 > 1.5; + assert(find!(pred)(arr) == arr); +} + +@safe pure unittest +{ + int[] r = [ 1, 2, 3 ]; + assert(find!(a=>a > 2)(r) == [3]); + bool pred(int x) { return x + 1 > 1.5; } + assert(find!(pred)(r) == r); + + assert(find!(a=>a > 'v')("hello world") == "world"); + assert(find!(a=>a%4 == 0)("日本語") == "本語"); +} + +/** Finds an individual element in an $(REF_ALTTEXT input range, isInputRange, std,range,primitives). Elements of `haystack` are compared with `needle` by using predicate `pred` with `pred(haystack.front, needle)`. -`find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`. - The predicate is passed to $(REF binaryFun, std, functional), and can either accept a string, or any callable that can be executed via `pred(element, element)`. -To _find the last occurrence of `needle` in a -$(REF_ALTTEXT bidirectional, isBidirectionalRange, std,range,primitives) `haystack`, -call `find(retro(haystack), needle)`. See $(REF retro, std,range). - -If no `needle` is provided, `pred(haystack.front)` will be evaluated on each -element of the input range. - -If `input` is a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives), +If `haystack` is a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives), `needle` can be a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) too. In this case `startsWith!pred(haystack, needle)` is evaluated on each evaluation. -Note: - `find` behaves similar to `dropWhile` in other languages. +$(NOTE To find the first element $(I not) matching the needle, use predicate `"a != b"`.) Complexity: `find` performs $(BIGOH walkLength(haystack)) evaluations of `pred`. @@ -1579,21 +1647,16 @@ Complexity: Params: pred = The predicate for comparing each element with the needle, defaulting to equality `"a == b"`. - The negated predicate `"a != b"` can be used to search instead for the first - element $(I not) matching the needle. - haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) searched in. - needle = The element searched for. Returns: - `haystack` advanced such that the front element is the one searched for; that is, until `binaryFun!pred(haystack.front, needle)` is `true`. If no such position exists, returns an empty `haystack`. -See_ALso: $(LREF findAdjacent), $(LREF findAmong), $(LREF findSkip), $(LREF findSplit), $(LREF startsWith) +See_Also: $(LREF findAdjacent), $(LREF findAmong), $(LREF findSkip), $(LREF findSplit), $(LREF startsWith) */ InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle) if (isInputRange!InputRange && @@ -1754,8 +1817,8 @@ if (isInputRange!InputRange && assert(arr.find(4) == [4, 4, 4, 4, 5, 6, 9]); assert(arr.find(1) == arr); assert(arr.find(9) == [9]); - assert(arr.find!((a, b) => a > b)(4) == [5, 6, 9]); - assert(arr.find!((a, b) => a < b)(4) == arr); + assert(arr.find!((e, n) => e > n)(4) == [5, 6, 9]); + assert(arr.find!((e, n) => e < n)(4) == arr); assert(arr.find(0).empty); assert(arr.find(10).empty); assert(arr.find(8).empty); @@ -1770,7 +1833,7 @@ if (isInputRange!InputRange && import std.uni : toLower; string[] s = ["Hello", "world", "!"]; - assert(s.find!((a, b) => toLower(a) == b)("hello") == s); + assert(s.find!((e, n) => toLower(e) == n)("hello") == s); } @safe unittest @@ -1863,60 +1926,6 @@ if (isInputRange!InputRange && } /// ditto -InputRange find(alias pred, InputRange)(InputRange haystack) -if (isInputRange!InputRange) -{ - alias R = InputRange; - alias predFun = unaryFun!pred; - static if (isNarrowString!R) - { - import std.utf : decode; - - immutable len = haystack.length; - size_t i = 0, next = 0; - while (next < len) - { - if (predFun(decode(haystack, next))) - return haystack[i .. $]; - i = next; - } - return haystack[$ .. $]; - } - else - { - //standard range - for ( ; !haystack.empty; haystack.popFront() ) - { - if (predFun(haystack.front)) - break; - } - return haystack; - } -} - -/// -@safe unittest -{ - auto arr = [ 1, 2, 3, 4, 1 ]; - assert(find!("a > 2")(arr) == [ 3, 4, 1 ]); - - // with predicate alias - bool pred(int x) { return x + 1 > 1.5; } - assert(find!(pred)(arr) == arr); -} - -@safe pure unittest -{ - int[] r = [ 1, 2, 3 ]; - assert(find!(a=>a > 2)(r) == [3]); - bool pred(int x) { return x + 1 > 1.5; } - assert(find!(pred)(r) == r); - - assert(find!(a=>a > 'v')("hello world") == "world"); - assert(find!(a=>a%4 == 0)("日本語") == "本語"); -} - -/// ditto R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle) if (isForwardRange!R1 && isForwardRange!R2 && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool)) @@ -2376,9 +2385,9 @@ is considered to be 1.) The strategy used in searching several subranges at once maximizes cache usage by moving in `haystack` as few times as possible. */ -Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...) -(Range haystack, Ranges needles) -if (Ranges.length > 1 && is(typeof(startsWith!pred(haystack, needles)))) +Tuple!(Range, size_t) find(alias pred = "a == b", Range, Needles...) +(Range haystack, Needles needles) +if (Needles.length > 1 && is(typeof(startsWith!pred(haystack, needles)))) { for (;; haystack.popFront()) { @@ -2536,13 +2545,13 @@ was successful. For more information about `pred` see $(LREF find). See_Also: -$(REF among, std,algorithm,comparison) for checking a value against multiple possibilities. +$(REF among, std,algorithm,comparison) for checking a value against multiple arguments. +/ template canFind(alias pred="a == b") { /++ - Returns `true` if and only if any value `v` found in the - input range `range` satisfies the predicate `pred`. + Returns `true` if and only if `pred(e)` is true for any value `e` in the + input range `range`. Performs (at most) $(BIGOH haystack.length) evaluations of `pred`. +/ bool canFind(Range)(Range haystack) @@ -2565,16 +2574,15 @@ template canFind(alias pred="a == b") Returns the 1-based index of the first needle found in `haystack`. If no needle is found, then `0` is returned. - So, if used directly in the condition of an if statement or loop, the result + So, if used directly in the condition of an `if` statement or loop, the result will be `true` if one of the needles is found and `false` if none are found, whereas if the result is used elsewhere, it can either be cast to `bool` for the same effect or used to get which needle was found first - without having to deal with the tuple that `LREF find` returns for the + without having to deal with the tuple that $(LREF find) returns for the same operation. +/ - size_t canFind(Range, Ranges...)(Range haystack, scope Ranges needles) - if (Ranges.length > 1 && - allSatisfy!(isForwardRange, Ranges) && + size_t canFind(Range, Needles...)(Range haystack, scope Needles needles) + if (Needles.length > 1 && is(typeof(find!pred(haystack, needles)))) { return find!pred(haystack, needles)[1]; @@ -2584,15 +2592,21 @@ template canFind(alias pred="a == b") /// @safe unittest { - assert(canFind([0, 1, 2, 3], 2) == true); - assert(canFind([0, 1, 2, 3], [1, 2], [2, 3])); - assert(canFind([0, 1, 2, 3], [1, 2], [2, 3]) == 1); - assert(canFind([0, 1, 2, 3], [1, 7], [2, 3])); - assert(canFind([0, 1, 2, 3], [1, 7], [2, 3]) == 2); + const arr = [0, 1, 2, 3]; + assert(canFind(arr, 2)); + assert(!canFind(arr, 4)); + + // find one of several needles + assert(arr.canFind(3, 2)); + assert(arr.canFind(3, 2) == 2); // second needle found + assert(arr.canFind([1, 3], 2) == 2); - assert(canFind([0, 1, 2, 3], 4) == false); - assert(!canFind([0, 1, 2, 3], [1, 3], [2, 4])); - assert(canFind([0, 1, 2, 3], [1, 3], [2, 4]) == 0); + assert(canFind(arr, [1, 2], [2, 3])); + assert(canFind(arr, [1, 2], [2, 3]) == 1); + assert(canFind(arr, [1, 7], [2, 3])); + assert(canFind(arr, [1, 7], [2, 3]) == 2); + assert(!canFind(arr, [1, 3], [2, 4])); + assert(canFind(arr, [1, 3], [2, 4]) == 0); } /** @@ -2607,10 +2621,10 @@ template canFind(alias pred="a == b") "cardboard" ]; assert(!canFind(words, "bees")); - assert( canFind!((string a, string b) => a.startsWith(b))(words, "bees")); + assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees")); } -/// Search for mutliple items in an array of items (search for needles in an array of hay stacks) +/// Search for multiple items in an array of items (search for needles in an array of haystacks) @safe unittest { string s1 = "aaa111aaa"; @@ -2618,7 +2632,7 @@ template canFind(alias pred="a == b") string s3 = "aaa333aaa"; string s4 = "aaa444aaa"; const hay = [s1, s2, s3, s4]; - assert(hay.canFind!(e => (e.canFind("111", "222")))); + assert(hay.canFind!(e => e.canFind("111", "222"))); } @safe unittest @@ -2736,7 +2750,7 @@ Returns: `seq` advanced to the first matching element, or until empty if there are no matching elements. -See_Also: $(LREF find), $(REF std,algorithm,comparison,among) +See_Also: $(LREF find), $(REF among, std,algorithm,comparison) */ InputRange findAmong(alias pred = "a == b", InputRange, ForwardRange)( InputRange seq, ForwardRange choices) diff --git a/libphobos/src/std/array.d b/libphobos/src/std/array.d index a613a8d..494fa29 100644 --- a/libphobos/src/std/array.d +++ b/libphobos/src/std/array.d @@ -1201,7 +1201,7 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow auto a2 = minimallyInitializedArray!(S2[][])(2, 2); assert(a2); enum b2 = minimallyInitializedArray!(S2[][])(2, 2); - assert(b2); + assert(b2 !is null); static struct S3 { //this() @disable; @@ -1210,7 +1210,7 @@ private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow auto a3 = minimallyInitializedArray!(S3[][])(2, 2); assert(a3); enum b3 = minimallyInitializedArray!(S3[][])(2, 2); - assert(b3); + assert(b3 !is null); } /++ diff --git a/libphobos/src/std/container/array.d b/libphobos/src/std/container/array.d index 0d6be93..ad120c1 100644 --- a/libphobos/src/std/container/array.d +++ b/libphobos/src/std/container/array.d @@ -594,6 +594,10 @@ if (!is(immutable T == immutable bool)) assert(capacity == values.length); // We check that reserve has been called before the loop. } + /// ditto + // needed when T is an array and only one argument is passed + this(T single) { __ctor!T(single); } + /** * Constructor taking an $(REF_ALTTEXT input range, isInputRange, std,range,primitives) */ @@ -1282,6 +1286,13 @@ if (!is(immutable T == immutable bool)) } } +@system unittest +{ + import std.algorithm.comparison : equal; + auto a = Array!string("test"); + assert(a[].equal(["test"])); +} + @safe unittest { // https://issues.dlang.org/show_bug.cgi?id=13621 diff --git a/libphobos/src/std/logger/package.d b/libphobos/src/std/logger/package.d index 4f4183c..14a4394 100644 --- a/libphobos/src/std/logger/package.d +++ b/libphobos/src/std/logger/package.d @@ -54,6 +54,7 @@ $(UL $(LI `trace`) $(LI `info`) $(LI `warning`) + $(LI `error`) $(LI `critical`) $(LI `fatal`) ) diff --git a/libphobos/src/std/math/hardware.d b/libphobos/src/std/math/hardware.d index 81c7302..cb6cb87 100644 --- a/libphobos/src/std/math/hardware.d +++ b/libphobos/src/std/math/hardware.d @@ -33,6 +33,7 @@ version (SPARC64) version = SPARC_Any; version (SystemZ) version = IBMZ_Any; version (RISCV32) version = RISCV_Any; version (RISCV64) version = RISCV_Any; +version (LoongArch64) version = LoongArch_Any; version (D_InlineAsm_X86) version = InlineAsm_X86_Any; version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any; @@ -60,6 +61,7 @@ else version (X86_Any) version = IeeeFlagsSupport; else version (PPC_Any) version = IeeeFlagsSupport; else version (RISCV_Any) version = IeeeFlagsSupport; else version (MIPS_Any) version = IeeeFlagsSupport; +else version (LoongArch_Any) version = IeeeFlagsSupport; else version (ARM_Any) version = IeeeFlagsSupport; // Struct FloatingPointControl is only available if hardware FP units are available. @@ -90,6 +92,7 @@ private: // The ARM and PowerPC FPSCR is a 32-bit register. // The SPARC FSR is a 32bit register (64 bits for SPARC 7 & 8, but high bits are uninteresting). // The RISC-V (32 & 64 bit) fcsr is 32-bit register. + // THe LoongArch fcsr (fcsr0) is a 32-bit register. uint flags; version (CRuntime_Microsoft) @@ -216,6 +219,15 @@ private: return result; `); } + else version (LoongArch_Any) + { + uint result = void; + asm pure nothrow @nogc + { + "movfcsr2gr %0,$r2" : "=r" (result); + } + return result & EXCEPTIONS_MASK; + } else assert(0, "Not yet supported"); } @@ -303,6 +315,13 @@ private: } `); } + else version (LoongArch_Any) + { + asm nothrow @nogc + { + "movgr2fcsr $r2,$r0"; + } + } else { /* SPARC: @@ -725,6 +744,21 @@ nothrow @nogc: | inexactException, } } + else version (LoongArch_Any) + { + enum : ExceptionMask + { + inexactException = 0x00, + divByZeroException = 0x01, + overflowException = 0x02, + underflowException = 0x04, + invalidException = 0x08, + severeExceptions = overflowException | divByZeroException + | invalidException, + allExceptions = severeExceptions | underflowException + | inexactException, + } + } else version (MIPS_Any) { enum : ExceptionMask @@ -812,6 +846,8 @@ nothrow @nogc: return true; else version (MIPS_Any) return true; + else version (LoongArch_Any) + return true; else version (ARM_Any) { // The hasExceptionTraps_impl function is basically pure, @@ -885,6 +921,10 @@ private: { alias ControlState = uint; } + else version (LoongArch_Any) + { + alias ControlState = uint; + } else version (MIPS_Any) { alias ControlState = uint; @@ -1008,6 +1048,16 @@ private: return cont; `); } + else version (LoongArch_Any) + { + ControlState cont; + asm pure nothrow @nogc + { + "movfcsr2gr %0,$r0" : "=r" (cont); + } + cont &= (roundingMask | allExceptions); + return cont; + } else assert(0, "Not yet supported"); } @@ -1120,6 +1170,14 @@ private: } `); } + else version (LoongArch_Any) + { + asm nothrow @nogc + { + "movgr2fcsr $r0,%0" : + : "r" (newState & (roundingMask | allExceptions)); + } + } else assert(0, "Not yet supported"); } diff --git a/libphobos/src/std/range/primitives.d b/libphobos/src/std/range/primitives.d index 89cfa07..fec5c85 100644 --- a/libphobos/src/std/range/primitives.d +++ b/libphobos/src/std/range/primitives.d @@ -1015,12 +1015,27 @@ See_Also: enum bool isForwardRange(R) = isInputRange!R && is(typeof((R r) { return r.save; } (R.init)) == R); +/// ditto +enum bool isForwardRange(R, E) = + .isForwardRange!R && isQualifierConvertible!(ElementType!R, E); + /// @safe unittest { static assert(!isForwardRange!(int)); static assert( isForwardRange!(int[])); static assert( isForwardRange!(inout(int)[])); + + static assert( isForwardRange!(int[], const int)); + static assert(!isForwardRange!(int[], immutable int)); + + static assert(!isForwardRange!(const(int)[], int)); + static assert( isForwardRange!(const(int)[], const int)); + static assert(!isForwardRange!(const(int)[], immutable int)); + + static assert(!isForwardRange!(immutable(int)[], int)); + static assert( isForwardRange!(immutable(int)[], const int)); + static assert( isForwardRange!(immutable(int)[], immutable int)); } @safe unittest diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index f4b9f5f..bb1feca 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,10 @@ +2023-11-21 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/112562 + * sanitizer_common/sanitizer_asm.h: Cherry-pick llvm-project revision + a855a16a02e76a0f4192c038bb64f3773947a2f7. + * interception/interception.h: Likewise. + 2023-11-18 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> * asan/asan_mac.cpp: Protect Apple blocks behind the diff --git a/libsanitizer/interception/interception.h b/libsanitizer/interception/interception.h index 069f73d..9d8b60b 100644 --- a/libsanitizer/interception/interception.h +++ b/libsanitizer/interception/interception.h @@ -185,6 +185,11 @@ const interpose_substitution substitution_##func_name[] \ # else # define __ASM_WEAK_WRAPPER(func) ".weak " #func "\n" # endif // SANITIZER_FREEBSD || SANITIZER_NETBSD +# if defined(__arm__) || defined(__aarch64__) +# define ASM_TYPE_FUNCTION_STR "%function" +# else +# define ASM_TYPE_FUNCTION_STR "@function" +# endif // Keep trampoline implementation in sync with sanitizer_common/sanitizer_asm.h # define DECLARE_WRAPPER(ret_type, func, ...) \ extern "C" ret_type func(__VA_ARGS__); \ @@ -196,7 +201,8 @@ const interpose_substitution substitution_##func_name[] \ __ASM_WEAK_WRAPPER(func) \ ".set " #func ", " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ ".globl " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ - ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", %function\n" \ + ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ + ASM_TYPE_FUNCTION_STR "\n" \ SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \ SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \ SANITIZER_STRINGIFY(ASM_TAIL_CALL) " __interceptor_" \ diff --git a/libsanitizer/sanitizer_common/sanitizer_asm.h b/libsanitizer/sanitizer_common/sanitizer_asm.h index 3c9bbdc..bbb18cf 100644 --- a/libsanitizer/sanitizer_common/sanitizer_asm.h +++ b/libsanitizer/sanitizer_common/sanitizer_asm.h @@ -62,7 +62,11 @@ #if !defined(__APPLE__) # define ASM_HIDDEN(symbol) .hidden symbol -# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function +# if defined(__arm__) || defined(__aarch64__) +# define ASM_TYPE_FUNCTION(symbol) .type symbol, %function +# else +# define ASM_TYPE_FUNCTION(symbol) .type symbol, @function +# endif # define ASM_SIZE(symbol) .size symbol, .-symbol # define ASM_SYMBOL(symbol) symbol # define ASM_SYMBOL_INTERCEPTOR(symbol) symbol diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f636961..fb48d2d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,106 @@ +2023-11-24 Jan Hubicka <jh@suse.cz> + + PR middle-end/109849 + * include/bits/stl_uninitialized.h (__relocate_a_1): Use memcpy instead + of memmove. + +2023-11-23 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/111055 + * include/bits/ranges_base.h (from_range_t): Define new tag + type. + (from_range): Define new tag object. + * include/bits/version.def (ranges_to_container): Define. + * include/bits/version.h: Regenerate. + * include/std/ranges (ranges::to): Define. + * testsuite/std/ranges/conv/1.cc: New test. + * testsuite/std/ranges/conv/2_neg.cc: New test. + * testsuite/std/ranges/conv/version.cc: New test. + +2023-11-23 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/util/testsuite_allocator.h (uneq_allocator): Fix + equality operator for heterogeneous comparisons. + +2023-11-21 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/version.def (freestanding_cstring): Add. + * include/bits/version.h: Regenerate. + * include/c_compatibility/string.h (strtok): Do not declare for + C++26 freestanding. + * include/c_global/cstring (strtok): Likewise. + * testsuite/21_strings/headers/cstring/version.cc: New test. + +2023-11-21 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/version.def (freestanding_algorithm) + (freestanding_array, freestanding_optional) + (freestanding_string_view, freestanding_variant): Add. + * include/bits/version.h: Regenerate. + * include/std/algorithm (__glibcxx_want_freestanding_algorithm): + Define. + * include/std/array (__glibcxx_want_freestanding_array): + Define. + * include/std/optional (__glibcxx_want_freestanding_optional): + Define. + * include/std/string_view + (__glibcxx_want_freestanding_string_view): Define. + * include/std/variant (__glibcxx_want_freestanding_variant): + Define. + * testsuite/20_util/optional/version.cc: Add checks for + __cpp_lib_freestanding_optional. + * testsuite/20_util/variant/version.cc: Add checks for + __cpp_lib_freestanding_variant. + * testsuite/23_containers/array/tuple_interface/get_neg.cc: + Adjust dg-error line numbers. + * testsuite/21_strings/basic_string_view/requirements/version.cc: + New test. + * testsuite/23_containers/array/requirements/version.cc: New + test. + * testsuite/25_algorithms/fill_n/requirements/version.cc: New + test. + * testsuite/25_algorithms/swap_ranges/requirements/version.cc: + New test. + +2023-11-21 Jonathan Wakely <jwakely@redhat.com> + + * include/bits/version.def (freestanding_expected): New macro. + (span): Add C++26 value. + * include/bits/version.h: Regenerate. + * include/std/expected (__glibcxx_want_freestanding_expected): + Define. + * include/std/span (span::at): New member function. + * testsuite/20_util/expected/version.cc: Add checks for + __cpp_lib_freestanding_expected. + * testsuite/23_containers/span/2.cc: Moved to... + * testsuite/23_containers/span/version.cc: ...here. Add checks + for __cpp_lib_span in <span> as well as in <version>. + * testsuite/23_containers/span/1.cc: Removed. + * testsuite/23_containers/span/at.cc: New test. + +2023-11-21 Jonathan Wakely <jwakely@redhat.com> + + * include/tr2/dynamic_bitset (dynamic_bitset): Pass zero and one + characters to _M_copy_from_string. + * testsuite/tr2/dynamic_bitset/string.cc: New test. + +2023-11-21 Jonathan Wakely <jwakely@redhat.com> + + * doc/html/*: Regenerate. + * doc/xml/faq.xml: Remove reference to buildstat.html pages. + * doc/xml/manual/test.xml: Likewise + +2023-11-21 Jan Hubicka <jh@suse.cz> + + PR libstdc++/110287 + PR middle-end/109811 + PR middle-end/109849 + * include/bits/stl_vector.h (_M_realloc_append): New member function. + (push_back): Use it. + * include/bits/vector.tcc: (emplace_back): Use it. + (_M_realloc_insert): Let compiler know that new vector size is non-zero. + (_M_realloc_append): New member function. + 2023-11-18 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/112607 diff --git a/libstdc++-v3/doc/html/faq.html b/libstdc++-v3/doc/html/faq.html index d08f039..e84e455 100644 --- a/libstdc++-v3/doc/html/faq.html +++ b/libstdc++-v3/doc/html/faq.html @@ -131,9 +131,8 @@ (<span class="command"><strong>gcc</strong></span>, <span class="command"><strong>g++</strong></span>, etc) is widely considered to be one of the leading compilers in the world. Its development is overseen by the - <a class="link" href="https://gcc.gnu.org/" target="_top">GCC team</a>. All of - the rapid development and near-legendary - <a class="link" href="https://gcc.gnu.org/buildstat.html" target="_top">portability</a> + <a class="link" href="https://gcc.gnu.org/" target="_top">GCC team</a>. + All of the rapid development and near-legendary portability that are the hallmarks of an open-source project are applied to libstdc++. </p><p> All of the standard classes and functions from C++98/C++03, C++11 and C++14 diff --git a/libstdc++-v3/doc/html/manual/test.html b/libstdc++-v3/doc/html/manual/test.html index b29c2eb..4b7f60c 100644 --- a/libstdc++-v3/doc/html/manual/test.html +++ b/libstdc++-v3/doc/html/manual/test.html @@ -139,10 +139,8 @@ cat 27_io/objects/char/3_xin.in | a.out</pre></dd><dt><span class="term"><code c output, and the executable output (if any) for each test. </p><p> Archives of test results for various versions and platforms are - available on the GCC website in the <a class="link" href="http://gcc.gnu.org/gcc-4.3/buildstat.html" target="_top">build - status</a> section of each individual release, and are also archived on a daily basis on the <a class="link" href="http://gcc.gnu.org/ml/gcc-testresults/current" target="_top">gcc-testresults</a> - mailing list. Please check either of these places for a similar + mailing list. Please check there for a similar combination of source version, operating system, and host CPU. </p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="test.run.variations"></a>Variations</h4></div></div></div><p> There are several options for running tests, including testing diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml index da41199..79edb02 100644 --- a/libstdc++-v3/doc/xml/faq.xml +++ b/libstdc++-v3/doc/xml/faq.xml @@ -64,9 +64,8 @@ (<command>gcc</command>, <command>g++</command>, etc) is widely considered to be one of the leading compilers in the world. Its development is overseen by the - <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/">GCC team</link>. All of - the rapid development and near-legendary - <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/buildstat.html">portability</link> + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://gcc.gnu.org/">GCC team</link>. + All of the rapid development and near-legendary portability that are the hallmarks of an open-source project are applied to libstdc++. </para> <para> diff --git a/libstdc++-v3/doc/xml/manual/test.xml b/libstdc++-v3/doc/xml/manual/test.xml index 936f974..f2c709b 100644 --- a/libstdc++-v3/doc/xml/manual/test.xml +++ b/libstdc++-v3/doc/xml/manual/test.xml @@ -266,10 +266,8 @@ cat 27_io/objects/char/3_xin.in | a.out</programlisting> <para> Archives of test results for various versions and platforms are - available on the GCC website in the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/gcc-4.3/buildstat.html">build - status</link> section of each individual release, and are also archived on a daily basis on the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://gcc.gnu.org/ml/gcc-testresults/current">gcc-testresults</link> - mailing list. Please check either of these places for a similar + mailing list. Please check there for a similar combination of source version, operating system, and host CPU. </para> </section> diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 7fa43d1..1ca2c5c 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -37,6 +37,7 @@ #include <bits/stl_iterator.h> #include <ext/numeric_traits.h> #include <bits/max_size_type.h> +#include <bits/version.h> #ifdef __cpp_lib_concepts namespace std _GLIBCXX_VISIBILITY(default) @@ -1056,8 +1057,13 @@ namespace ranges using borrowed_iterator_t = __conditional_t<borrowed_range<_Range>, iterator_t<_Range>, dangling>; - } // namespace ranges + +#if __glibcxx_ranges_to_container // C++ >= 23 + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // library concepts diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 1282af3..a9b8027 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -1119,14 +1119,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_is_constant_evaluated if (std::is_constant_evaluated()) { - // Can't use memmove. Wrap the pointer so that __relocate_a_1 + // Can't use memcpu. Wrap the pointer so that __relocate_a_1 // resolves to the non-trivial overload above. __gnu_cxx::__normal_iterator<_Tp*, void> __out(__result); __out = std::__relocate_a_1(__first, __last, __out, __alloc); return __out.base(); } #endif - __builtin_memmove(__result, __first, __count * sizeof(_Tp)); + __builtin_memcpy(__result, __first, __count * sizeof(_Tp)); } return __result + __count; } diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 5e18f6e..973f4d7 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1288,7 +1288,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_ASAN_ANNOTATE_GREW(1); } else - _M_realloc_insert(end(), __x); + _M_realloc_append(__x); } #if __cplusplus >= 201103L @@ -1822,6 +1822,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_realloc_insert(iterator __position, const value_type& __x); + + void + _M_realloc_append(const value_type& __x); #else // A value_type object constructed with _Alloc_traits::construct() // and destroyed with _Alloc_traits::destroy(). @@ -1871,6 +1874,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_realloc_insert(iterator __position, _Args&&... __args); + template<typename... _Args> + _GLIBCXX20_CONSTEXPR + void + _M_realloc_append(_Args&&... __args); + // Either move-construct at the end, or forward to _M_insert_aux. _GLIBCXX20_CONSTEXPR iterator diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 80631d1..0ccef79 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -120,7 +120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_ASAN_ANNOTATE_GREW(1); } else - _M_realloc_insert(end(), std::forward<_Args>(__args)...); + _M_realloc_append(std::forward<_Args>(__args)...); #if __cplusplus > 201402L return back(); #endif @@ -459,6 +459,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif { const size_type __len = _M_check_len(1u, "vector::_M_realloc_insert"); + if (__len <= 0) + __builtin_unreachable (); pointer __old_start = this->_M_impl._M_start; pointer __old_finish = this->_M_impl._M_finish; const size_type __elems_before = __position - begin(); @@ -571,6 +573,127 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_end_of_storage = __new_start + __len; } +#if __cplusplus >= 201103L + template<typename _Tp, typename _Alloc> + template<typename... _Args> + _GLIBCXX20_CONSTEXPR + void + vector<_Tp, _Alloc>:: + _M_realloc_append(_Args&&... __args) +#else + template<typename _Tp, typename _Alloc> + void + vector<_Tp, _Alloc>:: + _M_realloc_append(const _Tp& __x) +#endif + { + const size_type __len = _M_check_len(1u, "vector::_M_realloc_append"); + if (__len <= 0) + __builtin_unreachable (); + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __elems = end() - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + + // RAII guard for allocated storage. + struct _Guard + { + pointer _M_storage; // Storage to deallocate + size_type _M_len; + _Tp_alloc_type& _M_alloc; + + _GLIBCXX20_CONSTEXPR + _Guard(pointer __s, size_type __l, _Tp_alloc_type& __a) + : _M_storage(__s), _M_len(__l), _M_alloc(__a) + { } + + _GLIBCXX20_CONSTEXPR + ~_Guard() + { + if (_M_storage) + __gnu_cxx::__alloc_traits<_Tp_alloc_type>:: + deallocate(_M_alloc, _M_storage, _M_len); + } + + private: + _Guard(const _Guard&); + }; + + { + _Guard __guard(__new_start, __len, _M_impl); + + // The order of the three operations is dictated by the C++11 + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by lvalue ref (see last bullet of C++11 + // [res.on.arguments]). + + // If this throws, the existing elements are unchanged. +#if __cplusplus >= 201103L + _Alloc_traits::construct(this->_M_impl, + std::__to_address(__new_start + __elems), + std::forward<_Args>(__args)...); +#else + _Alloc_traits::construct(this->_M_impl, + __new_start + __elems, + __x); +#endif + +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + // Relocation cannot throw. + __new_finish = _S_relocate(__old_start, __old_finish, + __new_start, _M_get_Tp_allocator()); + ++__new_finish; + } + else +#endif + { + // RAII type to destroy initialized elements. + struct _Guard_elts + { + pointer _M_first, _M_last; // Elements to destroy + _Tp_alloc_type& _M_alloc; + + _GLIBCXX20_CONSTEXPR + _Guard_elts(pointer __elt, _Tp_alloc_type& __a) + : _M_first(__elt), _M_last(__elt + 1), _M_alloc(__a) + { } + + _GLIBCXX20_CONSTEXPR + ~_Guard_elts() + { std::_Destroy(_M_first, _M_last, _M_alloc); } + + private: + _Guard_elts(const _Guard_elts&); + }; + + // Guard the new element so it will be destroyed if anything throws. + _Guard_elts __guard_elts(__new_start + __elems, _M_impl); + + __new_finish = std::__uninitialized_move_if_noexcept_a( + __old_start, __old_finish, + __new_start, _M_get_Tp_allocator()); + + ++__new_finish; + + // New storage has been fully initialized, destroy the old elements. + __guard_elts._M_first = __old_start; + __guard_elts._M_last = __old_finish; + } + __guard._M_storage = __old_start; + __guard._M_len = this->_M_impl._M_end_of_storage - __old_start; + } + // deallocate should be called before assignments to _M_impl, + // to avoid call-clobbering + + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + template<typename _Tp, typename _Alloc> _GLIBCXX20_CONSTEXPR void diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 447fdeb..1407778 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -960,6 +960,11 @@ ftms = { ftms = { name = span; values = { + v = 202311; + cxxmin = 26; + extra_cond = "__glibcxx_concepts"; + }; + values = { v = 202002; cxxmin = 20; extra_cond = "__glibcxx_concepts"; @@ -1344,6 +1349,70 @@ ftms = { }; ftms = { + name = freestanding_algorithm; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { + name = freestanding_array; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { + name = freestanding_cstring; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { + name = freestanding_expected; + values = { + v = 202311; + cxxmin = 23; + // This is a C++26 feature, but we support it in C++23. + extra_cond = "__cpp_lib_expected"; + }; +}; + +ftms = { + name = freestanding_optional; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { + name = freestanding_string_view; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { + name = freestanding_variant; + values = { + v = 202311; + // This is a C++26 feature, but we support it in C++23. + cxxmin = 23; + }; +}; + +ftms = { name = invoke_r; values = { v = 202106; @@ -1370,19 +1439,21 @@ ftms = { }; }; -ftms = { - name = to_underlying; - values = { - v = 202102; - cxxmin = 23; - }; -}; +//ftms = { +// name = container_ranges; +// values = { +// v = 202202; +// cxxmin = 23; +// hosted = yes; +// }; +//}; ftms = { - name = unreachable; + name = ranges_to_container; values = { v = 202202; cxxmin = 23; + hosted = yes; }; }; @@ -1571,7 +1642,7 @@ ftms = { ftms = { name = out_ptr; values = { - v = 202106; + v = 202311; cxxmin = 23; }; }; @@ -1615,6 +1686,22 @@ ftms = { }; ftms = { + name = to_underlying; + values = { + v = 202102; + cxxmin = 23; + }; +}; + +ftms = { + name = unreachable; + values = { + v = 202202; + cxxmin = 23; + }; +}; + +ftms = { name = fstream_native_handle; values = { v = 202306; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 97c6d85..1fb1d14 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1173,7 +1173,12 @@ // from version.def line 961 #if !defined(__cpp_lib_span) -# if (__cplusplus >= 202002L) && (__glibcxx_concepts) +# if (__cplusplus > 202302L) && (__glibcxx_concepts) +# define __glibcxx_span 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_span) +# define __cpp_lib_span 202311L +# endif +# elif (__cplusplus >= 202002L) && (__glibcxx_concepts) # define __glibcxx_span 202002L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_span) # define __cpp_lib_span 202002L @@ -1182,7 +1187,7 @@ #endif /* !defined(__cpp_lib_span) && defined(__glibcxx_want_span) */ #undef __glibcxx_want_span -// from version.def line 970 +// from version.def line 975 #if !defined(__cpp_lib_ssize) # if (__cplusplus >= 202002L) # define __glibcxx_ssize 201902L @@ -1193,7 +1198,7 @@ #endif /* !defined(__cpp_lib_ssize) && defined(__glibcxx_want_ssize) */ #undef __glibcxx_want_ssize -// from version.def line 978 +// from version.def line 983 #if !defined(__cpp_lib_three_way_comparison) # if (__cplusplus >= 202002L) && (__cpp_impl_three_way_comparison >= 201907L && __glibcxx_concepts) # define __glibcxx_three_way_comparison 201907L @@ -1204,7 +1209,7 @@ #endif /* !defined(__cpp_lib_three_way_comparison) && defined(__glibcxx_want_three_way_comparison) */ #undef __glibcxx_want_three_way_comparison -// from version.def line 988 +// from version.def line 993 #if !defined(__cpp_lib_to_address) # if (__cplusplus >= 202002L) # define __glibcxx_to_address 201711L @@ -1215,7 +1220,7 @@ #endif /* !defined(__cpp_lib_to_address) && defined(__glibcxx_want_to_address) */ #undef __glibcxx_want_to_address -// from version.def line 996 +// from version.def line 1001 #if !defined(__cpp_lib_to_array) # if (__cplusplus >= 202002L) && (__cpp_generic_lambdas >= 201707L) # define __glibcxx_to_array 201907L @@ -1226,7 +1231,7 @@ #endif /* !defined(__cpp_lib_to_array) && defined(__glibcxx_want_to_array) */ #undef __glibcxx_want_to_array -// from version.def line 1005 +// from version.def line 1010 #if !defined(__cpp_lib_type_identity) # if (__cplusplus >= 202002L) # define __glibcxx_type_identity 201806L @@ -1237,7 +1242,7 @@ #endif /* !defined(__cpp_lib_type_identity) && defined(__glibcxx_want_type_identity) */ #undef __glibcxx_want_type_identity -// from version.def line 1013 +// from version.def line 1018 #if !defined(__cpp_lib_unwrap_ref) # if (__cplusplus >= 202002L) # define __glibcxx_unwrap_ref 201811L @@ -1248,7 +1253,7 @@ #endif /* !defined(__cpp_lib_unwrap_ref) && defined(__glibcxx_want_unwrap_ref) */ #undef __glibcxx_want_unwrap_ref -// from version.def line 1021 +// from version.def line 1026 #if !defined(__cpp_lib_constexpr_iterator) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_iterator 201811L @@ -1259,7 +1264,7 @@ #endif /* !defined(__cpp_lib_constexpr_iterator) && defined(__glibcxx_want_constexpr_iterator) */ #undef __glibcxx_want_constexpr_iterator -// from version.def line 1029 +// from version.def line 1034 #if !defined(__cpp_lib_interpolate) # if (__cplusplus >= 202002L) # define __glibcxx_interpolate 201902L @@ -1270,7 +1275,7 @@ #endif /* !defined(__cpp_lib_interpolate) && defined(__glibcxx_want_interpolate) */ #undef __glibcxx_want_interpolate -// from version.def line 1037 +// from version.def line 1042 #if !defined(__cpp_lib_constexpr_utility) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_utility 201811L @@ -1281,7 +1286,7 @@ #endif /* !defined(__cpp_lib_constexpr_utility) && defined(__glibcxx_want_constexpr_utility) */ #undef __glibcxx_want_constexpr_utility -// from version.def line 1045 +// from version.def line 1050 #if !defined(__cpp_lib_shift) # if (__cplusplus >= 202002L) # define __glibcxx_shift 201806L @@ -1292,7 +1297,7 @@ #endif /* !defined(__cpp_lib_shift) && defined(__glibcxx_want_shift) */ #undef __glibcxx_want_shift -// from version.def line 1053 +// from version.def line 1058 #if !defined(__cpp_lib_ranges) # if (__cplusplus >= 202100L) && (__glibcxx_concepts) # define __glibcxx_ranges 202211L @@ -1308,7 +1313,7 @@ #endif /* !defined(__cpp_lib_ranges) && defined(__glibcxx_want_ranges) */ #undef __glibcxx_want_ranges -// from version.def line 1067 +// from version.def line 1072 #if !defined(__cpp_lib_constexpr_numeric) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_numeric 201911L @@ -1319,7 +1324,7 @@ #endif /* !defined(__cpp_lib_constexpr_numeric) && defined(__glibcxx_want_constexpr_numeric) */ #undef __glibcxx_want_constexpr_numeric -// from version.def line 1075 +// from version.def line 1080 #if !defined(__cpp_lib_constexpr_functional) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_functional 201907L @@ -1330,7 +1335,7 @@ #endif /* !defined(__cpp_lib_constexpr_functional) && defined(__glibcxx_want_constexpr_functional) */ #undef __glibcxx_want_constexpr_functional -// from version.def line 1083 +// from version.def line 1088 #if !defined(__cpp_lib_constexpr_algorithms) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_algorithms 201806L @@ -1341,7 +1346,7 @@ #endif /* !defined(__cpp_lib_constexpr_algorithms) && defined(__glibcxx_want_constexpr_algorithms) */ #undef __glibcxx_want_constexpr_algorithms -// from version.def line 1091 +// from version.def line 1096 #if !defined(__cpp_lib_constexpr_tuple) # if (__cplusplus >= 202002L) # define __glibcxx_constexpr_tuple 201811L @@ -1352,7 +1357,7 @@ #endif /* !defined(__cpp_lib_constexpr_tuple) && defined(__glibcxx_want_constexpr_tuple) */ #undef __glibcxx_want_constexpr_tuple -// from version.def line 1099 +// from version.def line 1104 #if !defined(__cpp_lib_constexpr_memory) # if (__cplusplus >= 202100L) && (__cpp_constexpr_dynamic_alloc) # define __glibcxx_constexpr_memory 202202L @@ -1368,7 +1373,7 @@ #endif /* !defined(__cpp_lib_constexpr_memory) && defined(__glibcxx_want_constexpr_memory) */ #undef __glibcxx_want_constexpr_memory -// from version.def line 1112 +// from version.def line 1117 #if !defined(__cpp_lib_atomic_shared_ptr) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_atomic_shared_ptr 201711L @@ -1379,7 +1384,7 @@ #endif /* !defined(__cpp_lib_atomic_shared_ptr) && defined(__glibcxx_want_atomic_shared_ptr) */ #undef __glibcxx_want_atomic_shared_ptr -// from version.def line 1121 +// from version.def line 1126 #if !defined(__cpp_lib_atomic_wait) # if (__cplusplus >= 202002L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED # define __glibcxx_atomic_wait 201907L @@ -1395,7 +1400,7 @@ #endif /* !defined(__cpp_lib_atomic_wait) && defined(__glibcxx_want_atomic_wait) */ #undef __glibcxx_want_atomic_wait -// from version.def line 1139 +// from version.def line 1144 #if !defined(__cpp_lib_barrier) # if (__cplusplus >= 202002L) && (__cpp_aligned_new && __glibcxx_atomic_wait) # define __glibcxx_barrier 201907L @@ -1406,7 +1411,7 @@ #endif /* !defined(__cpp_lib_barrier) && defined(__glibcxx_want_barrier) */ #undef __glibcxx_want_barrier -// from version.def line 1156 +// from version.def line 1161 #if !defined(__cpp_lib_format) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_format 202106L @@ -1417,7 +1422,7 @@ #endif /* !defined(__cpp_lib_format) && defined(__glibcxx_want_format) */ #undef __glibcxx_want_format -// from version.def line 1169 +// from version.def line 1174 #if !defined(__cpp_lib_constexpr_complex) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_constexpr_complex 201711L @@ -1428,7 +1433,7 @@ #endif /* !defined(__cpp_lib_constexpr_complex) && defined(__glibcxx_want_constexpr_complex) */ #undef __glibcxx_want_constexpr_complex -// from version.def line 1178 +// from version.def line 1183 #if !defined(__cpp_lib_constexpr_dynamic_alloc) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_constexpr_dynamic_alloc 201907L @@ -1439,7 +1444,7 @@ #endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) && defined(__glibcxx_want_constexpr_dynamic_alloc) */ #undef __glibcxx_want_constexpr_dynamic_alloc -// from version.def line 1187 +// from version.def line 1192 #if !defined(__cpp_lib_constexpr_string) # if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED && (defined(__glibcxx_is_constant_evaluated)) # define __glibcxx_constexpr_string 201907L @@ -1460,7 +1465,7 @@ #endif /* !defined(__cpp_lib_constexpr_string) && defined(__glibcxx_want_constexpr_string) */ #undef __glibcxx_want_constexpr_string -// from version.def line 1211 +// from version.def line 1216 #if !defined(__cpp_lib_constexpr_vector) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_constexpr_vector 201907L @@ -1471,7 +1476,7 @@ #endif /* !defined(__cpp_lib_constexpr_vector) && defined(__glibcxx_want_constexpr_vector) */ #undef __glibcxx_want_constexpr_vector -// from version.def line 1220 +// from version.def line 1225 #if !defined(__cpp_lib_erase_if) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_erase_if 202002L @@ -1482,7 +1487,7 @@ #endif /* !defined(__cpp_lib_erase_if) && defined(__glibcxx_want_erase_if) */ #undef __glibcxx_want_erase_if -// from version.def line 1229 +// from version.def line 1234 #if !defined(__cpp_lib_generic_unordered_lookup) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_generic_unordered_lookup 201811L @@ -1493,7 +1498,7 @@ #endif /* !defined(__cpp_lib_generic_unordered_lookup) && defined(__glibcxx_want_generic_unordered_lookup) */ #undef __glibcxx_want_generic_unordered_lookup -// from version.def line 1238 +// from version.def line 1243 #if !defined(__cpp_lib_jthread) # if (__cplusplus >= 202002L) && defined(_GLIBCXX_HAS_GTHREADS) && _GLIBCXX_HOSTED # define __glibcxx_jthread 201911L @@ -1504,7 +1509,7 @@ #endif /* !defined(__cpp_lib_jthread) && defined(__glibcxx_want_jthread) */ #undef __glibcxx_want_jthread -// from version.def line 1248 +// from version.def line 1253 #if !defined(__cpp_lib_latch) # if (__cplusplus >= 202002L) && (__glibcxx_atomic_wait) # define __glibcxx_latch 201907L @@ -1515,7 +1520,7 @@ #endif /* !defined(__cpp_lib_latch) && defined(__glibcxx_want_latch) */ #undef __glibcxx_want_latch -// from version.def line 1257 +// from version.def line 1262 #if !defined(__cpp_lib_list_remove_return_type) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_list_remove_return_type 201806L @@ -1526,7 +1531,7 @@ #endif /* !defined(__cpp_lib_list_remove_return_type) && defined(__glibcxx_want_list_remove_return_type) */ #undef __glibcxx_want_list_remove_return_type -// from version.def line 1266 +// from version.def line 1271 #if !defined(__cpp_lib_polymorphic_allocator) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_polymorphic_allocator 201902L @@ -1537,7 +1542,7 @@ #endif /* !defined(__cpp_lib_polymorphic_allocator) && defined(__glibcxx_want_polymorphic_allocator) */ #undef __glibcxx_want_polymorphic_allocator -// from version.def line 1275 +// from version.def line 1280 #if !defined(__cpp_lib_move_iterator_concept) # if (__cplusplus >= 202002L) && (__glibcxx_concepts) # define __glibcxx_move_iterator_concept 202207L @@ -1548,7 +1553,7 @@ #endif /* !defined(__cpp_lib_move_iterator_concept) && defined(__glibcxx_want_move_iterator_concept) */ #undef __glibcxx_want_move_iterator_concept -// from version.def line 1285 +// from version.def line 1290 #if !defined(__cpp_lib_semaphore) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE) # define __glibcxx_semaphore 201907L @@ -1559,7 +1564,7 @@ #endif /* !defined(__cpp_lib_semaphore) && defined(__glibcxx_want_semaphore) */ #undef __glibcxx_want_semaphore -// from version.def line 1295 +// from version.def line 1300 #if !defined(__cpp_lib_smart_ptr_for_overwrite) # if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED # define __glibcxx_smart_ptr_for_overwrite 202002L @@ -1570,7 +1575,7 @@ #endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) && defined(__glibcxx_want_smart_ptr_for_overwrite) */ #undef __glibcxx_want_smart_ptr_for_overwrite -// from version.def line 1304 +// from version.def line 1309 #if !defined(__cpp_lib_syncbuf) # if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED # define __glibcxx_syncbuf 201803L @@ -1581,7 +1586,7 @@ #endif /* !defined(__cpp_lib_syncbuf) && defined(__glibcxx_want_syncbuf) */ #undef __glibcxx_want_syncbuf -// from version.def line 1314 +// from version.def line 1319 #if !defined(__cpp_lib_byteswap) # if (__cplusplus >= 202100L) # define __glibcxx_byteswap 202110L @@ -1592,7 +1597,7 @@ #endif /* !defined(__cpp_lib_byteswap) && defined(__glibcxx_want_byteswap) */ #undef __glibcxx_want_byteswap -// from version.def line 1322 +// from version.def line 1327 #if !defined(__cpp_lib_constexpr_charconv) # if (__cplusplus >= 202100L) # define __glibcxx_constexpr_charconv 202207L @@ -1603,7 +1608,7 @@ #endif /* !defined(__cpp_lib_constexpr_charconv) && defined(__glibcxx_want_constexpr_charconv) */ #undef __glibcxx_want_constexpr_charconv -// from version.def line 1330 +// from version.def line 1335 #if !defined(__cpp_lib_constexpr_typeinfo) # if (__cplusplus >= 202100L) # define __glibcxx_constexpr_typeinfo 202106L @@ -1614,7 +1619,7 @@ #endif /* !defined(__cpp_lib_constexpr_typeinfo) && defined(__glibcxx_want_constexpr_typeinfo) */ #undef __glibcxx_want_constexpr_typeinfo -// from version.def line 1338 +// from version.def line 1343 #if !defined(__cpp_lib_expected) # if (__cplusplus >= 202100L) && (__cpp_concepts >= 202002L) # define __glibcxx_expected 202211L @@ -1625,7 +1630,84 @@ #endif /* !defined(__cpp_lib_expected) && defined(__glibcxx_want_expected) */ #undef __glibcxx_want_expected -// from version.def line 1347 +// from version.def line 1352 +#if !defined(__cpp_lib_freestanding_algorithm) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_algorithm 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_algorithm) +# define __cpp_lib_freestanding_algorithm 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_algorithm) && defined(__glibcxx_want_freestanding_algorithm) */ +#undef __glibcxx_want_freestanding_algorithm + +// from version.def line 1361 +#if !defined(__cpp_lib_freestanding_array) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_array 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_array) +# define __cpp_lib_freestanding_array 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_array) && defined(__glibcxx_want_freestanding_array) */ +#undef __glibcxx_want_freestanding_array + +// from version.def line 1370 +#if !defined(__cpp_lib_freestanding_cstring) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_cstring 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_cstring) +# define __cpp_lib_freestanding_cstring 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_cstring) && defined(__glibcxx_want_freestanding_cstring) */ +#undef __glibcxx_want_freestanding_cstring + +// from version.def line 1379 +#if !defined(__cpp_lib_freestanding_expected) +# if (__cplusplus >= 202100L) && (__cpp_lib_expected) +# define __glibcxx_freestanding_expected 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_expected) +# define __cpp_lib_freestanding_expected 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_expected) && defined(__glibcxx_want_freestanding_expected) */ +#undef __glibcxx_want_freestanding_expected + +// from version.def line 1389 +#if !defined(__cpp_lib_freestanding_optional) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_optional 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_optional) +# define __cpp_lib_freestanding_optional 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_optional) && defined(__glibcxx_want_freestanding_optional) */ +#undef __glibcxx_want_freestanding_optional + +// from version.def line 1398 +#if !defined(__cpp_lib_freestanding_string_view) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_string_view 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_string_view) +# define __cpp_lib_freestanding_string_view 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_string_view) && defined(__glibcxx_want_freestanding_string_view) */ +#undef __glibcxx_want_freestanding_string_view + +// from version.def line 1407 +#if !defined(__cpp_lib_freestanding_variant) +# if (__cplusplus >= 202100L) +# define __glibcxx_freestanding_variant 202311L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_freestanding_variant) +# define __cpp_lib_freestanding_variant 202311L +# endif +# endif +#endif /* !defined(__cpp_lib_freestanding_variant) && defined(__glibcxx_want_freestanding_variant) */ +#undef __glibcxx_want_freestanding_variant + +// from version.def line 1416 #if !defined(__cpp_lib_invoke_r) # if (__cplusplus >= 202100L) # define __glibcxx_invoke_r 202106L @@ -1636,7 +1718,7 @@ #endif /* !defined(__cpp_lib_invoke_r) && defined(__glibcxx_want_invoke_r) */ #undef __glibcxx_want_invoke_r -// from version.def line 1355 +// from version.def line 1424 #if !defined(__cpp_lib_is_scoped_enum) # if (__cplusplus >= 202100L) # define __glibcxx_is_scoped_enum 202011L @@ -1647,7 +1729,7 @@ #endif /* !defined(__cpp_lib_is_scoped_enum) && defined(__glibcxx_want_is_scoped_enum) */ #undef __glibcxx_want_is_scoped_enum -// from version.def line 1363 +// from version.def line 1432 #if !defined(__cpp_lib_reference_from_temporary) # if (__cplusplus >= 202100L) && (__has_builtin(__reference_constructs_from_temporary) && __has_builtin(__reference_converts_from_temporary)) # define __glibcxx_reference_from_temporary 202202L @@ -1658,29 +1740,18 @@ #endif /* !defined(__cpp_lib_reference_from_temporary) && defined(__glibcxx_want_reference_from_temporary) */ #undef __glibcxx_want_reference_from_temporary -// from version.def line 1374 -#if !defined(__cpp_lib_to_underlying) -# if (__cplusplus >= 202100L) -# define __glibcxx_to_underlying 202102L -# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_underlying) -# define __cpp_lib_to_underlying 202102L -# endif -# endif -#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ -#undef __glibcxx_want_to_underlying - -// from version.def line 1382 -#if !defined(__cpp_lib_unreachable) -# if (__cplusplus >= 202100L) -# define __glibcxx_unreachable 202202L -# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unreachable) -# define __cpp_lib_unreachable 202202L +// from version.def line 1452 +#if !defined(__cpp_lib_ranges_to_container) +# if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED +# define __glibcxx_ranges_to_container 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_to_container) +# define __cpp_lib_ranges_to_container 202202L # endif # endif -#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ -#undef __glibcxx_want_unreachable +#endif /* !defined(__cpp_lib_ranges_to_container) && defined(__glibcxx_want_ranges_to_container) */ +#undef __glibcxx_want_ranges_to_container -// from version.def line 1390 +// from version.def line 1461 #if !defined(__cpp_lib_ranges_zip) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_zip 202110L @@ -1691,7 +1762,7 @@ #endif /* !defined(__cpp_lib_ranges_zip) && defined(__glibcxx_want_ranges_zip) */ #undef __glibcxx_want_ranges_zip -// from version.def line 1398 +// from version.def line 1469 #if !defined(__cpp_lib_ranges_chunk) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_chunk 202202L @@ -1702,7 +1773,7 @@ #endif /* !defined(__cpp_lib_ranges_chunk) && defined(__glibcxx_want_ranges_chunk) */ #undef __glibcxx_want_ranges_chunk -// from version.def line 1406 +// from version.def line 1477 #if !defined(__cpp_lib_ranges_slide) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_slide 202202L @@ -1713,7 +1784,7 @@ #endif /* !defined(__cpp_lib_ranges_slide) && defined(__glibcxx_want_ranges_slide) */ #undef __glibcxx_want_ranges_slide -// from version.def line 1414 +// from version.def line 1485 #if !defined(__cpp_lib_ranges_chunk_by) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_chunk_by 202202L @@ -1724,7 +1795,7 @@ #endif /* !defined(__cpp_lib_ranges_chunk_by) && defined(__glibcxx_want_ranges_chunk_by) */ #undef __glibcxx_want_ranges_chunk_by -// from version.def line 1422 +// from version.def line 1493 #if !defined(__cpp_lib_ranges_join_with) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_join_with 202202L @@ -1735,7 +1806,7 @@ #endif /* !defined(__cpp_lib_ranges_join_with) && defined(__glibcxx_want_ranges_join_with) */ #undef __glibcxx_want_ranges_join_with -// from version.def line 1430 +// from version.def line 1501 #if !defined(__cpp_lib_ranges_repeat) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_repeat 202207L @@ -1746,7 +1817,7 @@ #endif /* !defined(__cpp_lib_ranges_repeat) && defined(__glibcxx_want_ranges_repeat) */ #undef __glibcxx_want_ranges_repeat -// from version.def line 1438 +// from version.def line 1509 #if !defined(__cpp_lib_ranges_stride) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_stride 202207L @@ -1757,7 +1828,7 @@ #endif /* !defined(__cpp_lib_ranges_stride) && defined(__glibcxx_want_ranges_stride) */ #undef __glibcxx_want_ranges_stride -// from version.def line 1446 +// from version.def line 1517 #if !defined(__cpp_lib_ranges_cartesian_product) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_cartesian_product 202207L @@ -1768,7 +1839,7 @@ #endif /* !defined(__cpp_lib_ranges_cartesian_product) && defined(__glibcxx_want_ranges_cartesian_product) */ #undef __glibcxx_want_ranges_cartesian_product -// from version.def line 1454 +// from version.def line 1525 #if !defined(__cpp_lib_ranges_as_rvalue) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_as_rvalue 202207L @@ -1779,7 +1850,7 @@ #endif /* !defined(__cpp_lib_ranges_as_rvalue) && defined(__glibcxx_want_ranges_as_rvalue) */ #undef __glibcxx_want_ranges_as_rvalue -// from version.def line 1462 +// from version.def line 1533 #if !defined(__cpp_lib_ranges_as_const) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_as_const 202207L @@ -1790,7 +1861,7 @@ #endif /* !defined(__cpp_lib_ranges_as_const) && defined(__glibcxx_want_ranges_as_const) */ #undef __glibcxx_want_ranges_as_const -// from version.def line 1470 +// from version.def line 1541 #if !defined(__cpp_lib_ranges_enumerate) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_enumerate 202302L @@ -1801,7 +1872,7 @@ #endif /* !defined(__cpp_lib_ranges_enumerate) && defined(__glibcxx_want_ranges_enumerate) */ #undef __glibcxx_want_ranges_enumerate -// from version.def line 1478 +// from version.def line 1549 #if !defined(__cpp_lib_ranges_fold) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_fold 202207L @@ -1812,7 +1883,7 @@ #endif /* !defined(__cpp_lib_ranges_fold) && defined(__glibcxx_want_ranges_fold) */ #undef __glibcxx_want_ranges_fold -// from version.def line 1486 +// from version.def line 1557 #if !defined(__cpp_lib_ranges_contains) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_contains 202207L @@ -1823,7 +1894,7 @@ #endif /* !defined(__cpp_lib_ranges_contains) && defined(__glibcxx_want_ranges_contains) */ #undef __glibcxx_want_ranges_contains -// from version.def line 1494 +// from version.def line 1565 #if !defined(__cpp_lib_ranges_iota) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_iota 202202L @@ -1834,7 +1905,7 @@ #endif /* !defined(__cpp_lib_ranges_iota) && defined(__glibcxx_want_ranges_iota) */ #undef __glibcxx_want_ranges_iota -// from version.def line 1502 +// from version.def line 1573 #if !defined(__cpp_lib_ranges_find_last) # if (__cplusplus >= 202100L) # define __glibcxx_ranges_find_last 202207L @@ -1845,7 +1916,7 @@ #endif /* !defined(__cpp_lib_ranges_find_last) && defined(__glibcxx_want_ranges_find_last) */ #undef __glibcxx_want_ranges_find_last -// from version.def line 1510 +// from version.def line 1581 #if !defined(__cpp_lib_constexpr_bitset) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__cpp_constexpr_dynamic_alloc) # define __glibcxx_constexpr_bitset 202202L @@ -1856,7 +1927,7 @@ #endif /* !defined(__cpp_lib_constexpr_bitset) && defined(__glibcxx_want_constexpr_bitset) */ #undef __glibcxx_want_constexpr_bitset -// from version.def line 1520 +// from version.def line 1591 #if !defined(__cpp_lib_stdatomic_h) # if (__cplusplus >= 202100L) # define __glibcxx_stdatomic_h 202011L @@ -1867,7 +1938,7 @@ #endif /* !defined(__cpp_lib_stdatomic_h) && defined(__glibcxx_want_stdatomic_h) */ #undef __glibcxx_want_stdatomic_h -// from version.def line 1528 +// from version.def line 1599 #if !defined(__cpp_lib_adaptor_iterator_pair_constructor) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_adaptor_iterator_pair_constructor 202106L @@ -1878,7 +1949,7 @@ #endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) && defined(__glibcxx_want_adaptor_iterator_pair_constructor) */ #undef __glibcxx_want_adaptor_iterator_pair_constructor -// from version.def line 1537 +// from version.def line 1608 #if !defined(__cpp_lib_formatters) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_formatters 202302L @@ -1889,7 +1960,7 @@ #endif /* !defined(__cpp_lib_formatters) && defined(__glibcxx_want_formatters) */ #undef __glibcxx_want_formatters -// from version.def line 1546 +// from version.def line 1617 #if !defined(__cpp_lib_forward_like) # if (__cplusplus >= 202100L) # define __glibcxx_forward_like 202207L @@ -1900,7 +1971,7 @@ #endif /* !defined(__cpp_lib_forward_like) && defined(__glibcxx_want_forward_like) */ #undef __glibcxx_want_forward_like -// from version.def line 1554 +// from version.def line 1625 #if !defined(__cpp_lib_ios_noreplace) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_ios_noreplace 202207L @@ -1911,7 +1982,7 @@ #endif /* !defined(__cpp_lib_ios_noreplace) && defined(__glibcxx_want_ios_noreplace) */ #undef __glibcxx_want_ios_noreplace -// from version.def line 1563 +// from version.def line 1634 #if !defined(__cpp_lib_move_only_function) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_move_only_function 202110L @@ -1922,18 +1993,18 @@ #endif /* !defined(__cpp_lib_move_only_function) && defined(__glibcxx_want_move_only_function) */ #undef __glibcxx_want_move_only_function -// from version.def line 1572 +// from version.def line 1643 #if !defined(__cpp_lib_out_ptr) # if (__cplusplus >= 202100L) -# define __glibcxx_out_ptr 202106L +# define __glibcxx_out_ptr 202311L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_out_ptr) -# define __cpp_lib_out_ptr 202106L +# define __cpp_lib_out_ptr 202311L # endif # endif #endif /* !defined(__cpp_lib_out_ptr) && defined(__glibcxx_want_out_ptr) */ #undef __glibcxx_want_out_ptr -// from version.def line 1580 +// from version.def line 1651 #if !defined(__cpp_lib_spanstream) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__glibcxx_span) # define __glibcxx_spanstream 202106L @@ -1944,7 +2015,7 @@ #endif /* !defined(__cpp_lib_spanstream) && defined(__glibcxx_want_spanstream) */ #undef __glibcxx_want_spanstream -// from version.def line 1590 +// from version.def line 1661 #if !defined(__cpp_lib_stacktrace) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (_GLIBCXX_HAVE_STACKTRACE) # define __glibcxx_stacktrace 202011L @@ -1955,7 +2026,7 @@ #endif /* !defined(__cpp_lib_stacktrace) && defined(__glibcxx_want_stacktrace) */ #undef __glibcxx_want_stacktrace -// from version.def line 1600 +// from version.def line 1671 #if !defined(__cpp_lib_string_contains) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_string_contains 202011L @@ -1966,7 +2037,7 @@ #endif /* !defined(__cpp_lib_string_contains) && defined(__glibcxx_want_string_contains) */ #undef __glibcxx_want_string_contains -// from version.def line 1609 +// from version.def line 1680 #if !defined(__cpp_lib_string_resize_and_overwrite) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_string_resize_and_overwrite 202110L @@ -1977,7 +2048,29 @@ #endif /* !defined(__cpp_lib_string_resize_and_overwrite) && defined(__glibcxx_want_string_resize_and_overwrite) */ #undef __glibcxx_want_string_resize_and_overwrite -// from version.def line 1618 +// from version.def line 1689 +#if !defined(__cpp_lib_to_underlying) +# if (__cplusplus >= 202100L) +# define __glibcxx_to_underlying 202102L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_to_underlying) +# define __cpp_lib_to_underlying 202102L +# endif +# endif +#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ +#undef __glibcxx_want_to_underlying + +// from version.def line 1697 +#if !defined(__cpp_lib_unreachable) +# if (__cplusplus >= 202100L) +# define __glibcxx_unreachable 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_unreachable) +# define __cpp_lib_unreachable 202202L +# endif +# endif +#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ +#undef __glibcxx_want_unreachable + +// from version.def line 1705 #if !defined(__cpp_lib_fstream_native_handle) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED # define __glibcxx_fstream_native_handle 202306L @@ -1988,7 +2081,7 @@ #endif /* !defined(__cpp_lib_fstream_native_handle) && defined(__glibcxx_want_fstream_native_handle) */ #undef __glibcxx_want_fstream_native_handle -// from version.def line 1627 +// from version.def line 1714 #if !defined(__cpp_lib_ratio) # if (__cplusplus > 202302L) # define __glibcxx_ratio 202306L @@ -1999,7 +2092,7 @@ #endif /* !defined(__cpp_lib_ratio) && defined(__glibcxx_want_ratio) */ #undef __glibcxx_want_ratio -// from version.def line 1635 +// from version.def line 1722 #if !defined(__cpp_lib_saturation_arithmetic) # if (__cplusplus > 202302L) # define __glibcxx_saturation_arithmetic 202311L @@ -2010,7 +2103,7 @@ #endif /* !defined(__cpp_lib_saturation_arithmetic) && defined(__glibcxx_want_saturation_arithmetic) */ #undef __glibcxx_want_saturation_arithmetic -// from version.def line 1643 +// from version.def line 1730 #if !defined(__cpp_lib_to_string) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED && (__glibcxx_to_chars) # define __glibcxx_to_string 202306L diff --git a/libstdc++-v3/include/c_compatibility/string.h b/libstdc++-v3/include/c_compatibility/string.h index 1d9e0d2..06529af 100644 --- a/libstdc++-v3/include/c_compatibility/string.h +++ b/libstdc++-v3/include/c_compatibility/string.h @@ -50,7 +50,9 @@ using std::strpbrk; using std::strrchr; using std::strspn; using std::strstr; +#if _GLIBCXX_HOSTED || __cplusplus <= 202302L using std::strtok; +#endif using std::memset; using std::strerror; using std::strlen; diff --git a/libstdc++-v3/include/c_global/cstring b/libstdc++-v3/include/c_global/cstring index d0a129a..f39aae1 100644 --- a/libstdc++-v3/include/c_global/cstring +++ b/libstdc++-v3/include/c_global/cstring @@ -38,7 +38,8 @@ #pragma GCC system_header -#include <bits/c++config.h> +#define __glibcxx_want_freestanding_cstring +#include <bits/version.h> #include <string.h> #ifndef _GLIBCXX_CSTRING @@ -90,7 +91,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using ::strncmp; using ::strncpy; using ::strspn; +#if _GLIBCXX_HOSTED || __cplusplus <= 202302L using ::strtok; +#endif using ::strxfrm; using ::strchr; using ::strpbrk; diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm index d7fab41..40aff50 100644 --- a/libstdc++-v3/include/std/algorithm +++ b/libstdc++-v3/include/std/algorithm @@ -65,6 +65,7 @@ #define __glibcxx_want_clamp #define __glibcxx_want_constexpr_algorithms +#define __glibcxx_want_freestanding_algorithm #define __glibcxx_want_parallel_algorithm #define __glibcxx_want_ranges_contains #define __glibcxx_want_ranges_find_last diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index d34ec5c..ddc15b6 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -46,6 +46,7 @@ #include <debug/assertions.h> #define __glibcxx_want_array_constexpr +#define __glibcxx_want_freestanding_array #define __glibcxx_want_nonmember_container_access #define __glibcxx_want_to_array #include <bits/version.h> diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index a176d4c..86026c3 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -32,6 +32,7 @@ #pragma GCC system_header #define __glibcxx_want_expected +#define __glibcxx_want_freestanding_expected #include <bits/version.h> #ifdef __cpp_lib_expected // C++ >= 23 && __cpp_concepts >= 202002L diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index a8c9771..937486f 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -32,6 +32,7 @@ #pragma GCC system_header +#define __glibcxx_want_freestanding_optional #define __glibcxx_want_optional #include <bits/version.h> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 26d6c01..63bea86 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -64,6 +64,7 @@ #define __glibcxx_want_ranges_repeat #define __glibcxx_want_ranges_slide #define __glibcxx_want_ranges_stride +#define __glibcxx_want_ranges_to_container #define __glibcxx_want_ranges_zip #include <bits/version.h> @@ -9213,8 +9214,366 @@ namespace views::__adaptor namespace views = ranges::views; +#if __cpp_lib_ranges_to_container // C++ >= 23 +namespace ranges +{ +/// @cond undocumented +namespace __detail +{ + template<typename _Container> + constexpr bool __reservable_container + = sized_range<_Container> + && requires(_Container& __c, range_size_t<_Container> __n) { + __c.reserve(__n); + { __c.capacity() } -> same_as<decltype(__n)>; + { __c.max_size() } -> same_as<decltype(__n)>; + }; + + template<typename _Container, typename _Ref> + constexpr bool __container_insertable + = requires(_Container& __c, _Ref&& __ref) { + typename _Container::value_type; + requires ( + requires { __c.push_back(std::forward<_Ref>(__ref)); } + || requires { __c.insert(__c.end(), std::forward<_Ref>(__ref)); } + ); + }; + + template<typename _Ref, typename _Container> + constexpr auto + __container_inserter(_Container& __c) + { + if constexpr (requires { __c.push_back(std::declval<_Ref>()); }) + return std::back_inserter(__c); + else + return std::inserter(__c, __c.end()); + } + + template<typename _Cont, typename _Range> + constexpr bool __toable = requires { + requires (!input_range<_Range> + || convertible_to<range_reference_t<_Range>, + range_value_t<_Cont>>); + }; +} // namespace __detail +/// @endcond + + /// Convert a range to a container. + /** + * @tparam _Cont A container type. + * @param __r A range that models the `input_range` concept. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This function converts a range to the `_Cont` type. + * + * For example, `std::ranges::to<std::vector<int>>(some_view)` + * will convert the view to `std::vector<int>`. + * + * Additional constructor arguments for the container can be supplied after + * the input range argument, e.g. + * `std::ranges::to<std::vector<int, Alloc<int>>>(a_range, an_allocator)`. + */ + template<typename _Cont, input_range _Rg, typename... _Args> + requires (!view<_Cont>) + constexpr _Cont + to [[nodiscard]] (_Rg&& __r, _Args&&... __args) + { + static_assert(!is_const_v<_Cont> && !is_volatile_v<_Cont>); + static_assert(is_class_v<_Cont>); + + if constexpr (__detail::__toable<_Cont, _Rg>) + { + if constexpr (constructible_from<_Cont, _Rg, _Args...>) + return _Cont(std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (constructible_from<_Cont, from_range_t, _Rg, _Args...>) + return _Cont(from_range, std::forward<_Rg>(__r), + std::forward<_Args>(__args)...); + else if constexpr (requires { common_range<_Rg>; + typename __iter_category_t<iterator_t<_Rg>>; + requires derived_from<__iter_category_t<iterator_t<_Rg>>, + input_iterator_tag>; + requires constructible_from<_Cont, iterator_t<_Rg>, + sentinel_t<_Rg>, _Args...>; + }) + return _Cont(ranges::begin(__r), ranges::end(__r), + std::forward<_Args>(__args)...); + else + { + using __detail::__container_insertable; + using __detail::__reservable_container; + using _RefT = range_reference_t<_Rg>; + static_assert(constructible_from<_Cont, _Args...>); + static_assert(__container_insertable<_Cont, _RefT>); + _Cont __c(std::forward<_Args>(__args)...); + if constexpr (sized_range<_Rg> && __reservable_container<_Cont>) + __c.reserve(static_cast<range_size_t<_Cont>>(ranges::size(__r))); + auto __ins = __detail::__container_inserter<_RefT>(__c); + for (auto&& __e : __r) + *__ins++ = std::forward<decltype(__e)>(__e); + return __c; + } + } + else + { + static_assert(input_range<range_reference_t<_Rg>>); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3984. ranges::to's recursion branch may be ill-formed + return ranges::to<_Cont>(ref_view(__r) | views::transform( + []<typename _Elt>(_Elt&& __elem) { + using _ValT = range_value_t<_Cont>; + return ranges::to<_ValT>(std::forward<_Elt>(__elem)); + }), std::forward<_Args>(__args)...); + } + } + +/// @cond undocumented +namespace __detail +{ + template<typename _Rg> + struct _InputIter + { + using iterator_category = input_iterator_tag; + using value_type = range_value_t<_Rg>; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t<range_reference_t<_Rg>>; + using reference = range_reference_t<_Rg>; + reference operator*() const; + pointer operator->() const; + _InputIter& operator++(); + _InputIter operator++(int); + bool operator==(const _InputIter&) const; + }; + +#if 0 + template<template<typename...> typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_1 = requires { + _Cont(std::declval<_Rg>(), std::declval<_Args>()...); + }; + + template<template<typename...> typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_2 = requires { + _Cont(from_range, std::declval<_Rg>(), std::declval<_Args>()...); + }; + + template<template<typename...> typename _Cont, typename _Rg, + typename... _Args> + concept __deduce_expr_3 = requires(_InputIter<_Rg> __i) { + _Cont(std::move(__i), std::move(__i), std::declval<_Args>()...); + }; +#endif + + template<template<typename...> typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr1 + = decltype(_Cont(std::declval<_Rg>(), std::declval<_Args>()...)); + + template<template<typename...> typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr2 + = decltype(_Cont(from_range, std::declval<_Rg>(), + std::declval<_Args>()...)); + + template<template<typename...> typename _Cont, input_range _Rg, + typename... _Args> + using _DeduceExpr3 + = decltype(_Cont(std::declval<_InputIter<_Rg>>(), + std::declval<_InputIter<_Rg>>(), + std::declval<_Args>()...)); + +} // namespace __detail +/// @endcond + + template<template<typename...> typename _Cont, input_range _Rg, + typename... _Args> + constexpr auto + to [[nodiscard]] (_Rg&& __r, _Args&&... __args) + { + using __detail::_DeduceExpr1; + using __detail::_DeduceExpr2; + using __detail::_DeduceExpr3; + if constexpr (requires { typename _DeduceExpr1<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr1<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr2<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr2<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else if constexpr (requires { typename _DeduceExpr3<_Cont, _Rg, _Args...>; }) + return ranges::to<_DeduceExpr3<_Cont, _Rg, _Args...>>( + std::forward<_Rg>(__r), std::forward<_Args>(__args)...); + else + static_assert(false); // Cannot deduce container specialization. + } + +/// @cond undocumented +namespace __detail +{ + template<typename _Cont, typename... _Args> + class _ToClosure + : public views::__adaptor::_RangeAdaptorClosure<_ToClosure<_Cont, _Args...>> + { + tuple<decay_t<_Args>...> _M_bound_args; + + public: + _ToClosure(_Args&&... __args) + : _M_bound_args(std::forward<_Args>(__args)...) + { } + + // TODO: use explicit object functions ("deducing this"). + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) & + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) const & + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) && + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) const && + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + }; +} // namespace __detail +/// @endcond + + /// ranges::to adaptor for converting a range to a container type + /** + * @tparam _Cont A container type. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This range adaptor returns a range adaptor closure object that converts + * a range to the `_Cont` type. + * + * For example, `some_view | std::ranges::to<std::vector<int>>()` + * will convert the view to `std::vector<int>`. + * + * Additional constructor arguments for the container can be supplied, e.g. + * `r | std::ranges::to<std::vector<int, Alloc<int>>>(an_allocator)`. + */ + template<typename _Cont, typename... _Args> + requires (!view<_Cont>) + constexpr __detail::_ToClosure<_Cont, _Args...> + to [[nodiscard]] (_Args&&... __args) + { return {std::forward<_Args>(__args)...}; } + +/// @cond undocumented +namespace __detail +{ + template<template<typename...> typename _Cont, typename... _Args> + class _ToClosure2 + : public views::__adaptor::_RangeAdaptorClosure<_ToClosure2<_Cont, _Args...>> + { + tuple<decay_t<_Args>...> _M_bound_args; + + public: + _ToClosure2(_Args&&... __args) + : _M_bound_args(std::forward<_Args>(__args)...) + { } + + // TODO: use explicit object functions ("deducing this"). + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) & + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) const & + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, _M_bound_args); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) && + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + + template<typename _Rg> + constexpr auto + operator()(_Rg&& __r) const && + { + return std::apply([&__r]<typename... _Tp>(_Tp&&... __args) { + return ranges::to<_Cont>(std::forward<_Rg>(__r), + std::forward<_Tp>(__args)...); + }, std::move(_M_bound_args)); + } + }; +} // namespace __detail +/// @endcond + + /// ranges::to adaptor for converting a range to a deduced container type. + /** + * @tparam _Cont A container template. + * @param __args... Arguments to pass to the container constructor. + * @since C++23 + * + * This range adaptor returns a range adaptor closure object that converts + * a range to a specialization of the `_Cont` class template. The specific + * specialization of `_Cont` to be used is deduced automatically. + * + * For example, `some_view | std::ranges::to<std::vector>(Alloc<int>{})` + * will convert the view to `std::vector<T, Alloc<T>>`, where `T` is the + * view's value type, i.e. `std::ranges::range_value_t<decltype(some_view)>`. + * + * Additional constructor arguments for the container can be supplied, e.g. + * `r | std::ranges::to<std::vector>(an_allocator)`. + */ + template<template<typename...> typename _Cont, typename... _Args> + constexpr __detail::_ToClosure2<_Cont, _Args...> + to [[nodiscard]] (_Args&&... __args) + { return {std::forward<_Args>(__args)...}; } + +} // namespace ranges +#endif // __cpp_lib_ranges_to_container + _GLIBCXX_END_NAMESPACE_VERSION -} // namespace +} // namespace std #endif // library concepts #endif // C++2a #endif /* _GLIBCXX_RANGES */ diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 90d08f1..57222a5 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -288,6 +288,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } [[nodiscard]] + constexpr reference + at(size_type __idx) const + { + if (__idx >= size()) + __throw_out_of_range_fmt(__N("span::at(%zu) out-of-range for span " + "of size %zu"), __idx, this->size()); + return *(this->_M_ptr + __idx); + } + + [[nodiscard]] constexpr pointer data() const noexcept { return this->_M_ptr; } diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index cbb6bb0..44d13b4 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -36,8 +36,9 @@ #pragma GCC system_header #define __glibcxx_want_constexpr_char_traits -#define __glibcxx_want_string_view #define __glibcxx_want_constexpr_string_view +#define __glibcxx_want_freestanding_string_view +#define __glibcxx_want_string_view #define __glibcxx_want_starts_ends_with #define __glibcxx_want_string_contains #include <bits/version.h> diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 7f24e76..36bb37c 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -31,6 +31,7 @@ #pragma GCC system_header +#define __glibcxx_want_freestanding_variant #define __glibcxx_want_variant #include <bits/version.h> diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset index dd2845b..ffdce82 100644 --- a/libstdc++-v3/include/tr2/dynamic_bitset +++ b/libstdc++-v3/include/tr2/dynamic_bitset @@ -622,7 +622,7 @@ namespace tr2 // Watch for npos. this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n); this->resize(this->_M_Nb); - this->_M_copy_from_string(__str, __pos, __n); + this->_M_copy_from_string(__str, __pos, __n, __zero, __one); } /** diff --git a/libstdc++-v3/testsuite/20_util/expected/version.cc b/libstdc++-v3/testsuite/20_util/expected/version.cc index 6deaa68..682835c 100644 --- a/libstdc++-v3/testsuite/20_util/expected/version.cc +++ b/libstdc++-v3/testsuite/20_util/expected/version.cc @@ -8,3 +8,25 @@ #elif __cpp_lib_expected != 202211L # error "Feature-test macro for expected has wrong value in <version>" #endif + +#ifndef __cpp_lib_freestanding_expected +# error "Feature-test macro for freestanding expected missing in <version>" +#elif __cpp_lib_freestanding_expected != 202311L +# error "Feature-test macro for freestanding expected has wrong value in <version>" +#endif + +#undef __cpp_lib_expected +#undef __cpp_lib_freestanding_expected +#include <expected> + +#ifndef __cpp_lib_expected +# error "Feature-test macro for expected missing in <expected>" +#elif __cpp_lib_expected != 202211L +# error "Feature-test macro for expected has wrong value in <expected>" +#endif + +#ifndef __cpp_lib_freestanding_expected +# error "Feature-test macro for freestanding expected missing in <expected>" +#elif __cpp_lib_freestanding_expected != 202311L +# error "Feature-test macro for freestanding expected has wrong value in <expected>" +#endif diff --git a/libstdc++-v3/testsuite/20_util/optional/version.cc b/libstdc++-v3/testsuite/20_util/optional/version.cc index 7e63d42..657a399 100644 --- a/libstdc++-v3/testsuite/20_util/optional/version.cc +++ b/libstdc++-v3/testsuite/20_util/optional/version.cc @@ -12,3 +12,23 @@ #elif __cplusplus > 202002L && __cpp_lib_optional != 202110L # error "Feature test macro for optional has wrong value for C++23 in <version>" #endif + +#if __cplusplus >= 202302L +#ifndef __cpp_lib_freestanding_optional +# error "Feature test macro for freestanding std::optional is missing in <version>" +#elif __cpp_lib_freestanding_optional < 202311L +# error "Feature test macro for freestanding std::optional has wrong value in <version>" +#endif +#endif + +#undef __cpp_lib_optional +#undef __cpp_lib_freestanding_optional +#include <optional> + +#if __cplusplus >= 202302L +#ifndef __cpp_lib_freestanding_optional +# error "Feature test macro for freestanding std::optional is missing in <optional>" +#elif __cpp_lib_freestanding_optional < 202311L +# error "Feature test macro for freestanding std::optional has wrong value in <optional>" +#endif +#endif diff --git a/libstdc++-v3/testsuite/20_util/variant/version.cc b/libstdc++-v3/testsuite/20_util/variant/version.cc index fd251dd..f798532 100644 --- a/libstdc++-v3/testsuite/20_util/variant/version.cc +++ b/libstdc++-v3/testsuite/20_util/variant/version.cc @@ -10,3 +10,23 @@ #elif __cplusplus >= 202002L && __cpp_lib_variant < 202106L # error "Feature test macro for variant has wrong value for C++20 in <version>" #endif + +#if __cplusplus >= 202302L +#ifndef __cpp_lib_freestanding_variant +# error "Feature test macro for freestanding std::variant is missing in <version>" +#elif __cpp_lib_freestanding_variant < 202311L +# error "Feature test macro for freestanding std::variant has wrong value in <version>" +#endif +#endif + +#undef __cpp_lib_variant +#undef __cpp_lib_freestanding_variant +#include <variant> + +#if __cplusplus >= 202302L +#ifndef __cpp_lib_freestanding_variant +# error "Feature test macro for freestanding std::variant is missing in <variant>" +#elif __cpp_lib_freestanding_variant < 202311L +# error "Feature test macro for freestanding std::variant has wrong value in <variant>" +#endif +#endif diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/version.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/version.cc new file mode 100644 index 0000000..cc36699 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/requirements/version.cc @@ -0,0 +1,19 @@ +// { dg-do compile { target c++23 } } +// { dg-add-options no_pch } + +#include <string_view> + +#ifndef __cpp_lib_freestanding_string_view +# error "Feature test macro for freestanding std::string_view is missing in <string_view>" +#elif __cpp_lib_freestanding_string_view < 202311L +# error "Feature test macro for freestanding std::string_view has wrong value in <string_view>" +#endif + +#undef __cpp_lib_freestanding_string_view +#include <version> + +#ifndef __cpp_lib_freestanding_string_view +# error "Feature test macro for freestanding std::string_view is missing in <version>" +#elif __cpp_lib_freestanding_string_view < 202311L +# error "Feature test macro for freestanding std::string_view has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/21_strings/headers/cstring/version.cc b/libstdc++-v3/testsuite/21_strings/headers/cstring/version.cc new file mode 100644 index 0000000..06735e8 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/headers/cstring/version.cc @@ -0,0 +1,19 @@ +// { dg-do compile { target c++26 } } +// { dg-add-options no_pch } + +#include <cstring> + +#ifndef __cpp_lib_freestanding_cstring +# error "Feature test macro for freestanding <cstring> is missing in <cstring>" +#elif __cpp_lib_freestanding_cstring < 202311L +# error "Feature test macro for freestanding <cstring> has wrong value in <cstring>" +#endif + +#undef __cpp_lib_freestanding_cstring +#include <version> + +#ifndef __cpp_lib_freestanding_cstring +# error "Feature test macro for freestanding <cstring> is missing in <version>" +#elif __cpp_lib_freestanding_cstring < 202311L +# error "Feature test macro for freestanding <cstring> has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/23_containers/array/requirements/version.cc b/libstdc++-v3/testsuite/23_containers/array/requirements/version.cc new file mode 100644 index 0000000..1930805 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/array/requirements/version.cc @@ -0,0 +1,19 @@ +// { dg-do preprocess { target c++23 } } +// { dg-add-options no_pch } + +#include <array> + +#ifndef __cpp_lib_freestanding_array +# error "Feature test macro for freestanding std::array is missing in <array>" +#elif __cpp_lib_freestanding_array < 202311L +# error "Feature test macro for freestanding std::array has wrong value in <array>" +#endif + +#undef __cpp_lib_freestanding_array +#include <version> + +#ifndef __cpp_lib_freestanding_array +# error "Feature test macro for freestanding std::array is missing in <version>" +#elif __cpp_lib_freestanding_array < 202311L +# error "Feature test macro for freestanding std::array has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc index bf64d29..e1c92f8 100644 --- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc @@ -26,6 +26,6 @@ int n1 = std::get<1>(a); int n2 = std::get<1>(std::move(a)); int n3 = std::get<1>(ca); -// { dg-error "static assertion failed" "" { target *-*-* } 391 } -// { dg-error "static assertion failed" "" { target *-*-* } 400 } -// { dg-error "static assertion failed" "" { target *-*-* } 409 } +// { dg-error "static assertion failed" "" { target *-*-* } 392 } +// { dg-error "static assertion failed" "" { target *-*-* } 401 } +// { dg-error "static assertion failed" "" { target *-*-* } 410 } diff --git a/libstdc++-v3/testsuite/23_containers/span/1.cc b/libstdc++-v3/testsuite/23_containers/span/1.cc deleted file mode 100644 index c1c0a7e..0000000 --- a/libstdc++-v3/testsuite/23_containers/span/1.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2019-2023 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -// { dg-do compile { target c++20 } } -// { dg-add-options no_pch } - -#include <span> - -#ifndef __cpp_lib_span -# error "Feature-test macro for span missing in <span>" -#elif __cpp_lib_span != 202002L -# error "Feature-test macro for span has wrong value in <span>" -#endif diff --git a/libstdc++-v3/testsuite/23_containers/span/at.cc b/libstdc++-v3/testsuite/23_containers/span/at.cc new file mode 100644 index 0000000..dc4d8e3 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/span/at.cc @@ -0,0 +1,36 @@ +// { dg-do run { target c++26 } } + +#include <span> +#include <stdexcept> +#include <testsuite_hooks.h> + +void +test_at() +{ + int arr[4]{0, 1, 2, 3}; + std::span<int> s(arr); + VERIFY(s.at(2) == 2); +#if __cpp_exceptions + try { + s.at(4); // { dg-warning "ignoring return value" } + VERIFY(false); + } catch (const std::out_of_range&) { + } +#endif + + auto s2 = s.subspan(1, 2); + VERIFY(s2.at(0) == 1); + VERIFY(s2.at(1) == 2); +#if __cpp_exceptions + try { + s2.at(2); // { dg-warning "ignoring return value" } + VERIFY(false); + } catch (const std::out_of_range&) { + } +#endif +} + +int main() +{ + test_at(); +} diff --git a/libstdc++-v3/testsuite/23_containers/span/2.cc b/libstdc++-v3/testsuite/23_containers/span/version.cc index 2931c0b..7441812 100644 --- a/libstdc++-v3/testsuite/23_containers/span/2.cc +++ b/libstdc++-v3/testsuite/23_containers/span/version.cc @@ -18,10 +18,23 @@ // { dg-do compile { target c++20 } } // { dg-add-options no_pch } +#include <span> + +#ifndef __cpp_lib_span +# error "Feature-test macro for span missing in <span>" +#elif __cplusplus <= 202302L && __cpp_lib_span != 202002L +# error "Feature-test macro for span has wrong value in <span>" +#elif __cplusplus > 202302L && __cpp_lib_span != 202311L +# error "Feature-test macro for span has wrong value in <span>" +#endif + +#undef __cpp_lib_span #include <version> #ifndef __cpp_lib_span # error "Feature-test macro for span missing in <version>" -#elif __cpp_lib_span != 202002L +#elif __cplusplus <= 202302L && __cpp_lib_span != 202002L +# error "Feature-test macro for span has wrong value in <version>" +#elif __cplusplus > 202302L && __cpp_lib_span != 202311L # error "Feature-test macro for span has wrong value in <version>" #endif diff --git a/libstdc++-v3/testsuite/25_algorithms/fill_n/requirements/version.cc b/libstdc++-v3/testsuite/25_algorithms/fill_n/requirements/version.cc new file mode 100644 index 0000000..6691aff --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/fill_n/requirements/version.cc @@ -0,0 +1,19 @@ +// { dg-do preprocess { target c++23 } } +// { dg-add-options no_pch } + +#include <algorithm> + +#ifndef __cpp_lib_freestanding_algorithm +# error "Feature test macro for freestanding fill_n is missing in <algorithm>" +#elif __cpp_lib_freestanding_algorithm < 202311L +# error "Feature test macro for freestanding fill_n has wrong value in <algorithm>" +#endif + +#undef __cpp_lib_freestanding_algorithm +#include <version> + +#ifndef __cpp_lib_freestanding_algorithm +# error "Feature test macro for freestanding fill_n is missing in <version>" +#elif __cpp_lib_freestanding_algorithm < 202311L +# error "Feature test macro for freestanding fill_n has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/requirements/version.cc b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/requirements/version.cc new file mode 100644 index 0000000..2a65e7c --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/requirements/version.cc @@ -0,0 +1,19 @@ +// { dg-do preprocess { target c++23 } } +// { dg-add-options no_pch } + +#include <algorithm> + +#ifndef __cpp_lib_freestanding_algorithm +# error "Feature test macro for freestanding swap_ranges is missing in <algorithm>" +#elif __cpp_lib_freestanding_algorithm < 202311L +# error "Feature test macro for freestanding swap_ranges has wrong value in <algorithm>" +#endif + +#undef __cpp_lib_freestanding_algorithm +#include <version> + +#ifndef __cpp_lib_freestanding_algorithm +# error "Feature test macro for freestanding swap_ranges is missing in <version>" +#elif __cpp_lib_freestanding_algorithm < 202311L +# error "Feature test macro for freestanding swap_ranges has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/std/ranges/conv/1.cc b/libstdc++-v3/testsuite/std/ranges/conv/1.cc new file mode 100644 index 0000000..0032cf32 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/conv/1.cc @@ -0,0 +1,369 @@ +// { dg-do run { target c++23 } } + +// C++23 26.5.7 Range conversions [range.utility.conv] + +#include <ranges> +#include <vector> +#include <string> +#include <deque> +#include <list> +#include <forward_list> +#include <map> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> +#include <testsuite_iterators.h> + +void +test_p1206r7_examples() +{ + using Alloc = __gnu_test::uneq_allocator<int>; + const Alloc alloc(303); + const std::map<int, const char*> m{{1, "one"}, {2, "two"}, {3, "three"}}; + namespace ranges = std::ranges; + + auto l = std::views::iota(1, 10); + // create a vector with the elements of l + auto vec = ranges::to<std::vector<int>>(l); // or vector{std::from_range, l}; + //Specify an allocator + auto b = ranges::to<std::vector<int, Alloc>>(l, alloc); // or vector{std::from_range, l, alloc}; + //deducing value_type + auto c = ranges::to<std::vector>(l); + // explicit conversion int -> long + auto d = ranges::to<std::vector<long>>(l); + //Supports converting associative container to sequence containers + auto f = ranges::to<std::vector>(m); + //Supports converting sequence containers to associative ones + auto g = ranges::to<std::map>(f); + //Pipe syntax + auto g2 = l | ranges::views::take(42) | ranges::to<std::vector>(); + //Pipe syntax with allocator + auto h = l | ranges::views::take(42) | ranges::to<std::vector>(alloc); + //The pipe syntax also support specifying the type and conversions + auto i = l | ranges::views::take(42) | ranges::to<std::vector<long>>(); + // Nested ranges + std::list<std::forward_list<int>> lst = {{0, 1, 2, 3}, {4, 5, 6, 7}}; + auto vec1 = ranges::to<std::vector<std::vector<int>>>(lst); + auto vec2 = ranges::to<std::vector<std::deque<double>>>(lst); + + VERIFY( vec == std::vector<int>(std::ranges::begin(l), std::ranges::end(l)) ); + static_assert(std::is_same_v<decltype(b), std::vector<int, Alloc>>); + VERIFY( b == (std::vector<int, Alloc>(vec.begin(), vec.end())) ); + VERIFY( b.get_allocator() == alloc ); + static_assert(std::is_same_v<decltype(c), std::vector<int>>); + VERIFY( c == vec ); + static_assert(std::is_same_v<decltype(d), std::vector<long>>); + VERIFY( d == std::vector<long>(vec.begin(), vec.end()) ); + VERIFY( g == m ); + static_assert(std::is_same_v<decltype(g2), std::vector<int>>); + VERIFY( g2 == vec ); + static_assert(std::is_same_v<decltype(h), std::vector<int, Alloc>>); + VERIFY( h == b ); + VERIFY( h.get_allocator() == alloc ); + VERIFY( i == d ); + static_assert(std::is_same_v<decltype(vec1), std::vector<std::vector<int>>>); + VERIFY( vec1[1][1] == 5 ); + static_assert(std::is_same_v<decltype(vec2), std::vector<std::deque<double>>>); + VERIFY( vec2[1][2] == 6.0 ); +} + +void +test_example_1() +{ + using namespace std; + using ranges::to; + + // Example 1 from C++23 [range.utility.conv.general] + string_view str = "the quick brown fox"; + auto words = views::split(str, ' ') | to<vector<string>>(); + + VERIFY( (is_same_v<decltype(words), vector<string>>) ); + VERIFY( words == vector<string>({"the", "quick", "brown", "fox"}) ); +} + +template<typename C> +struct Cont1 +{ + template<typename R, typename... Args> + requires std::constructible_from<C, R&, Args&...> + Cont1(R&& r, Args&&... args) + : c(r, args...) + { } + + typename C::iterator begin(); + typename C::iterator end(); + + C c; +}; + +void +test_2_1_1() +{ + // (2.1.1) constructible_from<C, R, Args...> + + std::vector<int> v{1, 2, 3, 4}; + auto v2 = std::ranges::to<std::vector<int>>(v); + static_assert(std::is_same_v<decltype(v2), decltype(v)>); + VERIFY( v2 == v ); + + std::initializer_list<int> il{5, 6, 7, 8}; + v2 = std::ranges::to<std::vector<int>>(il); + VERIFY( v2 == std::vector<int>(il) ); + + v2 = std::ranges::to<std::vector<int>>(il, std::allocator<int>{}); + VERIFY( v2 == std::vector<int>(il) ); + + using Alloc = __gnu_test::uneq_allocator<int>; + using V = std::vector<int, Alloc>; + + V v3({10, 11, 12, 13}, Alloc(14)); + auto v4 = std::ranges::to<V>(v3); + static_assert(std::is_same_v<decltype(v4), V>); + VERIFY( v4 == v3 ); + VERIFY( v4.get_allocator() == v3.get_allocator() ); + + auto v5 = std::ranges::to<V>(v3, Alloc(33)); + VERIFY( v5 == v3 ); + VERIFY( v5.get_allocator() == Alloc(33) ); + + auto v6 = std::ranges::to<V>(il, Alloc(44)); + VERIFY( v6 == V(il) ); + VERIFY( v6.get_allocator() == Alloc(44) ); + + auto c = std::ranges::to<Cont1<V>>(V{1, 2, 3}); + static_assert(std::is_same_v<decltype(c), Cont1<V>>); + VERIFY( c.c == V({1, 2, 3}) ); + + auto c2 = std::ranges::to<Cont1<V>>(V{4, 5, 6}, Alloc(55)); + static_assert(std::is_same_v<decltype(c2), Cont1<V>>); + VERIFY( c2.c == V({4, 5, 6}) ); + VERIFY( c2.c.get_allocator() == Alloc(55) ); + + auto c3 = std::ranges::to<Cont1<V>>(il, Alloc(66)); + static_assert(std::is_same_v<decltype(c2), Cont1<V>>); + VERIFY( c3.c == V(v2.begin(), v2.end()) ); + VERIFY( c3.c.get_allocator() == Alloc(66) ); +} + +template<typename C> +struct Cont2 +{ + template<typename R, typename... Args> + requires std::constructible_from<C, R&, Args&...> + Cont2(std::from_range_t, R&& r, Args&&... args) + : c(r, args...) + { } + + typename C::iterator begin(); + typename C::iterator end(); + + C c; +}; + +void +test_2_1_2() +{ + // (2.1.2) constructible_from<C, from_range_t, R, Args...> + + using Alloc = __gnu_test::uneq_allocator<int>; + using V = std::vector<int, Alloc>; + auto c = std::ranges::to<Cont2<V>>(V{1, 2, 3}); + static_assert(std::is_same_v<decltype(c), Cont2<V>>); + VERIFY( c.c == V({1, 2, 3}) ); + + auto c2 = std::ranges::to<Cont2<V>>(V{4, 5, 6}, Alloc(7)); + static_assert(std::is_same_v<decltype(c2), Cont2<V>>); + VERIFY( c2.c == V({4, 5, 6}) ); + VERIFY( c2.c.get_allocator() == Alloc(7) ); +} + +template<typename C> +struct Cont3 +{ + template<typename It, typename Sent, typename... Args> + requires std::same_as<It, Sent> + && std::constructible_from<C, It&, Sent&, Args&...> + Cont3(It first, Sent last, Args&&... args) + : c(first, last, args...) + { } + + typename C::iterator begin(); + typename C::iterator end(); + + C c; +}; + +void +test_2_1_3() +{ + // (2.1.3) constructible_from<C, iterator_t<R>, sentinel_t<R<, Args...> + + using Alloc = __gnu_test::uneq_allocator<int>; + using V = std::vector<int, Alloc>; + + std::list<unsigned> l{1u, 2u, 3u}; + auto c = std::ranges::to<Cont3<V>>(l); + static_assert(std::is_same_v<decltype(c), Cont3<V>>); + VERIFY( c.c == V(l.begin(), l.end()) ); + + std::list<long> l2{4l, 5l, 6l}; + auto c2 = std::ranges::to<Cont3<V>>(l2, Alloc(78)); + static_assert(std::is_same_v<decltype(c2), Cont3<V>>); + VERIFY( c2.c == V(l2.begin(), l2.end()) ); + VERIFY( c2.c.get_allocator() == Alloc(78) ); +} + +template<typename C, bool UsePushBack = true> +struct Cont4 +{ + using value_type = typename C::value_type; + + // Only support construction with no args or an allocator. + // This forces the use of either push_back or insert to fill the container. + Cont4() { } + Cont4(typename C::allocator_type a) : c(a) { } + + // Required to satisfy range + typename C::iterator begin() { return c.begin(); } + typename C::iterator end() { return c.end(); } + + // Satisfying container-insertable requires either this ... + template<typename T> + requires UsePushBack + && requires(C& c, T&& t) { c.push_back(std::forward<T>(t)); } + void + push_back(T&& t) + { + c.push_back(std::forward<T>(t)); + used_push_back = true; + } + + // ... or this: + template<typename T> + typename C::iterator + insert(typename C::iterator, T&& t) + { + used_push_back = false; + return c.insert(c.end(), std::forward<T>(t)); + } + + // Required to satisfy reservable-container + void + reserve(typename C::size_type n) requires requires(C& c) { c.reserve(n); } + { + c.reserve(n); + used_reserve = true; + } + + // Required to satisfy reservable-container + auto size() const { return c.size(); } + + // Required to satisfy reservable-container + auto capacity() const requires requires(C& c) { c.capacity(); } + { return c.capacity(); } + + // Required to satisfy reservable-container + auto max_size() const { return c.max_size(); } + + C c; + bool used_push_back = false; + bool used_reserve = false; +}; + +void +test_2_1_4() +{ + // (2.1.4) constructible_from<C, Args...> and + // container-insertable<C, range_reference_t<R>> + + using Alloc = __gnu_test::uneq_allocator<int>; + using V = std::vector<int, Alloc>; + + std::list<unsigned> l{1u, 2u, 3u}; + auto c = std::ranges::to<Cont4<V>>(l); + static_assert(std::is_same_v<decltype(c), Cont4<V>>); + VERIFY( c.c == V(l.begin(), l.end()) ); + VERIFY( c.used_push_back ); + VERIFY( c.used_reserve ); + + std::list<long> l2{4l, 5l, 6l}; + auto c2 = std::ranges::to<Cont4<V>>(l2, Alloc(78)); + static_assert(std::is_same_v<decltype(c2), Cont4<V>>); + VERIFY( c2.c == V(l2.begin(), l2.end()) ); + VERIFY( c2.c.get_allocator() == Alloc(78) ); + VERIFY( c2.used_push_back ); + VERIFY( c2.used_reserve ); + + using Alloc2 = __gnu_test::uneq_allocator<short>; + using List = std::list<short, Alloc2>; + auto c3 = std::ranges::to<Cont4<List>>(c.c, Alloc2(99)); + static_assert(std::is_same_v<decltype(c3), Cont4<List>>); + VERIFY( c3.c == List(l.begin(), l.end()) ); + VERIFY( c3.c.get_allocator() == Alloc(99) ); + VERIFY( c3.used_push_back ); + VERIFY( ! c3.used_reserve ); + + auto c4 = std::ranges::to<Cont4<List, false>>(c.c, Alloc2(111)); + static_assert(std::is_same_v<decltype(c4), Cont4<List, false>>); + VERIFY( c4.c == List(l.begin(), l.end()) ); + VERIFY( c4.c.get_allocator() == Alloc(111) ); + VERIFY( ! c4.used_push_back ); + VERIFY( ! c4.used_reserve ); +} + +void +test_2_2() +{ + // (2.2) input_range<range_reference_t<R>> + + std::string s1[]{ "one", "two", "three", "four" }; + std::string s2[]{ "V", "VI", "VII", "VIII" }; + std::string s3[]{ "0x09", "0x0a", "0x0b", "0x0c" }; + using R = __gnu_test::test_input_range<std::string>; + R input_ranges[]{R(s1), R(s2), R(s3)}; + __gnu_test::test_input_range<R> rr(input_ranges); + namespace pmr = std::pmr; + __gnu_test::memory_resource res; +#if _GLIBCXX_USE_CXX11_ABI + auto vvs = std::ranges::to<pmr::vector<pmr::vector<pmr::string>>>(rr, &res); + auto str_alloc = pmr::polymorphic_allocator<char>(&res); +#else + auto vvs = std::ranges::to<pmr::vector<pmr::vector<std::string>>>(rr, &res); + auto str_alloc = std::allocator<char>(); +#endif + VERIFY( vvs[1][1] == "VI" ); + VERIFY( vvs[2][2] == "0x0b" ); + VERIFY( vvs[0].get_allocator().resource() == &res ); + VERIFY( vvs[2][2].get_allocator() == str_alloc ); +} + +void +test_lwg3984() +{ + std::vector<std::vector<int>> v; + auto r = std::views::all(std::move(v)); + auto l = std::ranges::to<std::list<std::list<int>>>(r); + VERIFY(l.empty()); +} + +void +test_nodiscard() +{ + std::vector<int> v; + std::ranges::to<std::vector<long>>(v); // { dg-warning "ignoring return" } + std::ranges::to<std::vector>(v); // { dg-warning "ignoring return" } + std::ranges::to<std::vector<long>>(); // { dg-warning "ignoring return" } + std::ranges::to<std::vector>(); // { dg-warning "ignoring return" } +} + +int main() +{ + test_p1206r7_examples(); + test_example_1(); + test_2_1_1(); + test_2_1_2(); + test_2_1_3(); + test_2_1_4(); + test_2_2(); + test_lwg3984(); + test_nodiscard(); +} diff --git a/libstdc++-v3/testsuite/std/ranges/conv/2_neg.cc b/libstdc++-v3/testsuite/std/ranges/conv/2_neg.cc new file mode 100644 index 0000000..1e5f6f1 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/conv/2_neg.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++23 } } + +// C++23 26.5.7 Range conversions [range.utility.conv] + +#include <ranges> +#include <vector> +#include <testsuite_allocator.h> + +void +test_2_1_5() +{ + // (2.1.5) Otherwise, the program is ill-formed. + + using Alloc = __gnu_test::uneq_allocator<int>; + using Vec = std::vector<int, Alloc>; + + std::vector<int> v; + (void) std::ranges::to<Vec>(v, v.get_allocator()); // { dg-error "here" } + + (void) std::ranges::to<Vec>(Vec{}, 1, 2, 3, 4, 5, 6); // { dg-error "here" } +} + +// { dg-error "static assertion failed" "" { target *-*-* } 0 } +// { dg-prune-output "no matching function" } diff --git a/libstdc++-v3/testsuite/std/ranges/conv/version.cc b/libstdc++-v3/testsuite/std/ranges/conv/version.cc new file mode 100644 index 0000000..3373680 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/conv/version.cc @@ -0,0 +1,19 @@ +// { dg-do preprocess { target c++23 } } +// { dg-add-options no_pch } + +#include <ranges> + +#ifndef __cpp_lib_ranges_to_container +# error "Feature test macro for ranges_to_container is missing in <ranges>" +#elif __cpp_lib_ranges_to_container < 202202L +# error "Feature test macro for ranges_to_container has wrong value in <ranges>" +#endif + +#undef __cpp_lib_ranges_to_container +#include <version> + +#ifndef __cpp_lib_ranges_to_container +# error "Feature test macro for ranges_to_container is missing in <version>" +#elif __cpp_lib_ranges_to_container < 202202L +# error "Feature test macro for ranges_to_container has wrong value in <version>" +#endif diff --git a/libstdc++-v3/testsuite/tr2/dynamic_bitset/string.cc b/libstdc++-v3/testsuite/tr2/dynamic_bitset/string.cc new file mode 100644 index 0000000..c7d0efa --- /dev/null +++ b/libstdc++-v3/testsuite/tr2/dynamic_bitset/string.cc @@ -0,0 +1,36 @@ +// { dg-do run { target c++11 } } + +#include <tr2/dynamic_bitset> +#include <string> +#include <testsuite_hooks.h> + +void +test_string_ctor() +{ + std::tr2::dynamic_bitset<> b("101001"); + VERIFY( b[0] == true ); + VERIFY( b[1] == false ); + VERIFY( b[2] == false ); + VERIFY( b[3] == true ); + VERIFY( b[4] == false ); + VERIFY( b[5] == true ); +} + +void +test_alt_chars() +{ + std::string str = "xOIOIOIOx"; + std::tr2::dynamic_bitset<> b(str, 1, 6, 'I', 'O'); + VERIFY( b[0] == false ); + VERIFY( b[1] == true ); + VERIFY( b[2] == false ); + VERIFY( b[3] == true ); + VERIFY( b[4] == false ); + VERIFY( b[5] == true ); +} + +int main() +{ + test_string_ctor(); + test_alt_chars(); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 70dacb3..1773b72 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -418,7 +418,7 @@ namespace __gnu_test operator==(const uneq_allocator& a, const uneq_allocator<Tp1, typename AllocTraits::template rebind<Tp1>::other>& b) - { return a.personality == b.personality; } + { return a.personality == b.get_personality(); } template<typename Tp1> friend inline bool @@ -4312,7 +4312,6 @@ _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC -_LT_TAGVAR(enable_darwin_at_rpath, $1)=no # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- |