]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/93491 - avoid PRE of trapping calls across exits
authorRichard Biener <rguenther@suse.de>
Wed, 1 Sep 2021 09:49:39 +0000 (11:49 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 1 Sep 2021 10:56:13 +0000 (12:56 +0200)
This makes us avoid PREing calls that could trap across other
calls that might not return.  The PR88087 testcase has exactly
such case so I've refactored the testcase to contain a valid PRE.
I've also adjusted PRE to not consider pure calls possibly
not returning in line with what we do elsewhere.

Note we don't have a good idea whether a function always returns
normally or whether its body is known to never trap.  That's
something IPA could compute.

2021-09-01  Richard Biener  <rguenther@suse.de>

PR tree-optimization/93491
* tree-ssa-pre.c (compute_avail): Set BB_MAY_NOTRETURN
after processing the stmt itself.  Do not consider
pure functions possibly not returning.  Properly avoid
adding possibly trapping calls to EXP_GEN when there's
a preceeding possibly not returning call.
* tree-ssa-sccvn.c (vn_reference_may_trap): Conservatively
not handle calls.

* gcc.dg/torture/pr93491.c: New testcase.
* gcc.dg/tree-ssa/pr88087.c: Change to valid PRE opportunity.

gcc/testsuite/gcc.dg/torture/pr93491.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr88087.c
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr93491.c b/gcc/testsuite/gcc.dg/torture/pr93491.c
new file mode 100644 (file)
index 0000000..2cb4c0c
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+extern void exit (int);
+
+__attribute__((noipa))
+void f(int i)
+{
+  exit(i);
+}
+
+__attribute__((const,noipa))
+int g(int i)
+{
+  return 1 / i;
+}
+
+int main()
+{
+  while (1)
+    {
+      f(0);
+      f(g(0));
+    }
+}
index d0061b61aedb0e11792f90ac81424b478b298aff..c48dba5bf21c339197d337b616f5fd71a08cd45e 100644 (file)
@@ -1,17 +1,17 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-pre-stats" } */
+/* { dg-options "-O2 -fno-code-hoisting -fdump-tree-pre-stats" } */
 
 int f();
 int d;
-void c()
+void c(int x)
 {
-  for (;;)
-    {
-      f();
-      int (*fp)() __attribute__((const)) = (void *)f;
-      d = fp();
-    }
+  int (*fp)() __attribute__((const)) = (void *)f;
+  if (x)
+    d = fp ();
+  int tem = fp ();
+  f();
+  d = tem;
 }
 
-/* We shouldn't ICE and hoist the const call of fp out of the loop.  */
+/* We shouldn't ICE and PRE the const call.  */
 /* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */
index ebe95cc6c73f0540db5986869f8d89816df470a4..769aadb2315ab39acab82d26397443e94a918d52 100644 (file)
@@ -3957,6 +3957,7 @@ compute_avail (function *fun)
 
       /* Now compute value numbers and populate value sets with all
         the expressions computed in BLOCK.  */
+      bool set_bb_may_notreturn = false;
       for (gimple_stmt_iterator gsi = gsi_start_bb (block); !gsi_end_p (gsi);
           gsi_next (&gsi))
        {
@@ -3965,6 +3966,12 @@ compute_avail (function *fun)
 
          stmt = gsi_stmt (gsi);
 
+         if (set_bb_may_notreturn)
+           {
+             BB_MAY_NOTRETURN (block) = 1;
+             set_bb_may_notreturn = false;
+           }
+
          /* Cache whether the basic-block has any non-visible side-effect
             or control flow.
             If this isn't a call or it is the last stmt in the
@@ -3976,10 +3983,12 @@ compute_avail (function *fun)
                 that forbids hoisting possibly trapping expressions
                 before it.  */
              int flags = gimple_call_flags (stmt);
-             if (!(flags & ECF_CONST)
+             if (!(flags & (ECF_CONST|ECF_PURE))
                  || (flags & ECF_LOOPING_CONST_OR_PURE)
                  || stmt_can_throw_external (fun, stmt))
-               BB_MAY_NOTRETURN (block) = 1;
+               /* Defer setting of BB_MAY_NOTRETURN to avoid it
+                  influencing the processing of the call itself.  */
+               set_bb_may_notreturn = true;
            }
 
          FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
@@ -4030,11 +4039,16 @@ compute_avail (function *fun)
                /* If the value of the call is not invalidated in
                   this block until it is computed, add the expression
                   to EXP_GEN.  */
-               if (!gimple_vuse (stmt)
-                   || gimple_code
-                        (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI
-                   || gimple_bb (SSA_NAME_DEF_STMT
-                                   (gimple_vuse (stmt))) != block)
+               if ((!gimple_vuse (stmt)
+                    || gimple_code
+                         (SSA_NAME_DEF_STMT (gimple_vuse (stmt))) == GIMPLE_PHI
+                    || gimple_bb (SSA_NAME_DEF_STMT
+                                  (gimple_vuse (stmt))) != block)
+                   /* If the REFERENCE traps and there was a preceding
+                      point in the block that might not return avoid
+                      adding the reference to EXP_GEN.  */
+                   && (!BB_MAY_NOTRETURN (block)
+                       || !vn_reference_may_trap (ref)))
                  {
                    result = get_or_alloc_expr_for_reference
                               (ref, gimple_location (stmt));
@@ -4220,6 +4234,11 @@ compute_avail (function *fun)
              break;
            }
        }
+      if (set_bb_may_notreturn)
+       {
+         BB_MAY_NOTRETURN (block) = 1;
+         set_bb_may_notreturn = false;
+       }
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
index bf87cee38573064e552ec04e4fc1b3ec37f0cc02..2357bbdbf9022c4ee540f97e323ad81073a3ec3e 100644 (file)
@@ -5851,6 +5851,7 @@ vn_reference_may_trap (vn_reference_t ref)
     case MODIFY_EXPR:
     case CALL_EXPR:
       /* We do not handle calls.  */
+      return true;
     case ADDR_EXPR:
       /* And toplevel address computations never trap.  */
       return false;