On Wed, Apr 14, 2021 at 4:27 PM Richard Biener <rguent...@suse.de> wrote:
>
> 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.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1.

g:52a5515ed6619739eb122f05ce26057dd8b06fb6

> 2021-04-14  Richard Biener  <rguent...@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 |   2 +-
>  gcc/gimple-fold.c               | 219 ++++++++++++++++++++++-
>  gcc/gimple-fold.h               |   1 +
>  gcc/gimple-ssa-sprintf.c        |   3 +-
>  gcc/tree-cfg.c                  |   2 +-
>  gcc/tree-ssa-ccp.c              |  15 +-
>  gcc/tree-ssa-dce.c              |   3 +-
>  gcc/tree-ssa-propagate.c        | 300 +-------------------------------
>  gcc/tree-ssa-propagate.h        |   3 -
>  gcc/tree-ssa-strlen.c           |   9 +-
>  gcc/tsan.c                      |   2 +-
>  11 files changed, 226 insertions(+), 333 deletions(-)
>
> diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
> index f5676255387..6f6dc47f0ae 100644
> --- a/gcc/config/rs6000/rs6000-call.c
> +++ b/gcc/config/rs6000/rs6000-call.c
> @@ -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.  */
> diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
> index 9e6683dbac9..a118ef4bbc3 100644
> --- a/gcc/gimple-fold.c
> +++ b/gcc/gimple-fold.c
> @@ -338,6 +338,123 @@ maybe_fold_reference (tree expr, bool is_lhs)
>    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
> @@ -551,6 +668,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
> @@ -573,17 +756,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);
> @@ -602,8 +809,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);
>  }
>
> @@ -4972,8 +5177,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;
>      }
>
> @@ -5569,8 +5773,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;
>         }
>      }
> diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
> index f495dac9e71..2401646c484 100644
> --- a/gcc/gimple-fold.h
> +++ b/gcc/gimple-fold.h
> @@ -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 *);
> diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
> index fed4fe76279..fc744669e4b 100644
> --- a/gcc/gimple-ssa-sprintf.c
> +++ b/gcc/gimple-ssa-sprintf.c
> @@ -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);
>         }
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index 4f63aa69ba8..a393e47882a 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -7539,7 +7539,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)
> diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
> index 3bfd4a6265c..bf31f035153 100644
> --- a/gcc/tree-ssa-ccp.c
> +++ b/gcc/tree-ssa-ccp.c
> @@ -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;
> diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
> index c027230acdc..096cfc8721d 100644
> --- a/gcc/tree-ssa-dce.c
> +++ b/gcc/tree-ssa-dce.c
> @@ -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
> diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
> index 17dd1efd81d..b3dcd43c00d 100644
> --- a/gcc/tree-ssa-propagate.c
> +++ b/gcc/tree-ssa-propagate.c
> @@ -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);
> diff --git a/gcc/tree-ssa-propagate.h b/gcc/tree-ssa-propagate.h
> index 60e2f68baa8..5257fbb0cf8 100644
> --- a/gcc/tree-ssa-propagate.h
> +++ b/gcc/tree-ssa-propagate.h
> @@ -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);
> diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
> index cccd4a06771..c7b5e2c6e6b 100644
> --- a/gcc/tree-ssa-strlen.c
> +++ b/gcc/tree-ssa-strlen.c
> @@ -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)
> diff --git a/gcc/tsan.c b/gcc/tsan.c
> index 7db157e21e5..a1868b661e6 100644
> --- a/gcc/tsan.c
> +++ b/gcc/tsan.c
> @@ -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"
> --
> 2.26.2

Reply via email to