From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-qv1-xf35.google.com (mail-qv1-xf35.google.com [IPv6:2607:f8b0:4864:20::f35]) by sourceware.org (Postfix) with ESMTPS id 89F083831C98 for ; Tue, 28 Jun 2022 07:37:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 89F083831C98 Received: by mail-qv1-xf35.google.com with SMTP id cs6so18834839qvb.6 for ; Tue, 28 Jun 2022 00:37:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=JAiuE9hF2Ir06WONYqI3BhHDgvSaKxQH8ilymaad2Zc=; b=Li9zdqFBdi4vhWLTJcYuzYUtLGl4Alfc7megxz9X2dDZD14iOV4oWV8JzmDszGDu+J HIE5xhdZ9zCspca488E2RAet6lJq4++J7bpG0t0iovrA2qMFDhZn4cImODaXoMPFrzqO /K9zC/VTqJKBdr/Wrdr4tEJ/mrnEt2HMttF50V8oYs9lLoJZ7GWe6Y09qDXZ47eGr2Lw HfsNIleEBbRx4bKu+Eptv+XENaABjqBIBHVK1m2q7lZY/NdlrIvgujD1ONBJMsCRSdEP PPOPepMiei+RHM/f5nO8jhoOy2gWSNhikj4YHznSgUJkw8oApNCyDcGvJWNBHIuN2PYQ 0cDQ== X-Gm-Message-State: AJIora9b6fLgh6ZAEI9Py7r07Q9+PgVRlnD6lE7xwDjSq+yJR+iONFKk hnWcQ4XyYnBtKW9ZdTpTPIXfcXaJJkURXPi1HE8B1NqplHo= X-Google-Smtp-Source: AGRyM1vUz4l1IHWozpSEl+gNZWSXmNx4QpkioAzptMnFAE02x6+NLRuQugKSofOy1PsuHAa5u4SOoYzwb2BduNTJsZg= X-Received: by 2002:a05:6214:2129:b0:470:396d:19c4 with SMTP id r9-20020a056214212900b00470396d19c4mr1420593qvc.34.1656401846585; Tue, 28 Jun 2022 00:37:26 -0700 (PDT) MIME-Version: 1.0 References: <20220627190358.126291-1-aldyh@redhat.com> In-Reply-To: <20220627190358.126291-1-aldyh@redhat.com> From: Richard Biener Date: Tue, 28 Jun 2022 09:37:15 +0200 Message-ID: Subject: Re: [PATCH] Remove legacy EVRP code. To: Aldy Hernandez Cc: GCC patches , Andrew MacLeod Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Jun 2022 07:37:32 -0000 On Mon, Jun 27, 2022 at 9:04 PM Aldy Hernandez wrote: > > With DOM converted to ranger, there are no longer any uses of the EVRP > engine. For that matter, we haven't used the legacy mode in quite a > while, so I think it's safe to remove any associated code. > > There are some methods in vr_values which should now be private, but I > didn't bother changing them, as most of the vr_values class will be > removed when VRP1 is converted to ranger. > > Does anyone have any issues with me pushing this? Fine with me. > gcc/ChangeLog: > > * Makefile.in: Remove gimple-ssa-evrp.o and gimple-ssa-evrp-analyze.o. > * flag-types.h (enum evrp_mode): Remove. > * params.opt: Remove --param=evrp-mode. > * tree-vrp.cc (make_pass_early_vrp): New. > (pass_vrp::execute): Call early VRP instance. > * gimple-ssa-evrp-analyze.cc: Removed. > * gimple-ssa-evrp-analyze.h: Removed. > * gimple-ssa-evrp.cc: Removed. > --- > gcc/Makefile.in | 2 - > gcc/flag-types.h | 9 - > gcc/gimple-ssa-evrp-analyze.cc | 456 -------------------------------- > gcc/gimple-ssa-evrp-analyze.h | 58 ---- > gcc/gimple-ssa-evrp.cc | 395 --------------------------- > gcc/params.opt | 19 -- > gcc/testsuite/g++.dg/pr100774.C | 2 +- > gcc/testsuite/gcc.dg/pr100781.c | 2 +- > gcc/tree-vrp.cc | 34 ++- > 9 files changed, 31 insertions(+), 946 deletions(-) > delete mode 100644 gcc/gimple-ssa-evrp-analyze.cc > delete mode 100644 gcc/gimple-ssa-evrp-analyze.h > delete mode 100644 gcc/gimple-ssa-evrp.cc > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index b6dcc45a58a..86257a8b84f 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1413,8 +1413,6 @@ OBJS = \ > gimple-range-infer.o \ > gimple-range-trace.o \ > gimple-ssa-backprop.o \ > - gimple-ssa-evrp.o \ > - gimple-ssa-evrp-analyze.o \ > gimple-ssa-isolate-paths.o \ > gimple-ssa-nonnull-compare.o \ > gimple-ssa-split-paths.o \ > diff --git a/gcc/flag-types.h b/gcc/flag-types.h > index 2c8498169e0..a11f99af887 100644 > --- a/gcc/flag-types.h > +++ b/gcc/flag-types.h > @@ -479,15 +479,6 @@ enum threader_debug > THREADER_DEBUG_ALL = 1 > }; > > -/* EVRP mode. */ > -enum evrp_mode > -{ > - EVRP_MODE_RVRP_ONLY, > - EVRP_MODE_EVRP_ONLY, > - EVRP_MODE_EVRP_FIRST, > - EVRP_MODE_RVRP_FIRST > -}; > - > /* VRP modes. */ > enum vrp_mode > { > diff --git a/gcc/gimple-ssa-evrp-analyze.cc b/gcc/gimple-ssa-evrp-analyze.cc > deleted file mode 100644 > index 82142db7976..00000000000 > --- a/gcc/gimple-ssa-evrp-analyze.cc > +++ /dev/null > @@ -1,456 +0,0 @@ > -/* Support routines for Value Range Propagation (VRP). > - Copyright (C) 2005-2022 Free Software Foundation, Inc. > - > -This file is part of GCC. > - > -GCC is free software; you can redistribute it and/or modify > -it under the terms of the GNU General Public License as published by > -the Free Software Foundation; either version 3, or (at your option) > -any later version. > - > -GCC is distributed in the hope that it will be useful, > -but WITHOUT ANY WARRANTY; without even the implied warranty of > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > -GNU General Public License for more details. > - > -You should have received a copy of the GNU General Public License > -along with GCC; see the file COPYING3. If not see > -. */ > - > -#include "config.h" > -#include "system.h" > -#include "coretypes.h" > -#include "backend.h" > -#include "tree.h" > -#include "gimple.h" > -#include "tree-pass.h" > -#include "ssa.h" > -#include "gimple-pretty-print.h" > -#include "cfganal.h" > -#include "gimple-iterator.h" > -#include "gimple-fold.h" > -#include "tree-eh.h" > -#include "tree-cfg.h" > -#include "tree-ssa-loop-manip.h" > -#include "tree-ssa-loop.h" > -#include "cfgloop.h" > -#include "tree-scalar-evolution.h" > -#include "tree-ssa-propagate.h" > -#include "alloc-pool.h" > -#include "domwalk.h" > -#include "tree-cfgcleanup.h" > -#include "vr-values.h" > -#include "gimple-ssa-evrp-analyze.h" > - > -evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges) > - : stack (10), m_update_global_ranges (update_global_ranges) > -{ > - edge e; > - edge_iterator ei; > - basic_block bb; > - FOR_EACH_BB_FN (bb, cfun) > - { > - bb->flags &= ~BB_VISITED; > - FOR_EACH_EDGE (e, ei, bb->preds) > - e->flags |= EDGE_EXECUTABLE; > - } > -} > - > -/* Push an unwinding marker onto the unwinding stack. */ > - > -void > -evrp_range_analyzer::push_marker () > -{ > - stack.safe_push (std::make_pair (NULL_TREE, (value_range_equiv *)NULL)); > -} > - > -/* Analyze ranges as we enter basic block BB. */ > - > -void > -evrp_range_analyzer::enter (basic_block bb) > -{ > - if (!optimize) > - return; > - push_marker (); > - record_ranges_from_incoming_edge (bb); > - record_ranges_from_phis (bb); > - bb->flags |= BB_VISITED; > -} > - > -/* Find new range for NAME such that (OP CODE LIMIT) is true. */ > -value_range_equiv * > -evrp_range_analyzer::try_find_new_range (tree name, > - tree op, tree_code code, tree limit) > -{ > - value_range_equiv vr; > - const value_range_equiv *old_vr = get_value_range (name); > - > - /* Discover VR when condition is true. */ > - extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr); > - /* If we found any usable VR, set the VR to ssa_name and create a > - PUSH old value in the stack with the old VR. */ > - if (!vr.undefined_p () && !vr.varying_p ()) > - { > - if (old_vr->equal_p (vr, /*ignore_equivs=*/true)) > - return NULL; > - value_range_equiv *new_vr = allocate_value_range_equiv (); > - new_vr->move (&vr); > - return new_vr; > - } > - return NULL; > -} > - > -/* For LHS record VR in the SSA info. */ > -void > -evrp_range_analyzer::set_ssa_range_info (tree lhs, value_range_equiv *vr) > -{ > - gcc_assert (m_update_global_ranges); > - > - /* Set the SSA with the value range. */ > - if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) > - { > - if (!vr->varying_p () && vr->constant_p ()) > - set_range_info (lhs, *vr); > - } > - else if (POINTER_TYPE_P (TREE_TYPE (lhs)) > - && range_includes_zero_p (vr) == 0) > - set_ptr_nonnull (lhs); > -} > - > -/* Return true if all uses of NAME are dominated by STMT or feed STMT > - via a chain of single immediate uses. */ > - > -static bool > -all_uses_feed_or_dominated_by_stmt (tree name, gimple *stmt) > -{ > - use_operand_p use_p, use2_p; > - imm_use_iterator iter; > - basic_block stmt_bb = gimple_bb (stmt); > - > - FOR_EACH_IMM_USE_FAST (use_p, iter, name) > - { > - gimple *use_stmt = USE_STMT (use_p), *use_stmt2; > - if (use_stmt == stmt > - || is_gimple_debug (use_stmt) > - || (gimple_bb (use_stmt) != stmt_bb > - && dominated_by_p (CDI_DOMINATORS, > - gimple_bb (use_stmt), stmt_bb))) > - continue; > - while (use_stmt != stmt > - && is_gimple_assign (use_stmt) > - && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME > - && single_imm_use (gimple_assign_lhs (use_stmt), > - &use2_p, &use_stmt2)) > - use_stmt = use_stmt2; > - if (use_stmt != stmt) > - return false; > - } > - return true; > -} > - > -void > -evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb) > -{ > - edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false); > - if (pred_e) > - { > - gimple *stmt = last_stmt (pred_e->src); > - tree op0 = NULL_TREE; > - > - if (stmt > - && gimple_code (stmt) == GIMPLE_COND > - && (op0 = gimple_cond_lhs (stmt)) > - && TREE_CODE (op0) == SSA_NAME > - && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))) > - || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))))) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "Visiting controlling predicate "); > - print_gimple_stmt (dump_file, stmt, 0); > - } > - /* Entering a new scope. Try to see if we can find a VR > - here. */ > - tree op1 = gimple_cond_rhs (stmt); > - if (TREE_OVERFLOW_P (op1)) > - op1 = drop_tree_overflow (op1); > - tree_code code = gimple_cond_code (stmt); > - > - auto_vec asserts; > - register_edge_assert_for (op0, pred_e, code, op0, op1, asserts); > - if (TREE_CODE (op1) == SSA_NAME) > - register_edge_assert_for (op1, pred_e, code, op0, op1, asserts); > - > - auto_vec, 8> vrs; > - for (unsigned i = 0; i < asserts.length (); ++i) > - { > - value_range_equiv *vr > - = try_find_new_range (asserts[i].name, > - asserts[i].expr, > - asserts[i].comp_code, > - asserts[i].val); > - if (vr) > - vrs.safe_push (std::make_pair (asserts[i].name, vr)); > - } > - > - /* If pred_e is really a fallthru we can record value ranges > - in SSA names as well. */ > - bool is_fallthru = assert_unreachable_fallthru_edge_p (pred_e); > - > - /* Push updated ranges only after finding all of them to avoid > - ordering issues that can lead to worse ranges. */ > - for (unsigned i = 0; i < vrs.length (); ++i) > - { > - /* But make sure we do not weaken ranges like when > - getting first [64, +INF] and then ~[0, 0] from > - conditions like (s & 0x3cc0) == 0). */ > - const value_range_equiv *old_vr > - = get_value_range (vrs[i].first); > - value_range tem (*old_vr); > - tem.legacy_verbose_intersect (vrs[i].second); > - if (tem.equal_p (*old_vr)) > - { > - free_value_range (vrs[i].second); > - continue; > - } > - push_value_range (vrs[i].first, vrs[i].second); > - if (is_fallthru > - && m_update_global_ranges > - && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt) > - /* The condition must post-dominate the definition point. */ > - && (SSA_NAME_IS_DEFAULT_DEF (vrs[i].first) > - || (gimple_bb (SSA_NAME_DEF_STMT (vrs[i].first)) > - == pred_e->src))) > - { > - set_ssa_range_info (vrs[i].first, vrs[i].second); > - maybe_set_nonzero_bits (pred_e, vrs[i].first); > - } > - } > - } > - } > -} > - > -void > -evrp_range_analyzer::record_ranges_from_phis (basic_block bb) > -{ > - /* Visit PHI stmts and discover any new VRs possible. */ > - bool has_unvisited_preds = false; > - edge_iterator ei; > - edge e; > - FOR_EACH_EDGE (e, ei, bb->preds) > - if (e->flags & EDGE_EXECUTABLE > - && !(e->src->flags & BB_VISITED)) > - { > - has_unvisited_preds = true; > - break; > - } > - > - for (gphi_iterator gpi = gsi_start_phis (bb); > - !gsi_end_p (gpi); gsi_next (&gpi)) > - { > - gphi *phi = gpi.phi (); > - tree lhs = PHI_RESULT (phi); > - if (virtual_operand_p (lhs)) > - continue; > - > - /* Skips floats and other things we can't represent in a > - range. */ > - if (!value_range_equiv::supports_p (TREE_TYPE (lhs))) > - continue; > - > - value_range_equiv vr_result; > - bool interesting = stmt_interesting_for_vrp (phi); > - if (!has_unvisited_preds && interesting) > - extract_range_from_phi_node (phi, &vr_result); > - else > - { > - vr_result.set_varying (TREE_TYPE (lhs)); > - /* When we have an unvisited executable predecessor we can't > - use PHI arg ranges which may be still UNDEFINED but have > - to use VARYING for them. But we can still resort to > - SCEV for loop header PHIs. */ > - class loop *l; > - if (scev_initialized_p () > - && interesting > - && (l = loop_containing_stmt (phi)) > - && l->header == gimple_bb (phi)) > - adjust_range_with_scev (&vr_result, l, phi, lhs); > - } > - update_value_range (lhs, &vr_result); > - > - /* Set the SSA with the value range. */ > - if (m_update_global_ranges) > - set_ssa_range_info (lhs, &vr_result); > - } > -} > - > -/* Record ranges from STMT into our VR_VALUES class. If TEMPORARY is > - true, then this is a temporary equivalence and should be recorded > - into the unwind table. Othewise record the equivalence into the > - global table. */ > - > -void > -evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary) > -{ > - tree output = NULL_TREE; > - > - if (!optimize) > - return; > - > - if (dyn_cast (stmt)) > - ; > - else if (stmt_interesting_for_vrp (stmt)) > - { > - edge taken_edge; > - value_range_equiv vr; > - extract_range_from_stmt (stmt, &taken_edge, &output, &vr); > - if (output) > - { > - /* Set the SSA with the value range. There are two cases to > - consider. First (the the most common) is we are processing > - STMT in a context where its resulting range globally holds > - and thus it can be reflected into the global ranges and need > - not be unwound as we leave scope. > - > - The second case occurs if we are processing a statement in > - a context where the resulting range must not be reflected > - into the global tables and must be unwound as we leave > - the current context. This happens in jump threading for > - example. */ > - if (!temporary) > - { > - /* Case one. We can just update the underlying range > - information as well as the global information. */ > - update_value_range (output, &vr); > - if (m_update_global_ranges) > - set_ssa_range_info (output, &vr); > - } > - else > - { > - /* We're going to need to unwind this range. We cannot > - use VR as that's a stack object. We have to allocate > - a new range and push the old range onto the stack. We > - also have to be very careful about sharing the underlying > - bitmaps. Ugh. */ > - value_range_equiv *new_vr = allocate_value_range_equiv (); > - new_vr->set (vr.min (), vr.max (), NULL, vr.kind ()); > - vr.equiv_clear (); > - push_value_range (output, new_vr); > - } > - } > - else > - set_defs_to_varying (stmt); > - } > - else > - set_defs_to_varying (stmt); > - > - /* See if we can derive a range for any of STMT's operands. */ > - tree op; > - ssa_op_iter i; > - FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE) > - { > - tree value; > - enum tree_code comp_code; > - > - /* If OP is used in such a way that we can infer a value > - range for it, and we don't find a previous assertion for > - it, create a new assertion location node for OP. */ > - if (infer_value_range (stmt, op, &comp_code, &value)) > - { > - /* If we are able to infer a nonzero value range for OP, > - then walk backwards through the use-def chain to see if OP > - was set via a typecast. > - If so, then we can also infer a nonzero value range > - for the operand of the NOP_EXPR. */ > - if (comp_code == NE_EXPR && integer_zerop (value)) > - { > - tree t = op; > - gimple *def_stmt = SSA_NAME_DEF_STMT (t); > - while (is_gimple_assign (def_stmt) > - && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)) > - && TREE_CODE > - (gimple_assign_rhs1 (def_stmt)) == SSA_NAME > - && POINTER_TYPE_P > - (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))) > - { > - t = gimple_assign_rhs1 (def_stmt); > - def_stmt = SSA_NAME_DEF_STMT (t); > - > - /* Add VR when (T COMP_CODE value) condition is > - true. */ > - value_range_equiv *op_range > - = try_find_new_range (t, t, comp_code, value); > - if (op_range) > - push_value_range (t, op_range); > - } > - } > - /* Add VR when (OP COMP_CODE value) condition is true. */ > - value_range_equiv *op_range = try_find_new_range (op, op, > - comp_code, value); > - if (op_range) > - push_value_range (op, op_range); > - } > - } > -} > - > -/* Unwind recorded ranges to their most recent state. */ > - > -void > -evrp_range_analyzer::pop_to_marker (void) > -{ > - gcc_checking_assert (!stack.is_empty ()); > - while (stack.last ().first != NULL_TREE) > - pop_value_range (); > - stack.pop (); > -} > - > -/* Restore/pop VRs valid only for BB when we leave BB. */ > - > -void > -evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED) > -{ > - if (!optimize) > - return; > - pop_to_marker (); > -} > - > - > -/* Push the Value Range of VAR to the stack and update it with new VR. */ > - > -void > -evrp_range_analyzer::push_value_range (tree var, value_range_equiv *vr) > -{ > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "pushing new range for "); > - print_generic_expr (dump_file, var); > - fprintf (dump_file, ": "); > - dump_value_range (dump_file, vr); > - fprintf (dump_file, "\n"); > - } > - value_range_equiv *old_vr = swap_vr_value (var, vr); > - stack.safe_push (std::make_pair (var, old_vr)); > -} > - > -/* Pop a Value Range from the vrp_stack. */ > - > -void > -evrp_range_analyzer::pop_value_range () > -{ > - std::pair e = stack.pop (); > - tree var = e.first; > - value_range_equiv *vr = e.second; > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "popping range for "); > - print_generic_expr (dump_file, var); > - fprintf (dump_file, ", restoring "); > - dump_value_range (dump_file, vr); > - fprintf (dump_file, "\n"); > - } > - /* We saved off a lattice entry, now give it back and release > - the one we popped. */ > - value_range_equiv *popped_vr = swap_vr_value (var, vr); > - if (popped_vr) > - free_value_range (popped_vr); > -} > diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h > deleted file mode 100644 > index 51c32099dc5..00000000000 > --- a/gcc/gimple-ssa-evrp-analyze.h > +++ /dev/null > @@ -1,58 +0,0 @@ > -/* Support routines for Value Range Propagation (VRP). > - Copyright (C) 2016-2022 Free Software Foundation, Inc. > - > -This file is part of GCC. > - > -GCC is free software; you can redistribute it and/or modify > -it under the terms of the GNU General Public License as published by > -the Free Software Foundation; either version 3, or (at your option) > -any later version. > - > -GCC is distributed in the hope that it will be useful, > -but WITHOUT ANY WARRANTY; without even the implied warranty of > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > -GNU General Public License for more details. > - > -You should have received a copy of the GNU General Public License > -along with GCC; see the file COPYING3. If not see > -. */ > - > -#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H > -#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H > - > -class evrp_range_analyzer : public vr_values > -{ > - public: > - evrp_range_analyzer (bool update_global_ranges); > - ~evrp_range_analyzer (void) > - { > - stack.release (); > - } > - > - void enter (basic_block); > - void push_marker (void); > - void pop_to_marker (void); > - void leave (basic_block); > - void record_ranges_from_stmt (gimple *, bool); > - > - /* Record a new unwindable range. */ > - void push_value_range (tree var, value_range_equiv *vr); > - > - private: > - DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer); > - > - void pop_value_range (); > - value_range_equiv *try_find_new_range (tree, tree op, tree_code code, > - tree limit); > - void record_ranges_from_incoming_edge (basic_block); > - void record_ranges_from_phis (basic_block); > - void set_ssa_range_info (tree, value_range_equiv *); > - > - /* STACK holds the old VR. */ > - auto_vec > stack; > - > - /* True if we are updating global ranges, false otherwise. */ > - bool m_update_global_ranges; > -}; > - > -#endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */ > diff --git a/gcc/gimple-ssa-evrp.cc b/gcc/gimple-ssa-evrp.cc > deleted file mode 100644 > index 20388ed5431..00000000000 > --- a/gcc/gimple-ssa-evrp.cc > +++ /dev/null > @@ -1,395 +0,0 @@ > -/* Support routines for Value Range Propagation (VRP). > - Copyright (C) 2005-2022 Free Software Foundation, Inc. > - > -This file is part of GCC. > - > -GCC is free software; you can redistribute it and/or modify > -it under the terms of the GNU General Public License as published by > -the Free Software Foundation; either version 3, or (at your option) > -any later version. > - > -GCC is distributed in the hope that it will be useful, > -but WITHOUT ANY WARRANTY; without even the implied warranty of > -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > -GNU General Public License for more details. > - > -You should have received a copy of the GNU General Public License > -along with GCC; see the file COPYING3. If not see > -. */ > - > -#include "config.h" > -#include "system.h" > -#include "coretypes.h" > -#include "backend.h" > -#include "tree.h" > -#include "gimple.h" > -#include "tree-pass.h" > -#include "ssa.h" > -#include "gimple-pretty-print.h" > -#include "cfganal.h" > -#include "gimple-iterator.h" > -#include "gimple-fold.h" > -#include "tree-eh.h" > -#include "tree-cfg.h" > -#include "tree-ssa-loop-manip.h" > -#include "tree-ssa-loop.h" > -#include "cfgloop.h" > -#include "tree-scalar-evolution.h" > -#include "tree-ssa-propagate.h" > -#include "alloc-pool.h" > -#include "domwalk.h" > -#include "tree-cfgcleanup.h" > -#include "vr-values.h" > -#include "gimple-ssa-evrp-analyze.h" > -#include "gimple-range.h" > -#include "fold-const.h" > -#include "value-pointer-equiv.h" > -#include "tree-vrp.h" > - > -// This is the classic EVRP folder which uses a dominator walk and pushes > -// ranges into the next block if it is a single predecessor block. > - > -class evrp_folder : public substitute_and_fold_engine > -{ > -public: > - evrp_folder () : > - substitute_and_fold_engine (), > - m_range_analyzer (/*update_global_ranges=*/true), > - simplifier (&m_range_analyzer) > - { } > - > - ~evrp_folder () > - { > - if (dump_file) > - { > - fprintf (dump_file, "\nValue ranges after Early VRP:\n\n"); > - m_range_analyzer.dump (dump_file); > - fprintf (dump_file, "\n"); > - } > - } > - > - tree value_of_expr (tree name, gimple *stmt) override > - { > - return m_range_analyzer.value_of_expr (name, stmt); > - } > - > - void pre_fold_bb (basic_block bb) override > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, "evrp visiting BB%d\n", bb->index); > - m_range_analyzer.enter (bb); > - } > - > - void pre_fold_stmt (gimple *stmt) override > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "evrp visiting stmt "); > - print_gimple_stmt (dump_file, stmt, 0); > - } > - m_range_analyzer.record_ranges_from_stmt (stmt, false); > - } > - > - bool fold_stmt (gimple_stmt_iterator *gsi) override > - { > - return simplifier.simplify (gsi); > - } > - > - void post_fold_bb (basic_block bb) override > - { > - m_range_analyzer.leave (bb); > - } > - > - void post_new_stmt (gimple *stmt) override > - { > - m_range_analyzer.set_defs_to_varying (stmt); > - } > - > -protected: > - DISABLE_COPY_AND_ASSIGN (evrp_folder); > - evrp_range_analyzer m_range_analyzer; > - simplify_using_ranges simplifier; > -}; > - > -// In a hybrid folder, start with an EVRP folder, and add the required > -// fold_stmt bits to either try the ranger first or second. > -// > -// The 3 value_* routines will always query both EVRP and the ranger for > -// a result, and ensure they return the same value. If either returns a value > -// when the other doesn't, it is flagged in the listing, and the discoverd > -// value is returned. > -// > -// The simplifier is unable to process 2 different sources, thus we try to > -// use one engine, and if it fails to simplify, try using the other engine. > -// It is reported when the first attempt fails and the second succeeds. > - > -class hybrid_folder : public evrp_folder > -{ > -public: > - hybrid_folder (bool evrp_first) > - { > - m_ranger = enable_ranger (cfun); > - > - if (evrp_first) > - { > - first = &m_range_analyzer; > - first_exec_flag = 0; > - second = m_ranger; > - second_exec_flag = m_ranger->non_executable_edge_flag; > - } > - else > - { > - first = m_ranger; > - first_exec_flag = m_ranger->non_executable_edge_flag; > - second = &m_range_analyzer; > - second_exec_flag = 0; > - } > - m_pta = new pointer_equiv_analyzer (m_ranger); > - } > - > - ~hybrid_folder () > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - m_ranger->dump (dump_file); > - > - m_ranger->export_global_ranges (); > - disable_ranger (cfun); > - delete m_pta; > - } > - > - bool fold_stmt (gimple_stmt_iterator *gsi) override > - { > - simplifier.set_range_query (first, first_exec_flag); > - if (simplifier.simplify (gsi)) > - return true; > - > - simplifier.set_range_query (second, second_exec_flag); > - if (simplifier.simplify (gsi)) > - { > - if (dump_file) > - fprintf (dump_file, "EVRP:hybrid: Second query simplifed stmt\n"); > - return true; > - } > - return false; > - } > - > - void pre_fold_stmt (gimple *stmt) override > - { > - evrp_folder::pre_fold_stmt (stmt); > - m_pta->visit_stmt (stmt); > - } > - > - void pre_fold_bb (basic_block bb) override > - { > - evrp_folder::pre_fold_bb (bb); > - m_pta->enter (bb); > - } > - > - void post_fold_bb (basic_block bb) override > - { > - evrp_folder::post_fold_bb (bb); > - m_pta->leave (bb); > - } > - > - tree value_of_expr (tree name, gimple *) override; > - tree value_on_edge (edge, tree name) override; > - tree value_of_stmt (gimple *, tree name) override; > - > -private: > - DISABLE_COPY_AND_ASSIGN (hybrid_folder); > - gimple_ranger *m_ranger; > - range_query *first; > - int first_exec_flag; > - range_query *second; > - int second_exec_flag; > - pointer_equiv_analyzer *m_pta; > - tree choose_value (tree evrp_val, tree ranger_val); > -}; > - > - > -tree > -hybrid_folder::value_of_expr (tree op, gimple *stmt) > -{ > - tree evrp_ret = evrp_folder::value_of_expr (op, stmt); > - tree ranger_ret; > - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op)) > - ranger_ret = NULL; > - else > - { > - ranger_ret = m_ranger->value_of_expr (op, stmt); > - if (!ranger_ret && supported_pointer_equiv_p (op)) > - ranger_ret = m_pta->get_equiv (op); > - } > - return choose_value (evrp_ret, ranger_ret); > -} > - > -tree > -hybrid_folder::value_on_edge (edge e, tree op) > -{ > - // Call evrp::value_of_expr directly. Otherwise another dual call is made > - // via hybrid_folder::value_of_expr, but without an edge. > - tree evrp_ret = evrp_folder::value_of_expr (op, NULL); > - tree ranger_ret; > - if (TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op)) > - ranger_ret = NULL; > - else > - { > - ranger_ret = m_ranger->value_on_edge (e, op); > - if (!ranger_ret && supported_pointer_equiv_p (op)) > - ranger_ret = m_pta->get_equiv (op); > - } > - return choose_value (evrp_ret, ranger_ret); > -} > - > -tree > -hybrid_folder::value_of_stmt (gimple *stmt, tree op) > -{ > - // Call evrp::value_of_expr directly. Otherwise another dual call is made > - // via hybrid_folder::value_of_expr, but without a stmt. > - tree evrp_ret; > - if (op) > - evrp_ret = evrp_folder::value_of_expr (op, NULL); > - else > - evrp_ret = NULL_TREE; > - > - tree ranger_ret; > - if (op && TREE_CODE (op) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op)) > - ranger_ret = NULL; > - else > - ranger_ret = m_ranger->value_of_stmt (stmt, op); > - return choose_value (evrp_ret, ranger_ret); > -} > - > -// Given trees returned by EVRP and Ranger, choose/report the value to use > -// by the folder. > - > -tree > -hybrid_folder::choose_value (tree evrp_val, tree ranger_val) > -{ > - // If both found the same value, just return it. > - if (evrp_val && ranger_val && !compare_values (evrp_val, ranger_val)) > - return evrp_val; > - > - // If neither returned a value, return NULL_TREE. > - if (!ranger_val && !evrp_val) > - return NULL_TREE; > - > - // Otherwise there is a discrepancy to flag. > - if (dump_file) > - { > - if (evrp_val && ranger_val) > - fprintf (dump_file, "EVRP:hybrid: Disagreement\n"); > - if (evrp_val) > - { > - fprintf (dump_file, "EVRP:hybrid: EVRP found singleton "); > - print_generic_expr (dump_file, evrp_val); > - fprintf (dump_file, "\n"); > - } > - if (ranger_val) > - { > - fprintf (dump_file, "EVRP:hybrid: RVRP found singleton "); > - print_generic_expr (dump_file, ranger_val); > - fprintf (dump_file, "\n"); > - } > - } > - > - // If one value was found, return it. > - if (!evrp_val) > - return ranger_val; > - if (!ranger_val) > - return evrp_val; > - > - // If values are different, return the first calculated value. > - if (param_evrp_mode == EVRP_MODE_RVRP_FIRST) > - return ranger_val; > - return evrp_val; > -} > - > -/* Main entry point for the early vrp pass which is a simplified non-iterative > - version of vrp where basic blocks are visited in dominance order. Value > - ranges discovered in early vrp will also be used by ipa-vrp. */ > - > -static unsigned int > -execute_early_vrp () > -{ > - if (param_evrp_mode == EVRP_MODE_RVRP_ONLY) > - return execute_ranger_vrp (cfun, false); > - > - /* Ideally this setup code would move into the ctor for the folder > - However, this setup can change the number of blocks which > - invalidates the internal arrays that are set up by the dominator > - walker in substitute_and_fold_engine. */ > - loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); > - rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); > - scev_initialize (); > - calculate_dominance_info (CDI_DOMINATORS); > - > - // Only the last 2 bits matter for choosing the folder. > - switch (param_evrp_mode) > - { > - case EVRP_MODE_EVRP_ONLY: > - { > - evrp_folder folder; > - folder.substitute_and_fold (); > - break; > - } > - case EVRP_MODE_EVRP_FIRST: > - { > - hybrid_folder folder (true); > - folder.substitute_and_fold (); > - break; > - } > - case EVRP_MODE_RVRP_FIRST: > - { > - hybrid_folder folder (false); > - folder.substitute_and_fold (); > - break; > - } > - default: > - gcc_unreachable (); > - } > - > - scev_finalize (); > - loop_optimizer_finalize (); > - return 0; > -} > - > -namespace { > - > -const pass_data pass_data_early_vrp = > -{ > - GIMPLE_PASS, /* type */ > - "evrp", /* name */ > - OPTGROUP_NONE, /* optinfo_flags */ > - TV_TREE_EARLY_VRP, /* tv_id */ > - PROP_ssa, /* properties_required */ > - 0, /* properties_provided */ > - 0, /* properties_destroyed */ > - 0, /* todo_flags_start */ > - ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ), > -}; > - > -class pass_early_vrp : public gimple_opt_pass > -{ > -public: > - pass_early_vrp (gcc::context *ctxt) > - : gimple_opt_pass (pass_data_early_vrp, ctxt) > - {} > - > - /* opt_pass methods: */ > - opt_pass * clone () { return new pass_early_vrp (m_ctxt); } > - virtual bool gate (function *) > - { > - return flag_tree_vrp != 0; > - } > - virtual unsigned int execute (function *) > - { return execute_early_vrp (); } > - > -}; // class pass_vrp > -} // anon namespace > - > -gimple_opt_pass * > -make_pass_early_vrp (gcc::context *ctxt) > -{ > - return new pass_early_vrp (ctxt); > -} > diff --git a/gcc/params.opt b/gcc/params.opt > index bcf1423671a..2f9c9cf27dd 100644 > --- a/gcc/params.opt > +++ b/gcc/params.opt > @@ -134,25 +134,6 @@ Maximum number of basic blocks before EVRP uses a sparse cache. > Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param > Maximum number of outgoing edges in a switch before EVRP will not process it. > > --param=evrp-mode= > -Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization > ---param=evrp-mode=[legacy|ranger|legacy-first|ranger-first] Specifies the mode Early VRP should operate in. > - > -Enum > -Name(evrp_mode) Type(enum evrp_mode) UnknownError(unknown evrp mode %qs) > - > -EnumValue > -Enum(evrp_mode) String(legacy) Value(EVRP_MODE_EVRP_ONLY) > - > -EnumValue > -Enum(evrp_mode) String(ranger) Value(EVRP_MODE_RVRP_ONLY) > - > -EnumValue > -Enum(evrp_mode) String(legacy-first) Value(EVRP_MODE_EVRP_FIRST) > - > -EnumValue > -Enum(evrp_mode) String(ranger-first) Value(EVRP_MODE_RVRP_FIRST) > - > -param=fsm-scale-path-blocks= > Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization > Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements. > diff --git a/gcc/testsuite/g++.dg/pr100774.C b/gcc/testsuite/g++.dg/pr100774.C > index 345fcfa0d01..63320ef73fc 100644 > --- a/gcc/testsuite/g++.dg/pr100774.C > +++ b/gcc/testsuite/g++.dg/pr100774.C > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-O2 -fno-tree-forwprop --param=evrp-mode=ranger -fcompare-debug " } */ > +/* { dg-options "-O2 -fno-tree-forwprop -fcompare-debug " } */ > > extern void __attribute__((noreturn)) error(); > > diff --git a/gcc/testsuite/gcc.dg/pr100781.c b/gcc/testsuite/gcc.dg/pr100781.c > index c0e008a3ba5..96f0a7a6012 100644 > --- a/gcc/testsuite/gcc.dg/pr100781.c > +++ b/gcc/testsuite/gcc.dg/pr100781.c > @@ -1,5 +1,5 @@ > /* { dg-do compile } */ > -/* { dg-options "-O2 --param=evrp-mode=ranger -fcompare-debug " } */ > +/* { dg-options "-O2 -fcompare-debug " } */ > > struct a { > int b; > diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc > index 30022dac108..7b4e2917340 100644 > --- a/gcc/tree-vrp.cc > +++ b/gcc/tree-vrp.cc > @@ -4388,17 +4388,30 @@ const pass_data pass_data_vrp = > ( TODO_cleanup_cfg | TODO_update_ssa ), /* todo_flags_finish */ > }; > > +const pass_data pass_data_early_vrp = > +{ > + GIMPLE_PASS, /* type */ > + "evrp", /* name */ > + OPTGROUP_NONE, /* optinfo_flags */ > + TV_TREE_EARLY_VRP, /* tv_id */ > + PROP_ssa, /* properties_required */ > + 0, /* properties_provided */ > + 0, /* properties_destroyed */ > + 0, /* todo_flags_start */ > + ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ), > +}; > + > static int vrp_pass_num = 0; > class pass_vrp : public gimple_opt_pass > { > public: > - pass_vrp (gcc::context *ctxt) > - : gimple_opt_pass (pass_data_vrp, ctxt), warn_array_bounds_p (false), > - my_pass (++vrp_pass_num) > + pass_vrp (gcc::context *ctxt, const pass_data &data_) > + : gimple_opt_pass (data_, ctxt), data (data_), warn_array_bounds_p (false), > + my_pass (vrp_pass_num++) > {} > > /* opt_pass methods: */ > - opt_pass * clone () { return new pass_vrp (m_ctxt); } > + opt_pass * clone () { return new pass_vrp (m_ctxt, data); } > void set_pass_param (unsigned int n, bool param) > { > gcc_assert (n == 0); > @@ -4407,6 +4420,10 @@ public: > virtual bool gate (function *) { return flag_tree_vrp != 0; } > virtual unsigned int execute (function *fun) > { > + // Early VRP pass. > + if (my_pass == 0) > + return execute_ranger_vrp (fun, /*warn_array_bounds_p=*/false); > + > if ((my_pass == 1 && param_vrp1_mode == VRP_MODE_RANGER) > || (my_pass == 2 && param_vrp2_mode == VRP_MODE_RANGER)) > return execute_ranger_vrp (fun, warn_array_bounds_p); > @@ -4414,6 +4431,7 @@ public: > } > > private: > + const pass_data &data; > bool warn_array_bounds_p; > int my_pass; > }; // class pass_vrp > @@ -4423,5 +4441,11 @@ public: > gimple_opt_pass * > make_pass_vrp (gcc::context *ctxt) > { > - return new pass_vrp (ctxt); > + return new pass_vrp (ctxt, pass_data_vrp); > +} > + > +gimple_opt_pass * > +make_pass_early_vrp (gcc::context *ctxt) > +{ > + return new pass_vrp (ctxt, pass_data_early_vrp); > } > -- > 2.36.1 >