]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
internal-fn, tree-cfg: Fix .TRAP handling and another __builtin_trap vops issue ...
authorJakub Jelinek <jakub@redhat.com>
Fri, 26 Aug 2022 07:28:48 +0000 (09:28 +0200)
committerJakub Jelinek <jakub@redhat.com>
Fri, 26 Aug 2022 07:28:48 +0000 (09:28 +0200)
This patch fixes 2 __builtin_unreachable/__builtin_trap related issues.
One (first hunk) is that CDDCE happily removes calls to .TRAP ()
internal-fn as useless.  The problem is that the internal-fn is
ECF_CONST | ECF_NORETURN, doesn't have lhs and so DCE thinks it doesn't
have side-effects and removes it.  __builtin_unreachable which has
the same ECF_* flags works fine, as since PR44485 we implicitly add
ECF_LOOPING_CONST_OR_PURE to ECF_CONST | ECF_NORETURN builtins, but
do it in flags_from_decl_or_type which isn't called for internal-fns.
As IFN_TRAP is the only ifn with such flags, it seems easier to
add it explicitly.

The other issue (which on the testcase can be seen only with the
first bug unfixed) is that execute_fixup_cfg can add a __builtin_trap
which needs vops, but nothing adds it and it can appear in many passes
which don't have corresponding TODO_update_ssa_only_virtuals etc.
Fixed similarly as last time but emitting ifn there instead.

2022-08-26  Jakub Jelinek  <jakub@redhat.com>

PR tree-optimization/106099
* internal-fn.def (TRAP): Add ECF_LOOPING_CONST_OR_PURE flag.
* tree-cfg.cc (execute_fixup_cfg): Add IFN_TRAP instead of
__builtin_trap to avoid the need of vops.

* gcc.dg/pr106099.c: New test.

gcc/internal-fn.def
gcc/testsuite/gcc.dg/pr106099.c [new file with mode: 0644]
gcc/tree-cfg.cc

index 7bf661ca376e3dbe5fbc3dec69e46206de9859e4..5e672183f4def9d0cdc29cf12fe17e8cff928f9f 100644 (file)
@@ -458,7 +458,8 @@ DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
 
 /* __builtin_trap created from/for __builtin_unreachable.  */
 DEF_INTERNAL_FN (TRAP, ECF_CONST | ECF_LEAF | ECF_NORETURN
-                      | ECF_NOTHROW | ECF_COLD, NULL)
+                      | ECF_NOTHROW | ECF_COLD | ECF_LOOPING_CONST_OR_PURE,
+                NULL)
 
 #undef DEF_INTERNAL_INT_FN
 #undef DEF_INTERNAL_FLT_FN
diff --git a/gcc/testsuite/gcc.dg/pr106099.c b/gcc/testsuite/gcc.dg/pr106099.c
new file mode 100644 (file)
index 0000000..01b1144
--- /dev/null
@@ -0,0 +1,10 @@
+/* PR tree-optimization/106099 */
+/* { dg-do compile } */
+/* { dg-options "-O -fharden-compares -fno-tree-forwprop -fno-tree-ch -fno-tree-dominator-opts -fno-tree-ccp -funreachable-traps --param=scev-max-expr-size=1" } */
+
+void
+foo (void)
+{
+  for (unsigned i = 0; i == 0; i++)
+    __builtin_printf ("%d", i);
+}
index 5bcf78198e78b018669e1c60889e8915d409421e..91ec33c80a41e1e0cc6224e137dd42144724a168 100644 (file)
@@ -9878,16 +9878,16 @@ execute_fixup_cfg (void)
            {
              if (stmt && is_gimple_call (stmt))
                gimple_call_set_ctrl_altering (stmt, false);
-             tree fndecl = builtin_decl_unreachable ();
-             stmt = gimple_build_call (fndecl, 0);
+             stmt = gimple_build_builtin_unreachable (UNKNOWN_LOCATION);
              gimple_stmt_iterator gsi = gsi_last_bb (bb);
              gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
              if (!cfun->after_inlining)
-               {
-                 gcall *call_stmt = dyn_cast <gcall *> (stmt);
-                 node->create_edge (cgraph_node::get_create (fndecl),
-                                    call_stmt, bb->count);
-               }
+               if (tree fndecl = gimple_call_fndecl (stmt))
+                 {
+                   gcall *call_stmt = dyn_cast <gcall *> (stmt);
+                   node->create_edge (cgraph_node::get_create (fndecl),
+                                      call_stmt, bb->count);
+                 }
            }
        }
     }