On Sat, Nov 18, 2017 at 9:00 AM, Jeff Law <l...@redhat.com> wrote: > > > > This is just a straight cut-n-paste pulling the evrp_range_analyzer > methods out of gimple-ssa-evrp.c into gimple-ssa-evrp-analyze.[ch]. > > Bootstrapped and regression tested on x86_64. > > > OK for the trunk?
Hum. That makes things harder to follow - what's the advantage to making two files of EVRP? Richard. > Jeff > > * Makefile.in (OBJS): Add gimple-ssa-evrp-analyze.o. > * gimple-ssa-evrp-analyze.c: New file pulled from gimple-ssa-evrp.c. > * gimple-ssa-evrp-analyze.h: New file pulled from gimple-ssa-evrp.c. > * gimple-ssa-evrp.c: Remove bits moved into new files. Include > gimple-ssa-evrp-analyze.h. > > > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 5db78558c0c..38ab4e81026 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1302,6 +1302,7 @@ OBJS = \ > gimple-pretty-print.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/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c > new file mode 100644 > index 00000000000..4f33c644a74 > --- /dev/null > +++ b/gcc/gimple-ssa-evrp-analyze.c > @@ -0,0 +1,342 @@ > +/* Support routines for Value Range Propagation (VRP). > + Copyright (C) 2005-2017 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GCC is distributed in the hope that it will be useful, > +but WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +GNU General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#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-fold.h" > +#include "tree-eh.h" > +#include "gimple-iterator.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 () : stack (10) > +{ > + 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; > + } > +} > + > +void > +evrp_range_analyzer::enter (basic_block bb) > +{ > + stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL)); > + record_ranges_from_incoming_edge (bb); > + record_ranges_from_phis (bb); > +} > + > +/* Find new range for NAME such that (OP CODE LIMIT) is true. */ > +value_range * > +evrp_range_analyzer::try_find_new_range (tree name, > + tree op, tree_code code, tree limit) > +{ > + value_range vr = VR_INITIALIZER; > + value_range *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.type == VR_RANGE || vr.type == VR_ANTI_RANGE) > + { > + if (old_vr->type == vr.type > + && vrp_operand_equal_p (old_vr->min, vr.min) > + && vrp_operand_equal_p (old_vr->max, vr.max)) > + return NULL; > + value_range *new_vr = vr_values.vrp_value_range_pool.allocate (); > + *new_vr = vr; > + return new_vr; > + } > + return NULL; > +} > + > +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<assert_info, 8> 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<std::pair<tree, value_range *>, 8> vrs; > + for (unsigned i = 0; i < asserts.length (); ++i) > + { > + value_range *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)); > + } > + /* 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) > + push_value_range (vrs[i].first, vrs[i].second); > + } > + } > +} > + > +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; > + > + value_range vr_result = VR_INITIALIZER; > + bool interesting = stmt_interesting_for_vrp (phi); > + if (!has_unvisited_preds && interesting) > + extract_range_from_phi_node (phi, &vr_result); > + else > + { > + set_value_range_to_varying (&vr_result); > + /* 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. */ > + struct loop *l; > + if (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 (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) > + { > + if ((vr_result.type == VR_RANGE > + || vr_result.type == VR_ANTI_RANGE) > + && (TREE_CODE (vr_result.min) == INTEGER_CST) > + && (TREE_CODE (vr_result.max) == INTEGER_CST)) > + set_range_info (lhs, vr_result.type, > + wi::to_wide (vr_result.min), > + wi::to_wide (vr_result.max)); > + } > + else if (POINTER_TYPE_P (TREE_TYPE (lhs)) > + && ((vr_result.type == VR_RANGE > + && range_includes_zero_p (vr_result.min, > + vr_result.max) == 0) > + || (vr_result.type == VR_ANTI_RANGE > + && range_includes_zero_p (vr_result.min, > + vr_result.max) == 1))) > + set_ptr_nonnull (lhs); > + } > +} > + > +void > +evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt) > +{ > + tree output = NULL_TREE; > + > + if (dyn_cast <gcond *> (stmt)) > + ; > + else if (stmt_interesting_for_vrp (stmt)) > + { > + edge taken_edge; > + value_range vr = VR_INITIALIZER; > + extract_range_from_stmt (stmt, &taken_edge, &output, &vr); > + if (output > + && (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)) > + { > + update_value_range (output, &vr); > + > + /* Set the SSA with the value range. */ > + if (INTEGRAL_TYPE_P (TREE_TYPE (output))) > + { > + if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE) > + && (TREE_CODE (vr.min) == INTEGER_CST) > + && (TREE_CODE (vr.max) == INTEGER_CST)) > + set_range_info (output, vr.type, > + wi::to_wide (vr.min), > + wi::to_wide (vr.max)); > + } > + else if (POINTER_TYPE_P (TREE_TYPE (output)) > + && ((vr.type == VR_RANGE > + && range_includes_zero_p (vr.min, vr.max) == 0) > + || (vr.type == VR_ANTI_RANGE > + && range_includes_zero_p (vr.min, vr.max) == 1))) > + set_ptr_nonnull (output); > + } > + 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 *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 *op_range = try_find_new_range (op, op, > + comp_code, value); > + if (op_range) > + push_value_range (op, op_range); > + } > + } > +} > + > +/* Restore/pop VRs valid only for BB when we leave BB. */ > + > +void > +evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED) > +{ > + gcc_checking_assert (!stack.is_empty ()); > + while (stack.last ().first != NULL_TREE) > + pop_value_range (stack.last ().first); > + stack.pop (); > +} > + > +/* 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 *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"); > + } > + stack.safe_push (std::make_pair (var, get_value_range (var))); > + set_vr_value (var, vr); > +} > + > +/* Pop the Value Range from the vrp_stack and update VAR with it. */ > + > +value_range * > +evrp_range_analyzer::pop_value_range (tree var) > +{ > + value_range *vr = stack.last ().second; > + gcc_checking_assert (var == stack.last ().first); > + 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"); > + } > + set_vr_value (var, vr); > + stack.pop (); > + return vr; > +} > diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h > new file mode 100644 > index 00000000000..2e6c609c45b > --- /dev/null > +++ b/gcc/gimple-ssa-evrp-analyze.h > @@ -0,0 +1,71 @@ > +/* Support routines for Value Range Propagation (VRP). > + Copyright (C) 2016-2017 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify > +it under the terms of the GNU General Public License as published by > +the Free Software Foundation; either version 3, or (at your option) > +any later version. > + > +GCC is distributed in the hope that it will be useful, > +but WITHOUT ANY WARRANTY; without even the implied warranty of > +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +GNU General Public License for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > +#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H > +#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H > + > +class evrp_range_analyzer > +{ > + public: > + evrp_range_analyzer (void); > + ~evrp_range_analyzer (void) { stack.release (); } > + > + void enter (basic_block); > + void leave (basic_block); > + void record_ranges_from_stmt (gimple *); > + > + class vr_values vr_values; > + > + private: > + DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer); > + void push_value_range (tree var, value_range *vr); > + value_range *pop_value_range (tree var); > + value_range *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); > + > + /* STACK holds the old VR. */ > + auto_vec<std::pair <tree, value_range*> > stack; > + > + /* Temporary delegators. */ > + value_range *get_value_range (const_tree op) > + { return vr_values.get_value_range (op); } > + bool update_value_range (const_tree op, value_range *vr) > + { return vr_values.update_value_range (op, vr); } > + void extract_range_from_phi_node (gphi *phi, value_range *vr) > + { vr_values.extract_range_from_phi_node (phi, vr); } > + void adjust_range_with_scev (value_range *vr, struct loop *loop, > + gimple *stmt, tree var) > + { vr_values.adjust_range_with_scev (vr, loop, stmt, var); } > + void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p, > + tree *output_p, value_range *vr) > + { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); } > + void set_defs_to_varying (gimple *stmt) > + { return vr_values.set_defs_to_varying (stmt); } > + void set_vr_value (tree name, value_range *vr) > + { vr_values.set_vr_value (name, vr); } > + void extract_range_for_var_from_comparison_expr (tree var, > + enum tree_code cond_code, > + tree op, tree limit, > + value_range *vr_p) > + { vr_values.extract_range_for_var_from_comparison_expr (var, cond_code, > + op, limit, vr_p); > } > +}; > + > +#endif /* GCC_GIMPLE_SSA_EVRP_ANALYZE_H */ > diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c > index 76eeb13c63e..5fa9cfb3538 100644 > --- a/gcc/gimple-ssa-evrp.c > +++ b/gcc/gimple-ssa-evrp.c > @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see > #include "domwalk.h" > #include "tree-cfgcleanup.h" > #include "vr-values.h" > +#include "gimple-ssa-evrp-analyze.h" > > class evrp_folder : public substitute_and_fold_engine > { > @@ -55,69 +56,6 @@ evrp_folder::get_value (tree op) > return vr_values->op_with_constant_singleton_value_range (op); > } > > -class evrp_range_analyzer > -{ > - public: > - evrp_range_analyzer (void); > - ~evrp_range_analyzer (void) { stack.release (); } > - > - void enter (basic_block); > - void leave (basic_block); > - void record_ranges_from_stmt (gimple *); > - > - class vr_values vr_values; > - > - private: > - DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer); > - void push_value_range (tree var, value_range *vr); > - value_range *pop_value_range (tree var); > - value_range *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); > - > - /* STACK holds the old VR. */ > - auto_vec<std::pair <tree, value_range*> > stack; > - > - /* Temporary delegators. */ > - value_range *get_value_range (const_tree op) > - { return vr_values.get_value_range (op); } > - bool update_value_range (const_tree op, value_range *vr) > - { return vr_values.update_value_range (op, vr); } > - void extract_range_from_phi_node (gphi *phi, value_range *vr) > - { vr_values.extract_range_from_phi_node (phi, vr); } > - void adjust_range_with_scev (value_range *vr, struct loop *loop, > - gimple *stmt, tree var) > - { vr_values.adjust_range_with_scev (vr, loop, stmt, var); } > - void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p, > - tree *output_p, value_range *vr) > - { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); } > - void set_defs_to_varying (gimple *stmt) > - { return vr_values.set_defs_to_varying (stmt); } > - void set_vr_value (tree name, value_range *vr) > - { vr_values.set_vr_value (name, vr); } > - void extract_range_for_var_from_comparison_expr (tree var, > - enum tree_code cond_code, > - tree op, tree limit, > - value_range *vr_p) > - { vr_values.extract_range_for_var_from_comparison_expr (var, cond_code, > - op, limit, vr_p); > } > -}; > - > -evrp_range_analyzer::evrp_range_analyzer () : stack (10) > -{ > - 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; > - } > -} > - > - > /* evrp_dom_walker visits the basic blocks in the dominance order and set > the Value Ranges (VR) for SSA_NAMEs in the scope. Use this VR to > discover more VRs. */ > @@ -154,246 +92,6 @@ public: > { evrp_range_analyzer.vr_values.vrp_visit_cond_stmt (cond, e); } > }; > > -void > -evrp_range_analyzer::enter (basic_block bb) > -{ > - stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL)); > - record_ranges_from_incoming_edge (bb); > - record_ranges_from_phis (bb); > -} > - > -/* Find new range for NAME such that (OP CODE LIMIT) is true. */ > -value_range * > -evrp_range_analyzer::try_find_new_range (tree name, > - tree op, tree_code code, tree limit) > -{ > - value_range vr = VR_INITIALIZER; > - value_range *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.type == VR_RANGE || vr.type == VR_ANTI_RANGE) > - { > - if (old_vr->type == vr.type > - && vrp_operand_equal_p (old_vr->min, vr.min) > - && vrp_operand_equal_p (old_vr->max, vr.max)) > - return NULL; > - value_range *new_vr = vr_values.vrp_value_range_pool.allocate (); > - *new_vr = vr; > - return new_vr; > - } > - return NULL; > -} > - > -/* If BB is reached by a single incoming edge (ignoring loop edges), > - then derive ranges implied by traversing that edge. */ > - > -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<assert_info, 8> 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<std::pair<tree, value_range *>, 8> vrs; > - for (unsigned i = 0; i < asserts.length (); ++i) > - { > - value_range *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)); > - } > - /* 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) > - push_value_range (vrs[i].first, vrs[i].second); > - } > - } > -} > - > -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; > - > - value_range vr_result = VR_INITIALIZER; > - bool interesting = stmt_interesting_for_vrp (phi); > - if (!has_unvisited_preds && interesting) > - extract_range_from_phi_node (phi, &vr_result); > - else > - { > - set_value_range_to_varying (&vr_result); > - /* 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. */ > - struct loop *l; > - if (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 (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) > - { > - if ((vr_result.type == VR_RANGE > - || vr_result.type == VR_ANTI_RANGE) > - && (TREE_CODE (vr_result.min) == INTEGER_CST) > - && (TREE_CODE (vr_result.max) == INTEGER_CST)) > - set_range_info (lhs, vr_result.type, > - wi::to_wide (vr_result.min), > - wi::to_wide (vr_result.max)); > - } > - else if (POINTER_TYPE_P (TREE_TYPE (lhs)) > - && ((vr_result.type == VR_RANGE > - && range_includes_zero_p (vr_result.min, > - vr_result.max) == 0) > - || (vr_result.type == VR_ANTI_RANGE > - && range_includes_zero_p (vr_result.min, > - vr_result.max) == 1))) > - set_ptr_nonnull (lhs); > - } > -} > - > -/* Record any ranges created by statement STMT. */ > - > -void > -evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt) > -{ > - tree output = NULL_TREE; > - > - if (dyn_cast <gcond *> (stmt)) > - ; > - else if (stmt_interesting_for_vrp (stmt)) > - { > - edge taken_edge; > - value_range vr = VR_INITIALIZER; > - extract_range_from_stmt (stmt, &taken_edge, &output, &vr); > - if (output && (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)) > - { > - update_value_range (output, &vr); > - > - /* Set the SSA with the value range. */ > - if (INTEGRAL_TYPE_P (TREE_TYPE (output))) > - { > - if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE) > - && (TREE_CODE (vr.min) == INTEGER_CST) > - && (TREE_CODE (vr.max) == INTEGER_CST)) > - set_range_info (output, vr.type, > - wi::to_wide (vr.min), > - wi::to_wide (vr.max)); > - } > - else if (POINTER_TYPE_P (TREE_TYPE (output)) > - && ((vr.type == VR_RANGE > - && range_includes_zero_p (vr.min, vr.max) == 0) > - || (vr.type == VR_ANTI_RANGE > - && range_includes_zero_p (vr.min, vr.max) == 1))) > - set_ptr_nonnull (output); > - } > - 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 *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 *op_range = try_find_new_range (op, op, > - comp_code, value); > - if (op_range) > - push_value_range (op, op_range); > - } > - } > -} > - > edge > evrp_dom_walker::before_dom_children (basic_block bb) > { > @@ -541,54 +239,6 @@ evrp_dom_walker::after_dom_children (basic_block bb) > evrp_range_analyzer.leave (bb); > } > > -/* Restore/pop VRs valid only for BB when we leave BB. */ > - > -void > -evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED) > -{ > - gcc_checking_assert (!stack.is_empty ()); > - while (stack.last ().first != NULL_TREE) > - pop_value_range (stack.last ().first); > - stack.pop (); > -} > - > -/* 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 *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"); > - } > - stack.safe_push (std::make_pair (var, get_value_range (var))); > - set_vr_value (var, vr); > -} > - > -/* Pop the Value Range from the vrp_stack and update VAR with it. */ > - > -value_range * > -evrp_range_analyzer::pop_value_range (tree var) > -{ > - value_range *vr = stack.last ().second; > - gcc_checking_assert (var == stack.last ().first); > - 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"); > - } > - set_vr_value (var, vr); > - stack.pop (); > - return vr; > -} > - > /* Perform any cleanups after the main phase of EVRP has completed. */ > > void >