[PATCH, PR 61540] Do not ICE on impossible devirtualization

Jan Hubicka hubicka@ucw.cz
Thu Jun 19 16:51:00 GMT 2014


> Hi,
> 
> On Wed, Jun 18, 2014 at 06:12:34PM +0200, Bernhard Reutner-Fischer wrote:
> > On 18 June 2014 10:24:16 Martin Jambor <mjambor@suse.cz> wrote:
> > 
> > >@@ -3002,10 +3014,8 @@ try_make_edge_direct_virtual_call (struct
> > >cgraph_edge *ie,
> > >
> > >   if (target)
> > >     {
> > >-#ifdef ENABLE_CHECKING
> > >-      gcc_assert (possible_polymorphic_call_target_p
> > >-	 (ie, cgraph_get_node (target)));
> > >-#endif
> > >+      if (!possible_polymorphic_call_target_p (ie, cgraph_get_node (target)))
> > >+	return ipa_make_edge_direct_to_target (ie, target);
> > >       return ipa_make_edge_direct_to_target (ie, target);
> > >     }
> > 
> > The above looks odd. You return the same thing both conditionally
> > and unconditionally?
> > 
> 
> You are obviously right, apparently I was too tired to attempt to work
> that night.  Thanks, for spotting it.  The following patch has this
> corrected and it also passes bootstrap and testing on x86_64-linux on
> both the trunk and the 4.9 branch. OK for both?

OK,
Honza
> 
> Thanks,
> 
> Martin
> 
> 
> 2014-06-19  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/61540
> 	* ipa-prop.c (impossible_devirt_target): New function.
> 	(try_make_edge_direct_virtual_call): Use it, also instead of
> 	asserting.
> 
> testsuite/
>         * g++.dg/ipa/pr61540.C: New test.
> 
> diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
> index b67deed..d9dca52 100644
> --- a/gcc/ipa-prop.c
> +++ b/gcc/ipa-prop.c
> @@ -2912,6 +2912,29 @@ try_make_edge_direct_simple_call (struct cgraph_edge *ie,
>    return cs;
>  }
>  
> +/* Return the target to be used in cases of impossible devirtualization.  IE
> +   and target (the latter can be NULL) are dumped when dumping is enabled.  */
> +
> +static tree
> +impossible_devirt_target (struct cgraph_edge *ie, tree target)
> +{
> +  if (dump_file)
> +    {
> +      if (target)
> +	fprintf (dump_file,
> +		 "Type inconsident devirtualization: %s/%i->%s\n",
> +		 ie->caller->name (), ie->caller->order,
> +		 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
> +      else
> +	fprintf (dump_file,
> +		 "No devirtualization target in %s/%i\n",
> +		 ie->caller->name (), ie->caller->order);
> +    }
> +  tree new_target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
> +  cgraph_get_create_node (new_target);
> +  return new_target;
> +}
> +
>  /* Try to find a destination for indirect edge IE that corresponds to a virtual
>     call based on a formal parameter which is described by jump function JFUNC
>     and if it can be determined, make it direct and return the direct edge.
> @@ -2946,15 +2969,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
>  		   && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
>  		  || !possible_polymorphic_call_target_p
>  		       (ie, cgraph_get_node (target)))
> -		{
> -		  if (dump_file)
> -		    fprintf (dump_file,
> -			     "Type inconsident devirtualization: %s/%i->%s\n",
> -			     ie->caller->name (), ie->caller->order,
> -			     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (target)));
> -		  target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
> -		  cgraph_get_create_node (target);
> -		}
> +		target = impossible_devirt_target (ie, target);
>  	      return ipa_make_edge_direct_to_target (ie, target);
>  	    }
>  	}
> @@ -2984,10 +2999,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
>        if (targets.length () == 1)
>  	target = targets[0]->decl;
>        else
> -	{
> -          target = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
> -	  cgraph_get_create_node (target);
> -	}
> +	target = impossible_devirt_target (ie, NULL_TREE);
>      }
>    else
>      {
> @@ -3002,10 +3014,8 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
>  
>    if (target)
>      {
> -#ifdef ENABLE_CHECKING
> -      gcc_assert (possible_polymorphic_call_target_p
> -	 (ie, cgraph_get_node (target)));
> -#endif
> +      if (!possible_polymorphic_call_target_p (ie, cgraph_get_node (target)))
> +	target = impossible_devirt_target (ie, target);
>        return ipa_make_edge_direct_to_target (ie, target);
>      }
>    else
> diff --git a/gcc/testsuite/g++.dg/ipa/pr61540.C b/gcc/testsuite/g++.dg/ipa/pr61540.C
> new file mode 100644
> index 0000000..d298964
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr61540.C
> @@ -0,0 +1,41 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -fno-early-inlining -fdump-ipa-cp" } */
> +
> +struct data {
> +  data(int) {}
> +};
> +
> +struct top {
> +  virtual int topf() {}
> +};
> +
> +struct intermediate: top {
> +    int topf() /* override */ { return 0; }
> +};
> +
> +struct child1: top {
> +    void childf()
> +    {
> +        data d(topf());
> +    }
> +};
> +
> +struct child2: intermediate {};
> +
> +void test(top& t)
> +{
> +    child1& c = static_cast<child1&>(t);
> +    c.childf();
> +    child2 d;
> +    test(d);
> +}
> +
> +int main (int argc, char **argv)
> +{
> +  child1 c;
> +  test (c);
> +  return 0;
> +}
> +
> +/* { dg-final { scan-ipa-dump "Type inconsident devirtualization" "cp" } } */
> +/* { dg-final { cleanup-ipa-dump "cp" } } */



More information about the Gcc-patches mailing list