public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <rguenther@suse.de>
To: Jakub Jelinek <jakub@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] tree-optimization/108691 - indirect calls to setjmp
Date: Mon, 13 Feb 2023 13:18:56 +0000 (UTC)	[thread overview]
Message-ID: <nycvar.YFH.7.77.849.2302131318140.9226@jbgna.fhfr.qr> (raw)
In-Reply-To: <Y+oxQBPcBdaW6JjO@tucnak>

On Mon, 13 Feb 2023, Jakub Jelinek wrote:

> On Mon, Feb 13, 2023 at 12:41:48PM +0000, Richard Biener wrote:
> > > Could we e.g. prevent turning such indirect calls into direct calls?
> > 
> > We do exactly have gimple_call_fntype and gimple_call_ctrl_altering_p
> > to not require special-casing indirect to direct call promotion here.
> 
> Ah, so if we make returns_twice apply to function types, then we could
> just compare if gimple_call_fntype has also returns_twice and if not, not
> consider it actually returns_twice.
> 
> > > Anyway, notice_special_calls is called in various spots, not just DCE,
> > > wouldn't it be better to simply not set calls_setjmp flag in there if
> > > the current function already has cfg and the call isn't ctrl altering?
> > 
> > I thought about changing gimple_call_flags instead, filtering out
> > ECF_RETURNS_TWICE.  I just didn't make up my mind on what
> > property to key at (and to require 'cfun' to be set to query it).
> > But sure, changing notice_special_calls also works - the only
> > other relevant caller is the inliner I think, and that could be
> > replaced by caller |= callee of the two flags tracked instead of
> > re-scanning each inlined stmt.
> > 
> > Would you be happy with changing notice_special_calls, dropping the
> > DCE hunk but keeping the cfgexpand/calls.cc hunks?
> 
> I think so.

I'm testing the following and am queueing the second patch below
for next stage1.

Richard.


From d5e62f27489c1e7a8696a85e7bc98cc0a26564d2 Mon Sep 17 00:00:00 2001
From: Richard Biener <rguenther@suse.de>
Date: Mon, 13 Feb 2023 10:41:51 +0100
Subject: [PATCH 1/2] tree-optimization/108691 - indirect calls to setjmp
To: gcc-patches@gcc.gnu.org

DCE now chokes on indirect setjmp calls becoming direct because
that exposes them too late to be subject to abnormal edge creation.
The following patch honors gimple_call_ctrl_altering for those and
_not_ treat formerly indirect calls to setjmp as calls to setjmp
in notice_special_calls.

Unfortunately there's no way to have an indirect call to setjmp
properly annotated (the returns_twice attribute is ignored on types).

RTL expansion late discovers returns-twice for the purpose of
adding REG_SETJMP notes and also sets ->calls_setjmp
(instead of asserting it is set).  There's no good way to
transfer proper knowledge around here so I'm using ->calls_setjmp
as a flag to indicate whether gimple_call_ctrl_altering_p was set.

	PR tree-optimization/108691
	* tree-cfg.cc (notice_special_calls): When the CFG is built
	honor gimple_call_ctrl_altering_p.
	* cfgexpand.cc (expand_call_stmt): Clear cfun->calls_setjmp
	temporarily if the call is not control-altering.
	* calls.cc (emit_call_1): Do not add REG_SETJMP if
	cfun->calls_setjmp is not set.  Do not alter cfun->calls_setjmp.

	* gcc.dg/pr108691.c: New testcase.
---
 gcc/calls.cc                    | 10 +++++-----
 gcc/cfgexpand.cc                |  7 +++++++
 gcc/testsuite/gcc.dg/pr108691.c |  9 +++++++++
 gcc/tree-cfg.cc                 |  4 +++-
 4 files changed, 24 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr108691.c

diff --git a/gcc/calls.cc b/gcc/calls.cc
index 4d7f6c3d291..0242d52cfb3 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -506,11 +506,11 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   if (ecf_flags & ECF_NORETURN)
     add_reg_note (call_insn, REG_NORETURN, const0_rtx);
 
-  if (ecf_flags & ECF_RETURNS_TWICE)
-    {
-      add_reg_note (call_insn, REG_SETJMP, const0_rtx);
-      cfun->calls_setjmp = 1;
-    }
+  if (ecf_flags & ECF_RETURNS_TWICE
+      /* We rely on GIMPLE setting this flag and here use it to
+	 catch formerly indirect and not control-altering calls.  */
+      && cfun->calls_setjmp)
+    add_reg_note (call_insn, REG_SETJMP, const0_rtx);
 
   SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
 
diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc
index 25b1558dcb9..ab143a6d2d3 100644
--- a/gcc/cfgexpand.cc
+++ b/gcc/cfgexpand.cc
@@ -2808,6 +2808,11 @@ expand_call_stmt (gcall *stmt)
   /* Must come after copying location.  */
   copy_warning (exp, stmt);
 
+  /* For calls that do not alter control flow avoid REG_SETJMP notes.  */
+  bool saved_calls_setjmp = cfun->calls_setjmp;
+  if (!gimple_call_ctrl_altering_p (stmt))
+    cfun->calls_setjmp = false;
+
   /* Ensure RTL is created for debug args.  */
   if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
     {
@@ -2846,6 +2851,8 @@ expand_call_stmt (gcall *stmt)
     }
 
   mark_transaction_restart_calls (stmt);
+
+  cfun->calls_setjmp = saved_calls_setjmp;
 }
 
 
diff --git a/gcc/testsuite/gcc.dg/pr108691.c b/gcc/testsuite/gcc.dg/pr108691.c
new file mode 100644
index 00000000000..e412df10f22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr108691.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern int __attribute__((returns_twice)) setjmp(void*);
+
+void bbb(void) {
+  int (*fnptr)(void*) = setjmp;
+  fnptr(0);
+}
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index a9fcc7fd050..e23293e5cd1 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -2280,7 +2280,9 @@ notice_special_calls (gcall *call)
 
   if (flags & ECF_MAY_BE_ALLOCA)
     cfun->calls_alloca = true;
-  if (flags & ECF_RETURNS_TWICE)
+  if (flags & ECF_RETURNS_TWICE
+      && (!(cfun->curr_properties & PROP_cfg)
+	  || gimple_call_ctrl_altering_p (call)))
     cfun->calls_setjmp = true;
 }
 
-- 
2.35.3


From 01375d8b209c91ea3d5b9e6f6ee6fa3e814c4142 Mon Sep 17 00:00:00 2001
From: Richard Biener <rguenther@suse.de>
Date: Mon, 13 Feb 2023 14:14:02 +0100
Subject: [PATCH 2/2] TLC to notice_special_calls
To: gcc-patches@gcc.gnu.org

The following adds a struct function argument to notice_special_calls,
removes the use from the inliner and make sure to not switch cfun
for each stmt outlined to another function.

	* tree-cfg.h (notice_speical_calls): Add struct function
	argument.
	* tree-cfg.cc (notice_special_calls): Likewise.
	(move_block_to_fn): Do not switch cfun around update_stmt and
	notice_special_calls.
	* gimplify.cc (gimplify_call_expr): Adjust.
	(gimplify_modify_expr): Likewise.
	* tree-ssa-dce.cc (eliminate_unnecessary_stmts): Likewise.
---
 gcc/gimplify.cc     |  4 ++--
 gcc/tree-cfg.cc     | 14 ++++++--------
 gcc/tree-cfg.h      |  2 +-
 gcc/tree-inline.cc  |  5 +++--
 gcc/tree-ssa-dce.cc |  2 +-
 5 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 1b362dd83e3..254ddc3c211 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -3864,7 +3864,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
 	 have to do is replicate it as a GIMPLE_CALL tuple.  */
       gimple_stmt_iterator gsi;
       call = gimple_build_call_from_tree (*expr_p, fnptrtype);
-      notice_special_calls (call);
+      notice_special_calls (cfun, call);
       gimplify_seq_add_stmt (pre_p, call);
       gsi = gsi_last (*pre_p);
       maybe_fold_stmt (&gsi);
@@ -6298,7 +6298,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 	      call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
 	    }
 	}
-      notice_special_calls (call_stmt);
+      notice_special_calls (cfun, call_stmt);
       if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
 	gimple_call_set_lhs (call_stmt, *to_p);
       else if (TREE_CODE (*to_p) == SSA_NAME)
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index e23293e5cd1..1dffcc6a693 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -2274,16 +2274,16 @@ single_noncomplex_succ (basic_block bb)
 /* T is CALL_EXPR.  Set current_function_calls_* flags.  */
 
 void
-notice_special_calls (gcall *call)
+notice_special_calls (function *fn, gcall *call)
 {
   int flags = gimple_call_flags (call);
 
   if (flags & ECF_MAY_BE_ALLOCA)
-    cfun->calls_alloca = true;
+    fn->calls_alloca = true;
   if (flags & ECF_RETURNS_TWICE
-      && (!(cfun->curr_properties & PROP_cfg)
+      && (!(fn->curr_properties & PROP_cfg)
 	  || gimple_call_ctrl_altering_p (call)))
-    cfun->calls_setjmp = true;
+    fn->calls_setjmp = true;
 }
 
 
@@ -7446,11 +7446,9 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb,
       /* We cannot leave any operands allocated from the operand caches of
 	 the current function.  */
       free_stmt_operands (cfun, stmt);
-      push_cfun (dest_cfun);
-      update_stmt (stmt);
+      update_stmt_fn (dest_cfun, stmt);
       if (is_gimple_call (stmt))
-	notice_special_calls (as_a <gcall *> (stmt));
-      pop_cfun ();
+	notice_special_calls (dest_cfun, as_a <gcall *> (stmt));
     }
 
   FOR_EACH_EDGE (e, ei, bb->succs)
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index 9b56a68fe9d..f845fcb9699 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -40,7 +40,7 @@ extern bool group_case_labels_stmt (gswitch *);
 extern bool group_case_labels (void);
 extern void replace_uses_by (tree, tree);
 extern basic_block single_noncomplex_succ (basic_block bb);
-extern void notice_special_calls (gcall *);
+extern void notice_special_calls (struct function *, gcall *);
 extern void clear_special_calls (void);
 extern edge find_taken_edge (basic_block, tree);
 extern void gimple_debug_bb (basic_block);
diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
index 7fd08310acf..af5b99fbaa3 100644
--- a/gcc/tree-inline.cc
+++ b/gcc/tree-inline.cc
@@ -2353,8 +2353,6 @@ copy_bb (copy_body_data *id, basic_block bb,
 			       dest->dump_name ());
 		    }
 		}
-
-	      notice_special_calls (as_a <gcall *> (stmt));
 	    }
 
 	  maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,
@@ -3076,6 +3074,9 @@ copy_cfg_body (copy_body_data * id,
 	new_bb->loop_father = entry_block_map->loop_father;
       }
 
+  cfun->calls_alloca |= src_cfun->calls_alloca;
+  cfun->calls_setjmp |= src_cfun->calls_setjmp;
+
   last = last_basic_block_for_fn (cfun);
 
   /* Now that we've duplicated the blocks, duplicate their edges.  */
diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc
index ceeb0ad5ab3..e9404c55bf9 100644
--- a/gcc/tree-ssa-dce.cc
+++ b/gcc/tree-ssa-dce.cc
@@ -1420,7 +1420,7 @@ eliminate_unnecessary_stmts (bool aggressive)
 	    {
 	      tree name = gimple_call_lhs (stmt);
 
-	      notice_special_calls (as_a <gcall *> (stmt));
+	      notice_special_calls (cfun, as_a <gcall *> (stmt));
 
 	      /* When LHS of var = call (); is dead, simplify it into
 		 call (); saving one operand.  */
-- 
2.35.3


      reply	other threads:[~2023-02-13 13:18 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-13 11:00 Richard Biener
2023-02-13 11:14 ` Jakub Jelinek
2023-02-13 12:41   ` Richard Biener
2023-02-13 12:46     ` Jakub Jelinek
2023-02-13 13:18       ` Richard Biener [this message]

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=nycvar.YFH.7.77.849.2302131318140.9226@jbgna.fhfr.qr \
    --to=rguenther@suse.de \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    /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).