[Bug middle-end/50890] [4.7 Regression] ICE in fold_convert_loc, at fold-const.c:1894

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Oct 28 12:45:00 GMT 2011


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50890

--- Comment #2 from Richard Guenther <rguenth at gcc dot gnu.org> 2011-10-28 12:45:28 UTC ---
Bah, probably triggered by that change but reveals some bigger issue with how
we keep the mismatched-function-flags (gimple_call_cannot_inline_p and
the corresponding edge flag e->call_stmt_cannot_inline_p) up-to-date.

In this case the inliner when inlining emit_pattern_after_noloc turns
the make_raw () call into a direct call but fails to set this flag,
so we inline it during the 2nd early inliner iteration.

Setting that flag at a convenient place with

+  /* Check whether propagating into the function address made the
+     call direct, and thus possibly non-inlineable.
+     ???  This asks for a more conservative setting of the non-inlinable
+     flag, namely true for all indirect calls.  But that would require
+     that we can re-compute the flag conservatively, thus it isn't
+     ever initialized from something else than return/argument type
+     checks .  */
+  callee = gimple_call_fndecl (stmt);
+  if (callee
+      && !gimple_check_call_matching_types (stmt, callee))
+    gimple_call_set_cannot_inline (stmt, true);

during statement folding (CCP can also cause such change when
turning an indirect into a direct call) causes us to hit

#1  0x00000000012b80e7 in can_inline_edge_p (e=0x7ffff5b286e8, report=true)
    at /space/rguenther/src/svn/trunk/gcc/ipa-inline.c:339
339       gcc_checking_assert (!e->call_stmt

because nobody updated the edge flag ... (and I don't think we should
do that from the statement folder).  That's during the 2nd iteration
of the early inliner.

Honza, why do we get away not re-building cgraph edges while
iterating?  What is supposed to keep the edges up-to-date?
I suppose we can adjust the flag when we do

          /* Technically we ought to recompute inline parameters so the new
             iteration of early inliner works as expected.  We however have
             values approximately right and thus we only need to update edge
             info that might be cleared out for newly discovered edges.  */
          for (edge = node->callees; edge; edge = edge->next_callee)
            {
              struct inline_edge_summary *es = inline_edge_summary (edge);
              es->call_stmt_size
                = estimate_num_insns (edge->call_stmt, &eni_size_weights);
              es->call_stmt_time
                = estimate_num_insns (edge->call_stmt, &eni_time_weights);
            }

Testing a patch.



More information about the Gcc-bugs mailing list