diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/DATESTAMP | 2 | ||||
-rw-r--r-- | gcc/auto-profile.cc | 4 | ||||
-rw-r--r-- | gcc/config/avr/avr-mcus.def | 11 | ||||
-rw-r--r-- | gcc/coverage.cc | 1 | ||||
-rw-r--r-- | gcc/doc/avr-mmcu.texi | 6 | ||||
-rw-r--r-- | gcc/gcov-io.h | 5 | ||||
-rw-r--r-- | gcc/ipa-inline.cc | 1 | ||||
-rw-r--r-- | gcc/lto-cgraph.cc | 19 | ||||
-rw-r--r-- | gcc/profile-count.cc | 27 | ||||
-rw-r--r-- | gcc/profile-count.h | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr120951-1.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c | 2 | ||||
-rw-r--r-- | gcc/tree-call-cdce.cc | 17 | ||||
-rw-r--r-- | gcc/tree-cfg.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/ranges_algo.h | 115 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/version.def | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/version.h | 7 | ||||
-rw-r--r-- | libstdc++-v3/src/c++23/std.cc.in | 8 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/shift_left/constrained.cc | 105 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/25_algorithms/shift_right/constrained.cc | 104 |
21 files changed, 456 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7160c96..319b756 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2025-07-05 Alexandre Oliva <oliva@adacore.com> + + * config/rs6000/vxworks.h (SUBTARGET_DRIVER_SELF_SPECS): + Redefine to select word size matching TARGET_VXWORKS64. + (TARGET_VXWORKS64): Redefine in terms of TARGET_64BIT. + 2025-07-04 Vineet Gupta <vineetg@rivosinc.com> PR target/118241 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 93909f8..0f0154f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250705 +20250706 diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc index 64f4cda..a970eb8 100644 --- a/gcc/auto-profile.cc +++ b/gcc/auto-profile.cc @@ -2522,6 +2522,7 @@ autofdo_source_profile::read () afdo_count_scale = MAX (((gcov_type)1 << (profile_count::n_bits / 2)) / afdo_profile_info->sum_max, 1); + afdo_profile_info->cutoff *= afdo_count_scale; afdo_hot_bb_threshod = hot_frac ? afdo_profile_info->sum_max * afdo_count_scale / hot_frac @@ -2531,10 +2532,12 @@ autofdo_source_profile::read () fprintf (dump_file, "Max count in profile %" PRIu64 "\n" "Setting scale %" PRIu64 "\n" "Scaled max count %" PRIu64 "\n" + "Cutoff %" PRIu64 "\n" "Hot count threshold %" PRIu64 "\n\n", (int64_t)afdo_profile_info->sum_max, (int64_t)afdo_count_scale, (int64_t)(afdo_profile_info->sum_max * afdo_count_scale), + (int64_t)afdo_profile_info->cutoff, (int64_t)afdo_hot_bb_threshod); afdo_profile_info->sum_max *= afdo_count_scale; return true; @@ -3865,6 +3868,7 @@ read_autofdo_file (void) autofdo::afdo_profile_info = XNEW (gcov_summary); autofdo::afdo_profile_info->runs = 1; autofdo::afdo_profile_info->sum_max = 0; + autofdo::afdo_profile_info->cutoff = 1; /* Read the profile from the profile file. */ autofdo::read_profile (); diff --git a/gcc/config/avr/avr-mcus.def b/gcc/config/avr/avr-mcus.def index ad64050..2e7c8ac 100644 --- a/gcc/config/avr/avr-mcus.def +++ b/gcc/config/avr/avr-mcus.def @@ -313,6 +313,10 @@ AVR_MCU ("avr64da28", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR AVR_MCU ("avr64da32", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA32__", 0x6000, 0x0, 0x10000, 0) AVR_MCU ("avr64da48", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA48__", 0x6000, 0x0, 0x10000, 0) AVR_MCU ("avr64da64", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA64__", 0x6000, 0x0, 0x10000, 0) +AVR_MCU ("avr64da28s", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA28S__", 0x6000, 0x0, 0x10000, 0) +AVR_MCU ("avr64da32s", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA32S__", 0x6000, 0x0, 0x10000, 0) +AVR_MCU ("avr64da48s", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA48S__", 0x6000, 0x0, 0x10000, 0) +AVR_MCU ("avr64da64s", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DA64S__", 0x6000, 0x0, 0x10000, 0) AVR_MCU ("avr64db28", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DB28__", 0x6000, 0x0, 0x10000, 0) AVR_MCU ("avr64db32", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DB32__", 0x6000, 0x0, 0x10000, 0) AVR_MCU ("avr64db48", ARCH_AVRXMEGA2, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR64DB48__", 0x6000, 0x0, 0x10000, 0) @@ -389,6 +393,9 @@ AVR_MCU ("avr16du32", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR AVR_MCU ("avr32da28", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA28__", 0x7000, 0x0, 0x8000, 0x8000) AVR_MCU ("avr32da32", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA32__", 0x7000, 0x0, 0x8000, 0x8000) AVR_MCU ("avr32da48", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA48__", 0x7000, 0x0, 0x8000, 0x8000) +AVR_MCU ("avr32da28s", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA28S__", 0x7000, 0x0, 0x8000, 0x8000) +AVR_MCU ("avr32da32s", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA32S__", 0x7000, 0x0, 0x8000, 0x8000) +AVR_MCU ("avr32da48s", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DA48S__", 0x7000, 0x0, 0x8000, 0x8000) AVR_MCU ("avr32db28", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DB28__", 0x7000, 0x0, 0x8000, 0x8000) AVR_MCU ("avr32db32", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DB32__", 0x7000, 0x0, 0x8000, 0x8000) AVR_MCU ("avr32db48", ARCH_AVRXMEGA3, AVR_CVT, "__AVR_AVR32DB48__", 0x7000, 0x0, 0x8000, 0x8000) @@ -427,6 +434,10 @@ AVR_MCU ("avr128da28", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR AVR_MCU ("avr128da32", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA32__", 0x4000, 0x0, 0x20000, 0) AVR_MCU ("avr128da48", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA48__", 0x4000, 0x0, 0x20000, 0) AVR_MCU ("avr128da64", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA64__", 0x4000, 0x0, 0x20000, 0) +AVR_MCU ("avr128da28s", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA28S__", 0x4000, 0x0, 0x20000, 0) +AVR_MCU ("avr128da32s", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA32S__", 0x4000, 0x0, 0x20000, 0) +AVR_MCU ("avr128da48s", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA48S__", 0x4000, 0x0, 0x20000, 0) +AVR_MCU ("avr128da64s", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DA64S__", 0x4000, 0x0, 0x20000, 0) AVR_MCU ("avr128db28", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DB28__", 0x4000, 0x0, 0x20000, 0) AVR_MCU ("avr128db32", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DB32__", 0x4000, 0x0, 0x20000, 0) AVR_MCU ("avr128db48", ARCH_AVRXMEGA4, AVR_CVT | AVR_ISA_FLMAP, "__AVR_AVR128DB48__", 0x4000, 0x0, 0x20000, 0) diff --git a/gcc/coverage.cc b/gcc/coverage.cc index dd3ed2e..75a24c6 100644 --- a/gcc/coverage.cc +++ b/gcc/coverage.cc @@ -238,6 +238,7 @@ read_counts_file (void) gcov_profile_info = profile_info = XCNEW (gcov_summary); profile_info->runs = gcov_read_unsigned (); profile_info->sum_max = gcov_read_unsigned (); + profile_info->cutoff = 1; } else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) { diff --git a/gcc/doc/avr-mmcu.texi b/gcc/doc/avr-mmcu.texi index feb7725..5efcc81 100644 --- a/gcc/doc/avr-mmcu.texi +++ b/gcc/doc/avr-mmcu.texi @@ -50,15 +50,15 @@ @item @anchor{avrxmega2}avrxmega2 ``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB of program memory. -@*@var{mcu}@tie{}= @code{atxmega8e5}, @code{atxmega16a4}, @code{atxmega16a4u}, @code{atxmega16c4}, @code{atxmega16d4}, @code{atxmega16e5}, @code{atxmega32a4}, @code{atxmega32a4u}, @code{atxmega32c3}, @code{atxmega32c4}, @code{atxmega32d3}, @code{atxmega32d4}, @code{atxmega32e5}, @code{avr64da28}, @code{avr64da32}, @code{avr64da48}, @code{avr64da64}, @code{avr64db28}, @code{avr64db32}, @code{avr64db48}, @code{avr64db64}, @code{avr64dd14}, @code{avr64dd20}, @code{avr64dd28}, @code{avr64dd32}, @code{avr64du28}, @code{avr64du32}, @code{avr64ea28}, @code{avr64ea32}, @code{avr64ea48}, @code{avr64sd28}, @code{avr64sd32}, @code{avr64sd48}. +@*@var{mcu}@tie{}= @code{atxmega8e5}, @code{atxmega16a4}, @code{atxmega16a4u}, @code{atxmega16c4}, @code{atxmega16d4}, @code{atxmega16e5}, @code{atxmega32a4}, @code{atxmega32a4u}, @code{atxmega32c3}, @code{atxmega32c4}, @code{atxmega32d3}, @code{atxmega32d4}, @code{atxmega32e5}, @code{avr64da28}, @code{avr64da28s}, @code{avr64da32}, @code{avr64da32s}, @code{avr64da48}, @code{avr64da48s}, @code{avr64da64}, @code{avr64da64s}, @code{avr64db28}, @code{avr64db32}, @code{avr64db48}, @code{avr64db64}, @code{avr64dd14}, @code{avr64dd20}, @code{avr64dd28}, @code{avr64dd32}, @code{avr64du28}, @code{avr64du32}, @code{avr64ea28}, @code{avr64ea32}, @code{avr64ea48}, @code{avr64sd28}, @code{avr64sd32}, @code{avr64sd48}. @item @anchor{avrxmega3}avrxmega3 ``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, and with program memory visible in the RAM address space. -@*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, @code{attiny214}, @code{attiny402}, @code{attiny404}, @code{attiny406}, @code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny416auto}, @code{attiny417}, @code{attiny424}, @code{attiny426}, @code{attiny427}, @code{attiny804}, @code{attiny806}, @code{attiny807}, @code{attiny814}, @code{attiny816}, @code{attiny817}, @code{attiny824}, @code{attiny826}, @code{attiny827}, @code{attiny1604}, @code{attiny1606}, @code{attiny1607}, @code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny1624}, @code{attiny1626}, @code{attiny1627}, @code{attiny3214}, @code{attiny3216}, @code{attiny3217}, @code{attiny3224}, @code{attiny3226}, @code{attiny3227}, @code{atmega808}, @code{atmega809}, @code{atmega1608}, @code{atmega1609}, @code{atmega3208}, @code{atmega3209}, @code{atmega4808}, @code{atmega4809}, @code{avr16dd14}, @code{avr16dd20}, @code{avr16dd28}, @code{avr16dd32}, @code{avr16du14}, @code{avr16du20}, @code{avr16du28}, @code{avr16du32}, @code{avr16ea28}, @code{avr16ea32}, @code{avr16ea48}, @code{avr16eb14}, @code{avr16eb20}, @code{avr16eb28}, @code{avr16eb32}, @code{avr32da28}, @code{avr32da32}, @code{avr32da48}, @code{avr32db28}, @code{avr32db32}, @code{avr32db48}, @code{avr32dd14}, @code{avr32dd20}, @code{avr32dd28}, @code{avr32dd32}, @code{avr32du14}, @code{avr32du20}, @code{avr32du28}, @code{avr32du32}, @code{avr32ea28}, @code{avr32ea32}, @code{avr32ea48}, @code{avr32sd20}, @code{avr32sd28}, @code{avr32sd32}. +@*@var{mcu}@tie{}= @code{attiny202}, @code{attiny204}, @code{attiny212}, @code{attiny214}, @code{attiny402}, @code{attiny404}, @code{attiny406}, @code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny416auto}, @code{attiny417}, @code{attiny424}, @code{attiny426}, @code{attiny427}, @code{attiny804}, @code{attiny806}, @code{attiny807}, @code{attiny814}, @code{attiny816}, @code{attiny817}, @code{attiny824}, @code{attiny826}, @code{attiny827}, @code{attiny1604}, @code{attiny1606}, @code{attiny1607}, @code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny1624}, @code{attiny1626}, @code{attiny1627}, @code{attiny3214}, @code{attiny3216}, @code{attiny3217}, @code{attiny3224}, @code{attiny3226}, @code{attiny3227}, @code{atmega808}, @code{atmega809}, @code{atmega1608}, @code{atmega1609}, @code{atmega3208}, @code{atmega3209}, @code{atmega4808}, @code{atmega4809}, @code{avr16dd14}, @code{avr16dd20}, @code{avr16dd28}, @code{avr16dd32}, @code{avr16du14}, @code{avr16du20}, @code{avr16du28}, @code{avr16du32}, @code{avr16ea28}, @code{avr16ea32}, @code{avr16ea48}, @code{avr16eb14}, @code{avr16eb20}, @code{avr16eb28}, @code{avr16eb32}, @code{avr32da28}, @code{avr32da28s}, @code{avr32da32}, @code{avr32da32s}, @code{avr32da48}, @code{avr32da48s}, @code{avr32db28}, @code{avr32db32}, @code{avr32db48}, @code{avr32dd14}, @code{avr32dd20}, @code{avr32dd28}, @code{avr32dd32}, @code{avr32du14}, @code{avr32du20}, @code{avr32du28}, @code{avr32du32}, @code{avr32ea28}, @code{avr32ea32}, @code{avr32ea48}, @code{avr32sd20}, @code{avr32sd28}, @code{avr32sd32}. @item @anchor{avrxmega4}avrxmega4 ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory. -@*@var{mcu}@tie{}= @code{atxmega64a3}, @code{atxmega64a3u}, @code{atxmega64a4u}, @code{atxmega64b1}, @code{atxmega64b3}, @code{atxmega64c3}, @code{atxmega64d3}, @code{atxmega64d4}, @code{avr128da28}, @code{avr128da32}, @code{avr128da48}, @code{avr128da64}, @code{avr128db28}, @code{avr128db32}, @code{avr128db48}, @code{avr128db64}. +@*@var{mcu}@tie{}= @code{atxmega64a3}, @code{atxmega64a3u}, @code{atxmega64a4u}, @code{atxmega64b1}, @code{atxmega64b3}, @code{atxmega64c3}, @code{atxmega64d3}, @code{atxmega64d4}, @code{avr128da28}, @code{avr128da28s}, @code{avr128da32}, @code{avr128da32s}, @code{avr128da48}, @code{avr128da48s}, @code{avr128da64}, @code{avr128da64s}, @code{avr128db28}, @code{avr128db32}, @code{avr128db48}, @code{avr128db64}. @item @anchor{avrxmega5}avrxmega5 ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory and more than 64@tie{}KiB of RAM. diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index d48291c..f3e3a1c 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -349,6 +349,11 @@ struct gcov_summary { gcov_unsigned_t runs; /* Number of program runs. */ gcov_type sum_max; /* Sum of individual run max values. */ + gcov_type cutoff; /* Values smaller than this value are not + reliable (0 may mean non-zero). + For read profile cutoff is typically 1 + however when we scale up or use auto-fdo + it may become bigger value. */ }; #if !defined(inhibit_libc) diff --git a/gcc/ipa-inline.cc b/gcc/ipa-inline.cc index ca605b0..0cf97a80 100644 --- a/gcc/ipa-inline.cc +++ b/gcc/ipa-inline.cc @@ -2222,6 +2222,7 @@ inline_small_functions (void) gcc_assert (in_lto_p || !(max_count > 0) + || flag_auto_profile || (profile_info && flag_branch_probabilities)); while (!edge_heap.empty ()) diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc index ec34f65..0af2e88 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -718,11 +718,12 @@ output_profile_summary (struct lto_simple_output_block *ob) { if (profile_info) { - /* We do not output num and run_max, they are not used by - GCC profile feedback and they are difficult to merge from multiple - units. */ unsigned runs = (profile_info->runs); streamer_write_uhwi_stream (ob->main_stream, runs); + streamer_write_gcov_count_stream (ob->main_stream, + profile_info->sum_max); + streamer_write_gcov_count_stream (ob->main_stream, + profile_info->cutoff); /* IPA-profile computes hot bb threshold based on cumulated whole program profile. We need to stream it down to ltrans. */ @@ -1678,6 +1679,8 @@ input_profile_summary (class lto_input_block *ib, if (runs) { file_data->profile_info.runs = runs; + file_data->profile_info.sum_max = streamer_read_gcov_count (ib); + file_data->profile_info.cutoff = streamer_read_gcov_count (ib); /* IPA-profile computes hot bb threshold based on cumulated whole program profile. We need to stream it down to ltrans. */ @@ -1719,6 +1722,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec) profile_info = XCNEW (gcov_summary); profile_info->runs = max_runs; + profile_info->sum_max = 0; + profile_info->cutoff = 0; /* If merging already happent at WPA time, we are done. */ if (flag_ltrans) @@ -1735,6 +1740,14 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec) scale = RDIV (node->count_materialization_scale * max_runs, node->lto_file_data->profile_info.runs); + gcov_type sum_max = RDIV (node->lto_file_data->profile_info.sum_max * max_runs, + node->lto_file_data->profile_info.runs); + gcov_type cutoff = RDIV (node->lto_file_data->profile_info.cutoff * max_runs, + node->lto_file_data->profile_info.runs); + if (sum_max > profile_info->sum_max) + profile_info->sum_max = sum_max; + if (cutoff > profile_info->cutoff) + profile_info->cutoff = cutoff; node->count_materialization_scale = scale; if (scale < 0) fatal_error (input_location, "Profile information in %s corrupted", diff --git a/gcc/profile-count.cc b/gcc/profile-count.cc index 190bbeb..8f05a79 100644 --- a/gcc/profile-count.cc +++ b/gcc/profile-count.cc @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "wide-int.h" #include "sreal.h" +#include "profile.h" /* Names from profile_quality enum values. */ @@ -557,7 +558,7 @@ profile_count::operator* (const sreal &num) const sreal scaled = num * m_val; gcc_checking_assert (scaled >= 0); profile_count ret; - if (m_val > max_count) + if (scaled > max_count) ret.m_val = max_count; else ret.m_val = scaled.to_nearest_int (); @@ -570,3 +571,27 @@ profile_count::operator*= (const sreal &num) { return *this * num; } + +/* Make counter forcibly nonzero. */ +profile_count +profile_count::force_nonzero () const +{ + if (!initialized_p ()) + return *this; + profile_count ret = *this; + /* Generally values are forced non-zero to handle inconsistent profile + where count 0 needs to be scaled up to non-zero. + + Use cutoff value here to avoid situation where profile has large + cutoff and we perform count = count * num / den where num is non-zero + and den is 0. If profile was scaled by large factor, forcing value + to 1 would lead to large scale factor. */ + gcov_unsigned_t small = profile_info ? profile_info->cutoff / 2 + 1 + : 1; + if (ret.m_val < small) + { + ret.m_val = small; + ret.m_quality = MIN (m_quality, ADJUSTED); + } + return ret; +} diff --git a/gcc/profile-count.h b/gcc/profile-count.h index 2160540..20c03a2 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -1112,18 +1112,7 @@ public: } /* Make counter forcibly nonzero. */ - profile_count force_nonzero () const - { - if (!initialized_p ()) - return *this; - profile_count ret = *this; - if (ret.m_val == 0) - { - ret.m_val = 1; - ret.m_quality = MIN (m_quality, ADJUSTED); - } - return ret; - } + profile_count force_nonzero () const; profile_count max (profile_count other) const { diff --git a/gcc/testsuite/gcc.dg/torture/pr120951-1.c b/gcc/testsuite/gcc.dg/torture/pr120951-1.c new file mode 100644 index 0000000..4e2b41d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr120951-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fnon-call-exceptions -fsignaling-nans" } */ + +/* PR tree-optimization/120951 */ + +/* cdce would create a trapping comparison inside a condition. + tests to make sure that does not happen. */ + +double f(double r, double i) { + return __builtin_fmod(r, i); +} + diff --git a/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c b/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c index 43a9090..904dd0c 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c +++ b/gcc/testsuite/gcc.dg/tree-prof/clone-merge-1.c @@ -31,4 +31,4 @@ int main() } /* We will have profiles for test2 and test2.constprop.0 that will have to be merged, */ -/* { dg-final-use-autofdo { scan-ipa-dump "Merging duplicate symbol test2" "afdo_offline"} } */ +/* { dg-final-use-autofdo { scan-ipa-dump "Merging duplicate instance: test2" "afdo_offline"} } */ diff --git a/gcc/tree-call-cdce.cc b/gcc/tree-call-cdce.cc index 649c1e2..3edea75 100644 --- a/gcc/tree-call-cdce.cc +++ b/gcc/tree-call-cdce.cc @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "internal-fn.h" #include "tree-dfa.h" +#include "tree-eh.h" /* This pass serves two closely-related purposes: @@ -1222,8 +1223,20 @@ use_internal_fn (gcall *call) { /* Skip the call if LHS == LHS. If we reach here, EDOM is the only valid errno value and it is used iff the result is NaN. */ - conds.quick_push (gimple_build_cond (EQ_EXPR, lhs, lhs, - NULL_TREE, NULL_TREE)); + /* In the case of non call exceptions, with signaling NaNs, EQ_EXPR + can throw an exception and that can't be part of the GIMPLE_COND. */ + if (flag_exceptions + && cfun->can_throw_non_call_exceptions + && operation_could_trap_p (EQ_EXPR, true, false, NULL_TREE)) + { + tree b = make_ssa_name (boolean_type_node); + conds.quick_push (gimple_build_assign (b, EQ_EXPR, lhs, lhs)); + conds.quick_push (gimple_build_cond (NE_EXPR, b, boolean_false_node, + NULL_TREE, NULL_TREE)); + } + else + conds.quick_push (gimple_build_cond (EQ_EXPR, lhs, lhs, + NULL_TREE, NULL_TREE)); nconds++; /* Try replacing the original call with a direct assignment to diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index 72763fd..9a5479a 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -4623,6 +4623,14 @@ verify_gimple_assign_single (gassign *stmt) return true; } + /* LHS can't be a constant or an address expression. */ + if (CONSTANT_CLASS_P (lhs)|| TREE_CODE (lhs) == ADDR_EXPR) + { + error ("invalid LHS (%qs) for assignment: %qs", + get_tree_code_name (TREE_CODE (lhs)), code_name); + return true; + } + if (gimple_clobber_p (stmt) && !(DECL_P (lhs) || TREE_CODE (lhs) == MEM_REF)) { @@ -4745,6 +4753,11 @@ verify_gimple_assign_single (gassign *stmt) if (CONSTRUCTOR_NELTS (rhs1) == 0) return res; + if (!is_gimple_reg (lhs)) + { + error ("non-register as LHS with vector constructor"); + return true; + } /* For vector CONSTRUCTORs we require that either it is empty CONSTRUCTOR, or it is a CONSTRUCTOR of smaller vector elements (then the element count must be correct to cover the whole diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index cf369c5..9f8945a 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -5218,6 +5218,7 @@ namespace ranges #endif // __glibcxx_ranges_fold } // namespace ranges +#if __glibcxx_shift >= 201806L // C++ >= 20 template<typename _ForwardIterator> constexpr _ForwardIterator shift_left(_ForwardIterator __first, _ForwardIterator __last, @@ -5308,6 +5309,120 @@ namespace ranges } } } +#endif + +namespace ranges +{ +#if __glibcxx_shift >= 202202L // C++ >= 23 + struct __shift_left_fn + { + template<permutable _Iter, sentinel_for<_Iter> _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return {__first, ranges::next(__first, __last)}; + + auto __mid = ranges::next(__first, __n, __last); + if (__mid == __last) + return {__first, __first}; + return {__first, ranges::move(__mid, __last, __first).out}; + } + + template<forward_range _Range> + requires permutable<iterator_t<_Range>> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __n) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __n); } + }; + + inline constexpr __shift_left_fn shift_left{}; + + struct __shift_right_fn + { + template<permutable _Iter, sentinel_for<_Iter> _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return {__first, ranges::next(__first, __last)}; + + if constexpr (bidirectional_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto __mid = ranges::next(__last, -__n, __first); + if (__mid == __first) + return {__last, __last}; + + return {ranges::move_backward(__first, __mid, __last).out, __last}; + } + else + { + auto __result = ranges::next(__first, __n, __last); + if (__result == __last) + return {__result, __result}; + + auto __dest_head = __first, __dest_tail = __result; + while (__dest_head != __result) + { + if (__dest_tail == __last) + { + // If we get here, then we must have + // 2*n >= distance(__first, __last) + // i.e. we are shifting out at least half of the range. In + // this case we can safely perform the shift with a single + // move. + auto __lasti = ranges::move(__first, __dest_head, __result).out; + // __glibcxx_assert(__lasti == __last); + return {__result, __lasti}; + } + ++__dest_head; + ++__dest_tail; + } + + for (;;) + { + // At the start of each iteration of this outer loop, the range + // [__first, __result) contains those elements that after shifting + // the whole range right by __n, should end up in + // [__dest_head, __dest_tail) in order. + + // The below inner loop swaps the elements of [__first, __result) + // and [__dest_head, __dest_tail), while simultaneously shifting + // the latter range by __n. + auto __cursor = __first; + while (__cursor != __result) + { + if (__dest_tail == __last) + { + // At this point the ranges [__first, result) and + // [__dest_head, dest_tail) are disjoint, so we can safely + // move the remaining elements. + __dest_head = ranges::move(__cursor, __result, __dest_head).out; + auto __lasti = ranges::move(__first, __cursor, __dest_head).out; + // __glibcxx_assert(__lasti == __last); + return {__result, __lasti}; + } + ranges::iter_swap(__cursor, __dest_head); + ++__dest_head; + ++__dest_tail; + ++__cursor; + } + } + } + } + + template<forward_range _Range> + requires permutable<iterator_t<_Range>> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __n) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __n); } + }; + + inline constexpr __shift_right_fn shift_right{}; +#endif // C++23 +} // namespace ranges _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 5d5758b..64f8190 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1092,6 +1092,10 @@ ftms = { ftms = { name = shift; values = { + v = 202202; + cxxmin = 23; + }; + values = { v = 201806; cxxmin = 20; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 2b00e84..744246a 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1224,7 +1224,12 @@ #undef __glibcxx_want_constexpr_utility #if !defined(__cpp_lib_shift) -# if (__cplusplus >= 202002L) +# if (__cplusplus >= 202100L) +# define __glibcxx_shift 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift) +# define __cpp_lib_shift 202202L +# endif +# elif (__cplusplus >= 202002L) # define __glibcxx_shift 201806L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift) # define __cpp_lib_shift 201806L diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 483b6c6..86e6d88 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -278,10 +278,14 @@ export namespace std } using std::shift_left; namespace ranges - {} + { + using std::ranges::shift_left; + } using std::shift_right; namespace ranges - {} + { + using std::ranges::shift_right; + } using std::sort; namespace ranges { diff --git a/libstdc++-v3/testsuite/25_algorithms/shift_left/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/shift_left/constrained.cc new file mode 100644 index 0000000..73d0614 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/shift_left/constrained.cc @@ -0,0 +1,105 @@ +// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++23 } } +// This test is based on shift_left/1.cc. + +#include <algorithm> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +struct X +{ + int a = -1; + bool moved_from = false; + + X() = default; + + X(int a) + : a(a) + { } + + X(const X&) = delete; + X& operator=(const X&) = delete; + + X(X&& other) + { + if (this != &other) + *this = std::move(other); + } + + X& + operator=(X&& other) + { + a = other.a; + other.moved_from = true; + moved_from = false; + return *this; + } +}; + +template<int N, template<typename> typename Wrapper> +void +test01() +{ + for (int n = 0; n < N+5; n++) + { + X x[N]; + for (int i = 0; i < N; i++) + x[i] = X{i}; + test_range<X, Wrapper> rx(x); + auto [first,out] = std::ranges::shift_left(rx.begin(), rx.end(), n); + VERIFY( first == rx.begin() ); + if (n < N) + { + VERIFY( out.ptr == x+(N-n) ); + for (int i = 0; i < N-n; i++) + { + VERIFY( x[i].a == n+i ); + VERIFY( !x[i].moved_from ); + } + for (int i = std::max(n, N-n); i < N; i++) + VERIFY( x[i].moved_from ); + } + else + { + VERIFY( out.ptr == x ); + for (int i = 0; i < N; i++) + { + VERIFY( x[i].a == i ); + VERIFY( !x[i].moved_from ); + } + } + } +} + +int +main() +{ + test01<23, forward_iterator_wrapper>(); + test01<23, bidirectional_iterator_wrapper>(); + test01<23, random_access_iterator_wrapper>(); + + test01<24, forward_iterator_wrapper>(); + test01<24, bidirectional_iterator_wrapper>(); + test01<24, random_access_iterator_wrapper>(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/shift_right/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/shift_right/constrained.cc new file mode 100644 index 0000000..0d53707 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/shift_right/constrained.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-do run { target c++23 } } +// This test is based on shift_right/1.cc. + +#include <algorithm> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +struct X +{ + int a = -1; + bool moved_from = false; + + X() = default; + + X(int a) + : a(a) + { } + + X(const X&) = delete; + X& operator=(const X&) = delete; + + X(X&& other) + { + if (this != &other) + *this = std::move(other); + } + + X& + operator=(X&& other) + { + a = other.a; + other.moved_from = true; + moved_from = false; + return *this; + } +}; + +template<int N, template<typename> typename Wrapper> +void +test01() +{ + for (int n = 0; n < N+5; n++) + { + X x[N]; + for (int i = 0; i < N; i++) + x[i] = X(i); + test_range<X, Wrapper> rx(x); + auto [out,last] = std::ranges::shift_right(rx.begin(), rx.end(), n); + VERIFY( last == rx.end() ); + if (n < N) + { + VERIFY( out.ptr == x+n ); + for (int i = n; i < N; i++) + VERIFY( x[i].a == i-n ); + for (int i = 0; i < std::min(n, N-n); i++) + VERIFY( x[i].moved_from ); + for (int i = std::min(n, N-n); i < std::max(n, N-n); i++) + VERIFY( !x[i].moved_from ); + } + else + { + VERIFY( out.ptr == x+N ); + for (int i = 0; i < N; i++) + { + VERIFY( x[i].a == i ); + VERIFY( !x[i].moved_from ); + } + } + } +} + +int +main() +{ + test01<23, forward_iterator_wrapper>(); + test01<23, bidirectional_iterator_wrapper>(); + test01<23, random_access_iterator_wrapper>(); + + test01<24, forward_iterator_wrapper>(); + test01<24, bidirectional_iterator_wrapper>(); + test01<24, random_access_iterator_wrapper>(); +} |