This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tuples][patch] Convert pass_fold_builtins to tuples and related fixes
- From: "Bill Maddox" <maddox at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: "Diego Novillo" <dnovillo at google dot com>
- Date: Wed, 12 Mar 2008 21:53:57 -0700
- Subject: [tuples][patch] Convert pass_fold_builtins to tuples and related fixes
This patch converts pass_fold_builtins to tuples and enables it,
removes some FIXMES and makes other minor corrections in
tree-ssa-ccp.c, and corrects several errors elsewhere revealed
during the development and testing of that work.
* tree.h (fold_call_stmt, gimple_fold_builtin_snprintf_chk):
Declare new functions.
* builtins.c (fold_builtin_object_size): Disable call to
compute_builtin_object_size, which has not been converted.
(gimple_rewrite_call_expr, gimple_fold_builtin_sprintf_chk,
gimple_fold_builtin_snprintf_chk, gimple_fold_builtin_varargs,
fold_call_stmt): New functions.
* tree-chrec.h (build_polynomial_chrec): Silence uninitialized
variable warning.
* tree-ssa-ccp.c (likely_value): Recognize additional cases
of constant values.
(surely_varying_stmt_p): Note that return statements are not
interesting to CCP as they no longer contain assignments.
(ccp_fold): Add missing spaces.
(valid_gimple_call_p): New function.
(get_maxval_strlen): Don't trip over unary operator.
(ccp_fold_builtin): Use fold_call_stmt and
gimple_fold_builtin_snprintf_chk. Enable disabled
call now that target has been converted for tuples.
Add missing spaces.
(move_ssa_defining_stmt_for_defs): New function.
(update_call_from_tree): New function.
(fold_gimple_call): Use update_call_from_tree.
(fold_stmt_inplace): Assert that operand folding tree
walk goes to completion, i.e., does not return non-null.
(optimize_stack_restore, optimize_stdarg_builtin):
Convert to tuples
(convert_to_gimple_builtin): Removed.
(gimplify_and_update_call_from_tree): New function.
Replaces convert_to_gimple_builtin.
(execute_fold_all_builtins): Convert to tuples.
* tree-ssa-propagate.c (substitute_and_fold):
Add comment regarding unused value of replaced_address.
* gimple-iterator.c (update_modified_stmt): Moved to
head of file to avoid a forward declaration.
(update_modified_stmts): New function.
(gsi_insert_seq_before_without_update,
gsi_insert_before_without_update,
gsi_insert_seq_after_without_update,
gsi_insert_after_without_update): New functions.
(gsi_insert_before, gsi_insert_seq_before,
gsi_insert_after, gsi_insert_seq_after): Call the
_without_update variants.
* gimplify.c (gimplify_seq_add_stmt, gimplify_seq_add_seq):
New functions.
(gimple_pop_condition, gimplify_return_expr, gimplify_loop_expr,
gimplify_switch_expr, gimplify_case_label_expr,
gimplify_self_mod_expr, gimplify_call_expr,
gimplify_modify_expr_to_memcpy, gimplify_modify_expr_to_memset,
gimplify_init_ctor_eval_range, gimpllify_modify_expr_complex_part,
gimplify_modify_expr, gimplify_asm_expr, gimplify_cleanup_point_expr,
gimple_push_cleanup, gimplify_omp_parallel, gimplify_omp_atomic,
gimplify_expr, gimplify_body, gimplify_function_tree): When adding
to statement sequences in the gimplifier, do not update operands.
* tree-dfa.c (find_new_referenced_vars): Convert to tuples.
* tree-flow.h (find_new_referenced_vars): Declare with new signature.
* gimple.h (gimple_return_set_retval): Add comment regarding
inconsistent validation of GIMPLE_RETURN result.
(gsi_insert_seq_before_without_update,
gsi_insert_before_without_update,
gsi_insert_seq_after_without_update,
gsi_insert_after_without_update): Declare new functions.
* passes.c (init_optimization_passes): Enable pass_fold_builtins.
Index: gcc/tree.h
===================================================================
--- gcc/tree.h (revision 133160)
+++ gcc/tree.h (working copy)
@@ -4814,6 +4814,8 @@ extern tree build_va_arg_indirect_ref (t
extern tree build_string_literal (int, const char *);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
extern int get_pointer_alignment (tree, unsigned int);
+extern tree fold_call_stmt (gimple, bool);
+extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum
built_in_function);
/* In convert.c */
extern tree strip_float_extensions (tree);
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c (revision 133160)
+++ gcc/builtins.c (working copy)
@@ -12154,6 +12154,8 @@ fold_builtin_object_size (tree ptr, tree
if (TREE_SIDE_EFFECTS (ptr))
return build_int_cst_type (size_type_node, object_size_type < 2 ? -1 : 0);
+ /* FIXME tuples. */
+#if 0
if (TREE_CODE (ptr) == ADDR_EXPR)
ret = build_int_cstu (size_type_node,
compute_builtin_object_size (ptr, object_size_type));
@@ -12170,6 +12172,9 @@ fold_builtin_object_size (tree ptr, tree
? -1 : 0))
ret = build_int_cstu (size_type_node, bytes);
}
+#else
+ ret = NULL_TREE;
+#endif
if (ret)
{
@@ -13337,3 +13342,304 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg,
return result;
}
#endif
+
+/* FIXME tuples.
+ The functions below provide an alternate interface for folding
builtin function
+ calls presented as GIMPLE_CALL statements rather than as
CALL_EXPRs. The folded
+ result is still expressed as a tree. There is too much code duplication in
+ the handling of varargs functions, and a more intrusive
re-factoring would permit
+ better sharing of code between the tree and statement-based
versions of these
+ functions. */
+
+/* Construct a new CALL_EXPR using the tail of the argument list of STMT
+ along with N new arguments specified as the "..." parameters. SKIP
+ is the number of arguments in STMT to be omitted. This function is used
+ to do varargs-to-varargs transformations. */
+
+static tree
+gimple_rewrite_call_expr (gimple stmt, int skip, tree fndecl, int n, ...)
+{
+ int oldnargs = gimple_call_num_args (stmt);
+ int nargs = oldnargs - skip + n;
+ tree fntype = TREE_TYPE (fndecl);
+ tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
+ tree *buffer;
+ int i, j;
+ va_list ap;
+
+ buffer = alloca (nargs * sizeof (tree));
+ va_start (ap, n);
+ for (i = 0; i < n; i++)
+ buffer[i] = va_arg (ap, tree);
+ va_end (ap);
+ for (j = skip; j < oldnargs; j++, i++)
+ buffer[i] = gimple_call_arg (stmt, j);
+
+ return fold (build_call_array (TREE_TYPE (fntype), fn, nargs, buffer));
+}
+
+/* Fold a call STMT to __{,v}sprintf_chk. Return NULL_TREE if
+ a normal call should be emitted rather than expanding the function
+ inline. FCODE is either BUILT_IN_SPRINTF_CHK or BUILT_IN_VSPRINTF_CHK. */
+
+static tree
+gimple_fold_builtin_sprintf_chk (gimple stmt, enum built_in_function fcode)
+{
+ tree dest, size, len, fn, fmt, flag;
+ const char *fmt_str;
+ int nargs = gimple_call_num_args (stmt);
+
+ /* Verify the required arguments in the original call. */
+ if (nargs < 4)
+ return NULL_TREE;
+ dest = gimple_call_arg (stmt, 0);
+ if (!validate_arg (dest, POINTER_TYPE))
+ return NULL_TREE;
+ flag = gimple_call_arg (stmt, 1);
+ if (!validate_arg (flag, INTEGER_TYPE))
+ return NULL_TREE;
+ size = gimple_call_arg (stmt, 2);
+ if (!validate_arg (size, INTEGER_TYPE))
+ return NULL_TREE;
+ fmt = gimple_call_arg (stmt, 3);
+ if (!validate_arg (fmt, POINTER_TYPE))
+ return NULL_TREE;
+
+ if (! host_integerp (size, 1))
+ return NULL_TREE;
+
+ len = NULL_TREE;
+
+ if (!init_target_chars ())
+ return NULL_TREE;
+
+ /* Check whether the format is a literal string constant. */
+ fmt_str = c_getstr (fmt);
+ if (fmt_str != NULL)
+ {
+ /* If the format doesn't contain % args or %%, we know the size. */
+ if (strchr (fmt_str, target_percent) == 0)
+ {
+ if (fcode != BUILT_IN_SPRINTF_CHK || nargs == 4)
+ len = build_int_cstu (size_type_node, strlen (fmt_str));
+ }
+ /* If the format is "%s" and first ... argument is a string literal,
+ we know the size too. */
+ else if (fcode == BUILT_IN_SPRINTF_CHK
+ && strcmp (fmt_str, target_percent_s) == 0)
+ {
+ tree arg;
+
+ if (nargs == 5)
+ {
+ arg = gimple_call_arg (stmt, 4);
+ if (validate_arg (arg, POINTER_TYPE))
+ {
+ len = c_strlen (arg, 1);
+ if (! len || ! host_integerp (len, 1))
+ len = NULL_TREE;
+ }
+ }
+ }
+ }
+
+ if (! integer_all_onesp (size))
+ {
+ if (! len || ! tree_int_cst_lt (len, size))
+ return NULL_TREE;
+ }
+
+ /* Only convert __{,v}sprintf_chk to {,v}sprintf if flag is 0
+ or if format doesn't contain % chars or is "%s". */
+ if (! integer_zerop (flag))
+ {
+ if (fmt_str == NULL)
+ return NULL_TREE;
+ if (strchr (fmt_str, target_percent) != NULL
+ && strcmp (fmt_str, target_percent_s))
+ return NULL_TREE;
+ }
+
+ /* If __builtin_{,v}sprintf_chk is used, assume {,v}sprintf is available. */
+ fn = built_in_decls[fcode == BUILT_IN_VSPRINTF_CHK
+ ? BUILT_IN_VSPRINTF : BUILT_IN_SPRINTF];
+ if (!fn)
+ return NULL_TREE;
+
+ return gimple_rewrite_call_expr (stmt, 4, fn, 2, dest, fmt);
+}
+
+/* Fold a call STMT to {,v}snprintf. Return NULL_TREE if
+ a normal call should be emitted rather than expanding the function
+ inline. FCODE is either BUILT_IN_SNPRINTF_CHK or
+ BUILT_IN_VSNPRINTF_CHK. If MAXLEN is not NULL, it is maximum length
+ passed as second argument. */
+
+tree
+gimple_fold_builtin_snprintf_chk (gimple stmt, tree maxlen,
+ enum built_in_function fcode)
+{
+ tree dest, size, len, fn, fmt, flag;
+ const char *fmt_str;
+
+ /* Verify the required arguments in the original call. */
+ if (gimple_call_num_args (stmt) < 5)
+ return NULL_TREE;
+ dest = gimple_call_arg (stmt, 0);
+ if (!validate_arg (dest, POINTER_TYPE))
+ return NULL_TREE;
+ len = gimple_call_arg (stmt, 1);
+ if (!validate_arg (len, INTEGER_TYPE))
+ return NULL_TREE;
+ flag = gimple_call_arg (stmt, 2);
+ if (!validate_arg (flag, INTEGER_TYPE))
+ return NULL_TREE;
+ size = gimple_call_arg (stmt, 3);
+ if (!validate_arg (size, INTEGER_TYPE))
+ return NULL_TREE;
+ fmt = gimple_call_arg (stmt, 4);
+ if (!validate_arg (fmt, POINTER_TYPE))
+ return NULL_TREE;
+
+ if (! host_integerp (size, 1))
+ return NULL_TREE;
+
+ if (! integer_all_onesp (size))
+ {
+ if (! host_integerp (len, 1))
+ {
+ /* If LEN is not constant, try MAXLEN too.
+ For MAXLEN only allow optimizing into non-_ocs function
+ if SIZE is >= MAXLEN, never convert to __ocs_fail (). */
+ if (maxlen == NULL_TREE || ! host_integerp (maxlen, 1))
+ return NULL_TREE;
+ }
+ else
+ maxlen = len;
+
+ if (tree_int_cst_lt (size, maxlen))
+ return NULL_TREE;
+ }
+
+ if (!init_target_chars ())
+ return NULL_TREE;
+
+ /* Only convert __{,v}snprintf_chk to {,v}snprintf if flag is 0
+ or if format doesn't contain % chars or is "%s". */
+ if (! integer_zerop (flag))
+ {
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
+ return NULL_TREE;
+ if (strchr (fmt_str, target_percent) != NULL
+ && strcmp (fmt_str, target_percent_s))
+ return NULL_TREE;
+ }
+
+ /* If __builtin_{,v}snprintf_chk is used, assume {,v}snprintf is
+ available. */
+ fn = built_in_decls[fcode == BUILT_IN_VSNPRINTF_CHK
+ ? BUILT_IN_VSNPRINTF : BUILT_IN_SNPRINTF];
+ if (!fn)
+ return NULL_TREE;
+
+ return gimple_rewrite_call_expr (stmt, 5, fn, 3, dest, len, fmt);
+}
+
+/* Builtins with folding operations that operate on "..." arguments
+ need special handling; we need to store the arguments in a convenient
+ data structure before attempting any folding. Fortunately there are
+ only a few builtins that fall into this category. FNDECL is the
+ function, EXP is the CALL_EXPR for the call, and IGNORE is true if the
+ result of the function call is ignored. */
+
+static tree
+gimple_fold_builtin_varargs (tree fndecl, gimple stmt, bool ignore
ATTRIBUTE_UNUSED)
+{
+ enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+ tree ret = NULL_TREE;
+
+ switch (fcode)
+ {
+ case BUILT_IN_SPRINTF_CHK:
+ case BUILT_IN_VSPRINTF_CHK:
+ ret = gimple_fold_builtin_sprintf_chk (stmt, fcode);
+ break;
+
+ case BUILT_IN_SNPRINTF_CHK:
+ case BUILT_IN_VSNPRINTF_CHK:
+ ret = gimple_fold_builtin_snprintf_chk (stmt, NULL_TREE, fcode);
+
+ default:
+ break;
+ }
+ if (ret)
+ {
+ ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
+ TREE_NO_WARNING (ret) = 1;
+ return ret;
+ }
+ return NULL_TREE;
+}
+
+/* A wrapper function for builtin folding that prevents warnings for
+ "statement without effect" and the like, caused by removing the
+ call node earlier than the warning is generated. */
+
+tree
+fold_call_stmt (gimple stmt, bool ignore)
+{
+ tree ret = NULL_TREE;
+ tree fndecl = gimple_call_fndecl (stmt);
+ if (fndecl
+ && TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_BUILT_IN (fndecl)
+ /* FIXME tuples. Do we need this?
+ Are we guaranteed that the arguments have been finalized
+ by the time we are in GIMPLE? */
+ && true /* !CALL_EXPR_VA_ARG_PACK (exp) */ )
+ {
+ int nargs = gimple_call_num_args (stmt);
+
+ /* FIXME: Don't use a list in this interface. */
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ {
+ tree arglist = NULL_TREE;
+ int i;
+ for (i = nargs - 1; i >= 0; i--)
+ arglist = tree_cons (NULL_TREE, gimple_call_arg (stmt,
i), arglist);
+ return targetm.fold_builtin (fndecl, arglist, ignore);
+ }
+ else
+ {
+ if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
+ {
+ tree args[MAX_ARGS_TO_FOLD_BUILTIN];
+ int i;
+ for (i = 0; i < nargs; i++)
+ args[i] = gimple_call_arg (stmt, i);
+ ret = fold_builtin_n (fndecl, args, nargs, ignore);
+ }
+ if (!ret)
+ ret = gimple_fold_builtin_varargs (fndecl, stmt, ignore);
+ if (ret)
+ {
+ /* Propagate location information from original call to
+ expansion of builtin. Otherwise things like
+ maybe_emit_chk_warning, that operate on the expansion
+ of a builtin, will use the wrong location information. */
+ if (gimple_has_location (stmt))
+ {
+ tree realret = ret;
+ if (TREE_CODE (ret) == NOP_EXPR)
+ realret = TREE_OPERAND (ret, 0);
+ if (CAN_HAVE_LOCATION_P (realret)
+ && !EXPR_HAS_LOCATION (realret))
+ SET_EXPR_LOCATION (realret, gimple_location (stmt));
+ }
+ return ret;
+ }
+ }
+ }
+ return NULL_TREE;
+}
Index: gcc/tree-chrec.h
===================================================================
--- gcc/tree-chrec.h (revision 133160)
+++ gcc/tree-chrec.h (working copy)
@@ -123,7 +123,7 @@ build_polynomial_chrec (unsigned loop_nu
tree left,
tree right)
{
- bool val;
+ bool val = false; /* Silence warning. */
if (left == chrec_dont_know
|| right == chrec_dont_know)
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c (revision 133160)
+++ gcc/tree-ssa-ccp.c (working copy)
@@ -566,6 +566,15 @@ likely_value (gimple stmt)
&& is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
return CONSTANT;
+ if (code == GIMPLE_COND
+ && is_gimple_min_invariant (gimple_cond_lhs (stmt))
+ && is_gimple_min_invariant (gimple_cond_rhs (stmt)))
+ return CONSTANT;
+
+ if (code == GIMPLE_SWITCH
+ && is_gimple_min_invariant (gimple_switch_index (stmt)))
+ return CONSTANT;
+
/* Arrive here for more complex cases. */
has_constant_operand = false;
@@ -652,8 +661,6 @@ surely_varying_stmt_p (gimple stmt)
/* Anything other than assignments and conditional jumps are not
interesting for CCP. */
if (gimple_code (stmt) != GIMPLE_ASSIGN
- && !(gimple_code (stmt) == GIMPLE_RETURN
- && gimple_return_retval (stmt) != NULL_TREE)
&& (gimple_code (stmt) != GIMPLE_COND)
&& (gimple_code (stmt) != GIMPLE_SWITCH))
return true;
@@ -991,7 +998,7 @@ ccp_fold (gimple stmt)
}
default:
- gcc_unreachable();
+ gcc_unreachable ();
}
}
break;
@@ -1000,7 +1007,7 @@ ccp_fold (gimple stmt)
/* It may be possible to fold away calls to builtin functions if
their arguments are constants. At present, such folding will not
be attempted, as likely_value classifies all calls as VARYING. */
- gcc_unreachable();
+ gcc_unreachable ();
break;
case GIMPLE_COND:
@@ -1043,7 +1050,7 @@ ccp_fold (gimple stmt)
}
default:
- gcc_unreachable();
+ gcc_unreachable ();
}
}
@@ -2251,6 +2258,22 @@ valid_gimple_rhs_p (tree expr)
return true;
}
+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++)
+ if (! is_gimple_operand (CALL_EXPR_ARG (expr, i)))
+ return false;
+
+ return true;
+}
+
/* For passing state through walk_tree into fold_stmt_r and its
children. */
@@ -2483,14 +2506,13 @@ get_maxval_strlen (tree arg, tree *lengt
{
case GIMPLE_ASSIGN:
{
- tree rhs;
-
/* The RHS of the statement defining VAR must either have a
constant length or come from another SSA_NAME with a constant
length. */
- if (gimple_num_ops (def_stmt) == 2)
+ if (get_gimple_rhs_class (gimple_subcode (def_stmt))
+ == GIMPLE_SINGLE_RHS)
{
- rhs = gimple_assign_rhs1 (def_stmt);
+ tree rhs = gimple_assign_rhs1 (def_stmt);
return get_maxval_strlen (rhs, length, visited, type);
}
}
@@ -2548,18 +2570,15 @@ ccp_fold_builtin (gimple stmt)
ignore = (gimple_call_lhs (stmt) == NULL);
- /* FIXME tuples. */
-#if 0
/* First try the generic builtin folder. If that succeeds, return the
result directly. */
- result = fold_call_expr (fn, ignore);
+ result = fold_call_stmt (stmt, ignore);
if (result)
{
if (ignore)
STRIP_NOPS (result);
return result;
}
-#endif
/* Ignore MD builtins. */
callee = gimple_call_fndecl (stmt);
@@ -2708,12 +2727,9 @@ ccp_fold_builtin (gimple stmt)
case BUILT_IN_SNPRINTF_CHK:
case BUILT_IN_VSNPRINTF_CHK:
- /* FIXME tuples. */
-#if 0
if (val[1] && is_gimple_val (val[1]))
- result = fold_builtin_snprintf_chk (fn, val[1],
- DECL_FUNCTION_CODE (callee));
-#endif
+ result = gimple_fold_builtin_snprintf_chk (stmt, val[1],
+ DECL_FUNCTION_CODE
(callee));
break;
default:
@@ -2808,7 +2824,7 @@ fold_gimple_assign (gimple stmt)
break;
case GIMPLE_INVALID_RHS:
- gcc_unreachable();
+ gcc_unreachable ();
}
return false;
@@ -2840,6 +2856,124 @@ fold_gimple_cond (gimple stmt)
return false;
}
+
+/* Make SSA names defined by OLD_STMT point to NEW_STMT
+ as their defining statement. */
+
+static 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;
+ }
+ }
+}
+
+
+/* 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 addtional 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. */
+
+static bool
+update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
+{
+ tree lhs;
+
+ gimple stmt = gsi_stmt (*si_p);
+
+ gcc_assert (gimple_code (stmt) == GIMPLE_CALL);
+
+ lhs = gimple_call_lhs (stmt);
+
+ 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, gc) *args = NULL;
+ gimple new_stmt;
+
+ if (nargs > 0)
+ {
+ args = VEC_alloc (tree, gc, nargs);
+ VEC_safe_grow (tree, gc, args, nargs);
+
+ for (i = 0; i < nargs; i++)
+ VEC_replace (tree, args, i, CALL_EXPR_ARG (expr, i));
+ }
+
+ new_stmt = gimple_build_call_vec (fn, args);
+ gimple_call_set_lhs (new_stmt, lhs);
+ copy_virtual_operands (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 if (valid_gimple_rhs_p (expr))
+ {
+ 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);
+ copy_virtual_operands (new_stmt, stmt);
+ move_ssa_defining_stmt_for_defs (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 ();
+ }
+ 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);
+ lhs = create_tmp_var (TREE_TYPE (expr), NULL);
+ new_stmt = gimple_build_assign (lhs, expr);
+ add_referenced_var (lhs);
+ lhs = make_ssa_name (lhs, new_stmt);
+ gimple_assign_set_lhs (new_stmt, lhs);
+ copy_virtual_operands (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;
+}
+
/* Attempt to fold a call statement referenced by the statement iterator GSI.
The statement may be replaced by another statement, e.g., if the call
simplifies to a constant value. Return true if any changes were made.
@@ -2858,33 +2992,8 @@ fold_gimple_call (gimple_stmt_iterator *
{
tree result = ccp_fold_builtin (stmt);
- if (result) {
- if (TREE_CODE (result) == CALL_EXPR)
- {
- /* FIXME tuples. Replace statement with the new call. */
- return false;
- }
- else if (valid_gimple_rhs_p (result))
- {
- /* The call has simplified to an expression
- that cannot be represented as a GIMPLE_CALL.
- Introduce a new GIMPLE_ASSIGN statement. */
- gimple new_stmt;
- tree lhs = gimple_call_lhs (stmt);
-
- STRIP_USELESS_TYPE_CONVERSION (result);
- new_stmt = gimple_build_assign (lhs, result);
- gimple_set_location (new_stmt, gimple_location (stmt));
- gsi_replace (gsi, new_stmt, false);
- return true;
- }
- else
- /* The call simplified to an expression that is
- not a valid GIMPLE RHS. */
- return false;
- }
- else
- return false;
+ if (result)
+ return update_call_from_tree (gsi, result);
}
else
{
@@ -3014,7 +3123,7 @@ fold_stmt_inplace (gimple stmt)
signal that the entire statement should be replaced with
a call to _builtin_trap. This functionality is currently
disabled, as noted in a FIXME, and cannot be supported here. */
- walk_gimple_op (stmt, fold_stmt_r, &wi);
+ gcc_assert (!walk_gimple_op (stmt, fold_stmt_r, &wi));
/* Fold the main computation performed by the statement. */
switch (gimple_code (stmt))
@@ -3033,9 +3142,6 @@ fold_stmt_inplace (gimple stmt)
return changed;
}
-/* FIXME tuples. */
-#if 0
-
/* Try to optimize out __builtin_stack_restore. Optimize it out
if there is another __builtin_stack_restore in the same basic
block and no calls or ASM_EXPRs are in between, or if this block's
@@ -3043,108 +3149,109 @@ fold_stmt_inplace (gimple stmt)
ASM_EXPRs after this __builtin_stack_restore. */
static tree
-optimize_stack_restore (basic_block bb, tree call, block_stmt_iterator i)
+optimize_stack_restore (gimple_stmt_iterator i)
{
- tree stack_save, stmt, callee;
+ tree callee, rhs;
+ gimple stmt, stack_save;
+ gimple_stmt_iterator stack_save_gsi;
- if (TREE_CODE (call) != CALL_EXPR
- || call_expr_nargs (call) != 1
- || TREE_CODE (CALL_EXPR_ARG (call, 0)) != SSA_NAME
- || !POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_ARG (call, 0))))
- return NULL_TREE;
+ basic_block bb = gsi_bb (i);
+ gimple call = gsi_stmt (i);
- for (bsi_next (&i); !bsi_end_p (i); bsi_next (&i))
- {
- tree call;
+ if (gimple_code (call) != GIMPLE_CALL
+ || gimple_call_num_args (call) != 1
+ || TREE_CODE (gimple_call_arg (call, 0)) != SSA_NAME
+ || !POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (call, 0))))
+ return false;
- stmt = bsi_stmt (i);
- if (TREE_CODE (stmt) == ASM_EXPR)
- return NULL_TREE;
- call = get_call_expr_in (stmt);
- if (call == NULL)
+ for (gsi_next (&i); !gsi_end_p (i); gsi_next (&i))
+ {
+ stmt = gsi_stmt (i);
+ if (gimple_code (stmt) == GIMPLE_ASM)
+ return false;
+ if (gimple_code (stmt) != GIMPLE_CALL)
continue;
- callee = get_callee_fndecl (call);
+ callee = gimple_call_fndecl (stmt);
if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
- return NULL_TREE;
+ return false;
if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE)
break;
}
- if (bsi_end_p (i)
+ if (gsi_end_p (i)
&& (! single_succ_p (bb)
|| single_succ_edge (bb)->dest != EXIT_BLOCK_PTR))
- return NULL_TREE;
+ return false;
- stack_save = SSA_NAME_DEF_STMT (CALL_EXPR_ARG (call, 0));
- if (TREE_CODE (stack_save) != GIMPLE_MODIFY_STMT
- || GIMPLE_STMT_OPERAND (stack_save, 0) != CALL_EXPR_ARG (call, 0)
- || TREE_CODE (GIMPLE_STMT_OPERAND (stack_save, 1)) != CALL_EXPR
- || tree_could_throw_p (stack_save)
- || !has_single_use (CALL_EXPR_ARG (call, 0)))
- return NULL_TREE;
+ stack_save = SSA_NAME_DEF_STMT (gimple_call_arg (call, 0));
+ if (gimple_code (stack_save) != GIMPLE_CALL
+ || gimple_call_lhs (stack_save) != gimple_call_arg (call, 0)
+ || stmt_could_throw_p (stack_save)
+ || !has_single_use (gimple_call_arg (call, 0)))
+ return false;
- callee = get_callee_fndecl (GIMPLE_STMT_OPERAND (stack_save, 1));
+ callee = gimple_call_fndecl (stack_save);
if (!callee
|| DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
|| DECL_FUNCTION_CODE (callee) != BUILT_IN_STACK_SAVE
- || call_expr_nargs (GIMPLE_STMT_OPERAND (stack_save, 1)) != 0)
- return NULL_TREE;
+ || gimple_call_num_args (stack_save) != 0)
+ return false;
- stmt = stack_save;
- push_stmt_changes (&stmt);
- if (!set_rhs (&stmt,
- build_int_cst (TREE_TYPE (CALL_EXPR_ARG (call, 0)), 0)))
+ stack_save_gsi = gsi_for_stmt (stack_save);
+ push_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
+ rhs = build_int_cst (TREE_TYPE (gimple_call_arg (call, 0)), 0);
+ if (!update_call_from_tree (&stack_save_gsi, rhs))
{
- discard_stmt_changes (&stmt);
+ discard_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
return NULL_TREE;
}
- gcc_assert (stmt == stack_save);
- pop_stmt_changes (&stmt);
+ pop_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
+ /* No effect, so the statement will be deleted. */
return integer_zero_node;
}
-
+
/* If va_list type is a simple pointer and nothing special is needed,
optimize __builtin_va_start (&ap, 0) into ap = __builtin_next_arg (0),
__builtin_va_end (&ap) out as NOP and __builtin_va_copy into a simple
pointer assignment. */
static tree
-optimize_stdarg_builtin (tree call)
+optimize_stdarg_builtin (gimple call)
{
tree callee, lhs, rhs;
bool va_list_simple_ptr;
- if (TREE_CODE (call) != CALL_EXPR)
+ if (gimple_code (call) != GIMPLE_CALL)
return NULL_TREE;
va_list_simple_ptr = POINTER_TYPE_P (va_list_type_node)
&& (TREE_TYPE (va_list_type_node) == void_type_node
|| TREE_TYPE (va_list_type_node) == char_type_node);
- callee = get_callee_fndecl (call);
+ callee = gimple_call_fndecl (call);
switch (DECL_FUNCTION_CODE (callee))
{
case BUILT_IN_VA_START:
if (!va_list_simple_ptr
|| targetm.expand_builtin_va_start != NULL
- || built_in_decls[BUILT_IN_NEXT_ARG] == NULL)
+ || built_in_decls[BUILT_IN_NEXT_ARG] == NULL)
return NULL_TREE;
- if (call_expr_nargs (call) != 2)
+ if (gimple_call_num_args (call) != 2)
return NULL_TREE;
- lhs = CALL_EXPR_ARG (call, 0);
+ lhs = gimple_call_arg (call, 0);
if (!POINTER_TYPE_P (TREE_TYPE (lhs))
|| TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
!= TYPE_MAIN_VARIANT (va_list_type_node))
return NULL_TREE;
-
+
lhs = build_fold_indirect_ref (lhs);
rhs = build_call_expr (built_in_decls[BUILT_IN_NEXT_ARG],
- 1, integer_zero_node);
+ 1, integer_zero_node);
rhs = fold_convert (TREE_TYPE (lhs), rhs);
return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
@@ -3152,17 +3259,17 @@ optimize_stdarg_builtin (tree call)
if (!va_list_simple_ptr)
return NULL_TREE;
- if (call_expr_nargs (call) != 2)
+ if (gimple_call_num_args (call) != 2)
return NULL_TREE;
- lhs = CALL_EXPR_ARG (call, 0);
+ lhs = gimple_call_arg (call, 0);
if (!POINTER_TYPE_P (TREE_TYPE (lhs))
|| TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs)))
!= TYPE_MAIN_VARIANT (va_list_type_node))
return NULL_TREE;
lhs = build_fold_indirect_ref (lhs);
- rhs = CALL_EXPR_ARG (call, 1);
+ rhs = gimple_call_arg (call, 1);
if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs))
!= TYPE_MAIN_VARIANT (va_list_type_node))
return NULL_TREE;
@@ -3171,52 +3278,72 @@ optimize_stdarg_builtin (tree call)
return build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
case BUILT_IN_VA_END:
+ /* No effect, so the statement will be deleted. */
return integer_zero_node;
default:
gcc_unreachable ();
}
}
-
+
/* Convert EXPR into a GIMPLE value suitable for substitution on the
RHS of an assignment. Insert the necessary statements before
- iterator *SI_P.
- When IGNORE is set, don't worry about the return value. */
+ iterator *SI_P. The statement at *SI_P, which must be a GIMPLE_CALL
+ is replaced. If the call is expected to produces a result, then it
+ is replaced by an assignment of the new RHS to the result variable.
+ If the result is to be ignored, then the call is replaced by a
+ GIMPLE_NOP. */
-static tree
-convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr, bool ignore)
+static void
+gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{
- tree_stmt_iterator ti;
- tree stmt = bsi_stmt (*si_p);
- tree tmp, stmts = NULL;
+ tree lhs;
+ tree tmp = NULL_TREE; /* Silence warning. */
+ gimple stmt, new_stmt;
+ gimple_stmt_iterator i;
+ gimple_seq stmts = gimple_seq_alloc();
+
+ stmt = gsi_stmt (*si_p);
+
+ gcc_assert (gimple_code (stmt) == GIMPLE_CALL);
+
+ lhs = gimple_call_lhs (stmt);
push_gimplify_context ();
- if (ignore)
- {
- tmp = build_empty_stmt ();
- gimplify_and_add (expr, &stmts);
- }
- else
+
+ if (lhs == NULL_TREE)
+ gimplify_and_add (expr, &stmts);
+ else
tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+
pop_gimplify_context (NULL);
- if (EXPR_HAS_LOCATION (stmt))
- annotate_all_with_location (&stmts, EXPR_LOCATION (stmt));
+ if (gimple_has_location (stmt))
+ annotate_all_with_location (stmts, gimple_location (stmt));
/* The replacement can expose previously unreferenced variables. */
- for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
+ for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
+ {
+ new_stmt = gsi_stmt (i);
+ find_new_referenced_vars (&i);
+ gsi_insert_before (si_p, new_stmt, GSI_NEW_STMT);
+ mark_symbols_for_renaming (new_stmt);
+ gsi_next (si_p);
+ }
+
+ if (lhs == NULL_TREE)
+ new_stmt = gimple_build_nop ();
+ else
{
- tree new_stmt = tsi_stmt (ti);
- find_new_referenced_vars (tsi_stmt_ptr (ti));
- bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
- mark_symbols_for_renaming (new_stmt);
- bsi_next (si_p);
+ new_stmt = gimple_build_assign (lhs, tmp);
+ copy_virtual_operands (new_stmt, stmt);
+ move_ssa_defining_stmt_for_defs (new_stmt, stmt);
}
- return tmp;
+ gimple_set_location (new_stmt, gimple_location (stmt));
+ gsi_replace (si_p, new_stmt, false);
}
-
/* A simple pass that attempts to fold all builtin functions. This pass
is run after we've propagated as many constants as we can. */
@@ -3229,29 +3356,29 @@ execute_fold_all_builtins (void)
FOR_EACH_BB (bb)
{
- block_stmt_iterator i;
- for (i = bsi_start (bb); !bsi_end_p (i); )
+ gimple_stmt_iterator i;
+ for (i = gsi_start_bb (bb); !gsi_end_p (i); )
{
- tree *stmtp = bsi_stmt_ptr (i);
- tree old_stmt = *stmtp;
- tree call = get_rhs (*stmtp);
+ gimple stmt, old_stmt;
tree callee, result;
enum built_in_function fcode;
- if (!call || TREE_CODE (call) != CALL_EXPR)
+ stmt = gsi_stmt (i);
+
+ if (gimple_code (stmt) != GIMPLE_CALL)
{
- bsi_next (&i);
+ gsi_next (&i);
continue;
}
- callee = get_callee_fndecl (call);
+ callee = gimple_call_fndecl (stmt);
if (!callee || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL)
{
- bsi_next (&i);
+ gsi_next (&i);
continue;
}
fcode = DECL_FUNCTION_CODE (callee);
- result = ccp_fold_builtin (*stmtp, call);
+ result = ccp_fold_builtin (stmt);
if (!result)
switch (DECL_FUNCTION_CODE (callee))
{
@@ -3259,77 +3386,71 @@ execute_fold_all_builtins (void)
/* Resolve __builtin_constant_p. If it hasn't been
folded to integer_one_node by now, it's fairly
certain that the value simply isn't constant. */
- result = integer_zero_node;
+ result = integer_zero_node;
break;
case BUILT_IN_STACK_RESTORE:
- result = optimize_stack_restore (bb, *stmtp, i);
+ result = optimize_stack_restore (i);
if (result)
break;
- bsi_next (&i);
+ gsi_next (&i);
continue;
case BUILT_IN_VA_START:
case BUILT_IN_VA_END:
case BUILT_IN_VA_COPY:
/* These shouldn't be folded before pass_stdarg. */
- result = optimize_stdarg_builtin (*stmtp);
+ result = optimize_stdarg_builtin (stmt);
if (result)
break;
/* FALLTHRU */
default:
- bsi_next (&i);
+ gsi_next (&i);
continue;
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Simplified\n ");
- print_generic_stmt (dump_file, *stmtp, dump_flags);
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
}
- push_stmt_changes (stmtp);
+ old_stmt = stmt;
+ push_stmt_changes (gsi_stmt_ptr (&i));
- if (!set_rhs (stmtp, result))
- {
- result = convert_to_gimple_builtin (&i, result,
- TREE_CODE (old_stmt)
- != GIMPLE_MODIFY_STMT);
- if (result)
- {
- bool ok = set_rhs (stmtp, result);
- gcc_assert (ok);
- todoflags |= TODO_rebuild_alias;
- }
- }
+ if (!update_call_from_tree (&i, result))
+ {
+ gimplify_and_update_call_from_tree (&i, result);
+ todoflags |= TODO_rebuild_alias;
+ }
- pop_stmt_changes (stmtp);
+ stmt = gsi_stmt (i);
+ pop_stmt_changes (gsi_stmt_ptr (&i));
- if (maybe_clean_or_replace_eh_stmt (old_stmt, *stmtp)
- && tree_purge_dead_eh_edges (bb))
+ if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt)
+ && gimple_purge_dead_eh_edges (bb))
cfg_changed = true;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "to\n ");
- print_generic_stmt (dump_file, *stmtp, dump_flags);
+ print_gimple_stmt (dump_file, stmt, 0, dump_flags);
fprintf (dump_file, "\n");
}
/* Retry the same statement if it changed into another
builtin, there might be new opportunities now. */
- call = get_rhs (*stmtp);
- if (!call || TREE_CODE (call) != CALL_EXPR)
+ if (gimple_code (stmt) != GIMPLE_CALL)
{
- bsi_next (&i);
+ gsi_next (&i);
continue;
}
- callee = get_callee_fndecl (call);
+ callee = gimple_call_fndecl (stmt);
if (!callee
- || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
+ || DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
|| DECL_FUNCTION_CODE (callee) == fcode)
- bsi_next (&i);
+ gsi_next (&i);
}
}
@@ -3359,4 +3480,3 @@ struct tree_opt_pass pass_fold_builtins
| TODO_update_ssa, /* todo_flags_finish */
0 /* letter */
};
-#endif
Index: gcc/tree-ssa-propagate.c
===================================================================
--- gcc/tree-ssa-propagate.c (revision 133160)
+++ gcc/tree-ssa-propagate.c (working copy)
@@ -1183,6 +1183,7 @@ substitute_and_fold (prop_value_t *prop_
if (use_ranges_p)
did_replace = fold_predicate_in (stmt);
+ /* NOTE: The boolean variable REPLACED_ADDRESS is never used. */
if (prop_value)
{
/* Only replace real uses if we couldn't fold the
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c (revision 133160)
+++ gcc/gimple-iterator.c (working copy)
@@ -29,6 +29,31 @@ Boston, MA 02110-1301, USA. */
#include "value-prof.h"
+/* Mark the statement STMT as modified, and update it. */
+
+static inline void
+update_modified_stmt (gimple stmt)
+{
+ if (!ssa_operands_active ())
+ return;
+ update_stmt_if_modified (stmt);
+}
+
+
+/* Mark the statements in SEQ as modified, and update them. */
+
+static void
+update_modified_stmts (gimple_seq seq)
+{
+ gimple_stmt_iterator gsi;
+
+ if (!ssa_operands_active ())
+ return;
+ for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
+ update_stmt_if_modified (gsi_stmt (gsi));
+}
+
+
/* Set BB to be the basic block for all the statements in the list
starting at FIRST and LAST. */
@@ -108,11 +133,16 @@ gsi_insert_seq_nodes_before (gimple_stmt
/* Inserts the sequence of statements SEQ before the statement pointed
by iterator I. MODE indicates what to do with the iterator after
- insertion (see enum gsi_iterator_update). */
+ insertion (see enum gsi_iterator_update).
+
+ This function does not scan for new operands. It is provided for
+ the use of the gimplifier, which manipulates statements for which
+ def/use information has not yet been constructed. Most callers
+ should use gsi_insert_seq_before. */
void
-gsi_insert_seq_before (gimple_stmt_iterator *i, gimple_seq seq,
- enum gsi_iterator_update mode)
+gsi_insert_seq_before_without_update (gimple_stmt_iterator *i, gimple_seq seq,
+ enum gsi_iterator_update mode)
{
gimple_seq_node first, last;
@@ -137,6 +167,20 @@ gsi_insert_seq_before (gimple_stmt_itera
}
+/* Inserts the sequence of statements SEQ before the statement pointed
+ by iterator I. MODE indicates what to do with the iterator after
+ insertion (see enum gsi_iterator_update). Scan the statements in SEQ
+ for new operands. */
+
+void
+gsi_insert_seq_before (gimple_stmt_iterator *i, gimple_seq seq,
+ enum gsi_iterator_update mode)
+{
+ update_modified_stmts (seq);
+ gsi_insert_seq_before_without_update (i, seq, mode);
+}
+
+
/* Insert the sequence delimited by nodes FIRST and LAST after
iterator I. M specifies how to update iterator I after insertion
(see enum gsi_iterator_update).
@@ -197,11 +241,16 @@ gsi_insert_seq_nodes_after (gimple_stmt_
/* Links sequence SEQ after the statement pointed-to by iterator I.
- MODE is as in gsi_insert_after. */
+ MODE is as in gsi_insert_after.
+
+ This function does not scan for new operands. It is provided for
+ the use of the gimplifier, which manipulates statements for which
+ def/use information has not yet been constructed. Most callers
+ should use gsi_insert_seq_after. */
void
-gsi_insert_seq_after (gimple_stmt_iterator *i, gimple_seq seq,
- enum gsi_iterator_update mode)
+gsi_insert_seq_after_without_update (gimple_stmt_iterator *i, gimple_seq seq,
+ enum gsi_iterator_update mode)
{
gimple_seq_node first, last;
@@ -226,6 +275,19 @@ gsi_insert_seq_after (gimple_stmt_iterat
}
+/* Links sequence SEQ after the statement pointed-to by iterator I.
+ MODE is as in gsi_insert_after. Scan the statements in SEQ
+ for new operands. */
+
+void
+gsi_insert_seq_after (gimple_stmt_iterator *i, gimple_seq seq,
+ enum gsi_iterator_update mode)
+{
+ update_modified_stmts (seq);
+ gsi_insert_seq_after_without_update (i, seq, mode);
+}
+
+
/* Move all statements in the sequence after I to a new sequence.
Return this new sequence. */
@@ -289,17 +351,6 @@ gsi_split_seq_before (gimple_stmt_iterat
}
-/* Mark the statement T as modified, and update it. */
-
-static inline void
-update_modified_stmt (gimple t)
-{
- if (!ssa_operands_active ())
- return;
- update_stmt_if_modified (t);
-}
-
-
/* Replace the statement pointed-to by GSI to STMT. If UPDATE_EH_INFO
is true, the exception handling information of the original
statement is moved to the new statement. */
@@ -337,18 +388,20 @@ gsi_replace (gimple_stmt_iterator *gsi,
}
-/* Insert statement STMT before the statement pointed-to by iterator
- I, update STMT's basic block and scan it for new operands. M
- specifies how to update iterator I after insertion (see enum
- gsi_iterator_update). */
+/* Insert statement STMT before the statement pointed-to by iterator I.
+ M specifies how to update iterator I after insertion (see enum
+ gsi_iterator_update).
+
+ This function does not scan for new operands. It is provided for
+ the use of the gimplifier, which manipulates statements for which
+ def/use information has not yet been constructed. Most callers
+ should use gsi_insert_before. */
void
-gsi_insert_before (gimple_stmt_iterator *i, gimple stmt,
- enum gsi_iterator_update m)
+gsi_insert_before_without_update (gimple_stmt_iterator *i, gimple stmt,
+ enum gsi_iterator_update m)
{
gimple_seq_node n;
-
- update_modified_stmt (stmt);
n = ggc_alloc (sizeof (*n));
n->prev = n->next = NULL;
@@ -356,19 +409,34 @@ gsi_insert_before (gimple_stmt_iterator
gsi_insert_seq_nodes_before (i, n, n, m);
}
-
-/* Insert statement STMT after the statement pointed-to by iterator I,
- update STMT's basic block and scan it for new operands. M
+/* Insert statement STMT before the statement pointed-to by iterator I.
+ Update STMT's basic block and scan it for new operands. M
specifies how to update iterator I after insertion (see enum
gsi_iterator_update). */
void
-gsi_insert_after (gimple_stmt_iterator *i, gimple stmt,
- enum gsi_iterator_update m)
+gsi_insert_before (gimple_stmt_iterator *i, gimple stmt,
+ enum gsi_iterator_update m)
{
- gimple_seq_node n;
-
update_modified_stmt (stmt);
+ gsi_insert_before_without_update (i, stmt, m);
+}
+
+
+/* Insert statement STMT after the statement pointed-to by iterator I.
+ M specifies how to update iterator I after insertion (see enum
+ gsi_iterator_update).
+
+ This function does not scan for new operands. It is provided for
+ the use of the gimplifier, which manipulates statements for which
+ def/use information has not yet been constructed. Most callers
+ should use gsi_insert_after. */
+
+void
+gsi_insert_after_without_update (gimple_stmt_iterator *i, gimple stmt,
+ enum gsi_iterator_update m)
+{
+ gimple_seq_node n;
n = ggc_alloc (sizeof (*n));
n->prev = n->next = NULL;
@@ -377,6 +445,20 @@ gsi_insert_after (gimple_stmt_iterator *
}
+/* Insert statement STMT after the statement pointed-to by iterator I.
+ Update STMT's basic block and scan it for new operands. M
+ specifies how to update iterator I after insertion (see enum
+ gsi_iterator_update). */
+
+void
+gsi_insert_after (gimple_stmt_iterator *i, gimple stmt,
+ enum gsi_iterator_update m)
+{
+ update_modified_stmt (stmt);
+ gsi_insert_after_without_update (i, stmt, m);
+}
+
+
/* Remove the current stmt from the sequence. The iterator is updated
to point to the next statement.
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c (revision 133160)
+++ gcc/gimplify.c (working copy)
@@ -160,6 +160,49 @@ gimple_tree_eq (const void *p1, const vo
return 1;
}
+/* Link gimple statement GS to the end of the sequence *SEQ_P. If
+ *SEQ_P is NULL, a new sequence is allocated. This function is
+ similar to gimple_seq_add_stmt, but does not scan the operands.
+ During gimplification, we need to manipulate statement sequences
+ before the def/use vectors have been constructed. */
+
+static void
+gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs)
+{
+ gimple_stmt_iterator si;
+
+ if (gs == NULL)
+ return;
+
+ if (*seq_p == NULL)
+ *seq_p = gimple_seq_alloc ();
+
+ si = gsi_last (*seq_p);
+
+ gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
+}
+
+/* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
+ NULL, a new sequence is allocated. This function is
+ similar to gimple_seq_add_seq, but does not scan the operands.
+ During gimplification, we need to manipulate statement sequences
+ before the def/use vectors have been constructed. */
+
+static void
+gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
+{
+ gimple_stmt_iterator si;
+
+ if (src == NULL)
+ return;
+
+ if (*dst_p == NULL)
+ *dst_p = gimple_seq_alloc ();
+
+ si = gsi_last (*dst_p);
+ gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
+}
+
/* Set up a context for the gimplifier. */
void
@@ -254,7 +297,7 @@ gimple_pop_condition (gimple_seq *pre_p)
gcc_assert (conds >= 0);
if (conds == 0)
{
- gimple_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
+ gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
gimple_seq_free (gimplify_ctxp->conditional_cleanups);
}
}
@@ -1148,19 +1191,19 @@ gimplify_bind_expr (tree *expr_p, gimple
build_stack_save_restore (&stack_save, &stack_restore);
cleanup = new_body = NULL;
- gimple_seq_add_stmt (&cleanup, stack_restore);
+ gimplify_seq_add_stmt (&cleanup, stack_restore);
gs = gimple_build_try (gimple_bind_body (gimple_bind), cleanup,
GIMPLE_TRY_FINALLY);
- gimple_seq_add_stmt (&new_body, stack_save);
- gimple_seq_add_stmt (&new_body, gs);
+ gimplify_seq_add_stmt (&new_body, stack_save);
+ gimplify_seq_add_stmt (&new_body, gs);
gimple_bind_set_body (gimple_bind, new_body);
}
gimplify_ctxp->save_stack = old_save_stack;
gimple_pop_bind_expr ();
- gimple_seq_add_stmt (pre_p, gimple_bind);
+ gimplify_seq_add_stmt (pre_p, gimple_bind);
if (temp)
{
@@ -1194,7 +1237,7 @@ gimplify_return_expr (tree stmt, gimple_
{
gimple ret = gimple_build_return (ret_expr);
gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
- gimple_seq_add_stmt (pre_p, ret);
+ gimplify_seq_add_stmt (pre_p, ret);
return GS_ALL_DONE;
}
@@ -1252,7 +1295,7 @@ gimplify_return_expr (tree stmt, gimple_
ret = gimple_build_return (result);
gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
- gimple_seq_add_stmt (pre_p, ret);
+ gimplify_seq_add_stmt (pre_p, ret);
return GS_ALL_DONE;
}
@@ -1355,16 +1398,16 @@ gimplify_loop_expr (tree *expr_p, gimple
tree saved_label = gimplify_ctxp->exit_label;
tree start_label = create_artificial_label ();
- gimple_seq_add_stmt (pre_p, gimple_build_label (start_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
gimplify_ctxp->exit_label = NULL_TREE;
gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
- gimple_seq_add_stmt (pre_p, gimple_build_goto (start_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
if (gimplify_ctxp->exit_label)
- gimple_seq_add_stmt (pre_p, gimple_build_label
(gimplify_ctxp->exit_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label
(gimplify_ctxp->exit_label));
gimplify_ctxp->exit_label = saved_label;
@@ -1499,7 +1542,7 @@ gimplify_switch_expr (tree *expr_p, gimp
default_case = build3 (CASE_LABEL_EXPR, void_type_node, NULL_TREE,
NULL_TREE, create_artificial_label ());
new_default = gimple_build_label (CASE_LABEL (default_case));
- gimple_seq_add_stmt (&switch_body_seq, new_default);
+ gimplify_seq_add_stmt (&switch_body_seq, new_default);
}
if (!VEC_empty (tree, labels))
@@ -1507,8 +1550,8 @@ gimplify_switch_expr (tree *expr_p, gimp
gimple_switch = gimple_build_switch_vec (SWITCH_COND (switch_expr),
default_case, labels);
- gimple_seq_add_stmt (pre_p, gimple_switch);
- gimple_seq_add_seq (pre_p, switch_body_seq);
+ gimplify_seq_add_stmt (pre_p, gimple_switch);
+ gimplify_seq_add_seq (pre_p, switch_body_seq);
VEC_free(tree, heap, labels);
}
else
@@ -1533,7 +1576,7 @@ gimplify_case_label_expr (tree *expr_p,
gimple_label = gimple_build_label (CASE_LABEL (*expr_p));
VEC_safe_push (tree, heap, ctxp->case_labels, *expr_p);
- gimple_seq_add_stmt (pre_p, gimple_label);
+ gimplify_seq_add_stmt (pre_p, gimple_label);
return GS_ALL_DONE;
}
@@ -2058,7 +2101,7 @@ gimplify_self_mod_expr (tree *expr_p, gi
if (postfix)
{
gimplify_and_add (t1, orig_post_p);
- gimple_seq_add_seq (orig_post_p, post);
+ gimplify_seq_add_seq (orig_post_p, post);
*expr_p = lhs;
return GS_ALL_DONE;
}
@@ -2339,7 +2382,7 @@ gimplify_call_expr (tree *expr_p, gimple
/* Now add the GIMPLE call to PRE_P. If WANT_VALUE is set, we need
to create the appropriate temporary for the call's LHS. */
call = gimple_build_call_vec (fndecl ? fndecl : CALL_EXPR_FN
(*expr_p), args);
- gimple_seq_add_stmt (pre_p, call);
+ gimplify_seq_add_stmt (pre_p, call);
if (want_value)
{
tree lhs = get_tmp_var_for (call);
@@ -2823,14 +2866,14 @@ gimplify_cond_expr (tree *expr_p, gimple
gimple_cond = gimple_build_cond (pred_code, arm1, arm2, label_true,
label_false);
- gimple_seq_add_stmt (pre_p, gimple_cond);
- gimple_seq_add_stmt (pre_p, gimple_build_label (label_true));
+ gimplify_seq_add_stmt (pre_p, gimple_cond);
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (label_true));
have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), pre_p);
label_cont = create_artificial_label ();
- gimple_seq_add_stmt (pre_p, gimple_build_goto (label_cont));
- gimple_seq_add_stmt (pre_p, gimple_build_label (label_false));
+ gimplify_seq_add_stmt (pre_p, gimple_build_goto (label_cont));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (label_false));
have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), pre_p);
- gimple_seq_add_stmt (pre_p, gimple_build_label (label_cont));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (label_cont));
gimple_pop_condition (pre_p);
@@ -2873,13 +2916,13 @@ gimplify_modify_expr_to_memcpy (tree *ex
/* tmp = memcpy() */
t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
gimple_call_set_lhs (gs, t);
- gimple_seq_add_stmt (seq_p, gs);
+ gimplify_seq_add_stmt (seq_p, gs);
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
return GS_ALL_DONE;
}
- gimple_seq_add_stmt (seq_p, gs);
+ gimplify_seq_add_stmt (seq_p, gs);
*expr_p = NULL;
return GS_ALL_DONE;
}
@@ -2907,13 +2950,13 @@ gimplify_modify_expr_to_memset (tree *ex
/* tmp = memset() */
t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
gimple_call_set_lhs (gs, t);
- gimple_seq_add_stmt (seq_p, gs);
+ gimplify_seq_add_stmt (seq_p, gs);
*expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
return GS_ALL_DONE;
}
- gimple_seq_add_stmt (seq_p, gs);
+ gimplify_seq_add_stmt (seq_p, gs);
*expr_p = NULL;
return GS_ALL_DONE;
}
@@ -3076,10 +3119,10 @@ gimplify_init_ctor_eval_range (tree obje
/* Create and initialize the index variable. */
var_type = TREE_TYPE (upper);
var = create_tmp_var (var_type, NULL);
- gimple_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
/* Add the loop entry label. */
- gimple_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
/* Build the reference. */
cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
@@ -3094,22 +3137,22 @@ gimplify_init_ctor_eval_range (tree obje
gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
pre_p, cleared);
else
- gimple_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
/* We exit the loop when the index var is equal to the upper bound. */
- gimple_seq_add_stmt (pre_p, gimple_build_cond (EQ_EXPR, var, upper,
+ gimplify_seq_add_stmt (pre_p, gimple_build_cond (EQ_EXPR, var, upper,
loop_exit_label, NULL_TREE));
/* Otherwise, increment the index var... */
tmp = build2 (PLUS_EXPR, var_type, var,
fold_convert (var_type, integer_one_node));
- gimple_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
/* ...and jump back to the loop entry. */
- gimple_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
/* Add the loop exit label. */
- gimple_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
+ gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
}
/* Return true if FDECL is accessing a field that is zero sized. */
@@ -3554,7 +3597,7 @@ gimplify_init_constructor (tree *expr_p,
tree lhs = TREE_OPERAND (*expr_p, 0);
tree rhs = TREE_OPERAND (*expr_p, 1);
gimple init = gimple_build_assign (lhs, rhs);
- gimple_seq_add_stmt (pre_p, init);
+ gimplify_seq_add_stmt (pre_p, init);
*expr_p = NULL;
}
@@ -3898,7 +3941,7 @@ gimplify_modify_expr_complex_part (tree
else
new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
- gimple_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
+ gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
*expr_p = (want_value) ? rhs : NULL_TREE;
return GS_ALL_DONE;
@@ -4015,7 +4058,7 @@ gimplify_modify_expr (tree *expr_p, gimp
}
assign = gimple_build_assign (unshare_expr (*to_p), unshare_expr (*from_p));
- gimple_seq_add_stmt (pre_p, assign);
+ gimplify_seq_add_stmt (pre_p, assign);
if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
{
@@ -4483,7 +4526,7 @@ gimplify_asm_expr (tree *expr_p, gimple_
if (TREE_THIS_VOLATILE (expr))
gimple_asm_set_volatile (stmt);
- gimple_seq_add_stmt (pre_p, stmt);
+ gimplify_seq_add_stmt (pre_p, stmt);
return ret;
}
@@ -4529,8 +4572,11 @@ gimplify_cleanup_point_expr (tree *expr_
{
if (gsi_one_before_end_p (iter))
{
- gsi_insert_seq_before (&iter, gimple_wce_cleanup (wce),
- GSI_SAME_STMT);
+ /* Note that gsi_insert_seq_before and gsi_remove do not
+ scan operands, unlike some other sequence mutators. */
+ gsi_insert_seq_before_without_update (&iter,
+ gimple_wce_cleanup (wce),
+ GSI_SAME_STMT);
gsi_remove (&iter, true);
break;
}
@@ -4544,12 +4590,12 @@ gimplify_cleanup_point_expr (tree *expr_
kind = GIMPLE_TRY_CATCH;
else
kind = GIMPLE_TRY_FINALLY;
-
seq = gsi_split_seq_after (iter);
try = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
-
- gsi_replace (&iter, try, GSI_SAME_STMT);
+ /* Do not use gsi_replace here, as it may scan operands.
+ We want to do a simple structural modification only. */
+ *gsi_stmt_ptr (&iter) = try;
iter = gsi_start (seq);
}
}
@@ -4557,7 +4603,7 @@ gimplify_cleanup_point_expr (tree *expr_
gsi_next (&iter);
}
- gimple_seq_add_seq (pre_p, body_sequence);
+ gimplify_seq_add_seq (pre_p, body_sequence);
if (temp)
{
*expr_p = temp;
@@ -4615,9 +4661,9 @@ gimple_push_cleanup (tree var, tree clea
gimplify_stmt (&cleanup, &cleanup_stmts);
wce = gimple_build_wce (cleanup_stmts);
- gimple_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
- gimple_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
- gimple_seq_add_stmt (pre_p, ftrue);
+ gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
+ gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
+ gimplify_seq_add_stmt (pre_p, ftrue);
/* Because of this manipulation, and the EH edges that jump
threading cannot redirect, the temporary (VAR) will appear
@@ -4629,7 +4675,7 @@ gimple_push_cleanup (tree var, tree clea
gimplify_stmt (&cleanup, &cleanup_stmts);
wce = gimple_build_wce (cleanup_stmts);
gimple_wce_set_cleanup_eh_only (wce, eh_only);
- gimple_seq_add_stmt (pre_p, wce);
+ gimplify_seq_add_stmt (pre_p, wce);
}
}
@@ -5354,7 +5400,7 @@ gimplify_omp_parallel (tree *expr_p, gim
OMP_PARALLEL_DATA_ARG (expr));
if (OMP_PARALLEL_COMBINED (expr))
gimple_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
- gimple_seq_add_stmt (pre_p, g);
+ gimplify_seq_add_stmt (pre_p, g);
*expr_p = NULL_TREE;
}
@@ -5477,12 +5523,12 @@ gimplify_omp_for (tree *expr_p, gimple_s
for_body = gimple_seq_alloc ();
if (init_decl)
- gimple_seq_add_stmt (&for_body, init_decl);
+ gimplify_seq_add_stmt (&for_body, init_decl);
gimplify_and_add (OMP_FOR_BODY (for_stmt), &for_body);
gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
- gimple_seq_add_stmt
+ gimplify_seq_add_stmt
(pre_p, gimple_build_omp_for (for_body, OMP_FOR_CLAUSES (for_stmt),
for_index, for_initial, for_final, for_incr,
for_pre_body, for_predicate));
@@ -5618,11 +5664,11 @@ gimplify_omp_atomic (tree *expr_p, gimpl
!= GS_ALL_DONE)
return GS_ERROR;
- gimple_seq_add_stmt (pre_p, gimple_build_omp_atomic_load (tmp_load, addr));
+ gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_load
(tmp_load, addr));
if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
!= GS_ALL_DONE)
return GS_ERROR;
- gimple_seq_add_stmt (pre_p, gimple_build_omp_atomic_store (rhs));
+ gimplify_seq_add_stmt (pre_p, gimple_build_omp_atomic_store (rhs));
*expr_p = NULL;
return GS_ALL_DONE;
@@ -5981,7 +6027,7 @@ gimplify_expr (tree *expr_p, gimple_seq
if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
NULL, is_gimple_val, fb_rvalue);
- gimple_seq_add_stmt (pre_p,
+ gimplify_seq_add_stmt (pre_p,
gimple_build_goto (GOTO_DESTINATION (*expr_p)));
break;
@@ -5989,7 +6035,7 @@ gimplify_expr (tree *expr_p, gimple_seq
ret = GS_ALL_DONE;
gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
== current_function_decl);
- gimple_seq_add_stmt (pre_p,
+ gimplify_seq_add_stmt (pre_p,
gimple_build_label (LABEL_EXPR_LABEL (*expr_p)));
break;
@@ -6079,7 +6125,7 @@ gimplify_expr (tree *expr_p, gimple_seq
TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
? GIMPLE_TRY_FINALLY
: GIMPLE_TRY_CATCH);
- gimple_seq_add_stmt (pre_p, try_);
+ gimplify_seq_add_stmt (pre_p, try_);
ret = GS_ALL_DONE;
break;
}
@@ -6098,7 +6144,7 @@ gimplify_expr (tree *expr_p, gimple_seq
gimple_seq handler = NULL;
gimplify_and_add (CATCH_BODY (*expr_p), &handler);
c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
- gimple_seq_add_stmt (pre_p, c);
+ gimplify_seq_add_stmt (pre_p, c);
ret = GS_ALL_DONE;
break;
}
@@ -6112,7 +6158,7 @@ gimplify_expr (tree *expr_p, gimple_seq
ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
gimple_eh_filter_set_must_not_throw
(ehf, EH_FILTER_MUST_NOT_THROW (*expr_p));
- gimple_seq_add_stmt (pre_p, ehf);
+ gimplify_seq_add_stmt (pre_p, ehf);
ret = GS_ALL_DONE;
break;
}
@@ -6125,7 +6171,7 @@ gimplify_expr (tree *expr_p, gimple_seq
pre_p, post_p, is_gimple_reg, fb_lvalue);
cdt = gimple_build_cdt (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*expr_p),
CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p));
- gimple_seq_add_stmt (pre_p, cdt);
+ gimplify_seq_add_stmt (pre_p, cdt);
ret = GS_ALL_DONE;
}
break;
@@ -6222,7 +6268,7 @@ gimplify_expr (tree *expr_p, gimple_seq
default:
gcc_unreachable ();
}
- gimple_seq_add_stmt (pre_p, g);
+ gimplify_seq_add_stmt (pre_p, g);
ret = GS_ALL_DONE;
break;
}
@@ -6433,8 +6479,8 @@ gimplify_expr (tree *expr_p, gimple_seq
if (!gimple_seq_empty_p (internal_pre)
|| !gimple_seq_empty_p (internal_post))
{
- gimple_seq_add_seq (&internal_pre, internal_post);
- gimple_seq_add_seq (pre_p, internal_pre);
+ gimplify_seq_add_seq (&internal_pre, internal_post);
+ gimplify_seq_add_seq (pre_p, internal_pre);
}
if (!gimple_seq_empty_p (*pre_p))
@@ -6546,7 +6592,7 @@ gimplify_expr (tree *expr_p, gimple_seq
if (!gimple_seq_empty_p (internal_post))
{
annotate_all_with_location (internal_post, input_location);
- gimple_seq_add_seq (pre_p, internal_post);
+ gimplify_seq_add_seq (pre_p, internal_post);
}
out:
@@ -6727,7 +6773,7 @@ gimplify_body (tree *body_p, tree fndecl
if (!outer_bind)
{
outer_bind = gimple_build_nop ();
- gimple_seq_add_stmt (&seq, outer_bind);
+ gimplify_seq_add_stmt (&seq, outer_bind);
}
/* The body must contain exactly one statement, a GIMPLE_BIND. If this is
@@ -6744,7 +6790,7 @@ gimplify_body (tree *body_p, tree fndecl
of the function. */
if (!gimple_seq_empty_p (parm_stmts))
{
- gimple_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
+ gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
gimple_bind_set_body (outer_bind, parm_stmts);
}
@@ -6816,19 +6862,19 @@ gimplify_function_tree (tree fndecl)
gimple_seq cleanup = NULL, body = NULL;
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_EXIT];
- gimple_seq_add_stmt (&cleanup, gimple_build_call (x, 0));
+ gimplify_seq_add_stmt (&cleanup, gimple_build_call (x, 0));
tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
x = implicit_built_in_decls[BUILT_IN_PROFILE_FUNC_ENTER];
- gimple_seq_add_stmt (&body, gimple_build_call (x, 0));
- gimple_seq_add_stmt (&body, tf);
+ gimplify_seq_add_stmt (&body, gimple_build_call (x, 0));
+ gimplify_seq_add_stmt (&body, tf);
bind = gimple_build_bind (NULL, body);
}
/* The tree body of the function is no longer needed, replace it
with the new GIMPLE body. */
seq = gimple_seq_alloc ();
- gimple_seq_add_stmt (&seq, bind);
+ gimplify_seq_add_stmt (&seq, bind);
gimple_set_body (fndecl, seq);
DECL_SAVED_TREE (fndecl) = NULL_TREE;
Index: gcc/tree-dfa.c
===================================================================
--- gcc/tree-dfa.c (revision 133160)
+++ gcc/tree-dfa.c (working copy)
@@ -797,9 +797,11 @@ find_new_referenced_vars_1 (tree *tp, in
}
void
-find_new_referenced_vars (tree *stmt_p)
+find_new_referenced_vars (gimple_stmt_iterator *gsi)
{
- walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
+ /* Invoke callback on each operand, in both the statement
+ referenced by GSI and in any embedded statements. */
+ walk_gimple_stmt (gsi, NULL, find_new_referenced_vars_1, NULL);
}
@@ -987,4 +989,3 @@ stmt_references_abnormal_ssa_name (gimpl
return false;
}
-
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h (revision 133160)
+++ gcc/tree-flow.h (working copy)
@@ -775,7 +775,7 @@ extern tree get_virtual_var (tree);
extern void add_referenced_var (tree);
extern void remove_referenced_var (tree);
extern void mark_symbols_for_renaming (gimple);
-extern void find_new_referenced_vars (tree *);
+extern void find_new_referenced_vars (gimple_stmt_iterator *);
extern tree make_rename_temp (tree, const char *);
extern void set_default_def (tree, tree);
extern tree gimple_default_def (struct function *, tree);
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h (revision 133160)
+++ gcc/gimple.h (working copy)
@@ -2722,6 +2722,8 @@ gimple_return_set_retval (gimple gs, tre
{
GIMPLE_CHECK (gs, GIMPLE_RETURN);
gcc_assert (gs->with_ops.num_ops == 1);
+ /* FIXME tuples. The check in gimple_build_return
+ is more restrictive. Which one is correct? */
gcc_assert (is_gimple_operand (retval));
gimple_set_op (gs, 0, retval);
}
@@ -3013,12 +3015,20 @@ gimple_seq gsi_split_seq_before (gimple_
void gsi_replace (gimple_stmt_iterator *, gimple, bool);
void gsi_insert_before (gimple_stmt_iterator *, gimple,
enum gsi_iterator_update);
+void gsi_insert_before_without_update (gimple_stmt_iterator *, gimple,
+ enum gsi_iterator_update);
void gsi_insert_seq_before (gimple_stmt_iterator *, gimple_seq,
- enum gsi_iterator_update);
+ enum gsi_iterator_update);
+void gsi_insert_seq_before_without_update (gimple_stmt_iterator *, gimple_seq,
+ enum gsi_iterator_update);
void gsi_insert_after (gimple_stmt_iterator *, gimple,
enum gsi_iterator_update);
+void gsi_insert_after_without_update (gimple_stmt_iterator *, gimple,
+ enum gsi_iterator_update);
void gsi_insert_seq_after (gimple_stmt_iterator *, gimple_seq,
enum gsi_iterator_update);
+void gsi_insert_seq_after_without_update (gimple_stmt_iterator *, gimple_seq,
+ enum gsi_iterator_update);
void gsi_remove (gimple_stmt_iterator *, bool);
gimple_stmt_iterator gsi_for_stmt (gimple);
void gsi_move_after (gimple_stmt_iterator *, gimple_stmt_iterator *);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c (revision 133160)
+++ gcc/passes.c (working copy)
@@ -652,7 +652,10 @@ init_optimization_passes (void)
/* FIXME tuples. */
#if 0
NEXT_PASS (pass_copy_prop);
+#endif
NEXT_PASS (pass_fold_builtins);
+ /* FIXME tuples. */
+#if 0
NEXT_PASS (pass_cse_sincos);
NEXT_PASS (pass_split_crit_edges);
NEXT_PASS (pass_pre);