Obscure inline/nesting interaction (ACATS c61008a)

Richard Kenner kenner@vlsi1.ultra.nyu.edu
Sun Nov 28 16:49:00 GMT 2004


The two of us discussed this a while back and I think this is what we
came up with.  The comments I added explain the issue.

This fixes ACATS tests c61008a.

I'm starting testing now in x86_64-linux-gnu.

As I imply in the comments, I'm not thrilled with this solution, but don't
see a better one.  Do you?

2004-11-28  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>

	* tree-nested.c (check_for_nested_with_variably_modified): New.
	(create_nesting_tree): Call it.

*** tree-nested.c	6 Oct 2004 23:45:48 -0000	2.20
--- tree-nested.c	28 Nov 2004 14:45:12 -0000
*************** walk_all_functions (walk_tree_fn callbac
*** 613,618 ****
    while (root);
  }
- 
  
  /* Construct our local datastructure describing the function nesting
     tree rooted by CGN.  */
--- 613,655 ----
    while (root);
  }
  
+ /* We have to check for a fairly pathalogical case.  The operands of function
+    nested function are to be interpreted in the context of the enclosing
+    function.  So if any are variably-sized, they will get remapped when the
+    enclosing function is inlined.  But that remapping would also have to be
+    done in the types of the PARM_DECLs of the nested function, meaning we'd
+    have to make a copy of the nested function corresponding to each time the
+    enclosing function was inlined.  That's not practical, so we don't inline
+    such an enclosing function.
+ 
+    We have to do that check recursively, so here return indicating whether
+    FNDECL has such a nested function.  ORIG_FN is the function we were
+    trying to inline to use for checking whether any argument is variably
+    modified by anything in it.
+ 
+    It would be better to do this in tree-inline.c so that we could give
+    the appropriate warning for why a function can't be inlined, but that's
+    too late since the nesting structure has already been flattened and
+    adding a flag just to record this fact seems a waste of a flag.  */
+ 
+ static bool
+ check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl)
+ {
+   struct cgraph_node *cgn = cgraph_node (fndecl);
+   tree arg;
+ 
+   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+     {
+       for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = TREE_CHAIN (arg))
+ 	if (variably_modified_type_p (TREE_TYPE (arg), 0), orig_fndecl)
+ 	  return true;
+ 
+       if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl))
+ 	return true;
+     }
+ 
+   return false;
+ }
+ 
  /* Construct our local datastructure describing the function nesting
     tree rooted by CGN.  */
*************** create_nesting_tree (struct cgraph_node 
*** 633,636 ****
--- 670,678 ----
      }
  
+   /* See discussion at check_for_nested_with_variably_modified for a
+      discussion of why this has to be here.  */
+   if (check_for_nested_with_variably_modified (info->context, info->context))
+     DECL_UNINLINABLE (info->context) = true;
+ 
    return info;
  }



More information about the Gcc-patches mailing list