Commit ba4d8f9d by Richard Guenther Committed by Richard Biener

re PR middle-end/23401 (Gimplifier produces too many temporaries)

2009-03-31  Richard Guenther  <rguenther@suse.de>

	PR middle-end/23401
	PR middle-end/27810
	* tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove.
	(struct tree_decl_with_vis): Remove gimple_formal_temp member.
	* tree-eh.c (lower_eh_constructs_2): Move LHS assignment to
	a separate statement.
	* gimplify.c (pop_gimplify_context): Remove formal temp handling.
	(lookup_tmp_var): Likewise.
	(is_gimple_formal_tmp_or_call_rhs): Remove.
	(is_gimple_reg_or_call_rhs): Rename to ...
	(is_gimple_reg_rhs_or_call): ... this.
	(is_gimple_mem_or_call_rhs): Rename to ...
	(is_gimple_mem_rhs_or_call): ... this.
	(internal_get_tmp_var): Use is_gimple_reg_rhs_or_call.  Set
	DECL_GIMPLE_REG_P only if is_formal is true.
	(gimplify_compound_lval): Use is_gimple_reg.  Remove workaround
	for non-proper post-modify expression gimplification.
	(gimplify_self_mod_expr): For post-modify expressions gimplify
	the lvalue to a minimal lvalue.
	(rhs_predicate_for): Remove formal temp case.
	(gimplify_modify_expr_rhs): Likewise.
	(gimplify_addr_expr): Use is_gimple_reg.
	(gimplify_expr): Remove formal temp cases.
	(gimple_regimplify_operands): Likewise.
	* tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR
	and FILTER_EXPR like constants.
	* gimple.c (walk_gimple_op): Fix val_only initialization, use
	is_gimple_reg.
	(is_gimple_formal_tmp_rhs): Remove.
	(is_gimple_reg_rhs): Remove special casing.
	(is_gimple_mem_rhs): Fix.
	(is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier.
	(is_gimple_formal_tmp_var): Remove.
	(is_gimple_formal_tmp_reg): Likewise.
	(is_gimple_min_lval): Allow invariant component ref parts.
	* gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var,
	is_gimple_formal_tmp_reg): Remove declarations.
	* tree-cfg.c (verify_expr): Verify that variables with address
	taken do not have DECL_GIMPLE_REG_P set.
	* tree-mudflap.c (mf_build_check_statement_for): Use
	force_gimple_operand instead of gimplify_expr.

	java/
	* java-gimplify.c (java_gimplify_expr): Do not manually gimplify
	the first operand of binary and comaprison expressions.

	* gcc.dg/tree-ssa/pr23401.c: New testcase.
	* gcc.dg/tree-ssa/pr27810.c: Likewise.

From-SVN: r145338
parent 8de9b877
2009-03-31 Richard Guenther <rguenther@suse.de>
PR middle-end/23401
PR middle-end/27810
* tree.h (DECL_GIMPLE_FORMAL_TEMP_P): Remove.
(struct tree_decl_with_vis): Remove gimple_formal_temp member.
* tree-eh.c (lower_eh_constructs_2): Move LHS assignment to
a separate statement.
* gimplify.c (pop_gimplify_context): Remove formal temp handling.
(lookup_tmp_var): Likewise.
(is_gimple_formal_tmp_or_call_rhs): Remove.
(is_gimple_reg_or_call_rhs): Rename to ...
(is_gimple_reg_rhs_or_call): ... this.
(is_gimple_mem_or_call_rhs): Rename to ...
(is_gimple_mem_rhs_or_call): ... this.
(internal_get_tmp_var): Use is_gimple_reg_rhs_or_call. Set
DECL_GIMPLE_REG_P only if is_formal is true.
(gimplify_compound_lval): Use is_gimple_reg. Remove workaround
for non-proper post-modify expression gimplification.
(gimplify_self_mod_expr): For post-modify expressions gimplify
the lvalue to a minimal lvalue.
(rhs_predicate_for): Remove formal temp case.
(gimplify_modify_expr_rhs): Likewise.
(gimplify_addr_expr): Use is_gimple_reg.
(gimplify_expr): Remove formal temp cases.
(gimple_regimplify_operands): Likewise.
* tree-ssa-pre.c (get_or_alloc_expr_for): Treat EXC_PTR_EXPR
and FILTER_EXPR like constants.
* gimple.c (walk_gimple_op): Fix val_only initialization, use
is_gimple_reg.
(is_gimple_formal_tmp_rhs): Remove.
(is_gimple_reg_rhs): Remove special casing.
(is_gimple_mem_rhs): Fix.
(is_gimple_reg): Move DECL_GIMPLE_REG_P handling earlier.
(is_gimple_formal_tmp_var): Remove.
(is_gimple_formal_tmp_reg): Likewise.
(is_gimple_min_lval): Allow invariant component ref parts.
* gimple.h (is_gimple_formal_tmp_rhs, is_gimple_formal_tmp_var,
is_gimple_formal_tmp_reg): Remove declarations.
* tree-cfg.c (verify_expr): Verify that variables with address
taken do not have DECL_GIMPLE_REG_P set.
* tree-mudflap.c (mf_build_check_statement_for): Use
force_gimple_operand instead of gimplify_expr.
2009-03-31 Ayal Zaks <zaks@il.ibm.com>
* modulo-sched.c (sms_schedule_by_order): Pass the actual
......
......@@ -1380,7 +1380,8 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
/* Walk the RHS operands. A formal temporary LHS may use a
COMPONENT_REF RHS. */
if (wi)
wi->val_only = !is_gimple_formal_tmp_var (gimple_assign_lhs (stmt));
wi->val_only = !is_gimple_reg (gimple_assign_lhs (stmt))
|| !gimple_assign_single_p (stmt);
for (i = 1; i < gimple_num_ops (stmt); i++)
{
......@@ -2559,37 +2560,13 @@ is_gimple_operand (const_tree op)
return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS;
}
/* Return true if T is a GIMPLE RHS for an assignment to a temporary. */
bool
is_gimple_formal_tmp_rhs (tree t)
{
if (is_gimple_lvalue (t) || is_gimple_val (t))
return true;
return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
}
/* Returns true iff T is a valid RHS for an assignment to a renamed
user -- or front-end generated artificial -- variable. */
bool
is_gimple_reg_rhs (tree t)
{
/* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
and the LHS is a user variable, then we need to introduce a formal
temporary. This way the optimizers can determine that the user
variable is only modified if evaluation of the RHS does not throw.
Don't force a temp of a non-renamable type; the copy could be
arbitrarily expensive. Instead we will generate a VDEF for
the assignment. */
if (is_gimple_reg_type (TREE_TYPE (t)) && tree_could_throw_p (t))
return false;
return is_gimple_formal_tmp_rhs (t);
return get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS;
}
/* Returns true iff T is a valid RHS for an assignment to an un-renamed
......@@ -2603,7 +2580,7 @@ is_gimple_mem_rhs (tree t)
if (is_gimple_reg_type (TREE_TYPE (t)))
return is_gimple_val (t);
else
return is_gimple_formal_tmp_rhs (t);
return is_gimple_val (t) || is_gimple_lvalue (t);
}
/* Return true if T is a valid LHS for a GIMPLE assignment expression. */
......@@ -2895,6 +2872,12 @@ is_gimple_reg (tree t)
if (!is_gimple_variable (t))
return false;
/* Complex and vector values must have been put into SSA-like form.
That is, no assignments to the individual components. */
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
return DECL_GIMPLE_REG_P (t);
if (!is_gimple_reg_type (TREE_TYPE (t)))
return false;
......@@ -2921,45 +2904,10 @@ is_gimple_reg (tree t)
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
return false;
/* Complex and vector values must have been put into SSA-like form.
That is, no assignments to the individual components. */
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|| TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
return DECL_GIMPLE_REG_P (t);
return true;
}
/* Returns true if T is a GIMPLE formal temporary variable. */
bool
is_gimple_formal_tmp_var (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
return true;
return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
}
/* Returns true if T is a GIMPLE formal temporary register variable. */
bool
is_gimple_formal_tmp_reg (tree t)
{
/* The intent of this is to get hold of a value that won't change.
An SSA_NAME qualifies no matter if its of a user variable or not. */
if (TREE_CODE (t) == SSA_NAME)
return true;
/* We don't know the lifetime characteristics of user variables. */
if (!is_gimple_formal_tmp_var (t))
return false;
/* Finally, it must be capable of being placed in a register. */
return is_gimple_reg (t);
}
/* Return true if T is a GIMPLE variable whose address is not needed. */
bool
......@@ -3006,6 +2954,8 @@ is_gimple_asm_val (tree t)
bool
is_gimple_min_lval (tree t)
{
if (!(t = CONST_CAST_TREE (strip_invariant_refs (t))))
return false;
return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF);
}
......
......@@ -859,10 +859,6 @@ extern bool is_gimple_stmt (tree);
extern bool is_gimple_reg_type (tree);
/* Returns true iff T is a scalar register variable. */
extern bool is_gimple_reg (tree);
/* Returns true if T is a GIMPLE temporary variable, false otherwise. */
extern bool is_gimple_formal_tmp_var (tree);
/* Returns true if T is a GIMPLE temporary register variable. */
extern bool is_gimple_formal_tmp_reg (tree);
/* Returns true iff T is any sort of variable. */
extern bool is_gimple_variable (tree);
/* Returns true iff T is any sort of symbol. */
......@@ -894,7 +890,6 @@ extern bool is_gimple_asm_val (tree);
/* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a
GIMPLE temporary, a renamed user variable, or something else,
respectively. */
extern bool is_gimple_formal_tmp_rhs (tree);
extern bool is_gimple_reg_rhs (tree);
extern bool is_gimple_mem_rhs (tree);
......
2009-03-31 Richard Guenther <rguenther@suse.de>
* java-gimplify.c (java_gimplify_expr): Do not manually gimplify
the first operand of binary and comaprison expressions.
2009-03-30 Joseph Myers <joseph@codesourcery.com>
PR rtl-optimization/323
......
......@@ -96,26 +96,6 @@ java_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gcc_unreachable ();
default:
/* Java insists on strict left-to-right evaluation of expressions.
A problem may arise if a variable used in the LHS of a binary
operation is altered by an assignment to that value in the RHS
before we've performed the operation. So, we always copy every
LHS to a temporary variable.
FIXME: Are there any other cases where we should do this?
Parameter lists, maybe? Or perhaps that's unnecessary because
the front end already generates SAVE_EXPRs. */
if (TREE_CODE_CLASS (code) == tcc_binary
|| TREE_CODE_CLASS (code) == tcc_comparison)
{
enum gimplify_status stat
= gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_formal_tmp_var, fb_rvalue);
if (stat == GS_ERROR)
return stat;
}
return GS_UNHANDLED;
}
......
2009-03-31 Richard Guenther <rguenther@suse.de>
PR middle-end/23401
PR middle-end/27810
* gcc.dg/tree-ssa/pr23401.c: New testcase.
* gcc.dg/tree-ssa/pr27810.c: Likewise.
2009-03-30 Steven G. Kargl <kargls@comcast.net>
PR fortran/38389
......
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
struct f
{
struct {
int i;
} ff[10];
};
struct f g;
int ffff(int i)
{
int t1 = 0;
int i1 = g.ff[t1].i;
int i2 = g.ff[i].i;
return i1 + i2;
}
/* We should not use extra temporaries apart from for i1 + i2. */
/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
/* { dg-do compile } */
/* { dg-options "-fdump-tree-gimple" } */
int bar (int);
int qqq (int a)
{
int result;
result = bar (a);
return result;
}
/* We should not use an extra temporary for the result of the
function call. */
/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */
/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */
/* { dg-final { cleanup-tree-dump "gimple" } } */
......@@ -2886,6 +2886,11 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
error ("address taken, but ADDRESSABLE bit not set");
return x;
}
if (DECL_GIMPLE_REG_P (x))
{
error ("DECL_GIMPLE_REG_P set on a variable with address taken");
return x;
}
break;
}
......
......@@ -1823,6 +1823,25 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
{
case GIMPLE_CALL:
case GIMPLE_ASSIGN:
/* If the stmt can throw use a new temporary for the assignment
to a LHS. This makes sure the old value of the LHS is
available on the EH edge. */
if (stmt_could_throw_p (stmt)
&& gimple_has_lhs (stmt)
&& !tree_could_throw_p (gimple_get_lhs (stmt))
&& is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))))
{
tree lhs = gimple_get_lhs (stmt);
tree tmp = create_tmp_var (TREE_TYPE (lhs), NULL);
gimple s = gimple_build_assign (lhs, tmp);
gimple_set_location (s, gimple_location (stmt));
gimple_set_block (s, gimple_block (stmt));
gimple_set_lhs (stmt, tmp);
if (TREE_CODE (TREE_TYPE (tmp)) == COMPLEX_TYPE
|| TREE_CODE (TREE_TYPE (tmp)) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (tmp) = 1;
gsi_insert_after (gsi, s, GSI_SAME_STMT);
}
/* Look for things that can throw exceptions, and record them. */
if (state->cur_region && stmt_could_throw_p (stmt))
{
......
......@@ -503,7 +503,7 @@ mf_build_check_statement_for (tree base, tree limit,
tree mf_elem;
tree mf_limit;
gimple g;
gimple_seq seq;
gimple_seq seq, stmts;
/* We first need to split the current basic block, and start altering
the CFG. This allows us to insert the statements we're about to
......@@ -553,14 +553,16 @@ mf_build_check_statement_for (tree base, tree limit,
/* Build: __mf_base = (uintptr_t) <base address expression>. */
seq = gimple_seq_alloc ();
t = fold_convert (mf_uintptr_type, unshare_expr (base));
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
gimple_seq_add_seq (&seq, stmts);
g = gimple_build_assign (mf_base, t);
gimple_set_location (g, location);
gimple_seq_add_stmt (&seq, g);
/* Build: __mf_limit = (uintptr_t) <limit address expression>. */
t = fold_convert (mf_uintptr_type, unshare_expr (limit));
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
gimple_seq_add_seq (&seq, stmts);
g = gimple_build_assign (mf_limit, t);
gimple_set_location (g, location);
gimple_seq_add_stmt (&seq, g);
......@@ -577,7 +579,8 @@ mf_build_check_statement_for (tree base, tree limit,
TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
gimple_seq_add_seq (&seq, stmts);
g = gimple_build_assign (mf_elem, t);
gimple_set_location (g, location);
gimple_seq_add_stmt (&seq, g);
......@@ -622,7 +625,8 @@ mf_build_check_statement_for (tree base, tree limit,
result of the evaluation of 't' in a temporary variable which we
can use as the condition for the conditional jump. */
t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
gimplify_expr (&t, &seq, &seq, is_gimple_reg_rhs, fb_rvalue);
t = force_gimple_operand (t, &stmts, false, NULL_TREE);
gimple_seq_add_seq (&seq, stmts);
cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
g = gimple_build_assign (cond, t);
gimple_set_location (g, location);
......@@ -663,7 +667,8 @@ mf_build_check_statement_for (tree base, tree limit,
v = fold_build2 (PLUS_EXPR, integer_type_node,
fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
integer_one_node);
gimplify_expr (&v, &seq, &seq, is_gimple_mem_rhs, fb_rvalue);
v = force_gimple_operand (v, &stmts, true, NULL_TREE);
gimple_seq_add_seq (&seq, stmts);
g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u);
gimple_seq_add_stmt (&seq, g);
......
......@@ -1051,7 +1051,9 @@ get_or_alloc_expr_for (tree t)
{
if (TREE_CODE (t) == SSA_NAME)
return get_or_alloc_expr_for_name (t);
else if (is_gimple_min_invariant (t))
else if (is_gimple_min_invariant (t)
|| TREE_CODE (t) == EXC_PTR_EXPR
|| TREE_CODE (t) == FILTER_EXPR)
return get_or_alloc_expr_for_constant (t);
else
{
......
......@@ -2928,11 +2928,6 @@ struct tree_parm_decl GTY(())
/* Used to indicate that this DECL has weak linkage. */
#define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
/* Internal to the gimplifier. Indicates that the value is a formal
temporary controlled by the gimplifier. */
#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
/* Used to indicate that the DECL is a dllimport. */
#define DECL_DLLIMPORT_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
......@@ -3044,7 +3039,6 @@ struct tree_decl_with_vis GTY(())
unsigned thread_local:1;
unsigned common_flag:1;
unsigned in_text_section : 1;
unsigned gimple_formal_temp : 1;
unsigned dllimport_flag : 1;
unsigned based_on_restrict_p : 1;
/* Used by C++. Might become a generic decl flag. */
......@@ -3062,7 +3056,7 @@ struct tree_decl_with_vis GTY(())
/* Belongs to VAR_DECL exclusively. */
ENUM_BITFIELD(tls_model) tls_model : 3;
/* 12 unused bits. */
/* 13 unused bits. */
};
/* In a VAR_DECL that's static,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment