This is the mail archive of the gcc-patches@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]

PR middle-end/40102


Hi,
this patch fix ICE in PR 40102. The problem here is that indirect
inlining discovers the fact that there is direct call to foo0 after
inlining, but it happens only in some clones but not in another.  When
producing IPA-CP clone we fail to add the edge consistently.

Bootstrapping/regtesting x86_64-linux, will commit it if passes.
Honza

	* cgraph.c (cgraph_create_edge_including_clones): Also asume that the
	original node might've been modified.
	* tree-inline.c (copy_bb): Do not assume that all clones are the same.
	* g++.dg/torture/pr40102.C: New testcase.
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 148275)
--- cgraph.c	(working copy)
*************** cgraph_create_edge_including_clones (str
*** 701,708 ****
  {
    struct cgraph_node *node;
  
!   cgraph_create_edge (orig, callee, stmt, count, freq, loop_depth)->inline_failed =
!     reason;
  
    if (orig->clones)
      for (node = orig->clones; node != orig;)
--- 701,709 ----
  {
    struct cgraph_node *node;
  
!   if (!cgraph_edge (orig, stmt))
!      cgraph_create_edge (orig, callee, stmt,
!      			 count, freq, loop_depth)->inline_failed = reason;
  
    if (orig->clones)
      for (node = orig->clones; node != orig;)
Index: testsuite/g++.dg/torture/pr40102.C
===================================================================
*** testsuite/g++.dg/torture/pr40102.C	(revision 0)
--- testsuite/g++.dg/torture/pr40102.C	(revision 0)
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do compile } */
+ bool foo0(int) { return true; }
+ 
+ bool foo1();
+ 
+ struct A
+ {
+   A();
+   ~A();
+ 
+   template<typename T> void bar1(T f)
+   {
+     if (f(0))
+       foo1();
+   }
+ 
+   template<typename T> void bar2(T);
+ };
+ 
+ template<typename T> void A::bar2(T f)
+ {
+   A a, b[1], *p;
+ 
+   while (foo1())
+   {
+     if (p)
+       ++p;
+     if (p && foo1())
+       bar1(f);
+     if (p)
+       ++p;
+   }
+ 
+   if (foo1())
+     bar1(f);
+ }
+ 
+ void baz()
+ {
+   A().bar2(foo0);
+ }
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 148275)
--- tree-inline.c	(working copy)
*************** copy_bb (copy_body_data *id, basic_block
*** 1508,1518 ****
  		gcc_unreachable ();
  		}
  
  	    /* Constant propagation on argument done during inlining
  	       may create new direct call.  Produce an edge for it.  */
! 	    if (!edge && is_gimple_call (stmt)
! 		&& (fn = gimple_call_fndecl (stmt)) != NULL
! 		&& !cgraph_edge (id->dst_node, stmt))
  	      {
  		struct cgraph_node *dest = cgraph_node (fn);
  
--- 1508,1521 ----
  		gcc_unreachable ();
  		}
  
+ 	    edge = cgraph_edge (id->src_node, orig_stmt);
  	    /* Constant propagation on argument done during inlining
  	       may create new direct call.  Produce an edge for it.  */
! 	    if ((!edge 
! 		 || (edge->indirect_call
! 		     && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
! 		&& is_gimple_call (stmt)
! 		&& (fn = gimple_call_fndecl (stmt)) != NULL)
  	      {
  		struct cgraph_node *dest = cgraph_node (fn);
  


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