This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug ipa/65028] [5 Regression] 450.soplex in SPEC CPU 2006 is miscompiled


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65028

--- Comment #4 from Martin Jambor <jamborm at gcc dot gnu.org> ---
OK, so here are my findings.  Switching off IPA-CP helps because the
pass then does not propagate polymorphic context from
_ZN8MySoPlexC2EN6soplex6SoPlex4TypeENS1_14RepresentationE/5887 to
_ZN6soplex9SPxSolverC2ENS_6SoPlex4TypeENS1_14RepresentationE/51162
(both are constructors) for the 0th parameter.  This propagation
clears the dynamic flag and speculation from the context on the edge
and the result is stored to a lattice describing the callee.

Later on, inlining comes along and calls ipa_context_from_jfunc which
picks up this value from the lattice and uses it as a base for a jump
function on the edge being inlined.  In this process, it also checks
for dynamic type changes in constructors and destructors but
apparently it relies on edge flag in_polymorphic_cdtor being correct.

And that is the problem, apparently it is not.  When we are inlining
into a function that has itself already been inlined into the
constructor, the flag is false, although we are basing jump function
calculations on lattices corresponding to the constructor.

Therefore I'd suggest the following fix.  (Alternatively we could
easily do this propagation in update_jump_functions_after_inlining,
without introducing another recursion.)


2015-02-13  Martin Jambor  <mjambor@suse.cz>

    PR ipa/65028
    * ipa-inline-transform.c (mark_all_inlined_calls_cdtor): New function.
    (inline_call): Use it.

diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 235219d..61229ac 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -261,6 +261,21 @@ clone_inlined_nodes (struct cgraph_edge *e, bool
duplicate,
     }
 }

+/* Mark all call graph edges coming out of NODE and all nodes that have been
+   inlined to it as in_polymorphic_cdtor.  */
+
+static void
+mark_all_inlined_calls_cdtor (cgraph_node *node)
+{
+  for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
+    {
+      cs->in_polymorphic_cdtor = true;
+      if (!cs->inline_failed)
+    mark_all_inlined_calls_cdtor (cs->callee);
+    }
+  for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
+    cs->in_polymorphic_cdtor = true;
+}

 /* Mark edge E as inlined and update callgraph accordingly.  UPDATE_ORIGINAL
    specify whether profile of original function should be updated.  If any new
@@ -332,6 +347,8 @@ inline_call (struct cgraph_edge *e, bool update_original,

   old_size = inline_summaries->get (to)->size;
   inline_merge_summary (e);
+  if (e->in_polymorphic_cdtor)
+    mark_all_inlined_calls_cdtor (e->callee);
   if (opt_for_fn (e->caller->decl, optimize))
     new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
   if (update_overall_summary)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]