public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Alexandre Oliva <aoliva@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc(refs/users/aoliva/heads/strub)] fix strub function type sharing
Date: Tue, 16 Nov 2021 05:13:17 +0000 (GMT)	[thread overview]
Message-ID: <20211116051317.76EBB3857823@sourceware.org> (raw)

https://gcc.gnu.org/g:859656002a7d255ed6697d06afe654fceb8302e7

commit 859656002a7d255ed6697d06afe654fceb8302e7
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Wed Nov 10 00:24:30 2021 -0300

    fix strub function type sharing
    
    When a function type is copied and modified to add an at-calls strub
    mode, propagate the function type to fntype and address type in any
    calls involving the function, so that we don't modify unrelated types
    equivalent to the unmodified function type.
    
    
    for  gcc/ChangeLog
    
            * ipa-strub.cc (effective_strub_mode_for_call): New.
            (distinctify_node_type): New.
            (same_strub_mode_in_variants_p): New.
            (verify_strub): Use factored-out effective mode logic.
            (pass_ipa_strub::adjust_at_calls_type): Likewise.  Check mode
            in all variant and canonical types.
            (pass_ipa_strub::execute): Use dinstinctify_node_type.

Diff:
---
 gcc/ipa-strub.cc | 120 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 96 insertions(+), 24 deletions(-)

diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
index 43b2dd80d5d..4c1efe73f7f 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -1317,6 +1317,90 @@ strub_comptypes (tree t1, tree t2)
   return 2;
 }
 
+/* Return the effective strub mode used for CALL, and set *TYPEP to
+   the effective type used for the call.  The effective type and mode
+   are those of the callee, unless the call involves a typecast.  */
+
+static enum strub_mode
+effective_strub_mode_for_call (gcall *call, tree *typep)
+{
+  tree type;
+  enum strub_mode mode;
+
+  if (gimple_call_fntype_override_p (call))
+    {
+      type = gimple_call_fntype (call);
+      mode = get_strub_mode_from_type (type);
+    }
+  else
+    {
+      type = TREE_TYPE (TREE_TYPE (gimple_call_fn (call)));
+      tree decl = gimple_call_fndecl (call);
+      if (decl)
+	mode = get_strub_mode_from_fndecl (decl);
+      else
+	mode = get_strub_mode_from_type (type);
+    }
+
+  if (typep)
+    *typep = type;
+
+  return mode;
+}
+
+/* Create a distinct copy of the type of NODE's function, and change
+   the fntype of all calls to it with the same main type to the new
+   type.  */
+
+static void
+distinctify_node_type (cgraph_node *node)
+{
+  tree old_type = TREE_TYPE (node->decl);
+  tree new_type = build_distinct_type_copy (old_type);
+  tree new_ptr_type = NULL_TREE;
+
+  /* Remap any calls to node->decl that use old_type, or a variant
+     thereof, to new_type as well.  We don't look for aliases, their
+     declarations will have their types changed independently, and
+     we'll adjust their fntypes then.  */
+  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+    {
+      tree fnaddr = gimple_call_fn (e->call_stmt);
+      gcc_checking_assert (TREE_CODE (fnaddr) == ADDR_EXPR
+			   && TREE_OPERAND (fnaddr, 0) == node->decl);
+      if (gimple_call_fntype_override_p (e->call_stmt))
+	continue;
+      if (!new_ptr_type)
+	new_ptr_type = build_pointer_type (new_type);
+      TREE_TYPE (fnaddr) = new_ptr_type;
+      gimple_call_set_fntype (e->call_stmt, new_type);
+    }
+
+  TREE_TYPE (node->decl) = new_type;
+}
+
+/* Return TRUE if TYPE and any variants have the same strub mode,
+   and false otherwise.  */
+
+static bool
+same_strub_mode_in_variants_p (tree type)
+{
+  if (TYPE_CANONICAL (type)
+      && (get_strub_mode_from_type (type)
+	  != get_strub_mode_from_type (TYPE_CANONICAL (type))))
+    return false;
+
+  for (tree other = TYPE_MAIN_VARIANT (type);
+       other != NULL_TREE; other = TYPE_NEXT_VARIANT (type))
+    if (other == type)
+      continue;
+    else if (get_strub_mode_from_type (type)
+	     != get_strub_mode_from_type (TYPE_MAIN_VARIANT (type)))
+      return false;
+
+  return true;
+}
+
 /* Check that strub functions don't call non-strub functions, and that
    always_inline strub functions are only called by strub
    functions.  */
@@ -1341,9 +1425,8 @@ verify_strub ()
       {
 	gcc_checking_assert (e->indirect_unknown_callee);
 
-	tree callee_fntype = gimple_call_fntype (e->call_stmt);
 	enum strub_mode callee_mode
-	  = get_strub_mode_from_type (callee_fntype);
+	  = effective_strub_mode_for_call (e->call_stmt, NULL);
 
 	if (!strub_callable_from_p (caller_mode, callee_mode))
 	  error_at (gimple_location (e->call_stmt),
@@ -1355,17 +1438,9 @@ verify_strub ()
       {
 	gcc_checking_assert (!e->indirect_unknown_callee);
 
-	tree callee_fntype = gimple_call_fntype (e->call_stmt);
-	/* fntype is NULL for internal calls, and builtins may carry a
-	   variant type.  */
-	bool use_callee_mode_p
-	  = (!callee_fntype
-	     || (TYPE_MAIN_VARIANT (TREE_TYPE (e->callee->decl))
-		 == TYPE_MAIN_VARIANT (callee_fntype)));
-	strub_mode callee_mode
-	  = (use_callee_mode_p
-	     ? get_strub_mode (e->callee)
-	     : get_strub_mode_from_type (callee_fntype));
+	tree callee_fntype;
+	enum strub_mode callee_mode
+	  = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
 
 	if (!strub_callable_from_p (caller_mode, callee_mode))
 	  {
@@ -1379,7 +1454,7 @@ verify_strub ()
 	      /* This is ok, it will be kept in the STRUB_WRAPPER, and removed
 		 from the STRUB_WRAPPED's strub context.  */
 	      continue;
-	    else if (use_callee_mode_p)
+	    else if (!gimple_call_fntype_override_p (e->call_stmt))
 	      error_at (gimple_location (e->call_stmt),
 			"calling non-%<strub%> %qD in %<strub%> context %qD",
 			e->callee->decl, node->decl);
@@ -2056,6 +2131,8 @@ pass_ipa_strub::adjust_at_calls_type (tree type)
 {
   int named_args = 0;
 
+  gcc_checking_assert (same_strub_mode_in_variants_p (type));
+
   if (!TYPE_ARG_TYPES (type))
     return named_args;
 
@@ -2312,9 +2389,9 @@ pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node)
 	{
 	  gcc_checking_assert (e->indirect_unknown_callee);
 
-	  tree callee_fntype = gimple_call_fntype (e->call_stmt);
+	  tree callee_fntype;
 	  enum strub_mode callee_mode
-	    = get_strub_mode_from_type (callee_fntype);
+	    = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
 
 	  if (callee_mode != STRUB_AT_CALLS
 	      && callee_mode != STRUB_AT_CALLS_OPT)
@@ -2334,13 +2411,9 @@ pass_ipa_strub::adjust_at_calls_calls (cgraph_node *node)
 	{
 	  gcc_checking_assert (!e->indirect_unknown_callee);
 
-	  tree callee_fntype = gimple_call_fntype (e->call_stmt);
+	  tree callee_fntype;
 	  enum strub_mode callee_mode
-	    = (!callee_fntype
-	       || (TYPE_MAIN_VARIANT (callee_fntype)
-		   != TYPE_MAIN_VARIANT (TREE_TYPE (e->callee->decl)))
-	       ? get_strub_mode (e->callee)
-	       : get_strub_mode_from_type (callee_fntype));
+	    = effective_strub_mode_for_call (e->call_stmt, &callee_fntype);
 
 	  if (callee_mode != STRUB_AT_CALLS
 	      && callee_mode != STRUB_AT_CALLS_OPT)
@@ -2401,8 +2474,7 @@ pass_ipa_strub::execute (function *)
 	/* Create a type variant if strubbing was not explicitly requested in
 	   the function type.  */
 	if (get_strub_mode_from_type (TREE_TYPE (onode->decl)) != mode)
-	  TREE_TYPE (onode->decl) = build_distinct_type_copy (TREE_TYPE
-							      (onode->decl));
+	  distinctify_node_type (onode);
 
 	int named_args = adjust_at_calls_type (TREE_TYPE (onode->decl));


                 reply	other threads:[~2021-11-16  5:13 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211116051317.76EBB3857823@sourceware.org \
    --to=aoliva@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).