Simplify {gimplify_and_,}update_call_from_tree API
authorRichard Biener <rguenther@suse.de>
Wed, 14 Apr 2021 11:40:58 +0000 (13:40 +0200)
committerRichard Biener <rguenther@suse.de>
Mon, 26 Apr 2021 08:08:46 +0000 (10:08 +0200)
This removes update_call_from_tree in favor of
gimplify_and_update_call_from_tree, removing some code duplication
and simplifying the API use.  Some users of update_call_from_tree
have been transitioned to replace_call_with_value and the API
and its dependences have been moved to gimple-fold.h.

This shaves off another user of valid_gimple_rhs_p which is now
only used from within gimple-fold.c and thus moved and made private.

2021-04-14  Richard Biener  <rguenther@suse.de>

* tree-ssa-propagate.h (valid_gimple_rhs_p): Remove.
(update_gimple_call): Likewise.
(update_call_from_tree): Likewise.
* tree-ssa-propagate.c (valid_gimple_rhs_p): Remove.
(valid_gimple_call_p): Likewise.
(move_ssa_defining_stmt_for_defs): Likewise.
(finish_update_gimple_call): Likewise.
(update_gimple_call): Likewise.
(update_call_from_tree): Likewise.
(propagate_tree_value_into_stmt): Use replace_call_with_value.
* gimple-fold.h (update_gimple_call): Declare.
* gimple-fold.c (valid_gimple_rhs_p): Move here from
tree-ssa-propagate.c.
(update_gimple_call): Likewise.
(valid_gimple_call_p): Likewise.
(finish_update_gimple_call): Likewise, and simplify.
(gimplify_and_update_call_from_tree): Implement
update_call_from_tree functionality, avoid excessive
push/pop_gimplify_context.
(gimple_fold_builtin): Use only gimplify_and_update_call_from_tree.
(gimple_fold_call): Likewise.
* gimple-ssa-sprintf.c (try_substitute_return_value): Likewise.
* tree-ssa-ccp.c (ccp_folder::fold_stmt): Likewise.
(pass_fold_builtins::execute): Likewise.
(optimize_stack_restore): Use replace_call_with_value.
* tree-cfg.c (fold_loop_internal_call): Likewise.
* tree-ssa-dce.c (maybe_optimize_arith_overflow): Use
only gimplify_and_update_call_from_tree.
* tree-ssa-strlen.c (handle_builtin_strlen): Likewise.
(handle_builtin_strchr): Likewise.
* tsan.c: Include gimple-fold.h instead of tree-ssa-propagate.h.

* config/rs6000/rs6000-call.c (rs6000_gimple_fold_builtin):
Use replace_call_with_value.

gcc/config/rs6000/rs6000-call.c
gcc/gimple-fold.c
gcc/gimple-fold.h
gcc/gimple-ssa-sprintf.c
gcc/tree-cfg.c
gcc/tree-ssa-ccp.c
gcc/tree-ssa-dce.c
gcc/tree-ssa-propagate.c
gcc/tree-ssa-propagate.h
gcc/tree-ssa-strlen.c
gcc/tsan.c

index f567625..6f6dc47 100644 (file)
@@ -12369,7 +12369,7 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
        /* Convert result back to the lhs type.  */
        res = gimple_build (&stmts, VIEW_CONVERT_EXPR, TREE_TYPE (lhs), res);
        gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
-       update_call_from_tree (gsi, res);
+       replace_call_with_value (gsi, res);
        return true;
       }
     /* Vector loads.  */
index 7602018..aa33779 100644 (file)
@@ -335,6 +335,123 @@ maybe_fold_reference (tree expr)
   return NULL_TREE;
 }
 
+/* Return true if EXPR is an acceptable right-hand-side for a
+   GIMPLE assignment.  We validate the entire tree, not just
+   the root node, thus catching expressions that embed complex
+   operands that are not permitted in GIMPLE.  This function
+   is needed because the folding routines in fold-const.c
+   may return such expressions in some cases, e.g., an array
+   access with an embedded index addition.  It may make more
+   sense to have folding routines that are sensitive to the
+   constraints on GIMPLE operands, rather than abandoning any
+   any attempt to fold if the usual folding turns out to be too
+   aggressive.  */
+
+bool
+valid_gimple_rhs_p (tree expr)
+{
+  enum tree_code code = TREE_CODE (expr);
+
+  switch (TREE_CODE_CLASS (code))
+    {
+    case tcc_declaration:
+      if (!is_gimple_variable (expr))
+       return false;
+      break;
+
+    case tcc_constant:
+      /* All constants are ok.  */
+      break;
+
+    case tcc_comparison:
+      /* GENERIC allows comparisons with non-boolean types, reject
+        those for GIMPLE.  Let vector-typed comparisons pass - rules
+        for GENERIC and GIMPLE are the same here.  */
+      if (!(INTEGRAL_TYPE_P (TREE_TYPE (expr))
+           && (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
+               || TYPE_PRECISION (TREE_TYPE (expr)) == 1))
+         && ! VECTOR_TYPE_P (TREE_TYPE (expr)))
+       return false;
+
+      /* Fallthru.  */
+    case tcc_binary:
+      if (!is_gimple_val (TREE_OPERAND (expr, 0))
+         || !is_gimple_val (TREE_OPERAND (expr, 1)))
+       return false;
+      break;
+
+    case tcc_unary:
+      if (!is_gimple_val (TREE_OPERAND (expr, 0)))
+       return false;
+      break;
+
+    case tcc_expression:
+      switch (code)
+       {
+       case ADDR_EXPR:
+         {
+           tree t;
+           if (is_gimple_min_invariant (expr))
+             return true;
+           t = TREE_OPERAND (expr, 0);
+           while (handled_component_p (t))
+             {
+               /* ??? More checks needed, see the GIMPLE verifier.  */
+               if ((TREE_CODE (t) == ARRAY_REF
+                    || TREE_CODE (t) == ARRAY_RANGE_REF)
+                   && !is_gimple_val (TREE_OPERAND (t, 1)))
+                 return false;
+               t = TREE_OPERAND (t, 0);
+             }
+           if (!is_gimple_id (t))
+             return false;
+         }
+         break;
+
+       default:
+         if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
+           {
+             if ((code == COND_EXPR
+                  ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
+                  : !is_gimple_val (TREE_OPERAND (expr, 0)))
+                 || !is_gimple_val (TREE_OPERAND (expr, 1))
+                 || !is_gimple_val (TREE_OPERAND (expr, 2)))
+               return false;
+             break;
+           }
+         return false;
+       }
+      break;
+
+    case tcc_vl_exp:
+      return false;
+
+    case tcc_exceptional:
+      if (code == CONSTRUCTOR)
+       {
+         unsigned i;
+         tree elt;
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt)
+           if (!is_gimple_val (elt))
+             return false;
+         return true;
+       }
+      if (code != SSA_NAME)
+       return false;
+      break;
+
+    case tcc_reference:
+      if (code == BIT_FIELD_REF)
+       return is_gimple_val (TREE_OPERAND (expr, 0));
+      return false;
+
+    default:
+      return false;
+    }
+
+  return true;
+}
+
 
 /* Attempt to fold an assignment statement pointed-to by SI.  Returns a
    replacement rhs for the statement or NULL_TREE if no simplification
@@ -534,6 +651,72 @@ gsi_replace_with_seq_vops (gimple_stmt_iterator *si_p, gimple_seq stmts)
   gsi_replace_with_seq (si_p, stmts, false);
 }
 
+/* Helper function for update_gimple_call and
+   gimplify_and_update_call_from_tree.  A GIMPLE_CALL STMT is being replaced
+   with GIMPLE_CALL NEW_STMT.  */
+
+static void
+finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple *new_stmt,
+                          gimple *stmt)
+{
+  tree lhs = gimple_call_lhs (stmt);
+  gimple_call_set_lhs (new_stmt, lhs);
+  if (lhs && TREE_CODE (lhs) == SSA_NAME)
+    SSA_NAME_DEF_STMT (lhs) = new_stmt;
+  gimple_move_vops (new_stmt, stmt);
+  gimple_set_location (new_stmt, gimple_location (stmt));
+  if (gimple_block (new_stmt) == NULL_TREE)
+    gimple_set_block (new_stmt, gimple_block (stmt));
+  gsi_replace (si_p, new_stmt, false);
+}
+
+/* Update a GIMPLE_CALL statement at iterator *SI_P to call to FN
+   with number of arguments NARGS, where the arguments in GIMPLE form
+   follow NARGS argument.  */
+
+bool
+update_gimple_call (gimple_stmt_iterator *si_p, tree fn, int nargs, ...)
+{
+  va_list ap;
+  gcall *new_stmt, *stmt = as_a <gcall *> (gsi_stmt (*si_p));
+
+  gcc_assert (is_gimple_call (stmt));
+  va_start (ap, nargs);
+  new_stmt = gimple_build_call_valist (fn, nargs, ap);
+  finish_update_gimple_call (si_p, new_stmt, stmt);
+  va_end (ap);
+  return true;
+}
+
+/* Return true if EXPR is a CALL_EXPR suitable for representation
+   as a single GIMPLE_CALL statement.  If the arguments require
+   further gimplification, return false.  */
+
+static bool
+valid_gimple_call_p (tree expr)
+{
+  unsigned i, nargs;
+
+  if (TREE_CODE (expr) != CALL_EXPR)
+    return false;
+
+  nargs = call_expr_nargs (expr);
+  for (i = 0; i < nargs; i++)
+    {
+      tree arg = CALL_EXPR_ARG (expr, i);
+      if (is_gimple_reg_type (TREE_TYPE (arg)))
+       {
+         if (!is_gimple_val (arg))
+           return false;
+       }
+      else
+       if (!is_gimple_lvalue (arg))
+         return false;
+    }
+
+  return true;
+}
+
 /* Convert EXPR into a GIMPLE value suitable for substitution on the
    RHS of an assignment.  Insert the necessary statements before
    iterator *SI_P.  The statement at *SI_P, which must be a GIMPLE_CALL
@@ -556,17 +739,41 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
 
   gcc_assert (is_gimple_call (stmt));
 
-  push_gimplify_context (gimple_in_ssa_p (cfun));
+  if (valid_gimple_call_p (expr))
+    {
+      /* The call has simplified to another call.  */
+      tree fn = CALL_EXPR_FN (expr);
+      unsigned i;
+      unsigned nargs = call_expr_nargs (expr);
+      vec<tree> args = vNULL;
+      gcall *new_stmt;
+
+      if (nargs > 0)
+       {
+         args.create (nargs);
+         args.safe_grow_cleared (nargs, true);
+
+         for (i = 0; i < nargs; i++)
+           args[i] = CALL_EXPR_ARG (expr, i);
+       }
+
+      new_stmt = gimple_build_call_vec (fn, args);
+      finish_update_gimple_call (si_p, new_stmt, stmt);
+      args.release ();
+      return;
+    }
 
   lhs = gimple_call_lhs (stmt);
   if (lhs == NULL_TREE)
     {
+      push_gimplify_context (gimple_in_ssa_p (cfun));
       gimplify_and_add (expr, &stmts);
+      pop_gimplify_context (NULL);
+
       /* We can end up with folding a memcpy of an empty class assignment
         which gets optimized away by C++ gimplification.  */
       if (gimple_seq_empty_p (stmts))
        {
-         pop_gimplify_context (NULL);
          if (gimple_in_ssa_p (cfun))
            {
              unlink_stmt_vdef (stmt);
@@ -585,8 +792,6 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
                                       GSI_CONTINUE_LINKING);
     }
 
-  pop_gimplify_context (NULL);
-
   gsi_replace_with_seq_vops (si_p, stmts);
 }
 
@@ -4955,8 +5160,7 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi)
        STRIP_NOPS (result);
       else
        result = fold_convert (gimple_call_return_type (stmt), result);
-      if (!update_call_from_tree (gsi, result))
-       gimplify_and_update_call_from_tree (gsi, result);
+      gimplify_and_update_call_from_tree (gsi, result);
       return true;
     }
 
@@ -5552,8 +5756,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
                result = build2_loc (gimple_location (stmt), COMPLEX_EXPR,
                                     ctype, result, overflow);
            }
-         if (!update_call_from_tree (gsi, result))
-           gimplify_and_update_call_from_tree (gsi, result);
+         gimplify_and_update_call_from_tree (gsi, result);
          changed = true;
        }
     }
index f495dac..2401646 100644 (file)
@@ -28,6 +28,7 @@ extern tree get_symbol_constant_value (tree);
 struct c_strlen_data;
 extern bool get_range_strlen (tree, c_strlen_data *, unsigned eltsize);
 extern void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
+extern bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
 extern bool fold_stmt (gimple_stmt_iterator *);
 extern bool fold_stmt (gimple_stmt_iterator *, tree (*) (tree));
 extern bool fold_stmt_inplace (gimple_stmt_iterator *);
index fed4fe7..fc74466 100644 (file)
@@ -4149,8 +4149,7 @@ try_substitute_return_value (gimple_stmt_iterator *gsi,
          /* Replace the call to the bounded function with a zero size
             (e.g., snprintf(0, 0, "%i", 123) with the constant result
             of the function.  */
-         if (!update_call_from_tree (gsi, cst))
-           gimplify_and_update_call_from_tree (gsi, cst);
+         gimplify_and_update_call_from_tree (gsi, cst);
          gimple *callstmt = gsi_stmt (*gsi);
          update_stmt (callstmt);
        }
index f985867..316aa83 100644 (file)
@@ -7530,7 +7530,7 @@ fold_loop_internal_call (gimple *g, tree value)
   gimple *use_stmt;
   gimple_stmt_iterator gsi = gsi_for_stmt (g);
 
-  update_call_from_tree (&gsi, value);
+  replace_call_with_value (&gsi, value);
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
     {
       FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
index 3bfd4a6..bf31f03 100644 (file)
@@ -2332,12 +2332,10 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
            && (flags & ECF_LOOPING_CONST_OR_PURE) == 0)
          {
            tree new_rhs = unshare_expr (val);
-           bool res;
            if (!useless_type_conversion_p (TREE_TYPE (lhs),
                                            TREE_TYPE (new_rhs)))
              new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
-           res = update_call_from_tree (gsi, new_rhs);
-           gcc_assert (res);
+           gimplify_and_update_call_from_tree (gsi, new_rhs);
            return true;
          }
 
@@ -2355,9 +2353,8 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
             tree new_rhs = fold_builtin_alloca_with_align (stmt);
             if (new_rhs)
              {
-               bool res = update_call_from_tree (gsi, new_rhs);
+               gimplify_and_update_call_from_tree (gsi, new_rhs);
                tree var = TREE_OPERAND (TREE_OPERAND (new_rhs, 0),0);
-               gcc_assert (res);
                insert_clobbers_for_var (*gsi, var);
                return true;
              }
@@ -2382,8 +2379,7 @@ ccp_folder::fold_stmt (gimple_stmt_iterator *gsi)
                    && ((TREE_INT_CST_LOW (ptrval.value) & (align - 1))
                        == (TREE_INT_CST_LOW (val.value) & (align - 1))))
                  {
-                   bool res = update_call_from_tree (gsi, ptr);
-                   gcc_assert (res);
+                   replace_call_with_value (gsi, ptr);
                    return true;
                  }
              }
@@ -2710,7 +2706,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
 
              stack_save_gsi = gsi_for_stmt (stack_save);
              rhs = build_int_cst (TREE_TYPE (gimple_call_arg (call, 0)), 0);
-             update_call_from_tree (&stack_save_gsi, rhs);
+             replace_call_with_value (&stack_save_gsi, rhs);
            }
        }
     }
@@ -3434,8 +3430,7 @@ pass_fold_builtins::execute (function *fun)
                  continue;
                }
 
-             if (!update_call_from_tree (&i, result))
-               gimplify_and_update_call_from_tree (&i, result);
+             gimplify_and_update_call_from_tree (&i, result);
            }
 
          todoflags |= TODO_update_address_taken;
index c027230..096cfc8 100644 (file)
@@ -1274,8 +1274,7 @@ maybe_optimize_arith_overflow (gimple_stmt_iterator *gsi,
       fprintf (dump_file, "\n");
     }
 
-  if (!update_call_from_tree (gsi, result))
-    gimplify_and_update_call_from_tree (gsi, result);
+  gimplify_and_update_call_from_tree (gsi, result);
 }
 
 /* Eliminate unnecessary statements. Any instruction not marked as necessary
index 17dd1ef..b3dcd43 100644 (file)
@@ -439,302 +439,6 @@ ssa_prop_fini (void)
 }
 
 
-/* Return true if EXPR is an acceptable right-hand-side for a
-   GIMPLE assignment.  We validate the entire tree, not just
-   the root node, thus catching expressions that embed complex
-   operands that are not permitted in GIMPLE.  This function
-   is needed because the folding routines in fold-const.c
-   may return such expressions in some cases, e.g., an array
-   access with an embedded index addition.  It may make more
-   sense to have folding routines that are sensitive to the
-   constraints on GIMPLE operands, rather than abandoning any
-   any attempt to fold if the usual folding turns out to be too
-   aggressive.  */
-
-bool
-valid_gimple_rhs_p (tree expr)
-{
-  enum tree_code code = TREE_CODE (expr);
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    case tcc_declaration:
-      if (!is_gimple_variable (expr))
-       return false;
-      break;
-
-    case tcc_constant:
-      /* All constants are ok.  */
-      break;
-
-    case tcc_comparison:
-      /* GENERIC allows comparisons with non-boolean types, reject
-         those for GIMPLE.  Let vector-typed comparisons pass - rules
-        for GENERIC and GIMPLE are the same here.  */
-      if (!(INTEGRAL_TYPE_P (TREE_TYPE (expr))
-           && (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
-               || TYPE_PRECISION (TREE_TYPE (expr)) == 1))
-         && ! VECTOR_TYPE_P (TREE_TYPE (expr)))
-       return false;
-
-      /* Fallthru.  */
-    case tcc_binary:
-      if (!is_gimple_val (TREE_OPERAND (expr, 0))
-         || !is_gimple_val (TREE_OPERAND (expr, 1)))
-       return false;
-      break;
-
-    case tcc_unary:
-      if (!is_gimple_val (TREE_OPERAND (expr, 0)))
-       return false;
-      break;
-
-    case tcc_expression:
-      switch (code)
-        {
-        case ADDR_EXPR:
-          {
-           tree t;
-           if (is_gimple_min_invariant (expr))
-             return true;
-            t = TREE_OPERAND (expr, 0);
-            while (handled_component_p (t))
-              {
-                /* ??? More checks needed, see the GIMPLE verifier.  */
-                if ((TREE_CODE (t) == ARRAY_REF
-                     || TREE_CODE (t) == ARRAY_RANGE_REF)
-                    && !is_gimple_val (TREE_OPERAND (t, 1)))
-                  return false;
-                t = TREE_OPERAND (t, 0);
-              }
-            if (!is_gimple_id (t))
-              return false;
-          }
-          break;
-
-       default:
-         if (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS)
-           {
-             if ((code == COND_EXPR
-                  ? !is_gimple_condexpr (TREE_OPERAND (expr, 0))
-                  : !is_gimple_val (TREE_OPERAND (expr, 0)))
-                 || !is_gimple_val (TREE_OPERAND (expr, 1))
-                 || !is_gimple_val (TREE_OPERAND (expr, 2)))
-               return false;
-             break;
-           }
-         return false;
-       }
-      break;
-
-    case tcc_vl_exp:
-      return false;
-
-    case tcc_exceptional:
-      if (code == CONSTRUCTOR)
-       {
-         unsigned i;
-         tree elt;
-         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt)
-           if (!is_gimple_val (elt))
-             return false;
-         return true;
-       }
-      if (code != SSA_NAME)
-        return false;
-      break;
-
-    case tcc_reference:
-      if (code == BIT_FIELD_REF)
-       return is_gimple_val (TREE_OPERAND (expr, 0));
-      return false;
-
-    default:
-      return false;
-    }
-
-  return true;
-}
-
-
-/* Return true if EXPR is a CALL_EXPR suitable for representation
-   as a single GIMPLE_CALL statement.  If the arguments require
-   further gimplification, return false.  */
-
-static bool
-valid_gimple_call_p (tree expr)
-{
-  unsigned i, nargs;
-
-  if (TREE_CODE (expr) != CALL_EXPR)
-    return false;
-
-  nargs = call_expr_nargs (expr);
-  for (i = 0; i < nargs; i++)
-    {
-      tree arg = CALL_EXPR_ARG (expr, i);
-      if (is_gimple_reg_type (TREE_TYPE (arg)))
-       {
-         if (!is_gimple_val (arg))
-           return false;
-       }
-      else
-       if (!is_gimple_lvalue (arg))
-         return false;
-    }
-
-  return true;
-}
-
-
-/* Make SSA names defined by OLD_STMT point to NEW_STMT
-   as their defining statement.  */
-
-void
-move_ssa_defining_stmt_for_defs (gimple *new_stmt, gimple *old_stmt)
-{
-  tree var;
-  ssa_op_iter iter;
-
-  if (gimple_in_ssa_p (cfun))
-    {
-      /* Make defined SSA_NAMEs point to the new
-         statement as their definition.  */
-      FOR_EACH_SSA_TREE_OPERAND (var, old_stmt, iter, SSA_OP_ALL_DEFS)
-        {
-          if (TREE_CODE (var) == SSA_NAME)
-            SSA_NAME_DEF_STMT (var) = new_stmt;
-        }
-    }
-}
-
-/* Helper function for update_gimple_call and update_call_from_tree.
-   A GIMPLE_CALL STMT is being replaced with GIMPLE_CALL NEW_STMT.  */
-
-static void
-finish_update_gimple_call (gimple_stmt_iterator *si_p, gimple *new_stmt,
-                          gimple *stmt)
-{
-  gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
-  move_ssa_defining_stmt_for_defs (new_stmt, stmt);
-  gimple_move_vops (new_stmt, stmt);
-  gimple_set_location (new_stmt, gimple_location (stmt));
-  if (gimple_block (new_stmt) == NULL_TREE)
-    gimple_set_block (new_stmt, gimple_block (stmt));
-  gsi_replace (si_p, new_stmt, false);
-}
-
-/* Update a GIMPLE_CALL statement at iterator *SI_P to call to FN
-   with number of arguments NARGS, where the arguments in GIMPLE form
-   follow NARGS argument.  */
-
-bool
-update_gimple_call (gimple_stmt_iterator *si_p, tree fn, int nargs, ...)
-{
-  va_list ap;
-  gcall *new_stmt, *stmt = as_a <gcall *> (gsi_stmt (*si_p));
-
-  gcc_assert (is_gimple_call (stmt));
-  va_start (ap, nargs);
-  new_stmt = gimple_build_call_valist (fn, nargs, ap);
-  finish_update_gimple_call (si_p, new_stmt, stmt);
-  va_end (ap);
-  return true;
-}
-
-/* Update a GIMPLE_CALL statement at iterator *SI_P to reflect the
-   value of EXPR, which is expected to be the result of folding the
-   call.  This can only be done if EXPR is a CALL_EXPR with valid
-   GIMPLE operands as arguments, or if it is a suitable RHS expression
-   for a GIMPLE_ASSIGN.  More complex expressions will require
-   gimplification, which will introduce additional statements.  In this
-   event, no update is performed, and the function returns false.
-   Note that we cannot mutate a GIMPLE_CALL in-place, so we always
-   replace the statement at *SI_P with an entirely new statement.
-   The new statement need not be a call, e.g., if the original call
-   folded to a constant.  */
-
-bool
-update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
-{
-  gimple *stmt = gsi_stmt (*si_p);
-
-  if (valid_gimple_call_p (expr))
-    {
-      /* The call has simplified to another call.  */
-      tree fn = CALL_EXPR_FN (expr);
-      unsigned i;
-      unsigned nargs = call_expr_nargs (expr);
-      vec<tree> args = vNULL;
-      gcall *new_stmt;
-
-      if (nargs > 0)
-        {
-          args.create (nargs);
-         args.safe_grow_cleared (nargs, true);
-
-          for (i = 0; i < nargs; i++)
-            args[i] = CALL_EXPR_ARG (expr, i);
-        }
-
-      new_stmt = gimple_build_call_vec (fn, args);
-      finish_update_gimple_call (si_p, new_stmt, stmt);
-      args.release ();
-
-      return true;
-    }
-  else if (valid_gimple_rhs_p (expr))
-    {
-      tree lhs = gimple_call_lhs (stmt);
-      gimple *new_stmt;
-
-      /* The call has simplified to an expression
-         that cannot be represented as a GIMPLE_CALL. */
-      if (lhs)
-        {
-          /* A value is expected.
-             Introduce a new GIMPLE_ASSIGN statement.  */
-          STRIP_USELESS_TYPE_CONVERSION (expr);
-          new_stmt = gimple_build_assign (lhs, expr);
-          move_ssa_defining_stmt_for_defs (new_stmt, stmt);
-         gimple_move_vops (new_stmt, stmt);
-        }
-      else if (!TREE_SIDE_EFFECTS (expr))
-        {
-          /* No value is expected, and EXPR has no effect.
-             Replace it with an empty statement.  */
-          new_stmt = gimple_build_nop ();
-         if (gimple_in_ssa_p (cfun))
-           {
-             unlink_stmt_vdef (stmt);
-             release_defs (stmt);
-           }
-        }
-      else
-        {
-          /* No value is expected, but EXPR has an effect,
-             e.g., it could be a reference to a volatile
-             variable.  Create an assignment statement
-             with a dummy (unused) lhs variable.  */
-          STRIP_USELESS_TYPE_CONVERSION (expr);
-         if (gimple_in_ssa_p (cfun))
-           lhs = make_ssa_name (TREE_TYPE (expr));
-         else
-           lhs = create_tmp_var (TREE_TYPE (expr));
-          new_stmt = gimple_build_assign (lhs, expr);
-         gimple_move_vops (new_stmt, stmt);
-          move_ssa_defining_stmt_for_defs (new_stmt, stmt);
-        }
-      gimple_set_location (new_stmt, gimple_location (stmt));
-      gsi_replace (si_p, new_stmt, false);
-      return true;
-    }
-  else
-    /* The call simplified to an expression that is
-       not a valid GIMPLE RHS.  */
-    return false;
-}
-
 /* Entry point to the propagation engine.
 
    The VISIT_STMT virtual function is called for every statement
@@ -1539,10 +1243,8 @@ propagate_tree_value_into_stmt (gimple_stmt_iterator *gsi, tree val)
            && gimple_call_lhs (stmt) != NULL_TREE)
     {
       tree expr = NULL_TREE;
-      bool res;
       propagate_tree_value (&expr, val);
-      res = update_call_from_tree (gsi, expr);
-      gcc_assert (res);
+      replace_call_with_value (gsi, expr);
     }
   else if (gswitch *swtch_stmt = dyn_cast <gswitch *> (stmt))
     propagate_tree_value (gimple_switch_index_ptr (swtch_stmt), val);
index 60e2f68..5257fbb 100644 (file)
@@ -63,10 +63,7 @@ enum ssa_prop_result {
 };
 
 
-extern bool valid_gimple_rhs_p (tree);
 extern void move_ssa_defining_stmt_for_defs (gimple *, gimple *);
-extern bool update_gimple_call (gimple_stmt_iterator *, tree, int, ...);
-extern bool update_call_from_tree (gimple_stmt_iterator *, tree);
 extern bool stmt_makes_single_store (gimple *);
 extern bool may_propagate_copy (tree, tree);
 extern bool may_propagate_copy_into_stmt (gimple *, tree);
index cccd4a0..c7b5e2c 100644 (file)
@@ -2158,8 +2158,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
          if (bound)
            rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
 
-         if (!update_call_from_tree (gsi, rhs))
-           gimplify_and_update_call_from_tree (gsi, rhs);
+         gimplify_and_update_call_from_tree (gsi, rhs);
          stmt = gsi_stmt (*gsi);
          update_stmt (stmt);
          if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -2258,8 +2257,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
              }
            if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (ret)))
              ret = fold_convert_loc (loc, TREE_TYPE (lhs), ret);
-           if (!update_call_from_tree (gsi, ret))
-             gimplify_and_update_call_from_tree (gsi, ret);
+           gimplify_and_update_call_from_tree (gsi, ret);
            stmt = gsi_stmt (*gsi);
            update_stmt (stmt);
            if (dump_file && (dump_flags & TDF_DETAILS) != 0)
@@ -2337,8 +2335,7 @@ handle_builtin_strchr (gimple_stmt_iterator *gsi)
                                              TREE_TYPE (rhs)))
                rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
            }
-         if (!update_call_from_tree (gsi, rhs))
-           gimplify_and_update_call_from_tree (gsi, rhs);
+         gimplify_and_update_call_from_tree (gsi, rhs);
          stmt = gsi_stmt (*gsi);
          update_stmt (stmt);
          if (dump_file && (dump_flags & TDF_DETAILS) != 0)
index 7db157e..a1868b6 100644 (file)
@@ -36,7 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "tree-cfg.h"
 #include "tree-iterator.h"
-#include "tree-ssa-propagate.h"
+#include "gimple-fold.h"
 #include "tree-ssa-loop-ivopts.h"
 #include "tree-eh.h"
 #include "tsan.h"