From patchwork Mon Jun 27 19:03:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 55455 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3FA78385E00A for ; Mon, 27 Jun 2022 19:04:46 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3FA78385E00A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1656356686; bh=qACSoGdWkZlHCNlI89ziTvric3FTp2zPBlx0OQ5gU3s=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=ZMgExBb122d8yi/hVr5/sOlqMRSh94t2ptygfloKaWMGyoLUdrKv7s4f0ausl1e5d tpkcN3Td99b2ap97d4Ccgd9s22WClvm1lVTtp0BcC3WQHDZYhhFEbmw3+MiPSwVvjz K/c1O/MoY1ZQQuz0Tx7jNmss7YUxib4bBKhhrAEU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 7F9EF38582BE for ; Mon, 27 Jun 2022 19:04:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7F9EF38582BE Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-672-nyWHOK9-PVCf7uQOKEBU2w-1; Mon, 27 Jun 2022 15:04:11 -0400 X-MC-Unique: nyWHOK9-PVCf7uQOKEBU2w-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C3C241C0515E; Mon, 27 Jun 2022 19:04:09 +0000 (UTC) Received: from abulafia.quesejoda.com (unknown [10.39.192.81]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CFC8E40C141F; Mon, 27 Jun 2022 19:04:08 +0000 (UTC) Received: from abulafia.quesejoda.com (localhost [127.0.0.1]) by abulafia.quesejoda.com (8.17.1/8.17.1) with ESMTPS id 25RJ46LF126408 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Mon, 27 Jun 2022 21:04:06 +0200 Received: (from aldyh@localhost) by abulafia.quesejoda.com (8.17.1/8.17.1/Submit) id 25RJ45I8126407; Mon, 27 Jun 2022 21:04:05 +0200 To: GCC patches Subject: [PATCH] Remove legacy EVRP code. Date: Mon, 27 Jun 2022 21:03:58 +0200 Message-Id: <20220627190358.126291-1-aldyh@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, 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-Patchwork-Original-From: Aldy Hernandez via Gcc-patches From: Aldy Hernandez Reply-To: Aldy Hernandez Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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? 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); }