diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2021-09-22 18:10:43 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2021-09-23 08:05:48 +0200 |
commit | 4c0c43623efe2900dd0feb3abf8b611023362c43 (patch) | |
tree | 860a45c2308629979c2118f93a69b4f17d91b6e0 /gcc/tree-ssa-dom.c | |
parent | e4777439fc77465b4cf89b6bfeb47cd00329cb20 (diff) | |
download | gcc-4c0c43623efe2900dd0feb3abf8b611023362c43.zip gcc-4c0c43623efe2900dd0feb3abf8b611023362c43.tar.gz gcc-4c0c43623efe2900dd0feb3abf8b611023362c43.tar.bz2 |
Overhaul jump thread state in forward threader.
I've been pulling state from across the forward jump threader into the
jt_state class, but it it still didn't feel right. The ultimate goal
was to keep track of candidate threading paths so that the simplifier
could simplify statements with the path as context. This patch completes
the transition, while cleaning up a lot of things in the process.
I've revamped both state and the simplifier such that a base state class
contains only the blocks as they're registered, and any pass specific
knowledge is where it belongs... in the pass. This allows VRP to keep
its const and copies business, and DOM to keep this as well as its evrp
client. This makes the threader cleaner, as it will now have no knowledge
of either const/copies or evrp.
This also paves the wave for the upcoming hybrid threader, which will
just derive the state class and provide almost nothing, since the ranger
doesn't need to register any equivalences or ranges as it folds.
There is some code duplication in the simplifier, since both the DOM and
VRP clients use a vr_values based simplifier, but this is temporary as
the VRP client is about to be replaced with a hybrid ranger.
For a better view of what this patch achieves, here are the base
classes:
class jt_state
{
public:
virtual ~jt_state () { }
virtual void push (edge);
virtual void pop ();
virtual void register_equiv (tree dest, tree src, bool update_range =
false);
virtual void register_equivs_edge (edge e);
virtual void register_equivs_stmt (gimple *, basic_block,
class jt_simplifier *);
virtual void record_ranges_from_stmt (gimple *stmt, bool temporary);
void get_path (vec<basic_block> &);
void append_path (basic_block);
void dump (FILE *);
void debug ();
private:
auto_vec<basic_block> m_blocks;
};
class jt_simplifier
{
public:
virtual ~jt_simplifier () { }
virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) =
0;
};
There are no functional changes.
gcc/ChangeLog:
* tree-ssa-dom.c (class dom_jump_threader_simplifier): Rename...
(class dom_jt_state): ...this and provide virtual overrides.
(dom_jt_state::register_equiv): New.
(class dom_jt_simplifier): Rename from
dom_jump_threader_simplifier.
(dom_jump_threader_simplifier::simplify): Rename...
(dom_jt_simplifier::simplify): ...to this.
(pass_dominator::execute): Use dom_jt_simplifier and
dom_jt_state.
* tree-ssa-threadedge.c (jump_threader::jump_threader):
Clean-up.
(jt_state::register_equivs_stmt): Abstract out...
(jump_threader::record_temporary_equivalences_from_stmts_at_dest):
...from here.
(jump_threader::thread_around_empty_blocks): Update state.
(jump_threader::thread_through_normal_block): Same.
(jt_state::jt_state): Remove.
(jt_state::push): Remove pass specific bits. Keep block vector
updated.
(jt_state::append_path): New.
(jt_state::pop): Remove pass specific bits.
(jt_state::register_equiv): Same.
(jt_state::record_ranges_from_stmt): Same.
(jt_state::register_equivs_on_edge): Same. Rename...
(jt_state::register_equivs_edge): ...to this.
(jt_state::dump): New.
(jt_state::debug): New.
(jump_threader_simplifier::simplify): Remove.
(jt_state::get_path): New.
* tree-ssa-threadedge.h (class jt_simplifier): Make into a base
class. Expose common functionality as virtual methods.
(class jump_threader_simplifier): Same. Rename...
(class jt_simplifier): ...to this.
* tree-vrp.c (class vrp_jump_threader_simplifier): Rename...
(class vrp_jt_simplifier): ...to this. Provide pass specific
overrides.
(class vrp_jt_state): New.
(vrp_jump_threader_simplifier::simplify): Rename...
(vrp_jt_simplifier::simplify): ...to this. Inline code from
what used to be the base class.
(vrp_jump_threader::vrp_jump_threader): Use vrp_jt_state and
vrp_jt_simplifier.
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r-- | gcc/tree-ssa-dom.c | 134 |
1 files changed, 120 insertions, 14 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 49d8f96..f58b6b7 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -585,31 +585,137 @@ record_edge_info (basic_block bb) } } -class dom_jump_threader_simplifier : public jump_threader_simplifier +class dom_jt_state : public jt_state { public: - dom_jump_threader_simplifier (vr_values *v, - avail_exprs_stack *avails) - : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { } + dom_jt_state (const_and_copies *copies, avail_exprs_stack *avails, + evrp_range_analyzer *evrp) + : m_copies (copies), m_avails (avails), m_evrp (evrp) + { + } + void push (edge e) override + { + m_copies->push_marker (); + m_avails->push_marker (); + m_evrp->push_marker (); + jt_state::push (e); + } + void pop () override + { + m_copies->pop_to_marker (); + m_avails->pop_to_marker (); + m_evrp->pop_to_marker (); + jt_state::pop (); + } + void register_equivs_edge (edge e) override + { + record_temporary_equivalences (e, m_copies, m_avails); + } + void record_ranges_from_stmt (gimple *stmt, bool temporary) override + { + m_evrp->record_ranges_from_stmt (stmt, temporary); + } + void register_equiv (tree dest, tree src, bool update) override; +private: + const_and_copies *m_copies; + avail_exprs_stack *m_avails; + evrp_range_analyzer *m_evrp; +}; + +void +dom_jt_state::register_equiv (tree dest, tree src, bool update) +{ + m_copies->record_const_or_copy (dest, src); + + /* If requested, update the value range associated with DST, using + the range from SRC. */ + if (update) + { + /* Get new VR we can pass to push_value_range. */ + value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv (); + new (new_vr) value_range_equiv (); + + /* There are three cases to consider: + + First if SRC is an SSA_NAME, then we can copy the value range + from SRC into NEW_VR. + + Second if SRC is an INTEGER_CST, then we can just set NEW_VR + to a singleton range. Note that even if SRC is a constant we + need to set a suitable output range so that VR_UNDEFINED + ranges do not leak through. + + Otherwise set NEW_VR to varying. This may be overly + conservative. */ + if (TREE_CODE (src) == SSA_NAME) + new_vr->deep_copy (m_evrp->get_value_range (src)); + else if (TREE_CODE (src) == INTEGER_CST) + new_vr->set (src); + else + new_vr->set_varying (TREE_TYPE (src)); + + /* This is a temporary range for DST, so push it. */ + m_evrp->push_value_range (dest, new_vr); + } +} + +class dom_jt_simplifier : public jt_simplifier +{ +public: + dom_jt_simplifier (vr_values *v, avail_exprs_stack *avails) + : m_vr_values (v), m_avails (avails) { } private: tree simplify (gimple *, gimple *, basic_block, jt_state *) override; - avail_exprs_stack *m_avail_exprs_stack; + vr_values *m_vr_values; + avail_exprs_stack *m_avails; }; tree -dom_jump_threader_simplifier::simplify (gimple *stmt, - gimple *within_stmt, - basic_block bb, - jt_state *state) +dom_jt_simplifier::simplify (gimple *stmt, gimple *within_stmt, + basic_block, jt_state *) { /* First see if the conditional is in the hash table. */ - tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, - false, true); + tree cached_lhs = m_avails->lookup_avail_expr (stmt, false, true); if (cached_lhs) return cached_lhs; - return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state); + if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) + { + simplify_using_ranges simplifier (m_vr_values); + return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), + gimple_cond_lhs (cond_stmt), + gimple_cond_rhs (cond_stmt), + within_stmt); + } + if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt)) + { + tree op = gimple_switch_index (switch_stmt); + if (TREE_CODE (op) != SSA_NAME) + return NULL_TREE; + + const value_range_equiv *vr = m_vr_values->get_value_range (op); + return find_case_label_range (switch_stmt, vr); + } + if (gassign *assign_stmt = dyn_cast <gassign *> (stmt)) + { + tree lhs = gimple_assign_lhs (assign_stmt); + if (TREE_CODE (lhs) == SSA_NAME + && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + || POINTER_TYPE_P (TREE_TYPE (lhs))) + && stmt_interesting_for_vrp (stmt)) + { + edge dummy_e; + tree dummy_tree; + value_range_equiv new_vr; + m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree, + &new_vr); + tree singleton; + if (new_vr.singleton_p (&singleton)) + return singleton; + } + } + return NULL; } class dom_opt_dom_walker : public dom_walker @@ -752,8 +858,8 @@ pass_dominator::execute (function *fun) /* Recursively walk the dominator tree optimizing statements. */ evrp_range_analyzer analyzer (true); - dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack); - jt_state state (const_and_copies, avail_exprs_stack, &analyzer); + dom_jt_simplifier simplifier (&analyzer, avail_exprs_stack); + dom_jt_state state (const_and_copies, avail_exprs_stack, &analyzer); jump_threader threader (&simplifier, &state); dom_opt_dom_walker walker (CDI_DOMINATORS, &threader, |