aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-forwprop.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-01-09 11:14:55 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2015-01-09 11:14:55 +0000
commit2f2782497acb6efa025c1f832a37a0afeb3925f7 (patch)
tree03add0605b49b2b5c0f9393c96db9dfd878e15e2 /gcc/tree-ssa-forwprop.c
parent520b30221300436cbc178a4110123c12ad3ee0ee (diff)
downloadgcc-2f2782497acb6efa025c1f832a37a0afeb3925f7.zip
gcc-2f2782497acb6efa025c1f832a37a0afeb3925f7.tar.gz
gcc-2f2782497acb6efa025c1f832a37a0afeb3925f7.tar.bz2
re PR tree-optimization/64410 (gcc 25% slower than clang 3.5 for adding complex numbers)
2015-01-09 Richard Biener <rguenther@suse.de> PR tree-optimization/64410 * tree-ssa.c (non_rewritable_lvalue_p): Allow REALPART/IMAGPART_EXPR on the LHS. (execute_update_addresses_taken): Deal with that. * tree-ssa-forwprop.c (pass_forwprop::execute): Use component-wise loads/stores for complex variables. * g++.dg/vect/pr64410.cc: New testcase. From-SVN: r219380
Diffstat (limited to 'gcc/tree-ssa-forwprop.c')
-rw-r--r--gcc/tree-ssa-forwprop.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 04b1509..a8fbccc 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2210,6 +2210,97 @@ pass_forwprop::execute (function *fun)
else
gsi_next (&gsi);
}
+ else if (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE
+ && gimple_assign_load_p (stmt)
+ && !gimple_has_volatile_ops (stmt)
+ && !stmt_can_throw_internal (stmt))
+ {
+ /* Rewrite loads used only in real/imagpart extractions to
+ component-wise loads. */
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ bool rewrite = true;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
+ {
+ gimple use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
+ if (!is_gimple_assign (use_stmt)
+ || (gimple_assign_rhs_code (use_stmt) != REALPART_EXPR
+ && gimple_assign_rhs_code (use_stmt) != IMAGPART_EXPR))
+ {
+ rewrite = false;
+ break;
+ }
+ }
+ if (rewrite)
+ {
+ gimple use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+ {
+ if (is_gimple_debug (use_stmt))
+ {
+ if (gimple_debug_bind_p (use_stmt))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ continue;
+ }
+
+ tree new_rhs = build1 (gimple_assign_rhs_code (use_stmt),
+ TREE_TYPE (TREE_TYPE (rhs)),
+ unshare_expr (rhs));
+ gimple new_stmt
+ = gimple_build_assign (gimple_assign_lhs (use_stmt),
+ new_rhs);
+
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+ unlink_stmt_vdef (use_stmt);
+ gsi_remove (&gsi2, true);
+
+ gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+ }
+ gsi_remove (&gsi, true);
+ }
+ else
+ gsi_next (&gsi);
+ }
+ else if (code == COMPLEX_EXPR)
+ {
+ /* Rewrite stores of a single-use complex build expression
+ to component-wise stores. */
+ use_operand_p use_p;
+ gimple use_stmt;
+ if (single_imm_use (lhs, &use_p, &use_stmt)
+ && gimple_store_p (use_stmt)
+ && !gimple_has_volatile_ops (use_stmt)
+ && is_gimple_assign (use_stmt))
+ {
+ tree use_lhs = gimple_assign_lhs (use_stmt);
+ tree new_lhs = build1 (REALPART_EXPR,
+ TREE_TYPE (TREE_TYPE (use_lhs)),
+ unshare_expr (use_lhs));
+ gimple new_stmt = gimple_build_assign (new_lhs, rhs);
+ gimple_set_vuse (new_stmt, gimple_vuse (use_stmt));
+ gimple_set_vdef (new_stmt, make_ssa_name (gimple_vop (cfun)));
+ SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
+ gimple_set_vuse (use_stmt, gimple_vdef (new_stmt));
+ gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt);
+ gsi_insert_before (&gsi2, new_stmt, GSI_SAME_STMT);
+
+ new_lhs = build1 (IMAGPART_EXPR,
+ TREE_TYPE (TREE_TYPE (use_lhs)),
+ unshare_expr (use_lhs));
+ gimple_assign_set_lhs (use_stmt, new_lhs);
+ gimple_assign_set_rhs1 (use_stmt, gimple_assign_rhs2 (stmt));
+ update_stmt (use_stmt);
+
+ gsi_remove (&gsi, true);
+ }
+ else
+ gsi_next (&gsi);
+ }
else
gsi_next (&gsi);
}