Commit 4517b378 by Martin Jambor Committed by Martin Jambor

[PR 89330] Remove non-useful speculations from new_edges

2019-07-26  Martin Jambor  <mjambor@suse.cz>

	PR ipa/89330
	* ipa-inline-transform.c (check_speculations_1): New function.
	(push_all_edges_in_set_to_vec): Likewise.
	(check_speculations): Use check_speculations_1, new parameter
	new_edges.
	(inline_call): Pass new_edges to check_speculations.
	* ipa-inline.c (add_new_edges_to_heap): Assert edge_callee is not
	NULL.
	(speculation_useful_p): Early return true if edge is inlined, remove
	later checks for inline_failed.

	testsuite/
	* g++.dg/lto/pr89330_[01].C: New test.
	* g++.dg/tree-prof/devirt.C: Added -fno-profile-values to dg-options.

From-SVN: r273825
parent ac2dca4d
2019-07-26 Martin Jambor <mjambor@suse.cz>
PR ipa/89330
* ipa-inline-transform.c (check_speculations_1): New function.
(push_all_edges_in_set_to_vec): Likewise.
(check_speculations): Use check_speculations_1, new parameter
new_edges.
(inline_call): Pass new_edges to check_speculations.
* ipa-inline.c (add_new_edges_to_heap): Assert edge_callee is not
NULL.
(speculation_useful_p): Early return true if edge is inlined, remove
later checks for inline_failed.
2019-07-25 Vladimir Makarov <vmakarov@redhat.com> 2019-07-25 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/91223 PR rtl-optimization/91223
......
...@@ -237,10 +237,13 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, ...@@ -237,10 +237,13 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
} }
} }
/* Check all speculations in N and resolve them if they seems useless. */ /* Check all speculations in N and if any seem useless, resolve them. When a
first edge is resolved, pop all edges from NEW_EDGES and insert them to
EDGE_SET. Then remove each resolved edge from EDGE_SET, if it is there. */
static bool static bool
check_speculations (cgraph_node *n) check_speculations_1 (cgraph_node *n, vec<cgraph_edge *> *new_edges,
hash_set <cgraph_edge *> *edge_set)
{ {
bool speculation_removed = false; bool speculation_removed = false;
cgraph_edge *next; cgraph_edge *next;
...@@ -250,15 +253,46 @@ check_speculations (cgraph_node *n) ...@@ -250,15 +253,46 @@ check_speculations (cgraph_node *n)
next = e->next_callee; next = e->next_callee;
if (e->speculative && !speculation_useful_p (e, true)) if (e->speculative && !speculation_useful_p (e, true))
{ {
while (new_edges && !new_edges->is_empty ())
edge_set->add (new_edges->pop ());
edge_set->remove (e);
e->resolve_speculation (NULL); e->resolve_speculation (NULL);
speculation_removed = true; speculation_removed = true;
} }
else if (!e->inline_failed) else if (!e->inline_failed)
speculation_removed |= check_speculations (e->callee); speculation_removed |= check_speculations_1 (e->callee, new_edges,
edge_set);
} }
return speculation_removed; return speculation_removed;
} }
/* Push E to NEW_EDGES. Called from hash_set traverse method, which
unfortunately means this function has to have external linkage, otherwise
the code will not compile with gcc 4.8. */
bool
push_all_edges_in_set_to_vec (cgraph_edge * const &e,
vec<cgraph_edge *> *new_edges)
{
new_edges->safe_push (e);
return true;
}
/* Check all speculations in N and if any seem useless, resolve them and remove
them from NEW_EDGES. */
static bool
check_speculations (cgraph_node *n, vec<cgraph_edge *> *new_edges)
{
hash_set <cgraph_edge *> edge_set;
bool res = check_speculations_1 (n, new_edges, &edge_set);
if (!edge_set.is_empty ())
edge_set.traverse <vec<cgraph_edge *> *,
push_all_edges_in_set_to_vec> (new_edges);
return res;
}
/* Mark all call graph edges coming out of NODE and all nodes that have been /* Mark all call graph edges coming out of NODE and all nodes that have been
inlined to it as in_polymorphic_cdtor. */ inlined to it as in_polymorphic_cdtor. */
...@@ -450,7 +484,7 @@ inline_call (struct cgraph_edge *e, bool update_original, ...@@ -450,7 +484,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
mark_all_inlined_calls_cdtor (e->callee); mark_all_inlined_calls_cdtor (e->callee);
if (opt_for_fn (e->caller->decl, optimize)) if (opt_for_fn (e->caller->decl, optimize))
new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges); new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
check_speculations (e->callee); check_speculations (e->callee, new_edges);
if (update_overall_summary) if (update_overall_summary)
ipa_update_overall_fn_summary (to); ipa_update_overall_fn_summary (to);
else else
......
...@@ -1629,6 +1629,7 @@ add_new_edges_to_heap (edge_heap_t *heap, vec<cgraph_edge *> new_edges) ...@@ -1629,6 +1629,7 @@ add_new_edges_to_heap (edge_heap_t *heap, vec<cgraph_edge *> new_edges)
struct cgraph_edge *edge = new_edges.pop (); struct cgraph_edge *edge = new_edges.pop ();
gcc_assert (!edge->aux); gcc_assert (!edge->aux);
gcc_assert (edge->callee);
if (edge->inline_failed if (edge->inline_failed
&& can_inline_edge_p (edge, true) && can_inline_edge_p (edge, true)
&& want_inline_small_function_p (edge, true) && want_inline_small_function_p (edge, true)
...@@ -1656,6 +1657,10 @@ heap_edge_removal_hook (struct cgraph_edge *e, void *data) ...@@ -1656,6 +1657,10 @@ heap_edge_removal_hook (struct cgraph_edge *e, void *data)
bool bool
speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining) speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining)
{ {
/* If we have already decided to inline the edge, it seems useful. */
if (!e->inline_failed)
return true;
enum availability avail; enum availability avail;
struct cgraph_node *target = e->callee->ultimate_alias_target (&avail, struct cgraph_node *target = e->callee->ultimate_alias_target (&avail,
e->caller); e->caller);
...@@ -1690,12 +1695,11 @@ speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining) ...@@ -1690,12 +1695,11 @@ speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining)
to an ipa-cp clone (that are seen by having local flag set), to an ipa-cp clone (that are seen by having local flag set),
it is probably pointless to inline it unless hardware is missing it is probably pointless to inline it unless hardware is missing
indirect call predictor. */ indirect call predictor. */
if (!anticipate_inlining && e->inline_failed && !target->local.local) if (!anticipate_inlining && !target->local.local)
return false; return false;
/* For overwritable targets there is not much to do. */ /* For overwritable targets there is not much to do. */
if (e->inline_failed if (!can_inline_edge_p (e, false)
&& (!can_inline_edge_p (e, false) || !can_inline_edge_by_limits_p (e, false, true))
|| !can_inline_edge_by_limits_p (e, false, true)))
return false; return false;
/* OK, speculation seems interesting. */ /* OK, speculation seems interesting. */
return true; return true;
......
2019-07-26 Martin Jambor <mjambor@suse.cz>
PR ipa/89330
* g++.dg/lto/pr89330_[01].C: New test.
* g++.dg/tree-prof/devirt.C: Added -fno-profile-values to dg-options.
2019-07-25 Martin Sebor <msebor@redhat.com> 2019-07-25 Martin Sebor <msebor@redhat.com>
PR tree-optimization/91183 PR tree-optimization/91183
......
// { dg-lto-do link }
// { dg-lto-options { { -O3 -g -flto -shared -Wno-odr } } }
namespace Inkscape {
class Anchored {};
namespace XML {
enum NodeType {};
class Node :Anchored {
public:
virtual NodeType type() ;
virtual char name() ;
virtual int code() ;
virtual unsigned position() ;
virtual unsigned childCount() ;
virtual char content() ;
virtual char *attribute() const ;
virtual int attributeList() ;
virtual bool matchAttributeName() ;
virtual void setPosition() ;
virtual void setContent() ;
virtual void setAttribute() ;
virtual int document() ;
virtual int document() const ;
virtual Node *root() ;
virtual Node *root() const ;
virtual Node *parent() ;
virtual Node *next() const ;
virtual Node *firstChild() const ;
};
} } struct rdf_license_t {
};
;
class RDFImpl {
;
rdf_license_t *getLicense();
};
static bool rdf_match_license(Inkscape::XML::Node const *repr) {
for (Inkscape::XML::Node *current = repr->firstChild(); current;
current->next()->attribute());
return 0;
}
rdf_license_t *RDFImpl::getLicense() {
Inkscape::XML::Node *repr ;
for (rdf_license_t *license ; license;
license) {
rdf_match_license(repr);
}
return 0;
}
typedef char gchar;
namespace Inkscape {
class Anchored {
int _anchor;
};
namespace XML {
enum NodeType {};
class Node :Anchored {
virtual NodeType type() ;
virtual char const *name() const ;
virtual int code() ;
virtual unsigned position() ;
virtual unsigned childCount() ;
virtual char content() ;
virtual char attribute() ;
virtual int attributeList() ;
virtual bool matchAttributeName() ;
virtual void setPosition() ;
virtual void setContent() ;
virtual int document() ;
virtual int document() const ;
virtual Node *root() ;
virtual Node *root() const ;
virtual Node *parent() ;
virtual Node *parent() const ;
virtual Node *next() ;
virtual Node const *next() const ;
};
class SimpleNode : virtual Node {
char const *name() const;
Node *next() const { return _next; }
SimpleNode *_next;
};
gchar const *SimpleNode::name() const { return 0; }
} }
/* PR ipa/88561 */ /* PR ipa/88561 */
/* { dg-options "-O3 -fdump-tree-tracer-details -fdump-tree-dom3-details" } */ /* { dg-options "-O3 -fdump-tree-tracer-details -fdump-tree-dom3-details -fno-profile-values" } */
struct nsISupports struct nsISupports
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment