mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-23 15:39:46 +08:00
re PR tree-optimization/20610 (Real by complex multiplications perform unnecessary operations)
PR tree-opt/20610 * tree.h (DECL_COMPLEX_GIMPLE_REG_P): New. (struct tree_decl): Add gimple_reg_flag. * integrate.c (copy_decl_for_inlining): Copy it. * gimplify.c (internal_get_tmp_var): Set it. (gimplify_bind_expr): Likewise. (gimplify_function_tree): Likewise. (gimplify_modify_expr_complex_part): New. (gimplify_modify_expr): Use it. * tree-gimple.c (is_gimple_reg_type): Allow complex. (is_gimple_reg): Allow complex with DECL_COMPLEX_GIMPLE_REG_P set. * tree-complex.c (complex_lattice_t): New. (complex_lattice_values, complex_variable_components): New. (some_nonzerop, find_lattice_value, is_complex_reg, init_parameter_lattice_values, init_dont_simulate_again, complex_visit_stmt, complex_visit_phi, create_components, update_complex_components, update_parameter_components, update_phi_components, update_all_vops, expand_complex_move): New. (extract_component): Handle INDIRECT_REF, COMPONENT_REF, ARRAY_REF, SSA_NAME. (update_complex_assignment): Use update_complex_components; handle updates of return_expr properly. (expand_complex_addition): Use complex lattice values. (expand_complex_multiplication): Likewise. (expand_complex_division): Likewise. (expand_complex_libcall): Use update_complex_components. (expand_complex_comparison): Use update_stmt. (expand_complex_operations_1): Use expand_complex_move, retrieve lattice values. (tree_lower_complex): Compute lattice values. (tree_lower_complex_O0): Duplicate from tree_lower_complex. (pass_lower_complex_O0): Rename from pass_lower_complex. (pass_lower_complex, gate_no_optimization): New. * tree-optimize.c (init_tree_optimization_passes): Update for complex pass changes. * tree-pass.h (pass_lower_complex_O0): Declare. From-SVN: r100793
This commit is contained in:
parent
31920d83c2
commit
e41d82f5d7
@ -1,3 +1,43 @@
|
||||
2005-06-09 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR tree-opt/20610
|
||||
* tree.h (DECL_COMPLEX_GIMPLE_REG_P): New.
|
||||
(struct tree_decl): Add gimple_reg_flag.
|
||||
* integrate.c (copy_decl_for_inlining): Copy it.
|
||||
* gimplify.c (internal_get_tmp_var): Set it.
|
||||
(gimplify_bind_expr): Likewise.
|
||||
(gimplify_function_tree): Likewise.
|
||||
(gimplify_modify_expr_complex_part): New.
|
||||
(gimplify_modify_expr): Use it.
|
||||
* tree-gimple.c (is_gimple_reg_type): Allow complex.
|
||||
(is_gimple_reg): Allow complex with DECL_COMPLEX_GIMPLE_REG_P set.
|
||||
|
||||
* tree-complex.c (complex_lattice_t): New.
|
||||
(complex_lattice_values, complex_variable_components): New.
|
||||
(some_nonzerop, find_lattice_value, is_complex_reg,
|
||||
init_parameter_lattice_values, init_dont_simulate_again,
|
||||
complex_visit_stmt, complex_visit_phi, create_components,
|
||||
update_complex_components, update_parameter_components,
|
||||
update_phi_components, update_all_vops, expand_complex_move): New.
|
||||
(extract_component): Handle INDIRECT_REF, COMPONENT_REF, ARRAY_REF,
|
||||
SSA_NAME.
|
||||
(update_complex_assignment): Use update_complex_components;
|
||||
handle updates of return_expr properly.
|
||||
(expand_complex_addition): Use complex lattice values.
|
||||
(expand_complex_multiplication): Likewise.
|
||||
(expand_complex_division): Likewise.
|
||||
(expand_complex_libcall): Use update_complex_components.
|
||||
(expand_complex_comparison): Use update_stmt.
|
||||
(expand_complex_operations_1): Use expand_complex_move, retrieve
|
||||
lattice values.
|
||||
(tree_lower_complex): Compute lattice values.
|
||||
(tree_lower_complex_O0): Duplicate from tree_lower_complex.
|
||||
(pass_lower_complex_O0): Rename from pass_lower_complex.
|
||||
(pass_lower_complex, gate_no_optimization): New.
|
||||
* tree-optimize.c (init_tree_optimization_passes): Update for
|
||||
complex pass changes.
|
||||
* tree-pass.h (pass_lower_complex_O0): Declare.
|
||||
|
||||
2005-06-08 Dale Johannesen <dalej@apple.com>
|
||||
|
||||
* config/darwin.c (darwin_binds_local_p): New.
|
||||
|
@ -470,6 +470,9 @@ internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal)
|
||||
|
||||
t = lookup_tmp_var (val, is_formal);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
|
||||
DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
|
||||
|
||||
mod = build (MODIFY_EXPR, TREE_TYPE (t), t, val);
|
||||
|
||||
if (EXPR_HAS_LOCATION (val))
|
||||
@ -856,7 +859,18 @@ gimplify_bind_expr (tree *expr_p, tree temp, tree *pre_p)
|
||||
|
||||
/* Mark variables seen in this bind expr. */
|
||||
for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
|
||||
DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
|
||||
{
|
||||
DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
|
||||
|
||||
/* Preliminarily mark non-addressed complex variables as eligible
|
||||
for promotion to gimple registers. We'll transform their uses
|
||||
as we find them. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
|
||||
&& !TREE_THIS_VOLATILE (t)
|
||||
&& (TREE_CODE (t) == VAR_DECL && !DECL_HARD_REGISTER (t))
|
||||
&& !needs_to_live_in_memory (t))
|
||||
DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
|
||||
}
|
||||
|
||||
gimple_push_bind_expr (bind_expr);
|
||||
gimplify_ctxp->save_stack = false;
|
||||
@ -3009,6 +3023,45 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
|
||||
a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a variable with
|
||||
DECL_COMPLEX_GIMPLE_REG_P set. */
|
||||
|
||||
static enum gimplify_status
|
||||
gimplify_modify_expr_complex_part (tree *expr_p, tree *pre_p, bool want_value)
|
||||
{
|
||||
enum tree_code code, ocode;
|
||||
tree lhs, rhs, new_rhs, other, realpart, imagpart;
|
||||
|
||||
lhs = TREE_OPERAND (*expr_p, 0);
|
||||
rhs = TREE_OPERAND (*expr_p, 1);
|
||||
code = TREE_CODE (lhs);
|
||||
lhs = TREE_OPERAND (lhs, 0);
|
||||
|
||||
ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
|
||||
other = build1 (ocode, TREE_TYPE (rhs), lhs);
|
||||
other = get_formal_tmp_var (other, pre_p);
|
||||
|
||||
realpart = code == REALPART_EXPR ? rhs : other;
|
||||
imagpart = code == REALPART_EXPR ? other : rhs;
|
||||
|
||||
if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
|
||||
new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
|
||||
else
|
||||
new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
|
||||
|
||||
TREE_OPERAND (*expr_p, 0) = lhs;
|
||||
TREE_OPERAND (*expr_p, 1) = new_rhs;
|
||||
|
||||
if (want_value)
|
||||
{
|
||||
append_to_statement_list (*expr_p, pre_p);
|
||||
*expr_p = rhs;
|
||||
}
|
||||
|
||||
return GS_ALL_DONE;
|
||||
}
|
||||
|
||||
/* Gimplify the MODIFY_EXPR node pointed by EXPR_P.
|
||||
|
||||
modify_expr
|
||||
@ -3084,6 +3137,14 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
|
||||
}
|
||||
}
|
||||
|
||||
/* Transform partial stores to non-addressable complex variables into
|
||||
total stores. This allows us to use real instead of virtual operands
|
||||
for these variables, which improves optimization. */
|
||||
if ((TREE_CODE (*to_p) == REALPART_EXPR
|
||||
|| TREE_CODE (*to_p) == IMAGPART_EXPR)
|
||||
&& is_gimple_reg (TREE_OPERAND (*to_p, 0)))
|
||||
return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
|
||||
|
||||
if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
|
||||
{
|
||||
/* If we've somehow already got an SSA_NAME on the LHS, then
|
||||
@ -4668,7 +4729,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
|
||||
void
|
||||
gimplify_function_tree (tree fndecl)
|
||||
{
|
||||
tree oldfn;
|
||||
tree oldfn, parm, ret;
|
||||
|
||||
oldfn = current_function_decl;
|
||||
current_function_decl = fndecl;
|
||||
@ -4676,6 +4737,22 @@ gimplify_function_tree (tree fndecl)
|
||||
if (cfun == NULL)
|
||||
allocate_struct_function (fndecl);
|
||||
|
||||
for (parm = DECL_ARGUMENTS (fndecl); parm ; parm = TREE_CHAIN (parm))
|
||||
{
|
||||
/* Preliminarily mark non-addressed complex variables as eligible
|
||||
for promotion to gimple registers. We'll transform their uses
|
||||
as we find them. */
|
||||
if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
|
||||
&& !TREE_THIS_VOLATILE (parm)
|
||||
&& !needs_to_live_in_memory (parm))
|
||||
DECL_COMPLEX_GIMPLE_REG_P (parm) = 1;
|
||||
}
|
||||
|
||||
ret = DECL_RESULT (fndecl);
|
||||
if (TREE_CODE (TREE_TYPE (ret)) == COMPLEX_TYPE
|
||||
&& !needs_to_live_in_memory (ret))
|
||||
DECL_COMPLEX_GIMPLE_REG_P (ret) = 1;
|
||||
|
||||
gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
|
||||
|
||||
/* If we're instrumenting function entry/exit, then prepend the call to
|
||||
|
@ -107,6 +107,7 @@ copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn)
|
||||
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
|
||||
TREE_READONLY (copy) = TREE_READONLY (decl);
|
||||
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
|
||||
DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (decl);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -260,12 +260,10 @@ is_gimple_id (tree t)
|
||||
bool
|
||||
is_gimple_reg_type (tree type)
|
||||
{
|
||||
return (!AGGREGATE_TYPE_P (type)
|
||||
&& TREE_CODE (type) != COMPLEX_TYPE);
|
||||
return !AGGREGATE_TYPE_P (type);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if T is a scalar register variable. */
|
||||
/* Return true if T is a non-aggregate register variable. */
|
||||
|
||||
bool
|
||||
is_gimple_reg (tree t)
|
||||
@ -275,6 +273,7 @@ is_gimple_reg (tree t)
|
||||
|
||||
if (!is_gimple_variable (t))
|
||||
return false;
|
||||
|
||||
if (!is_gimple_reg_type (TREE_TYPE (t)))
|
||||
return false;
|
||||
|
||||
@ -301,6 +300,11 @@ is_gimple_reg (tree t)
|
||||
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
|
||||
return false;
|
||||
|
||||
/* Complex values must have been put into ssa form. That is, no
|
||||
assignments to the individual components. */
|
||||
if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
|
||||
return DECL_COMPLEX_GIMPLE_REG_P (t);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ init_tree_optimization_passes (void)
|
||||
NEXT_PASS (pass_lower_cf);
|
||||
NEXT_PASS (pass_lower_eh);
|
||||
NEXT_PASS (pass_build_cfg);
|
||||
NEXT_PASS (pass_lower_complex);
|
||||
NEXT_PASS (pass_lower_complex_O0);
|
||||
NEXT_PASS (pass_lower_vector);
|
||||
NEXT_PASS (pass_warn_function_return);
|
||||
NEXT_PASS (pass_tree_profile);
|
||||
@ -417,6 +417,7 @@ init_tree_optimization_passes (void)
|
||||
NEXT_PASS (pass_profile);
|
||||
NEXT_PASS (pass_ch);
|
||||
NEXT_PASS (pass_stdarg);
|
||||
NEXT_PASS (pass_lower_complex);
|
||||
NEXT_PASS (pass_sra);
|
||||
/* FIXME: SRA may generate arbitrary gimple code, exposing new
|
||||
aliased and call-clobbered variables. As mentioned below,
|
||||
|
@ -192,6 +192,7 @@ extern struct tree_opt_pass pass_may_alias;
|
||||
extern struct tree_opt_pass pass_split_crit_edges;
|
||||
extern struct tree_opt_pass pass_pre;
|
||||
extern struct tree_opt_pass pass_profile;
|
||||
extern struct tree_opt_pass pass_lower_complex_O0;
|
||||
extern struct tree_opt_pass pass_lower_complex;
|
||||
extern struct tree_opt_pass pass_lower_vector;
|
||||
extern struct tree_opt_pass pass_lower_vector_ssa;
|
||||
|
13
gcc/tree.h
13
gcc/tree.h
@ -2353,6 +2353,14 @@ extern void decl_value_expr_insert (tree, tree);
|
||||
#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
|
||||
DECL_CHECK (DECL)->decl.gimple_formal_temp
|
||||
|
||||
/* For function local variables of COMPLEX type, indicates that the
|
||||
variable is not aliased, and that all modifications to the variable
|
||||
have been adjusted so that they are killing assignments. Thus the
|
||||
variable may now be treated as a GIMPLE register, and use real
|
||||
instead of virtual ops in SSA form. */
|
||||
#define DECL_COMPLEX_GIMPLE_REG_P(DECL) \
|
||||
DECL_CHECK (DECL)->decl.gimple_reg_flag
|
||||
|
||||
/* Enumerate visibility settings. */
|
||||
#ifndef SYMBOL_VISIBILITY_DEFINED
|
||||
#define SYMBOL_VISIBILITY_DEFINED
|
||||
@ -2424,8 +2432,9 @@ struct tree_decl GTY(())
|
||||
unsigned returns_twice_flag : 1;
|
||||
unsigned seen_in_bind_expr : 1;
|
||||
unsigned novops_flag : 1;
|
||||
unsigned has_value_expr:1;
|
||||
/* 8 unused bits. */
|
||||
unsigned has_value_expr : 1;
|
||||
unsigned gimple_reg_flag : 1;
|
||||
/* 7 unused bits. */
|
||||
|
||||
union tree_decl_u1 {
|
||||
/* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
|
||||
|
Loading…
Reference in New Issue
Block a user