/* Support routines for Value Range Propagation (VRP).
- Copyright (C) 2005-2017 Free Software Foundation, Inc.
+ Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of GCC.
{
public:
tree get_value (tree) FINAL OVERRIDE;
-
+ evrp_folder (class vr_values *vr_values_) : vr_values (vr_values_) { }
+ bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+ { return vr_values->simplify_stmt_using_ranges (gsi); }
class vr_values *vr_values;
+
+ private:
+ DISABLE_COPY_AND_ASSIGN (evrp_folder);
};
tree
class evrp_dom_walker : public dom_walker
{
public:
- evrp_dom_walker () : dom_walker (CDI_DOMINATORS)
+ evrp_dom_walker ()
+ : dom_walker (CDI_DOMINATORS),
+ evrp_range_analyzer (true),
+ evrp_folder (evrp_range_analyzer.get_vr_values ())
{
need_eh_cleanup = BITMAP_ALLOC (NULL);
}
auto_vec<gimple *> stmts_to_remove;
class evrp_range_analyzer evrp_range_analyzer;
-
- /* Temporary delegators. */
- value_range *get_value_range (const_tree op)
- { return evrp_range_analyzer.vr_values.get_value_range (op); }
- tree op_with_constant_singleton_value_range (tree op)
- { return evrp_range_analyzer.vr_values.op_with_constant_singleton_value_range (op); }
- void vrp_visit_cond_stmt (gcond *cond, edge *e)
- { evrp_range_analyzer.vr_values.vrp_visit_cond_stmt (cond, e); }
+ class evrp_folder evrp_folder;
};
edge
if (virtual_operand_p (lhs))
continue;
+ const value_range_equiv *vr = evrp_range_analyzer.get_value_range (lhs);
/* Mark PHIs whose lhs we fully propagate for removal. */
- tree val = op_with_constant_singleton_value_range (lhs);
- if (val && may_propagate_copy (lhs, val))
+ tree val;
+ if (vr->singleton_p (&val) && may_propagate_copy (lhs, val))
{
stmts_to_remove.safe_push (phi);
continue;
print_gimple_stmt (dump_file, stmt, 0);
}
- evrp_range_analyzer.record_ranges_from_stmt (stmt);
+ evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
if (gcond *cond = dyn_cast <gcond *> (stmt))
{
- vrp_visit_cond_stmt (cond, &taken_edge);
+ evrp_range_analyzer.vrp_visit_cond_stmt (cond, &taken_edge);
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)
}
else if (stmt_interesting_for_vrp (stmt))
{
- value_range vr = VR_INITIALIZER;
output = get_output_for_vrp (stmt);
if (output)
{
- tree val;
- vr = *get_value_range (output);
+ const value_range_equiv *vr
+ = evrp_range_analyzer.get_value_range (output);
/* Mark stmts whose output we fully propagate for removal. */
- if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
- && (val = op_with_constant_singleton_value_range (output))
+ tree val;
+ if (vr->singleton_p (&val)
&& may_propagate_copy (output, val)
- && !stmt_could_throw_p (stmt)
+ && !stmt_could_throw_p (cfun, stmt)
&& !gimple_has_side_effects (stmt))
{
stmts_to_remove.safe_push (stmt);
}
/* Try folding stmts with the VR discovered. */
- class evrp_folder evrp_folder;
- evrp_folder.vr_values = &evrp_range_analyzer.vr_values;
bool did_replace = evrp_folder.replace_uses_in (stmt);
+ gimple_stmt_iterator prev_gsi = gsi;
+ gsi_prev (&prev_gsi);
if (fold_stmt (&gsi, follow_single_use_edges)
|| did_replace)
{
update_stmt (stmt);
did_replace = true;
}
+ if (evrp_folder.simplify_stmt_using_ranges (&gsi))
+ {
+ stmt = gsi_stmt (gsi);
+ update_stmt (stmt);
+ did_replace = true;
+ }
if (did_replace)
{
+ /* If we wound up generating new stmts during folding
+ drop all their defs to VARYING. We can't easily
+ process them because we've already instantiated
+ ranges on uses on STMT that only hold after it. */
+ if (gsi_end_p (prev_gsi))
+ prev_gsi = gsi_start_bb (bb);
+ else
+ gsi_next (&prev_gsi);
+ while (gsi_stmt (prev_gsi) != gsi_stmt (gsi))
+ {
+ evrp_range_analyzer.get_vr_values ()
+ ->set_defs_to_varying (gsi_stmt (prev_gsi));
+ gsi_next (&prev_gsi);
+ }
+
/* If we cleaned up EH information from the statement,
remove EH edges. */
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
if (TREE_CODE (arg) != SSA_NAME
|| virtual_operand_p (arg))
continue;
- tree val = op_with_constant_singleton_value_range (arg);
- if (val && may_propagate_copy (arg, val))
+ const value_range_equiv
+ *vr = evrp_range_analyzer.get_value_range (arg);
+ tree val;
+ if (vr->singleton_p (&val) && may_propagate_copy (arg, val))
propagate_value (use_p, val);
}
}
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
- evrp_range_analyzer.vr_values.dump_all_value_ranges (dump_file);
+ evrp_range_analyzer.dump_all_value_ranges (dump_file);
fprintf (dump_file, "\n");
}
gimple *stmt = stmts_to_fixup.pop ();
fixup_noreturn_call (stmt);
}
+
+ evrp_folder.vr_values->cleanup_edges_and_switches ();
}
/* Main entry point for the early vrp pass which is a simplified non-iterative