aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-ssa-evrp.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2017-11-20 10:44:45 -0700
committerJeff Law <law@gcc.gnu.org>2017-11-20 10:44:45 -0700
commit74ba745bdc684bc66c669539f487089c7acbcd77 (patch)
tree508745dee41b1d0f3a0e677873e5b715f9d91acb /gcc/gimple-ssa-evrp.c
parent8c66dd9b3330192da7b5e173acbe7bb58bf7a89d (diff)
downloadgcc-74ba745bdc684bc66c669539f487089c7acbcd77.zip
gcc-74ba745bdc684bc66c669539f487089c7acbcd77.tar.gz
gcc-74ba745bdc684bc66c669539f487089c7acbcd77.tar.bz2
Makefile.in (OBJS): Add gimple-ssa-evrp-analyze.o.
* 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. From-SVN: r254961
Diffstat (limited to 'gcc/gimple-ssa-evrp.c')
-rw-r--r--gcc/gimple-ssa-evrp.c353
1 files changed, 1 insertions, 352 deletions
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 8afec31..27a983d 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,247 +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);
- bb->flags |= BB_VISITED;
-}
-
-/* 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)
{
@@ -540,54 +237,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