]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-ssa-dce.c
Use function_arg_info for TARGET_MUST_PASS_IN_STACK
[thirdparty/gcc.git] / gcc / tree-ssa-dce.c
index 2478219d8737d9e95fbc7eab47a56e8b6a86aa4d..80d5f5c30f7f4bbe209db5357414ff443ee88b5f 100644 (file)
@@ -115,6 +115,14 @@ static bool cfg_altered;
 static int *bb_postorder;
 
 
+/* True if we should treat any stmt with a vdef as necessary.  */
+
+static inline bool
+keep_all_vdefs_p ()
+{
+  return optimize_debug;
+}
+
 /* If STMT is not already marked necessary, mark it, and add it to the
    worklist if ADD_TO_WORKLIST is true.  */
 
@@ -237,6 +245,12 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
 
            default:;
            }
+
+       if (callee != NULL_TREE
+           && flag_allocation_dce
+           && DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee))
+         return;
+
        /* Most, but not all function calls are required.  Function calls that
           produce no result and have no side effects (i.e. const pure
           functions) are unnecessary.  */
@@ -245,6 +259,17 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
            mark_stmt_necessary (stmt, true);
            return;
          }
+       /* IFN_GOACC_LOOP calls are necessary in that they are used to
+          represent parameter (i.e. step, bound) of a lowered OpenACC
+          partitioned loop.  But this kind of partitioned loop might not
+          survive from aggressive loop removal for it has loop exit and
+          is assumed to be finite.  Therefore, we need to explicitly mark
+          these calls. (An example is libgomp.oacc-c-c++-common/pr84955.c) */
+       if (gimple_call_internal_p (stmt, IFN_GOACC_LOOP))
+         {
+           mark_stmt_necessary (stmt, true);
+           return;
+         }
        if (!gimple_call_lhs (stmt))
          return;
        break;
@@ -300,6 +325,12 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
       return;
     }
 
+  if (gimple_vdef (stmt) && keep_all_vdefs_p ())
+    {
+      mark_stmt_necessary (stmt, true);
+      return;
+    }
+
   return;
 }
 
@@ -400,7 +431,7 @@ find_obviously_necessary_stmts (bool aggressive)
   /* Prevent the empty possibly infinite loops from being removed.  */
   if (aggressive)
     {
-      struct loop *loop;
+      class loop *loop;
       if (mark_irreducible_loops ())
        FOR_EACH_BB_FN (bb, cfun)
          {
@@ -515,6 +546,9 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
 static void
 mark_aliased_reaching_defs_necessary (gimple *stmt, tree ref)
 {
+  /* Should have been caught before calling this function.  */
+  gcc_checking_assert (!keep_all_vdefs_p ());
+
   unsigned int chain;
   ao_ref refd;
   gcc_assert (!chain_ovfl);
@@ -577,6 +611,11 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
 
          default:;
          }
+
+      if (callee != NULL_TREE
+         && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)
+             || DECL_IS_OPERATOR_DELETE_P (callee)))
+       return false;
     }
 
   if (! gimple_clobber_p (def_stmt))
@@ -588,6 +627,8 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
 static void
 mark_all_reaching_defs_necessary (gimple *stmt)
 {
+  /* Should have been caught before calling this function.  */
+  gcc_checking_assert (!keep_all_vdefs_p ());
   walk_aliased_vdefs (NULL, gimple_vuse (stmt),
                      mark_all_reaching_defs_necessary_1, NULL, &visited);
 }
@@ -763,7 +804,11 @@ propagate_necessity (bool aggressive)
          /* If this is a call to free which is directly fed by an
             allocation function do not mark that necessary through
             processing the argument.  */
-         if (gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+         bool is_delete_operator
+           = (is_gimple_call (stmt)
+              && gimple_call_operator_delete_p (as_a <gcall *> (stmt)));
+         if (is_delete_operator
+             || gimple_call_builtin_p (stmt, BUILT_IN_FREE))
            {
              tree ptr = gimple_call_arg (stmt, 0);
              gimple *def_stmt;
@@ -773,11 +818,25 @@ propagate_necessity (bool aggressive)
              if (TREE_CODE (ptr) == SSA_NAME
                  && is_gimple_call (def_stmt = SSA_NAME_DEF_STMT (ptr))
                  && (def_callee = gimple_call_fndecl (def_stmt))
-                 && DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
-                 && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC
-                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
-                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
-               continue;
+                 && ((DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
+                      && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC
+                          || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
+                          || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
+                     || DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee)))
+               {
+                 /* Delete operators can have alignment and (or) size as next
+                    arguments.  When being a SSA_NAME, they must be marked
+                    as necessary.  */
+                 if (is_delete_operator && gimple_call_num_args (stmt) >= 2)
+                   for (unsigned i = 1; i < gimple_call_num_args (stmt); i++)
+                     {
+                       tree arg = gimple_call_arg (stmt, i);
+                       if (TREE_CODE (arg) == SSA_NAME)
+                         mark_operand_necessary (arg);
+                     }
+
+                 continue;
+               }
            }
 
          FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
@@ -787,6 +846,10 @@ propagate_necessity (bool aggressive)
          if (!use)
            continue;
 
+         /* No need to search for vdefs if we intrinsicly keep them all.  */
+         if (keep_all_vdefs_p ())
+           continue;
+
          /* If we dropped to simple mode make all immediately
             reachable definitions necessary.  */
          if (chain_ovfl)
@@ -831,6 +894,11 @@ propagate_necessity (bool aggressive)
                      || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
                continue;
 
+             if (callee != NULL_TREE
+                 && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)
+                     || DECL_IS_OPERATOR_DELETE_P (callee)))
+               continue;
+
              /* Calls implicitly load from memory, their arguments
                 in addition may explicitly perform memory loads.  */
              mark_all_reaching_defs_necessary (stmt);
@@ -1251,7 +1319,9 @@ eliminate_unnecessary_stmts (void)
             defining statement of its argument is not necessary
             (and thus is getting removed).  */
          if (gimple_plf (stmt, STMT_NECESSARY)
-             && gimple_call_builtin_p (stmt, BUILT_IN_FREE))
+             && (gimple_call_builtin_p (stmt, BUILT_IN_FREE)
+                 || (is_gimple_call (stmt)
+                     && gimple_call_operator_delete_p (as_a <gcall *> (stmt)))))
            {
              tree ptr = gimple_call_arg (stmt, 0);
              if (TREE_CODE (ptr) == SSA_NAME)
@@ -1308,12 +1378,13 @@ eliminate_unnecessary_stmts (void)
                     did not mark as necessary, it will confuse the
                     special logic we apply to malloc/free pair removal.  */
                  && (!(call = gimple_call_fndecl (stmt))
-                     || DECL_BUILT_IN_CLASS (call) != BUILT_IN_NORMAL
-                     || (DECL_FUNCTION_CODE (call) != BUILT_IN_ALIGNED_ALLOC
-                         && DECL_FUNCTION_CODE (call) != BUILT_IN_MALLOC
-                         && DECL_FUNCTION_CODE (call) != BUILT_IN_CALLOC
-                         && !ALLOCA_FUNCTION_CODE_P
-                             (DECL_FUNCTION_CODE (call)))))
+                     || ((DECL_BUILT_IN_CLASS (call) != BUILT_IN_NORMAL
+                          || (DECL_FUNCTION_CODE (call) != BUILT_IN_ALIGNED_ALLOC
+                              && DECL_FUNCTION_CODE (call) != BUILT_IN_MALLOC
+                              && DECL_FUNCTION_CODE (call) != BUILT_IN_CALLOC
+                              && !ALLOCA_FUNCTION_CODE_P
+                              (DECL_FUNCTION_CODE (call))))
+                         && !DECL_IS_REPLACEABLE_OPERATOR_NEW_P (call))))
                {
                  something_changed = true;
                  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1328,14 +1399,14 @@ eliminate_unnecessary_stmts (void)
                  update_stmt (stmt);
                  release_ssa_name (name);
 
-                 /* GOMP_SIMD_LANE (unless two argument) or ASAN_POISON
+                 /* GOMP_SIMD_LANE (unless three argument) or ASAN_POISON
                     without lhs is not needed.  */
                  if (gimple_call_internal_p (stmt))
                    switch (gimple_call_internal_fn (stmt))
                      {
                      case IFN_GOMP_SIMD_LANE:
-                       if (gimple_call_num_args (stmt) >= 2
-                           && !integer_nonzerop (gimple_call_arg (stmt, 1)))
+                       if (gimple_call_num_args (stmt) >= 3
+                           && !integer_nonzerop (gimple_call_arg (stmt, 2)))
                          break;
                        /* FALLTHRU */
                      case IFN_ASAN_POISON: