[PATCH] Fix overactive reference removal with speculative devirtualization

Martin Jambor mjambor@suse.cz
Tue Sep 23 09:40:00 GMT 2014


code removing references to indirectly-inlined functions can remove a
few too many when speculative devirtualization gets into the picture.
Although we already handle the case when speculative devirtualization
clones an edge with a CONST jump function by also cloning the
appropriate reference, we do nothing when cloning a PASS_THROUGH jump
function.  However, inlining can later convert this into a CONST jump
function and when that gets deleted, the reference is dropped (as a
part of speculative devirtualization resolution).  Eventually this
leads to the function being removed as unreachable and missing in the
final link.  This is fixed by the following patch which increments
controlled use counter of formal parameters when this kind of edge

I have also attempted to add a hunk to the edge removal hook that
would decrement the counter in these situation (dropping the edge
after all means the call will never happen).  However, I have run into
ordering issues within indirect inlining (and speculative
devirtualization resolution which happens as a part of making an edge
direct).  So at the moment I'm posting only this fix and will work on
the removal hook later.

Bootstrapped and tested on x86_64-linux, I have also successfully
LTO-built Firefox with the patch (when before it was failing).



2014-09-19  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.c (ipa_edge_duplication_hook): Update controlled_use_count
	when duplicating a PASS_THROUGH jump function when creating a
	speculative edge.

diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index bbb417d..29c8681 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3643,6 +3643,21 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
 	      dst_jf->value.constant.rdesc = dst_rdesc;
+      else if (dst_jf->type == IPA_JF_PASS_THROUGH
+	       && src->caller == dst->caller)
+	{
+	  struct cgraph_node *inline_root = dst->caller->global.inlined_to
+	    ? dst->caller->global.inlined_to : dst->caller;
+	  struct ipa_node_params *root_info = IPA_NODE_REF (inline_root);
+	  int idx = ipa_get_jf_pass_through_formal_id (dst_jf);
+	  int c = ipa_get_controlled_uses (root_info, idx);
+	    {
+	      c++;
+	      ipa_set_controlled_uses (root_info, idx, c);
+	    }
+	}

More information about the Gcc-patches mailing list