diff options
202 files changed, 4845 insertions, 507 deletions
@@ -1,3 +1,7 @@ +2025-04-16 Waffl3x <waffl3x@baylibre.com> + + * MAINTAINERS: Add myself. + 2025-04-02 Iain Sandoe <iain@sandoe.co.uk> * configure: Regenerate. diff --git a/MAINTAINERS b/MAINTAINERS index 756227e..6ff4770 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -862,6 +862,7 @@ Ville Voutilainen ville <ville.voutilainen@gmail.com> Tom de Vries vries <tdevries@suse.de> Nenad Vukicevic nenadv <nenad@intrepid.com> Dmitry Vyukov dvyukov <dvyukov@google.com> +Waffl3x waffl3x <waffl3x@baylibre.com> Jonathan Wakely redi <jwakely@redhat.com> Krister Walfridsson kristerw <krister.walfridsson@gmail.com> Feng Wang - <wangfeng@eswincomputing.com> diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 334d1e4..e7a4cab 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,8 @@ +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + * gcc-changelog/git_update_version.py (active_refs): Add + releases/gcc-15. + 2025-04-11 Tomasz Kamiński <tkaminsk@redhat.com> PR libstdc++/109162 diff --git a/contrib/gcc-changelog/git_update_version.py b/contrib/gcc-changelog/git_update_version.py index 8e36c74..aa9adee 100755 --- a/contrib/gcc-changelog/git_update_version.py +++ b/contrib/gcc-changelog/git_update_version.py @@ -85,8 +85,8 @@ def prepend_to_changelog_files(repo, folder, git_commit, add_to_git): repo.git.add(full_path) -active_refs = ['master', - 'releases/gcc-12', 'releases/gcc-13', 'releases/gcc-14'] +active_refs = ['master', 'releases/gcc-12', + 'releases/gcc-13', 'releases/gcc-14', 'releases/gcc-15'] parser = argparse.ArgumentParser(description='Update DATESTAMP and generate ' 'ChangeLog entries') diff --git a/gcc/BASE-VER b/gcc/BASE-VER index 2bbd2b4..946789e 100644 --- a/gcc/BASE-VER +++ b/gcc/BASE-VER @@ -1 +1 @@ -15.0.1 +16.0.0 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e082958..4a2a79f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,268 @@ +2025-04-19 Jeff Law <jlaw@ventanamicro.com> + + PR target/119865 + * config/riscv/riscv.cc (parse_features_for_version): Do not + explicitly free the architecture string. + +2025-04-19 Jeff Law <jlaw@ventanamicro.com> + + PR target/118410 + * config/riscv/bitmanip.md (logical with constant argument): New + splitter for cases where synthesizing ~C is cheaper than synthesizing + the original constant C. + +2025-04-19 Jan Hubicka <hubicka@ucw.cz> + + * config/i386/i386.cc (vec_fp_conversion_cost): New function. + (ix86_rtx_costs): Use it for SSE/AVX FP conversoins. + (ix86_builtin_vectorization_cost): Fix indentation; + and use vec_fp_conversion_cost in vec_promote_demote. + (fp_conversion_stmt_cost): New function. + (ix86_vector_costs::add_stmt_cost): Use it to cost NOP_EXPR + and vec_promote_demote. + * config/i386/i386.h (struct processor_costs): + * config/i386/x86-tune-costs.h (struct processor_costs): + +2025-04-19 Andrew Pinski <quic_apinski@quicinc.com> + + PR rtl-optimization/111949 + * combine.cc (find_split_point): Add a split point + for `(and (not X) Y)` if not in the outer set already. + +2025-04-19 Jiaxun Yang <jiaxun.yang@flygoat.com> + + PR target/111814 + * config/sh/sh-modes.def (RESET_FLOAT_FORMAT): Use mips format. + (FLOAT_MODE): Use mips mode. + +2025-04-19 Maciej W. Rozycki <macro@orcam.me.uk> + + * config/alpha/alpha.cc + (alpha_get_mem_rtx_alignment_and_offset): Recurse into + COMPONENT_REF nodes. + +2025-04-18 Jeff Law <jlaw@ventanamicro.com> + + * config/riscv/bitmanip.md (*bext<mode>_mask_pos): New pattern + for extracting a single bit at masked bit position. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/87901 + * tree-ssa-dse.cc (maybe_trim_constructor_store): Add was_integer_cst argument. + Check for was_integer_cst instead of `{}` when was_integer_cst is true. + (maybe_trim_partially_dead_store): Handle INTEGER_CST stores of 0 as stores of `{}`. + Udpate call to maybe_trim_constructor_store for CONSTRUCTOR. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/87901 + * tree-ssa-dse.cc (maybe_trim_constructor_store): Strip over useless type + conversions after taking the address of the MEM_REF. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/118902 + * fold-const.cc (tree_swap_operands_p): Place invariants in the first operand + if not used with constants. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/118947 + * gimple-fold.cc (optimize_memcpy_to_memset): Walk back until we get a + statement that may clobber the read. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/78408 + PR tree-optimization/118947 + * gimple-fold.cc (optimize_memcpy_to_memset): Handle STRING_CST case too. + +2025-04-18 Richard Braun <rbraun@sceen.net> + + * config/c6x/c6x.h (ASM_PREFERRED_EH_DATA_FORMAT): Remove the + DW_EH_PE_indirect flag. + +2025-04-18 Richard Biener <rguenther@suse.de> + + PR tree-optimization/119858 + * tree-vect-loop.cc (vectorizable_live_operation): Convert + pointer offset to sizetype. + +2025-04-18 Hakan Candar <hakancandar@protonmail.com> + + * config.gcc: Recognize riscv*-*-gnu* targets. + * config/riscv/gnu.h: New file. + +2025-04-18 Alexey Merzlyakov <alexey.merzlyakov@samsung.com> + + PR middle-end/108016 + PR middle-end/108016 + * config/riscv/riscv.md (addv<mode>4, uaddv<mode>4, subv<mode>4, + usubv<mode>4): Tunes for unnecessary sext.w elimination. + +2025-04-18 kelefth <konstantinos.eleftheriou@vrull.eu> + + PR rtl-optimization/119160 + * avoid-store-forwarding.cc (process_store_forwarding): + Zero-extend the value stored in the base register, in case + of load-elimination, only when the mode of the destination + is wider. + +2025-04-18 kelefth <konstantinos.eleftheriou@vrull.eu> + + * doc/cfg.texi: Update the exception handling section for the + REG_EH_REGION notes to make it clear that the note is attached + to the instruction throwing the exception. + +2025-04-17 翁愷邑 <kaiweng9487@gmail.com> + + * config/riscv/riscv-target-attr.cc + (riscv_target_attr_parser::update_settings): + Do not manually free any arch string. + +2025-04-17 Eric Botcazou <ebotcazou@gcc.gnu.org> + + * tree.def (BOOLEAN_TYPE): Add more details. + +2025-04-17 Sam James <sam@gentoo.org> + + * doc/invoke.texi: Use "compatible types" term. Rephrase to be + more precise (and correct). + +2025-04-17 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/119351 + * tree-vect-stmts.cc (vectorizable_early_exit): Mask both operands of + the gcond for partial masking support. + +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + PR target/119834 + * config/s390/s390.md (define_split after *cpymem_short): Use + (clobber (match_scratch N)) instead of (clobber (scratch)). Use + (match_dup 4) and operands[4] instead of (match_dup 3) and operands[3] + in the last of those. + (define_split after *clrmem_short): Use (clobber (match_scratch N)) + instead of (clobber (scratch)). + (define_split after *cmpmem_short): Likewise. + +2025-04-17 Thomas Schwinge <tschwinge@baylibre.com> + + * config/nvptx/nvptx.cc (TARGET_ASM_NEED_VAR_DECL_BEFORE_USE): + Don't '#define'. + +2025-04-17 Hans-Peter Nilsson <hp@axis.com> + + * combine.cc: Correct comments about combine_validate_cost. + +2025-04-16 Sandra Loosemore <sloosemore@baylibre.com> + + PR c/88382 + * doc/extend.texi (Syntax Extensions): Adjust menu. + (Raw String Literals): New section. + +2025-04-16 Keith Packard <keithp@keithp.com> + + * config/rx/rx.md (cmpstrnsi): Allow constant length. For + static length 0, just store 0 into the output register. + For dynamic zero, set C/Z appropriately. + (rxcmpstrn): No longer set C/Z. + +2025-04-16 Eric Botcazou <ebotcazou@gcc.gnu.org> + + * tree-ssa-phiopt.cc (factor_out_conditional_operation): Do not + bypass the int_fits_type_p test for boolean types whose precision + is not 1. + +2025-04-16 Sandra Loosemore <sloosemore@baylibre.com> + + * common.opt.urls: Regenerated. + +2025-04-16 Ard Biesheuvel <ardb@kernel.org> + + PR target/119386 + * config/i386/i386-options.cc: Permit -mnop-mcount when + using -fpic with PLTs. + +2025-04-16 Ard Biesheuvel <ardb@kernel.org> + + PR target/119386 + * config/i386/i386.cc (x86_print_call_or_nop): Add @PLT suffix + where appropriate. + (x86_function_profiler): Fall through to x86_print_call_or_nop() + for PIC codegen when flag_plt is set. + +2025-04-16 Sandra Loosemore <sloosemore@baylibre.com> + + PR driver/90465 + * doc/invoke.texi (Overall Options): Add a @cindex for -Q in + connection with --help=. + (Developer Options): Point at --help= documentation for the + other use of -Q. + +2025-04-16 Thomas Schwinge <tschwinge@baylibre.com> + + PR target/97106 + * config/nvptx/nvptx.cc (nvptx_asm_output_def_from_decls) + [ACCEL_COMPILER]: Make sure to emit C++ constructor, destructor + aliases. + +2025-04-16 Jan Hubicka <hubicka@ucw.cz> + + PR tree-optimization/119614 + * ipa-prop.cc (ipa_write_return_summaries): New function. + (ipa_record_return_value_range_1): Break out from .... + (ipa_record_return_value_range): ... here. + (ipa_read_return_summaries): New function. + (ipa_prop_read_section): Read return summaries. + (read_ipcp_transformation_info): Read return summaries. + (ipcp_write_transformation_summaries): Write return summaries; + do not stream stray 0. + +2025-04-16 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/119351 + * tree-vectorizer.h (LOOP_VINFO_MASK_NITERS_PFA_OFFSET, + LOOP_VINFO_NON_LINEAR_IV): New. + (class _loop_vec_info): Add mask_skip_niters_pfa_offset and + nonlinear_iv. + * tree-vect-loop.cc (_loop_vec_info::_loop_vec_info): Initialize them. + (vect_analyze_scalar_cycles_1): Record non-linear inductions. + (vectorizable_induction): If early break and PFA using masking create a + new phi which tracks where the scalar code needs to start... + (vectorizable_live_operation): ...and generate the adjustments here. + (vect_use_loop_mask_for_alignment_p): Reject non-linear inductions and + early break needing peeling. + +2025-04-16 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/119808 + * gimple-lower-bitint.cc (gimple_lower_bitint): Don't set + m_single_use_names bits for SSA_NAMEs which have single use but + their SSA_NAME_DEF_STMT is a copy from another SSA_NAME which doesn't + have a single use, or single use which is such a copy etc. + +2025-04-16 Jesse Huang <jesse.huang@sifive.com> + + * config/riscv/riscv.cc (riscv_file_end): Fix .p2align value. + +2025-04-16 Kito Cheng <kito.cheng@sifive.com> + + * config/riscv/riscv.h (JUMP_TABLES_IN_TEXT_SECTION): Check if + large code model. + +2025-04-16 Tejas Belagod <tejas.belagod@arm.com> + + * config/aarch64/aarch64-sve.md (vec_extract<vpred><Vel>): Fix operand + order to gen_vcond_mask_*. + +2025-04-16 Alice Carlotti <alice.carlotti@arm.com> + + * config/aarch64/aarch64.cc + (aarch64_valid_sysreg_name_p): Remove feature check. + (aarch64_retrieve_sysreg): Ditto. + 2025-04-15 Sandra Loosemore <sloosemore@baylibre.com> PR tree-optimization/71094 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c9d404d..f21e9cc 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250416 +20250420 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index bc92ffe..650de8b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,7 @@ +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + * gnatvsn.ads: Bump Library_Version to 16. + 2025-04-12 Eric Botcazou <ebotcazou@adacore.com> PR ada/119643 diff --git a/gcc/ada/gnatvsn.ads b/gcc/ada/gnatvsn.ads index 176f88a..ad11c30 100644 --- a/gcc/ada/gnatvsn.ads +++ b/gcc/ada/gnatvsn.ads @@ -32,7 +32,7 @@ package Gnatvsn is -- Static string identifying this version, that can be used as an argument -- to e.g. pragma Ident. - Library_Version : constant String := "15"; + Library_Version : constant String := "16"; -- Library version. It needs to be updated whenever the major version -- number is changed. -- diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc index 34a7bba..ded8d7e 100644 --- a/gcc/avoid-store-forwarding.cc +++ b/gcc/avoid-store-forwarding.cc @@ -238,10 +238,15 @@ process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn, { start_sequence (); - rtx ext0 = gen_rtx_ZERO_EXTEND (GET_MODE (dest), it->mov_reg); - if (ext0) + machine_mode dest_mode = GET_MODE (dest); + rtx base_reg = it->mov_reg; + if (known_gt (GET_MODE_BITSIZE (dest_mode), + GET_MODE_BITSIZE (GET_MODE (it->mov_reg)))) + base_reg = gen_rtx_ZERO_EXTEND (dest_mode, it->mov_reg); + + if (base_reg) { - rtx_insn *move0 = emit_move_insn (dest, ext0); + rtx_insn *move0 = emit_move_insn (dest, base_reg); if (recog_memoized (move0) >= 0) { insns = get_insns (); diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog index 59a1107..27c31c1 100644 --- a/gcc/cobol/ChangeLog +++ b/gcc/cobol/ChangeLog @@ -1,3 +1,8 @@ +2025-04-16 Bob Dubner <rdubner@symas.com> + + PR cobol/119759 + * LICENSE: Deleted. + 2025-04-15 Richard Biener <rguenther@suse.de> PR cobol/119302 diff --git a/gcc/cobol/LICENSE b/gcc/cobol/LICENSE deleted file mode 100644 index aa5ba60..0000000 --- a/gcc/cobol/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -######################################################################### -# -# Copyright (c) 2021-2025 Symas Corporation -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of the Symas Corporation nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/gcc/combine.cc b/gcc/combine.cc index 5f08518..873c2bd 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -815,7 +815,7 @@ do_SUBST_LINK (struct insn_link **into, struct insn_link *newval) #define SUBST_LINK(oldval, newval) do_SUBST_LINK (&oldval, newval) /* Subroutine of try_combine. Determine whether the replacement patterns - NEWPAT, NEWI2PAT and NEWOTHERPAT are cheaper according to insn_cost + NEWPAT, NEWI2PAT and NEWOTHERPAT are more expensive according to insn_cost than the original sequence I0, I1, I2, I3 and undobuf.other_insn. Note that I0, I1 and/or NEWI2PAT may be NULL_RTX. Similarly, NEWOTHERPAT and undobuf.other_insn may also both be NULL_RTX. Return false if the cost @@ -4129,8 +4129,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, } } - /* Only allow this combination if insn_cost reports that the - replacement instructions are cheaper than the originals. */ + /* Reject this combination if insn_cost reports that the replacement + instructions are more expensive than the originals. */ if (!combine_validate_cost (i0, i1, i2, i3, newpat, newi2pat, other_pat)) { undo_all (); @@ -5280,6 +5280,12 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) SUBST (XEXP (x, 0), XEXP (x, 1)); SUBST (XEXP (x, 1), tem); } + /* Many targets have a `(and (not X) Y)` and/or `(ior (not X) Y)` instructions. + Split at that insns. However if this is + the SET_SRC, we likely do not have such an instruction and it's + worthless to try this split. */ + if (!set_src && GET_CODE (XEXP (x, 0)) == NOT) + return loc; break; case PLUS: diff --git a/gcc/common.opt.urls b/gcc/common.opt.urls index 8bd75b1..0077511 100644 --- a/gcc/common.opt.urls +++ b/gcc/common.opt.urls @@ -31,8 +31,9 @@ UrlSuffix(gcc/Optimize-Options.html#index-Og) Oz UrlSuffix(gcc/Optimize-Options.html#index-Oz) -Q -UrlSuffix(gcc/Developer-Options.html#index-Q) +; skipping UrlSuffix for 'Q' due to multiple URLs: +; duplicate: 'gcc/Developer-Options.html#index-Q-1' +; duplicate: 'gcc/Overall-Options.html#index-Q' Qn UrlSuffix(gcc/System-V-Options.html#index-Qn) diff --git a/gcc/config.gcc b/gcc/config.gcc index 40b50dc..d98df88 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2540,6 +2540,20 @@ riscv*-*-linux*) gcc_cv_initfini_array=yes with_tls=${with_tls:-trad} ;; +riscv*-*-gnu*) + tm_file="elfos.h gnu-user.h gnu.h glibc-stdint.h ${tm_file} riscv/gnu.h" + tmake_file="${tmake_file} riscv/t-riscv" + gnu_ld=yes + gas=yes + case $target in + riscv32be-*|riscv64be-*) + tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" + ;; + esac + # Force .init_array support. The configure script cannot always + # automatically detect that GAS supports it, yet we require it. + gcc_cv_initfini_array=yes + ;; riscv*-*-elf* | riscv*-*-rtems*) tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h" case ${target} in diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md index 3dbd659..d4af370 100644 --- a/gcc/config/aarch64/aarch64-sve.md +++ b/gcc/config/aarch64/aarch64-sve.md @@ -3133,9 +3133,9 @@ "TARGET_SVE" { rtx tmp = gen_reg_rtx (<MODE>mode); - emit_insn (gen_vcond_mask_<mode><vpred> (tmp, operands[1], - CONST1_RTX (<MODE>mode), - CONST0_RTX (<MODE>mode))); + emit_insn (gen_vcond_mask_<mode><vpred> (tmp, CONST1_RTX (<MODE>mode), + CONST0_RTX (<MODE>mode), + operands[1])); emit_insn (gen_vec_extract<mode><Vel> (operands[0], tmp, operands[2])); DONE; } diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc index ba470d9..14e7da5 100644 --- a/gcc/config/alpha/alpha.cc +++ b/gcc/config/alpha/alpha.cc @@ -4291,14 +4291,10 @@ alpha_get_mem_rtx_alignment_and_offset (rtx expr, int &a, HOST_WIDE_INT &o) tree mem = MEM_EXPR (expr); if (mem != NULL_TREE) - switch (TREE_CODE (mem)) - { - case MEM_REF: - tree_offset = mem_ref_offset (mem).force_shwi (); - tree_align = get_object_alignment (get_base_address (mem)); - break; + { + HOST_WIDE_INT comp_offset = 0; - case COMPONENT_REF: + for (; TREE_CODE (mem) == COMPONENT_REF; mem = TREE_OPERAND (mem, 0)) { tree byte_offset = component_ref_field_offset (mem); tree bit_offset = DECL_FIELD_BIT_OFFSET (TREE_OPERAND (mem, 1)); @@ -4307,14 +4303,15 @@ alpha_get_mem_rtx_alignment_and_offset (rtx expr, int &a, HOST_WIDE_INT &o) || !poly_int_tree_p (byte_offset, &offset) || !tree_fits_shwi_p (bit_offset)) break; - tree_offset = offset + tree_to_shwi (bit_offset) / BITS_PER_UNIT; + comp_offset += offset + tree_to_shwi (bit_offset) / BITS_PER_UNIT; } - tree_align = get_object_alignment (get_base_address (mem)); - break; - default: - break; - } + if (TREE_CODE (mem) == MEM_REF) + { + tree_offset = comp_offset + mem_ref_offset (mem).force_shwi (); + tree_align = get_object_alignment (get_base_address (mem)); + } + } if (reg_align > mem_align) { diff --git a/gcc/config/c6x/c6x.h b/gcc/config/c6x/c6x.h index e7da250..50bad27 100644 --- a/gcc/config/c6x/c6x.h +++ b/gcc/config/c6x/c6x.h @@ -444,11 +444,9 @@ struct GTY(()) machine_function #define TARG_VEC_PERMUTE_COST 1 #endif -/* ttype entries (the only interesting data references used) are - sb-relative got-indirect (aka .ehtype). */ +/* .ehtype ttype entries are sb-relative. */ #define ASM_PREFERRED_EH_DATA_FORMAT(code, data) \ - (((code) == 0 && (data) == 1) ? (DW_EH_PE_datarel | DW_EH_PE_indirect) \ - : DW_EH_PE_absptr) + (((code) == 0 && (data) == 1) ? DW_EH_PE_datarel : DW_EH_PE_absptr) /* This should be the same as the definition in elfos.h, plus the call to output special unwinding directives. */ diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc index a9fac01..964449f 100644 --- a/gcc/config/i386/i386-options.cc +++ b/gcc/config/i386/i386-options.cc @@ -2828,8 +2828,8 @@ ix86_option_override_internal (bool main_args_p, if (flag_nop_mcount) error ("%<-mnop-mcount%> is not compatible with this target"); #endif - if (flag_nop_mcount && flag_pic) - error ("%<-mnop-mcount%> is not implemented for %<-fPIC%>"); + if (flag_nop_mcount && flag_pic && !flag_plt) + error ("%<-mnop-mcount%> is not implemented for %<-fno-plt%>"); /* Accept -msseregparm only if at least SSE support is enabled. */ if (TARGET_SSEREGPARM_P (opts->x_target_flags) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index b172f71..28603c2 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -100,6 +100,7 @@ along with GCC; see the file COPYING3. If not see #include "i386-features.h" #include "function-abi.h" #include "rtl-error.h" +#include "gimple-pretty-print.h" /* This file should be included last. */ #include "target-def.h" @@ -21816,6 +21817,25 @@ ix86_insn_cost (rtx_insn *insn, bool speed) return insn_cost + pattern_cost (PATTERN (insn), speed); } +/* Return cost of SSE/AVX FP->FP conversion (extensions and truncates). */ + +static int +vec_fp_conversion_cost (const struct processor_costs *cost, int size) +{ + if (size < 128) + return cost->cvtss2sd; + else if (size < 256) + { + if (TARGET_SSE_SPLIT_REGS) + return cost->cvtss2sd * size / 64; + return cost->cvtss2sd; + } + if (size < 512) + return cost->vcvtps2pd256; + else + return cost->vcvtps2pd512; +} + /* Compute a (partial) cost for rtx X. Return true if the complete cost has been computed, and false if subexpressions should be scanned. In either case, *TOTAL contains the cost result. */ @@ -22479,17 +22499,18 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno, return false; case FLOAT_EXTEND: + /* x87 represents all values extended to 80bit. */ if (!SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode)) *total = 0; else - *total = ix86_vec_cost (mode, cost->addss); + *total = vec_fp_conversion_cost (cost, GET_MODE_BITSIZE (mode)); return false; case FLOAT_TRUNCATE: if (!SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode)) *total = cost->fadd; else - *total = ix86_vec_cost (mode, cost->addss); + *total = vec_fp_conversion_cost (cost, GET_MODE_BITSIZE (mode)); return false; case ABS: @@ -23164,6 +23185,12 @@ x86_print_call_or_nop (FILE *file, const char *target) if (flag_nop_mcount || !strcmp (target, "nop")) /* 5 byte nop: nopl 0(%[re]ax,%[re]ax,1) */ fprintf (file, "1:" ASM_BYTE "0x0f, 0x1f, 0x44, 0x00, 0x00\n"); + else if (!TARGET_PECOFF && flag_pic) + { + gcc_assert (flag_plt); + + fprintf (file, "1:\tcall\t%s@PLT\n", target); + } else fprintf (file, "1:\tcall\t%s\n", target); } @@ -23327,7 +23354,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) break; case CM_SMALL_PIC: case CM_MEDIUM_PIC: - if (!ix86_direct_extern_access) + if (!flag_plt) { if (ASSEMBLER_DIALECT == ASM_INTEL) fprintf (file, "1:\tcall\t[QWORD PTR %s@GOTPCREL[rip]]\n", @@ -23358,7 +23385,9 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) "\tleal\t%sP%d@GOTOFF(%%ebx), %%" PROFILE_COUNT_REGISTER "\n", LPREFIX, labelno); #endif - if (ASSEMBLER_DIALECT == ASM_INTEL) + if (flag_plt) + x86_print_call_or_nop (file, mcount_name); + else if (ASSEMBLER_DIALECT == ASM_INTEL) fprintf (file, "1:\tcall\t[DWORD PTR %s@GOT[ebx]]\n", mcount_name); else fprintf (file, "1:\tcall\t*%s@GOT(%%ebx)\n", mcount_name); @@ -24675,7 +24704,7 @@ ix86_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, switch (type_of_cost) { case scalar_stmt: - return fp ? ix86_cost->addss : COSTS_N_INSNS (1); + return fp ? ix86_cost->addss : COSTS_N_INSNS (1); case scalar_load: /* load/store costs are relative to register move which is 2. Recompute @@ -24746,7 +24775,11 @@ ix86_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, return ix86_cost->cond_not_taken_branch_cost; case vec_perm: + return ix86_vec_cost (mode, ix86_cost->sse_op); + case vec_promote_demote: + if (fp) + return vec_fp_conversion_cost (ix86_tune_cost, mode); return ix86_vec_cost (mode, ix86_cost->sse_op); case vec_construct: @@ -25224,6 +25257,32 @@ ix86_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) return new ix86_vector_costs (vinfo, costing_for_scalar); } +/* Return cost of statement doing FP conversion. */ + +static unsigned +fp_conversion_stmt_cost (machine_mode mode, gimple *stmt, bool scalar_p) +{ + int outer_size + = tree_to_uhwi + (TYPE_SIZE + (TREE_TYPE (gimple_assign_lhs (stmt)))); + int inner_size + = tree_to_uhwi + (TYPE_SIZE + (TREE_TYPE (gimple_assign_rhs1 (stmt)))); + int stmt_cost = vec_fp_conversion_cost + (ix86_tune_cost, GET_MODE_BITSIZE (mode)); + /* VEC_PACK_TRUNC_EXPR: If inner size is greater than outer size we will end + up doing two conversions and packing them. */ + if (!scalar_p && inner_size > outer_size) + { + int n = inner_size / outer_size; + stmt_cost = stmt_cost * n + + (n - 1) * ix86_vec_cost (mode, ix86_cost->sse_op); + } + return stmt_cost; +} + unsigned ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, stmt_vec_info stmt_info, slp_tree node, @@ -25334,6 +25393,9 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, (TREE_TYPE (gimple_assign_lhs (stmt_info->stmt)), TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt)))) stmt_cost = 0; + else if (fp) + stmt_cost = fp_conversion_stmt_cost (mode, stmt_info->stmt, + scalar_p); break; case BIT_IOR_EXPR: @@ -25375,6 +25437,10 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, break; } + if (kind == vec_promote_demote + && fp && FLOAT_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt)))) + stmt_cost = fp_conversion_stmt_cost (mode, stmt_info->stmt, scalar_p); + /* If we do elementwise loads into a vector then we are bound by latency and execution resources for the many scalar loads (AGU and load ports). Try to account for this by scaling the diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 8507243..18aa42d 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -207,6 +207,12 @@ struct processor_costs { const int divsd; /* cost of DIVSD instructions. */ const int sqrtss; /* cost of SQRTSS instructions. */ const int sqrtsd; /* cost of SQRTSD instructions. */ + const int cvtss2sd; /* cost SSE FP conversions, + such as CVTSS2SD. */ + const int vcvtps2pd256; /* cost 256bit packed FP conversions, + such as VCVTPD2PS with larger reg in ymm. */ + const int vcvtps2pd512; /* cost 512bit packed FP conversions, + such as VCVTPD2PS with larger reg in zmm. */ const int reassoc_int, reassoc_fp, reassoc_vec_int, reassoc_vec_fp; /* Specify reassociation width for integer, fp, vector integer and vector fp diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h index 9477345..cddcf61 100644 --- a/gcc/config/i386/x86-tune-costs.h +++ b/gcc/config/i386/x86-tune-costs.h @@ -121,16 +121,19 @@ struct processor_costs ix86_size_cost = {/* costs for tuning for size */ COSTS_N_BYTES (2), /* cost of FCHS instruction. */ COSTS_N_BYTES (2), /* cost of FSQRT instruction. */ - COSTS_N_BYTES (2), /* cost of cheap SSE instruction. */ - COSTS_N_BYTES (2), /* cost of ADDSS/SD SUBSS/SD insns. */ - COSTS_N_BYTES (2), /* cost of MULSS instruction. */ - COSTS_N_BYTES (2), /* cost of MULSD instruction. */ - COSTS_N_BYTES (2), /* cost of FMA SS instruction. */ - COSTS_N_BYTES (2), /* cost of FMA SD instruction. */ - COSTS_N_BYTES (2), /* cost of DIVSS instruction. */ - COSTS_N_BYTES (2), /* cost of DIVSD instruction. */ - COSTS_N_BYTES (2), /* cost of SQRTSS instruction. */ - COSTS_N_BYTES (2), /* cost of SQRTSD instruction. */ + COSTS_N_BYTES (4), /* cost of cheap SSE instruction. */ + COSTS_N_BYTES (4), /* cost of ADDSS/SD SUBSS/SD insns. */ + COSTS_N_BYTES (4), /* cost of MULSS instruction. */ + COSTS_N_BYTES (4), /* cost of MULSD instruction. */ + COSTS_N_BYTES (4), /* cost of FMA SS instruction. */ + COSTS_N_BYTES (4), /* cost of FMA SD instruction. */ + COSTS_N_BYTES (4), /* cost of DIVSS instruction. */ + COSTS_N_BYTES (4), /* cost of DIVSD instruction. */ + COSTS_N_BYTES (4), /* cost of SQRTSS instruction. */ + COSTS_N_BYTES (4), /* cost of SQRTSD instruction. */ + COSTS_N_BYTES (4), /* cost of CVTSS2SD etc. */ + COSTS_N_BYTES (4), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_BYTES (6), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ ix86_size_memcpy, ix86_size_memset, @@ -243,6 +246,9 @@ struct processor_costs i386_cost = { /* 386 specific costs */ COSTS_N_INSNS (88), /* cost of DIVSD instruction. */ COSTS_N_INSNS (122), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (122), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (27), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (54), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (108), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ i386_memcpy, i386_memset, @@ -356,6 +362,9 @@ struct processor_costs i486_cost = { /* 486 specific costs */ COSTS_N_INSNS (74), /* cost of DIVSD instruction. */ COSTS_N_INSNS (83), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (83), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (8), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (16), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (32), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ i486_memcpy, i486_memset, @@ -467,6 +476,9 @@ struct processor_costs pentium_cost = { COSTS_N_INSNS (39), /* cost of DIVSD instruction. */ COSTS_N_INSNS (70), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (70), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ pentium_memcpy, pentium_memset, @@ -571,6 +583,9 @@ struct processor_costs lakemont_cost = { COSTS_N_INSNS (60), /* cost of DIVSD instruction. */ COSTS_N_INSNS (31), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (63), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (5), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (10), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (20), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ pentium_memcpy, pentium_memset, @@ -690,6 +705,9 @@ struct processor_costs pentiumpro_cost = { COSTS_N_INSNS (18), /* cost of DIVSD instruction. */ COSTS_N_INSNS (31), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (31), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ pentiumpro_memcpy, pentiumpro_memset, @@ -800,6 +818,9 @@ struct processor_costs geode_cost = { COSTS_N_INSNS (47), /* cost of DIVSD instruction. */ COSTS_N_INSNS (54), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (54), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (6), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (12), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (24), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ geode_memcpy, geode_memset, @@ -913,6 +934,9 @@ struct processor_costs k6_cost = { COSTS_N_INSNS (56), /* cost of DIVSD instruction. */ COSTS_N_INSNS (56), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (56), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (2), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (4), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (8), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ k6_memcpy, k6_memset, @@ -1027,6 +1051,9 @@ struct processor_costs athlon_cost = { COSTS_N_INSNS (24), /* cost of DIVSD instruction. */ COSTS_N_INSNS (19), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (19), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (8), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (16), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ athlon_memcpy, athlon_memset, @@ -1150,6 +1177,9 @@ struct processor_costs k8_cost = { COSTS_N_INSNS (20), /* cost of DIVSD instruction. */ COSTS_N_INSNS (19), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (27), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (8), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (16), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ k8_memcpy, k8_memset, @@ -1281,6 +1311,9 @@ struct processor_costs amdfam10_cost = { COSTS_N_INSNS (20), /* cost of DIVSD instruction. */ COSTS_N_INSNS (19), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (27), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (8), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (16), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ amdfam10_memcpy, amdfam10_memset, @@ -1405,6 +1438,9 @@ const struct processor_costs bdver_cost = { COSTS_N_INSNS (27), /* cost of DIVSD instruction. */ COSTS_N_INSNS (15), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (26), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (7), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (14), /* cost of 512bit VCVTPS2PD etc. */ 1, 2, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ bdver_memcpy, bdver_memset, @@ -1553,6 +1589,10 @@ struct processor_costs znver1_cost = { COSTS_N_INSNS (13), /* cost of DIVSD instruction. */ COSTS_N_INSNS (10), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (15), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + /* Real latency is 4, but for split regs multiply cost of half op by 2. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ /* Zen can execute 4 integer operations per cycle. FP operations take 3 cycles and it can execute 2 integer additions and 2 multiplications thus reassociation may make sense up to with of 6. SPEC2k6 bencharks suggests @@ -1712,6 +1752,9 @@ struct processor_costs znver2_cost = { COSTS_N_INSNS (13), /* cost of DIVSD instruction. */ COSTS_N_INSNS (10), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (15), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (5), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (10), /* cost of 512bit VCVTPS2PD etc. */ /* Zen can execute 4 integer operations per cycle. FP operations take 3 cycles and it can execute 2 integer additions and 2 multiplications thus reassociation may make sense up to with of 6. @@ -1847,6 +1890,9 @@ struct processor_costs znver3_cost = { COSTS_N_INSNS (13), /* cost of DIVSD instruction. */ COSTS_N_INSNS (10), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (15), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (5), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (10), /* cost of 512bit VCVTPS2PD etc. */ /* Zen can execute 4 integer operations per cycle. FP operations take 3 cycles and it can execute 2 integer additions and 2 multiplications thus reassociation may make sense up to with of 6. @@ -1984,6 +2030,10 @@ struct processor_costs znver4_cost = { COSTS_N_INSNS (13), /* cost of DIVSD instruction. */ COSTS_N_INSNS (15), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (21), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (5), /* cost of 256bit VCVTPS2PD etc. */ + /* Real latency is 6, but for split regs multiply cost of half op by 2. */ + COSTS_N_INSNS (10), /* cost of 512bit VCVTPS2PD etc. */ /* Zen can execute 4 integer operations per cycle. FP operations take 3 cycles and it can execute 2 integer additions and 2 multiplications thus reassociation may make sense up to with of 6. @@ -2135,6 +2185,9 @@ struct processor_costs znver5_cost = { COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ /* DIVSD has throughtput 0.13 and latency 20. */ COSTS_N_INSNS (20), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (5), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (5), /* cost of 512bit VCVTPS2PD etc. */ /* Zen5 can execute: - integer ops: 6 per cycle, at most 3 multiplications. latency 1 for additions, 3 for multiplications (pipelined) @@ -2274,6 +2327,9 @@ struct processor_costs skylake_cost = { COSTS_N_INSNS (14), /* cost of DIVSD instruction. */ COSTS_N_INSNS (12), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (2), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (2), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (4), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 2, 2, /* reassoc int, fp, vec_int, vec_fp. */ skylake_memcpy, skylake_memset, @@ -2403,6 +2459,9 @@ struct processor_costs icelake_cost = { COSTS_N_INSNS (14), /* cost of DIVSD instruction. */ COSTS_N_INSNS (12), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (2), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (2), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (2), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 2, 2, /* reassoc int, fp, vec_int, vec_fp. */ icelake_memcpy, icelake_memset, @@ -2526,6 +2585,9 @@ struct processor_costs alderlake_cost = { COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (2), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (2), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (2), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ alderlake_memcpy, alderlake_memset, @@ -2642,6 +2704,9 @@ const struct processor_costs btver1_cost = { COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (48), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (7), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (14), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ btver1_memcpy, btver1_memset, @@ -2755,6 +2820,9 @@ const struct processor_costs btver2_cost = { COSTS_N_INSNS (19), /* cost of DIVSD instruction. */ COSTS_N_INSNS (16), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (21), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (4), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (7), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (14), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ btver2_memcpy, btver2_memset, @@ -2867,6 +2935,9 @@ struct processor_costs pentium4_cost = { COSTS_N_INSNS (38), /* cost of DIVSD instruction. */ COSTS_N_INSNS (23), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (38), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (10), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (20), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (40), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ pentium4_memcpy, pentium4_memset, @@ -2982,6 +3053,9 @@ struct processor_costs nocona_cost = { COSTS_N_INSNS (40), /* cost of DIVSD instruction. */ COSTS_N_INSNS (32), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (41), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (10), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (20), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (40), /* cost of 512bit VCVTPS2PD etc. */ 1, 1, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ nocona_memcpy, nocona_memset, @@ -3095,6 +3169,9 @@ struct processor_costs atom_cost = { COSTS_N_INSNS (60), /* cost of DIVSD instruction. */ COSTS_N_INSNS (31), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (63), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (6), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (12), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (24), /* cost of 512bit VCVTPS2PD etc. */ 2, 2, 2, 2, /* reassoc int, fp, vec_int, vec_fp. */ atom_memcpy, atom_memset, @@ -3208,6 +3285,9 @@ struct processor_costs slm_cost = { COSTS_N_INSNS (69), /* cost of DIVSD instruction. */ COSTS_N_INSNS (20), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (35), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 1, 2, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ slm_memcpy, slm_memset, @@ -3335,6 +3415,9 @@ struct processor_costs tremont_cost = { COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ tremont_memcpy, tremont_memset, @@ -3448,6 +3531,9 @@ struct processor_costs intel_cost = { COSTS_N_INSNS (20), /* cost of DIVSD instruction. */ COSTS_N_INSNS (40), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (40), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (8), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (16), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (32), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 1, 1, /* reassoc int, fp, vec_int, vec_fp. */ intel_memcpy, intel_memset, @@ -3566,6 +3652,9 @@ struct processor_costs lujiazui_cost = { COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ COSTS_N_INSNS (32), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (60), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ lujiazui_memcpy, lujiazui_memset, @@ -3682,6 +3771,9 @@ struct processor_costs yongfeng_cost = { COSTS_N_INSNS (14), /* cost of DIVSD instruction. */ COSTS_N_INSNS (20), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (35), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 4, 4, 4, 4, /* reassoc int, fp, vec_int, vec_fp. */ yongfeng_memcpy, yongfeng_memset, @@ -3798,6 +3890,9 @@ struct processor_costs shijidadao_cost = { COSTS_N_INSNS (14), /* cost of DIVSD instruction. */ COSTS_N_INSNS (11), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (6), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (12), /* cost of 512bit VCVTPS2PD etc. */ 4, 4, 4, 4, /* reassoc int, fp, vec_int, vec_fp. */ shijidadao_memcpy, shijidadao_memset, @@ -3922,6 +4017,9 @@ struct processor_costs generic_cost = { COSTS_N_INSNS (17), /* cost of DIVSD instruction. */ COSTS_N_INSNS (14), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (18), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (3), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (4), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (5), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 3, 3, /* reassoc int, fp, vec_int, vec_fp. */ generic_memcpy, generic_memset, @@ -4051,6 +4149,9 @@ struct processor_costs core_cost = { COSTS_N_INSNS (32), /* cost of DIVSD instruction. */ COSTS_N_INSNS (30), /* cost of SQRTSS instruction. */ COSTS_N_INSNS (58), /* cost of SQRTSD instruction. */ + COSTS_N_INSNS (2), /* cost of CVTSS2SD etc. */ + COSTS_N_INSNS (2), /* cost of 256bit VCVTPS2PD etc. */ + COSTS_N_INSNS (2), /* cost of 512bit VCVTPS2PD etc. */ 1, 4, 2, 2, /* reassoc int, fp, vec_int, vec_fp. */ core_memcpy, core_memset, diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc index 28da43c..f893971 100644 --- a/gcc/config/nvptx/nvptx.cc +++ b/gcc/config/nvptx/nvptx.cc @@ -7789,6 +7789,18 @@ nvptx_asm_output_def_from_decls (FILE *stream, tree name, #endif cgraph_node *cnode = cgraph_node::get (name); +#ifdef ACCEL_COMPILER + /* For nvptx offloading, make sure to emit C++ constructor, destructor aliases [PR97106] + + For some reason (yet to be analyzed), they're not 'cnode->referred_to_p ()'. + (..., or that's not the right approach at all; + <https://inbox.sourceware.org/87v7rx8lbx.fsf@euler.schwinge.ddns.net> + "Re: [committed][nvptx] Use .alias directive for mptx >= 6.3"). */ + if (DECL_CXX_CONSTRUCTOR_P (name) + || DECL_CXX_DESTRUCTOR_P (name)) + ; + else +#endif if (!cnode->referred_to_p ()) /* Prevent "Internal error: reference to deleted section". */ return; @@ -7893,8 +7905,6 @@ nvptx_asm_output_def_from_decls (FILE *stream, tree name, #define TARGET_ASM_DECLARE_CONSTANT_NAME nvptx_asm_declare_constant_name #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true -#undef TARGET_ASM_NEED_VAR_DECL_BEFORE_USE -#define TARGET_ASM_NEED_VAR_DECL_BEFORE_USE true #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG nvptx_reorg diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md index 5ed5e18..d0919ec 100644 --- a/gcc/config/riscv/bitmanip.md +++ b/gcc/config/riscv/bitmanip.md @@ -908,6 +908,24 @@ "bext\t%0,%1,%2" [(set_attr "type" "bitmanip")]) +;; We do not define SHIFT_COUNT_TRUNCATED, so we have to have variants +;; that mask/extend the count if we want to eliminate those ops +;; +;; We could (in theory) use GPR for the various modes, but I haven't +;; seen those cases appear in practice. Without a testcase I've +;; elected to keep the modes X which is easy to reason about. +(define_insn "*bext<mode>_mask_pos" + [(set (match_operand:X 0 "register_operand" "=r") + (zero_extract:X (match_operand:X 1 "register_operand" "r") + (const_int 1) + (and:X + (match_operand:X 2 "register_operand" "r") + (match_operand 3 "const_int_operand"))))] + "(TARGET_ZBS + && INTVAL (operands[3]) + 1 == GET_MODE_BITSIZE (<MODE>mode))" + "bext\t%0,%1,%2" + [(set_attr "type" "bitmanip")]) + ;; This is a bext followed by a seqz. Normally this would be a 3->2 split ;; But the and-not pattern with a constant operand is a define_insn_and_split, ;; so this looks like a 2->2 split, which combine rejects. So implement it @@ -1245,3 +1263,41 @@ expand_crc_using_clmul (<SUBX:MODE>mode, <SUBX1:MODE>mode, operands); DONE; }) + +;; If we have an XOR/IOR with a constant operand (C) and the we can +;; synthesize ~C more efficiently than C, then synthesize ~C and use +;; xnor/orn instead. +;; +;; The same can be done for AND, but mvconst_internal's issues get in +;; the way. That's future work. +(define_split + [(set (match_operand:X 0 "register_operand") + (any_or:X (match_operand:X 1 "register_operand") + (match_operand:X 2 "const_int_operand"))) + (clobber (match_operand:X 3 "register_operand"))] + "TARGET_ZBB + && (riscv_const_insns (operands[2], true) + > riscv_const_insns (GEN_INT (~INTVAL (operands[2])), true))" + [(const_int 0)] +{ + /* Get the inverted constant into the temporary register. */ + riscv_emit_move (operands[3], GEN_INT (~INTVAL (operands[2]))); + + /* For xnor, the NOT operation is in a different position. So + we have to customize the split code we generate a bit. + + It is expected that AND will be handled like IOR in the future. */ + if (<CODE> == XOR) + { + rtx x = gen_rtx_XOR (<X:MODE>mode, operands[1], operands[3]); + x = gen_rtx_NOT (<X:MODE>mode, x); + emit_insn (gen_rtx_SET (operands[0], x)); + } + else + { + rtx x = gen_rtx_NOT (<X:MODE>mode, operands[3]); + x = gen_rtx_IOR (<X:MODE>mode, x, operands[1]); + emit_insn (gen_rtx_SET (operands[0], x)); + } + DONE; +}) diff --git a/gcc/config/riscv/gnu.h b/gcc/config/riscv/gnu.h new file mode 100644 index 0000000..047399b --- /dev/null +++ b/gcc/config/riscv/gnu.h @@ -0,0 +1,59 @@ +/* Definitions for RISC-V GNU/Hurd systems with ELF format. + Copyright (C) 1998-2025 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define TARGET_OS_CPP_BUILTINS() \ + do { \ + GNU_USER_TARGET_OS_CPP_BUILTINS(); \ + } while (0) + +#define GNU_USER_DYNAMIC_LINKER "/lib/ld-riscv" XLEN_SPEC "-" ABI_SPEC ".so.1" + +#define ICACHE_FLUSH_FUNC "__riscv_flush_icache" + +#define CPP_SPEC "%{pthread:-D_REENTRANT}" + +#define LD_EMUL_SUFFIX \ + "%{mabi=lp64d:}" \ + "%{mabi=lp64f:_lp64f}" \ + "%{mabi=lp64:_lp64}" \ + "%{mabi=ilp32d:}" \ + "%{mabi=ilp32f:_ilp32f}" \ + "%{mabi=ilp32:_ilp32}" + +#define LINK_SPEC "\ +-melf" XLEN_SPEC DEFAULT_ENDIAN_SPEC "riscv" LD_EMUL_SUFFIX " \ +%{mno-relax:--no-relax} \ +-X \ +%{mbig-endian:-EB} \ +%{mlittle-endian:-EL} \ +%{shared} \ + %{!shared: \ + %{!static: \ + %{!static-pie: \ + %{rdynamic:-export-dynamic} \ + -dynamic-linker " GNU_USER_DYNAMIC_LINKER "}} \ + %{static:-static} %{static-pie:-static -pie --no-dynamic-linker -z text}}" + +#define STARTFILE_PREFIX_SPEC \ + "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \ + "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \ + "/lib/ " \ + "/usr/lib/ " + +#define RISCV_USE_CUSTOMISED_MULTI_LIB select_by_abi diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 1d96865..8ad3025 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -257,11 +257,7 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const { std::string local_arch = m_subset_list->to_string (true); const char* local_arch_str = local_arch.c_str (); - struct cl_target_option *default_opts - = TREE_TARGET_OPTION (target_option_default_node); - if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string) - free (CONST_CAST (void *, (const void *) opts->x_riscv_arch_string)); - opts->x_riscv_arch_string = xstrdup (local_arch_str); + opts->x_riscv_arch_string = ggc_strdup (local_arch_str); riscv_set_arch_by_subset_list (m_subset_list, opts); } diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 38f3ae7..bad59e2 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -10382,7 +10382,7 @@ riscv_file_end () fprintf (asm_out_file, "1:\n"); /* pr_type. */ - fprintf (asm_out_file, "\t.p2align\t3\n"); + fprintf (asm_out_file, "\t.p2align\t%u\n", p2align); fprintf (asm_out_file, "2:\n"); fprintf (asm_out_file, "\t.long\t0xc0000000\n"); /* pr_datasz. */ @@ -13136,9 +13136,6 @@ parse_features_for_version (tree decl, DECL_SOURCE_LOCATION (decl)); gcc_assert (parse_res); - if (arch_string != default_opts->x_riscv_arch_string) - free (CONST_CAST (void *, (const void *) arch_string)); - cl_target_option_restore (&global_options, &global_options_set, &cur_target); } diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 2bcabd0..2759a4c 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -888,7 +888,7 @@ extern enum riscv_cc get_riscv_cc (const rtx use); #define ASM_OUTPUT_OPCODE(STREAM, PTR) \ (PTR) = riscv_asm_output_opcode(STREAM, PTR) -#define JUMP_TABLES_IN_TEXT_SECTION 0 +#define JUMP_TABLES_IN_TEXT_SECTION (riscv_cmodel == CM_LARGE) #define CASE_VECTOR_MODE SImode #define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 26a247c..eec9687 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -789,7 +789,7 @@ rtx t5 = gen_reg_rtx (DImode); rtx t6 = gen_reg_rtx (DImode); - riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]); + emit_insn (gen_addsi3_extended (t6, operands[1], operands[2])); if (GET_CODE (operands[1]) != CONST_INT) emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0)); else @@ -799,7 +799,10 @@ else t5 = operands[2]; emit_insn (gen_adddi3 (t3, t4, t5)); - emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0)); + rtx t7 = gen_lowpart (SImode, t6); + SUBREG_PROMOTED_VAR_P (t7) = 1; + SUBREG_PROMOTED_SET (t7, SRP_SIGNED); + emit_move_insn (operands[0], t7); riscv_expand_conditional_branch (operands[3], NE, t6, t3); } @@ -835,8 +838,11 @@ emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0)); else t3 = operands[1]; - riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]); - emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0)); + emit_insn (gen_addsi3_extended (t4, operands[1], operands[2])); + rtx t5 = gen_lowpart (SImode, t4); + SUBREG_PROMOTED_VAR_P (t5) = 1; + SUBREG_PROMOTED_SET (t5, SRP_SIGNED); + emit_move_insn (operands[0], t5); riscv_expand_conditional_branch (operands[3], LTU, t4, t3); } @@ -966,7 +972,7 @@ rtx t5 = gen_reg_rtx (DImode); rtx t6 = gen_reg_rtx (DImode); - riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]); + emit_insn (gen_subsi3_extended (t6, operands[1], operands[2])); if (GET_CODE (operands[1]) != CONST_INT) emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0)); else @@ -976,7 +982,10 @@ else t5 = operands[2]; emit_insn (gen_subdi3 (t3, t4, t5)); - emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0)); + rtx t7 = gen_lowpart (SImode, t6); + SUBREG_PROMOTED_VAR_P (t7) = 1; + SUBREG_PROMOTED_SET (t7, SRP_SIGNED); + emit_move_insn (operands[0], t7); riscv_expand_conditional_branch (operands[3], NE, t6, t3); } @@ -1015,8 +1024,11 @@ emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0)); else t3 = operands[1]; - riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]); - emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0)); + emit_insn (gen_subsi3_extended (t4, operands[1], operands[2])); + rtx t5 = gen_lowpart (SImode, t4); + SUBREG_PROMOTED_VAR_P (t5) = 1; + SUBREG_PROMOTED_SET (t5, SRP_SIGNED); + emit_move_insn (operands[0], t5); riscv_expand_conditional_branch (operands[3], LTU, t3, t4); } diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index edb2c96..a3d966e 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -2541,10 +2541,17 @@ (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1 (match_operand:BLK 2 "memory_operand")] ;; String2 UNSPEC_CMPSTRN)) - (use (match_operand:SI 3 "register_operand")) ;; Max Length + (use (match_operand:SI 3 "nonmemory_operand")) ;; Max Length (match_operand:SI 4 "immediate_operand")] ;; Known Align "rx_allow_string_insns" { + bool const_len = CONST_INT_P (operands[3]); + if (const_len && operands[3] == CONST0_RTX (SImode)) + { + emit_move_insn (operands[0], CONST0_RTX (SImode)); + DONE; + } + rtx str1 = gen_rtx_REG (SImode, 1); rtx str2 = gen_rtx_REG (SImode, 2); rtx len = gen_rtx_REG (SImode, 3); @@ -2553,6 +2560,13 @@ emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX)); emit_move_insn (len, operands[3]); + /* Set flags in case len is zero */ + if (!const_len) + { + emit_insn (gen_setpsw (GEN_INT ('C'))); + emit_insn (gen_setpsw (GEN_INT ('Z'))); + } + emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2])); DONE; } @@ -2590,9 +2604,7 @@ (clobber (reg:SI 3)) (clobber (reg:CC CC_REG))] "rx_allow_string_insns" - "setpsw z ; Set flags in case len is zero - setpsw c - scmpu ; Perform the string comparison + "scmpu ; Perform the string comparison mov #-1, %0 ; Set up -1 result (which cannot be created ; by the SC insn) bnc ?+ ; If Carry is not set skip over diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 874974a..05b9da6 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -3597,7 +3597,7 @@ (match_operand:BLK 1 "memory_operand" "")) (use (match_operand 2 "const_int_operand" "")) (use (match_operand 3 "immediate_operand" "")) - (clobber (scratch))] + (clobber (match_scratch 4))] "reload_completed" [(parallel [(set (match_dup 0) (match_dup 1)) @@ -3609,7 +3609,7 @@ (match_operand:BLK 1 "memory_operand" "")) (use (match_operand 2 "register_operand" "")) (use (match_operand 3 "memory_operand" "")) - (clobber (scratch))] + (clobber (match_scratch 4))] "reload_completed" [(parallel [(unspec [(match_dup 2) (match_dup 3) @@ -3623,14 +3623,14 @@ (match_operand:BLK 1 "memory_operand" "")) (use (match_operand 2 "register_operand" "")) (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN))) - (clobber (scratch))] + (clobber (match_scratch 3))] "TARGET_Z10 && reload_completed" [(parallel [(unspec [(match_dup 2) (const_int 0) - (label_ref (match_dup 3))] UNSPEC_EXECUTE) + (label_ref (match_dup 4))] UNSPEC_EXECUTE) (set (match_dup 0) (match_dup 1)) (use (const_int 1))])] - "operands[3] = gen_label_rtx ();") + "operands[4] = gen_label_rtx ();") (define_split [(set (match_operand:BLK 0 "memory_operand" "") @@ -3852,7 +3852,7 @@ (const_int 0)) (use (match_operand 1 "const_int_operand" "")) (use (match_operand 2 "immediate_operand" "")) - (clobber (scratch)) + (clobber (match_scratch 3)) (clobber (reg:CC CC_REGNUM))] "reload_completed" [(parallel @@ -3866,7 +3866,7 @@ (const_int 0)) (use (match_operand 1 "register_operand" "")) (use (match_operand 2 "memory_operand" "")) - (clobber (scratch)) + (clobber (match_scratch 3)) (clobber (reg:CC CC_REGNUM))] "reload_completed" [(parallel @@ -3882,7 +3882,7 @@ (const_int 0)) (use (match_operand 1 "register_operand" "")) (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN))) - (clobber (scratch)) + (clobber (match_scratch 2)) (clobber (reg:CC CC_REGNUM))] "TARGET_Z10 && reload_completed" [(parallel @@ -4047,7 +4047,7 @@ (match_operand:BLK 1 "memory_operand" ""))) (use (match_operand 2 "const_int_operand" "")) (use (match_operand 3 "immediate_operand" "")) - (clobber (scratch))] + (clobber (match_scratch 4))] "reload_completed" [(parallel [(set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1))) @@ -4060,7 +4060,7 @@ (match_operand:BLK 1 "memory_operand" ""))) (use (match_operand 2 "register_operand" "")) (use (match_operand 3 "memory_operand" "")) - (clobber (scratch))] + (clobber (match_scratch 4))] "reload_completed" [(parallel [(unspec [(match_dup 2) (match_dup 3) @@ -4075,7 +4075,7 @@ (match_operand:BLK 1 "memory_operand" ""))) (use (match_operand 2 "register_operand" "")) (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN))) - (clobber (scratch))] + (clobber (match_scratch 3))] "TARGET_Z10 && reload_completed" [(parallel [(unspec [(match_dup 2) (const_int 0) diff --git a/gcc/config/sh/sh-modes.def b/gcc/config/sh/sh-modes.def index 80650b4..e31ae69 100644 --- a/gcc/config/sh/sh-modes.def +++ b/gcc/config/sh/sh-modes.def @@ -17,6 +17,12 @@ 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/>. */ +/* SH has the same reversed quiet bit as MIPS. */ +RESET_FLOAT_FORMAT (SF, mips_single_format); +RESET_FLOAT_FORMAT (DF, mips_double_format); +/* TFmode: IEEE quad floating point (software). */ +FLOAT_MODE (TF, 16, mips_quad_format); + /* Vector modes. */ VECTOR_MODE (INT, QI, 2); /* V2QI */ VECTOR_MODES (INT, 4); /* V4QI V2HI */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index aa2f076..6975efb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,61 @@ +2025-04-19 Jason Merrill <jason@redhat.com> + + * coroutines.cc (coro_build_expr_stmt) + (coro_build_cvt_void_expr_stmt): Remove. + (build_actor_fn): Use finish_expr_stmt. + * semantics.cc (finish_expr_stmt): Avoid wrapping statement in + EXPR_STMT. + (finish_stmt_expr_expr): Add comment. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * constexpr.cc (is_valid_constexpr_fn): Improve diagnostic. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * constexpr.cc (cxx_eval_outermost_constant_expr): Give both + expression and allocation location in allocated storage diagnostics. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * name-lookup.cc (name_lookup::preserve_state): Fix reserve call. + * rtti.cc (get_tinfo_desc): Use vec_safe_grow_cleared. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * semantics.cc (finish_type_pack_element): Add more info + to diagnostics. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * decl.cc (cp_make_fname_decl): Prevent silent failure. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * lex.cc (unqualified_name_lookup_error): Handle 'requires' better. + +2025-04-17 Jason Merrill <jason@redhat.com> + + PR c++/113360 + * cp-tree.h (struct language_function): Add erroneous bit. + * constexpr.cc (explain_invalid_constexpr_fn): Return if set. + (cxx_eval_call_expression): Quiet if set. + * parser.cc (cp_parser_function_definition_after_declarator) + * pt.cc (instantiate_body): Set it. + +2025-04-16 Jason Merrill <jason@redhat.com> + + PR c++/114772 + PR c++/101180 + * pt.cc (apply_late_template_attributes): Also override + target_option_current_node. + +2025-04-16 Jason Merrill <jason@redhat.com> + + PR c++/116954 + * contracts.cc (remove_contract_attributes): Preserve flags + on the attribute list. + 2025-04-15 Nathaniel Shead <nathanieloshead@gmail.com> PR c++/119755 diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 4346b29..f56c5c4 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -307,7 +307,14 @@ is_valid_constexpr_fn (tree fun, bool complain) { ret = false; if (complain) - error ("%q#T has virtual base classes", DECL_CONTEXT (fun)); + { + if (DECL_CONSTRUCTOR_P (fun)) + error ("%<constexpr%> constructor in %q#T that has " + "virtual base classes", DECL_CONTEXT (fun)); + else + error ("%<constexpr%> destructor in %q#T that has " + "virtual base classes", DECL_CONTEXT (fun)); + } } return ret; @@ -1048,6 +1055,12 @@ explain_invalid_constexpr_fn (tree fun) { static hash_set<tree> *diagnosed; tree body; + + /* Don't try to explain a function we already complained about. */ + if (function *f = DECL_STRUCT_FUNCTION (fun)) + if (f->language->erroneous) + return; + /* In C++23, a function marked 'constexpr' may not actually be a constant expression. We haven't diagnosed the problem yet: -Winvalid-constexpr wasn't enabled. The function was called, so diagnose why it cannot be @@ -3079,6 +3092,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } constexpr_ctx new_ctx = *ctx; + ctx = &new_ctx; if (DECL_CONSTRUCTOR_P (fun) && !ctx->object && TREE_CODE (t) == AGGR_INIT_EXPR) { @@ -3088,16 +3102,12 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL); CONSTRUCTOR_NO_CLEARING (ctor) = true; ctx->global->put_value (new_ctx.object, ctor); - ctx = &new_ctx; } /* An immediate invocation is manifestly constant evaluated including the arguments of the call, so use mce_true even for the argument evaluation. */ if (DECL_IMMEDIATE_FUNCTION_P (fun)) - { - new_ctx.manifestly_const_eval = mce_true; - ctx = &new_ctx; - } + new_ctx.manifestly_const_eval = mce_true; /* We used to shortcut trivial constructor/op= here, but nowadays we can only get a trivial function here with -fno-elide-constructors. */ @@ -3185,6 +3195,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } } + /* Don't complain about problems evaluating an ill-formed function. */ + if (function *f = DECL_STRUCT_FUNCTION (fun)) + if (f->language->erroneous) + new_ctx.quiet = true; + int depth_ok = push_cx_call_context (t); /* Remember the object we are constructing or destructing. */ @@ -9254,9 +9269,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (heap_var) { if (!allow_non_constant && !non_constant_p) - error_at (DECL_SOURCE_LOCATION (heap_var), - "%qE is not a constant expression because it refers to " - "a result of %<operator new%>", t); + { + error ("%qE is not a constant expression because it refers to " + "a result of %<operator new%>", t); + inform (DECL_SOURCE_LOCATION (heap_var), "allocated here"); + } r = t; non_constant_p = true; } @@ -9265,9 +9282,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (DECL_NAME (heap_var) != heap_deleted_identifier) { if (!allow_non_constant && !non_constant_p) - error_at (DECL_SOURCE_LOCATION (heap_var), - "%qE is not a constant expression because allocated " - "storage has not been deallocated", t); + { + error ("%qE is not a constant expression because allocated " + "storage has not been deallocated", t); + inform (DECL_SOURCE_LOCATION (heap_var), "allocated here"); + } r = t; non_constant_p = true; } diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc index f2b126c..3ca2102 100644 --- a/gcc/cp/contracts.cc +++ b/gcc/cp/contracts.cc @@ -863,7 +863,11 @@ remove_contract_attributes (tree fndecl) tree list = NULL_TREE; for (tree p = DECL_ATTRIBUTES (fndecl); p; p = TREE_CHAIN (p)) if (!cxx_contract_attribute_p (p)) - list = tree_cons (TREE_PURPOSE (p), TREE_VALUE (p), list); + { + tree nl = copy_node (p); + TREE_CHAIN (nl) = list; + list = nl; + } DECL_ATTRIBUTES (fndecl) = nreverse (list); } diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index b92d09f..743da06 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1852,21 +1852,6 @@ coro_build_frame_access_expr (tree coro_ref, tree member_id, bool preserve_ref, return expr; } -/* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */ - -static tree -coro_build_expr_stmt (tree expr, location_t loc) -{ - return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr)); -} - -static tree -coro_build_cvt_void_expr_stmt (tree expr, location_t loc) -{ - tree t = build1 (CONVERT_EXPR, void_type_node, expr); - return coro_build_expr_stmt (t, loc); -} - /* Helpers to build an artificial var, with location LOC, NAME and TYPE, in CTX, and with initializer INIT. */ @@ -2582,8 +2567,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error); r = cp_build_init_expr (ash, hfa); - r = coro_build_cvt_void_expr_stmt (r, loc); - add_stmt (r); + finish_expr_stmt (r); release_tree_vector (args); /* Now we know the real promise, and enough about the frame layout to @@ -2678,8 +2662,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody, we must tail call them. However, some targets do not support indirect tail calls to arbitrary callees. See PR94359. */ CALL_EXPR_TAILCALL (resume) = true; - resume = coro_build_cvt_void_expr_stmt (resume, loc); - add_stmt (resume); + finish_expr_stmt (resume); r = build_stmt (loc, RETURN_EXPR, NULL); gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 55f986e..7798efb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2206,6 +2206,8 @@ struct GTY(()) language_function { BOOL_BITFIELD invalid_constexpr : 1; BOOL_BITFIELD throwing_cleanup : 1; + /* True if we gave any errors in this function. */ + BOOL_BITFIELD erroneous : 1; hash_table<named_label_hash> *x_named_labels; diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 4e97093..84398e5 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -5339,6 +5339,8 @@ cp_make_fname_decl (location_t loc, tree id, int type_dep) decl = pushdecl_outermost_localscope (decl); if (decl != error_mark_node) add_decl_expr (decl); + else + gcc_assert (seen_error ()); } else { diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc index c12b084..12af81e 100644 --- a/gcc/cp/lex.cc +++ b/gcc/cp/lex.cc @@ -749,6 +749,9 @@ unqualified_name_lookup_error (tree name, location_t loc) if (IDENTIFIER_ANY_OP_P (name)) error_at (loc, "%qD not defined", name); + else if (!flag_concepts && name == ridpointers[(int)RID_REQUIRES]) + error_at (loc, "%<requires%> only available with %<-std=c++20%> or " + "%<-fconcepts%>"); else { if (!objc_diagnose_private_ivar (name)) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 1cd982e..498126a 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -583,7 +583,7 @@ name_lookup::preserve_state () if (previous) { unsigned length = vec_safe_length (previous->scopes); - vec_safe_reserve (previous->scopes, length * 2); + vec_safe_reserve (previous->scopes, length); for (unsigned ix = length; ix--;) { tree decl = (*previous->scopes)[ix]; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 812a7c5..3628cfe 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -33634,6 +33634,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, = parser->num_template_parameter_lists; parser->num_template_parameter_lists = 0; + int errs = errorcount + sorrycount; + /* If the next token is `try', `__transaction_atomic', or `__transaction_relaxed`, then we are looking at either function-try-block or function-transaction-block. Note that all of these include the @@ -33653,6 +33655,9 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, fn = finish_function (inline_p); check_module_decl_linkage (fn); + if ((errorcount + sorrycount) > errs) + DECL_STRUCT_FUNCTION (fn)->language->erroneous = true; + if (modules_p () && !inline_p && TYPE_P (DECL_CONTEXT (fn)) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 4349b19..a71705f 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12429,6 +12429,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute, NULL); auto o5 = make_temp_override (scope_chain->omp_begin_assumes, NULL); + auto o6 = make_temp_override (target_option_current_node, + target_option_default_node); cplus_decl_attributes (decl_p, late_attrs, attr_flags); @@ -27756,6 +27758,11 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p) if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern)) cp_check_omp_declare_reduction (d); + + if (int errs = errorcount + sorrycount) + if (errs > current_tinst_level->errors) + if (function *f = DECL_STRUCT_FUNCTION (d)) + f->language->erroneous = true; } /* We're not deferring instantiation any more. */ diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc index 3539962..18bc479 100644 --- a/gcc/cp/rtti.cc +++ b/gcc/cp/rtti.cc @@ -1318,18 +1318,9 @@ get_pseudo_ti_index (tree type) static tinfo_s * get_tinfo_desc (unsigned ix) { - unsigned len = tinfo_descs->length (); - - if (len <= ix) - { - /* too short, extend. */ - len = ix + 1 - len; - vec_safe_reserve (tinfo_descs, len); - tinfo_s elt; - elt.type = elt.vtable = elt.name = NULL_TREE; - while (len--) - tinfo_descs->quick_push (elt); - } + if (tinfo_descs->length () <= ix) + /* too short, extend. */ + vec_safe_grow_cleared (tinfo_descs, ix + 1); tinfo_s *res = &(*tinfo_descs)[ix]; diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index a10ef34..1aa35d3 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -1180,10 +1180,13 @@ finish_expr_stmt (tree expr) expr = error_mark_node; /* Simplification of inner statement expressions, compound exprs, - etc can result in us already having an EXPR_STMT. */ + etc can result in us already having an EXPR_STMT or other statement + tree. Don't wrap them in EXPR_STMT. */ if (TREE_CODE (expr) != CLEANUP_POINT_EXPR) { - if (TREE_CODE (expr) != EXPR_STMT) + if (TREE_CODE (expr) != EXPR_STMT + && !STATEMENT_CLASS_P (expr) + && TREE_CODE (expr) != STATEMENT_LIST) expr = build_stmt (loc, EXPR_STMT, expr); expr = maybe_cleanup_point_expr_void (expr); } @@ -3082,6 +3085,7 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr) } else if (processing_template_decl) { + /* Not finish_expr_stmt because we don't want convert_to_void. */ expr = build_stmt (input_location, EXPR_STMT, expr); expr = add_stmt (expr); /* Mark the last statement so that we can recognize it as such at @@ -5088,22 +5092,32 @@ static tree finish_type_pack_element (tree idx, tree types, tsubst_flags_t complain) { idx = maybe_constant_value (idx, NULL_TREE, mce_true); - if (TREE_CODE (idx) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (idx))) + if (!INTEGRAL_TYPE_P (TREE_TYPE (idx))) { if (complain & tf_error) - error ("pack index is not an integral constant"); + error ("pack index has non-integral type %qT", TREE_TYPE (idx)); + return error_mark_node; + } + if (TREE_CODE (idx) != INTEGER_CST) + { + if (complain & tf_error) + { + error ("pack index is not an integral constant"); + cxx_constant_value (idx); + } return error_mark_node; } if (tree_int_cst_sgn (idx) < 0) { if (complain & tf_error) - error ("pack index is negative"); + error ("pack index %qE is negative", idx); return error_mark_node; } if (wi::to_widest (idx) >= TREE_VEC_LENGTH (types)) { if (complain & tf_error) - error ("pack index is out of range"); + error ("pack index %qE is out of range for pack of length %qd", + idx, TREE_VEC_LENGTH (types)); return error_mark_node; } return TREE_VEC_ELT (types, tree_to_shwi (idx)); diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index b025453..f816c70 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,7 @@ +2025-04-17 Iain Buclaw <ibuclaw@gdcproject.org> + + * dmd/MERGE: Merge upstream dmd 956e73d64e. + 2025-04-15 Iain Buclaw <ibuclaw@gdcproject.org> PR d/119826 diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index ee5eb85..58d19b4 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -1b34fea4788136b54ec77c6ed9678754d109fc79 +956e73d64e532a68213970316c2590c572ec03f3 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/expressionsem.d b/gcc/d/dmd/expressionsem.d index 19111e3..b02f6ea 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -6978,10 +6978,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor while (1) { AttribDeclaration ad = s.isAttribDeclaration(); - if (!ad) - break; - if (ad.decl && ad.decl.length == 1) + if (ad && ad.decl && ad.decl.length == 1) s = (*ad.decl)[0]; + else + break; } //printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc); diff --git a/gcc/doc/cfg.texi b/gcc/doc/cfg.texi index b8c6427..bbd6694 100644 --- a/gcc/doc/cfg.texi +++ b/gcc/doc/cfg.texi @@ -297,10 +297,12 @@ edge. The opposite conversion is difficult, but should not happen anyway. The edges can be eliminated via @code{purge_dead_edges} call. @findex REG_EH_REGION, EDGE_ABNORMAL_CALL -In the RTL representation, the destination of an exception edge is -specified by @code{REG_EH_REGION} note attached to the insn. -In case of a trapping call the @code{EDGE_ABNORMAL_CALL} flag is set -too. In the @code{GIMPLE} representation, this extra flag is not set. +In the RTL representation, a @code{REG_EH_REGION} note is attached to +an instruction that can throw an exception. The destination of the +exception edge originating at such an instruction is specified by the +value of the @code{REG_EH_REGION} note. In case of a trapping call +the @code{EDGE_ABNORMAL_CALL} flag is set too. In the @code{GIMPLE} +representation, this extra flag is not set. @findex may_trap_p, tree_could_trap_p In the RTL representation, the predicate @code{may_trap_p} may be used diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 5bc2785..0978c4c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -12978,6 +12978,7 @@ C and/or C++ standards, while others remain specific to GNU C. * Binary constants:: Binary constants using the @samp{0b} prefix. * Dollar Signs:: Dollar sign is allowed in identifiers. * Character Escapes:: @samp{\e} stands for the character @key{ESC}. +* Raw String Literals:: C++ raw string literals are supported in C. * Alternate Keywords:: @code{__const__}, @code{__asm__}, etc., for header files. * Function Names:: Printable strings which are the name of the current function. @@ -13999,6 +14000,25 @@ machines, typically because the target assembler does not allow them. You can use the sequence @samp{\e} in a string or character constant to stand for the ASCII character @key{ESC}. +@node Raw String Literals +@subsection Raw String Literals +@cindex raw string literals +@cindex string literals, raw + +The C++11 standard added syntax for raw string literals prefixed +with @samp{R}. This syntax allows you to use an arbitrary delimiter +sequence instead of escaping special characters within the string. +For example, these string constants are all equivalent: + +@smallexample +const char *s1 = "\\"; +const char *s2 = R"(\)"; +const char *s3 = R"foo(\)foo"; +@end smallexample + +As an extension, GCC also accepts raw string literals in C with +@option{-std=gnu99} or later. + @node Alternate Keywords @subsection Alternate Keywords @cindex alternate keywords diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0b6644b..020442a 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2199,6 +2199,7 @@ those that have already been displayed. If @option{--help} is also specified anywhere on the command line then this takes precedence over any @option{--help=} option. +@opindex Q If the @option{-Q} option appears on the command line before the @option{--help=} option, then the descriptive text displayed by @option{--help=} is changed. Instead of describing the displayed @@ -14648,12 +14649,14 @@ Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. @item -fstrict-aliasing Allow the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C++), this activates -optimizations based on the type of expressions. In particular, an -object of one type is assumed never to reside at the same address as an -object of a different type, unless the types are almost the same. For -example, an @code{unsigned int} can alias an @code{int}, but not a -@code{void*} or a @code{double}. A character type may alias any other -type. +optimizations based on the type of expressions. In particular, accessing +an object of one type via an expression of a different type is not allowed, +unless the types are @dfn{compatible types}, differ only in signedness or +qualifiers, or the expression has a character type. Accessing scalar +objects via a corresponding vector type is also allowed. + +For example, an @code{unsigned int} can alias an @code{int}, but not a +@code{void*} or a @code{double}. A character type may alias any other type. @anchor{Type-punning}Pay special attention to code like this: @smallexample @@ -21311,8 +21314,13 @@ Toggle @option{-fvar-tracking-assignments}, in the same way that @opindex Q @item -Q -Makes the compiler print out each function name as it is compiled, and -print some statistics about each pass when it finishes. +When used on the command line prior to @option{--help=}, @option{-Q} +acts as a modifier to the help output. @xref{Overall Options}, +for details about @option{--help=}. + +Otherwise, this option makes the compiler print out each function name +as it is compiled, and print some statistics about each pass when it +finishes. @opindex ftime-report @item -ftime-report diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 1275ef7..c9471ea 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -7246,6 +7246,12 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1) if (TREE_CONSTANT (arg0)) return true; + /* Put invariant address in arg1. */ + if (is_gimple_invariant_address (arg1)) + return false; + if (is_gimple_invariant_address (arg0)) + return true; + /* It is preferable to swap two SSA_NAME to ensure a canonical form for commutative and comparison operators. Ensuring a canonical form allows the optimizers to find additional redundancies without diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 55bff2e..56325a9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,17 @@ +2025-04-19 Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/119836 + * resolve.cc (check_pure_function): Fix checking for + an impure subprogram within a DO CONCURRENT construct. + (pure_subroutine): Ditto. + +2025-04-16 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106948 + * resolve.cc (gfc_pure_function): If a function has been resolved, + but esym is not yet set, look at its attributes to see whether it + is pure or elemental. + 2025-04-15 Tobias Burnus <tburnus@baylibre.com> * f95-lang.cc (LANG_HOOKS_OMP_DEEP_MAPPING, diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index cdf043b..f03708e 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -3190,6 +3190,13 @@ gfc_pure_function (gfc_expr *e, const char **name) || e->value.function.isym->elemental; *name = e->value.function.isym->name; } + else if (e->symtree && e->symtree->n.sym && e->symtree->n.sym->attr.dummy) + { + /* The function has been resolved, but esym is not yet set. + This can happen with functions as dummy argument. */ + pure = e->symtree->n.sym->attr.pure; + *name = e->symtree->n.sym->name; + } else { /* Implicit functions are not pure. */ @@ -3253,14 +3260,30 @@ static bool check_pure_function (gfc_expr *e) gfc_do_concurrent_flag = 0 when the check for an impure function occurs. Check the stack to see if the source code has a nested BLOCK construct. */ + for (stack = cs_base; stack; stack = stack->prev) { - if (stack->current->op == EXEC_BLOCK) saw_block = true; + if (!saw_block && stack->current->op == EXEC_BLOCK) + { + saw_block = true; + continue; + } + if (saw_block && stack->current->op == EXEC_DO_CONCURRENT) { - gfc_error ("Reference to impure function at %L inside a " - "DO CONCURRENT", &e->where); - return false; + bool is_pure; + is_pure = (e->value.function.isym + && (e->value.function.isym->pure + || e->value.function.isym->elemental)) + || (e->value.function.esym + && (e->value.function.esym->attr.pure + || e->value.function.esym->attr.elemental)); + if (!is_pure) + { + gfc_error ("Reference to impure function at %L inside a " + "DO CONCURRENT", &e->where); + return false; + } } } @@ -3656,16 +3679,29 @@ pure_subroutine (gfc_symbol *sym, const char *name, locus *loc) /* A BLOCK construct within a DO CONCURRENT construct leads to gfc_do_concurrent_flag = 0 when the check for an impure subroutine - occurs. Check the stack to see if the source code has a nested - BLOCK construct. */ + occurs. Walk up the stack to see if the source code has a nested + construct. */ + for (stack = cs_base; stack; stack = stack->prev) { - if (stack->current->op == EXEC_BLOCK) saw_block = true; + if (stack->current->op == EXEC_BLOCK) + { + saw_block = true; + continue; + } + if (saw_block && stack->current->op == EXEC_DO_CONCURRENT) { - gfc_error ("Subroutine call at %L in a DO CONCURRENT block " - "is not PURE", loc); - return false; + + bool is_pure = true; + is_pure = sym->attr.pure || sym->attr.elemental; + + if (!is_pure) + { + gfc_error ("Subroutine call at %L in a DO CONCURRENT block " + "is not PURE", loc); + return false; + } } } diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index b645613..94d5a1e 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -906,20 +906,60 @@ size_must_be_zero_p (tree size) static bool optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree len) { + ao_ref read; gimple *stmt = gsi_stmt (*gsip); if (gimple_has_volatile_ops (stmt)) return false; - tree vuse = gimple_vuse (stmt); - if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME) - return false; - gimple *defstmt = SSA_NAME_DEF_STMT (vuse); tree src2 = NULL_TREE, len2 = NULL_TREE; poly_int64 offset, offset2; tree val = integer_zero_node; + bool len_was_null = len == NULL_TREE; + if (len == NULL_TREE) + len = (TREE_CODE (src) == COMPONENT_REF + ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1)) + : TYPE_SIZE_UNIT (TREE_TYPE (src))); + if (len == NULL_TREE + || !poly_int_tree_p (len)) + return false; + + ao_ref_init (&read, src); + tree vuse = gimple_vuse (stmt); + gimple *defstmt; + do { + if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME) + return false; + defstmt = SSA_NAME_DEF_STMT (vuse); + if (is_a <gphi*>(defstmt)) + return false; + + /* If the len was null, then we can use TBBA. */ + if (stmt_may_clobber_ref_p_1 (defstmt, &read, + /* tbaa_p = */ len_was_null)) + break; + vuse = gimple_vuse (defstmt); + } while (true); + if (gimple_store_p (defstmt) && gimple_assign_single_p (defstmt) + && TREE_CODE (gimple_assign_rhs1 (defstmt)) == STRING_CST + && !gimple_clobber_p (defstmt)) + { + tree str = gimple_assign_rhs1 (defstmt); + src2 = gimple_assign_lhs (defstmt); + /* The string must contain all null char's for now. */ + for (int i = 0; i < TREE_STRING_LENGTH (str); i++) + { + if (TREE_STRING_POINTER (str)[i] != 0) + { + src2 = NULL_TREE; + break; + } + } + } + else if (gimple_store_p (defstmt) + && gimple_assign_single_p (defstmt) && TREE_CODE (gimple_assign_rhs1 (defstmt)) == CONSTRUCTOR && !gimple_clobber_p (defstmt)) src2 = gimple_assign_lhs (defstmt); @@ -939,17 +979,11 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, tree if (src2 == NULL_TREE) return false; - if (len == NULL_TREE) - len = (TREE_CODE (src) == COMPONENT_REF - ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1)) - : TYPE_SIZE_UNIT (TREE_TYPE (src))); if (len2 == NULL_TREE) len2 = (TREE_CODE (src2) == COMPONENT_REF ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1)) : TYPE_SIZE_UNIT (TREE_TYPE (src2))); - if (len == NULL_TREE - || !poly_int_tree_p (len) - || len2 == NULL_TREE + if (len2 == NULL_TREE || !poly_int_tree_p (len2)) return false; diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc index c52a657..6fefc83 100644 --- a/gcc/gimple-lower-bitint.cc +++ b/gcc/gimple-lower-bitint.cc @@ -6647,10 +6647,28 @@ gimple_lower_bitint (void) bitmap_set_bit (large_huge.m_names, SSA_NAME_VERSION (s)); if (has_single_use (s)) { - if (!large_huge.m_single_use_names) - large_huge.m_single_use_names = BITMAP_ALLOC (NULL); - bitmap_set_bit (large_huge.m_single_use_names, - SSA_NAME_VERSION (s)); + tree s2 = s; + /* The coalescing hook special cases SSA_NAME copies. + Make sure not to mark in m_single_use_names single + use SSA_NAMEs copied from non-single use SSA_NAMEs. */ + while (gimple_assign_copy_p (SSA_NAME_DEF_STMT (s2))) + { + s2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (s2)); + if (TREE_CODE (s2) != SSA_NAME) + break; + if (!has_single_use (s2)) + { + s2 = NULL_TREE; + break; + } + } + if (s2) + { + if (!large_huge.m_single_use_names) + large_huge.m_single_use_names = BITMAP_ALLOC (NULL); + bitmap_set_bit (large_huge.m_single_use_names, + SSA_NAME_VERSION (s)); + } } if (SSA_NAME_VAR (s) && ((TREE_CODE (SSA_NAME_VAR (s)) == PARM_DECL diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 49d68ab..0398d69 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -5439,6 +5439,49 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, } } +/* Stream out ipa_return_summary. */ +static void +ipa_write_return_summaries (output_block *ob) +{ + if (!ipa_return_value_sum) + { + streamer_write_uhwi (ob, 0); + return; + } + + lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; + unsigned int count = 0; + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) + { + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + ipa_return_value_summary *v; + + if (cnode && cnode->definition && !cnode->alias + && (v = ipa_return_value_sum->get (cnode)) + && v->vr) + count++; + } + streamer_write_uhwi (ob, count); + + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) + { + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + ipa_return_value_summary *v; + + if (cnode && cnode->definition && !cnode->alias + && (v = ipa_return_value_sum->get (cnode)) + && v->vr) + { + streamer_write_uhwi + (ob, + lto_symtab_encoder_encode (encoder, cnode)); + v->vr->streamer_write (ob); + } + } +} + /* Write jump functions for nodes in SET. */ void @@ -5475,11 +5518,58 @@ ipa_prop_write_jump_functions (void) && ipa_node_params_sum->get (node) != NULL) ipa_write_node_info (ob, node); } - streamer_write_char_stream (ob->main_stream, 0); + ipa_write_return_summaries (ob); produce_asm (ob); destroy_output_block (ob); } +/* Record that return value range of N is VAL. */ + +static void +ipa_record_return_value_range_1 (cgraph_node *n, value_range val) +{ + 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 of %s:", n->dump_name ()); + val.dump (dump_file); + fprintf (dump_file, "\n"); + } +} + +/* Stream out ipa_return_summary. */ +static void +ipa_read_return_summaries (lto_input_block *ib, + struct lto_file_decl_data *file_data, + class data_in *data_in) +{ + unsigned int f_count = streamer_read_uhwi (ib); + for (unsigned int i = 0; i < f_count; i++) + { + unsigned int index = streamer_read_uhwi (ib); + lto_symtab_encoder_t encoder = file_data->symtab_node_encoder; + struct cgraph_node *node + = dyn_cast <cgraph_node *> + (lto_symtab_encoder_deref (encoder, index)); + ipa_vr rvr; + rvr.streamer_read (ib, data_in); + if (node->prevailing_p ()) + { + value_range tmp; + rvr.get_vrange (tmp); + ipa_record_return_value_range_1 (node, tmp); + } + } +} + /* Read section in file FILE_DATA of length LEN with data DATA. */ static void @@ -5516,6 +5606,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, gcc_assert (node->definition); ipa_read_node_info (&ib_main, node, data_in); } + ipa_read_return_summaries (&ib_main, file_data, data_in); lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, len); lto_data_in_delete (data_in); @@ -5635,6 +5726,7 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, } } + /* Write all aggregate replacement for nodes in set. */ void @@ -5673,7 +5765,7 @@ ipcp_write_transformation_summaries (void) && lto_symtab_encoder_encode_body_p (encoder, cnode)) write_ipcp_transformation_info (ob, cnode, ts); } - streamer_write_char_stream (ob->main_stream, 0); + ipa_write_return_summaries (ob); produce_asm (ob); destroy_output_block (ob); } @@ -5714,6 +5806,7 @@ read_replacements_section (struct lto_file_decl_data *file_data, index)); read_ipcp_transformation_info (&ib_main, node, data_in); } + ipa_read_return_summaries (&ib_main, file_data, data_in); lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, len); lto_data_in_delete (data_in); @@ -6194,22 +6287,8 @@ ipcp_transform_function (struct cgraph_node *node) 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"); - } + ipa_record_return_value_range_1 + (cgraph_node::get (current_function_decl), val); } /* Return true if value range of DECL is known and if so initialize RANGE. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 822c126..3b3c0c1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,242 @@ +2025-04-19 Thomas Schwinge <tschwinge@baylibre.com> + + PR testsuite/119508 + * rust/compile/nr2/compile.exp: Disable parallel testing. + +2025-04-19 Co-authored-by: Jeff Law <jlaw@ventanamicro.com> + + PR target/118410 + * gcc.target/riscv/pr118410-1.c: New test. + * gcc.target/riscv/pr118410-2.c: Likewise. + +2025-04-19 Andrew Pinski <quic_apinski@quicinc.com> + + * gcc.dg/pr118947-1.c: Use 1025 as the size of the buf. + * gcc.dg/pr78408-3.c: Likewise. + +2025-04-19 Andrew Pinski <quic_apinski@quicinc.com> + + PR rtl-optimization/111949 + * gcc.target/aarch64/bic-1.c: New test. + +2025-04-19 Jiaxun Yang <jiaxun.yang@flygoat.com> + + PR target/111814 + * gcc.target/sh/pr111814.c: New test. + +2025-04-19 Maciej W. Rozycki <macro@orcam.me.uk> + + * gcc.target/alpha/memcpy-nested-offset-long.c: New file. + * gcc.target/alpha/memcpy-nested-offset-quad.c: New file. + +2025-04-19 Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/119836 + * gfortran.dg/do_concurrent_all_clauses.f90: Remove invalid + dg-error test. + * gfortran.dg/pr119836_1.f90: New test. + * gfortran.dg/pr119836_2.f90: New test. + * gfortran.dg/pr119836_3.f90: New test. + * gfortran.dg/pr119836_4.f90: New test. + +2025-04-18 Thomas Schwinge <tschwinge@baylibre.com> + + PR cobol/119818 + * cobol.dg/group2/FUNCTION_DATE___TIME_OMNIBUS.cob: + 'dg-set-target-env-var TZ UTC0'. + +2025-04-18 Jeff Law <jlaw@ventanamicro.com> + + * gcc.target/riscv/bext-ext-2.c: New test + +2025-04-18 Jonathan Yong <10walls@gmail.com> + + * g++.dg/abi/ref-temp1.C: Replicate some test based on + PE expectations. + * lib/target-supports.exp: New check_effective_target_pe. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/87901 + * gcc.dg/tree-ssa/ssa-dse-53.c: New test. + * gcc.dg/tree-ssa/ssa-dse-54.c: New test. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/87901 + * gcc.dg/tree-ssa/ssa-dse-52.c: New test. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/118902 + * gcc.dg/tree-ssa/pr118902-1.c: New test. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/118947 + * gcc.dg/pr118947-1.c: New test. + +2025-04-18 Andrew Pinski <quic_apinski@quicinc.com> + + PR tree-optimization/78408 + PR tree-optimization/118947 + * gcc.dg/pr78408-3.c: New test. + +2025-04-18 Dimitar Dimitrov <dimitar@dinux.eu> + + * gcc.dg/pr116357.c: Use sizeof(int) instead of alignof(int). + +2025-04-18 Alexey Merzlyakov <alexey.merzlyakov@samsung.com> + + PR middle-end/108016 + * gcc.target/riscv/pr108016.c: New test. + +2025-04-18 kelefth <konstantinos.eleftheriou@vrull.eu> + + PR rtl-optimization/119160 + * gcc.dg/pr119160.c: New test. + +2025-04-18 Xing Li <lixing@loongson.cn> + + * gcc.target/loongarch/vector/loongarch-vector.exp: Change + {dg-do-what-default} save and restore logical. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp2a/constexpr-dtor16.C: Adjust diagnostic. + * g++.dg/cpp2a/constexpr-dynamic10.C: Likewise. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp1y/constexpr-new.C: Adjust diagnostics. + * g++.dg/cpp1z/constexpr-asm-5.C: Likewise. + * g++.dg/cpp26/static_assert1.C: Likewise. + * g++.dg/cpp2a/constexpr-dtor7.C: Likewise. + * g++.dg/cpp2a/constexpr-new26.C: Likewise. + * g++.dg/cpp2a/constexpr-new3.C: Likewise. + * g++.dg/cpp2a/constinit14.C: Likewise. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp26/pack-indexing2.C: Adjust diagnostics. + * g++.dg/ext/type_pack_element2.C: Likewise. + * g++.dg/ext/type_pack_element4.C: Likewise. + +2025-04-17 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/119351 + * gcc.target/aarch64/sve/pr119351.c: New test. + * gcc.target/aarch64/sve/pr119351_run.c: New test. + +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + PR target/119834 + * g++.target/s390/pr119834.C: New test. + +2025-04-17 Iain Buclaw <ibuclaw@gdcproject.org> + + * gdc.test/fail_compilation/test21247.d: New test. + * gdc.test/fail_compilation/test21247b.d: New test. + +2025-04-17 Jason Merrill <jason@redhat.com> + + PR c++/113360 + * g++.dg/cpp23/constexpr-nonlit18.C: Remove redundant message. + * g++.dg/cpp1y/constexpr-diag2.C: New test. + * g++.dg/cpp1y/pr63996.C: Adjust expected errors. + * g++.dg/template/explicit-args6.C: Likewise. + * g++.dg/cpp0x/constexpr-ice21.C: Likewise. + +2025-04-16 Alexandre Oliva <oliva@adacore.com> + + * gcc.dg/ipa/ipa-sra-19.c: Add -Wno-psabi on ppc-elf too. + +2025-04-16 Peter Bergner <bergner@linux.ibm.com> + + PR tree-optimization/112822 + * g++.dg/pr112822.C: Replace altivec vector attribute with a generic + vector attribute. + +2025-04-16 Eric Botcazou <ebotcazou@gcc.gnu.org> + + * gnat.dg/opt105.adb: New test. + * gnat.dg/opt105_pkg.ads, gnat.dg/opt105_pkg.adb: New helper. + +2025-04-16 Jason Merrill <jason@redhat.com> + + PR c++/114772 + PR c++/101180 + * g++.dg/ext/pragma-target2.C: New test. + +2025-04-16 Jason Merrill <jason@redhat.com> + + PR c++/116954 + * g++.dg/warn/Wformat-3.C: New test. + +2025-04-16 Ard Biesheuvel <ardb@kernel.org> + + PR target/119386 + * gcc.target/i386/pr119386-3.c: New test. + +2025-04-16 Ard Biesheuvel <ardb@kernel.org> + + PR target/119386 + * gcc.target/i386/pr119386-1.c: New test. + * gcc.target/i386/pr119386-2.c: New test. + +2025-04-16 Harald Anlauf <anlauf@gmx.de> + + PR fortran/106948 + * gfortran.dg/pure_formal_proc_4.f90: New test. + +2025-04-16 Jan Hubicka <hubicka@ucw.cz> + + * g++.dg/lto/pr119614_0.C: New test. + +2025-04-16 Tamar Christina <tamar.christina@arm.com> + + PR target/119286 + * gcc.dg/vect/vect-early-break_18.c: Force -march=gfx908 for amdgcn. + +2025-04-16 Tamar Christina <tamar.christina@arm.com> + + PR tree-optimization/119351 + * gcc.target/aarch64/sve/peel_ind_10.c: New test. + * gcc.target/aarch64/sve/peel_ind_10_run.c: New test. + * gcc.target/aarch64/sve/peel_ind_5.c: New test. + * gcc.target/aarch64/sve/peel_ind_5_run.c: New test. + * gcc.target/aarch64/sve/peel_ind_6.c: New test. + * gcc.target/aarch64/sve/peel_ind_6_run.c: New test. + * gcc.target/aarch64/sve/peel_ind_7.c: New test. + * gcc.target/aarch64/sve/peel_ind_7_run.c: New test. + * gcc.target/aarch64/sve/peel_ind_8.c: New test. + * gcc.target/aarch64/sve/peel_ind_8_run.c: New test. + * gcc.target/aarch64/sve/peel_ind_9.c: New test. + * gcc.target/aarch64/sve/peel_ind_9_run.c: New test. + +2025-04-16 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/119808 + * gcc.dg/bitint-121.c: New test. + +2025-04-16 Jesse Huang <jesse.huang@sifive.com> + + * gcc.target/riscv/gnu-property-align-rv32.c: New file. + * gcc.target/riscv/gnu-property-align-rv64.c: New file. + +2025-04-16 Kito Cheng <kito.cheng@sifive.com> + + * gcc.target/riscv/jump-table-large-code-model.c: New test. + +2025-04-16 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/116093 + * gcc.dg/bitint-122.c: New test. + +2025-04-16 Alice Carlotti <alice.carlotti@arm.com> + + * gcc.target/aarch64/acle/rwsr-ungated.c: New test. + 2025-04-15 Iain Buclaw <ibuclaw@gdcproject.org> PR d/119826 diff --git a/gcc/testsuite/cobol.dg/group2/FUNCTION_DATE___TIME_OMNIBUS.cob b/gcc/testsuite/cobol.dg/group2/FUNCTION_DATE___TIME_OMNIBUS.cob index cc2a4e1..88b1b84 100644 --- a/gcc/testsuite/cobol.dg/group2/FUNCTION_DATE___TIME_OMNIBUS.cob +++ b/gcc/testsuite/cobol.dg/group2/FUNCTION_DATE___TIME_OMNIBUS.cob @@ -1,4 +1,5 @@ *> { dg-do run } + *> { dg-set-target-env-var TZ UTC0 } identification division. program-id. test. diff --git a/gcc/testsuite/g++.dg/abi/ref-temp1.C b/gcc/testsuite/g++.dg/abi/ref-temp1.C index 70c9a7a..b02dcf6 100644 --- a/gcc/testsuite/g++.dg/abi/ref-temp1.C +++ b/gcc/testsuite/g++.dg/abi/ref-temp1.C @@ -7,11 +7,16 @@ struct B { const A (&x)[2]; }; template <typename T> B &&b = { { { { 1, 2, 3 } }, { { 4, 5, 6 } } } }; B &temp = b<void>; -// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE_" } } -// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE0_" } } -// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE1_" } } -// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE2_" } } +// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE_" { target { ! pe } } } } +// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE0_" { target { ! pe } } } } +// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE1_" { target { ! pe } } } } +// { dg-final { scan-assembler ".weak\(_definition\)?\[ \t\]_?_ZGR1bIvE2_" { target { ! pe } } } } +// { dg-final { scan-assembler "\.section\t\.data\\\$_ZGR1bIvE_,\"w\"\n\t\.linkonce same_size" { target pe } } } +// { dg-final { scan-assembler "\.section\t\.rdata\\\$_ZGR1bIvE0_,\"dr\"\n\t\.linkonce same_size" { target pe } } } +// { dg-final { scan-assembler "\.section\t\.rdata\\\$_ZGR1bIvE1_,\"dr\"\n\t\.linkonce same_size" { target pe } } } +// { dg-final { scan-assembler "\.section\t\.rdata\\\$_ZGR1bIvE2_,\"dr\"\n\t\.linkonce same_size" { target pe } } } +// // { dg-final { scan-assembler "_ZGR1bIvE_:\n\[^\n]+_ZGR1bIvE0_" } } // { dg-final { scan-assembler "_ZGR1bIvE0_:\n\[^\n]+_ZGR1bIvE1_" } } // { dg-final { scan-assembler "_ZGR1bIvE1_:\n\[^\n]+\[ \t\]1" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice21.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice21.C index 4627365..dcc4044 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice21.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice21.C @@ -3,7 +3,7 @@ struct NoMut1 { int a, b; }; struct NoMut3 : virtual NoMut1 { - constexpr NoMut3(int a, int b) // { dg-error "virtual base" "" { target c++23 } } + constexpr NoMut3(int a, int b) : NoMut1{a, b} {} // { dg-error "virtual base" } }; diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-diag2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-diag2.C new file mode 100644 index 0000000..93f3f10 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-diag2.C @@ -0,0 +1,12 @@ +// PR c++/113360 +// { dg-do compile { target c++14 } } + +constexpr bool init_list() // { dg-bogus "because" } +{ + int total{}; + for (int x : {1, 2, 3}) // { dg-error "initializer list" } + total += x; + return total == 6; +} + +static_assert(init_list(), ""); // { dg-error "constant" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C index d0ca0b7..f4c6d2e 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C @@ -6,7 +6,9 @@ constexpr int *f4(bool b) { return nullptr; } else { return new int{42}; // { dg-error "call to non-.constexpr." "" { target c++17_down } } - } // { dg-error "is not a constant expression because allocated storage has not been deallocated" "" { target c++2a } .-1 } + // { dg-message "allocated here" "" { target c++20 } .-1 } + } } static_assert(f4(true) == nullptr, ""); -static_assert(f4(false) == nullptr, ""); // { dg-error "non-.constant. condition|" } +static_assert(f4(false) == nullptr, ""); // { dg-error "non-constant condition" } +// { dg-error "is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr63996.C b/gcc/testsuite/g++.dg/cpp1y/pr63996.C index 8eee2e0..347c86c 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr63996.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr63996.C @@ -1,5 +1,4 @@ // { dg-do compile { target c++14 } } -// { dg-additional-options "-Wno-return-type" } constexpr int foo (int i) @@ -8,4 +7,4 @@ foo (int i) if (i == 23) return 0; } -constexpr int j = foo (1); // { dg-error "flows off the end|in .constexpr. expansion of" } +constexpr int j = foo (1); diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C index bcecea9..35beb27 100644 --- a/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-asm-5.C @@ -28,7 +28,7 @@ struct M { constexpr K size () const { return {}; } constexpr L data () const { return {}; } }; #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 } } + constexpr const char *data () const { return new char[3] { 'b', 'a', 'd' }; } }; #endif constexpr const char a[] = { 't', 'e', 's', 't' }; struct O { constexpr int size () const { return 4; } @@ -117,6 +117,7 @@ foo () asm ((M {})); #if __cpp_constexpr_dynamic_alloc >= 201907L asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } } + // { dg-error "'\\\* N\\\(\\\).N::data\\\(\\\)' is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } .-1 } #endif asm ((O {})); asm ((P (0))); @@ -190,6 +191,7 @@ bar () asm ((M {})); #if __cpp_constexpr_dynamic_alloc >= 201907L asm ((N {})); // { dg-error "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } } + // { dg-error "'\\\* N\\\(\\\).N::data\\\(\\\)' is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } .-1 } #endif asm ((O {})); asm ((P (0))); diff --git a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C index 8e230ef..f891814 100644 --- a/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C +++ b/gcc/testsuite/g++.dg/cpp23/constexpr-nonlit18.C @@ -24,7 +24,7 @@ f3 () } constexpr int -f4 () // { dg-message "declared here" "" { target c++20_down } } +f4 () { // { dg-message "is not usable as a 'constexpr' function because:" "" { target c++23 } .-1 } static const int a = f1 (1); // { dg-error "'a' defined 'static' in 'constexpr' function only available with" "" { target c++20_down } } return 0; // { dg-error "'a' defined 'static' in 'constexpr' context" "" { target c++23 } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C index fdc8320..4a7e494 100644 --- a/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing2.C @@ -49,7 +49,7 @@ template<int N> int getT2 (auto... Ts) { - return Ts...[N]; // { dg-error "pack index is negative" } + return Ts...[N]; // { dg-error "pack index '-1' is negative" } } template<auto N, typename... Ts> @@ -63,7 +63,7 @@ template<auto N, typename... Ts> void badtype2 () { - Ts...[N] t; // { dg-error "pack index is out of range" } + Ts...[N] t; // { dg-error "pack index '1' is out of range for pack of length '1'" } } template<auto N, typename... Ts> @@ -77,7 +77,7 @@ template<auto N, typename... Ts> void badtype4 () { - Ts...[N] t; // { dg-error "pack index is negative" } + Ts...[N] t; // { dg-error "pack index '-1' is negative" } } int nonconst () { return 42; } diff --git a/gcc/testsuite/g++.dg/cpp26/static_assert1.C b/gcc/testsuite/g++.dg/cpp26/static_assert1.C index f9ac831..1d0e6f2 100644 --- a/gcc/testsuite/g++.dg/cpp26/static_assert1.C +++ b/gcc/testsuite/g++.dg/cpp26/static_assert1.C @@ -69,10 +69,11 @@ static_assert (false, M {}); // { dg-warning "'static_assert' with non-string me // { 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 } } + constexpr const char *data () const { return new char[3] { 'b', 'a', 'd' }; } }; 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 "constexpr string 'data\\\(\\\)\\\[0\\\]' must be a constant expression" "" { target c++20 } .-1 } + // { dg-error "'\\\* N\\\(\\\).N::data\\\(\\\)' is not a constant expression because allocated storage has not been deallocated" "" { target c++20 } .-2 } #endif constexpr const char a[] = { 't', 'e', 's', 't' }; struct O { constexpr int size () const { return 4; } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor16.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor16.C index b84aaf9..99d1307 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor16.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor16.C @@ -3,5 +3,5 @@ struct A { virtual ~A (); }; struct B : virtual A { constexpr ~B () {} }; -// { dg-error "'struct B' has virtual base classes" "" { target c++20 } .-1 } +// { dg-error "'constexpr' destructor in 'struct B' that has virtual base classes" "" { target c++20 } .-1 } // { dg-error "'constexpr' destructors only available with" "" { target c++17_down } .-2 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C index 463eaca..f4546c1 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor7.C @@ -3,7 +3,7 @@ struct S { int *s; - constexpr S () : s(new int) {} // { dg-error "is not a constant expression because allocated storage has not been deallocated" } + constexpr S () : s(new int) {} S (const S &) = delete; S &operator= (const S &) = delete; constexpr ~S () { delete s; } @@ -17,3 +17,4 @@ foo (S v) } static_assert (foo (S ())); // { dg-error "non-constant condition for static assertion" } +// { dg-error "is not a constant expression because allocated storage has not been deallocated" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic10.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic10.C index f9f8223..e543ce4 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic10.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic10.C @@ -5,7 +5,7 @@ struct C { virtual void a(); }; struct B { virtual void b(); }; -struct A : virtual B, C { virtual void c(); }; // { dg-error ".struct A. has virtual base classes" } +struct A : virtual B, C { virtual void c(); }; // { dg-error "virtual base classes" } constexpr A a; // { dg-error "call" } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new26.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new26.C index c82bd43..d8e53b2 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new26.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new26.C @@ -4,7 +4,7 @@ constexpr int * f7 () { - int *p = new int (2); // { dg-error "is not a constant expression because it refers to a result of" } + int *p = new int (2); // { dg-message "allocated here" } delete p; return p; } @@ -12,6 +12,5 @@ f7 () void g () { - constexpr auto v7 = f7 (); + constexpr auto v7 = f7 (); // { dg-error "is not a constant expression because it refers to a result of" } } - diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C index 5d9f1925..30e453e 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C @@ -5,19 +5,19 @@ constexpr int * f1 () { - return new int (2); // { dg-error "is not a constant expression because it refers to a result of" } + return new int (2); // { dg-message "allocated here" } } -constexpr auto v1 = f1 (); +constexpr auto v1 = f1 (); // { dg-error "is not a constant expression because it refers to a result of" } constexpr bool f2 () { - int *p = new int (3); // { dg-error "is not a constant expression because allocated storage has not been deallocated" } + int *p = new int (3); // { dg-message "allocated here" } return false; } -constexpr auto v2 = f2 (); +constexpr auto v2 = f2 (); // { dg-error "is not a constant expression because allocated storage has not been deallocated" } constexpr bool f3 () @@ -64,12 +64,12 @@ constexpr auto v6 = f6 (); // { dg-message "in 'constexpr' expansion of" } constexpr int * f7 () { - int *p = new int (2); // { dg-error "is not a constant expression because it refers to a result of" } + int *p = new int (2); // { dg-message "allocated here" } delete p; return p; } -constexpr auto v7 = f7 (); +constexpr auto v7 = f7 (); // { dg-error "is not a constant expression because it refers to a result of" } constexpr bool f8_impl (int *p) diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit14.C b/gcc/testsuite/g++.dg/cpp2a/constinit14.C index 06c4cb4..26d82fe67 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constinit14.C +++ b/gcc/testsuite/g++.dg/cpp2a/constinit14.C @@ -2,12 +2,13 @@ // { dg-do compile { target c++20 } } struct Value { - Value() : v{new int{42}} {} // { dg-error "result of 'operator new'" "" { target implicit_constexpr } } + Value() : v{new int{42}} {} int* v; }; struct S { static constinit inline Value v{}; // { dg-error "variable .S::v. does not have a constant initializer|call to non-.constexpr. function" } + // { dg-error "result of 'operator new'" "" { target implicit_constexpr } .-1 } }; int main() { return *S::v.v; } diff --git a/gcc/testsuite/g++.dg/ext/pragma-target2.C b/gcc/testsuite/g++.dg/ext/pragma-target2.C new file mode 100644 index 0000000..53eb7dd --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pragma-target2.C @@ -0,0 +1,18 @@ +// PR c++/114772 +// { dg-do compile { target x86_64-*-* } } + +template<typename V, bool STREAMING> +inline __attribute__((always_inline)) +__attribute__((warn_unused_result)) +int walk_document(V visitor) {return 0;} + +template<bool STREAMING> +void parse_document() { + int r = walk_document<bool, STREAMING>(false); +} + +void stage2_next() { + parse_document<true>(); +} + +#pragma GCC target("pclmul") diff --git a/gcc/testsuite/g++.dg/ext/type_pack_element2.C b/gcc/testsuite/g++.dg/ext/type_pack_element2.C index 1bf7753..1b07673 100644 --- a/gcc/testsuite/g++.dg/ext/type_pack_element2.C +++ b/gcc/testsuite/g++.dg/ext/type_pack_element2.C @@ -2,7 +2,7 @@ int p; -using type = __type_pack_element<&p, int>; // { dg-error "not an integral constant" } +using type = __type_pack_element<&p, int>; // { dg-error "non-integral type" } using type = __type_pack_element<1, int>; // { dg-error "out of range" } using type = __type_pack_element<2, int, char>; // { dg-error "out of range" } using type = __type_pack_element<-1, int>; // { dg-error "negative" } diff --git a/gcc/testsuite/g++.dg/ext/type_pack_element4.C b/gcc/testsuite/g++.dg/ext/type_pack_element4.C index aa508c7..5a39194 100644 --- a/gcc/testsuite/g++.dg/ext/type_pack_element4.C +++ b/gcc/testsuite/g++.dg/ext/type_pack_element4.C @@ -3,7 +3,7 @@ template <typename... _Elements> class tuple{}; template <unsigned long __i, typename... _Elements> -__type_pack_element<__i, _Elements...> &get(tuple<_Elements...> &__t) noexcept; // { dg-error "index is out of range" } +__type_pack_element<__i, _Elements...> &get(tuple<_Elements...> &__t) noexcept; // { dg-error "out of range" } tuple<int,int> data; template <unsigned long Level> unsigned take_impl(unsigned idx) { diff --git a/gcc/testsuite/g++.dg/lto/pr119614_0.C b/gcc/testsuite/g++.dg/lto/pr119614_0.C new file mode 100644 index 0000000..09c07fb --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/pr119614_0.C @@ -0,0 +1,34 @@ +// PR tree-optimization/119614 +// { dg-lto-do link } +// { dg-lto-options { { -O2 -fPIC -flto -flto-partition=max } } } +// { dg-require-effective-target shared } +// { dg-require-effective-target fpic } +// { dg-require-effective-target musttail } +// { dg-extra-ld-options "-shared" } + +struct S {} b; +char *foo (); +int e, g; +void bar (); +void corge (S); + +[[gnu::noinline]] static char * +baz () +{ + bar (); + return 0; +} + +const char * +qux () +{ + if (e) + { + S a = b; + corge (a); + if (g) + return 0; + [[gnu::musttail]] return baz (); + } + return foo (); +} diff --git a/gcc/testsuite/g++.dg/pr112822.C b/gcc/testsuite/g++.dg/pr112822.C index a855752..f88bd83 100644 --- a/gcc/testsuite/g++.dg/pr112822.C +++ b/gcc/testsuite/g++.dg/pr112822.C @@ -89,7 +89,7 @@ template <typename aj, typename cm> struct cg<aj, cm> { typedef aj cn; }; namespace ai { template <typename cj, int> cj cp; template <typename bu, typename cj, int> void cl(bu *cr, cj cs) { ct(cr, cs); } -typedef __attribute__((altivec(vector__))) double co; +typedef double co __attribute__ ((vector_size (16))); void ct(double *cr, co cs) { *(co *)cr = cs; } struct cq { co q; diff --git a/gcc/testsuite/g++.dg/template/explicit-args6.C b/gcc/testsuite/g++.dg/template/explicit-args6.C index 18663d7b..0d9718c 100644 --- a/gcc/testsuite/g++.dg/template/explicit-args6.C +++ b/gcc/testsuite/g++.dg/template/explicit-args6.C @@ -24,10 +24,12 @@ frob() // narrowing check, reject negative values return unsigned{N}; // { dg-prune-output "narrowing" } -} // { dg-prune-output "flows off the end" } -// { dg-prune-output "not a return-statement" } +} -template<int N> void get_n(tuple& t) { get<frob<N>()>(t); } // { dg-error "" } +// This complains about calling frob only in C++11 because +// maybe_save_constexpr_fundef fails; in later standards it succeeds, +// and the evaluation failure is silent due to the earlier errors. +template<int N> void get_n(tuple& t) { get<frob<N>()>(t); } // { dg-error "" "" { target c++11_only } } int main() { diff --git a/gcc/testsuite/g++.dg/warn/Wformat-3.C b/gcc/testsuite/g++.dg/warn/Wformat-3.C new file mode 100644 index 0000000..e308530 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wformat-3.C @@ -0,0 +1,19 @@ +// PR c++/116954 +// { dg-additional-options -Wformat } + +#ifndef WORKS +template<int N> +int fn(char (&buf)[N], const char fmt[], ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +#endif + +template<int N> +__attribute__ ((__format__ (__printf__, 2, 3))) +int fn(char (&)[N], const char [], ...) +{ return 0; } + +int main() +{ + char buf[20]; + return fn(buf, "%s", 42); /* { dg-warning "Wformat" } */ +} diff --git a/gcc/testsuite/g++.target/s390/pr119834.C b/gcc/testsuite/g++.target/s390/pr119834.C new file mode 100644 index 0000000..66c0a69 --- /dev/null +++ b/gcc/testsuite/g++.target/s390/pr119834.C @@ -0,0 +1,76 @@ +// PR target/119834 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -march=z900" } + +int *a; +struct A; +struct B { + A begin (); + A end (); + operator bool * (); + void operator++ (); +}; +template <typename T> +auto operator| (int, T x) -> decltype (x (0)); +struct A : B { bool a; }; +struct C { A operator () (int); }; +enum D {} d; +int e; +void foo (); +struct E { + template <typename T> + T *garply () + { + if (d) + return 0; + if (e) + foo (); + return reinterpret_cast<T *> (f); + } + template <typename> + void bar (long x, bool) + { + if (&g - f) + __builtin_memset (a, 0, x); + f += x; + } + template <typename T> + T *baz (T *x, long y, bool z = true) + { + if (d) + return nullptr; + bar<T> ((char *)x + y - f, z); + return x; + } + template <typename T> + void qux (T x) { baz (x, x->j); } + char *f, g; +} *h; +struct F { + template <typename T> + int corge (T x) { x.freddy (this); return 0; } + template <typename T> + int boo (T x) { corge (x); return 0; } +} i; +template <typename T> +struct G { + template <typename U> friend T operator+ (U, G); + template <typename U> + void waldo (F *x, G y, U z) { x->boo (z + y); } + template <typename... Ts> + void plugh (E *y, Ts... z) { T *x = y->garply<T> (); x->thud (y, z...); } +}; +template <typename T> using H = G<T>; +struct I { + static constexpr unsigned j = 2; + void thud (E *x, A y) { x->qux (this); for (auto g : y) ; } +}; +H<I> k; +struct J { + void freddy (F *) { C a; auto b = 0 | a; k.plugh (h, b); } +}; +H<J> l; +struct K { + void freddy () { l.waldo (&i, l, this); } +}; +void grault () { K m; m.freddy (); } diff --git a/gcc/testsuite/gcc.dg/bitint-121.c b/gcc/testsuite/gcc.dg/bitint-121.c new file mode 100644 index 0000000..335b9a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-121.c @@ -0,0 +1,24 @@ +/* PR middle-end/119808 */ +/* { dg-do run { target { bitint && fstack_protector } } } */ +/* { dg-options "-O0 -ftree-coalesce-vars -fstack-protector-strong" } */ + +#if __BITINT_MAXWIDTH__ >= 129 +_BitInt(129) +foo () +{ + _BitInt(129) b = 0; + _BitInt(8) a + =__builtin_stdc_rotate_right (0x8c82111b5d2d37c57e9ada7213ed95a49uwb, b); + return b; +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 129 + _BitInt(129) x = foo (); + if (x) + __builtin_abort (); +#endif +} diff --git a/gcc/testsuite/gcc.dg/bitint-122.c b/gcc/testsuite/gcc.dg/bitint-122.c new file mode 100644 index 0000000..c791969 --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-122.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/116093 */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-Og -ftree-vrp -fno-tree-dce" } */ + +#if __BITINT_MAXWIDTH__ >= 129 +char +foo (int a, _BitInt (129) b, char c) +{ + return c << (5 / b % (0xdb75dbf5 | a)); +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 129 + if (foo (0, 6, 1) != 1) + __builtin_abort (); +#endif +} diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c index c34c89e..39874ad 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-19.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ /* { dg-additional-options "-msse2" { target ia32 } } */ -/* { dg-additional-options "-Wno-psabi" { target powerpc-ibm-aix* powerpc-wrs-vxworks* } } */ +/* { dg-additional-options "-Wno-psabi" { target powerpc-ibm-aix* powerpc-wrs-vxworks* powerpc-*-elf } } */ typedef int __attribute__((__vector_size__(16))) vectype; diff --git a/gcc/testsuite/gcc.dg/pr116357.c b/gcc/testsuite/gcc.dg/pr116357.c index 07effa1..12aaf62 100644 --- a/gcc/testsuite/gcc.dg/pr116357.c +++ b/gcc/testsuite/gcc.dg/pr116357.c @@ -2,9 +2,9 @@ /* { dg-do compile } */ /* { dg-options "" } */ -typedef int A __attribute__((aligned (2 * alignof (int)))); +typedef int A __attribute__((aligned (2 * sizeof (int)))); A a[4]; /* { dg-error "alignment of array elements is greater than element size" } */ -typedef volatile int B __attribute__((aligned (2 * alignof (int)))); +typedef volatile int B __attribute__((aligned (2 * sizeof (int)))); B b[4]; /* { dg-error "alignment of array elements is greater than element size" } */ -typedef const int C __attribute__((aligned (2 * alignof (int)))); +typedef const int C __attribute__((aligned (2 * sizeof (int)))); C c[4]; /* { dg-error "alignment of array elements is greater than element size" } */ diff --git a/gcc/testsuite/gcc.dg/pr118947-1.c b/gcc/testsuite/gcc.dg/pr118947-1.c new file mode 100644 index 0000000..8733e8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr118947-1.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/118947 */ +/* { dg-do compile { target size32plus } } */ +/* { dg-options "-O2 -fdump-tree-forwprop1-details" } */ +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */ + +void* aaa(); +void* bbb() +{ + char buf[1025] = {}; + /* Tha call to aaa should not matter and clobber buf. */ + void* ret = aaa(); + __builtin_memcpy(ret, buf, sizeof(buf)); + return ret; +} + diff --git a/gcc/testsuite/gcc.dg/pr119160.c b/gcc/testsuite/gcc.dg/pr119160.c new file mode 100644 index 0000000..b4629a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr119160.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -finstrument-functions-once -favoid-store-forwarding -fnon-call-exceptions -fschedule-insns -mgeneral-regs-only -Wno-psabi" } */ + +typedef __attribute__((__vector_size__ (32))) int V; + +void +foo (V v, V, V, V *r) +{ + V u = (V){} + v[0]; + *r = u; +} + +__attribute__((__noipa__)) void +bar(int x) +{ + if (x != 2) __builtin_abort(); +} + +int +main () +{ + V x; + foo ((V){ 2, 3 }, (V){ }, (V){ }, &x); + for (unsigned i = 0; i < sizeof(x)/sizeof(x[0]); i++) + bar(x[i]); +}
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/pr78408-3.c b/gcc/testsuite/gcc.dg/pr78408-3.c new file mode 100644 index 0000000..5ea5458 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr78408-3.c @@ -0,0 +1,14 @@ +/* PR tree-optimization/78408 */ +/* { dg-do compile { target size32plus } } */ +/* { dg-options "-O2 -fdump-tree-forwprop1-details" } */ +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */ + +void* aaa(); +void* bbb() +{ + void* ret = aaa(); + char buf[1025] = {}; + __builtin_memcpy(ret, buf, sizeof(buf)); + return ret; +} + diff --git a/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-2.c b/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-2.c new file mode 100644 index 0000000..871d489 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-2.c @@ -0,0 +1,71 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-O2 -march=x86-64-v3" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef int v8si __attribute__((vector_size(32))); +typedef int v2di __attribute__((vector_size(16))); + +v4si __RTL (startwith ("vregs1")) foo1 (void) +{ +(function "foo1" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V4SI <0>) (const_vector:V4SI [(const_int -1) (const_int -1) (const_int -1) (const_int -1)]))) + (cinsn 4 (set (reg:V4SI <1>) (const_vector:V4SI [(const_int -1) (const_int -1) (const_int -1) (const_int -1)]))) + (cinsn 5 (set (reg:V4SI <2>) + (eq:V4SI (reg:V4SI <0>) (reg:V4SI <1>)))) + (cinsn 6 (set (reg:V4SI <3>) (reg:V4SI <2>))) + (cinsn 7 (set (reg:V4SI xmm0) (reg:V4SI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V4SI xmm0))) +) +} + +v8si __RTL (startwith ("vregs1")) foo2 (void) +{ +(function "foo2" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V8SI <0>) (const_vector:V8SI [(const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1)]))) + (cinsn 4 (set (reg:V8SI <1>) (const_vector:V8SI [(const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1) (const_int -1)]))) + (cinsn 5 (set (reg:V8SI <2>) + (eq:V8SI (reg:V8SI <0>) (reg:V8SI <1>)))) + (cinsn 6 (set (reg:V8SI <3>) (reg:V8SI <2>))) + (cinsn 7 (set (reg:V8SI xmm0) (reg:V8SI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V8SI xmm0))) +) +} + +v2di __RTL (startwith ("vregs1")) foo3 (void) +{ +(function "foo3" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V2DI <0>) (const_vector:V2DI [(const_int -1) (const_int -1)]))) + (cinsn 4 (set (reg:V2DI <1>) (const_vector:V2DI [(const_int -1) (const_int -1)]))) + (cinsn 5 (set (reg:V2DI <2>) + (eq:V2DI (reg:V2DI <0>) (reg:V2DI <1>)))) + (cinsn 6 (set (reg:V2DI <3>) (reg:V2DI <2>))) + (cinsn 7 (set (reg:V2DI xmm0) (reg:V2DI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V2DI xmm0))) +) +} + +/* { dg-final { scan-assembler-times "vpcmpeq" 3 } } */ diff --git a/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-3.c b/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-3.c new file mode 100644 index 0000000..276c4c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/rtl/i386/vector_eq-3.c @@ -0,0 +1,74 @@ +/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-O2 -march=x86-64-v3" } */ + +typedef int v4si __attribute__((vector_size(16))); +typedef int v8si __attribute__((vector_size(32))); +typedef int v2di __attribute__((vector_size(16))); + +v4si __RTL (startwith ("vregs1")) foo1 (void) +{ +(function "foo1" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V4SI <1>) + (mem:V4SI (reg:SI di) [0 ptr S128 A128]))) + (cinsn 4 (set (reg:V4SI <2>) + (eq:V4SI (reg:V4SI <1>) + (mem:V4SI (reg:SI di) [0 ptr S128 A128])))) + (cinsn 5 (set (reg:V4SI <3>) (reg:V4SI <2>))) + (cinsn 6 (set (reg:V4SI xmm0) (reg:V4SI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V4SI xmm0))) +) +} + +v8si __RTL (startwith ("vregs1")) foo2 (void) +{ +(function "foo2" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V8SI <1>) + (mem:V8SI (reg:SI di) [0 ptr S256 A256]))) + (cinsn 4 (set (reg:V8SI <2>) + (eq:V8SI (mem:V8SI (reg:SI di) [0 ptr S256 A256]) + (reg:V8SI <1>)))) + (cinsn 5 (set (reg:V8SI <3>) (reg:V8SI <2>))) + (cinsn 6 (set (reg:V8SI xmm0) (reg:V8SI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V8SI xmm0))) +) +} + +v2di __RTL (startwith ("vregs1")) foo3 (void) +{ +(function "foo3" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:V2DI <1>) + (mem:V2DI (reg:SI di) [0 ptr S128 A128]))) + (cinsn 4 (set (reg:V2DI <2>) + (eq:V2DI (reg:V2DI <1>) + (mem:V2DI (reg:SI di) [0 ptr S128 A128])))) + (cinsn 5 (set (reg:V2DI <3>) (reg:V2DI <2>))) + (cinsn 6 (set (reg:V2DI xmm0) (reg:V2DI <3>))) + (edge-to exit (flags "FALLTHRU")) + ) + ) + (crtl (return_rtx (reg/i:V2DI xmm0))) +) +} + +/* { dg-final { scan-assembler-times "vpcmpeq" 3 } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr118902-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr118902-1.c new file mode 100644 index 0000000..fa21b8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr118902-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void foo(int); +void l(int**); +int f1(int j, int t) +{ + int p = 0; + int *a = &p; + l(&a); + if (a == &p) + return 0; + for(int i = 0; i < j; i++) + { + if (a == &p) foo(p); + } + return 0; +} + +/* We should be able to remove the call to foo because a is never equal to &p inside the loop. */ +/* { dg-final { scan-tree-dump-not "foo " "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-52.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-52.c new file mode 100644 index 0000000..9e605ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-52.c @@ -0,0 +1,30 @@ +/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre -fdump-tree-optimized" } */ + +/* PR tree-optimization/87901 */ + +char z[32]; +void foo1(void) +{ + char z1[17]; + char z2[24]; + __builtin_memset (z1, 0, 17); + __builtin_memcpy (z, z1, 17); + __builtin_memset (z2, 0, 24); + __builtin_memcpy (z+8, z2, 24); +} + +/* we should get: + MEM <unsigned char[8]> [(char * {ref-all})&z] = {}; + MEM <unsigned char[24]> [(char * {ref-all})&z + 8B] = {}; + after DSE; trimming the first memset to z (which was memcpy) to 8 bytes + from the original 17. + and not have a [17] in the IR after DSE. + The two memset to z1/z2 will also be removed. + */ +/* { dg-final { scan-tree-dump-not "\\\[17\\\]" "optimized" } } */ +/* { dg-final { scan-tree-dump "\\\[8\\\]" "dse1" } } */ + +/* { dg-final { scan-tree-dump-times "Trimming statement " 1 "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead call:" 2 "dse1" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-53.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-53.c new file mode 100644 index 0000000..a2df591 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-53.c @@ -0,0 +1,26 @@ +/* { dg-options "-O2 -fno-strict-aliasing -fdump-tree-dse-details -fno-tree-fre -fdump-tree-optimized" } */ + +/* PR tree-optimization/87901 */ + + +int i; +int foo () +{ + i = 0; + *((short *)&i + 1) = 1; + return i; +} + +/* we should get: + MEM <char[2]> [(int *)&i] = {}; + MEM[(short int *)&i + 2B] = 1; + in DSE1. + + Note later on the stores will be merged. */ +/* { dg-final { scan-tree-dump "return 65536;" "optimized" { target le } } } */ +/* { dg-final { scan-tree-dump "return 1;" "optimized" { target be } } } */ +/* { dg-final { scan-tree-dump "\\\[2\\\]" "dse1" } } */ + +/* { dg-final { scan-tree-dump-times "Trimming statement " 1 "dse1" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-54.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-54.c new file mode 100644 index 0000000..7e79a73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-54.c @@ -0,0 +1,25 @@ +/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre -fdump-tree-optimized" } */ + +/* PR tree-optimization/87901 */ + +int z[128]; +void foo1(void) +{ + int z1; + int z2[24/sizeof(int)]; + __builtin_memset (&z1, 0, sizeof(int)); + __builtin_memcpy (z, &z1, sizeof(int)); + __builtin_memset (z2, 0, 24); + __builtin_memcpy (((char*)z)+1, z2, 24); +} + +/* we should get: + MEM[(char * {ref-all})&z] = {}; + __builtin_memset (&MEM <int[128]> [(void *)&z + 1B], 0, 24); + */ + +/* { dg-final { scan-tree-dump-not "MEM <unsigned int>" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "MEM \\\[" "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Trimming statement " 1 "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead call:" 1 "dse1" } } */ + diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_18.c b/gcc/testsuite/gcc.dg/vect/vect-early-break_18.c index edddb44..cd39704 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-early-break_18.c +++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_18.c @@ -2,7 +2,7 @@ /* { dg-do compile } */ /* { dg-require-effective-target vect_early_break } */ /* { dg-require-effective-target vect_int } */ - +/* { dg-additional-options "-march=gfx908" { target amdgcn*-*-* } } */ /* { dg-additional-options "-Ofast" } */ /* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target vect_load_lanes } } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/bic-1.c b/gcc/testsuite/gcc.target/aarch64/bic-1.c new file mode 100644 index 0000000..65e1514 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/bic-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +/* PR rtl-optmization/111949 */ + +/* +**func1: +** bic w([0-9]+), w0, w1 +** and w0, w\1, 1 +** ret +*/ + +unsigned func1(unsigned a, bool b) +{ + int c = a & b; + return (c ^ a)&1; +} + +/* +**func2: +** bic w([0-9]+), w1, w0 +** and w0, w\1, 255 +** ret +*/ +unsigned func2(bool a, bool b) +{ + return ~a & b; +} + +/* +**func3: +** bic w([0-9]+), w1, w0 +** and w0, w\1, 1 +** ret +*/ +bool func3(bool a, unsigned char b) +{ + return !a & b; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10.c new file mode 100644 index 0000000..b7a7bc5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10.c @@ -0,0 +1,24 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 0 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (int start) +{ + for (unsigned int i = start; i < END; ++i) + { + if (x[i] == 0) + return i; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10_run.c new file mode 100644 index 0000000..6169aeb --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_10_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_10.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (START); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5.c new file mode 100644 index 0000000..a03bb1d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5.c @@ -0,0 +1,24 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 2 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (void) +{ + for (signed int i = START; i < END; ++i) + { + if (x[i] == 0) + return i; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5_run.c new file mode 100644 index 0000000..f26befe --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_5_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_5.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6.c new file mode 100644 index 0000000..9bfd1a6 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6.c @@ -0,0 +1,24 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 1 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (int start) +{ + for (unsigned int i = start; i < END; ++i) + { + if (x[i] == 0) + return i; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6_run.c new file mode 100644 index 0000000..4fdf3e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_6_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_6.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (START); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7.c new file mode 100644 index 0000000..0182e13 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7.c @@ -0,0 +1,24 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 1 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (void) +{ + for (unsigned int i = START; i < END; ++i) + { + if (x[i] == 0) + return i; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7_run.c new file mode 100644 index 0000000..05608dd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_7_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_7.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8.c new file mode 100644 index 0000000..043348b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8.c @@ -0,0 +1,24 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 1 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (void) +{ + for (unsigned int i = START; i < END; i*=2) + { + if (x[i] == 0) + return i; + } + return -1; +} + +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump-not "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump-not "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8_run.c new file mode 100644 index 0000000..aa86122 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_8_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_8.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9.c new file mode 100644 index 0000000..cc904e8 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9.c @@ -0,0 +1,25 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ + +#define N 512 +#define START 1 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +int __attribute__((noipa)) +foo (void) +{ + for (int *p = x + START; p < x + END; p++) + { + if (*p == 0) + return START; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* Peels using a scalar loop. */ +/* { dg-final { scan-tree-dump-not "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9_run.c b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9_run.c new file mode 100644 index 0000000..767f8bd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/peel_ind_9_run.c @@ -0,0 +1,17 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "peel_ind_9.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + int res = foo (); + asm volatile (""); + if (res != START) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c b/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c new file mode 100644 index 0000000..85aab35 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr119351.c @@ -0,0 +1,39 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do compile } */ +/* { dg-options "-Ofast -msve-vector-bits=256 --param aarch64-autovec-preference=sve-only -fdump-tree-vect-details" } */ +/* { dg-final { check-function-bodies "**" "" ""} } */ + +#define N 512 +#define START 1 +#define END 505 + +int x[N] __attribute__((aligned(32))); + +/* +** foo: +** ... +** ld1w z[0-9]+.s, p[0-9]+/z, \[x[0-9], x[0-9], lsl 2\] +** cmple p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0 +** ptest p[0-9]+, p[0-9]+.b +** ... +*/ + +int __attribute__((noipa)) +foo (void) +{ + int z = 0; + for (unsigned int i = START; i < END; ++i) + { + z++; + if (x[i] > 0) + continue; + + return z; + } + return -1; +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" } } */ +/* { dg-final { scan-tree-dump "pfa_iv_offset" "vect" } } */ +/* { dg-final { scan-tree-dump "Alignment of access forced using peeling" "vect" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c b/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c new file mode 100644 index 0000000..d36ab0e --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr119351_run.c @@ -0,0 +1,20 @@ +/* Fix for PR119351 alignment peeling with vectors and VLS. */ +/* { dg-do run { target aarch64_sve_hw } } */ +/* { dg-options "-Ofast --param aarch64-autovec-preference=sve-only" } */ +/* { dg-additional-options "-msve-vector-bits=256" { target aarch64_sve256_hw } } */ +/* { dg-additional-options "-msve-vector-bits=128" { target aarch64_sve128_hw } } */ + +#include "pr119351.c" + +int __attribute__ ((optimize (1))) +main (void) +{ + x[0] = 1; + x[1] = 21; + x[2] = 39; + x[3] = 59; + int res = foo (); + if (res != 4) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-long.c b/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-long.c new file mode 100644 index 0000000..631d14f --- /dev/null +++ b/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-long.c @@ -0,0 +1,76 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +typedef unsigned int __attribute__ ((mode (DI))) int64_t; +typedef unsigned int __attribute__ ((mode (SI))) int32_t; + +typedef union + { + int32_t l[8]; + } +val; + +typedef struct + { + int32_t l[2]; + val v; + } +tre; + +typedef struct + { + int32_t l[3]; + tre t; + } +due; + +typedef struct + { + val v; + int64_t q; + int32_t l[2]; + due d; + } +uno; + +void +memcpy_nested_offset_long (uno *u) +{ + u->d.t.v = u->v; +} + +/* Expect assembly such as: + + ldq $4,0($16) + ldq $3,8($16) + ldq $2,16($16) + srl $4,32,$7 + ldq $1,24($16) + srl $3,32,$6 + stl $4,68($16) + srl $2,32,$5 + stl $7,72($16) + srl $1,32,$4 + stl $3,76($16) + stl $6,80($16) + stl $2,84($16) + stl $5,88($16) + stl $1,92($16) + stl $4,96($16) + + that is with four quadword loads at offsets 0, 8, 16, 24 each and + eight longword stores at offsets 68, 72, 76, 80, 84, 88, 92, 96 each. */ + +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,0\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,8\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,16\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,24\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,68\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,72\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,76\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,80\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,84\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,88\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,92\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstl\\s\\\$\[0-9\]+,96\\\(\\\$16\\\)\\s" 1 } } */ diff --git a/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-quad.c b/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-quad.c new file mode 100644 index 0000000..1d2227e --- /dev/null +++ b/gcc/testsuite/gcc.target/alpha/memcpy-nested-offset-quad.c @@ -0,0 +1,64 @@ +/* { dg-do compile } */ +/* { dg-options "" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +typedef unsigned int __attribute__ ((mode (DI))) int64_t; +typedef unsigned int __attribute__ ((mode (SI))) int32_t; + +typedef union + { + int32_t l[8]; + } +val; + +typedef struct + { + int32_t l[2]; + val v; + } +tre; + +typedef struct + { + int32_t l[3]; + tre t; + } +due; + +typedef struct + { + val v; + int64_t q; + int32_t l[3]; + due d; + } +uno; + +void +memcpy_nested_offset_quad (uno *u) +{ + u->d.t.v = u->v; +} + +/* Expect assembly such as: + + ldq $4,0($16) + ldq $3,8($16) + ldq $2,16($16) + ldq $1,24($16) + stq $4,72($16) + stq $3,80($16) + stq $2,88($16) + stq $1,96($16) + + that is with four quadword loads at offsets 0, 8, 16, 24 each + and four quadword stores at offsets 72, 80, 88, 96 each. */ + +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,0\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,8\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,16\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sldq\\s\\\$\[0-9\]+,24\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstq\\s\\\$\[0-9\]+,72\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstq\\s\\\$\[0-9\]+,80\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstq\\s\\\$\[0-9\]+,88\\\(\\\$16\\\)\\s" 1 } } */ +/* { dg-final { scan-assembler-times "\\sstq\\s\\\$\[0-9\]+,96\\\(\\\$16\\\)\\s" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr119386-1.c b/gcc/testsuite/gcc.target/i386/pr119386-1.c new file mode 100644 index 0000000..9a0dc64 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr119386-1.c @@ -0,0 +1,10 @@ +/* PR target/119386 */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -pg" } */ +/* { dg-final { scan-assembler "call\[ \t\]+mcount@PLT" } } */ + +int +main () +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr119386-2.c b/gcc/testsuite/gcc.target/i386/pr119386-2.c new file mode 100644 index 0000000..3ea978e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr119386-2.c @@ -0,0 +1,12 @@ +/* PR target/119386 */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -fno-plt -pg" } */ +/* { dg-final { scan-assembler "call\[ \t\]+\\*mcount@GOTPCREL\\(" { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler "call\[ \t\]+\\*mcount@GOT\\(" { target ia32 } } } */ + + +int +main () +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr119386-3.c b/gcc/testsuite/gcc.target/i386/pr119386-3.c new file mode 100644 index 0000000..287410b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr119386-3.c @@ -0,0 +1,10 @@ +/* PR target/119386 */ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fpic -pg -mnop-mcount" } */ +/* { dg-final { scan-assembler ".byte\[ \t\]+0x0f, 0x1f, 0x44, 0x00, 0x00" } } */ + +int +main () +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/loongarch/vector/loongarch-vector.exp b/gcc/testsuite/gcc.target/loongarch/vector/loongarch-vector.exp index f56d2f1..9df3f29 100644 --- a/gcc/testsuite/gcc.target/loongarch/vector/loongarch-vector.exp +++ b/gcc/testsuite/gcc.target/loongarch/vector/loongarch-vector.exp @@ -35,7 +35,7 @@ dg-init # If the target hardware supports LSX, the default action is "run", otherwise # just "compile". -global dg-do-what-default +set saved-dg-do-what-default ${dg-do-what-default} if {[check_effective_target_loongarch_sx_hw]} then { set dg-do-what-default run } else { @@ -45,6 +45,7 @@ if {[check_effective_target_loongarch_sx_hw]} then { #Main loop. dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/lsx/*.\[cS\]]] \ " -mlsx" $DEFAULT_CFLAGS +set dg-do-what-default ${saved-dg-do-what-default} dg-finish @@ -52,7 +53,7 @@ dg-init # If the target hardware supports LASX, the default action is "run", otherwise # just "compile". -global dg-do-what-default +set saved-dg-do-what-default ${dg-do-what-default} if {[check_effective_target_loongarch_asx_hw]} then { set dg-do-what-default run } else { @@ -61,5 +62,6 @@ if {[check_effective_target_loongarch_asx_hw]} then { dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/lasx/*.\[cS\]]] \ " -mlasx" $DEFAULT_CFLAGS +set dg-do-what-default ${saved-dg-do-what-default} # All done. dg-finish diff --git a/gcc/testsuite/gcc.target/riscv/bext-ext-2.c b/gcc/testsuite/gcc.target/riscv/bext-ext-2.c new file mode 100644 index 0000000..aa170d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bext-ext-2.c @@ -0,0 +1,74 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcb -mabi=lp64" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +struct obstack; +struct bitmap_head_def; +typedef struct bitmap_head_def *bitmap; +struct obstack +{ + long chunk_size; + struct _obstack_chunk *chunk; + char *object_base; + char *next_free; + char *chunk_limit; + long int temp; + int alignment_mask; + + + + struct _obstack_chunk *(*chunkfun) (void *, long); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; + unsigned use_extra_arg:1; + unsigned maybe_empty_object:1; + + + + unsigned alloc_failed:1; + + +}; + +typedef unsigned long BITMAP_WORD; +typedef struct bitmap_obstack { + struct bitmap_element_def *elements; + struct bitmap_head_def *heads; + struct obstack obstack; +} bitmap_obstack; +typedef struct bitmap_element_def { + struct bitmap_element_def *next; + struct bitmap_element_def *prev; + unsigned int indx; + BITMAP_WORD bits[((128 + (8 + * 8 * 1u) - 1) / (8 + * 8 * 1u))]; +} bitmap_element; +bitmap_element *bitmap_find_bit (bitmap, unsigned int); + + +int +bitmap_bit_p (bitmap head, int bit) +{ + bitmap_element *ptr; + unsigned bit_num; + unsigned word_num; + + ptr = bitmap_find_bit (head, bit); + if (ptr == 0) + return 0; + + bit_num = bit % (8 + * 8 * 1u); + word_num = bit / (8 + * 8 * 1u) % ((128 + (8 + * 8 * 1u) - 1) / (8 + * 8 * 1u)); + + return (ptr->bits[word_num] >> bit_num) & 1; +} + +/* { dg-final { scan-assembler-times "bext\t" 1 } } */ +/* { dg-final { scan-assembler-not "slr\t"} } */ +/* { dg-final { scan-assembler-not "andi\t"} } */ + diff --git a/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv32.c b/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv32.c new file mode 100644 index 0000000..4f48cff --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv32.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32g_zicfiss -fcf-protection=return -mabi=ilp32d " } */ + +void foo() {} + +/* { dg-final { scan-assembler-times ".p2align\t2" 3 } } */ +/* { dg-final { scan-assembler-not ".p2align\t3" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv64.c b/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv64.c new file mode 100644 index 0000000..1bfd127 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/gnu-property-align-rv64.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64g_zicfiss -fcf-protection=return -mabi=lp64d " } */ + +void foo() {} + +/* { dg-final { scan-assembler-times ".p2align\t3" 3 } } */ +/* { dg-final { scan-assembler-not ".p2align\t2" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c b/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c new file mode 100644 index 0000000..1ee7f6c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/jump-table-large-code-model.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64 -mcmodel=large" } */ + +int foo(int x, int y) +{ + switch(x){ + case 0: + return 123 + y; + case 1: + return 456 + y; + case 2: + return 789 - y; + case 3: + return 12 * y; + case 4: + return 13 % y; + case 5: + return 11 *y; + } + return 0; +} + + +/* { dg-final { scan-assembler-not "\.section \.rodata" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr108016.c b/gcc/testsuite/gcc.target/riscv/pr108016.c new file mode 100644 index 0000000..b60df42 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr108016.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + +unsigned int addu (unsigned int a, unsigned int b) +{ + unsigned int out; + unsigned int overflow = __builtin_add_overflow (a, b, &out); + return overflow & out; +} + +int addi (int a, int b) +{ + int out; + int overflow = __builtin_add_overflow (a, b, &out); + return overflow & out; +} + +unsigned int subu (unsigned int a, unsigned int b) +{ + unsigned int out; + unsigned int overflow = __builtin_sub_overflow (a, b, &out); + return overflow & out; +} + +int subi (int a, int b) +{ + int out; + int overflow = __builtin_sub_overflow (a, b, &out); + return overflow & out; +} + +/* { dg-final { scan-assembler-not "sext\.w\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr118410-1.c b/gcc/testsuite/gcc.target/riscv/pr118410-1.c new file mode 100644 index 0000000..4a8b847 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr118410-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gcb -mabi=lp64d" { target { rv64} } } */ +/* { dg-options "-march=rv32gcb -mabi=ilp32" { target { rv32} } } */ + +long orlow(long x) { return x | ((1L << 24) - 1); } + +/* { dg-final { scan-assembler-times "orn\t" 1 } } */ +/* { dg-final { scan-assembler-not "addi\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr118410-2.c b/gcc/testsuite/gcc.target/riscv/pr118410-2.c new file mode 100644 index 0000000..b63a1d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr118410-2.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ +/* { dg-options "-march=rv64gcb -mabi=lp64d" { target { rv64} } } */ +/* { dg-options "-march=rv32gcb -mabi=ilp32" { target { rv32} } } */ + +long xorlow(long x) { return x ^ ((1L << 24) - 1); } + +/* { dg-final { scan-assembler-times "xnor\t" 1 } } */ +/* { dg-final { scan-assembler-not "addi\t" } } */ diff --git a/gcc/testsuite/gcc.target/sh/pr111814.c b/gcc/testsuite/gcc.target/sh/pr111814.c new file mode 100644 index 0000000..a88e5d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr111814.c @@ -0,0 +1,7 @@ +/* Verify that __builtin_nan("") produces a constant matches + architecture specification. */ +/* { dg-do compile } */ + +double d = __builtin_nan (""); + +/* { dg-final { scan-assembler "\t.long\t-1\n\t.long\t2146959359\n" } } */ diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21247.d b/gcc/testsuite/gdc.test/fail_compilation/test21247.d new file mode 100644 index 0000000..c3e4105 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21247.d @@ -0,0 +1,20 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test21247.d(13): Error: anonymous union can only be a part of an aggregate, not function `hang_dmd` +fail_compilation/test21247.d(17): Error: undefined identifier `u` +fail_compilation/test21247.d(18): Error: undefined identifier `b` +fail_compilation/test21247.d(20): called from here: `hang_dmd(0u)` +--- + */ +// https://github.com/dlang/dmd/issues/21247 +ubyte[4] hang_dmd(uint a) +{ + union { + uint u = void; + ubyte[4] b; + } + u = a; + return b; +} +enum T = hang_dmd(0); diff --git a/gcc/testsuite/gdc.test/fail_compilation/test21247b.d b/gcc/testsuite/gdc.test/fail_compilation/test21247b.d new file mode 100644 index 0000000..ecd4603 --- /dev/null +++ b/gcc/testsuite/gdc.test/fail_compilation/test21247b.d @@ -0,0 +1,14 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/test21247b.d(10): Error: anonymous union can only be a part of an aggregate, not function `test21247` +--- + */ +// https://github.com/dlang/dmd/issues/21247 +void test21247() +{ + union { + uint u = void; + ubyte[4] b; + } +} diff --git a/gcc/testsuite/gfortran.dg/do_concurrent_all_clauses.f90 b/gcc/testsuite/gfortran.dg/do_concurrent_all_clauses.f90 index 0c8a6ad..a7fa7c3 100644 --- a/gcc/testsuite/gfortran.dg/do_concurrent_all_clauses.f90 +++ b/gcc/testsuite/gfortran.dg/do_concurrent_all_clauses.f90 @@ -18,7 +18,7 @@ program do_concurrent_all_clauses squared = i * i arr(i) = temp2 + squared sum = sum + arr(i) - max_val = max(max_val, arr(i)) ! { dg-error "Reference to impure function" } + max_val = max(max_val, arr(i)) end block end do print *, arr, sum, max_val diff --git a/gcc/testsuite/gfortran.dg/pr119836_1.f90 b/gcc/testsuite/gfortran.dg/pr119836_1.f90 new file mode 100644 index 0000000..984e2d0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr119836_1.f90 @@ -0,0 +1,18 @@ +! +! { dg-do run } +! +! PR fortran/119836 +! +program p + implicit none + integer, parameter :: n = 4 + integer :: i + integer :: y(n), x(n) + do concurrent (i=1:n) + x(i) = shiftl (i,1) ! accepted + block + y(i) = shiftl (i,1) ! wrongly rejected + end block + end do + if (any(x /= y)) stop 1 +end program p diff --git a/gcc/testsuite/gfortran.dg/pr119836_2.f90 b/gcc/testsuite/gfortran.dg/pr119836_2.f90 new file mode 100644 index 0000000..5e2d0c9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr119836_2.f90 @@ -0,0 +1,21 @@ +! +! { dg-do compile } +! +! PR fortran/119836 +! +! Although intrinsic functions contained within the Fortran standard +! are pure procedures, many of the additional intrinsic functions +! supplied in libgfortran are impure. RAND() is one such function. +! +program foo + implicit none + integer i + real x(4) + do concurrent (i=1:4) + x = rand() ! { dg-error "Reference to impure function" } + block + x = rand() ! { dg-error "Reference to impure function" } + end block + end do + print *, x +end program foo diff --git a/gcc/testsuite/gfortran.dg/pr119836_3.f90 b/gcc/testsuite/gfortran.dg/pr119836_3.f90 new file mode 100644 index 0000000..69a5fcf --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr119836_3.f90 @@ -0,0 +1,30 @@ +! +! { dg-do run } +! +! PR fortran/119836 +! +program p + implicit none + integer, parameter :: n = 4 + integer :: i + integer :: y(n), x(n) + x = [(i,i=1,n)] + do concurrent (i=1:n) + call bar(x, y) + end do + if (any(x /= y)) stop 1 + x = 2 * x + do concurrent (i=1:n) + block + call bar(x, y) + end block + end do + if (any(x /= y)) stop 1 + + contains + elemental subroutine bar(x, y) + integer, intent(in) :: x + integer, intent(out) :: y + y = x + end subroutine +end program p diff --git a/gcc/testsuite/gfortran.dg/pr119836_4.f90 b/gcc/testsuite/gfortran.dg/pr119836_4.f90 new file mode 100644 index 0000000..dc6f72b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr119836_4.f90 @@ -0,0 +1,30 @@ +! +! { dg-do compile } +! +! PR fortran/119836 +! +program p + implicit none + integer, parameter :: n = 4 + integer :: i + integer :: y(n), x(n) + x = [(i,i=1,n)] + do concurrent (i=1:n) + call bar(x, y) ! { dg-error "Subroutine call" } + end do + if (any(x /= y)) stop 1 + x = 2 * x + do concurrent (i=1:n) + block + call bar(x, y) ! { dg-error "Subroutine call" } + end block + end do + if (any(x /= y)) stop 1 + + contains + subroutine bar(x, y) + integer, intent(in) :: x(:) + integer, intent(out) :: y(:) + y = x + end subroutine +end program p diff --git a/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90 b/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90 new file mode 100644 index 0000000..92640e2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90 @@ -0,0 +1,49 @@ +! { dg-do compile } +! PR fortran/106948 - check that passing of PURE procedures works +! +! Contributed by Jim Feng + +module a + implicit none + + interface new + pure module subroutine b(x, f) + integer, intent(inout) :: x + interface + pure function f(x) result(r) + real, intent(in) :: x + real :: r + end function f + end interface + end subroutine b + end interface new +end module a + +submodule(a) a_b + implicit none + +contains + module procedure b + x = int(f(real(x)) * 0.15) + end procedure b +end submodule a_b + +program test + use a + implicit none + + integer :: x + + x = 100 + call new(x, g) + print *, x + +contains + + pure function g(y) result(r) + real, intent(in) :: y + real :: r + + r = sqrt(y) + end function g +end program test diff --git a/gcc/testsuite/gnat.dg/opt105.adb b/gcc/testsuite/gnat.dg/opt105.adb new file mode 100644 index 0000000..eb2c197 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105.adb @@ -0,0 +1,30 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Opt105_Pkg; use Opt105_Pkg; + +procedure Opt105 is + + Val : constant Enum := + (if Enabled then (if Disabled then Two else One) else Three); + +begin + if Cond1 then + return; + end if; + + if Cond2 then + return; + end if; + + case Val is + when One => + raise Program_Error; + + when Two => + raise Constraint_Error; + + when Three => + null; + end case; +end; diff --git a/gcc/testsuite/gnat.dg/opt105_pkg.adb b/gcc/testsuite/gnat.dg/opt105_pkg.adb new file mode 100644 index 0000000..e00de94 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105_pkg.adb @@ -0,0 +1,6 @@ +package body Opt105_Pkg is + + function Cond1 return Boolean is (False); + function Cond2 return Boolean is (False); + +end Opt105_Pkg; diff --git a/gcc/testsuite/gnat.dg/opt105_pkg.ads b/gcc/testsuite/gnat.dg/opt105_pkg.ads new file mode 100644 index 0000000..2b373b7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt105_pkg.ads @@ -0,0 +1,11 @@ +package Opt105_Pkg is + + type Enum is (One, Two, Three); + + Enabled : Boolean := False; + Disabled : Boolean := False; + + function Cond1 return Boolean; + function Cond2 return Boolean; + +end Opt105_Pkg; diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index a62f459..869d150 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -562,6 +562,16 @@ proc check_effective_target_elf { } { } } +# Returns 1 if the target uses the PE/COFF object format, 0 otherwise. + +proc check_effective_target_pe { } { + if { [gcc_target_object_format] == "pe" } { + return 1; + } else { + return 0; + } +} + # Returns 1 if the target toolchain supports ifunc, 0 otherwise. proc check_ifunc_available { } { diff --git a/gcc/testsuite/rust/compile/nr2/compile.exp b/gcc/testsuite/rust/compile/nr2/compile.exp index 4d91dd0..9e15cdd 100644 --- a/gcc/testsuite/rust/compile/nr2/compile.exp +++ b/gcc/testsuite/rust/compile/nr2/compile.exp @@ -19,6 +19,15 @@ # Load support procs. load_lib rust-dg.exp +# These tests don't run runtest_file_p consistently if it +# doesn't return the same values, so disable parallelization +# of this *.exp file. The first parallel runtest to reach +# this will run all the tests serially. +if ![gcc_parallel_test_run_p compile] { + return +} +gcc_parallel_test_enable 0 + # Initialize `dg'. dg-init @@ -136,3 +145,5 @@ namespace eval rust-nr2-ns { # All done. dg-finish + +gcc_parallel_test_enable 1 diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc index bc632e3..d1d58bf 100644 --- a/gcc/tree-ssa-dse.cc +++ b/gcc/tree-ssa-dse.cc @@ -566,16 +566,17 @@ maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt) The most common case for getting here is a CONSTRUCTOR with no elements being used to zero initialize an object. We do not try to handle other cases as those would force us to fully cover the object with the - CONSTRUCTOR node except for the components that are dead. */ + CONSTRUCTOR node except for the components that are dead. + Also handles integer stores of 0 which can happen with memset/memcpy optimizations. */ static void -maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt) +maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt, bool was_integer_cst) { tree ctor = gimple_assign_rhs1 (stmt); /* This is the only case we currently handle. It actually seems to catch most cases of actual interest. */ - gcc_assert (CONSTRUCTOR_NELTS (ctor) == 0); + gcc_assert (was_integer_cst ? integer_zerop (ctor) : CONSTRUCTOR_NELTS (ctor) == 0); int head_trim = 0; int tail_trim = 0; @@ -588,6 +589,8 @@ maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt) /* We want &lhs for the MEM_REF expression. */ tree lhs_addr = build_fold_addr_expr (gimple_assign_lhs (stmt)); + STRIP_USELESS_TYPE_CONVERSION (lhs_addr); + if (! is_gimple_min_invariant (lhs_addr)) return; @@ -802,11 +805,16 @@ maybe_trim_partially_dead_store (ao_ref *ref, sbitmap live, gimple *stmt) switch (gimple_assign_rhs_code (stmt)) { case CONSTRUCTOR: - maybe_trim_constructor_store (ref, live, stmt); + maybe_trim_constructor_store (ref, live, stmt, false); break; case COMPLEX_CST: maybe_trim_complex_store (ref, live, stmt); break; + case INTEGER_CST: + if (integer_zerop (gimple_assign_rhs1 (stmt)) + && type_has_mode_precision_p (TREE_TYPE (gimple_assign_lhs (stmt)))) + maybe_trim_constructor_store (ref, live, stmt, true); + break; default: break; } diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index 7d2d169..a194bf6 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -403,12 +403,15 @@ factor_out_conditional_operation (edge e0, edge e1, basic_block merge, if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt))) return false; - /* Only handle if arg1 is a INTEGER_CST and one that fits - into the new type or if it is the same precision. */ + /* If arg1 is an INTEGER_CST, fold it to new type if it fits, or else + if the bits will not be modified during the conversion, except for + boolean types whose precision is not 1 (see int_fits_type_p). */ if (!INTEGRAL_TYPE_P (TREE_TYPE (new_arg0)) || !(int_fits_type_p (arg1, TREE_TYPE (new_arg0)) || (TYPE_PRECISION (TREE_TYPE (new_arg0)) - == TYPE_PRECISION (TREE_TYPE (arg1))))) + == TYPE_PRECISION (TREE_TYPE (arg1)) + && (TREE_CODE (TREE_TYPE (new_arg0)) != BOOLEAN_TYPE + || TYPE_PRECISION (TREE_TYPE (new_arg0)) == 1)))) return false; /* For the INTEGER_CST case, we are just moving the diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 9413dce..2d35fa1 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -653,6 +653,10 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, class loop *loop, if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "Detected induction.\n"); STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def; + + /* Mark if we have a non-linear IV. */ + LOOP_VINFO_NON_LINEAR_IV (loop_vinfo) + = STMT_VINFO_LOOP_PHI_EVOLUTION_TYPE (stmt_vinfo) != vect_step_op_add; } @@ -1046,12 +1050,14 @@ _loop_vec_info::_loop_vec_info (class loop *loop_in, vec_info_shared *shared) suggested_unroll_factor (1), max_vectorization_factor (0), mask_skip_niters (NULL_TREE), + mask_skip_niters_pfa_offset (NULL_TREE), rgroup_compare_type (NULL_TREE), simd_if_cond (NULL_TREE), partial_vector_style (vect_partial_vectors_none), unaligned_dr (NULL), peeling_for_alignment (0), ptr_mask (0), + nonlinear_iv (false), ivexpr_map (NULL), scan_map (NULL), slp_unrolling_factor (1), @@ -10678,6 +10684,54 @@ vectorizable_induction (loop_vec_info loop_vinfo, LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo)); peel_mul = gimple_build_vector_from_val (&init_stmts, step_vectype, peel_mul); + + /* If early break then we have to create a new PHI which we can use as + an offset to adjust the induction reduction in early exits. + + This is because when peeling for alignment using masking, the first + few elements of the vector can be inactive. As such if we find the + entry in the first iteration we have adjust the starting point of + the scalar code. + + We do this by creating a new scalar PHI that keeps track of whether + we are the first iteration of the loop (with the additional masking) + or whether we have taken a loop iteration already. + + The generated sequence: + + pre-header: + bb1: + i_1 = <number of leading inactive elements> + + header: + bb2: + i_2 = PHI <i_1(bb1), 0(latch)> + … + + early-exit: + bb3: + i_3 = iv_step * i_2 + PHI<vector-iv> + + The first part of the adjustment to create i_1 and i_2 are done here + and the last part creating i_3 is done in + vectorizable_live_operations when the induction extraction is + materialized. */ + if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo) + && !LOOP_VINFO_MASK_NITERS_PFA_OFFSET (loop_vinfo)) + { + auto skip_niters = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo); + tree ty_skip_niters = TREE_TYPE (skip_niters); + tree break_lhs_phi = vect_get_new_vect_var (ty_skip_niters, + vect_scalar_var, + "pfa_iv_offset"); + gphi *nphi = create_phi_node (break_lhs_phi, bb); + add_phi_arg (nphi, skip_niters, pe, UNKNOWN_LOCATION); + add_phi_arg (nphi, build_zero_cst (ty_skip_niters), + loop_latch_edge (iv_loop), UNKNOWN_LOCATION); + + LOOP_VINFO_MASK_NITERS_PFA_OFFSET (loop_vinfo) + = PHI_RESULT (nphi); + } } tree step_mul = NULL_TREE; unsigned ivn; @@ -11565,8 +11619,10 @@ vectorizable_live_operation (vec_info *vinfo, stmt_vec_info stmt_info, /* For early exit where the exit is not in the BB that leads to the latch then we're restarting the iteration in the scalar loop. So get the first live value. */ - if ((all_exits_as_early_p || !main_exit_edge) - && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def) + bool early_break_first_element_p + = (all_exits_as_early_p || !main_exit_edge) + && STMT_VINFO_DEF_TYPE (stmt_info) == vect_induction_def; + if (early_break_first_element_p) { tmp_vec_lhs = vec_lhs0; tmp_bitstart = build_zero_cst (TREE_TYPE (bitstart)); @@ -11581,6 +11637,45 @@ vectorizable_live_operation (vec_info *vinfo, stmt_vec_info stmt_info, lhs_type, &exit_gsi); auto gsi = gsi_for_stmt (use_stmt); + if (early_break_first_element_p + && LOOP_VINFO_MASK_NITERS_PFA_OFFSET (loop_vinfo)) + { + tree step_expr + = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (stmt_info); + tree break_lhs_phi + = LOOP_VINFO_MASK_NITERS_PFA_OFFSET (loop_vinfo); + tree ty_skip_niters = TREE_TYPE (break_lhs_phi); + gimple_seq iv_stmts = NULL; + + /* Now create the PHI for the outside loop usage to + retrieve the value for the offset counter. */ + tree rphi_step + = gimple_convert (&iv_stmts, ty_skip_niters, step_expr); + tree tmp2 + = gimple_build (&iv_stmts, MULT_EXPR, + ty_skip_niters, rphi_step, + break_lhs_phi); + + if (POINTER_TYPE_P (TREE_TYPE (new_tree))) + { + tmp2 = gimple_convert (&iv_stmts, sizetype, tmp2); + tmp2 = gimple_build (&iv_stmts, POINTER_PLUS_EXPR, + TREE_TYPE (new_tree), new_tree, + tmp2); + } + else + { + tmp2 = gimple_convert (&iv_stmts, TREE_TYPE (new_tree), + tmp2); + tmp2 = gimple_build (&iv_stmts, PLUS_EXPR, + TREE_TYPE (new_tree), new_tree, + tmp2); + } + + new_tree = tmp2; + gsi_insert_seq_before (&exit_gsi, iv_stmts, GSI_SAME_STMT); + } + tree lhs_phi = gimple_phi_result (use_stmt); remove_phi_node (&gsi, false); gimple *copy = gimple_build_assign (lhs_phi, new_tree); diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 7f87435..5af1973 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -13615,29 +13615,23 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, codegen so we must replace the original insn. */ gimple *orig_stmt = STMT_VINFO_STMT (vect_orig_stmt (stmt_info)); gcond *cond_stmt = as_a <gcond *>(orig_stmt); + + tree cst = build_zero_cst (vectype); + auto bb = gimple_bb (cond_stmt); + edge exit_true_edge = EDGE_SUCC (bb, 0); + if (exit_true_edge->flags & EDGE_FALSE_VALUE) + exit_true_edge = EDGE_SUCC (bb, 1); + gcc_assert (exit_true_edge->flags & EDGE_TRUE_VALUE); + /* When vectorizing we assume that if the branch edge is taken that we're exiting the loop. This is not however always the case as the compiler will rewrite conditions to always be a comparison against 0. To do this it sometimes flips the edges. This is fine for scalar, but for vector we - then have to flip the test, as we're still assuming that if you take the - branch edge that we found the exit condition. i.e. we need to know whether - we are generating a `forall` or an `exist` condition. */ - auto new_code = NE_EXPR; - auto reduc_optab = ior_optab; - auto reduc_op = BIT_IOR_EXPR; - tree cst = build_zero_cst (vectype); - edge exit_true_edge = EDGE_SUCC (gimple_bb (cond_stmt), 0); - if (exit_true_edge->flags & EDGE_FALSE_VALUE) - exit_true_edge = EDGE_SUCC (gimple_bb (cond_stmt), 1); - gcc_assert (exit_true_edge->flags & EDGE_TRUE_VALUE); - if (flow_bb_inside_loop_p (LOOP_VINFO_LOOP (loop_vinfo), - exit_true_edge->dest)) - { - new_code = EQ_EXPR; - reduc_optab = and_optab; - reduc_op = BIT_AND_EXPR; - cst = build_minus_one_cst (vectype); - } + then have to negate the result of the test, as we're still assuming that if + you take the branch edge that we found the exit condition. i.e. we need to + know whether we are generating a `forall` or an `exist` condition. */ + bool flipped = flow_bb_inside_loop_p (LOOP_VINFO_LOOP (loop_vinfo), + exit_true_edge->dest); /* Analyze only. */ if (!vec_stmt) @@ -13653,14 +13647,13 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, } if (ncopies > 1 - && direct_optab_handler (reduc_optab, mode) == CODE_FOR_nothing) + && direct_optab_handler (ior_optab, mode) == CODE_FOR_nothing) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "can't vectorize early exit because the " - "target does not support boolean vector %s " + "target does not support boolean vector IOR " "for type %T.\n", - reduc_optab == ior_optab ? "OR" : "AND", vectype); return false; } @@ -13720,6 +13713,29 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, stmts.quick_push (gimple_assign_lhs (stmt)); } + /* If we're comparing against a previous forall we need to negate the resullts + before we do the final comparison or reduction. */ + if (flipped) + { + /* Rewrite the if(all(mask)) into if (!all(mask)) which is the same as + if (any(~mask)) by negating the masks and flipping the branches. + + 1. For unmasked loops we simply reduce the ~mask. + 2. For masked loops we reduce (~mask & loop_mask) which is the same as + doing (mask & loop_mask) ^ loop_mask. */ + for (unsigned i = 0; i < stmts.length (); i++) + { + tree inv_lhs = make_temp_ssa_name (vectype, NULL, "vexit_inv"); + auto inv_stmt = gimple_build_assign (inv_lhs, BIT_NOT_EXPR, stmts[i]); + vect_finish_stmt_generation (loop_vinfo, stmt_info, inv_stmt, + &cond_gsi); + stmts[i] = inv_lhs; + } + + EDGE_SUCC (bb, 0)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); + EDGE_SUCC (bb, 1)->flags ^= (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); + } + /* Determine if we need to reduce the final value. */ if (stmts.length () > 1) { @@ -13758,7 +13774,7 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, new_temp = make_temp_ssa_name (vectype, NULL, "vexit_reduc"); tree arg0 = workset.pop (); tree arg1 = workset.pop (); - new_stmt = gimple_build_assign (new_temp, reduc_op, arg0, arg1); + new_stmt = gimple_build_assign (new_temp, BIT_IOR_EXPR, arg0, arg1); vect_finish_stmt_generation (loop_vinfo, stmt_info, new_stmt, &cond_gsi); workset.quick_insert (0, new_temp); @@ -13781,7 +13797,7 @@ vectorizable_early_exit (vec_info *vinfo, stmt_vec_info stmt_info, gcc_assert (new_temp); - gimple_cond_set_condition (cond_stmt, new_code, new_temp, cst); + gimple_cond_set_condition (cond_stmt, NE_EXPR, new_temp, cst); update_stmt (orig_stmt); if (slp_node) diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 97caf61..01d19c7 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -818,6 +818,11 @@ public: elements that should be false in the first mask). */ tree mask_skip_niters; + /* If we are using a loop mask to align memory addresses and we're in an + early break loop then this variable contains the number of elements that + were skipped during the initial iteration of the loop. */ + tree mask_skip_niters_pfa_offset; + /* The type that the loop control IV should be converted to before testing which of the VF scalars are active and inactive. Only meaningful if LOOP_VINFO_USING_PARTIAL_VECTORS_P. */ @@ -854,6 +859,9 @@ public: /* The mask used to check the alignment of pointers or arrays. */ int ptr_mask; + /* Indicates whether the loop has any non-linear IV. */ + bool nonlinear_iv; + /* Data Dependence Relations defining address ranges that are candidates for a run-time aliasing check. */ auto_vec<ddr_p> may_alias_ddrs; @@ -1064,6 +1072,7 @@ public: #define LOOP_VINFO_MASKS(L) (L)->masks #define LOOP_VINFO_LENS(L) (L)->lens #define LOOP_VINFO_MASK_SKIP_NITERS(L) (L)->mask_skip_niters +#define LOOP_VINFO_MASK_NITERS_PFA_OFFSET(L) (L)->mask_skip_niters_pfa_offset #define LOOP_VINFO_RGROUP_COMPARE_TYPE(L) (L)->rgroup_compare_type #define LOOP_VINFO_RGROUP_IV_TYPE(L) (L)->rgroup_iv_type #define LOOP_VINFO_PARTIAL_VECTORS_STYLE(L) (L)->partial_vector_style @@ -1073,6 +1082,7 @@ public: #define LOOP_VINFO_DDRS(L) (L)->shared->ddrs #define LOOP_VINFO_INT_NITERS(L) (TREE_INT_CST_LOW ((L)->num_iters)) #define LOOP_VINFO_PEELING_FOR_ALIGNMENT(L) (L)->peeling_for_alignment +#define LOOP_VINFO_NON_LINEAR_IV(L) (L)->nonlinear_iv #define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr #define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts #define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs @@ -2138,8 +2148,14 @@ unlimited_cost_model (loop_p loop) inline bool vect_use_loop_mask_for_alignment_p (loop_vec_info loop_vinfo) { + /* With early break vectorization we don't know whether the accesses will stay + inside the loop or not. TODO: The early break adjustment code can be + implemented the same way as vectorizable_linear_induction. However we + can't test this today so reject it. */ return (LOOP_VINFO_FULLY_MASKED_P (loop_vinfo) - && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo)); + && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) + && !(LOOP_VINFO_NON_LINEAR_IV (loop_vinfo) + && LOOP_VINFO_EARLY_BREAKS (loop_vinfo))); } /* Return the number of vectors of type VECTYPE that are needed to get diff --git a/gcc/tree.def b/gcc/tree.def index c4ad8d0..2c37e44 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -135,7 +135,11 @@ DEFTREECODE (OFFSET_TYPE, "offset_type", tcc_type, 0) DEFTREECODE (ENUMERAL_TYPE, "enumeral_type", tcc_type, 0) /* Boolean type (true or false are the only values). Looks like an - INTEGRAL_TYPE. */ + INTEGER_TYPE, but must be dealt with specially because TYPE_PRECISION + may be arbitrary despite the restricted set of valid values (in other + words, boolean types with TYPE_PRECISION > 1 exist in some languages). + Similarly, TYPE_UNSIGNED may be false for components of vector masks, + as well as for boolean types in languages other than C. */ DEFTREECODE (BOOLEAN_TYPE, "boolean_type", tcc_type, 0) /* Integer types in all languages, including char in C. diff --git a/libatomic/ChangeLog b/libatomic/ChangeLog index ac7e729..62e6c4e 100644 --- a/libatomic/ChangeLog +++ b/libatomic/ChangeLog @@ -1,3 +1,23 @@ +2025-04-16 Jakub Jelinek <jakub@redhat.com> + + PR libgcc/101075 + PR libgcc/119796 + * config/mingw/lock.c (libat_lock_n, libat_unlock_n): Start with + computing how many locks will be needed and take into account + ((uintptr_t)ptr % WATCH_SIZE). If some locks from the end of the + locks array and others from the start of it will be needed, first + lock the ones from the start followed by ones from the end. + +2025-04-16 Jakub Jelinek <jakub@redhat.com> + + PR libgcc/101075 + PR libgcc/119796 + * config/posix/lock.c (libat_lock_n, libat_unlock_n): Start with + computing how many locks will be needed and take into account + ((uintptr_t)ptr % WATCH_SIZE). If some locks from the end of the + locks array and others from the start of it will be needed, first + lock the ones from the start followed by ones from the end. + 2025-01-10 Wilco Dijkstra <wilco.dijkstra@arm.com> * config/linux/aarch64/host-config.h (has_lse2): Cleanup. diff --git a/libatomic/config/mingw/lock.c b/libatomic/config/mingw/lock.c index 17faa66..8b0b4dd 100644 --- a/libatomic/config/mingw/lock.c +++ b/libatomic/config/mingw/lock.c @@ -87,21 +87,30 @@ libat_lock_n (void *ptr, size_t n) { uintptr_t h = addr_hash (ptr); size_t i = 0; + size_t nlocks + = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE; /* Don't lock more than all the locks we have. */ - if (n > PAGE_SIZE) - n = PAGE_SIZE; + if (nlocks > NLOCKS) + nlocks = NLOCKS; - do + if (__builtin_expect (h + nlocks > NLOCKS, 0)) + { + size_t j = h + nlocks - NLOCKS; + for (; i < j; ++i) + { + if (!locks[i].mutex) + locks[i].mutex = CreateMutex (NULL, FALSE, NULL); + WaitForSingleObject (locks[i].mutex, INFINITE); + } + } + + for (; i < nlocks; ++i) { if (!locks[h].mutex) - locks[h].mutex = CreateMutex (NULL, FALSE, NULL); - WaitForSingleObject (locks[h].mutex, INFINITE); - if (++h == NLOCKS) - h = 0; - i += WATCH_SIZE; + locks[h].mutex = CreateMutex (NULL, FALSE, NULL); + WaitForSingleObject (locks[h++].mutex, INFINITE); } - while (i < n); } void @@ -109,17 +118,22 @@ libat_unlock_n (void *ptr, size_t n) { uintptr_t h = addr_hash (ptr); size_t i = 0; + size_t nlocks + = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE; - if (n > PAGE_SIZE) - n = PAGE_SIZE; + /* Don't lock more than all the locks we have. */ + if (nlocks > NLOCKS) + nlocks = NLOCKS; - do + if (__builtin_expect (h + nlocks > NLOCKS, 0)) { - if (locks[h].mutex) - ReleaseMutex (locks[h].mutex); - if (++h == NLOCKS) - h = 0; - i += WATCH_SIZE; + size_t j = h + nlocks - NLOCKS; + for (; i < j; ++i) + if (locks[i].mutex) + ReleaseMutex (locks[i].mutex); } - while (i < n); + + for (; i < nlocks; ++i, ++h) + if (locks[h].mutex) + ReleaseMutex (locks[h].mutex); } diff --git a/libatomic/config/posix/lock.c b/libatomic/config/posix/lock.c index 6ee4240..5662b77 100644 --- a/libatomic/config/posix/lock.c +++ b/libatomic/config/posix/lock.c @@ -81,19 +81,22 @@ libat_lock_n (void *ptr, size_t n) { uintptr_t h = addr_hash (ptr); size_t i = 0; + size_t nlocks + = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE; /* Don't lock more than all the locks we have. */ - if (n > PAGE_SIZE) - n = PAGE_SIZE; + if (nlocks > NLOCKS) + nlocks = NLOCKS; - do + if (__builtin_expect (h + nlocks > NLOCKS, 0)) { - pthread_mutex_lock (&locks[h].mutex); - if (++h == NLOCKS) - h = 0; - i += WATCH_SIZE; + size_t j = h + nlocks - NLOCKS; + for (; i < j; ++i) + pthread_mutex_lock (&locks[i].mutex); } - while (i < n); + + for (; i < nlocks; ++i) + pthread_mutex_lock (&locks[h++].mutex); } void @@ -101,16 +104,20 @@ libat_unlock_n (void *ptr, size_t n) { uintptr_t h = addr_hash (ptr); size_t i = 0; + size_t nlocks + = (n + ((uintptr_t)ptr % WATCH_SIZE) + WATCH_SIZE - 1) / WATCH_SIZE; - if (n > PAGE_SIZE) - n = PAGE_SIZE; + /* Don't lock more than all the locks we have. */ + if (nlocks > NLOCKS) + nlocks = NLOCKS; - do + if (__builtin_expect (h + nlocks > NLOCKS, 0)) { - pthread_mutex_unlock (&locks[h].mutex); - if (++h == NLOCKS) - h = 0; - i += WATCH_SIZE; + size_t j = h + nlocks - NLOCKS; + for (; i < j; ++i) + pthread_mutex_unlock (&locks[i].mutex); } - while (i < n); + + for (; i < nlocks; ++i) + pthread_mutex_unlock (&locks[h++].mutex); } diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 946bf13..66feed5 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,37 @@ +2025-04-19 Jiaxun Yang <jiaxun.yang@flygoat.com> + + PR target/118257 + * config/sh/sfp-machine.h (_FPU_GETCW): Implement with builtin. + (_FPU_SETCW): Likewise. + (FP_EX_ENABLE_SHIFT): Derive from arch spec. + (FP_EX_CAUSE_SHIFT): Likewise. + (FP_RND_MASK): Likewise. + (FP_EX_INVALID): Likewise. + (FP_EX_DIVZERO): Likewise. + (FP_EX_ALL): Likewise. + (FP_EX_OVERFLOW): Likewise. + (FP_EX_UNDERFLOW): Likewise. + (FP_EX_INEXACT): Likewise. + (_FP_DECL_EX): Declear default FCSR value. + (FP_RND_NEAREST): Derive from arch spec. + (FP_RND_ZERO): Likewise. + (FP_INIT_ROUNDMODE): Likewise. + (FP_ROUNDMODE): Likewise. + (FP_TRAPPING_EXCEPTIONS): Likewise. + (FP_HANDLE_EXCEPTIONS): Implement with _FPU_SETCW. + +2025-04-19 Jiaxun Yang <jiaxun.yang@flygoat.com> + + PR target/111814 + * config/sh/sfp-machine.h (_FP_NANFRAC_B): Reverse signaling bit. + (_FP_NANFRAC_H): Likewise. + (_FP_NANFRAC_S): Likewise. + (_FP_NANFRAC_D): Likewise. + (_FP_NANFRAC_Q): Likewise. + (_FP_KEEPNANFRACP): Enable for target. + (_FP_QNANNEGATEDP): Enable for target. + (_FP_CHOOSENAN): Port from MIPS. + 2025-04-14 Thomas Schwinge <tschwinge@baylibre.com> PR target/118794 diff --git a/libgcc/config/sh/sfp-machine.h b/libgcc/config/sh/sfp-machine.h index 66984d4..8030c80 100644 --- a/libgcc/config/sh/sfp-machine.h +++ b/libgcc/config/sh/sfp-machine.h @@ -39,11 +39,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) -#define _FP_NANFRAC_B _FP_QNANBIT_B -#define _FP_NANFRAC_H _FP_QNANBIT_H -#define _FP_NANFRAC_S _FP_QNANBIT_S -#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 -#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 +#define _FP_NANFRAC_B (_FP_QNANBIT_B - 1) +#define _FP_NANFRAC_H (_FP_QNANBIT_H - 1) +#define _FP_NANFRAC_S (_FP_QNANBIT_S - 1) +#define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1 +#define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1 /* The type of the result of a floating point comparison. This must match __libgcc_cmp_return__ in GCC for the target. */ @@ -56,15 +56,71 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); #define _FP_NANSIGN_D 0 #define _FP_NANSIGN_Q 0 -#define _FP_KEEPNANFRACP 0 -#define _FP_QNANNEGATEDP 0 +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 1 + +/* X is chosen unless one of the NaNs is sNaN. */ +# define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) | \ + _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#ifdef __SH_FPU_ANY__ +#define _FPU_GETCW(fpscr) fpscr = __builtin_sh_get_fpscr () +#define _FPU_SETCW(fpscr) __builtin_sh_set_fpscr (fpscr) +#define FP_EX_ENABLE_SHIFT 5 +#define FP_EX_CAUSE_SHIFT 10 -#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ - do { \ - R##_s = _FP_NANSIGN_##fs; \ - _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs); \ - R##_c = FP_CLS_NAN; \ +#define FP_EX_INVALID 0x0040 +#define FP_EX_DIVZERO 0x0020 +#if defined (__SH2E__) +#define FP_EX_ALL (FP_EX_DIVZERO | FP_EX_INVALID) +#else +#define FP_EX_OVERFLOW 0x0010 +#define FP_EX_UNDERFLOW 0x0008 +#define FP_EX_INEXACT 0x0004 +#define FP_EX_ALL (FP_EX_DIVZERO | FP_EX_INEXACT | \ + FP_EX_INVALID | FP_EX_OVERFLOW | FP_EX_UNDERFLOW) +#endif +#define _FP_DECL_EX \ + unsigned int _fcsr __attribute__ ((unused)) = FP_RND_NEAREST +/* Rounding modes. */ +#define FP_RND_NEAREST 0x0 +#define FP_RND_ZERO 0x1 +/* Placeholder, hardware does not have PINF/MINF modes. */ +#define FP_RND_PINF 0x2 +#define FP_RND_MINF 0x3 +#define FP_RND_MASK 3 + +#define FP_INIT_ROUNDMODE _FPU_GETCW (_fcsr) +#define FP_ROUNDMODE (_fcsr & FP_RND_MASK) +#define FP_TRAPPING_EXCEPTIONS ((_fcsr >> FP_EX_ENABLE_SHIFT) & FP_EX_ALL) +#define FP_HANDLE_EXCEPTIONS \ + do { \ + _fcsr &= ~(FP_EX_ALL << FP_EX_CAUSE_SHIFT); \ + _fcsr |= _fex | (_fex << FP_EX_CAUSE_SHIFT); \ + _FPU_SETCW (_fcsr); \ } while (0) +#else +#define FP_EX_INVALID (1 << 4) +#define FP_EX_DIVZERO (1 << 3) +#if !defined (__SH2E__) +#define FP_EX_OVERFLOW (1 << 2) +#define FP_EX_UNDERFLOW (1 << 1) +#define FP_EX_INEXACT (1 << 0) +#endif +#endif #define _FP_TININESS_AFTER_ROUNDING 1 diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index c61c9db..096e17b 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,32 @@ +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + PR libgomp/119849 + * testsuite/libgomp.c++/allocator-1.C (test_inequality, main): Guard + ompx::allocator::gnu_pinned_mem uses with #ifdef __gnu_linux__. + * testsuite/libgomp.c++/allocator-2.C (main): Likewise. + +2025-04-17 Tobias Burnus <tburnus@baylibre.com> + + * libgomp.texi (gcn interop, nvptx interop): For HIP with C/C++, add + a note about setting a preprocessor define. + +2025-04-16 Thomas Schwinge <tschwinge@baylibre.com> + + * testsuite/libgomp.c++/target-exceptions-pr118794-1.C: Remove + 'ALWAYS_INLINE' workaround. + +2025-04-16 Thomas Schwinge <tschwinge@baylibre.com> + + PR target/106445 + * testsuite/libgomp.c++/pr106445-1.C: New. + * testsuite/libgomp.c++/pr106445-1-O0.C: Likewise. + +2025-04-16 Thomas Schwinge <tschwinge@baylibre.com> + + PR target/97106 + * testsuite/libgomp.c++/pr96390.C: Un-XFAIL nvptx offloading. + * testsuite/libgomp.c-c++-common/pr96390.c: Adjust. + 2025-04-15 Tobias Burnus <tburnus@baylibre.com> * libgomp.texi (gcn, nvptx): Mention self_maps clause diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index dfd189b..6909c2b 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -6945,6 +6945,9 @@ or string (str) data type, call @code{omp_get_interop_int}, Note that @code{device_num} is the OpenMP device number while @code{device} is the HIP device number or HSA device handle. +When using HIP with C and C++, the @code{__HIP_PLATFORM_AMD__} preprocessor +macro must be defined before including the HIP header files. + For the API routine call, add the prefix @code{omp_ipr_} to the property name; for instance: @smallexample @@ -7107,6 +7110,9 @@ or string (str) data type, call @code{omp_get_interop_int}, Note that @code{device_num} is the OpenMP device number while @code{device} is the CUDA, CUDA Driver, or HIP device number. +When using HIP with C and C++, the @code{__HIP_PLATFORM_NVIDIA__} preprocessor +macro must be defined before including the HIP header files. + For the API routine call, add the prefix @code{omp_ipr_} to the property name; for instance: @smallexample diff --git a/libgomp/testsuite/libgomp.c++/allocator-1.C b/libgomp/testsuite/libgomp.c++/allocator-1.C index f820722..49425386 100644 --- a/libgomp/testsuite/libgomp.c++/allocator-1.C +++ b/libgomp/testsuite/libgomp.c++/allocator-1.C @@ -78,7 +78,10 @@ void test_inequality () CHECK_INEQUALITY (omp::allocator::cgroup_mem, void); CHECK_INEQUALITY (omp::allocator::pteam_mem, void); CHECK_INEQUALITY (omp::allocator::thread_mem, void); +#ifdef __gnu_linux__ + /* Pinning not implemented on other targets. */ CHECK_INEQUALITY (ompx::allocator::gnu_pinned_mem, void); +#endif /* And again with the same type passed to the allocator. */ CHECK_INEQUALITY (omp::allocator::null_allocator, T); CHECK_INEQUALITY (omp::allocator::default_mem, T); @@ -89,7 +92,9 @@ void test_inequality () CHECK_INEQUALITY (omp::allocator::cgroup_mem, T); CHECK_INEQUALITY (omp::allocator::pteam_mem, T); CHECK_INEQUALITY (omp::allocator::thread_mem, T); +#ifdef __gnu_linux__ CHECK_INEQUALITY (ompx::allocator::gnu_pinned_mem, T); +#endif } #undef CHECK_INEQUALITY @@ -121,7 +126,9 @@ int main () test<int, omp::allocator::cgroup_mem>(42); test<int, omp::allocator::pteam_mem>(42); test<int, omp::allocator::thread_mem>(42); +#ifdef __gnu_linux__ test<int, ompx::allocator::gnu_pinned_mem>(42); +#endif test<long long, omp::allocator::null_allocator>(42); test<long long, omp::allocator::default_mem>(42); @@ -132,7 +139,9 @@ int main () test<long long, omp::allocator::cgroup_mem>(42); test<long long, omp::allocator::pteam_mem>(42); test<long long, omp::allocator::thread_mem>(42); +#ifdef __gnu_linux__ test<long long, ompx::allocator::gnu_pinned_mem>(42); +#endif test<S, omp::allocator::null_allocator>( S{42, true, 128.f}); test<S, omp::allocator::default_mem>( S{42, true, 128.f}); @@ -143,7 +152,9 @@ int main () test<S, omp::allocator::cgroup_mem>( S{42, true, 128.f}); test<S, omp::allocator::pteam_mem>( S{42, true, 128.f}); test<S, omp::allocator::thread_mem>( S{42, true, 128.f}); +#ifdef __gnu_linux__ test<S, ompx::allocator::gnu_pinned_mem>(S{42, true, 128.f}); +#endif test_inequality<int, omp::allocator::null_allocator>(); test_inequality<int, omp::allocator::default_mem>(); @@ -154,5 +165,7 @@ int main () test_inequality<int, omp::allocator::cgroup_mem>(); test_inequality<int, omp::allocator::pteam_mem>(); test_inequality<int, omp::allocator::thread_mem>(); +#ifdef __gnu_linux__ test_inequality<int, ompx::allocator::gnu_pinned_mem>(); +#endif } diff --git a/libgomp/testsuite/libgomp.c++/allocator-2.C b/libgomp/testsuite/libgomp.c++/allocator-2.C index d25b755..ca94fc7 100644 --- a/libgomp/testsuite/libgomp.c++/allocator-2.C +++ b/libgomp/testsuite/libgomp.c++/allocator-2.C @@ -86,7 +86,10 @@ int main () f<int, omp::allocator::cgroup_mem >(0, 1, 2, 3); f<int, omp::allocator::pteam_mem >(0, 1, 2, 3); f<int, omp::allocator::thread_mem >(0, 1, 2, 3); +#ifdef __gnu_linux__ + /* Pinning not implemented on other targets. */ f<int, ompx::allocator::gnu_pinned_mem>(0, 1, 2, 3); +#endif f<long long, omp::allocator::null_allocator >(0, 1, 2, 3); f<long long, omp::allocator::default_mem >(0, 1, 2, 3); @@ -97,7 +100,9 @@ int main () f<long long, omp::allocator::cgroup_mem >(0, 1, 2, 3); f<long long, omp::allocator::pteam_mem >(0, 1, 2, 3); f<long long, omp::allocator::thread_mem >(0, 1, 2, 3); +#ifdef __gnu_linux__ f<long long, ompx::allocator::gnu_pinned_mem>(0, 1, 2, 3); +#endif S0 s0_0{ 42, true, 111128.f}; S0 s0_1{ 142, false, 11128.f}; @@ -112,7 +117,9 @@ int main () f<S0, omp::allocator::cgroup_mem >(s0_0, s0_1, s0_2, s0_3); f<S0, omp::allocator::pteam_mem >(s0_0, s0_1, s0_2, s0_3); f<S0, omp::allocator::thread_mem >(s0_0, s0_1, s0_2, s0_3); +#ifdef __gnu_linux__ f<S0, ompx::allocator::gnu_pinned_mem>(s0_0, s0_1, s0_2, s0_3); +#endif S1 s1_0{ 42, true, 111128.f}; S1 s1_1{ 142, false, 11128.f}; @@ -128,5 +135,7 @@ int main () f<S1, omp::allocator::cgroup_mem >(s1_0, s1_1, s1_2, s1_3); f<S1, omp::allocator::pteam_mem >(s1_0, s1_1, s1_2, s1_3); f<S1, omp::allocator::thread_mem >(s1_0, s1_1, s1_2, s1_3); +#ifdef __gnu_linux__ f<S1, ompx::allocator::gnu_pinned_mem>(s1_0, s1_1, s1_2, s1_3); +#endif } diff --git a/libgomp/testsuite/libgomp.c++/pr106445-1-O0.C b/libgomp/testsuite/libgomp.c++/pr106445-1-O0.C new file mode 100644 index 0000000..bcd499c --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/pr106445-1-O0.C @@ -0,0 +1,3 @@ +// { dg-additional-options -O0 } + +#include "pr106445-1.C" diff --git a/libgomp/testsuite/libgomp.c++/pr106445-1.C b/libgomp/testsuite/libgomp.c++/pr106445-1.C new file mode 100644 index 0000000..329ce62 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/pr106445-1.C @@ -0,0 +1,18 @@ +#include <vector> + +int main() +{ +#pragma omp target + { + { + std::vector<int> v; + if (!v.empty()) + __builtin_abort(); + } + { + std::vector<int> v(100); + if (v.capacity() < 100) + __builtin_abort(); + } + } +} diff --git a/libgomp/testsuite/libgomp.c++/pr96390.C b/libgomp/testsuite/libgomp.c++/pr96390.C index 1f3c3e0..be19601 100644 --- a/libgomp/testsuite/libgomp.c++/pr96390.C +++ b/libgomp/testsuite/libgomp.c++/pr96390.C @@ -1,6 +1,4 @@ /* { dg-additional-options "-O0 -fdump-tree-omplower" } */ -/* { dg-additional-options "-foffload=-Wa,--verify" { target offload_target_nvptx } } */ -/* { dg-xfail-if "PR 97106/PR 97102 - .alias not (yet) supported for nvptx" { offload_target_nvptx } } */ #include <cstdlib> #include <type_traits> diff --git a/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C b/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C index a73e7f8..24e3d07 100644 --- a/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C +++ b/libgomp/testsuite/libgomp.c++/target-exceptions-pr118794-1.C @@ -9,10 +9,6 @@ /* See also '../../../gcc/testsuite/g++.target/gcn/exceptions-pr118794-1.C', '../../../gcc/testsuite/g++.target/nvptx/exceptions-pr118794-1.C'. */ -/* Help nvptx offloading overcome a code generation issue; - PR106445, PR118518. */ -#define ALWAYS_INLINE __attribute__((always_inline)) - #pragma omp begin declare target bool ok = false; @@ -20,12 +16,10 @@ bool ok = false; template <typename T> struct C { - ALWAYS_INLINE C() { ok = true; } - ALWAYS_INLINE C(int) {}; ~C() {}; diff --git a/libgomp/testsuite/libgomp.c-c++-common/pr96390.c b/libgomp/testsuite/libgomp.c-c++-common/pr96390.c index b89f934..ca7865d 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/pr96390.c +++ b/libgomp/testsuite/libgomp.c-c++-common/pr96390.c @@ -1,7 +1,7 @@ /* { dg-additional-options "-O0 -fdump-tree-omplower" } */ /* { dg-additional-options "-foffload=-Wa,--verify" { target offload_target_nvptx } } */ /* { dg-require-alias "" } */ -/* { dg-xfail-if "PR 97102/PR 97106 - .alias not (yet) supported for nvptx" { offload_target_nvptx } } */ +/* { dg-xfail-if PR105018 { offload_target_nvptx } } */ #ifdef __cplusplus extern "C" { diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2f128f2..107b275 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,139 @@ +2025-04-18 François Dumont <frs.dumont@gmail.com> + + * testsuite/util/debug/unordered_checks.h (fill_container): New helper method. + (use_erased_local_iterator, invalid_local_iterator_pre_increment) + (invalid_local_iterator_post_increment, invalid_local_iterator_compare) + (invalid_local_iterator_range): Use latter. + (fill_and_get_local_iterator): New, use fill_container. + (use_invalid_local_iterator): Use latter. + (invalid_local_iterator_arrow_operator): New test function. + (invalid_local_iterator_copy_instantiation): New test function. + (invalid_local_iterator_move_instantiation): New test function. + (invalid_local_iterator_copy_assignment): New test function. + (invalid_local_iterator_move_assignment): New test function. + (invalid_local_iterator_const_conversion): New test function. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc: Test unordered_map. + * testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc: Test unordered_multimap. + * testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc: Likewise. + * testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc: Likewise. + * testsuite/23_containers/unordered_multimap/debug/cend_neg.cc: Likewise. + * testsuite/23_containers/unordered_multimap/debug/end1_neg.cc: Likewise. + * testsuite/23_containers/unordered_multimap/debug/end2_neg.cc: Likewise. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc: + Test unordered_multimap. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc: + New test case. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc: + New test case. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc: + New test case. + * testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc: + New test case. + +2025-04-18 Tomasz Kamiński <tkaminsk@redhat.com> + + * doc/xml/manual/appendix_contributing.xml: Add 'and functions'. + +2025-04-17 Jason Merrill <jason@redhat.com> + + * testsuite/20_util/tuple/element_access/get_neg.cc: Adjust + diagnostic. + +2025-04-17 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/119840 + * include/std/format (_M_parse_fill_and_align): Cast elements of + __not_fill to _CharT. + +2025-04-17 Jonathan Wakely <jwakely@redhat.com> + + * include/std/format (format_kind): Do not use 'not' + alternative token to make the primary template ill-formed. Use + the undeclared identifier __primary_template_not_defined and a + comment that will appear in diagnostics. + * testsuite/std/format/ranges/format_kind_neg.cc: New test. + +2025-04-17 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/109162 + * include/std/format (__format::__simply_formattable_range): Define. + (range_formatter::format): Do not instantiate _M_format for mutable + _Rg if const _Rg can be used. + +2025-04-16 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/109162 + * include/std/format (range_formatter::format): Format const range, + only if reference type is not changed. + * testsuite/std/format/ranges/formatter.cc: New tests. + +2025-04-16 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/109162 + * include/std/format (__formatter_int::_M_format_character_escaped) + (__formatter_str::format): Use __sink.out() to produce _Sink_iter. + (__format::__const_formattable_range): Moved closer to range_formatter. + (__format::__maybe_const_range): Use `__conditional_t` and moved closer + to range_formatter. + (__format::__format_padded, __format::maybe_const) + (__format::__indexed_formatter_storage, __format::__tuple_formatter) + (std::formatter<pair<_Fp, _Sp>, _CharT>>) + (std::formatter<tuple<_Tps...>, _CharT): Define. + (std::formatter<_Rg, _CharT>::format): Cast incoming range to + __format::__maybe_const_range<_Rg, _CharT>&. + (std::formatter<_Rg, _CharT>::_M_format): Extracted from format, + and use __format_padded. + (std::formatter<_Rg, _CharT>::_M_format_no_padding): Rename... + (std::formatter<_Rg, _CharT>::_M_format_elems): ...to this. + (std::formatter<_Rg, _CharT>::_M_format_with_padding): Extracted as + __format_padded. + * testsuite/util/testsuite_iterators.h (test_input_range_nocopy): + Define. + * testsuite/std/format/ranges/formatter.cc: Tests for `m` specifier. + * testsuite/std/format/ranges/sequence.cc: Tests for array and subrange. + * testsuite/std/format/ranges/map.cc: New test. + * testsuite/std/format/tuple.cc: New test. + 2025-04-15 Jonathan Wakely <jwakely@redhat.com> * include/std/ranges (__glibcxx_want_ranges_iota): Do not diff --git a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml index ac607fc..b924545 100644 --- a/libstdc++-v3/doc/xml/manual/appendix_contributing.xml +++ b/libstdc++-v3/doc/xml/manual/appendix_contributing.xml @@ -895,7 +895,7 @@ indicate a place that may require attention for multi-thread safety. Examples: <code>_M_num_elements _M_initialize ()</code> - Static data members, constants, and enumerations: <literal>_S_.*</literal> + Static data and function members, constants, and enumerations: <literal>_S_.*</literal> Examples: <code>_S_max_elements _S_default_value</code> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 096dda4..e557e10 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -555,8 +555,8 @@ namespace __format constexpr iterator _M_parse_fill_and_align(iterator __first, iterator __last, string_view __not_fill) noexcept { - for (char c : __not_fill) - if (*__first == c) + for (char __c : __not_fill) + if (*__first == static_cast<_CharT>(__c)) return __first; using namespace __unicode; @@ -1350,8 +1350,7 @@ namespace __format __fc, _M_spec); __format::_Str_sink<_CharT> __sink; - __format::_Sink_iter<_CharT> __out(__sink); - __format::__write_escaped(__out, __s, __term); + __format::__write_escaped(__sink.out(), __s, __term); basic_string_view<_CharT> __escaped(__sink.view().data(), __sink.view().size()); const size_t __escaped_width = _S_trunc(__escaped, __prec); @@ -1387,13 +1386,13 @@ namespace __format { ranges::iterator_t<_Rg> __first = ranges::begin(__rg); ranges::subrange __sub(__first, __first + __n); - return format(_String(from_range, __sub), __fc); + return format(_String(from_range, __sub), __fc); } else { // N.B. preserve the computed size ranges::subrange __sub(__rg, __n); - return format(_String(from_range, __sub), __fc); + return format(_String(from_range, __sub), __fc); } } else @@ -1698,7 +1697,7 @@ namespace __format template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator _M_format_character_escaped(_CharT __c, - basic_format_context<_Out, _CharT>& __fc) const + basic_format_context<_Out, _CharT>& __fc) const { using _Esc = _Escapes<_CharT>; constexpr auto __term = __format::_Term_char::_Tc_apos; @@ -1708,8 +1707,7 @@ namespace __format _CharT __buf[12]; __format::_Fixedbuf_sink<_CharT> __sink(__buf); - __format::_Sink_iter<_CharT> __out(__sink); - __format::__write_escaped(__out, __in, __term); + __format::__write_escaped(__sink.out(), __in, __term); const basic_string_view<_CharT> __escaped = __sink.view(); size_t __estimated_width; @@ -3077,19 +3075,6 @@ namespace __format concept formattable = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>; - /// @cond undocumented -namespace __format -{ - template<typename _Rg, typename _CharT> - concept __const_formattable_range - = ranges::input_range<const _Rg> - && formattable<ranges::range_reference_t<const _Rg>, _CharT>; - - template<typename _Rg, typename _CharT> - using __maybe_const_range - = conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>; -} // namespace __format - /// @endcond #endif // format_ranges /// An iterator after the last character written, and the number of @@ -5175,7 +5160,10 @@ namespace __format /// @cond undocumented template<typename _Rg> - constexpr auto format_kind = not defined(format_kind<_Rg>); + constexpr auto format_kind = + __primary_template_not_defined( + format_kind<_Rg> // you can specialize this for non-const input ranges + ); template<typename _Tp> consteval range_format @@ -5209,6 +5197,254 @@ namespace __format /// @cond undocumented namespace __format { + template<typename _CharT, typename _Out, typename _Callback> + typename basic_format_context<_Out, _CharT>::iterator + __format_padded(basic_format_context<_Out, _CharT>& __fc, + const _Spec<_CharT>& __spec, + _Callback&& __call) + { + // This is required to implement formatting with padding, + // as we need to format to temporary buffer, using the same iterator. + static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>); + + if (__spec._M_get_width(__fc) == 0) + return __call(__fc); + + struct _Restore_out + { + _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>& __fc) + : _M_ctx(std::addressof(__fc)), _M_out(__fc.out()) + { } + + void _M_trigger() + { + if (_M_ctx) + _M_ctx->advance_to(_M_out); + _M_ctx = nullptr; + } + + ~_Restore_out() + { _M_trigger(); } + + private: + basic_format_context<_Sink_iter<_CharT>, _CharT>* _M_ctx; + _Sink_iter<_CharT> _M_out; + }; + + _Restore_out __restore(__fc); + // TODO Consider double sinking, first buffer of width + // size and then original sink, if first buffer is overun + // we do not need to align + _Str_sink<_CharT> __buf; + __fc.advance_to(__buf.out()); + __call(__fc); + __restore._M_trigger(); + + basic_string_view<_CharT> __str(__buf.view()); + size_t __width; + if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) + __width = __unicode::__field_width(__str); + else + __width = __str.size(); + + return __format::__write_padded_as_spec(__str, __width, __fc, __spec); + } + + template<typename _Rg, typename _CharT> + concept __const_formattable_range + = ranges::input_range<const _Rg> + && formattable<ranges::range_reference_t<const _Rg>, _CharT>; + + // _Rg& and const _Rg& are both formattable and use same formatter + // specialization for their references. + template<typename _Rg, typename _CharT> + concept __simply_formattable_range + = __const_formattable_range<_Rg, _CharT> + && same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, + remove_cvref_t<ranges::range_reference_t<const _Rg>>>; + + template<typename _Rg, typename _CharT> + using __maybe_const_range + = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>; + + template<typename _Tp, typename _CharT> + using __maybe_const + = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>; + + template<size_t _Pos, typename _Tp, typename _CharT> + struct __indexed_formatter_storage + { + constexpr void + _M_parse() + { + basic_format_parse_context<_CharT> __pc({}); + if (_M_formatter.parse(__pc) != __pc.end()) + __format::__failed_to_parse_format_spec(); + } + + template<typename _Out> + void + _M_format(__maybe_const<_Tp, _CharT>& __elem, + basic_format_context<_Out, _CharT>& __fc, + basic_string_view<_CharT> __sep) const + { + if constexpr (_Pos != 0) + __fc.advance_to(__format::__write(__fc.out(), __sep)); + __fc.advance_to(_M_formatter.format(__elem, __fc)); + } + + [[__gnu__::__always_inline__]] + constexpr void + set_debug_format() + { + if constexpr (__has_debug_format<formatter<_Tp, _CharT>>) + _M_formatter.set_debug_format(); + } + + private: + formatter<_Tp, _CharT> _M_formatter; + }; + + template<typename _CharT, typename... _Tps> + class __tuple_formatter + { + using _String_view = basic_string_view<_CharT>; + using _Seps = __format::_Separators<_CharT>; + + public: + constexpr void + set_separator(basic_string_view<_CharT> __sep) noexcept + { _M_sep = __sep; } + + constexpr void + set_brackets(basic_string_view<_CharT> __open, + basic_string_view<_CharT> __close) noexcept + { + _M_open = __open; + _M_close = __close; + } + + // We deviate from standard, that declares this as template accepting + // unconstrained ParseContext type, which seems unimplementable. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { + auto __first = __pc.begin(); + const auto __last = __pc.end(); + __format::_Spec<_CharT> __spec{}; + + auto __finished = [&] + { + if (__first != __last && *__first != '}') + return false; + + _M_spec = __spec; + _M_felems._M_parse(); + _M_felems.set_debug_format(); + return true; + }; + + if (__finished()) + return __first; + + __first = __spec._M_parse_fill_and_align(__first, __last, "{:"); + if (__finished()) + return __first; + + __first = __spec._M_parse_width(__first, __last, __pc); + if (__finished()) + return __first; + + if (*__first == 'n') + { + ++__first; + _M_open = _M_close = _String_view(); + } + else if (*__first == 'm') + { + ++__first; + if constexpr (sizeof...(_Tps) == 2) + { + _M_sep = _Seps::_S_colon(); + _M_open = _M_close = _String_view(); + } + else + __throw_format_error("format error: 'm' specifier requires range" + " of pair or tuple of two elements"); + } + + if (__finished()) + return __first; + + __format::__failed_to_parse_format_spec(); + } + + protected: + template<typename _Tuple, typename _Out, size_t... _Ids> + typename basic_format_context<_Out, _CharT>::iterator + _M_format(_Tuple& __tuple, index_sequence<_Ids...>, + basic_format_context<_Out, _CharT>& __fc) const + { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); } + + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems, + basic_format_context<_Out, _CharT>& __fc) const + { + return __format::__format_padded( + __fc, _M_spec, + [this, &__elems...](basic_format_context<_Out, _CharT>& __nfc) + { + __nfc.advance_to(__format::__write(__nfc.out(), _M_open)); + _M_felems._M_format(__elems..., __nfc, _M_sep); + return __format::__write(__nfc.out(), _M_close); + }); + } + + private: + template<size_t... _Ids> + struct __formatters_storage + : __indexed_formatter_storage<_Ids, _Tps, _CharT>... + { + template<size_t _Id, typename _Up> + using _Base = __indexed_formatter_storage<_Id, _Up, _CharT>; + + constexpr void + _M_parse() + { + (_Base<_Ids, _Tps>::_M_parse(), ...); + } + + template<typename _Out> + void + _M_format(__maybe_const<_Tps, _CharT>&... __elems, + basic_format_context<_Out, _CharT>& __fc, + _String_view __sep) const + { + (_Base<_Ids, _Tps>::_M_format(__elems, __fc, __sep), ...); + } + + constexpr void + set_debug_format() + { + (_Base<_Ids, _Tps>::set_debug_format(), ...); + } + }; + + template<size_t... _Ids> + static auto + _S_create_storage(index_sequence<_Ids...>) + -> __formatters_storage<_Ids...>; + using _Formatters + = decltype(_S_create_storage(index_sequence_for<_Tps...>())); + + _Spec<_CharT> _M_spec{}; + _String_view _M_open = _Seps::_S_parens().substr(0, 1); + _String_view _M_close = _Seps::_S_parens().substr(1, 1); + _String_view _M_sep = _Seps::_S_comma(); + _Formatters _M_felems; + }; + template<typename _Tp> concept __is_map_formattable = __is_pair<_Tp> || (__is_tuple_v<_Tp> && tuple_size_v<_Tp> == 2); @@ -5216,6 +5452,46 @@ namespace __format } // namespace __format /// @endcond + // [format.tuple] Tuple formatter + template<__format::__char _CharT, formattable<_CharT> _Fp, + formattable<_CharT> _Sp> + struct formatter<pair<_Fp, _Sp>, _CharT> + : __format::__tuple_formatter<_CharT, remove_cvref_t<_Fp>, + remove_cvref_t<_Sp>> + { + private: + using __maybe_const_pair + = __conditional_t<formattable<const _Fp, _CharT> + && formattable<const _Sp, _CharT>, + const pair<_Fp, _Sp>, pair<_Fp, _Sp>>; + public: + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_pair& __p, + basic_format_context<_Out, _CharT>& __fc) const + { return this->_M_format_elems(__p.first, __p.second, __fc); } + }; + + template<__format::__char _CharT, formattable<_CharT>... _Tps> + struct formatter<tuple<_Tps...>, _CharT> + : __format::__tuple_formatter<_CharT, remove_cvref_t<_Tps>...> + { + private: + using __maybe_const_tuple + = __conditional_t<(formattable<const _Tps, _CharT> && ...), + const tuple<_Tps...>, tuple<_Tps...>>; + public: + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_tuple& __t, + basic_format_context<_Out, _CharT>& __fc) const + { return this->_M_format(__t, index_sequence_for<_Tps...>(), __fc); } + }; + // [format.range.formatter], class template range_formatter template<typename _Tp, __format::__char _CharT = char> requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> @@ -5369,9 +5645,18 @@ namespace __format typename basic_format_context<_Out, _CharT>::iterator format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const { - // This is required to implement formatting with padding, - // as we need to format to temporary buffer, using the same iterator. - static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>); + using _Range = remove_reference_t<_Rg>; + if constexpr (__format::__simply_formattable_range<_Range, _CharT>) + return _M_format<const _Range>(__rg, __fc); + else + return _M_format(__rg, __fc); + } + + private: + template<ranges::input_range _Rg, typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc) const + { if constexpr (same_as<_Tp, _CharT>) if (_M_spec._M_type == __format::_Pres_str || _M_spec._M_type == __format::_Pres_esc) @@ -5379,16 +5664,17 @@ namespace __format __format::__formatter_str __fstr(_M_spec); return __fstr._M_format_range(__rg, __fc); } - if (_M_spec._M_get_width(__fc) > 0) - return _M_format_with_padding(__rg, __fc); - return _M_format_no_padding(__rg, __fc); + return __format::__format_padded( + __fc, _M_spec, + [this, &__rg](basic_format_context<_Out, _CharT>& __nfc) + { return _M_format_elems(__rg, __nfc); }); } - private: + template<ranges::input_range _Rg, typename _Out> typename basic_format_context<_Out, _CharT>::iterator - _M_format_no_padding(_Rg& __rg, - basic_format_context<_Out, _CharT>& __fc) const + _M_format_elems(_Rg& __rg, + basic_format_context<_Out, _CharT>& __fc) const { auto __out = __format::__write(__fc.out(), _M_open); @@ -5409,50 +5695,6 @@ namespace __format return __format::__write(__out, _M_close); } - template<ranges::input_range _Rg, typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - _M_format_with_padding(_Rg& __rg, - basic_format_context<_Out, _CharT>& __fc) const - { - struct _Restore_out - { - _Restore_out(basic_format_context<_Out, _CharT>& __fc) - : _M_ctx(addressof(__fc)), _M_out(__fc.out()) - { } - - void trigger() - { - if (_M_ctx) - _M_ctx->advance_to(_M_out); - _M_ctx = nullptr; - } - - ~_Restore_out() - { trigger(); } - - private: - basic_format_context<_Out, _CharT>* _M_ctx; - __format::_Sink_iter<_CharT> _M_out; - }; - - _Restore_out __restore{__fc}; - // TODO Consider double sinking, first buffer of width - // size and then original sink, if first buffer is overrun - // we do not need to align - __format::_Str_sink<_CharT> __buf; - __fc.advance_to(__format::_Sink_iter<_CharT>(__buf)); - _M_format_no_padding(__rg, __fc); - __restore.trigger(); - - _String_view __s(__buf.view()); - size_t __width; - if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) - __width = __unicode::__field_width(__s); - else - __width = __s.size(); - return __format::__write_padded_as_spec(__s, __width, __fc, _M_spec); - } - __format::_Spec<_CharT> _M_spec{}; _String_view _M_open = _Seps::_S_squares().substr(0, 1); _String_view _M_close = _Seps::_S_squares().substr(1, 1); @@ -5537,7 +5779,7 @@ namespace __format return _M_under._M_format_range(__rg, __fc); else return _M_under.format(__rg, __fc); - } + } private: using _Formatter_under diff --git a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc index 48628a9..18d47d2 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/element_access/get_neg.cc @@ -61,4 +61,4 @@ test03() // { dg-error "tuple index must be in range" "" { target *-*-* } 0 } // { dg-prune-output "no type named 'type' in .*_Nth_type" } -// { dg-prune-output "pack index is out of range" } +// { dg-prune-output "pack index '.' is out of range" } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc new file mode 100644 index 0000000..09870a7 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_arrow_operator_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_arrow_operator + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc new file mode 100644 index 0000000..7bfe3a8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_const_conversion_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_const_conversion + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc new file mode 100644 index 0000000..d3b671b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_assignment + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc new file mode 100644 index 0000000..d609671 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_copy_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_construction + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc new file mode 100644 index 0000000..8d2ed6b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_assignment + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc new file mode 100644 index 0000000..dd9b7dc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/invalid_local_iterator_move_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_construction + <std::unordered_map<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc index 7fbc453..2596798 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/max_load_factor_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_multimap<int, int> um; + std::unordered_map<int, int> um; um.max_load_factor(-1.0f); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc index ff787cf..b2d67fb 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/begin2_neg.cc @@ -22,8 +22,8 @@ void test01() { - std::unordered_map<int, int> um; - const std::unordered_map<int, int>& cum = um; + std::unordered_multimap<int, int> um; + const std::unordered_multimap<int, int>& cum = um; cum.begin(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc index b5ddb18..4d5cb84 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/bucket_size_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_map<int, int> um; + std::unordered_multimap<int, int> um; um.bucket_size(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc index 5ba1da5..654d409 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cbegin_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_map<int, int> um; + std::unordered_multimap<int, int> um; um.cbegin(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc index 031be37..f7149d4 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/cend_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_map<int, int> um; + std::unordered_multimap<int, int> um; um.cend(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc index d412fcf..fd0f981 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end1_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_map<int, int> um; + std::unordered_multimap<int, int> um; um.end(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc index 0115351..0c3f86c 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/end2_neg.cc @@ -22,8 +22,8 @@ void test01() { - std::unordered_map<int, int> um; - const std::unordered_map<int, int>& cum = um; + std::unordered_multimap<int, int> um; + const std::unordered_multimap<int, int>& cum = um; cum.end(um.bucket_count()); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc new file mode 100644 index 0000000..8b23020 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_arrow_operator_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_arrow_operator + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc new file mode 100644 index 0000000..62c0280 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_const_conversion_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_const_conversion + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc new file mode 100644 index 0000000..9ac5b35 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_assignment + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc new file mode 100644 index 0000000..4140272 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_copy_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_construction + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc new file mode 100644 index 0000000..32c847c --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_assignment + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc new file mode 100644 index 0000000..124b9ec --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/invalid_local_iterator_move_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_map> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_construction + <std::unordered_multimap<int, int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc index 2596798..7fbc453 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/max_load_factor_neg.cc @@ -22,7 +22,7 @@ void test01() { - std::unordered_map<int, int> um; + std::unordered_multimap<int, int> um; um.max_load_factor(-1.0f); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc new file mode 100644 index 0000000..1677b20 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_arrow_operator_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_arrow_operator + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc new file mode 100644 index 0000000..0d64a41 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_const_conversion_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_const_conversion + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc new file mode 100644 index 0000000..b0d7b9f --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_assignment + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc new file mode 100644 index 0000000..fa9c5ee --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_copy_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_construction + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc new file mode 100644 index 0000000..b25fedc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_assignment + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc new file mode 100644 index 0000000..8b855b2 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/invalid_local_iterator_move_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_construction + <std::unordered_multiset<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc new file mode 100644 index 0000000..f62ed6b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_arrow_operator_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_arrow_operator + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc new file mode 100644 index 0000000..839f9ae --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_const_conversion_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_const_conversion + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc new file mode 100644 index 0000000..377019f --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_assignment + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc new file mode 100644 index 0000000..1f7e6dd --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_copy_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_copy_construction + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc new file mode 100644 index 0000000..d16a154 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_assignment_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_assignment + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc new file mode 100644 index 0000000..d878abf --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/invalid_local_iterator_move_construction_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { target c++11 xfail *-*-* } } +// { dg-require-debug-mode "" } + +#include <unordered_set> +#include <debug/unordered_checks.h> + +void test01() +{ + __gnu_test::invalid_local_iterator_move_construction + <std::unordered_set<int>>(); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc new file mode 100644 index 0000000..bf8619d --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind_neg.cc @@ -0,0 +1,13 @@ +// { dg-do compile { target c++23 } } + +// C++23 22.14.7.1 [format.range.fmtkind] p1: A program that instantiates +// the primary template of format_kind is ill-formed. + +#include <format> + +template<auto> struct Tester { }; + +Tester<std::format_kind<const int(&)[1]>> t; // { dg-error "here" } + +// { dg-error "use of 'std::format_kind" "" { target *-*-* } 0 } +// { dg-error "primary_template_not_defined" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc index 2045b51..00ce9f6 100644 --- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc +++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc @@ -1,5 +1,6 @@ // { dg-do run { target c++23 } } +#include <flat_map> #include <format> #include <testsuite_hooks.h> #include <vector> @@ -97,6 +98,7 @@ void test_override() { MyVector<_CharT, Formatter> vc{'a', 'b', 'c', 'd'}; + MyVector<std::pair<int, int>, Formatter> vp{{1, 11}, {2, 21}}; std::basic_string<_CharT> res; res = std::format(WIDEN("{:s}"), vc); @@ -106,7 +108,10 @@ test_override() res = std::format(WIDEN("{:+^6s}"), vc); VERIFY( res == WIDEN("+abcd+") ); - // TODO test map + res = std::format(WIDEN("{:m}"), vp); + VERIFY( res == WIDEN("{1: 11, 2: 21}") ); + res = std::format(WIDEN("{:=^20m}"), vp); + VERIFY( res == WIDEN("==={1: 11, 2: 21}===") ); } template<template<typename, typename> class Formatter> @@ -134,6 +139,26 @@ test_nested() VERIFY( res == "+<01; 02; 11; 12>+" ); } +struct MyFlatMap : std::flat_map<int, int> +{ + using std::flat_map<int, int>::flat_map; +}; + +template<typename CharT> +struct std::formatter<MyFlatMap, CharT> + // This cannot apply format BitVector const&, because formatted type would + // be std::pair<int const&, int const&>, and formatter for + // pair<int const&, int> cannot format it. + : std::range_formatter<MyFlatMap::reference> +{}; + +void test_const_ref_type_mismatch() +{ + MyFlatMap m{{1, 11}, {2, 22}}; + std::string res = std::format("{:m}", m); + VERIFY( res == "{1: 11, 2: 22}" ); +} + template<typename T, typename CharT> using VectorFormatter = std::formatter<std::vector<T>, CharT>; @@ -142,4 +167,5 @@ int main() test_outputs<std::range_formatter>(); test_outputs<VectorFormatter>(); test_nested(); + test_const_ref_type_mismatch(); } diff --git a/libstdc++-v3/testsuite/std/format/ranges/map.cc b/libstdc++-v3/testsuite/std/format/ranges/map.cc new file mode 100644 index 0000000..34c5ed5 --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/ranges/map.cc @@ -0,0 +1,209 @@ +// { dg-do run { target c++23 } } + +#include <flat_map> +#include <format> +#include <list> +#include <map> +#include <span> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <vector> + +struct NotFormattable +{ + friend auto operator<=>(NotFormattable, NotFormattable) = default; +}; + +static_assert( !std::formattable<std::map<int, NotFormattable>, char> ); +static_assert( !std::formattable<std::map<NotFormattable, int>, wchar_t> ); + +template<typename... Args> +bool +is_format_string_for(const char* str, Args&&... args) +{ + try { + (void) std::vformat(str, std::make_format_args(args...)); + return true; + } catch (const std::format_error&) { + return false; + } +} + +template<typename... Args> +bool +is_format_string_for(const wchar_t* str, Args&&... args) +{ + try { + (void) std::vformat(str, std::make_wformat_args(args...)); + return true; + } catch (const std::format_error&) { + return false; + } +} + +template<typename Rg, typename CharT> +bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg) +{ + using V = std::remove_cvref_t<std::ranges::range_reference_t<Rg>>; + std::range_formatter<V, CharT> fmt; + std::basic_format_parse_context<CharT> pc(spec); + try { + (void)fmt.parse(pc); + return true; + } catch (const std::format_error&) { + return false; + } +} + +#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S) +#define WIDEN(S) WIDEN_(_CharT, S) + +void +test_format_string() +{ + // only pair<T, U> amd tuple<T, U> value types are supported + VERIFY( !is_range_formatter_spec_for("m", std::vector<int>()) ); + VERIFY( !is_format_string_for("{:m}", std::vector<int>()) ); + VERIFY( !is_range_formatter_spec_for("m", std::vector<std::tuple<int, int, int>>()) ); + VERIFY( !is_format_string_for("{:m}", std::vector<std::tuple<int, int, int>>()) ); + + // invalid format stringss + VERIFY( !is_range_formatter_spec_for("?m", std::vector<std::pair<int, int>>()) ); + VERIFY( !is_format_string_for("{:?m}", std::vector<std::pair<int, int>>()) ); + VERIFY( !is_range_formatter_spec_for("m:", std::vector<std::pair<int, int>>()) ); + VERIFY( !is_format_string_for("{:m:}", std::vector<std::pair<int, int>>()) ); + + // precision is not supported + VERIFY( !is_range_formatter_spec_for(".10m", std::vector<std::pair<int, int>>()) ); + VERIFY( !is_format_string_for("{:.10m}", std::vector<std::pair<int, int>>()) ); + VERIFY( !is_format_string_for("{:.{}m}", std::vector<std::pair<int, int>>(), 10) ); + + // width needs to be integer type + VERIFY( !is_format_string_for("{:{}m}", std::vector<std::pair<int, int>>(), 1.0f) ); +} + +template<typename _CharT, typename Range> +void test_output(bool mapIsDefault) +{ + using Sv = std::basic_string_view<_CharT>; + using Pt = std::ranges::range_value_t<Range>; + using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pt>>; + using St = std::remove_cvref_t<std::tuple_element_t<1, Pt>>; + auto makeRange = [](std::span<Pt> s) { + return Range(s.data(), s.data() + s.size()); + }; + + std::basic_string<_CharT> res; + size_t size = 0; + + Ft f1[]{1, 2, 3}; + St s1[]{11, 22, 33}; + Pt v1[]{{f1[0], s1[0]}, {f1[1], s1[1]}, {f1[2], s1[2]}}; + + res = std::format(WIDEN("{}"), makeRange(v1)); + if (mapIsDefault) + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") ); + else + VERIFY( res == WIDEN("[(1, 11), (2, 22), (3, 33)]") ); + + res = std::format(WIDEN("{:m}"), makeRange(v1)); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") ); + res = std::format(WIDEN("{:nm}"), makeRange(v1)); + VERIFY( res == WIDEN("1: 11, 2: 22, 3: 33") ); + + res = std::format(WIDEN("{:3m}"), makeRange(v1)); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}") ); + + res = std::format(WIDEN("{:25m}"), makeRange(v1)); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") ); + + res = std::format(WIDEN("{:{}m}"), makeRange(v1), 25); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") ); + + res = std::format(WIDEN("{1:{0}m}"), 25, makeRange(v1)); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33} ") ); + + res = std::format(WIDEN("{:25nm}"), makeRange(v1)); + VERIFY( res == WIDEN("1: 11, 2: 22, 3: 33 ") ); + + res = std::format(WIDEN("{:*<23m}"), makeRange(v1)); + VERIFY( res == WIDEN("{1: 11, 2: 22, 3: 33}**") ); + + res = std::format(WIDEN("{:->24m}"), makeRange(v1)); + VERIFY( res == WIDEN("---{1: 11, 2: 22, 3: 33}") ); + + res = std::format(WIDEN("{:=^25m}"), makeRange(v1)); + VERIFY( res == WIDEN("=={1: 11, 2: 22, 3: 33}==") ); + + res = std::format(WIDEN("{:=^25nm}"), makeRange(v1)); + VERIFY( res == WIDEN("===1: 11, 2: 22, 3: 33===") ); + + size = std::formatted_size(WIDEN("{:m}"), makeRange(v1)); + VERIFY( size == Sv(WIDEN("{1: 11, 2: 22, 3: 33}")).size() ); + + size = std::formatted_size(WIDEN("{:3m}"), makeRange(v1)); + VERIFY( size == Sv(WIDEN("{1: 11, 2: 22, 3: 33}")).size() ); + + size = std::formatted_size(WIDEN("{:25m}"), makeRange(v1)); + VERIFY( size == 25 ); +} + +template<class Range> +void test_output_c(bool mapIsDefault = false) +{ + test_output<char, Range>(mapIsDefault); + test_output<wchar_t, Range>(mapIsDefault); +} + +template<template<typename> class RangeT> +void test_output_pc() +{ + test_output_c<RangeT<std::pair<int, int>>>(); + test_output_c<RangeT<std::pair<const int, int>>>(); + test_output_c<RangeT<std::tuple<const int&, int&>>>(); +} + +void +test_outputs() +{ + using namespace __gnu_test; + test_output_c<std::map<int, int>>(true); + test_output_c<std::flat_map<int, int>>(true); + + test_output_pc<std::vector>(); + test_output_pc<std::list>(); + test_output_pc<std::span>(); + + test_output_pc<test_forward_range>(); + test_output_pc<test_input_range>(); + test_output_pc<test_input_range_nocopy>(); +} + +void +test_nested() +{ + std::vector<std::map<int, std::string>> vm{ + {{1, "one"}, {2, "two"}}, + {{1, "jeden"}, {2, "dwa"}}, + }; + std::string res; + + res = std::format("{}", vm); + VERIFY( res == R"([{1: "one", 2: "two"}, {1: "jeden", 2: "dwa"}])" ); + res = std::format("{:n:n}", vm); + VERIFY( res == R"(1: "one", 2: "two", 1: "jeden", 2: "dwa")" ); + + std::map<std::string, std::vector<std::string>> mv{ + {"english", {"zero", "one", "two"}}, + {"polish", {"zero", "jeden", "dwa"}}, + }; + res = std::format("{}", mv); + VERIFY( res == R"({"english": ["zero", "one", "two"], "polish": ["zero", "jeden", "dwa"]})" ); +} + +int main() +{ + test_format_string(); + test_outputs(); + test_nested(); +} diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc index 0657437..61fc68e 100644 --- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc +++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc @@ -1,7 +1,9 @@ // { dg-do run { target c++23 } } +#include <array> #include <format> #include <list> +#include <ranges> #include <span> #include <testsuite_hooks.h> #include <testsuite_iterators.h> @@ -73,19 +75,23 @@ test_format_string() #define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S) #define WIDEN(S) WIDEN_(_CharT, S) -template<typename _CharT, typename Range> +template<typename _CharT, typename Range, typename Storage> void test_output() { using Sv = std::basic_string_view<_CharT>; using T = std::ranges::range_value_t<Range>; - auto makeRange = [](std::span<T> s) { - return Range(s.data(), s.data() + s.size()); + auto makeRange = [](Storage& s) -> Range { + if constexpr (std::is_same_v<std::remove_cvref_t<Range>, Storage>) + return s; + else + return Range(std::ranges::data(s), + std::ranges::data(s) + std::ranges::size(s)); }; std::basic_string<_CharT> res; size_t size = 0; - T v1[]{1, 2, 3}; + Storage v1{1, 2, 3}; res = std::format(WIDEN("{}"), makeRange(v1)); VERIFY( res == WIDEN("[1, 2, 3]") ); res = std::format(WIDEN("{:}"), makeRange(v1)); @@ -143,27 +149,37 @@ void test_output() VERIFY( size == 25 ); } -template<typename Range> -void test_output_c() +template<typename Cont> +void test_output_cont() { - test_output<char, Range>(); - test_output<wchar_t, Range>(); + test_output<char, Cont&, Cont>(); + test_output<wchar_t, Cont const&, Cont>(); +} + +template<typename View> +void test_output_view() +{ + test_output<char, View, int[3]>(); + test_output<wchar_t, View, int[3]>(); } void test_outputs() { using namespace __gnu_test; - test_output_c<std::vector<int>>(); - test_output_c<std::list<int>>(); - test_output_c<std::span<int>>(); - - test_output_c<test_forward_range<int>>(); - test_output_c<test_input_range<int>>(); - test_output_c<test_range_nocopy<int, input_iterator_wrapper_nocopy>>(); - - test_output_c<std::span<const int>>(); - test_output_c<test_forward_range<const int>>(); + test_output_cont<std::vector<int>>(); + test_output_cont<std::list<int>>(); + test_output_cont<std::array<int, 3>>(); + + test_output_view<std::span<int>>(); + test_output_view<std::ranges::subrange<int*>>(); + test_output_view<test_forward_range<int>>(); + test_output_view<test_input_range<int>>(); + test_output_view<test_input_range_nocopy<int>>(); + + test_output_view<std::span<const int>>(); + test_output_view<std::ranges::subrange<const int*>>(); + test_output_view<test_forward_range<const int>>(); } void diff --git a/libstdc++-v3/testsuite/std/format/tuple.cc b/libstdc++-v3/testsuite/std/format/tuple.cc new file mode 100644 index 0000000..62f9d29 --- /dev/null +++ b/libstdc++-v3/testsuite/std/format/tuple.cc @@ -0,0 +1,259 @@ +// { dg-do run { target c++23 } } + +#include <format> +#include <string> +#include <testsuite_hooks.h> +#include <tuple> +#include <utility> + +struct NotFormattable +{}; + +static_assert( !std::formattable<std::pair<int, NotFormattable>, char> ); +static_assert( !std::formattable<std::tuple<int, NotFormattable, int>, wchar_t> ); + +template<typename... Args> +bool +is_format_string_for(const char* str, Args&&... args) +{ + try { + (void) std::vformat(str, std::make_format_args(args...)); + return true; + } catch (const std::format_error&) { + return false; + } +} + +template<typename... Args> +bool +is_format_string_for(const wchar_t* str, Args&&... args) +{ + try { + (void) std::vformat(str, std::make_wformat_args(args...)); + return true; + } catch (const std::format_error&) { + return false; + } +} + +#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S) +#define WIDEN(S) WIDEN_(_CharT, S) + +void +test_format_string() +{ + // invalid format stringss + VERIFY( !is_format_string_for("{:p}", std::tuple<>()) ); + VERIFY( !is_format_string_for("{:nm}", std::tuple<>()) ); + + // 'm' is only valid for 2 elemenst + VERIFY( !is_format_string_for("{:m}", std::tuple<>()) ); + VERIFY( !is_format_string_for("{:m}", std::tuple<int, int, int>()) ); + + // element specifier is not supported + VERIFY( !is_format_string_for("{::}", std::tuple<>()) ); + + // precision is not supported + VERIFY( !is_format_string_for("{:.10}", std::tuple<>()) ); + + // width needs to be integer type + VERIFY( !is_format_string_for("{:{}}", std::tuple<>(), 1.0f) ); +} + +template<typename _CharT> +void test_multi() +{ + using Sv = std::basic_string_view<_CharT>; + using Str = std::basic_string<_CharT>; + + std::basic_string<_CharT> res; + std::size_t size = 0; + std::tuple<int, Str, float> t1(1, WIDEN("test"), 2.1); + + res = std::format(WIDEN("{}"), t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1))") ); + res = std::format(WIDEN("{:}"), t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1))") ); + res = std::format(WIDEN("{:n}"), t1); + VERIFY( res == WIDEN(R"(1, "test", 2.1)") ); + + res = std::format(WIDEN("{:3}"), t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1))") ); + + res = std::format(WIDEN("{:20}"), t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1) )") ); + + res = std::format(WIDEN("{:{}}"), t1, 20); + VERIFY( res == WIDEN(R"((1, "test", 2.1) )") ); + + res = std::format(WIDEN("{1:{0}}"), 20, t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1) )") ); + + res = std::format(WIDEN("{:^>17}"), t1); + VERIFY( res == WIDEN(R"(^(1, "test", 2.1))") ); + + res = std::format(WIDEN("{:$<18}"), t1); + VERIFY( res == WIDEN(R"((1, "test", 2.1)$$)") ); + + res = std::format(WIDEN("{:+^19}"), t1); + VERIFY( res == WIDEN(R"(+(1, "test", 2.1)++)") ); + + res = std::format(WIDEN("{:|^19n}"), t1); + VERIFY( res == WIDEN(R"(||1, "test", 2.1|||)") ); + + size = std::formatted_size(WIDEN("{}"), t1); + VERIFY( size == Sv(WIDEN(R"((1, "test", 2.1))")).size() ); + + size = std::formatted_size(WIDEN("{:3}"), t1); + VERIFY( size == Sv(WIDEN(R"((1, "test", 2.1))")).size() ); + + size = std::formatted_size(WIDEN("{:20}"), t1); + VERIFY( size == 20 ); + + std::tuple<int&, Str&, float&> t2 = t1; + res = std::format(WIDEN("{}"), t2); + VERIFY( res == WIDEN(R"((1, "test", 2.1))") ); + + std::tuple<int, int, int, int> t3(1, 2, 3, 4); + res = std::format(WIDEN("{}"), t3); + VERIFY( res == WIDEN(R"((1, 2, 3, 4))") ); + +} + +template<typename _CharT, typename Tuple> +void test_empty() +{ + std::basic_string<_CharT> res; + + Tuple e1; + res = std::format(WIDEN("{}"), e1); + VERIFY( res == WIDEN(R"(())") ); + + res = std::format(WIDEN("{:}"), e1); + VERIFY( res == WIDEN(R"(())") ); + + res = std::format(WIDEN("{:n}"), e1); + VERIFY( res == WIDEN(R"()") ); + + res = std::format(WIDEN("{:^>6}"), e1); + VERIFY( res == WIDEN(R"(^^^^())") ); +} + +template<typename _CharT, typename Pair> +void test_pair() +{ + using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pair>>; + using St = std::remove_cvref_t<std::tuple_element_t<1, Pair>>; + + std::basic_string<_CharT> res; + + Ft f1 = 1; + St s1 = WIDEN("abc"); + Pair p1(f1, s1); + + res = std::format(WIDEN("{}"), p1); + VERIFY( res == WIDEN(R"((1, "abc"))") ); + + res = std::format(WIDEN("{:}"), p1); + VERIFY( res == WIDEN(R"((1, "abc"))") ); + + res = std::format(WIDEN("{:m}"), p1); + VERIFY( res == WIDEN(R"(1: "abc")") ); + + res = std::format(WIDEN("{:|^12m}"), p1); + VERIFY( res == WIDEN(R"(||1: "abc"||)") ); +} + +template<typename CharT, template<typename, typename> class PairT> +void test_pair_e() +{ + test_pair<CharT, PairT<int, std::basic_string<CharT>>>(); + test_pair<CharT, PairT<int, const CharT*>>(); + test_pair<CharT, PairT<const int, std::basic_string<CharT>>>(); + test_pair<CharT, PairT<int&, std::basic_string<CharT>&>>(); + test_pair<CharT, PairT<const int&, const std::basic_string<CharT>&>>(); +} + +template<typename Pair> +struct MyPair : Pair +{ + using Pair::Pair; +}; + +template<typename Pair, typename CharT> +struct std::formatter<MyPair<Pair>, CharT> +{ + constexpr formatter() noexcept + { + using _CharT = CharT; + _formatter.set_brackets(WIDEN("<"), WIDEN(">")); + _formatter.set_separator(WIDEN("; ")); + } + + constexpr std::basic_format_parse_context<CharT>::iterator + parse(std::basic_format_parse_context<CharT>& pc) + { return _formatter.parse(pc); } + + template<typename Out> + typename std::basic_format_context<Out, CharT>::iterator + format(const MyPair<Pair>& mp, + std::basic_format_context<Out, CharT>& fc) const + { return _formatter.format(mp, fc); } + +private: + std::formatter<Pair, CharT> _formatter; +}; + +template<typename _CharT, template<typename, typename> class PairT> +void test_custom() +{ + std::basic_string<_CharT> res; + MyPair<PairT<int, const _CharT*>> c1(1, WIDEN("abc")); + + res = std::format(WIDEN("{}"), c1); + VERIFY( res == WIDEN(R"(<1; "abc">)") ); + + res = std::format(WIDEN("{:}"), c1); + VERIFY( res == WIDEN(R"(<1; "abc">)") ); + + res = std::format(WIDEN("{:n}"), c1); + VERIFY( res == WIDEN(R"(1; "abc")") ); + + res = std::format(WIDEN("{:m}"), c1); + VERIFY( res == WIDEN(R"(1: "abc")") ); + + res = std::format(WIDEN("{:|^14}"), c1); + VERIFY( res == WIDEN(R"(||<1; "abc">||)") ); +} + +template<typename CharT> +void test_outputs() +{ + test_multi<CharT>(); + test_empty<CharT, std::tuple<>>(); + test_pair_e<CharT, std::pair>(); + test_pair_e<CharT, std::tuple>(); + test_custom<CharT, std::pair>(); + test_custom<CharT, std::tuple>(); +} + +void test_nested() +{ + std::string res; + std::tuple<std::tuple<>, std::pair<int, std::string>> tt{{}, {1, "abc"}}; + + res = std::format("{}", tt); + VERIFY( res == R"(((), (1, "abc")))" ); + res = std::format("{:n}", tt); + VERIFY( res == R"((), (1, "abc"))" ); + res = std::format("{:m}", tt); + VERIFY( res == R"((): (1, "abc"))" ); +} + +int main() +{ + test_format_string(); + test_outputs<char>(); + test_outputs<wchar_t>(); + test_nested(); +} diff --git a/libstdc++-v3/testsuite/util/debug/unordered_checks.h b/libstdc++-v3/testsuite/util/debug/unordered_checks.h index d01ee82..785aeb4 100644 --- a/libstdc++-v3/testsuite/util/debug/unordered_checks.h +++ b/libstdc++-v3/testsuite/util/debug/unordered_checks.h @@ -65,28 +65,36 @@ namespace __gnu_test template<typename _Tp> struct KeyExtractor { - static _Tp get_key(const _Tp& val) + static const _Tp& get_key(const _Tp& val) { return val; } }; template<typename _Tp1, typename _Tp2> - struct KeyExtractor<std::pair<const _Tp1, _Tp2>> + struct KeyExtractor<std::pair<_Tp1, _Tp2>> { - static _Tp1 get_key(const std::pair<const _Tp1, _Tp2>& val) + static const _Tp1& get_key(const std::pair<_Tp1, _Tp2>& val) { return val.first; } }; template<typename _Tp> - void use_erased_local_iterator() + void fill_container(_Tp& c) { typedef _Tp cont_type; typedef typename cont_type::value_type cont_val_type; typedef typename CopyableValueType<cont_val_type>::value_type val_type; generate_unique<val_type> gu; - cont_type c; for (size_t i = 0; i != 5; ++i) c.insert(gu.build()); + } + + template<typename _Tp> + void use_erased_local_iterator() + { + typedef _Tp cont_type; + typedef typename cont_type::value_type cont_val_type; + cont_type c; + fill_container(c); typename cont_type::local_iterator it, end; for (size_t i = 0; i != c.bucket_count(); ++i) @@ -96,22 +104,18 @@ namespace __gnu_test if (it != end) break; } - typename cont_type::key_type key = KeyExtractor<cont_val_type>::get_key(*it); + + const auto& key = KeyExtractor<cont_val_type>::get_key(*it); c.erase(key); VERIFY( it != end ); } template<typename _Tp> - void use_invalid_local_iterator() + typename _Tp::local_iterator + fill_and_get_local_iterator(_Tp& c) { typedef _Tp cont_type; - typedef typename cont_type::value_type cont_val_type; - typedef typename CopyableValueType<cont_val_type>::value_type val_type; - generate_unique<val_type> gu; - - cont_type c; - for (size_t i = 0; i != 5; ++i) - c.insert(gu.build()); + fill_container(c); typename cont_type::local_iterator it; for (size_t i = 0; i != c.bucket_count(); ++i) @@ -120,22 +124,107 @@ namespace __gnu_test if (it != c.end(i)) break; } - cont_val_type val = *it; + + return it; + } + + template<typename _Tp> + void use_invalid_local_iterator() + { + typedef _Tp cont_type; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; c.clear(); VERIFY( *it == val ); } template<typename _Tp> - void invalid_local_iterator_pre_increment() + void invalid_local_iterator_arrow_operator() { typedef _Tp cont_type; - typedef typename cont_type::value_type cont_val_type; - typedef typename CopyableValueType<cont_val_type>::value_type val_type; - generate_unique<val_type> gu; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + VERIFY( *it.operator->() == val ); + } + template<typename _Tp> + void invalid_local_iterator_copy_construction() + { + typedef _Tp cont_type; cont_type c; - for (size_t i = 0; i != 5; ++i) - c.insert(gu.build()); + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + typename cont_type::local_iterator lit(it); + VERIFY( *lit == val ); + } + + template<typename _Tp> + void invalid_local_iterator_move_construction() + { + typedef _Tp cont_type; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + typename cont_type::local_iterator lit(std::move(it)); + VERIFY( *lit == val ); + } + + template<typename _Tp> + void invalid_local_iterator_copy_assignment() + { + typedef _Tp cont_type; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + typename cont_type::local_iterator lit; + lit = it; + VERIFY( *lit == val ); + } + + template<typename _Tp> + void invalid_local_iterator_move_assignment() + { + typedef _Tp cont_type; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + typename cont_type::local_iterator lit; + lit = std::move(it); + VERIFY( *lit == val ); + } + + template<typename _Tp> + void invalid_local_iterator_const_conversion() + { + typedef _Tp cont_type; + cont_type c; + auto it = fill_and_get_local_iterator(c); + + const auto& val = *it; + c.clear(); + typename cont_type::const_local_iterator clit(it); + VERIFY( *clit == val ); + } + + template<typename _Tp> + void invalid_local_iterator_pre_increment() + { + typedef _Tp cont_type; + cont_type c; + fill_container(c); auto lit = c.begin(0); for (size_t i = 0; i != 6; ++i) @@ -146,13 +235,8 @@ namespace __gnu_test void invalid_local_iterator_post_increment() { typedef _Tp cont_type; - typedef typename cont_type::value_type cont_val_type; - typedef typename CopyableValueType<cont_val_type>::value_type val_type; - generate_unique<val_type> gu; - cont_type c; - for (size_t i = 0; i != 5; ++i) - c.insert(gu.build()); + fill_container(c); auto lit = c.begin(0); for (size_t i = 0; i != 6; ++i) @@ -163,13 +247,8 @@ namespace __gnu_test void invalid_local_iterator_compare() { typedef _Tp cont_type; - typedef typename cont_type::value_type cont_val_type; - typedef typename CopyableValueType<cont_val_type>::value_type val_type; - generate_unique<val_type> gu; - cont_type c; - for (size_t i = 0; i != 5; ++i) - c.insert(gu.build()); + fill_container(c); typename cont_type::local_iterator it1, it2; size_t i; @@ -194,13 +273,8 @@ namespace __gnu_test void invalid_local_iterator_range() { typedef _Tp cont_type; - typedef typename cont_type::value_type cont_val_type; - typedef typename CopyableValueType<cont_val_type>::value_type val_type; - generate_unique<val_type> gu; - cont_type c; - for (size_t i = 0; i != 5; ++i) - c.insert(gu.build()); + fill_container(c); typename cont_type::local_iterator it, end; for (size_t i = 0; i != c.bucket_count(); ++i) diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h b/libstdc++-v3/testsuite/util/testsuite_iterators.h index 20539ec..74a8739 100644 --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h @@ -892,6 +892,9 @@ namespace __gnu_test using test_input_range = test_range<T, input_iterator_wrapper>; template<typename T> + using test_input_range_nocopy + = test_range_nocopy<T, input_iterator_wrapper_nocopy>; + template<typename T> using test_output_range = test_range<T, output_iterator_wrapper>; diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog index d08a03b..3c33199 100644 --- a/maintainer-scripts/ChangeLog +++ b/maintainer-scripts/ChangeLog @@ -1,3 +1,8 @@ +2025-04-17 Jakub Jelinek <jakub@redhat.com> + + * crontab: Snapshots from trunk are now GCC 16 related. + Add GCC 15 snapshots from the respective branch. + 2025-04-07 Jakub Jelinek <jakub@redhat.com> PR web/119227 diff --git a/maintainer-scripts/crontab b/maintainer-scripts/crontab index 7bb7362..c880d7d 100644 --- a/maintainer-scripts/crontab +++ b/maintainer-scripts/crontab @@ -1,7 +1,8 @@ 16 0 * * * sh /home/gccadmin/scripts/update_version_git 50 0 * * * sh /home/gccadmin/scripts/update_web_docs_git 55 0 * * * sh /home/gccadmin/scripts/update_web_docs_libstdcxx_git -32 22 * * 4 sh /home/gccadmin/scripts/gcc_release -s 12:releases/gcc-12 -l -d /sourceware/snapshot-tmp/gcc all -32 22 * * 5 sh /home/gccadmin/scripts/gcc_release -s 13:releases/gcc-13 -l -d /sourceware/snapshot-tmp/gcc all -32 22 * * 6 sh /home/gccadmin/scripts/gcc_release -s 14:releases/gcc-14 -l -d /sourceware/snapshot-tmp/gcc all -32 22 * * 7 sh /home/gccadmin/scripts/gcc_release -s 15:master -l -d /sourceware/snapshot-tmp/gcc all +32 22 * * 3 sh /home/gccadmin/scripts/gcc_release -s 12:releases/gcc-12 -l -d /sourceware/snapshot-tmp/gcc all +32 22 * * 4 sh /home/gccadmin/scripts/gcc_release -s 13:releases/gcc-13 -l -d /sourceware/snapshot-tmp/gcc all +32 22 * * 5 sh /home/gccadmin/scripts/gcc_release -s 14:releases/gcc-14 -l -d /sourceware/snapshot-tmp/gcc all +32 22 * * 6 sh /home/gccadmin/scripts/gcc_release -s 15:releases/gcc-15 -l -d /sourceware/snapshot-tmp/gcc all +32 22 * * 7 sh /home/gccadmin/scripts/gcc_release -s 16:master -l -d /sourceware/snapshot-tmp/gcc all |