aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-05-27 09:52:01 +0200
committerMartin Liska <mliska@suse.cz>2021-05-27 09:52:01 +0200
commitd4997738800da4be5954fa1849bbf2ade74cc20e (patch)
tree84e2dfcf6a774a8868f10c6b534c4f2afadc20c2
parent2a0afc4ad163ba4a8b5ef10b777b20e62baf5f79 (diff)
parent01c59ef2e5a59b44d2b662361196abb6be872a20 (diff)
downloadgcc-d4997738800da4be5954fa1849bbf2ade74cc20e.zip
gcc-d4997738800da4be5954fa1849bbf2ade74cc20e.tar.gz
gcc-d4997738800da4be5954fa1849bbf2ade74cc20e.tar.bz2
Merge branch 'master' into devel/sphinx
-rw-r--r--gcc/ChangeLog214
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/init.c2
-rw-r--r--gcc/builtins.c40
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-decl.c7
-rw-r--r--gcc/config/arc/arc.c20
-rw-r--r--gcc/config/arm/aout.h2
-rw-r--r--gcc/config/arm/mve.md2
-rw-r--r--gcc/config/arm/neon.md13
-rw-r--r--gcc/config/arm/vec-common.md26
-rw-r--r--gcc/config/bfin/bfin.c6
-rw-r--r--gcc/config/csky/csky.c16
-rw-r--r--gcc/config/epiphany/epiphany.c2
-rw-r--r--gcc/config/i386/i386.c5
-rw-r--r--gcc/config/iq2000/iq2000.md6
-rw-r--r--gcc/config/microblaze/microblaze.c26
-rw-r--r--gcc/config/microblaze/microblaze.md18
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/cvt.c36
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/cp/tree.c15
-rw-r--r--gcc/cp/typeck.c10
-rw-r--r--gcc/doc/extend.texi5
-rw-r--r--gcc/doc/sourcebuild.texi6
-rw-r--r--gcc/fold-const.c8
-rw-r--r--gcc/function.c4
-rw-r--r--gcc/function.h17
-rw-r--r--gcc/gimple-fold.c7
-rw-r--r--gcc/gimple-match-head.c1
-rw-r--r--gcc/gimple-pretty-print.c12
-rw-r--r--gcc/gimple-range-cache.cc1
-rw-r--r--gcc/gimple-range-gori.cc2
-rw-r--r--gcc/gimple-range.cc126
-rw-r--r--gcc/gimple-range.h60
-rw-r--r--gcc/gimple-ssa-evrp.c22
-rw-r--r--gcc/gimple-ssa-warn-alloca.c10
-rw-r--r--gcc/gimple-ssa-warn-restrict.c8
-rw-r--r--gcc/gimplify.c2
-rw-r--r--gcc/graphite-sese-to-poly.c9
-rw-r--r--gcc/internal-fn.c14
-rw-r--r--gcc/ipa-fnsummary.c11
-rw-r--r--gcc/ipa-prop.c16
-rw-r--r--gcc/match.pd19
-rw-r--r--gcc/omp-low.c39
-rw-r--r--gcc/omp-offload.c12
-rw-r--r--gcc/testsuite/ChangeLog55
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept68.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/elide6.C16
-rw-r--r--gcc/testsuite/g++.dg/template/access37.C26
-rw-r--r--gcc/testsuite/g++.dg/template/access37a.C6
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-55.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr80776-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/sso-13.c24
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr71264.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-28.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-3.c8
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/mve-vaddv-1.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100637-3b.c56
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100637-3w.c86
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100637-4b.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr100637-4w.c19
-rw-r--r--gcc/testsuite/lib/target-supports.exp7
-rw-r--r--gcc/tree-data-ref.c24
-rw-r--r--gcc/tree-dfa.c14
-rw-r--r--gcc/tree-scalar-evolution.c13
-rw-r--r--gcc/tree-ssa-loop-niter.c81
-rw-r--r--gcc/tree-ssa-phiopt.c11
-rw-r--r--gcc/tree-ssa-pre.c19
-rw-r--r--gcc/tree-ssa-reassoc.c9
-rw-r--r--gcc/tree-ssa-strlen.c85
-rw-r--r--gcc/tree-ssa-structalias.c8
-rw-r--r--gcc/tree-ssa-uninit.c8
-rw-r--r--gcc/tree-ssanames.c57
-rw-r--r--gcc/tree-ssanames.h2
-rw-r--r--gcc/tree-switch-conversion.c10
-rw-r--r--gcc/tree-vect-patterns.c18
-rw-r--r--gcc/tree-vrp.c23
-rw-r--r--gcc/tree.c13
-rw-r--r--gcc/value-query.cc5
-rw-r--r--gcc/value-query.h1
-rw-r--r--gcc/vr-values.c14
-rw-r--r--gcc/vr-values.h2
-rw-r--r--libgomp/ChangeLog15
-rw-r--r--libgomp/config/gcn/target.c65
-rw-r--r--libgomp/config/nvptx/target.c65
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/for-3.c56
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-41.c28
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-42.c26
-rw-r--r--libstdc++-v3/ChangeLog38
-rw-r--r--libstdc++-v3/include/bits/ranges_base.h378
-rw-r--r--libstdc++-v3/include/debug/formatter.h12
-rw-r--r--libstdc++-v3/src/c++11/debug.cc483
-rw-r--r--libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc25
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_operations/100768.cc128
-rw-r--r--libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc3
-rw-r--r--libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc3
98 files changed, 2176 insertions, 860 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 897c704..c639576 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,217 @@
+2021-05-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c/100653
+ * doc/extend.texi (scalar_storage_order): Rephrase slightly.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-ssanames.c (get_range_info): Merge both copies of
+ get_range_info into one that works with irange.
+ * tree-ssanames.h (get_range_info): Remove version that works on
+ wide_ints.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * builtins.c (check_nul_terminated_array): Convert to get_range_query.
+ (expand_builtin_strnlen): Same.
+ (determine_block_size): Same.
+ * fold-const.c (expr_not_equal_to): Same.
+ * gimple-fold.c (size_must_be_zero_p): Same.
+ * gimple-match-head.c: Include gimple-range.h.
+ * gimple-pretty-print.c (dump_ssaname_info): Convert to get_range_query.
+ * gimple-ssa-warn-restrict.c
+ (builtin_memref::extend_offset_range): Same.
+ * graphite-sese-to-poly.c (add_param_constraints): Same.
+ * internal-fn.c (get_min_precision): Same.
+ * ipa-fnsummary.c (set_switch_stmt_execution_predicate): Same.
+ * ipa-prop.c (ipa_compute_jump_functions_for_edge): Same.
+ * match.pd: Same.
+ * tree-data-ref.c (split_constant_offset): Same.
+ (dr_step_indicator): Same.
+ * tree-dfa.c (get_ref_base_and_extent): Same.
+ * tree-scalar-evolution.c (iv_can_overflow_p): Same.
+ * tree-ssa-loop-niter.c (refine_value_range_using_guard): Same.
+ (determine_value_range): Same.
+ (record_nonwrapping_iv): Same.
+ (infer_loop_bounds_from_signedness): Same.
+ (scev_var_range_cant_overflow): Same.
+ * tree-ssa-phiopt.c (two_value_replacement): Same.
+ * tree-ssa-pre.c (insert_into_preds_of_block): Same.
+ * tree-ssa-reassoc.c (optimize_range_tests_to_bit_test): Same.
+ * tree-ssa-strlen.c (handle_builtin_stxncpy_strncat): Same.
+ (get_range): Same.
+ (dump_strlen_info): Same.
+ (set_strlen_range): Same.
+ (maybe_diag_stxncpy_trunc): Same.
+ (get_len_or_size): Same.
+ (handle_integral_assign): Same.
+ * tree-ssa-structalias.c (find_what_p_points_to): Same.
+ * tree-ssa-uninit.c (find_var_cmp_const): Same.
+ * tree-switch-conversion.c (bit_test_cluster::emit): Same.
+ * tree-vect-patterns.c (vect_get_range_info): Same.
+ (vect_recog_divmod_pattern): Same.
+ * tree-vrp.c (intersect_range_with_nonzero_bits): Same.
+ (register_edge_assert_for_2): Same.
+ (determine_value_range_1): Same.
+ * tree.c (get_range_pos_neg): Same.
+ * vr-values.c (vr_values::get_lattice_entry): Same.
+ (vr_values::update_value_range): Same.
+ (simplify_conversion_using_ranges): Same.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-warn-alloca.c (alloca_call_type): Use
+ get_range_query instead of query argument.
+ (pass_walloca::execute): Enable and disable global ranger.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp.c (rvrp_folder::rvrp_folder): Call
+ enable_ranger.
+ (rvrp_folder::~rvrp_folder): Call disable_ranger.
+ (hybrid_folder::hybrid_folder): Call enable_ranger.
+ (hybrid_folder::~hybrid_folder): Call disable_ranger.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * function.c (allocate_struct_function): Set cfun->x_range_query.
+ * function.h (struct function): Declare x_range_query.
+ (get_range_query): New.
+ (get_global_range_query): New.
+ * gimple-range-cache.cc (ssa_global_cache::ssa_global_cache):
+ Remove call to safe_grow_cleared.
+ * gimple-range.cc (get_range_global): New.
+ (gimple_range_global): Move from gimple-range.h.
+ (get_global_range_query): New.
+ (global_range_query::range_of_expr): New.
+ (enable_ranger): New.
+ (disable_ranger): New.
+ * gimple-range.h (gimple_range_global): Move to gimple-range.cc.
+ (class global_range_query): New.
+ (enable_ranger): New.
+ (disable_ranger): New.
+ * gimple-ssa-evrp.c (evrp_folder::~evrp_folder): Rename
+ dump_all_value_ranges to dump.
+ * tree-vrp.c (vrp_prop::finalize): Same.
+ * value-query.cc (range_query::dump): New.
+ * value-query.h (range_query::dump): New.
+ * vr-values.c (vr_values::dump_all_value_ranges): Rename to...
+ (vr_values::dump): ...this.
+ * vr-values.h (class vr_values): Rename dump_all_value_ranges to
+ dump and make virtual.
+
+2021-05-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_autovectorize_vector_modes):
+ Add V4QImode and V16QImode for TARGET_SSE2.
+ * doc/sourcebuild.texi (Vector-specific attributes):
+ Add vect64 and vect32 description.
+
+2021-05-26 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ * gimple-range-gori.cc (range_def_chain::register_dependency):
+ Resize m_def_chain when needed.
+
+2021-05-26 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/arm/mve.md (mve_vaddvq_<supf><mode>): Prefix with '@'.
+ * config/arm/neon.md (reduc_plus_scal_<mode>): Move to ..
+ * config/arm/vec-common.md: .. here. Add support for MVE.
+
+2021-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ * config/epiphany/epiphany.c (epiphany_print_operand_address): Remove
+ register keywords.
+ * config/microblaze/microblaze.c (microblaze_legitimize_address,
+ call_internal1,
+ microblaze_option_override, print_operand): Likewise.
+ * config/microblaze/microblaze.md (call_internal_plt,
+ call_value_intern_plt, call_value_intern): Likewise.
+ * config/arm/aout.h (ASM_OUTPUT_ALIGN): Likewise.
+ * config/iq2000/iq2000.md (call_internal1, call_value_internal1,
+ call_value_multiple_internal1): Likewise.
+ * config/bfin/bfin.c (symbolic_reference_mentioned_p): Likewise.
+
+2021-05-26 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/arc/arc.c (arc_address_cost, arc_print_operand_address,
+ arc_ccfsm_advance, symbolic_reference_mentioned_p,
+ arc_raw_symbolic_reference_mentioned_p): Remove register
+ keyword.
+
+2021-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/100573
+ * omp-low.c: Include omp-offload.h.
+ (create_omp_child_function): If current_function_decl has
+ "omp declare target" attribute and is_gimple_omp_offloaded,
+ remove that attribute from the copy of attribute list and
+ add "omp target entrypoint" attribute instead.
+ (lower_omp_target): Mark .omp_data_sizes.* and .omp_data_kinds.*
+ variables for offloading if in omp_maybe_offloaded_ctx.
+ * omp-offload.c (pass_omp_target_link::execute): Nullify second
+ argument to GOMP_target_data_ext in offloaded code.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/csky/csky.c (csky_can_change_mode_class): Delete.
+ For csky, HF/SF mode use the low bits of VREGS.
+
+2021-05-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gimplify.c (gimplify_decl_expr): Do not clear TREE_READONLY on a
+ DECL which is a reference for OMP.
+
+2021-05-26 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/100751
+ * doc/gcov.texi: Document that __gcov_dump can be called just
+ once and that __gcov_reset resets run-time counters.
+
+2021-05-26 Martin Liska <mliska@suse.cz>
+
+ * doc/install.texi: Port relevant part from install-old.texi
+ and re-generate list of CPUs and systems.
+
+2021-05-26 Martin Liska <mliska@suse.cz>
+
+ * Makefile.in: Remove it.
+ * doc/include/fdl.texi: Update next/previous chapters.
+ * doc/install.texi: Likewise.
+ * doc/install-old.texi: Removed.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/csky/csky.c (ck810_legitimate_index_p): Support
+ "base + index" with DF mode.
+ * config/csky/constraints.md ("Y"): New constraint for memory operands
+ without index register.
+ * config/csky/csky_insn_fpuv2.md (fpuv3_movdf): Use "Y" instead of "m"
+ when mov between memory and general registers, and lower their priority.
+ * config/csky/csky_insn_fpuv3.md (fpuv2_movdf): Likewise.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/csky/csky.c (TARGET_PROMOTE_PROTOTYPES): Delete.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/csky/csky.md (untyped_call): Emit clobber for return
+ registers to mark them used.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * config/csky/csky.md (cskyv2_sextend_ldbs): New.
+
+2021-05-26 Andrew Pinski <apinski@marvell.com>
+
+ * match.pd (x < 0 ? ~y : y): New patterns.
+
+2021-05-26 Andrew Pinski <apinski@marvell.com>
+
+ * match.pd (A?CST1:CST2): Add simplifcations for A?0:+-1, A?+-1:0,
+ A?POW2:0 and A?0:POW2.
+
2021-05-25 Andrew MacLeod <amacleod@redhat.com>
* gimple-range-gori.cc (class logical_stmt_cache): Delete
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index f3c7e4f..328fa3e 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20210526
+20210527
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 14a8c58..0641e60 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,7 @@
+2021-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ * init.c (__gnat_error_handler): Remove register keyword.
+
2021-05-25 Martin Liska <mliska@suse.cz>
* doc/share/conf.py: Fix Sphinx 4.0.x error.
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 08ff8d7..c48e244 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -1989,7 +1989,7 @@ __gnat_error_handler (int sig, siginfo_t *si, void *sc)
anything else.
This mechanism is only need in kernel mode. */
#if !(defined (__RTP__) || defined (VTHREADS)) && ((CPU == PPCE500V2) || (CPU == PPC85XX))
- register unsigned msr;
+ unsigned msr;
/* Read the MSR value */
asm volatile ("mfmsr %0" : "=r" (msr));
/* Force the SPE bit if not set. */
diff --git a/gcc/builtins.c b/gcc/builtins.c
index b0c880d..af1fe49b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -79,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-outof-ssa.h"
#include "attr-fnspec.h"
#include "demangle.h"
+#include "gimple-range.h"
struct target_builtins default_target_builtins;
#if SWITCHABLE_TARGET
@@ -1218,14 +1219,15 @@ check_nul_terminated_array (tree expr, tree src,
wide_int bndrng[2];
if (bound)
{
- if (TREE_CODE (bound) == INTEGER_CST)
- bndrng[0] = bndrng[1] = wi::to_wide (bound);
- else
- {
- value_range_kind rng = get_range_info (bound, bndrng, bndrng + 1);
- if (rng != VR_RANGE)
- return true;
- }
+ value_range r;
+
+ get_global_range_query ()->range_of_expr (r, bound);
+
+ if (r.kind () != VR_RANGE)
+ return true;
+
+ bndrng[0] = r.lower_bound ();
+ bndrng[1] = r.upper_bound ();
if (exact)
{
@@ -3831,9 +3833,12 @@ expand_builtin_strnlen (tree exp, rtx target, machine_mode target_mode)
return NULL_RTX;
wide_int min, max;
- enum value_range_kind rng = get_range_info (bound, &min, &max);
- if (rng != VR_RANGE)
+ value_range r;
+ get_global_range_query ()->range_of_expr (r, bound);
+ if (r.kind () != VR_RANGE)
return NULL_RTX;
+ min = r.lower_bound ();
+ max = r.upper_bound ();
if (!len || TREE_CODE (len) != INTEGER_CST)
{
@@ -3901,7 +3906,16 @@ determine_block_size (tree len, rtx len_rtx,
*probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
if (TREE_CODE (len) == SSA_NAME)
- range_type = get_range_info (len, &min, &max);
+ {
+ value_range r;
+ get_global_range_query ()->range_of_expr (r, len);
+ range_type = r.kind ();
+ if (range_type != VR_UNDEFINED)
+ {
+ min = wi::to_wide (r.min ());
+ max = wi::to_wide (r.max ());
+ }
+ }
if (range_type == VR_RANGE)
{
if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
@@ -4920,8 +4934,8 @@ check_read_access (tree exp, tree src, tree bound /* = NULL_TREE */,
/* If STMT is a call to an allocation function, returns the constant
maximum size of the object allocated by the call represented as
sizetype. If nonnull, sets RNG1[] to the range of the size.
- When nonnull, uses RVALS for range information, otherwise calls
- get_range_info to get it.
+ When nonnull, uses RVALS for range information, otherwise gets global
+ range info.
Returns null when STMT is not a call to a valid allocation function. */
tree
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 7780539..669a818 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2021-05-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR c/100653
+ * c-decl.c (finish_struct): Warn for a union containing an aggregate
+ field with a differing scalar storage order.
+
2021-05-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/99928
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 53b2b5b..3c7b306 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -8853,6 +8853,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
= c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
}
}
+
+ if (TREE_CODE (t) == UNION_TYPE
+ && AGGREGATE_TYPE_P (TREE_TYPE (field))
+ && TYPE_REVERSE_STORAGE_ORDER (t)
+ != TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (field)))
+ warning_at (DECL_SOURCE_LOCATION (field), OPT_Wscalar_storage_order,
+ "type punning toggles scalar storage order");
}
/* Now we have the truly final field list.
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index ec7328e..9153f05 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -2488,8 +2488,8 @@ arc_address_cost (rtx addr, machine_mode, addr_space_t, bool speed)
case PLUS :
{
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
+ rtx plus0 = XEXP (addr, 0);
+ rtx plus1 = XEXP (addr, 1);
if (GET_CODE (plus0) != REG
&& (GET_CODE (plus0) != MULT
@@ -5032,7 +5032,7 @@ arc_print_operand (FILE *file, rtx x, int code)
void
arc_print_operand_address (FILE *file , rtx addr)
{
- register rtx base, index = 0;
+ rtx base, index = 0;
switch (GET_CODE (addr))
{
@@ -5157,7 +5157,7 @@ static void
arc_ccfsm_advance (rtx_insn *insn, struct arc_ccfsm *state)
{
/* BODY will hold the body of INSN. */
- register rtx body;
+ rtx body;
/* This will be 1 if trying to repeat the trick (ie: do the `else' part of
an if/then/else), and things need to be reversed. */
@@ -6130,8 +6130,8 @@ arc_legitimate_pic_addr_p (rtx addr)
static bool
symbolic_reference_mentioned_p (rtx op)
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
return true;
@@ -6141,7 +6141,7 @@ symbolic_reference_mentioned_p (rtx op)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
@@ -6163,8 +6163,8 @@ symbolic_reference_mentioned_p (rtx op)
bool
arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (GET_CODE(op) == UNSPEC)
return false;
@@ -6184,7 +6184,7 @@ arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op, i, j),
diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h
index 9688fb6..25a2812 100644
--- a/gcc/config/arm/aout.h
+++ b/gcc/config/arm/aout.h
@@ -257,7 +257,7 @@
#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
do \
{ \
- register int amount = 1 << (POWER); \
+ int amount = 1 << (POWER); \
\
if (amount == 2) \
fprintf (STREAM, "\t.even\n"); \
diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md
index 133ebe9..0a6ba80 100644
--- a/gcc/config/arm/mve.md
+++ b/gcc/config/arm/mve.md
@@ -464,7 +464,7 @@
;;
;; [vaddvq_s, vaddvq_u])
;;
-(define_insn "mve_vaddvq_<supf><mode>"
+(define_insn "@mve_vaddvq_<supf><mode>"
[
(set (match_operand:SI 0 "s_register_operand" "=Te")
(unspec:SI [(match_operand:MVE_2 1 "s_register_operand" "w")]
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 977adef..6a65733 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -1161,19 +1161,6 @@
DONE;
})
-(define_expand "reduc_plus_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand")
- (match_operand:VQ 1 "s_register_operand")]
- "ARM_HAVE_NEON_<MODE>_ARITH && !BYTES_BIG_ENDIAN"
-{
- rtx step1 = gen_reg_rtx (<V_HALF>mode);
-
- emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
- emit_insn (gen_reduc_plus_scal_<V_half> (operands[0], step1));
-
- DONE;
-})
-
(define_expand "reduc_plus_scal_v2di"
[(match_operand:DI 0 "nonimmediate_operand")
(match_operand:V2DI 1 "s_register_operand")]
diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
index e8b2901..8e35151 100644
--- a/gcc/config/arm/vec-common.md
+++ b/gcc/config/arm/vec-common.md
@@ -539,3 +539,29 @@
emit_insn (gen_mve_vst4q<mode> (operands[0], operands[1]));
DONE;
})
+
+(define_expand "reduc_plus_scal_<mode>"
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQ 1 "s_register_operand")]
+ "ARM_HAVE_<MODE>_ARITH
+ && !(TARGET_HAVE_MVE && FLOAT_MODE_P (<MODE>mode))
+ && !BYTES_BIG_ENDIAN"
+{
+ if (TARGET_NEON)
+ {
+ rtx step1 = gen_reg_rtx (<V_HALF>mode);
+
+ emit_insn (gen_quad_halves_plus<mode> (step1, operands[1]));
+ emit_insn (gen_reduc_plus_scal_<V_half> (operands[0], step1));
+ }
+ else
+ {
+ /* vaddv generates a 32 bits accumulator. */
+ rtx op0 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_mve_vaddvq (VADDVQ_S, <MODE>mode, op0, operands[1]));
+ emit_move_insn (operands[0], gen_lowpart (<V_elem>mode, op0));
+ }
+
+ DONE;
+})
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index a000b7a..698dd87 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -1773,8 +1773,8 @@ function_arg_regno_p (int n)
int
symbolic_reference_mentioned_p (rtx op)
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
return 1;
@@ -1784,7 +1784,7 @@ symbolic_reference_mentioned_p (rtx op)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
index c0e42a2..e55821f 100644
--- a/gcc/config/csky/csky.c
+++ b/gcc/config/csky/csky.c
@@ -608,9 +608,6 @@ csky_default_logical_op_non_short_circuit (void)
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P csky_modes_tieable_p
-#undef TARGET_CAN_CHANGE_MODE_CLASS
-#define TARGET_CAN_CHANGE_MODE_CLASS csky_can_change_mode_class
-
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE csky_conditional_register_usage
@@ -2370,19 +2367,6 @@ csky_modes_tieable_p (machine_mode mode1, machine_mode mode2)
&& (mode1 == DFmode || mode2 == DFmode));
}
-/* Implement TARGET_CAN_CHANGE_MODE_CLASS.
- V_REG registers can't do subreg as all values are reformatted to
- internal precision. */
-
-static bool
-csky_can_change_mode_class (machine_mode from,
- machine_mode to,
- reg_class_t rclass)
-{
- return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to)
- || !reg_classes_intersect_p (V_REGS, rclass));
-}
-
/* Implement TARGET_CLASS_LIKELY_SPILLED_P.
We need to define this for MINI_REGS when we only use r0 - r7.
Otherwise we can end up using r0-r4 for function arguments, and don't
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index b60daa7..f248294 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -1394,7 +1394,7 @@ epiphany_print_operand (FILE *file, rtx x, int code)
static void
epiphany_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
{
- register rtx base, index = 0;
+ rtx base, index = 0;
int offset = 0;
switch (GET_CODE (addr))
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 28e6113..04649b4 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22190,12 +22190,15 @@ ix86_autovectorize_vector_modes (vector_modes *modes, bool all)
modes->safe_push (V16QImode);
modes->safe_push (V32QImode);
}
- else if (TARGET_MMX_WITH_SSE)
+ else if (TARGET_SSE2)
modes->safe_push (V16QImode);
if (TARGET_MMX_WITH_SSE)
modes->safe_push (V8QImode);
+ if (TARGET_SSE2)
+ modes->safe_push (V4QImode);
+
return 0;
}
diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md
index fd25e05..4637703 100644
--- a/gcc/config/iq2000/iq2000.md
+++ b/gcc/config/iq2000/iq2000.md
@@ -1553,7 +1553,7 @@
""
"*
{
- register rtx target = operands[0];
+ rtx target = operands[0];
if (GET_CODE (target) == CONST_INT)
return \"li\\t%@,%0\\n\\tjalr\\t%2,%@\";
@@ -1641,7 +1641,7 @@
""
"*
{
- register rtx target = operands[1];
+ rtx target = operands[1];
if (GET_CODE (target) == CONST_INT)
return \"li\\t%@,%1\\n\\tjalr\\t%3,%@\";
@@ -1678,7 +1678,7 @@
""
"*
{
- register rtx target = operands[1];
+ rtx target = operands[1];
if (GET_CODE (target) == CONST_INT)
return \"li\\t%@,%1\\n\\tjalr\\t%4,%@\";
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index b444db1..6e8f367 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -991,7 +991,7 @@ static rtx
microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED)
{
- register rtx xinsn = x, result;
+ rtx xinsn = x, result;
if (GET_CODE (xinsn) == CONST
&& flag_pic && pic_address_needs_scratch (xinsn))
@@ -1011,10 +1011,10 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (xinsn) == PLUS)
{
- register rtx xplus0 = XEXP (xinsn, 0);
- register rtx xplus1 = XEXP (xinsn, 1);
- register enum rtx_code code0 = GET_CODE (xplus0);
- register enum rtx_code code1 = GET_CODE (xplus1);
+ rtx xplus0 = XEXP (xinsn, 0);
+ rtx xplus1 = XEXP (xinsn, 1);
+ enum rtx_code code0 = GET_CODE (xplus0);
+ enum rtx_code code1 = GET_CODE (xplus1);
if (code0 != REG && code1 == REG)
{
@@ -1736,9 +1736,9 @@ microblaze_version_to_int (const char *version)
static void
microblaze_option_override (void)
{
- register int i, start;
- register int regno;
- register machine_mode mode;
+ int i, start;
+ int regno;
+ machine_mode mode;
int ver;
microblaze_section_threshold = (global_options_set.x_g_switch_value
@@ -1891,11 +1891,11 @@ microblaze_option_override (void)
for (mode = VOIDmode;
mode != MAX_MACHINE_MODE; mode = (machine_mode) ((int) mode + 1))
{
- register int size = GET_MODE_SIZE (mode);
+ int size = GET_MODE_SIZE (mode);
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
- register int ok;
+ int ok;
if (mode == CCmode)
{
@@ -2267,7 +2267,7 @@ microblaze_initial_elimination_offset (int from, int to)
void
print_operand (FILE * file, rtx op, int letter)
{
- register enum rtx_code code;
+ enum rtx_code code;
if (PRINT_OPERAND_PUNCT_VALID_P (letter))
{
@@ -2406,7 +2406,7 @@ print_operand (FILE * file, rtx op, int letter)
else if (code == REG || code == SUBREG)
{
- register int regnum;
+ int regnum;
if (code == REG)
regnum = REGNO (op);
@@ -2431,7 +2431,7 @@ print_operand (FILE * file, rtx op, int letter)
rtx mem_reg = XEXP (op, 0);
if (GET_CODE (mem_reg) == REG)
{
- register int regnum = REGNO (mem_reg);
+ int regnum = REGNO (mem_reg);
fprintf (file, "%s", reg_names[regnum]);
}
}
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 472ef4c..6d77752 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -2107,8 +2107,8 @@
(use (reg:SI R_GOT))]
"flag_pic"
{
- register rtx target2 = gen_rtx_REG (Pmode,
- GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ rtx target2
+ = gen_rtx_REG (Pmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
gen_rtx_CLOBBER (VOIDmode, target2);
return "brlid\tr15,%0\;%#";
}
@@ -2122,9 +2122,9 @@
(clobber (reg:SI R_SR))]
""
{
- register rtx target = operands[0];
- register rtx target2 = gen_rtx_REG (Pmode,
- GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ rtx target = operands[0];
+ rtx target2
+ = gen_rtx_REG (Pmode, GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
if (GET_CODE (target) == SYMBOL_REF) {
if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) {
gen_rtx_CLOBBER (VOIDmode, target2);
@@ -2216,7 +2216,8 @@
(use (match_operand:SI 4 "register_operand"))]
"flag_pic"
{
- register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ rtx target2
+ = gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
gen_rtx_CLOBBER (VOIDmode,target2);
return "brlid\tr15,%1\;%#";
@@ -2232,8 +2233,9 @@
(clobber (match_operand:SI 3 "register_operand" "=d"))]
""
{
- register rtx target = operands[1];
- register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ rtx target = operands[1];
+ rtx target2
+ = gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
if (GET_CODE (target) == SYMBOL_REF)
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1cbd043..7c13a6e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,27 @@
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/100502
+ * typeck.c (finish_class_member_access_expr): Disable ahead
+ of time access checking during the member lookup.
+
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/100368
+ * tree.c (build_target_expr_with_type): Don't call force_rvalue
+ on CALL_EXPR initializer. Simplify now that bot_manip is no
+ longer a caller.
+ (bot_manip): Use force_target_expr instead of
+ build_target_expr_with_type.
+
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97420
+ * cvt.c (noexcept_conv_p): Remove redundant checks and simplify.
+ (fnptr_conv_p): Don't call non_reference. Use INDIRECT_TYPE_P
+ instead of TYPE_PTR_P.
+ * pt.c (convert_nontype_argument_function): Look through
+ implicit INDIRECT_REFs before calling strip_fnptr_conv.
+
2021-05-25 Jakub Jelinek <jakub@redhat.com>
PR c++/100666
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7fa6e8d..330d658 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -2081,7 +2081,8 @@ can_convert_tx_safety (tree to, tree from)
&& same_type_p (to, tx_unsafe_fn_variant (from)));
}
-/* Return true iff FROM can convert to TO by dropping noexcept. */
+/* Return true iff FROM can convert to TO by dropping noexcept.
+ This is just a subroutine of of fnptr_conv_p. */
static bool
noexcept_conv_p (tree to, tree from)
@@ -2089,30 +2090,15 @@ noexcept_conv_p (tree to, tree from)
if (!flag_noexcept_type)
return false;
- tree t = non_reference (to);
- tree f = from;
- if (TYPE_PTRMEMFUNC_P (t)
- && TYPE_PTRMEMFUNC_P (f))
- {
- t = TYPE_PTRMEMFUNC_FN_TYPE (t);
- f = TYPE_PTRMEMFUNC_FN_TYPE (f);
- }
- if (TYPE_PTR_P (t)
- && TYPE_PTR_P (f))
- {
- t = TREE_TYPE (t);
- f = TREE_TYPE (f);
- }
- tree_code code = TREE_CODE (f);
- if (TREE_CODE (t) != code)
+ if (TREE_CODE (to) != TREE_CODE (from))
return false;
- if (code != FUNCTION_TYPE && code != METHOD_TYPE)
+ if (!FUNC_OR_METHOD_TYPE_P (from))
return false;
- if (!type_throw_all_p (t)
- || type_throw_all_p (f))
+ if (!type_throw_all_p (to)
+ || type_throw_all_p (from))
return false;
- tree v = build_exception_variant (f, NULL_TREE);
- return same_type_p (t, v);
+ tree v = build_exception_variant (from, NULL_TREE);
+ return same_type_p (to, v);
}
/* Return true iff FROM can convert to TO by a function pointer conversion. */
@@ -2120,7 +2106,7 @@ noexcept_conv_p (tree to, tree from)
bool
fnptr_conv_p (tree to, tree from)
{
- tree t = non_reference (to);
+ tree t = to;
tree f = from;
if (TYPE_PTRMEMFUNC_P (t)
&& TYPE_PTRMEMFUNC_P (f))
@@ -2128,8 +2114,8 @@ fnptr_conv_p (tree to, tree from)
t = TYPE_PTRMEMFUNC_FN_TYPE (t);
f = TYPE_PTRMEMFUNC_FN_TYPE (f);
}
- if (TYPE_PTR_P (t)
- && TYPE_PTR_P (f))
+ if (INDIRECT_TYPE_P (t)
+ && INDIRECT_TYPE_P (f))
{
t = TREE_TYPE (t);
f = TREE_TYPE (f);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 99a9ee5..f3fa9c1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6622,7 +6622,10 @@ convert_nontype_argument_function (tree type, tree expr,
if (value_dependent_expression_p (fn))
goto accept;
- fn_no_ptr = strip_fnptr_conv (fn);
+ fn_no_ptr = fn;
+ if (REFERENCE_REF_P (fn_no_ptr))
+ fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
+ fn_no_ptr = strip_fnptr_conv (fn_no_ptr);
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
if (BASELINK_P (fn_no_ptr))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 72f498f..372d89f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -843,21 +843,22 @@ tree
build_target_expr_with_type (tree init, tree type, tsubst_flags_t complain)
{
gcc_assert (!VOID_TYPE_P (type));
+ gcc_assert (!VOID_TYPE_P (TREE_TYPE (init)));
if (TREE_CODE (init) == TARGET_EXPR
|| init == error_mark_node)
return init;
else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
- && !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
- && TREE_CODE (init) != VA_ARG_EXPR)
- /* We need to build up a copy constructor call. A void initializer
- means we're being called from bot_manip. COND_EXPR is a special
+ && TREE_CODE (init) != VA_ARG_EXPR
+ && TREE_CODE (init) != CALL_EXPR)
+ /* We need to build up a copy constructor call. COND_EXPR is a special
case because we already have copies on the arms and we don't want
another one here. A CONSTRUCTOR is aggregate initialization, which
is handled separately. A VA_ARG_EXPR is magic creation of an
- aggregate; there's no additional work to be done. */
+ aggregate; there's no additional work to be done. A CALL_EXPR
+ already creates a prvalue. */
return force_rvalue (init, complain);
return force_target_expr (type, init, complain);
@@ -3112,8 +3113,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
}
else
- u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
- tf_warning_or_error);
+ u = force_target_expr (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t);
TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 703ddd3..3df4117 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3201,9 +3201,19 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
{
/* Look up the member. */
access_failure_info afi;
+ if (processing_template_decl)
+ /* Even though this class member access expression is at this
+ point not dependent, the member itself may be dependent, and
+ we must not potentially push a access check for a dependent
+ member onto TI_DEFERRED_ACCESS_CHECKS. So don't check access
+ ahead of time here; we're going to redo this member lookup at
+ instantiation time anyway. */
+ push_deferring_access_checks (dk_no_check);
member = lookup_member (access_path, name, /*protect=*/1,
/*want_type=*/false, complain,
&afi);
+ if (processing_template_decl)
+ pop_deferring_access_checks ();
afi.maybe_suggest_accessor (TYPE_READONLY (object_type));
if (member == NULL_TREE)
{
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 3ddeb0d..bfe9c21 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8586,8 +8586,9 @@ The second case is nevertheless allowed to be able to perform a block copy
from or to the array.
Moreover, the use of type punning or aliasing to toggle the storage order
-is not supported; that is to say, a given scalar object cannot be accessed
-through distinct types that assign a different storage order to it.
+is not supported; that is to say, if a given scalar object can be accessed
+through distinct types that assign a different storage order to it, then the
+behavior is undefined.
@item transparent_union
@cindex @code{transparent_union} type attribute
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index cf309874..16c6a3b 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1740,6 +1740,12 @@ circumstances.
@item vect_variable_length
Target has variable-length vectors.
+@item vect64
+Target supports vectors of 64 bits.
+
+@item vect32
+Target supports vectors of 32 bits.
+
@item vect_widen_sum_hi_to_si
Target supports a vector widening summation of @code{short} operands
into @code{int} results, or can promote (unpack) from @code{short}
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index d088187..33d64bf 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "vec-perm-indices.h"
#include "asan.h"
+#include "gimple-range.h"
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
@@ -10686,7 +10687,12 @@ expr_not_equal_to (tree t, const wide_int &w)
case SSA_NAME:
if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
return false;
- get_range_info (t, vr);
+
+ if (cfun)
+ get_range_query (cfun)->range_of_expr (vr, t);
+ else
+ get_global_range_query ()->range_of_expr (vr, t);
+
if (!vr.undefined_p ()
&& !vr.contains_p (wide_int_to_tree (TREE_TYPE (t), w)))
return true;
diff --git a/gcc/function.c b/gcc/function.c
index fc7b147..6757695 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -82,6 +82,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "options.h"
#include "function-abi.h"
+#include "value-range.h"
+#include "gimple-range.h"
/* So we can assign to cfun in this file. */
#undef cfun
@@ -4856,6 +4858,8 @@ allocate_struct_function (tree fndecl, bool abstract_p)
binding annotations among them. */
cfun->debug_nonbind_markers = lang_hooks.emits_begin_stmt
&& MAY_HAVE_DEBUG_MARKER_STMTS;
+
+ cfun->x_range_query = &global_ranges;
}
/* This is like allocate_struct_function, but pushes a new cfun for FNDECL
diff --git a/gcc/function.h b/gcc/function.h
index 66cfa97..0db5177 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -157,6 +157,7 @@ struct GTY(()) rtl_eh {
struct gimple_df;
struct call_site_record_d;
struct dw_fde_node;
+class range_query;
struct GTY(()) varasm_status {
/* If we're using a per-function constant pool, this is it. */
@@ -309,6 +310,11 @@ struct GTY(()) function {
debugging is enabled. */
struct dw_fde_node *fde;
+ /* Range query mechanism for functions. The default is to pick up
+ global ranges. If a pass wants on-demand ranges OTOH, it must
+ call enable/disable_ranger(). */
+ range_query * GTY ((skip)) x_range_query;
+
/* Last statement uid. */
int last_stmt_uid;
@@ -712,4 +718,15 @@ extern const char *current_function_name (void);
extern void used_types_insert (tree);
+/* Returns the currently active range access class. When there is no active
+ range class, global ranges are used. */
+
+inline range_query *
+get_range_query (struct function *fun)
+{
+ return fun->x_range_query;
+}
+
+extern range_query *get_global_range_query ();
+
#endif /* GCC_FUNCTION_H */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 68717cf..eaf0fb7 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -873,7 +873,12 @@ size_must_be_zero_p (tree size)
value_range valid_range (build_int_cst (type, 0),
wide_int_to_tree (type, ssize_max));
value_range vr;
- get_range_info (size, vr);
+ if (cfun)
+ get_range_query (cfun)->range_of_expr (vr, size);
+ else
+ get_global_range_query ()->range_of_expr (vr, size);
+ if (vr.undefined_p ())
+ vr.set_varying (TREE_TYPE (size));
vr.intersect (&valid_range);
return vr.zero_p ();
}
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index b084a3157..7112c116 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "dbgcnt.h"
#include "tm.h"
+#include "gimple-range.h"
/* Forward declarations of the private auto-generated matchers.
They expect valueized operands in canonical order and do not
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 0ef01e6..c9c0a66 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
#include "cfgloop.h"
+#include "gimple-range.h"
/* Disable warnings about quoting issues in the pp_xxx calls below
that (intentionally) don't follow GCC diagnostic conventions. */
@@ -2263,8 +2264,17 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
&& SSA_NAME_RANGE_INFO (node))
{
wide_int min, max, nonzero_bits;
- value_range_kind range_type = get_range_info (node, &min, &max);
+ value_range r;
+ get_global_range_query ()->range_of_expr (r, node);
+ value_range_kind range_type = r.kind ();
+ if (!r.undefined_p ())
+ {
+ min = wi::to_wide (r.min ());
+ max = wi::to_wide (r.max ());
+ }
+
+ // FIXME: Use irange::dump() instead.
if (range_type == VR_VARYING)
pp_printf (buffer, "# RANGE VR_VARYING");
else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index 3969c4d..889cac1 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -384,7 +384,6 @@ block_range_cache::dump (FILE *f, basic_block bb, bool print_varying)
ssa_global_cache::ssa_global_cache ()
{
m_tab.create (0);
- m_tab.safe_grow_cleared (num_ssa_names);
m_irange_allocator = new irange_allocator;
}
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index a4c4bf5..c51e6ce 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -176,6 +176,8 @@ range_def_chain::register_dependency (tree name, tree dep, basic_block bb)
return;
unsigned v = SSA_NAME_VERSION (name);
+ if (v >= m_def_chain.length ())
+ m_def_chain.safe_grow_cleared (num_ssa_names + 1);
struct rdc &src = m_def_chain[v];
gimple *def_stmt = SSA_NAME_DEF_STMT (dep);
unsigned dep_v = SSA_NAME_VERSION (dep);
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index e2d24d6..e351a84 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -1440,3 +1440,129 @@ trace_ranger::range_of_expr (irange &r, tree name, gimple *s)
return trailer (idx, "range_of_expr", res, name, r);
}
+
+// Return the legacy global range for NAME if it has one, otherwise
+// return VARYING.
+
+static void
+get_range_global (irange &r, tree name)
+{
+ tree type = TREE_TYPE (name);
+
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ {
+ tree sym = SSA_NAME_VAR (name);
+ // Adapted from vr_values::get_lattice_entry().
+ // Use a range from an SSA_NAME's available range.
+ if (TREE_CODE (sym) == PARM_DECL)
+ {
+ // Try to use the "nonnull" attribute to create ~[0, 0]
+ // anti-ranges for pointers. Note that this is only valid with
+ // default definitions of PARM_DECLs.
+ if (POINTER_TYPE_P (type)
+ && ((cfun && nonnull_arg_p (sym)) || get_ptr_nonnull (name)))
+ r.set_nonzero (type);
+ else if (INTEGRAL_TYPE_P (type))
+ {
+ get_range_info (name, r);
+ if (r.undefined_p ())
+ r.set_varying (type);
+ }
+ else
+ r.set_varying (type);
+ }
+ // If this is a local automatic with no definition, use undefined.
+ else if (TREE_CODE (sym) != RESULT_DECL)
+ r.set_undefined ();
+ else
+ r.set_varying (type);
+ }
+ else if (!POINTER_TYPE_P (type) && SSA_NAME_RANGE_INFO (name))
+ {
+ get_range_info (name, r);
+ if (r.undefined_p ())
+ r.set_varying (type);
+ }
+ else if (POINTER_TYPE_P (type) && SSA_NAME_PTR_INFO (name))
+ {
+ if (get_ptr_nonnull (name))
+ r.set_nonzero (type);
+ else
+ r.set_varying (type);
+ }
+ else
+ r.set_varying (type);
+}
+
+// ?? Like above, but only for default definitions of NAME. This is
+// so VRP passes using ranger do not start with known ranges,
+// otherwise we'd eliminate builtin_unreachables too early because of
+// inlining.
+//
+// Without this restriction, the test in g++.dg/tree-ssa/pr61034.C has
+// all of its unreachable calls removed too early. We should
+// investigate whether we should just adjust the test above.
+
+value_range
+gimple_range_global (tree name)
+{
+ gcc_checking_assert (gimple_range_ssa_p (name));
+ tree type = TREE_TYPE (name);
+
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ {
+ value_range vr;
+ get_range_global (vr, name);
+ return vr;
+ }
+ return value_range (type);
+}
+
+// ----------------------------------------------
+// global_range_query implementation.
+
+global_range_query global_ranges;
+
+// Like get_range_query, but for accessing global ranges.
+
+range_query *
+get_global_range_query ()
+{
+ return &global_ranges;
+}
+
+bool
+global_range_query::range_of_expr (irange &r, tree expr, gimple *)
+{
+ tree type = TREE_TYPE (expr);
+
+ if (!irange::supports_type_p (type) || !gimple_range_ssa_p (expr))
+ return get_tree_range (r, expr);
+
+ get_range_global (r, expr);
+
+ return true;
+}
+
+gimple_ranger *
+enable_ranger (struct function *fun)
+{
+ gimple_ranger *r;
+
+ if (param_evrp_mode & EVRP_MODE_TRACE)
+ r = new trace_ranger;
+ else
+ r = new gimple_ranger;
+
+ fun->x_range_query = r;
+
+ return r;
+}
+
+void
+disable_ranger (struct function *fun)
+{
+ delete fun->x_range_query;
+
+ fun->x_range_query = &global_ranges;
+}
diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h
index 707dcfe..23734c6 100644
--- a/gcc/gimple-range.h
+++ b/gcc/gimple-range.h
@@ -65,7 +65,7 @@ public:
virtual void range_on_entry (irange &r, basic_block bb, tree name);
virtual void range_on_exit (irange &r, basic_block bb, tree name);
void export_global_ranges ();
- void dump (FILE *f);
+ virtual void dump (FILE *f) OVERRIDE;
void dump_bb (FILE *f, basic_block bb);
protected:
bool fold_range_internal (irange &r, gimple *s, tree name);
@@ -227,50 +227,6 @@ range_compatible_p (tree type1, tree type2)
&& TYPE_SIGN (type1) == TYPE_SIGN (type2));
}
-// Return the legacy GCC global range for NAME if it has one, otherwise
-// return VARYING.
-
-static inline value_range
-gimple_range_global (tree name)
-{
- gcc_checking_assert (gimple_range_ssa_p (name));
- tree type = TREE_TYPE (name);
-
- if (SSA_NAME_IS_DEFAULT_DEF (name))
- {
- tree sym = SSA_NAME_VAR (name);
- // Adapted from vr_values::get_lattice_entry().
- // Use a range from an SSA_NAME's available range.
- if (TREE_CODE (sym) == PARM_DECL)
- {
- // Try to use the "nonnull" attribute to create ~[0, 0]
- // anti-ranges for pointers. Note that this is only valid with
- // default definitions of PARM_DECLs.
- if (POINTER_TYPE_P (type)
- && (nonnull_arg_p (sym) || get_ptr_nonnull (name)))
- {
- value_range r;
- r.set_nonzero (type);
- return r;
- }
- else if (INTEGRAL_TYPE_P (type))
- {
- value_range r;
- get_range_info (name, r);
- if (r.undefined_p ())
- r.set_varying (type);
- return r;
- }
- }
- // If this is a local automatic with no definition, use undefined.
- else if (TREE_CODE (sym) != RESULT_DECL)
- return value_range ();
- }
- // Otherwise return range for the type.
- return value_range (type);
-}
-
-
// This class overloads the ranger routines to provide tracing facilties
// Entry and exit values to each of the APIs is placed in the dumpfile.
@@ -296,4 +252,18 @@ private:
// Flag to enable debugging the various internal Caches.
#define DEBUG_RANGE_CACHE (dump_file && (param_evrp_mode & EVRP_MODE_DEBUG))
+// Global ranges for SSA names using SSA_NAME_RANGE_INFO.
+
+class global_range_query : public range_query
+{
+public:
+ bool range_of_expr (irange &r, tree expr, gimple * = NULL) OVERRIDE;
+};
+
+extern global_range_query global_ranges;
+extern value_range gimple_range_global (tree name);
+
+extern gimple_ranger *enable_ranger (struct function *);
+extern void disable_ranger (struct function *);
+
#endif // GCC_GIMPLE_RANGE_STMT_H
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 5f566ae..118d103 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -60,7 +60,7 @@ public:
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
- m_range_analyzer.dump_all_value_ranges (dump_file);
+ m_range_analyzer.dump (dump_file);
fprintf (dump_file, "\n");
}
}
@@ -117,11 +117,8 @@ class rvrp_folder : public substitute_and_fold_engine
public:
rvrp_folder () : substitute_and_fold_engine (), m_simplifier ()
- {
- if (param_evrp_mode & EVRP_MODE_TRACE)
- m_ranger = new trace_ranger ();
- else
- m_ranger = new gimple_ranger ();
+ {
+ m_ranger = enable_ranger (cfun);
m_simplifier.set_range_query (m_ranger);
}
@@ -129,7 +126,9 @@ public:
{
if (dump_file && (dump_flags & TDF_DETAILS))
m_ranger->dump (dump_file);
- delete m_ranger;
+
+ m_ranger->export_global_ranges ();
+ disable_ranger (cfun);
}
tree value_of_expr (tree name, gimple *s = NULL) OVERRIDE
@@ -175,10 +174,7 @@ class hybrid_folder : public evrp_folder
public:
hybrid_folder (bool evrp_first)
{
- if (param_evrp_mode & EVRP_MODE_TRACE)
- m_ranger = new trace_ranger ();
- else
- m_ranger = new gimple_ranger ();
+ m_ranger = enable_ranger (cfun);
if (evrp_first)
{
@@ -196,7 +192,9 @@ public:
{
if (dump_file && (dump_flags & TDF_DETAILS))
m_ranger->dump (dump_file);
- delete m_ranger;
+
+ m_ranger->export_global_ranges ();
+ disable_ranger (cfun);
}
bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index e9a24d4..72480f1 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -165,7 +165,7 @@ adjusted_warn_limit (bool idx)
// call was created by the gimplifier for a VLA.
static class alloca_type_and_limit
-alloca_call_type (range_query &query, gimple *stmt, bool is_vla)
+alloca_call_type (gimple *stmt, bool is_vla)
{
gcc_assert (gimple_alloca_call_p (stmt));
tree len = gimple_call_arg (stmt, 0);
@@ -217,7 +217,7 @@ alloca_call_type (range_query &query, gimple *stmt, bool is_vla)
int_range_max r;
if (warn_limit_specified_p (is_vla)
&& TREE_CODE (len) == SSA_NAME
- && query.range_of_expr (r, len, stmt)
+ && get_range_query (cfun)->range_of_expr (r, len, stmt)
&& !r.varying_p ())
{
// The invalid bits are anything outside of [0, MAX_SIZE].
@@ -256,7 +256,7 @@ in_loop_p (gimple *stmt)
unsigned int
pass_walloca::execute (function *fun)
{
- gimple_ranger ranger;
+ gimple_ranger *ranger = enable_ranger (fun);
basic_block bb;
FOR_EACH_BB_FN (bb, fun)
{
@@ -290,7 +290,7 @@ pass_walloca::execute (function *fun)
continue;
class alloca_type_and_limit t
- = alloca_call_type (ranger, stmt, is_vla);
+ = alloca_call_type (stmt, is_vla);
unsigned HOST_WIDE_INT adjusted_alloca_limit
= adjusted_warn_limit (false);
@@ -383,6 +383,8 @@ pass_walloca::execute (function *fun)
}
}
}
+ ranger->export_global_ranges ();
+ disable_ranger (fun);
return 0;
}
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index ad37f20..c8c9f95 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -349,7 +349,13 @@ builtin_memref::extend_offset_range (tree offset)
/* There is a global version here because
check_bounds_or_overlap may be called from gimple
fold during gimple lowering. */
- rng = get_range_info (offset, &min, &max);
+ get_range_query (cfun)->range_of_expr (vr, offset, stmt);
+ rng = vr.kind ();
+ if (!vr.undefined_p ())
+ {
+ min = wi::to_wide (vr.min ());
+ max = wi::to_wide (vr.max ());
+ }
}
if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
{
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index ed825a9..54bf59a 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1829,7 +1829,7 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
gimplify_and_add (init, seq_p);
ggc_free (init);
/* Clear TREE_READONLY if we really have an initialization. */
- if (!DECL_INITIAL (decl))
+ if (!DECL_INITIAL (decl) && !omp_is_reference (decl))
TREE_READONLY (decl) = 0;
}
else
diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c
index eebf2e0..99ea032 100644
--- a/gcc/graphite-sese-to-poly.c
+++ b/gcc/graphite-sese-to-poly.c
@@ -418,13 +418,18 @@ static void
add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter)
{
tree type = TREE_TYPE (parameter);
+ value_range r;
wide_int min, max;
gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
if (INTEGRAL_TYPE_P (type)
- && get_range_info (parameter, &min, &max) == VR_RANGE)
- ;
+ && get_range_query (cfun)->range_of_expr (r, parameter)
+ && !r.undefined_p ())
+ {
+ min = r.lower_bound ();
+ max = r.upper_bound ();
+ }
else
{
min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index d209a52..f06c2711 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "ssa-iterators.h"
#include "explow.h"
#include "rtl-iter.h"
+#include "gimple-range.h"
/* The names of each internal function, indexed by function number. */
const char *const internal_fn_name_array[] = {
@@ -680,8 +681,9 @@ get_min_precision (tree arg, signop sign)
}
if (TREE_CODE (arg) != SSA_NAME)
return prec + (orig_sign != sign);
- wide_int arg_min, arg_max;
- while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+ value_range r;
+ while (!get_global_range_query ()->range_of_expr (r, arg)
+ || r.kind () != VR_RANGE)
{
gimple *g = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (g)
@@ -709,14 +711,14 @@ get_min_precision (tree arg, signop sign)
}
if (sign == TYPE_SIGN (TREE_TYPE (arg)))
{
- int p1 = wi::min_precision (arg_min, sign);
- int p2 = wi::min_precision (arg_max, sign);
+ int p1 = wi::min_precision (r.lower_bound (), sign);
+ int p2 = wi::min_precision (r.upper_bound (), sign);
p1 = MAX (p1, p2);
prec = MIN (prec, p1);
}
- else if (sign == UNSIGNED && !wi::neg_p (arg_min, SIGNED))
+ else if (sign == UNSIGNED && !wi::neg_p (r.lower_bound (), SIGNED))
{
- int p = wi::min_precision (arg_max, UNSIGNED);
+ int p = wi::min_precision (r.upper_bound (), UNSIGNED);
prec = MIN (prec, p);
}
return prec + (orig_sign != sign);
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 4e5be81..95d2875 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -85,6 +85,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "tree-into-ssa.h"
#include "symtab-clones.h"
+#include "gimple-range.h"
/* Summaries. */
fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
@@ -1687,8 +1688,14 @@ set_switch_stmt_execution_predicate (struct ipa_func_body_info *fbi,
int bound_limit = opt_for_fn (fbi->node->decl,
param_ipa_max_switch_predicate_bounds);
int bound_count = 0;
- wide_int vr_wmin, vr_wmax;
- value_range_kind vr_type = get_range_info (op, &vr_wmin, &vr_wmax);
+ value_range vr;
+
+ get_range_query (cfun)->range_of_expr (vr, op);
+ if (vr.undefined_p ())
+ vr.set_varying (TREE_TYPE (op));
+ value_range_kind vr_type = vr.kind ();
+ wide_int vr_wmin = wi::to_wide (vr.min ());
+ wide_int vr_wmax = wi::to_wide (vr.max ());
FOR_EACH_EDGE (e, ei, bb->succs)
{
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 0591ef1..f74d2e1 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see
#include "options.h"
#include "symtab-clones.h"
#include "attr-fnspec.h"
+#include "gimple-range.h"
/* Function summary where the parameter infos are actually stored. */
ipa_node_params_t *ipa_node_params_sum = NULL;
@@ -2237,6 +2238,7 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
gcall *call = cs->call_stmt;
int n, arg_num = gimple_call_num_args (call);
bool useful_context = false;
+ value_range vr;
if (arg_num == 0 || args->jump_functions)
return;
@@ -2274,7 +2276,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
if (TREE_CODE (arg) == SSA_NAME
&& param_type
- && get_ptr_nonnull (arg))
+ && get_range_query (cfun)->range_of_expr (vr, arg)
+ && vr.nonzero_p ())
addr_nonzero = true;
else if (tree_single_nonzero_warnv_p (arg, &strict_overflow))
addr_nonzero = true;
@@ -2289,19 +2292,14 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
}
else
{
- wide_int min, max;
- value_range_kind kind;
if (TREE_CODE (arg) == SSA_NAME
&& param_type
- && (kind = get_range_info (arg, &min, &max))
- && (kind == VR_RANGE || kind == VR_ANTI_RANGE))
+ && get_range_query (cfun)->range_of_expr (vr, arg)
+ && !vr.undefined_p ())
{
value_range resvr;
- value_range tmpvr (wide_int_to_tree (TREE_TYPE (arg), min),
- wide_int_to_tree (TREE_TYPE (arg), max),
- kind);
range_fold_unary_expr (&resvr, NOP_EXPR, param_type,
- &tmpvr, TREE_TYPE (arg));
+ &vr, TREE_TYPE (arg));
if (!resvr.undefined_p () && !resvr.varying_p ())
ipa_set_jfunc_vr (jfunc, &resvr);
else
diff --git a/gcc/match.pd b/gcc/match.pd
index dd73081..b60e270 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -663,11 +663,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(with
{
bool overflowed = true;
- wide_int wmin0, wmax0, wmin1, wmax1;
+ value_range vr0, vr1;
if (INTEGRAL_TYPE_P (type)
- && get_range_info (@0, &wmin0, &wmax0) == VR_RANGE
- && get_range_info (@1, &wmin1, &wmax1) == VR_RANGE)
+ && get_global_range_query ()->range_of_expr (vr0, @0)
+ && get_global_range_query ()->range_of_expr (vr1, @1)
+ && vr0.kind () == VR_RANGE
+ && vr1.kind () == VR_RANGE)
{
+ wide_int wmin0 = vr0.lower_bound ();
+ wide_int wmax0 = vr0.upper_bound ();
+ wide_int wmin1 = vr1.lower_bound ();
+ wide_int wmax1 = vr1.upper_bound ();
/* If the multiplication can't overflow/wrap around, then
it can be optimized too. */
wi::overflow_type min_ovf, max_ovf;
@@ -2509,9 +2515,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
= wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type),
TYPE_SIGN (inner_type));
- wide_int wmin0, wmax0;
- if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE)
+ value_range vr;
+ if (get_global_range_query ()->range_of_expr (vr, @0)
+ && vr.kind () == VR_RANGE)
{
+ wide_int wmin0 = vr.lower_bound ();
+ wide_int wmax0 = vr.upper_bound ();
wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf);
wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf);
}
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index e00051b..2d5cdf6 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-pretty-print.h"
#include "stringpool.h"
#include "attribs.h"
+#include "omp-offload.h"
/* Lowering of OMP parallel and workshare constructs proceeds in two
phases. The first phase scans the function looking for OMP statements
@@ -1944,16 +1945,25 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
g->have_offload = true;
}
- if (cgraph_node::get_create (decl)->offloadable
- && !lookup_attribute ("omp declare target",
- DECL_ATTRIBUTES (current_function_decl)))
+ if (cgraph_node::get_create (decl)->offloadable)
{
const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
? "omp target entrypoint"
: "omp declare target");
- DECL_ATTRIBUTES (decl)
- = tree_cons (get_identifier (target_attr),
- NULL_TREE, DECL_ATTRIBUTES (decl));
+ if (lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (current_function_decl)))
+ {
+ if (is_gimple_omp_offloaded (ctx->stmt))
+ DECL_ATTRIBUTES (decl)
+ = remove_attribute ("omp declare target",
+ copy_list (DECL_ATTRIBUTES (decl)));
+ else
+ target_attr = NULL;
+ }
+ if (target_attr)
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (get_identifier (target_attr),
+ NULL_TREE, DECL_ATTRIBUTES (decl));
}
t = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -12960,6 +12970,23 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_build_assign (TREE_VEC_ELT (t, i),
clobber));
}
+ else if (omp_maybe_offloaded_ctx (ctx->outer))
+ {
+ tree id = get_identifier ("omp declare target");
+ tree decl = TREE_VEC_ELT (t, i);
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
+ varpool_node *node = varpool_node::get (decl);
+ if (node)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ {
+ g->have_offload = true;
+ vec_safe_push (offload_vars, t);
+ }
+ }
+ }
tree clobber = build_clobber (ctx->record_type);
gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c
index e907827..0320ea6 100644
--- a/gcc/omp-offload.c
+++ b/gcc/omp-offload.c
@@ -2696,8 +2696,16 @@ pass_omp_target_link::execute (function *fun)
{
gimple_stmt_iterator gsi;
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
- gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
+ {
+ if (gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_GOMP_TARGET))
+ {
+ /* Nullify the second argument of __builtin_GOMP_target_ext. */
+ gimple_call_set_arg (gsi_stmt (gsi), 1, null_pointer_node);
+ update_stmt (gsi_stmt (gsi));
+ }
+ if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
+ gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
+ }
}
return 0;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 72d4f58..b62a557 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,58 @@
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/100502
+ * g++.dg/template/access37.C: New test.
+ * g++.dg/template/access37a.C: New test.
+
+2021-05-26 Aldy Hernandez <aldyh@redhat.com>
+
+ * gcc.dg/Wstringop-overflow-55.c: Adapt for range query changes.
+ * gcc.dg/pr80776-1.c: Same.
+
+2021-05-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * lib/target-supports.exp (check_effective_target_vect32): New.
+ (available_vector_sizes): Append 32 for x86 targets.
+ * gcc.dg/vect/pr71264.c (dg-final): Xfail scan dump for vect32 targets.
+ * gcc.dg/vect/slp-28.c (dg-final): Adjust dumps for vect32 targets.
+ * gcc.dg/vect/slp-3.c (dg-final): Ditto.
+ * gcc.target/i386/pr100637-3b.c: New test.
+ * gcc.target/i386/pr100637-3w.c: Ditto.
+ * gcc.target/i386/pr100637-4b.c: Ditto.
+ * gcc.target/i386/pr100637-4w.c: Ditto.
+
+2021-05-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/sso-13.c: New test.
+
+2021-05-26 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/simd/mve-vaddv-1.c: New test.
+
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/100368
+ * g++.dg/cpp1z/elide6.C: New test.
+
+2021-05-26 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/97420
+ * g++.dg/cpp0x/noexcept68.C: New test.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * gcc.target/csky/fldrd_fstrd.c: New.
+ * gcc.target/csky/fpuv3/fldr64_fstr64.c: New.
+
+2021-05-26 Geng Qi <gengqi@linux.alibaba.com>
+
+ * gcc.target/csky/ldbs.c: New.
+
+2021-05-26 Andrew Pinski <apinski@marvell.com>
+
+ * gcc.dg/tree-ssa/pr96928.c: Update test for slightly different IR.
+ * gcc.dg/tree-ssa/pr96928-1.c: New testcase.
+
2021-05-25 Jakub Jelinek <jakub@redhat.com>
PR c++/100666
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept68.C b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
new file mode 100644
index 0000000..086899a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept68.C
@@ -0,0 +1,8 @@
+// PR c++/97420
+// { dg-do compile { target c++11 } }
+
+int f(int) noexcept;
+template<int (&)(int)> void A();
+int main() {
+ A<f>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/elide6.C b/gcc/testsuite/g++.dg/cpp1z/elide6.C
new file mode 100644
index 0000000..399e1a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/elide6.C
@@ -0,0 +1,16 @@
+// PR c++/100368
+// { dg-do compile { target c++11 } }
+
+struct A {
+ A() = default;
+ A(const A&) = delete;
+};
+
+struct B { A a; }; // { dg-error "deleted" "" { target c++14_down } }
+
+constexpr B f() { return {}; }
+
+struct C {
+ constexpr C() : b(f()) {} // { dg-error "deleted" "" { target c++14_down } }
+ B b;
+};
diff --git a/gcc/testsuite/g++.dg/template/access37.C b/gcc/testsuite/g++.dg/template/access37.C
new file mode 100644
index 0000000..5be532c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access37.C
@@ -0,0 +1,26 @@
+// PR c++/100502
+
+template <class T>
+struct EnumeratorRange {
+ struct Iterator {
+ EnumeratorRange range_;
+
+ friend void f(Iterator i) {
+ i.range_.end_reached_; // { dg-error "private" }
+ i.range_.EnumeratorRange::end_reached_; // { dg-error "private" }
+ &i.range_.end_reached_; // { dg-error "private" }
+ &i.range_.EnumeratorRange::end_reached_; // { dg-error "private" }
+ }
+ };
+
+ private:
+ bool end_reached_;
+#if DECLARE_FRIEND
+ friend void f(Iterator);
+#endif
+};
+
+int main() {
+ EnumeratorRange<int>::Iterator i;
+ f(i);
+}
diff --git a/gcc/testsuite/g++.dg/template/access37a.C b/gcc/testsuite/g++.dg/template/access37a.C
new file mode 100644
index 0000000..4ce1b27
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access37a.C
@@ -0,0 +1,6 @@
+// PR c++/100502
+// { dg-additional-options "-DDECLARE_FRIEND -Wno-non-template-friend" }
+
+// Verify that access37.C is accepted if the appropriate friend relation
+// is declared (controlled by the macro DECLARE_FRIEND).
+#include "access37.C"
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c
index 25f5b82..8df5cb6 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-55.c
@@ -66,7 +66,7 @@ void warn_ptrdiff_anti_range_add (ptrdiff_t i)
{
i |= 1;
- char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" { xfail *-*-* } }
+ char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" }
char *p0 = ca5; // offset
char *p1 = p0 + i; // 1-5
char *p2 = p1 + i; // 2-5
@@ -74,7 +74,7 @@ void warn_ptrdiff_anti_range_add (ptrdiff_t i)
char *p4 = p3 + i; // 4-5
char *p5 = p4 + i; // 5
- memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size 0" "pr?????" { xfail *-*-* } }
+ memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size" "pr?????" }
sink (p0, p1, p2, p3, p4, p5);
}
@@ -83,7 +83,7 @@ void warn_int_anti_range (int i)
{
i |= 1;
- char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" { xfail *-*-* } }
+ char ca5[5]; // { dg-message "at offset \\\[1, 5]" "pr?????" }
char *p0 = ca5; // offset
char *p1 = p0 + i; // 1-5
char *p2 = p1 + i; // 2-5
@@ -91,7 +91,7 @@ void warn_int_anti_range (int i)
char *p4 = p3 + i; // 4-5
char *p5 = p4 + i; // 5
- memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size 0" "pr?????" { xfail *-*-* } }
+ memset (p5, 0, 5); // { dg-warning "writing 5 bytes into a region of size" "pr?????" }
sink (p0, p1, p2, p3, p4, p5);
}
diff --git a/gcc/testsuite/gcc.dg/pr80776-1.c b/gcc/testsuite/gcc.dg/pr80776-1.c
index af41c0c..f3a120b 100644
--- a/gcc/testsuite/gcc.dg/pr80776-1.c
+++ b/gcc/testsuite/gcc.dg/pr80776-1.c
@@ -17,7 +17,5 @@ Foo (void)
__builtin_unreachable ();
if (! (0 <= i && i <= 999999))
__builtin_unreachable ();
- /* The correctness bits for [E]VRP cannot handle chained conditionals
- when deciding to ignore a unreachable branch for setting SSA range info. */
- sprintf (number, "%d", i); /* { dg-bogus "writing" "" { xfail *-*-* } } */
+ sprintf (number, "%d", i); /* { dg-bogus "writing" "" } */
}
diff --git a/gcc/testsuite/gcc.dg/sso-13.c b/gcc/testsuite/gcc.dg/sso-13.c
new file mode 100644
index 0000000..ddfde00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-13.c
@@ -0,0 +1,24 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define REV_ENDIANNESS __attribute__((scalar_storage_order("big-endian")))
+#else
+#define REV_ENDIANNESS __attribute__((scalar_storage_order("little-endian")))
+#endif
+
+typedef struct tIp6Addr
+{
+ unsigned int s6_addr32[4];
+} tIp6Addr;
+
+struct _tBeTimNetAddr
+{
+ unsigned char isIPv4;
+ union
+ {
+ unsigned int addr;
+ tIp6Addr addr6; /* { dg-warning "type punning toggles" } */
+ } REV_ENDIANNESS u;
+} REV_ENDIANNESS;
diff --git a/gcc/testsuite/gcc.dg/vect/pr71264.c b/gcc/testsuite/gcc.dg/vect/pr71264.c
index dc849bf..1381e0e 100644
--- a/gcc/testsuite/gcc.dg/vect/pr71264.c
+++ b/gcc/testsuite/gcc.dg/vect/pr71264.c
@@ -19,5 +19,4 @@ void test(uint8_t *ptr, uint8_t *mask)
}
}
-/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" { xfail s390*-*-* sparc*-*-* } } } */
-
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" { xfail { { s390*-*-* sparc*-*-* } || vect32 } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-28.c b/gcc/testsuite/gcc.dg/vect/slp-28.c
index 7778bad..0bb5f0eb 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-28.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-28.c
@@ -88,6 +88,7 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! vect32 } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target vect32 } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { ! vect32 } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/slp-3.c b/gcc/testsuite/gcc.dg/vect/slp-3.c
index 46ab584..80ded18 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-3.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-3.c
@@ -141,8 +141,8 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { ! vect_partial_vectors } } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target vect_partial_vectors } } } */
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { ! vect_partial_vectors } } } }*/
-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target vect_partial_vectors } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { ! { vect_partial_vectors || vect32 } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target { vect_partial_vectors || vect32 } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target { ! { vect_partial_vectors || vect32 } } } } }*/
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 4 "vect" { target { vect_partial_vectors || vect32 } } } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/mve-vaddv-1.c b/gcc/testsuite/gcc.target/arm/simd/mve-vaddv-1.c
new file mode 100644
index 0000000..b6b0bc3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/mve-vaddv-1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_1m_mve_ok } */
+/* { dg-add-options arm_v8_1m_mve } */
+/* { dg-additional-options "-O3" } */
+
+#include <stdint.h>
+
+#define FUNC(SIGN, TYPE, BITS, NB) \
+ TYPE##32_t test_ ##_ ## SIGN ## BITS ## x ## NB (TYPE##BITS##_t *a) { \
+ int i; \
+ TYPE##BITS##_t result = 0; \
+ for (i=0; i<NB; i++) { \
+ result += a[i]; \
+ } \
+ return result; \
+}
+
+/* 128-bit vectors. */
+FUNC(s, int, 8, 16)
+FUNC(u, uint, 8, 16)
+FUNC(s, int, 16, 8)
+FUNC(u, uint, 16, 8)
+FUNC(s, int, 32, 4)
+FUNC(u, uint, 32, 4)
+
+/* { dg-final { scan-assembler-times {vaddv\.s} 6 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr100637-3b.c b/gcc/testsuite/gcc.target/i386/pr100637-3b.c
new file mode 100644
index 0000000..16df700
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr100637-3b.c
@@ -0,0 +1,56 @@
+/* PR target/100637 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse4" } */
+
+char r[4], a[4], b[4];
+unsigned char ur[4], ua[4], ub[4];
+
+void maxs (void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ r[i] = a[i] > b[i] ? a[i] : b[i];
+}
+
+/* { dg-final { scan-assembler "pmaxsb" } } */
+
+void maxu (void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ ur[i] = ua[i] > ub[i] ? ua[i] : ub[i];
+}
+
+/* { dg-final { scan-assembler "pmaxub" } } */
+
+void mins (void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ r[i] = a[i] < b[i] ? a[i] : b[i];
+}
+
+/* { dg-final { scan-assembler "pminsb" } } */
+
+void minu (void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ ur[i] = ua[i] < ub[i] ? ua[i] : ub[i];
+}
+
+/* { dg-final { scan-assembler "pminub" } } */
+
+void _abs (void)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ r[i] = a[i] < 0 ? -a[i] : a[i];
+}
+
+/* { dg-final { scan-assembler "pabsb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr100637-3w.c b/gcc/testsuite/gcc.target/i386/pr100637-3w.c
new file mode 100644
index 0000000..7f1882e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr100637-3w.c
@@ -0,0 +1,86 @@
+/* PR target/100637 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse4" } */
+
+short r[2], a[2], b[2];
+unsigned short ur[2], ua[2], ub[2];
+
+void mulh (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ r[i] = ((int) a[i] * b[i]) >> 16;
+}
+
+/* { dg-final { scan-assembler "pmulhw" { xfail *-*-* } } } */
+
+void mulhu (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ ur[i] = ((unsigned int) ua[i] * ub[i]) >> 16;
+}
+
+/* { dg-final { scan-assembler "pmulhuw" { xfail *-*-* } } } */
+
+void mulhrs (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ r[i] = ((((int) a[i] * b[i]) >> 14) + 1) >> 1;
+}
+
+/* { dg-final { scan-assembler "pmulhrsw" } } */
+
+void maxs (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ r[i] = a[i] > b[i] ? a[i] : b[i];
+}
+
+/* { dg-final { scan-assembler "pmaxsw" } } */
+
+void maxu (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ ur[i] = ua[i] > ub[i] ? ua[i] : ub[i];
+}
+
+/* { dg-final { scan-assembler "pmaxuw" } } */
+
+void mins (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ r[i] = a[i] < b[i] ? a[i] : b[i];
+}
+
+/* { dg-final { scan-assembler "pminsw" } } */
+
+void minu (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ ur[i] = ua[i] < ub[i] ? ua[i] : ub[i];
+}
+
+/* { dg-final { scan-assembler "pminuw" } } */
+
+void _abs (void)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ r[i] = a[i] < 0 ? -a[i] : a[i];
+}
+
+/* { dg-final { scan-assembler "pabsw" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr100637-4b.c b/gcc/testsuite/gcc.target/i386/pr100637-4b.c
new file mode 100644
index 0000000..198e3dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr100637-4b.c
@@ -0,0 +1,19 @@
+/* PR target/100637 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse2" } */
+
+typedef char T;
+
+#define M 4
+
+extern T a[M], b[M], s1[M], s2[M], r[M];
+
+void foo (void)
+{
+ int j;
+
+ for (j = 0; j < M; j++)
+ r[j] = (a[j] < b[j]) ? s1[j] : s2[j];
+}
+
+/* { dg-final { scan-assembler "pcmpgtb" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr100637-4w.c b/gcc/testsuite/gcc.target/i386/pr100637-4w.c
new file mode 100644
index 0000000..0f5dacc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr100637-4w.c
@@ -0,0 +1,19 @@
+/* PR target/100637 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -msse2" } */
+
+typedef short T;
+
+#define M 2
+
+extern T a[M], b[M], s1[M], s2[M], r[M];
+
+void foo (void)
+{
+ int j;
+
+ for (j = 0; j < M; j++)
+ r[j] = (a[j] < b[j]) ? s1[j] : s2[j];
+}
+
+/* { dg-final { scan-assembler "pcmpgtw" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 849f1bb..7f78c55 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -7626,6 +7626,7 @@ proc available_vector_sizes { } {
if { ![is-effective-target ia32] } {
lappend result 64
}
+ lappend result 32
} elseif { [istarget sparc*-*-*] } {
lappend result 64
} elseif { [istarget amdgcn*-*-*] } {
@@ -7655,6 +7656,12 @@ proc check_effective_target_vect64 { } {
return [expr { [lsearch -exact [available_vector_sizes] 64] >= 0 }]
}
+# Return 1 if the target supports vectors of 32 bits.
+
+proc check_effective_target_vect32 { } {
+ return [expr { [lsearch -exact [available_vector_sizes] 32] >= 0 }]
+}
+
# Return 1 if the target supports vector copysignf calls.
proc check_effective_target_vect_call_copysignf { } {
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index e6dd5f1..09d4667 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1035,14 +1035,23 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range,
*exp_range = type;
if (code == SSA_NAME)
{
- wide_int var_min, var_max;
- value_range_kind vr_kind = get_range_info (exp, &var_min, &var_max);
+ value_range vr;
+ get_range_query (cfun)->range_of_expr (vr, exp);
+ if (vr.undefined_p ())
+ vr.set_varying (TREE_TYPE (exp));
+ wide_int var_min = wi::to_wide (vr.min ());
+ wide_int var_max = wi::to_wide (vr.max ());
+ value_range_kind vr_kind = vr.kind ();
wide_int var_nonzero = get_nonzero_bits (exp);
vr_kind = intersect_range_with_nonzero_bits (vr_kind,
&var_min, &var_max,
var_nonzero,
TYPE_SIGN (type));
- if (vr_kind == VR_RANGE)
+ /* This check for VR_VARYING is here because the old code
+ using get_range_info would return VR_RANGE for the entire
+ domain, instead of VR_VARYING. The new code normalizes
+ full-domain ranges to VR_VARYING. */
+ if (vr_kind == VR_RANGE || vr_kind == VR_VARYING)
*exp_range = value_range (type, var_min, var_max);
}
}
@@ -6298,12 +6307,19 @@ dr_step_indicator (struct data_reference *dr, int useful_min)
/* Get the range of values that the unconverted step actually has. */
wide_int step_min, step_max;
+ value_range vr;
if (TREE_CODE (step) != SSA_NAME
- || get_range_info (step, &step_min, &step_max) != VR_RANGE)
+ || !get_range_query (cfun)->range_of_expr (vr, step)
+ || vr.kind () != VR_RANGE)
{
step_min = wi::to_wide (TYPE_MIN_VALUE (type));
step_max = wi::to_wide (TYPE_MAX_VALUE (type));
}
+ else
+ {
+ step_min = vr.lower_bound ();
+ step_max = vr.upper_bound ();
+ }
/* Check whether the unconverted step has an acceptable range. */
signop sgn = TYPE_SIGN (type);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index c6c3bd6..1d20de0 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "tree-dfa.h"
+#include "gimple-range.h"
/* Build and maintain data flow information for trees. */
@@ -535,14 +536,23 @@ get_ref_base_and_extent (tree exp, poly_int64_pod *poffset,
index. */
seen_variable_array_ref = true;
- wide_int min, max;
+ value_range vr;
+ range_query *query;
+ if (cfun)
+ query = get_range_query (cfun);
+ else
+ query = get_global_range_query ();
+
if (TREE_CODE (index) == SSA_NAME
&& (low_bound = array_ref_low_bound (exp),
poly_int_tree_p (low_bound))
&& (unit_size = array_ref_element_size (exp),
TREE_CODE (unit_size) == INTEGER_CST)
- && get_range_info (index, &min, &max) == VR_RANGE)
+ && query->range_of_expr (vr, index)
+ && vr.kind () == VR_RANGE)
{
+ wide_int min = vr.lower_bound ();
+ wide_int max = vr.upper_bound ();
poly_offset_int lbound = wi::to_poly_offset (low_bound);
/* Try to constrain maxsize with range information. */
offset_int omax
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index ff052be..b22d49a 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -3039,18 +3039,27 @@ iv_can_overflow_p (class loop *loop, tree type, tree base, tree step)
widest_int nit;
wide_int base_min, base_max, step_min, step_max, type_min, type_max;
signop sgn = TYPE_SIGN (type);
+ value_range r;
if (integer_zerop (step))
return false;
if (!INTEGRAL_TYPE_P (TREE_TYPE (base))
- || get_range_info (base, &base_min, &base_max) != VR_RANGE)
+ || !get_range_query (cfun)->range_of_expr (r, base)
+ || r.kind () != VR_RANGE)
return true;
+ base_min = r.lower_bound ();
+ base_max = r.upper_bound ();
+
if (!INTEGRAL_TYPE_P (TREE_TYPE (step))
- || get_range_info (step, &step_min, &step_max) != VR_RANGE)
+ || !get_range_query (cfun)->range_of_expr (r, step)
+ || r.kind () != VR_RANGE)
return true;
+ step_min = r.lower_bound ();
+ step_max = r.upper_bound ();
+
if (!get_max_loop_iterations (loop, &nit))
return true;
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 3817ec4..b5add82 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "tree-dfa.h"
+#include "gimple-range.h"
/* The maximum number of dominator BBs we search for conditions
@@ -121,7 +122,6 @@ refine_value_range_using_guard (tree type, tree var,
tree varc0, varc1, ctype;
mpz_t offc0, offc1;
mpz_t mint, maxt, minc1, maxc1;
- wide_int minv, maxv;
bool no_wrap = nowrap_type_p (type);
bool c0_ok, c1_ok;
signop sgn = TYPE_SIGN (type);
@@ -221,6 +221,7 @@ refine_value_range_using_guard (tree type, tree var,
get_type_static_bounds (type, mint, maxt);
mpz_init (minc1);
mpz_init (maxc1);
+ value_range r;
/* Setup range information for varc1. */
if (integer_zerop (varc1))
{
@@ -229,11 +230,12 @@ refine_value_range_using_guard (tree type, tree var,
}
else if (TREE_CODE (varc1) == SSA_NAME
&& INTEGRAL_TYPE_P (type)
- && get_range_info (varc1, &minv, &maxv) == VR_RANGE)
+ && get_range_query (cfun)->range_of_expr (r, varc1)
+ && r.kind () == VR_RANGE)
{
- gcc_assert (wi::le_p (minv, maxv, sgn));
- wi::to_mpz (minv, minc1, sgn);
- wi::to_mpz (maxv, maxc1, sgn);
+ gcc_assert (wi::le_p (r.lower_bound (), r.upper_bound (), sgn));
+ wi::to_mpz (r.lower_bound (), minc1, sgn);
+ wi::to_mpz (r.upper_bound (), maxc1, sgn);
}
else
{
@@ -372,34 +374,50 @@ determine_value_range (class loop *loop, tree type, tree var, mpz_t off,
gphi_iterator gsi;
/* Either for VAR itself... */
- rtype = get_range_info (var, &minv, &maxv);
+ value_range var_range;
+ get_range_query (cfun)->range_of_expr (var_range, var);
+ rtype = var_range.kind ();
+ if (!var_range.undefined_p ())
+ {
+ minv = var_range.lower_bound ();
+ maxv = var_range.upper_bound ();
+ }
+
/* Or for PHI results in loop->header where VAR is used as
PHI argument from the loop preheader edge. */
for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
{
gphi *phi = gsi.phi ();
- wide_int minc, maxc;
+ value_range phi_range;
if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
- && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
- == VR_RANGE))
+ && get_range_query (cfun)->range_of_expr (phi_range,
+ gimple_phi_result (phi))
+ && phi_range.kind () == VR_RANGE)
{
if (rtype != VR_RANGE)
{
rtype = VR_RANGE;
- minv = minc;
- maxv = maxc;
+ minv = phi_range.lower_bound ();
+ maxv = phi_range.upper_bound ();
}
else
{
- minv = wi::max (minv, minc, sgn);
- maxv = wi::min (maxv, maxc, sgn);
+ minv = wi::max (minv, phi_range.lower_bound (), sgn);
+ maxv = wi::min (maxv, phi_range.upper_bound (), sgn);
/* If the PHI result range are inconsistent with
the VAR range, give up on looking at the PHI
results. This can happen if VR_UNDEFINED is
involved. */
if (wi::gt_p (minv, maxv, sgn))
{
- rtype = get_range_info (var, &minv, &maxv);
+ value_range vr;
+ get_range_query (cfun)->range_of_expr (vr, var);
+ rtype = vr.kind ();
+ if (!vr.undefined_p ())
+ {
+ minv = vr.lower_bound ();
+ maxv = vr.upper_bound ();
+ }
break;
}
}
@@ -3545,12 +3563,16 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
if (tree_int_cst_sign_bit (step))
{
- wide_int min, max;
+ wide_int max;
+ value_range base_range;
+ if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
+ && !base_range.undefined_p ())
+ max = base_range.upper_bound ();
extreme = fold_convert (unsigned_type, low);
if (TREE_CODE (orig_base) == SSA_NAME
&& TREE_CODE (high) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (orig_base))
- && (get_range_info (orig_base, &min, &max) == VR_RANGE
+ && (base_range.kind () == VR_RANGE
|| get_cst_init_from_scev (orig_base, &max, false))
&& wi::gts_p (wi::to_wide (high), max))
base = wide_int_to_tree (unsigned_type, max);
@@ -3563,12 +3585,16 @@ record_nonwrapping_iv (class loop *loop, tree base, tree step, gimple *stmt,
}
else
{
- wide_int min, max;
+ wide_int min;
+ value_range base_range;
+ if (get_range_query (cfun)->range_of_expr (base_range, orig_base)
+ && !base_range.undefined_p ())
+ min = base_range.lower_bound ();
extreme = fold_convert (unsigned_type, high);
if (TREE_CODE (orig_base) == SSA_NAME
&& TREE_CODE (low) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (orig_base))
- && (get_range_info (orig_base, &min, &max) == VR_RANGE
+ && (base_range.kind () == VR_RANGE
|| get_cst_init_from_scev (orig_base, &min, true))
&& wi::gts_p (min, wi::to_wide (low)))
base = wide_int_to_tree (unsigned_type, min);
@@ -3835,11 +3861,12 @@ infer_loop_bounds_from_signedness (class loop *loop, gimple *stmt)
low = lower_bound_in_type (type, type);
high = upper_bound_in_type (type, type);
- wide_int minv, maxv;
- if (get_range_info (def, &minv, &maxv) == VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, def);
+ if (r.kind () == VR_RANGE)
{
- low = wide_int_to_tree (type, minv);
- high = wide_int_to_tree (type, maxv);
+ low = wide_int_to_tree (type, r.lower_bound ());
+ high = wide_int_to_tree (type, r.upper_bound ());
}
record_nonwrapping_iv (loop, base, step, stmt, low, high, false, true);
@@ -4873,7 +4900,6 @@ scev_var_range_cant_overflow (tree var, tree step, class loop *loop)
{
tree type;
wide_int minv, maxv, diff, step_wi;
- enum value_range_kind rtype;
if (TREE_CODE (step) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (var)))
return false;
@@ -4884,8 +4910,9 @@ scev_var_range_cant_overflow (tree var, tree step, class loop *loop)
if (!def_bb || !dominated_by_p (CDI_DOMINATORS, loop->latch, def_bb))
return false;
- rtype = get_range_info (var, &minv, &maxv);
- if (rtype != VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, var);
+ if (r.kind () != VR_RANGE)
return false;
/* VAR is a scev whose evolution part is STEP and value range info
@@ -4899,11 +4926,11 @@ scev_var_range_cant_overflow (tree var, tree step, class loop *loop)
type = TREE_TYPE (var);
if (tree_int_cst_sign_bit (step))
{
- diff = minv - wi::to_wide (lower_bound_in_type (type, type));
+ diff = r.lower_bound () - wi::to_wide (lower_bound_in_type (type, type));
step_wi = - step_wi;
}
else
- diff = wi::to_wide (upper_bound_in_type (type, type)) - maxv;
+ diff = wi::to_wide (upper_bound_in_type (type, type)) - r.upper_bound ();
return (wi::geu_p (diff, step_wi));
}
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index f133659..e3bd180 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "gimple-fold.h"
#include "internal-fn.h"
+#include "gimple-range.h"
static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
@@ -684,7 +685,15 @@ two_value_replacement (basic_block cond_bb, basic_block middle_bb,
return false;
wide_int min, max;
- if (get_range_info (lhs, &min, &max) != VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, lhs);
+
+ if (r.kind () == VR_RANGE)
+ {
+ min = r.lower_bound ();
+ max = r.upper_bound ();
+ }
+ else
{
int prec = TYPE_PRECISION (TREE_TYPE (lhs));
signop sgn = TYPE_SIGN (TREE_TYPE (lhs));
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 2d22535..d86fe26 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-dce.h"
#include "tree-cfgcleanup.h"
#include "alias.h"
+#include "gimple-range.h"
/* Even though this file is called tree-ssa-pre.c, we actually
implement a bit more than just PRE here. All of them piggy-back
@@ -3234,16 +3235,18 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
>= TYPE_PRECISION (TREE_TYPE (expr->u.nary->op[0])))
&& SSA_NAME_RANGE_INFO (expr->u.nary->op[0]))
{
- wide_int min, max;
- if (get_range_info (expr->u.nary->op[0], &min, &max) == VR_RANGE
- && !wi::neg_p (min, SIGNED)
- && !wi::neg_p (max, SIGNED))
+ value_range r;
+ if (get_range_query (cfun)->range_of_expr (r, expr->u.nary->op[0])
+ && r.kind () == VR_RANGE
+ && !wi::neg_p (r.lower_bound (), SIGNED)
+ && !wi::neg_p (r.upper_bound (), SIGNED))
/* Just handle extension and sign-changes of all-positive ranges. */
- set_range_info (temp,
- SSA_NAME_RANGE_TYPE (expr->u.nary->op[0]),
- wide_int_storage::from (min, TYPE_PRECISION (type),
+ set_range_info (temp, VR_RANGE,
+ wide_int_storage::from (r.lower_bound (),
+ TYPE_PRECISION (type),
TYPE_SIGN (type)),
- wide_int_storage::from (max, TYPE_PRECISION (type),
+ wide_int_storage::from (r.upper_bound (),
+ TYPE_PRECISION (type),
TYPE_SIGN (type)));
}
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 32e1632..6dfc703 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "case-cfn-macros.h"
#include "tree-ssa-reassoc.h"
#include "tree-ssa-math-opts.h"
+#include "gimple-range.h"
/* This is a simple global reassociation pass. It is, in part, based
on the LLVM pass of the same name (They do some things more/less
@@ -3221,12 +3222,14 @@ optimize_range_tests_to_bit_test (enum tree_code opcode, int first, int length,
amount, then we can merge the entry test in the bit test. In this
case, if we would need otherwise 2 or more comparisons, then use
the bit test; in the other cases, the threshold is 3 comparisons. */
- wide_int min, max;
bool entry_test_needed;
+ value_range r;
if (TREE_CODE (exp) == SSA_NAME
- && get_range_info (exp, &min, &max) == VR_RANGE
- && wi::leu_p (max - min, prec - 1))
+ && get_range_query (cfun)->range_of_expr (r, exp)
+ && r.kind () == VR_RANGE
+ && wi::leu_p (r.upper_bound () - r.lower_bound (), prec - 1))
{
+ wide_int min = r.lower_bound ();
wide_int ilowi = wi::to_wide (lowi);
if (wi::lt_p (min, ilowi, TYPE_SIGN (TREE_TYPE (lowi))))
{
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index c7b5e2c..423075b 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -196,7 +196,7 @@ static void handle_builtin_stxncpy_strncat (bool, gimple_stmt_iterator *);
/* Sets MINMAX to either the constant value or the range VAL is in
and returns either the constant value or VAL on success or null
when the range couldn't be determined. Uses RVALS when nonnull
- to determine the range, otherwise get_range_info. */
+ to determine the range, otherwise uses global range info. */
tree
get_range (tree val, gimple *stmt, wide_int minmax[2],
@@ -211,9 +211,9 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
if (TREE_CODE (val) != SSA_NAME)
return NULL_TREE;
+ value_range vr;
if (rvals && stmt)
{
- value_range vr;
if (!rvals->range_of_expr (vr, val, stmt))
return NULL_TREE;
value_range_kind rng = vr.kind ();
@@ -225,7 +225,15 @@ get_range (tree val, gimple *stmt, wide_int minmax[2],
return val;
}
- value_range_kind rng = get_range_info (val, minmax, minmax + 1);
+ // ?? This entire function should use get_range_query or get_global_range_query (),
+ // instead of doing something different for RVALS and global ranges.
+
+ if (!get_global_range_query ()->range_of_expr (vr, val) || vr.undefined_p ())
+ return NULL_TREE;
+
+ minmax[0] = wi::to_wide (vr.min ());
+ minmax[1] = wi::to_wide (vr.max ());
+ value_range_kind rng = vr.kind ();
if (rng == VR_RANGE)
/* This may be an inverted range whose MINMAX[1] < MINMAX[0]. */
return val;
@@ -929,7 +937,17 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
rng = VR_UNDEFINED;
}
else
- rng = get_range_info (si->nonzero_chars, &min, &max);
+ {
+ value_range vr;
+ get_global_range_query ()->range_of_expr (vr,
+ si->nonzero_chars);
+ rng = vr.kind ();
+ if (!vr.undefined_p ())
+ {
+ min = wi::to_wide (vr.min ());
+ max = wi::to_wide (vr.max ());
+ }
+ }
if (rng == VR_RANGE || rng == VR_ANTI_RANGE)
{
@@ -1809,18 +1827,17 @@ set_strlen_range (tree lhs, wide_int min, wide_int max,
}
else if (TREE_CODE (bound) == SSA_NAME)
{
- wide_int minbound, maxbound;
- // FIXME: Use range_query instead of global ranges.
- value_range_kind rng = get_range_info (bound, &minbound, &maxbound);
- if (rng == VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, bound);
+ if (!r.undefined_p ())
{
/* For a bound in a known range, adjust the range determined
above as necessary. For a bound in some anti-range or
in an unknown range, use the range determined by callers. */
- if (wi::ltu_p (minbound, min))
- min = minbound;
- if (wi::ltu_p (maxbound, max))
- max = maxbound;
+ if (wi::ltu_p (r.lower_bound (), min))
+ min = r.lower_bound ();
+ if (wi::ltu_p (r.upper_bound (), max))
+ max = r.upper_bound ();
}
}
}
@@ -2780,12 +2797,15 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
return false;
wide_int cntrange[2];
+ value_range r;
+ if (!get_range_query (cfun)->range_of_expr (r, cnt)
+ || r.varying_p ()
+ || r.undefined_p ())
+ return false;
- // FIXME: Use range_query instead of global ranges.
- enum value_range_kind rng = get_range_info (cnt, cntrange, cntrange + 1);
- if (rng == VR_RANGE)
- ;
- else if (rng == VR_ANTI_RANGE)
+ cntrange[0] = wi::to_wide (r.min ());
+ cntrange[1] = wi::to_wide (r.max ());
+ if (r.kind () == VR_ANTI_RANGE)
{
wide_int maxobjsize = wi::to_wide (TYPE_MAX_VALUE (ptrdiff_type_node));
@@ -2800,8 +2820,6 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
cntrange[0] = wi::zero (TYPE_PRECISION (TREE_TYPE (cnt)));
}
}
- else
- return false;
/* Negative value is the constant string length. If it's less than
the lower bound there is no truncation. Avoid calling get_stridx()
@@ -3923,13 +3941,12 @@ get_len_or_size (gimple *stmt, tree arg, int idx,
}
else if (TREE_CODE (si->nonzero_chars) == SSA_NAME)
{
- wide_int min, max;
- // FIXME: Use range_query instead of global ranges.
- value_range_kind rng = get_range_info (si->nonzero_chars, &min, &max);
- if (rng == VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, si->nonzero_chars);
+ if (r.kind () == VR_RANGE)
{
- lenrng[0] = min.to_uhwi ();
- lenrng[1] = max.to_uhwi ();
+ lenrng[0] = r.lower_bound ().to_uhwi ();
+ lenrng[1] = r.upper_bound ().to_uhwi ();
*nulterm = si->full_string_p;
}
}
@@ -5301,17 +5318,13 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh,
/* Reading a character before the final '\0'
character. Just set the value range to ~[0, 0]
if we don't have anything better. */
- wide_int min, max;
- signop sign = TYPE_SIGN (lhs_type);
- int prec = TYPE_PRECISION (lhs_type);
- // FIXME: Use range_query instead of global ranges.
- value_range_kind vr = get_range_info (lhs, &min, &max);
- if (vr == VR_VARYING
- || (vr == VR_RANGE
- && min == wi::min_value (prec, sign)
- && max == wi::max_value (prec, sign)))
- set_range_info (lhs, VR_ANTI_RANGE,
- wi::zero (prec), wi::zero (prec));
+ value_range r;
+ if (!get_range_query (cfun)->range_of_expr (r, lhs)
+ || r.varying_p ())
+ {
+ r.set_nonzero (lhs_type);
+ set_range_info (lhs, r);
+ }
}
}
}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index a023871..7163438 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -43,6 +43,7 @@
#include "attribs.h"
#include "tree-ssa.h"
#include "tree-cfg.h"
+#include "gimple-range.h"
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -6740,7 +6741,9 @@ find_what_p_points_to (tree fndecl, tree p)
struct ptr_info_def *pi;
tree lookup_p = p;
varinfo_t vi;
- bool nonnull = get_ptr_nonnull (p);
+ value_range vr;
+ get_range_query (DECL_STRUCT_FUNCTION (fndecl))->range_of_expr (vr, p);
+ bool nonnull = vr.nonzero_p ();
/* For parameters, get at the points-to set for the actual parm
decl. */
@@ -6758,8 +6761,7 @@ find_what_p_points_to (tree fndecl, tree p)
pi->pt = find_what_var_points_to (fndecl, vi);
/* Conservatively set to NULL from PTA (to true). */
pi->pt.null = 1;
- /* Preserve pointer nonnull computed by VRP. See get_ptr_nonnull
- in gcc/tree-ssaname.c for more information. */
+ /* Preserve pointer nonnull globally computed. */
if (nonnull)
set_ptr_nonnull (p);
}
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index f55ce19..dcfdec9 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "builtins.h"
#include "calls.h"
+#include "gimple-range.h"
/* This implements the pass that does predicate aware warning on uses of
possibly uninitialized variables. The pass first collects the set of
@@ -1606,11 +1607,14 @@ find_var_cmp_const (pred_chain_union preds, gphi *phi, gimple **flag_def,
flag_var <= [min, max] -> flag_var < [min, max+1]
flag_var >= [min, max] -> flag_var > [min-1, max]
if no overflow/wrap. */
- wide_int min, max;
tree type = TREE_TYPE (cond_lhs);
+ value_range r;
if (!INTEGRAL_TYPE_P (type)
- || get_range_info (cond_rhs, &min, &max) != VR_RANGE)
+ || !get_range_query (cfun)->range_of_expr (r, cond_rhs)
+ || r.kind () != VR_RANGE)
continue;
+ wide_int min = r.lower_bound ();
+ wide_int max = r.upper_bound ();
if (code == LE_EXPR
&& max != wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)))
{
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 51a26d2..5329c0a 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -423,58 +423,29 @@ set_range_info (tree name, const value_range &vr)
set_range_info (name, vr.kind (), min, max);
}
-/* Gets range information MIN, MAX and returns enum value_range_kind
- corresponding to tree ssa_name NAME. enum value_range_kind returned
- is used to determine if MIN and MAX are valid values. */
+/* Gets range information corresponding to ssa_name NAME and stores it
+ in a value_range VR. Returns the value_range_kind. */
enum value_range_kind
-get_range_info (const_tree expr, wide_int *min, wide_int *max)
+get_range_info (const_tree name, irange &vr)
{
- gcc_assert (!POINTER_TYPE_P (TREE_TYPE (expr)));
- gcc_assert (min && max);
- if (TREE_CODE (expr) == INTEGER_CST)
- {
- *min = wi::to_wide (expr);
- *max = *min;
- return VR_RANGE;
- }
- if (TREE_CODE (expr) != SSA_NAME)
- return VR_VARYING;
+ tree type = TREE_TYPE (name);
+ gcc_checking_assert (!POINTER_TYPE_P (type));
+ gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
- range_info_def *ri = SSA_NAME_RANGE_INFO (expr);
+ range_info_def *ri = SSA_NAME_RANGE_INFO (name);
/* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision. */
- if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (expr)))
+ if (!ri || (GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (TREE_TYPE (name)))
> 2 * HOST_BITS_PER_WIDE_INT))
- return VR_VARYING;
-
- *min = ri->get_min ();
- *max = ri->get_max ();
- return SSA_NAME_RANGE_TYPE (expr);
-}
-
-/* Gets range information corresponding to ssa_name NAME and stores it
- in a value_range VR. Returns the value_range_kind. */
-
-enum value_range_kind
-get_range_info (const_tree name, irange &vr)
-{
- tree min, max;
- wide_int wmin, wmax;
- enum value_range_kind kind = get_range_info (name, &wmin, &wmax);
-
- if (kind == VR_VARYING)
- vr.set_varying (TREE_TYPE (name));
- else if (kind == VR_UNDEFINED)
- vr.set_undefined ();
+ vr.set_varying (type);
else
- {
- min = wide_int_to_tree (TREE_TYPE (name), wmin);
- max = wide_int_to_tree (TREE_TYPE (name), wmax);
- vr.set (min, max, kind);
- }
- return kind;
+ vr.set (wide_int_to_tree (type, ri->get_min ()),
+ wide_int_to_tree (type, ri->get_max ()),
+ SSA_NAME_RANGE_TYPE (name));
+
+ return vr.kind ();
}
/* Set nonnull attribute to pointer NAME. */
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index cce2d2c..166f921 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -71,8 +71,6 @@ extern void set_range_info (tree, enum value_range_kind, const wide_int_ref &,
const wide_int_ref &);
extern void set_range_info (tree, const value_range &);
/* Gets the value range from SSA. */
-extern enum value_range_kind get_range_info (const_tree, wide_int *,
- wide_int *);
extern enum value_range_kind get_range_info (const_tree, irange &);
extern void set_nonzero_bits (tree, const wide_int_ref &);
extern wide_int get_nonzero_bits (const_tree);
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index 7f65c4c..294b545 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -50,6 +50,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "target.h"
#include "tree-into-ssa.h"
#include "omp-general.h"
+#include "gimple-range.h"
/* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
type in the GIMPLE type system that is language-independent? */
@@ -1553,12 +1554,15 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
/* If every possible relative value of the index expression is a valid shift
amount, then we can merge the entry test in the bit test. */
- wide_int min, max;
bool entry_test_needed;
+ value_range r;
if (TREE_CODE (index_expr) == SSA_NAME
- && get_range_info (index_expr, &min, &max) == VR_RANGE
- && wi::leu_p (max - min, prec - 1))
+ && get_range_query (cfun)->range_of_expr (r, index_expr)
+ && r.kind () == VR_RANGE
+ && wi::leu_p (r.upper_bound () - r.lower_bound (), prec - 1))
{
+ wide_int min = r.lower_bound ();
+ wide_int max = r.upper_bound ();
tree index_type = TREE_TYPE (index_expr);
minval = fold_convert (index_type, minval);
wide_int iminval = wi::to_wide (minval);
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 803de3f..177d44e 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
#include "predict.h"
#include "tree-vector-builder.h"
#include "vec-perm-indices.h"
+#include "gimple-range.h"
/* Return true if we have a useful VR_RANGE range for VAR, storing it
in *MIN_VALUE and *MAX_VALUE if so. Note the range in the dump files. */
@@ -55,7 +56,13 @@ along with GCC; see the file COPYING3. If not see
static bool
vect_get_range_info (tree var, wide_int *min_value, wide_int *max_value)
{
- value_range_kind vr_type = get_range_info (var, min_value, max_value);
+ value_range vr;
+ get_range_query (cfun)->range_of_expr (vr, var);
+ if (vr.undefined_p ())
+ vr.set_varying (TREE_TYPE (var));
+ *min_value = wi::to_wide (vr.min ());
+ *max_value = wi::to_wide (vr.max ());
+ value_range_kind vr_type = vr.kind ();
wide_int nonzero = get_nonzero_bits (var);
signop sgn = TYPE_SIGN (TREE_TYPE (var));
if (intersect_range_with_nonzero_bits (vr_type, min_value, max_value,
@@ -3437,13 +3444,14 @@ vect_recog_divmod_pattern (vec_info *vinfo,
else
t3 = t2;
- wide_int oprnd0_min, oprnd0_max;
int msb = 1;
- if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
+ value_range r;
+ get_range_query (cfun)->range_of_expr (r, oprnd0);
+ if (r.kind () == VR_RANGE)
{
- if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype)))
+ if (!wi::neg_p (r.lower_bound (), TYPE_SIGN (itype)))
msb = 0;
- else if (wi::neg_p (oprnd0_max, TYPE_SIGN (itype)))
+ else if (wi::neg_p (r.upper_bound (), TYPE_SIGN (itype)))
msb = -1;
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 12e6e6f..450926d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -228,7 +228,7 @@ intersect_range_with_nonzero_bits (enum value_range_kind vr_type,
vr_type = VR_RANGE;
}
}
- if (vr_type == VR_RANGE)
+ if (vr_type == VR_RANGE || vr_type == VR_VARYING)
{
*max = wi::round_down_for_mask (*max, nonzero_bits);
@@ -1717,7 +1717,7 @@ register_edge_assert_for_2 (tree name, edge e,
simply register the same assert for it. */
if (CONVERT_EXPR_CODE_P (rhs_code))
{
- wide_int rmin, rmax;
+ value_range vr;
tree rhs1 = gimple_assign_rhs1 (def_stmt);
if (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
&& TREE_CODE (rhs1) == SSA_NAME
@@ -1739,13 +1739,14 @@ register_edge_assert_for_2 (tree name, edge e,
&& int_fits_type_p (val, TREE_TYPE (rhs1))
&& ((TYPE_PRECISION (TREE_TYPE (name))
> TYPE_PRECISION (TREE_TYPE (rhs1)))
- || (get_range_info (rhs1, &rmin, &rmax) == VR_RANGE
+ || ((get_range_query (cfun)->range_of_expr (vr, rhs1)
+ && vr.kind () == VR_RANGE)
&& wi::fits_to_tree_p
- (widest_int::from (rmin,
+ (widest_int::from (vr.lower_bound (),
TYPE_SIGN (TREE_TYPE (rhs1))),
TREE_TYPE (name))
&& wi::fits_to_tree_p
- (widest_int::from (rmax,
+ (widest_int::from (vr.upper_bound (),
TYPE_SIGN (TREE_TYPE (rhs1))),
TREE_TYPE (name)))))
add_assert_info (asserts, rhs1, rhs1,
@@ -4044,7 +4045,7 @@ vrp_prop::finalize ()
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after VRP:\n\n");
- m_vr_values->dump_all_value_ranges (dump_file);
+ m_vr_values->dump (dump_file);
fprintf (dump_file, "\n");
}
@@ -4631,16 +4632,14 @@ determine_value_range_1 (value_range *vr, tree expr)
vr->set (expr);
else
{
- value_range_kind kind;
- wide_int min, max;
+ value_range r;
/* For SSA names try to extract range info computed by VRP. Otherwise
fall back to varying. */
if (TREE_CODE (expr) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (expr))
- && (kind = get_range_info (expr, &min, &max)) != VR_VARYING)
- vr->set (wide_int_to_tree (TREE_TYPE (expr), min),
- wide_int_to_tree (TREE_TYPE (expr), max),
- kind);
+ && get_range_query (cfun)->range_of_expr (r, expr)
+ && !r.undefined_p ())
+ *vr = r;
else
vr->set_varying (TREE_TYPE (expr));
}
diff --git a/gcc/tree.c b/gcc/tree.c
index bdb29b8..9cafe43 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "gimple-fold.h"
#include "escaped_string.h"
+#include "gimple-range.h"
/* Tree code classes. */
@@ -13831,8 +13832,8 @@ get_range_pos_neg (tree arg)
if (TREE_CODE (arg) != SSA_NAME)
return 3;
- wide_int arg_min, arg_max;
- while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+ value_range r;
+ while (!get_global_range_query ()->range_of_expr (r, arg) || r.kind () != VR_RANGE)
{
gimple *g = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (g)
@@ -13858,16 +13859,16 @@ get_range_pos_neg (tree arg)
{
/* For unsigned values, the "positive" range comes
below the "negative" range. */
- if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+ if (!wi::neg_p (wi::sext (r.upper_bound (), prec), SIGNED))
return 1;
- if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+ if (wi::neg_p (wi::sext (r.lower_bound (), prec), SIGNED))
return 2;
}
else
{
- if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+ if (!wi::neg_p (wi::sext (r.lower_bound (), prec), SIGNED))
return 1;
- if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+ if (wi::neg_p (wi::sext (r.upper_bound (), prec), SIGNED))
return 2;
}
return 3;
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index 4bb0897..509d2d3 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -135,6 +135,11 @@ range_query::value_of_stmt (gimple *stmt, tree name)
}
+void
+range_query::dump (FILE *)
+{
+}
+
// valuation_query support routines for value_range_equiv's.
class equiv_allocator : public object_allocator<value_range_equiv>
diff --git a/gcc/value-query.h b/gcc/value-query.h
index e2cbc68..5eff931 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -95,6 +95,7 @@ public:
// rewrite all uses of it to the above API.
virtual const class value_range_equiv *get_value_range (const_tree,
gimple * = NULL);
+ virtual void dump (FILE *);
protected:
class value_range_equiv *allocate_value_range_equiv ();
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 02bc0db..d283108 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -117,14 +117,16 @@ vr_values::get_lattice_entry (const_tree var)
default definitions of PARM_DECLs. */
if (POINTER_TYPE_P (TREE_TYPE (sym))
&& (nonnull_arg_p (sym)
- || get_ptr_nonnull (var)))
+ || (get_global_range_query ()->range_of_expr (*vr,
+ const_cast <tree> (var))
+ && vr->nonzero_p ())))
{
vr->set_nonzero (TREE_TYPE (sym));
vr->equiv_clear ();
}
else if (INTEGRAL_TYPE_P (TREE_TYPE (sym)))
{
- get_range_info (var, *vr);
+ get_global_range_query ()->range_of_expr (*vr, const_cast <tree> (var));
if (vr->undefined_p ())
vr->set_varying (TREE_TYPE (sym));
}
@@ -262,7 +264,7 @@ vr_values::update_value_range (const_tree var, value_range_equiv *new_vr)
if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
{
value_range_equiv nr;
- get_range_info (var, nr);
+ get_global_range_query ()->range_of_expr (nr, const_cast <tree> (var));
if (!nr.undefined_p ())
new_vr->intersect (&nr);
}
@@ -1819,7 +1821,7 @@ vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
/* Dump value ranges of all SSA_NAMEs to FILE. */
void
-vr_values::dump_all_value_ranges (FILE *file)
+vr_values::dump (FILE *file)
{
size_t i;
@@ -3829,13 +3831,13 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop))
return false;
- /* Get the value-range of the inner operand. Use get_range_info in
+ /* Get the value-range of the inner operand. Use global ranges in
case innerop was created during substitute-and-fold. */
wide_int imin, imax;
value_range vr;
if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop)))
return false;
- get_range_info (innerop, vr);
+ get_global_range_query ()->range_of_expr (vr, innerop, stmt);
if (vr.undefined_p () || vr.varying_p ())
return false;
innermin = widest_int::from (vr.lower_bound (), TYPE_SIGN (TREE_TYPE (innerop)));
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 8c1b2e0..81b9131 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -116,7 +116,7 @@ class vr_values : public range_query
tree op_with_constant_singleton_value_range (tree);
void adjust_range_with_scev (value_range_equiv *, class loop *,
gimple *, tree);
- void dump_all_value_ranges (FILE *);
+ virtual void dump (FILE *) OVERRIDE;
void extract_range_for_var_from_comparison_expr (tree, enum tree_code,
tree, tree,
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index accd3df..67bf1f0 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,18 @@
+2021-05-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgomp/100573
+ * config/nvptx/target.c (GOMP_target_ext, GOMP_target_data_ext,
+ GOMP_target_end_data, GOMP_target_update_ext,
+ GOMP_target_enter_exit_data): New dummy entrypoints.
+ * config/gcn/target.c (GOMP_target_ext, GOMP_target_data_ext,
+ GOMP_target_end_data, GOMP_target_update_ext,
+ GOMP_target_enter_exit_data): Likewise.
+ * testsuite/libgomp.c-c++-common/for-3.c (DO_PRAGMA, OMPTEAMS,
+ OMPFROM, OMPTO): Define.
+ (main): Remove #pragma omp target teams around all the tests.
+ * testsuite/libgomp.c-c++-common/target-41.c: New test.
+ * testsuite/libgomp.c-c++-common/target-42.c: New test.
+
2021-05-25 Jakub Jelinek <jakub@redhat.com>
PR middle-end/99928
diff --git a/libgomp/config/gcn/target.c b/libgomp/config/gcn/target.c
index 4016b7b..a93ecc9 100644
--- a/libgomp/config/gcn/target.c
+++ b/libgomp/config/gcn/target.c
@@ -65,3 +65,68 @@ omp_pause_resource_all (omp_pause_resource_t kind)
ialias (omp_pause_resource)
ialias (omp_pause_resource_all)
+
+void
+GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend, void **args)
+{
+ (void) device;
+ (void) fn;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ (void) args;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_end_data (void)
+{
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
diff --git a/libgomp/config/nvptx/target.c b/libgomp/config/nvptx/target.c
index 1410577..e4140e4 100644
--- a/libgomp/config/nvptx/target.c
+++ b/libgomp/config/nvptx/target.c
@@ -65,3 +65,68 @@ omp_pause_resource_all (omp_pause_resource_t kind)
ialias (omp_pause_resource)
ialias (omp_pause_resource_all)
+
+void
+GOMP_target_ext (int device, void (*fn) (void *), size_t mapnum,
+ void **hostaddrs, size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend, void **args)
+{
+ (void) device;
+ (void) fn;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ (void) args;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_data_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_end_data (void)
+{
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_update_ext (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
+
+void
+GOMP_target_enter_exit_data (int device, size_t mapnum, void **hostaddrs,
+ size_t *sizes, unsigned short *kinds,
+ unsigned int flags, void **depend)
+{
+ (void) device;
+ (void) mapnum;
+ (void) hostaddrs;
+ (void) sizes;
+ (void) kinds;
+ (void) flags;
+ (void) depend;
+ __builtin_unreachable ();
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/for-3.c b/libgomp/testsuite/libgomp.c-c++-common/for-3.c
index 173ce8e..285f8e9 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/for-3.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/for-3.c
@@ -9,6 +9,11 @@ void abort ();
#define M(x, y, z) O(x, y, z)
#define O(x, y, z) x ## _ ## y ## _ ## z
+#define DO_PRAGMA(x) _Pragma (#x)
+#define OMPTEAMS DO_PRAGMA (omp target teams)
+#define OMPFROM(v) DO_PRAGMA (omp target update from(v))
+#define OMPTO(v) DO_PRAGMA (omp target update to(v))
+
#pragma omp declare target
#define F distribute
@@ -81,33 +86,30 @@ int
main ()
{
int err = 0;
- #pragma omp target teams reduction(|:err)
- {
- err |= test_d_normal ();
- err |= test_d_ds128_normal ();
- err |= test_ds_normal ();
- err |= test_ds_ds128_normal ();
- err |= test_dpf_static ();
- err |= test_dpf_static32 ();
- err |= test_dpf_auto ();
- err |= test_dpf_guided32 ();
- err |= test_dpf_runtime ();
- err |= test_dpf_ds128_static ();
- err |= test_dpf_ds128_static32 ();
- err |= test_dpf_ds128_auto ();
- err |= test_dpf_ds128_guided32 ();
- err |= test_dpf_ds128_runtime ();
- err |= test_dpfs_static ();
- err |= test_dpfs_static32 ();
- err |= test_dpfs_auto ();
- err |= test_dpfs_guided32 ();
- err |= test_dpfs_runtime ();
- err |= test_dpfs_ds128_static ();
- err |= test_dpfs_ds128_static32 ();
- err |= test_dpfs_ds128_auto ();
- err |= test_dpfs_ds128_guided32 ();
- err |= test_dpfs_ds128_runtime ();
- }
+ err |= test_d_normal ();
+ err |= test_d_ds128_normal ();
+ err |= test_ds_normal ();
+ err |= test_ds_ds128_normal ();
+ err |= test_dpf_static ();
+ err |= test_dpf_static32 ();
+ err |= test_dpf_auto ();
+ err |= test_dpf_guided32 ();
+ err |= test_dpf_runtime ();
+ err |= test_dpf_ds128_static ();
+ err |= test_dpf_ds128_static32 ();
+ err |= test_dpf_ds128_auto ();
+ err |= test_dpf_ds128_guided32 ();
+ err |= test_dpf_ds128_runtime ();
+ err |= test_dpfs_static ();
+ err |= test_dpfs_static32 ();
+ err |= test_dpfs_auto ();
+ err |= test_dpfs_guided32 ();
+ err |= test_dpfs_runtime ();
+ err |= test_dpfs_ds128_static ();
+ err |= test_dpfs_ds128_static32 ();
+ err |= test_dpfs_ds128_auto ();
+ err |= test_dpfs_ds128_guided32 ();
+ err |= test_dpfs_ds128_runtime ();
if (err)
abort ();
return 0;
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-41.c b/libgomp/testsuite/libgomp.c-c++-common/target-41.c
new file mode 100644
index 0000000..3aca19a
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-41.c
@@ -0,0 +1,28 @@
+/* PR libgomp/100573 */
+
+int
+foo (int a)
+{
+ if (a == 0)
+ {
+ int c;
+ a++;
+ #pragma omp target map(tofrom:a)
+ a = foo (a);
+ #pragma omp target data map(tofrom:a)
+ c = a != 2;
+ if (c)
+ return -1;
+ #pragma omp target enter data map(to:a)
+ #pragma omp target exit data map(from:a)
+ }
+ return a + 1;
+}
+
+int
+main ()
+{
+ if (foo (0) != 3)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-42.c b/libgomp/testsuite/libgomp.c-c++-common/target-42.c
new file mode 100644
index 0000000..a334f47
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-42.c
@@ -0,0 +1,26 @@
+/* PR libgomp/100573 */
+
+int
+foo (int a)
+{
+ #pragma omp target firstprivate(a)
+ if (a == 0)
+ {
+ a++;
+ #pragma omp target map(tofrom:a) /* { dg-warning "'target' construct inside of 'target' region" } */
+ a = foo (a);
+ #pragma omp target data map(tofrom:a) /* { dg-warning "'target data' construct inside of 'target' region" } */
+ a++;
+ #pragma omp target enter data map(to:a) /* { dg-warning "'target enter data' construct inside of 'target' region" } */
+ #pragma omp target exit data map(from:a) /* { dg-warning "'target exit data' construct inside of 'target' region" } */
+ }
+ return a + 1;
+}
+
+int
+main ()
+{
+ if (foo (1) != 2)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 3297f63..879b2ec 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,41 @@
+2021-05-26 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/debug/formatter.h
+ (_Error_formatter::_Parameter::_Named): New.
+ (_Error_formatter::_Parameter::_Type): Inherit latter.
+ (_Error_formatter::_Parameter::_M_integer): Likewise.
+ (_Error_formatter::_Parameter::_M_string): Likewise.
+ * src/c++11/debug.cc: Include <cstring>.
+ (_Print_func_t): New.
+ (print_raw(PrintContext&, const char*, ptrdiff_t)): New.
+ (print_word): Use '%.*s' format in fprintf to render only expected number of chars.
+ (pretty_print(PrintContext&, const char*, _Print_func_t)): New.
+ (print_type): Rename in...
+ (print_type_info): ...this. Use pretty_print.
+ (print_address, print_integer): New.
+ (print_named_name, print_iterator_constness, print_iterator_state): New.
+ (print_iterator_seq_type): New.
+ (print_named_field, print_type_field, print_instance_field, print_iterator_field): New.
+ (print_field): Use latters.
+ (print_quoted_named_name, print_type_type, print_type, print_instance): New.
+ (print_string(PrintContext&, const char*, const _Parameter*, size_t)):
+ Change signature to...
+ (print_string(PrintContext&, const char*, ptrdiff_t, const _Parameter*, size_t)):
+ ...this and adapt. Remove intermediate buffer to render input string.
+ (print_string(PrintContext&, const char*, ptrdiff_t)): New.
+
+2021-05-26 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/100768
+ * include/bits/ranges_base.h (advance, distance, next, prev):
+ Replace function templates with function objects.
+ * testsuite/24_iterators/headers/iterator/synopsis_c++20.cc:
+ Adjust for changes to function objects.
+ * testsuite/std/ranges/adaptors/elements.cc: Add using
+ declarations for names from namespace ranges.
+ * testsuite/std/ranges/adaptors/transform.cc: Likewise.
+ * testsuite/24_iterators/range_operations/100768.cc: New test.
+
2021-05-24 François Dumont <fdumont@gcc.gnu.org>
PR libstdc++/96088
diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 9e5461f..11f05fa 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -674,197 +674,213 @@ namespace ranges
// [range.iter.ops] range iterator operations
- template<input_or_output_iterator _It>
- constexpr void
- advance(_It& __it, iter_difference_t<_It> __n)
- {
- if constexpr (random_access_iterator<_It>)
- __it += __n;
- else if constexpr (bidirectional_iterator<_It>)
- {
- if (__n > 0)
- {
- do
- {
- ++__it;
- }
- while (--__n);
- }
- else if (__n < 0)
- {
- do
- {
- --__it;
- }
- while (++__n);
- }
- }
- else
- {
- // cannot decrement a non-bidirectional iterator
- __glibcxx_assert(__n >= 0);
- while (__n-- > 0)
- ++__it;
- }
- }
-
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr void
- advance(_It& __it, _Sent __bound)
- {
- if constexpr (assignable_from<_It&, _Sent>)
- __it = std::move(__bound);
- else if constexpr (sized_sentinel_for<_Sent, _It>)
- ranges::advance(__it, __bound - __it);
- else
- {
- while (__it != __bound)
- ++__it;
- }
- }
+ struct __advance_fn
+ {
+ template<input_or_output_iterator _It>
+ constexpr void
+ operator()(_It& __it, iter_difference_t<_It> __n) const
+ {
+ if constexpr (random_access_iterator<_It>)
+ __it += __n;
+ else if constexpr (bidirectional_iterator<_It>)
+ {
+ if (__n > 0)
+ {
+ do
+ {
+ ++__it;
+ }
+ while (--__n);
+ }
+ else if (__n < 0)
+ {
+ do
+ {
+ --__it;
+ }
+ while (++__n);
+ }
+ }
+ else
+ {
+ // cannot decrement a non-bidirectional iterator
+ __glibcxx_assert(__n >= 0);
+ while (__n-- > 0)
+ ++__it;
+ }
+ }
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr iter_difference_t<_It>
- advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
- {
- if constexpr (sized_sentinel_for<_Sent, _It>)
- {
- const auto __diff = __bound - __it;
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated()
- && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)))
- throw "inconsistent directions for distance and bound";
-#endif
- // n and bound must not lead in opposite directions:
- __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
- const auto __absdiff = __diff < 0 ? -__diff : __diff;
- const auto __absn = __n < 0 ? -__n : __n;;
- if (__absn >= __absdiff)
- {
- ranges::advance(__it, __bound);
- return __n - __diff;
- }
- else
- {
- ranges::advance(__it, __n);
- return 0;
- }
- }
- else if (__it == __bound || __n == 0)
- return iter_difference_t<_It>(0);
- else if (__n > 0)
- {
- iter_difference_t<_It> __m = 0;
- do
- {
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr void
+ operator()(_It& __it, _Sent __bound) const
+ {
+ if constexpr (assignable_from<_It&, _Sent>)
+ __it = std::move(__bound);
+ else if constexpr (sized_sentinel_for<_Sent, _It>)
+ (*this)(__it, __bound - __it);
+ else
+ {
+ while (__it != __bound)
++__it;
- ++__m;
- }
- while (__m != __n && __it != __bound);
- return __n - __m;
- }
- else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
- {
- iter_difference_t<_It> __m = 0;
- do
- {
- --__it;
- --__m;
- }
- while (__m != __n && __it != __bound);
- return __n - __m;
- }
- else
- {
- // cannot decrement a non-bidirectional iterator
- __glibcxx_assert(__n >= 0);
- return __n;
- }
- }
+ }
+ }
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr iter_difference_t<_It>
- distance(_It __first, _Sent __last)
- {
- if constexpr (sized_sentinel_for<_Sent, _It>)
- return __last - __first;
- else
- {
- iter_difference_t<_It> __n = 0;
- while (__first != __last)
- {
- ++__first;
- ++__n;
- }
- return __n;
- }
- }
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ operator()(_It& __it, iter_difference_t<_It> __n, _Sent __bound) const
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ {
+ const auto __diff = __bound - __it;
+
+ // n and bound must not lead in opposite directions:
+ __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
+ const auto __absdiff = __diff < 0 ? -__diff : __diff;
+ const auto __absn = __n < 0 ? -__n : __n;;
+ if (__absn >= __absdiff)
+ {
+ (*this)(__it, __bound);
+ return __n - __diff;
+ }
+ else
+ {
+ (*this)(__it, __n);
+ return 0;
+ }
+ }
+ else if (__it == __bound || __n == 0)
+ return iter_difference_t<_It>(0);
+ else if (__n > 0)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ ++__it;
+ ++__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
+ {
+ iter_difference_t<_It> __m = 0;
+ do
+ {
+ --__it;
+ --__m;
+ }
+ while (__m != __n && __it != __bound);
+ return __n - __m;
+ }
+ else
+ {
+ // cannot decrement a non-bidirectional iterator
+ __glibcxx_assert(__n >= 0);
+ return __n;
+ }
+ }
+ };
- template<range _Range>
- constexpr range_difference_t<_Range>
- distance(_Range&& __r)
- {
- if constexpr (sized_range<_Range>)
- return static_cast<range_difference_t<_Range>>(ranges::size(__r));
- else
- return ranges::distance(ranges::begin(__r), ranges::end(__r));
- }
-
- template<input_or_output_iterator _It>
- constexpr _It
- next(_It __x)
- {
- ++__x;
- return __x;
- }
+ inline constexpr __advance_fn advance{};
- template<input_or_output_iterator _It>
- constexpr _It
- next(_It __x, iter_difference_t<_It> __n)
- {
- ranges::advance(__x, __n);
- return __x;
- }
+ struct __distance_fn
+ {
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr iter_difference_t<_It>
+ operator()(_It __first, _Sent __last) const
+ {
+ if constexpr (sized_sentinel_for<_Sent, _It>)
+ return __last - __first;
+ else
+ {
+ iter_difference_t<_It> __n = 0;
+ while (__first != __last)
+ {
+ ++__first;
+ ++__n;
+ }
+ return __n;
+ }
+ }
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr _It
- next(_It __x, _Sent __bound)
- {
- ranges::advance(__x, __bound);
- return __x;
- }
+ template<range _Range>
+ constexpr range_difference_t<_Range>
+ operator()(_Range&& __r) const
+ {
+ if constexpr (sized_range<_Range>)
+ return static_cast<range_difference_t<_Range>>(ranges::size(__r));
+ else
+ return (*this)(ranges::begin(__r), ranges::end(__r));
+ }
+ };
- template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
- constexpr _It
- next(_It __x, iter_difference_t<_It> __n, _Sent __bound)
- {
- ranges::advance(__x, __n, __bound);
- return __x;
- }
+ inline constexpr __distance_fn distance{};
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x)
- {
- --__x;
- return __x;
- }
+ struct __next_fn
+ {
+ template<input_or_output_iterator _It>
+ constexpr _It
+ operator()(_It __x) const
+ {
+ ++__x;
+ return __x;
+ }
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x, iter_difference_t<_It> __n)
- {
- ranges::advance(__x, -__n);
- return __x;
- }
+ template<input_or_output_iterator _It>
+ constexpr _It
+ operator()(_It __x, iter_difference_t<_It> __n) const
+ {
+ ranges::advance(__x, __n);
+ return __x;
+ }
- template<bidirectional_iterator _It>
- constexpr _It
- prev(_It __x, iter_difference_t<_It> __n, _It __bound)
- {
- ranges::advance(__x, -__n, __bound);
- return __x;
- }
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ operator()(_It __x, _Sent __bound) const
+ {
+ ranges::advance(__x, __bound);
+ return __x;
+ }
+
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ constexpr _It
+ operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const
+ {
+ ranges::advance(__x, __n, __bound);
+ return __x;
+ }
+ };
+
+ inline constexpr __next_fn next{};
+
+ struct __prev_fn
+ {
+ template<bidirectional_iterator _It>
+ constexpr _It
+ operator()(_It __x) const
+ {
+ --__x;
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ operator()(_It __x, iter_difference_t<_It> __n) const
+ {
+ ranges::advance(__x, -__n);
+ return __x;
+ }
+
+ template<bidirectional_iterator _It>
+ constexpr _It
+ operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const
+ {
+ ranges::advance(__x, -__n, __bound);
+ return __x;
+ }
+ };
+
+ inline constexpr __prev_fn prev{};
/// Type returned by algorithms instead of a dangling iterator or subrange.
struct dangling
diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h
index 7140fed..a83d33a 100644
--- a/libstdc++-v3/include/debug/formatter.h
+++ b/libstdc++-v3/include/debug/formatter.h
@@ -202,9 +202,13 @@ namespace __gnu_debug
__iterator_value_type
} _M_kind;
- struct _Type
+ struct _Named
{
const char* _M_name;
+ };
+
+ struct _Type : _Named
+ {
const type_info* _M_type;
};
@@ -228,16 +232,14 @@ namespace __gnu_debug
_Instance _M_sequence;
// When _M_kind == __integer
- struct
+ struct : _Named
{
- const char* _M_name;
long _M_value;
} _M_integer;
// When _M_kind == __string
- struct
+ struct : _Named
{
- const char* _M_name;
const char* _M_value;
} _M_string;
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index 5a64209..33d76bf 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -34,16 +34,12 @@
#include <cassert>
#include <cstdio>
-#include <cctype> // for std::isspace
+#include <cctype> // for std::isspace.
+#include <cstring> // for std::strstr.
-#include <algorithm> // for std::min
+#include <algorithm> // for std::min.
-#include <cxxabi.h> // for __cxa_demangle
-
-// libstdc++/85768
-#if 0 // defined _GLIBCXX_HAVE_EXECINFO_H
-# include <execinfo.h> // for backtrace
-#endif
+#include <cxxabi.h> // for __cxa_demangle.
#include "mutex_pool.h"
@@ -574,7 +570,7 @@ namespace
struct PrintContext
{
PrintContext()
- : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
+ : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false)
{ get_max_length(_M_max_length); }
std::size_t _M_max_length;
@@ -584,16 +580,26 @@ namespace
bool _M_wordwrap;
};
+ using _Print_func_t = void (PrintContext&, const char*, ptrdiff_t);
+
template<size_t Length>
void
print_literal(PrintContext& ctx, const char(&word)[Length])
{ print_word(ctx, word, Length - 1); }
void
- print_word(PrintContext& ctx, const char* word,
- std::ptrdiff_t count = -1)
+ print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1)
{
- size_t length = count >= 0 ? count : __builtin_strlen(word);
+ if (nbc >= 0)
+ ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str);
+ else
+ ctx._M_column += fprintf(stderr, "%s", str);
+ }
+
+ void
+ print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1)
+ {
+ size_t length = nbc >= 0 ? nbc : __builtin_strlen(word);
if (length == 0)
return;
@@ -610,7 +616,7 @@ namespace
}
size_t visual_length
- = isspace(word[length - 1]) ? length - 1 : length;
+ = isspace((unsigned char)word[length - 1]) ? length - 1 : length;
if (visual_length == 0
|| !ctx._M_wordwrap
|| (ctx._M_column + visual_length < ctx._M_max_length)
@@ -619,15 +625,11 @@ namespace
// If this isn't the first line, indent
if (ctx._M_column == 1 && !ctx._M_first_line)
{
- char spacing[ctx._M_indent + 1];
- for (int i = 0; i < ctx._M_indent; ++i)
- spacing[i] = ' ';
- spacing[ctx._M_indent] = '\0';
- fprintf(stderr, "%s", spacing);
- ctx._M_column += ctx._M_indent;
+ const char spacing[ctx._M_indent + 1] = " ";
+ print_raw(ctx, spacing, ctx._M_indent);
}
- int written = fprintf(stderr, "%s", word);
+ int written = fprintf(stderr, "%.*s", (int)length, word);
if (word[length - 1] == '\n')
{
@@ -640,15 +642,40 @@ namespace
else
{
print_literal(ctx, "\n");
- print_word(ctx, word, count);
+ print_word(ctx, word, nbc);
+ }
+ }
+
+ void
+ pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func)
+ {
+ const char cxx1998[] = "cxx1998::";
+ for (;;)
+ {
+ if (auto pos = strstr(str, "__"))
+ {
+ if (pos != str)
+ print_func(ctx, str, pos - str);
+
+ pos += 2; // advance past "__"
+ if (memcmp(pos, cxx1998, 9) == 0)
+ pos += 9; // advance part "cxx1998::"
+
+ str = pos;
+ }
+ else
+ {
+ print_func(ctx, str, -1);
+ break;
+ }
}
}
template<size_t Length>
void
- print_type(PrintContext& ctx,
- const type_info* info,
- const char(&unknown_name)[Length])
+ print_type_info(PrintContext& ctx,
+ const type_info* info,
+ const char(&unknown_name)[Length])
{
if (!info)
print_literal(ctx, unknown_name);
@@ -657,22 +684,86 @@ namespace
int status;
char* demangled_name =
__cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status);
- print_word(ctx, status == 0 ? demangled_name : info->name());
+ if (status == 0)
+ pretty_print(ctx, demangled_name, &print_word);
+ else
+ print_word(ctx, info->name());
free(demangled_name);
}
}
+ void
+ print_address(PrintContext& ctx, const char* fmt, const void* address)
+ {
+ char buf[128];
+ int written = __builtin_sprintf(buf, fmt, address);
+ print_word(ctx, buf, written);
+ }
+
+ void
+ print_address(PrintContext& ctx, const void* address)
+ { print_address(ctx, "%p", address); }
+
+ void
+ print_integer(PrintContext& ctx, long integer)
+ {
+ char buf[64];
+ int written = __builtin_sprintf(buf, "%ld", integer);
+ print_word(ctx, buf, written);
+ }
+
+ void
+ print_named_name(PrintContext& ctx, const _Parameter::_Named& named)
+ {
+ assert(named._M_name);
+ pretty_print(ctx, named._M_name, print_word);
+ }
+
+ template<typename _Iterator>
+ void
+ print_iterator_constness(PrintContext& ctx, const _Iterator& iterator)
+ {
+ static const char*
+ constness_names[_Error_formatter::__last_constness] =
+ {
+ "<unknown constness>",
+ "constant",
+ "mutable"
+ };
+ print_word(ctx, constness_names[iterator._M_constness]);
+ }
+
+ template<typename _Iterator>
+ void
+ print_iterator_state(PrintContext& ctx, const _Iterator& iterator)
+ {
+ static const char*
+ state_names[_Error_formatter::__last_state] =
+ {
+ "<unknown state>",
+ "singular",
+ "dereferenceable (start-of-sequence)",
+ "dereferenceable",
+ "past-the-end",
+ "before-begin",
+ "dereferenceable (start-of-reverse-sequence)",
+ "dereferenceable (reverse)",
+ "past-the-reverse-end"
+ };
+ print_word(ctx, state_names[iterator._M_state]);
+ }
+
+ template<typename _Iterator>
+ void
+ print_iterator_seq_type(PrintContext& ctx, const _Iterator& iterator)
+ { print_type_info(ctx, iterator._M_seq_type, "<unknown seq_type>"); }
+
bool
- print_field(PrintContext& ctx,
- const char* name, const _Parameter::_Type& type)
+ print_named_field(PrintContext& ctx,
+ const char* fname, const _Parameter::_Named& named)
{
- if (__builtin_strcmp(name, "name") == 0)
- {
- assert(type._M_name);
- print_word(ctx, type._M_name);
- }
- else if (__builtin_strcmp(name, "type") == 0)
- print_type(ctx, type._M_type, "<unknown type>");
+ if (__builtin_strcmp(fname, "name") == 0)
+ print_named_name(ctx, named);
else
return false;
@@ -680,112 +771,92 @@ namespace
}
bool
- print_field(PrintContext& ctx,
- const char* name, const _Parameter::_Instance& inst)
+ print_type_field(PrintContext& ctx,
+ const char* fname, const _Parameter::_Type& type)
{
- const _Parameter::_Type& type = inst;
- if (print_field(ctx, name, type))
+ if (print_named_field(ctx, fname, type))
{ }
- else if (__builtin_strcmp(name, "address") == 0)
- {
- char buf[64];
- int ret = __builtin_sprintf(buf, "%p", inst._M_address);
- print_word(ctx, buf, ret);
- }
+ else if (__builtin_strcmp(fname, "type") == 0)
+ print_type_info(ctx, type._M_type, "<unknown type>");
+ else
+ return false;
+
+ return true;
+ }
+
+ bool
+ print_instance_field(PrintContext& ctx,
+ const char* fname, const _Parameter::_Instance& inst)
+ {
+ if (print_type_field(ctx, fname, inst))
+ { }
+ else if (__builtin_strcmp(fname, "address") == 0)
+ print_address(ctx, inst._M_address);
else
return false;
return true;
}
+ template<typename _Iterator>
+ bool
+ print_iterator_field(PrintContext& ctx,
+ const char* fname, const _Iterator& iterator)
+ {
+ if (print_instance_field(ctx, fname, iterator))
+ { }
+ else if (__builtin_strcmp(fname, "constness") == 0)
+ print_iterator_constness(ctx, iterator);
+ else if (__builtin_strcmp(fname, "state") == 0)
+ print_iterator_state(ctx, iterator);
+ else if (__builtin_strcmp(fname, "sequence") == 0)
+ {
+ assert(iterator._M_sequence);
+ print_address(ctx, iterator._M_sequence);
+ }
+ else if (__builtin_strcmp(fname, "seq_type") == 0)
+ print_iterator_seq_type(ctx, iterator);
+ else
+ return false;
+
+ return true;
+ }
+
void
- print_field(PrintContext& ctx, const _Parameter& param, const char* name)
+ print_field(PrintContext& ctx, const _Parameter& param, const char* fname)
{
assert(param._M_kind != _Parameter::__unused_param);
- const int bufsize = 64;
- char buf[bufsize];
const auto& variant = param._M_variant;
switch (param._M_kind)
{
case _Parameter::__iterator:
- {
- const auto& iterator = variant._M_iterator;
- if (print_field(ctx, name, iterator))
- { }
- else if (__builtin_strcmp(name, "constness") == 0)
- {
- static const char*
- constness_names[_Error_formatter::__last_constness] =
- {
- "<unknown constness>",
- "constant",
- "mutable"
- };
- print_word(ctx, constness_names[iterator._M_constness]);
- }
- else if (__builtin_strcmp(name, "state") == 0)
- {
- static const char*
- state_names[_Error_formatter::__last_state] =
- {
- "<unknown state>",
- "singular",
- "dereferenceable (start-of-sequence)",
- "dereferenceable",
- "past-the-end",
- "before-begin",
- "dereferenceable (start-of-reverse-sequence)",
- "dereferenceable (reverse)",
- "past-the-reverse-end"
- };
- print_word(ctx, state_names[iterator._M_state]);
- }
- else if (__builtin_strcmp(name, "sequence") == 0)
- {
- assert(iterator._M_sequence);
- int written = __builtin_sprintf(buf, "%p", iterator._M_sequence);
- print_word(ctx, buf, written);
- }
- else if (__builtin_strcmp(name, "seq_type") == 0)
- print_type(ctx, iterator._M_seq_type, "<unknown seq_type>");
- else
- assert(false);
- }
+ if (!print_iterator_field(ctx, fname, variant._M_iterator))
+ assert(false);
break;
case _Parameter::__sequence:
- if (!print_field(ctx, name, variant._M_sequence))
+ if (!print_instance_field(ctx, fname, variant._M_sequence))
assert(false);
break;
case _Parameter::__integer:
- if (__builtin_strcmp(name, "name") == 0)
- {
- assert(variant._M_integer._M_name);
- print_word(ctx, variant._M_integer._M_name);
- }
- else
+ if (!print_named_field(ctx, fname, variant._M_integer))
assert(false);
break;
case _Parameter::__string:
- if (__builtin_strcmp(name, "name") == 0)
- {
- assert(variant._M_string._M_name);
- print_word(ctx, variant._M_string._M_name);
- }
- else
+ if (!print_named_field(ctx, fname, variant._M_string))
assert(false);
break;
case _Parameter::__instance:
- if (!print_field(ctx, name, variant._M_instance))
+ if (!print_instance_field(ctx, fname, variant._M_instance))
assert(false);
break;
case _Parameter::__iterator_value_type:
- if (!print_field(ctx, name, variant._M_iterator_value_type))
+ if (!print_type_field(ctx, fname, variant._M_iterator_value_type))
assert(false);
break;
@@ -796,55 +867,53 @@ namespace
}
void
- print_description(PrintContext& ctx, const _Parameter::_Type& type)
+ print_quoted_named_name(PrintContext& ctx, const _Parameter::_Named& named)
{
- if (type._M_name)
+ if (named._M_name)
{
print_literal(ctx, "\"");
- print_word(ctx, type._M_name);
- print_literal(ctx, "\"");
+ print_named_name(ctx, named);
+ print_literal(ctx, "\" ");
}
+ }
- print_literal(ctx, " {\n");
-
+ void
+ print_type_type(PrintContext& ctx, const _Parameter::_Type& type,
+ bool close_desc = true)
+ {
if (type._M_type)
{
print_literal(ctx, " type = ");
- print_type(ctx, type._M_type, "<unknown type>");
- print_literal(ctx, ";\n");
+ print_type_info(ctx, type._M_type, "<unknown type>");
+ if (close_desc)
+ print_literal(ctx, ";\n");
}
}
void
- print_description(PrintContext& ctx, const _Parameter::_Instance& inst)
+ print_type(PrintContext& ctx, const _Parameter::_Type& type)
{
- const int bufsize = 64;
- char buf[bufsize];
-
- if (inst._M_name)
- {
- print_literal(ctx, "\"");
- print_word(ctx, inst._M_name);
- print_literal(ctx, "\" ");
- }
+ print_quoted_named_name(ctx, type);
+ print_literal(ctx, " {\n");
+ print_type_type(ctx, type);
+ print_literal(ctx, "}\n");
+ }
- int written
- = __builtin_sprintf(buf, "@ 0x%p {\n", inst._M_address);
- print_word(ctx, buf, written);
+ void
+ print_instance(PrintContext& ctx, const _Parameter::_Instance& inst,
+ bool close_desc = true)
+ {
+ print_quoted_named_name(ctx, inst);
+ print_address(ctx, "@ %p {\n", inst._M_address);
+ print_type_type(ctx, inst, close_desc);
- if (inst._M_type)
- {
- print_literal(ctx, " type = ");
- print_type(ctx, inst._M_type, "<unknown type>");
- }
+ if (close_desc)
+ print_literal(ctx, "}\n");
}
void
print_description(PrintContext& ctx, const _Parameter& param)
{
- const int bufsize = 128;
- char buf[bufsize];
-
const auto& variant = param._M_variant;
switch (param._M_kind)
{
@@ -853,14 +922,14 @@ namespace
const auto& ite = variant._M_iterator;
print_literal(ctx, "iterator ");
- print_description(ctx, ite);
+ print_instance(ctx, ite, false);
if (ite._M_type)
{
if (ite._M_constness != _Error_formatter::__unknown_constness)
{
print_literal(ctx, " (");
- print_field(ctx, param, "constness");
+ print_iterator_constness(ctx, ite);
print_literal(ctx, " iterator)");
}
@@ -870,7 +939,7 @@ namespace
if (ite._M_state != _Error_formatter::__unknown_state)
{
print_literal(ctx, " state = ");
- print_field(ctx, param, "state");
+ print_iterator_state(ctx, ite);
print_literal(ctx, ";\n");
}
@@ -880,13 +949,11 @@ namespace
if (ite._M_seq_type)
{
print_literal(ctx, "with type '");
- print_field(ctx, param, "seq_type");
+ print_iterator_seq_type(ctx, ite);
print_literal(ctx, "' ");
}
- int written
- = __builtin_sprintf(buf, "@ 0x%p\n", ite._M_sequence);
- print_word(ctx, buf, written);
+ print_address(ctx, "@ %p\n", ite._M_sequence);
}
print_literal(ctx, "}\n");
@@ -895,28 +962,17 @@ namespace
case _Parameter::__sequence:
print_literal(ctx, "sequence ");
- print_description(ctx, variant._M_sequence);
-
- if (variant._M_sequence._M_type)
- print_literal(ctx, ";\n");
-
- print_literal(ctx, "}\n");
+ print_instance(ctx, variant._M_sequence);
break;
case _Parameter::__instance:
print_literal(ctx, "instance ");
- print_description(ctx, variant._M_instance);
-
- if (variant._M_instance._M_type)
- print_literal(ctx, ";\n");
-
- print_literal(ctx, "}\n");
+ print_instance(ctx, variant._M_instance);
break;
case _Parameter::__iterator_value_type:
print_literal(ctx, "iterator::value_type ");
- print_description(ctx, variant._M_iterator_value_type);
- print_literal(ctx, "}\n");
+ print_type(ctx, variant._M_iterator_value_type);
break;
default:
@@ -925,71 +981,67 @@ namespace
}
void
- print_string(PrintContext& ctx, const char* string,
+ print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc,
const _Parameter* parameters, std::size_t num_parameters)
{
- const char* start = string;
- const int bufsize = 128;
- char buf[bufsize];
- int bufindex = 0;
+ const char* start = str;
+ const char* end = nbc >= 0 ? start + nbc : nullptr;
- while (*start)
+ while ((end && str != end) || (!end && *str))
{
- if (isspace(*start))
+ if (isspace((unsigned char)*str))
{
- buf[bufindex++] = *start++;
- buf[bufindex] = '\0';
- print_word(ctx, buf, bufindex);
- bufindex = 0;
+ ++str;
+ print_word(ctx, start, str - start);
+ start = str;
continue;
}
- if (!num_parameters || *start != '%')
+ if (!parameters || *str != '%')
{
// Normal char or no parameter to look for.
- buf[bufindex++] = *start++;
+ ++str;
continue;
}
- if (*++start == '%')
+ if (*++str == '%')
{
// Escaped '%'
- buf[bufindex++] = *start++;
+ print_word(ctx, start, str - start);
+ ++str;
+ start = str;
continue;
}
// We are on a parameter property reference, we need to flush buffer
// first.
- if (bufindex != 0)
+ if (str != start)
{
- buf[bufindex] = '\0';
- print_word(ctx, buf, bufindex);
- bufindex = 0;
+ // Avoid printing the '%'.
+ if (str - start > 1)
+ print_word(ctx, start, str - start - 1);
+ start = str;
}
// Get the parameter number
- assert(*start >= '1' && *start <= '9');
- size_t param_index = *start - '0' - 1;
+ assert(*str >= '1' && *str <= '9');
+ size_t param_index = *str - '0' - 1;
assert(param_index < num_parameters);
const auto& param = parameters[param_index];
// '.' separates the parameter number from the field
// name, if there is one.
- ++start;
- if (*start != '.')
+ ++str;
+ if (*str != '.')
{
- assert(*start == ';');
- ++start;
+ assert(*str == ';');
+ ++str;
if (param._M_kind == _Parameter::__integer)
- {
- int written
- = __builtin_sprintf(buf, "%ld",
- param._M_variant._M_integer._M_value);
- print_word(ctx, buf, written);
- }
+ print_integer(ctx, param._M_variant._M_integer._M_value);
else if (param._M_kind == _Parameter::__string)
- print_string(ctx, param._M_variant._M_string._M_value,
+ print_string(ctx, param._M_variant._M_string._M_value, -1,
parameters, num_parameters);
+ start = str;
continue;
}
@@ -997,26 +1049,28 @@ namespace
const int max_field_len = 16;
char field[max_field_len];
int field_idx = 0;
- ++start;
- while (*start != ';')
+ ++str;
+ while (*str != ';')
{
- assert(*start);
+ assert(*str);
assert(field_idx < max_field_len - 1);
- field[field_idx++] = *start++;
+ field[field_idx++] = *str++;
}
- ++start;
+ ++str;
field[field_idx] = '\0';
print_field(ctx, param, field);
+ start = str;
}
// Might need to flush.
- if (bufindex)
- {
- buf[bufindex] = '\0';
- print_word(ctx, buf, bufindex);
- }
+ if (str != start)
+ print_word(ctx, start, str - start);
}
+
+ void
+ print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc)
+ { print_string(ctx, str, nbc, nullptr, 0); }
}
namespace __gnu_debug
@@ -1036,16 +1090,15 @@ namespace __gnu_debug
PrintContext ctx;
if (_M_file)
{
- print_word(ctx, _M_file);
+ print_raw(ctx, _M_file);
print_literal(ctx, ":");
go_to_next_line = true;
}
if (_M_line > 0)
{
- char buf[64];
- int written = __builtin_sprintf(buf, "%u:", _M_line);
- print_word(ctx, buf, written);
+ ctx._M_column += fprintf(stderr, "%u", _M_line);
+ print_literal(ctx, ":");
go_to_next_line = true;
}
@@ -1058,41 +1111,17 @@ namespace __gnu_debug
if (_M_function)
{
print_literal(ctx, "In function:\n");
- print_string(ctx, _M_function, nullptr, 0);
+ pretty_print(ctx, _M_function, &print_string);
print_literal(ctx, "\n");
ctx._M_first_line = true;
print_literal(ctx, "\n");
}
-// libstdc++/85768
-#if 0 //defined _GLIBCXX_HAVE_EXECINFO_H
- {
- void* stack[32];
- int nb = backtrace(stack, 32);
-
- // Note that we skip current method symbol.
- if (nb > 1)
- {
- print_literal(ctx, "Backtrace:\n");
- auto symbols = backtrace_symbols(stack, nb);
- for (int i = 1; i < nb; ++i)
- {
- print_word(ctx, symbols[i]);
- print_literal(ctx, "\n");
- }
-
- free(symbols);
- ctx._M_first_line = true;
- print_literal(ctx, "\n");
- }
- }
-#endif
-
print_literal(ctx, "Error: ");
// Print the error message
assert(_M_text);
- print_string(ctx, _M_text, _M_parameters, _M_num_parameters);
+ print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters);
print_literal(ctx, ".\n");
// Emit descriptions of the objects involved in the operation
diff --git a/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc b/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
index 3103094..112d654 100644
--- a/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
+++ b/libstdc++-v3/testsuite/24_iterators/headers/iterator/synopsis_c++20.cc
@@ -31,26 +31,11 @@ namespace std
namespace ranges
{
- template<input_or_output_iterator I, sentinel_for<I> S>
- constexpr iter_difference_t<I> distance(I first, S last);
- template<range R>
- constexpr range_difference_t<R> distance(R&& r);
-
- template<input_or_output_iterator I>
- constexpr I next(I x);
- template<input_or_output_iterator I>
- constexpr I next(I x, iter_difference_t<I> n);
- template<input_or_output_iterator I, sentinel_for<I> S>
- constexpr I next(I x, S bound);
- template<input_or_output_iterator I, sentinel_for<I> S>
- constexpr I next(I x, iter_difference_t<I> n, S bound);
-
- template<bidirectional_iterator I>
- constexpr I prev(I x);
- template<bidirectional_iterator I>
- constexpr I prev(I x, iter_difference_t<I> n);
- template<bidirectional_iterator I>
- constexpr I prev(I x, iter_difference_t<I> n, I bound);
+ // These are function objects of unspecified type.
+ auto& _distance = distance;
+ auto& _advance = advance;
+ auto& _next = next;
+ auto& _prev = prev;
}
template<semiregular S> class move_sentinel;
diff --git a/libstdc++-v3/testsuite/24_iterators/range_operations/100768.cc b/libstdc++-v3/testsuite/24_iterators/range_operations/100768.cc
new file mode 100644
index 0000000..bbcfcec
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/range_operations/100768.cc
@@ -0,0 +1,128 @@
+// Copyright (C) 2021 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-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+// PR libstdc++/100768 - Range iterator operations should be function objects
+
+#include <iterator>
+#include <ranges>
+
+namespace ns1
+{
+ struct R { };
+ void check_adl(R) { }
+}
+
+namespace ns2
+{
+ using ns1::R;
+
+ struct A { };
+
+ template<typename I>
+ R advance(I, ...) { return R{}; }
+
+ template<typename I>
+ R distance(I, ...) { return R{}; }
+
+ template<typename I>
+ R next(I, ...) { return R{}; }
+
+ template<typename I>
+ R prev(I, ...) { return R{}; }
+}
+
+template<typename T, typename U> struct associated { };
+
+void
+test02()
+{
+ // This type has both ns2 and std::ranges as associated namespaces.
+ using X = associated<ns2::A, std::ranges::dangling>;
+
+ X range[1];
+ X* iter = range;
+ X* const sentinel = iter + 1;
+
+ // [range.iter.op.general] p2 says: "The function templates defined in
+ // [range.iter.ops] are not found by argument-dependent name lookup."
+ //
+ // If we do not meet that requirement then the following will find those
+ // function templates (because std::ranges is an associated namespace),
+ // and the calls to check_adl will be ill-formed.
+ check_adl( advance(iter, 1) );
+ check_adl( advance(iter, 1, sentinel) );
+ check_adl( distance(iter, sentinel) );
+ check_adl( distance(range) );
+ check_adl( next(iter) );
+ check_adl( next(iter, 1) );
+ check_adl( next(iter, sentinel) );
+ check_adl( next(iter, 1, sentinel) );
+ check_adl( prev(iter) );
+ check_adl( prev(iter, 1) );
+ check_adl( prev(iter, 1, sentinel) );
+}
+
+namespace ns3
+{
+ struct A { };
+
+ void advance(A*, int) = delete;
+ void advance(A*, int, A*) = delete;
+
+ void distance(A*, A*) = delete;
+ void distance(A(&)[1]) = delete;
+
+ void next(A*) = delete;
+ void next(A*, int) = delete;
+ void next(A*, A*) = delete;
+ void next(A*, int, A*) = delete;
+
+ void prev(A*) = delete;
+ void prev(A*, int) = delete;
+ void prev(A*, int, A*) = delete;
+}
+
+void
+test01()
+{
+ ns3::A range[1];
+ ns3::A* iter = range;
+ ns3::A* const sentinel = iter + 1;
+
+ // [range.iter.op.general] p2 also says: "When found by unqualified name
+ // lookup for the postfix-expression in a function call, they inhibit
+ // argument-dependent name lookup."
+ //
+ // If we do not meet that requirement then the following will find the
+ // deleted overloads in namespace ns3 (because it is an associated namespace
+ // and those functions are exact matches for the arguments).
+ using namespace std::ranges;
+ advance(iter, 1);
+ advance(iter, 3, sentinel);
+ distance(iter, sentinel);
+ distance(range);
+ next(iter);
+ next(iter, -1);
+ next(iter, sentinel);
+ next(iter, 5, sentinel);
+ prev(iter);
+ prev(iter, 0);
+ prev(iter, 0, sentinel);
+}
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
index 1322f44..633fb36 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc
@@ -76,6 +76,9 @@ struct X
void
test03()
{
+ using ranges::next;
+ using ranges::begin;
+
// LWG 3483
std::pair<int, X> x[3];
__gnu_test::test_forward_range<std::pair<int, X>> r(x);
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index ab2f28a..c2e7ba0 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -132,6 +132,9 @@ struct Y
void
test06()
{
+ using ranges::next;
+ using ranges::begin;
+
// LWG 3483
Y y[3];
__gnu_test::test_forward_range<Y> r(y);