This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR42749
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 22 Feb 2010 13:57:24 +0100 (CET)
- Subject: [PATCH] Fix PR42749
This fixes the wrong typed accumulation during tail-recursion elimination.
We need to make sure to reconstruct the original arithmetic types.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
Richard.
2010-02-22 Richard Guenther <rguenther@suse.de>
PR tree-optimization/42749
* tree-tailcall.c (adjust_return_value_with_ops): Drop update
parameter. Do arithmetic in the original type.
(update_accumulator_with_ops): Likewise.
(adjust_accumulator_values): Adjust.
* gcc.c-torture/compile/pr42749.c: New testcase.
Index: gcc/tree-tailcall.c
===================================================================
*** gcc/tree-tailcall.c (revision 156949)
--- gcc/tree-tailcall.c (working copy)
*************** add_successor_phi_arg (edge e, tree var,
*** 570,592 ****
static tree
adjust_return_value_with_ops (enum tree_code code, const char *label,
! tree op0, tree op1, gimple_stmt_iterator gsi,
! enum gsi_iterator_update update)
{
tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
tree tmp = create_tmp_var (ret_type, label);
! gimple stmt = gimple_build_assign_with_ops (code, tmp, op0, op1);
tree result;
if (TREE_CODE (ret_type) == COMPLEX_TYPE
|| TREE_CODE (ret_type) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (tmp) = 1;
add_referenced_var (tmp);
result = make_ssa_name (tmp, stmt);
gimple_assign_set_lhs (stmt, result);
update_stmt (stmt);
! gsi_insert_before (&gsi, stmt, update);
return result;
}
--- 570,606 ----
static tree
adjust_return_value_with_ops (enum tree_code code, const char *label,
! tree acc, tree op1, gimple_stmt_iterator gsi)
{
tree ret_type = TREE_TYPE (DECL_RESULT (current_function_decl));
tree tmp = create_tmp_var (ret_type, label);
! gimple stmt;
tree result;
if (TREE_CODE (ret_type) == COMPLEX_TYPE
|| TREE_CODE (ret_type) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (tmp) = 1;
add_referenced_var (tmp);
+
+ if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
+ stmt = gimple_build_assign_with_ops (code, tmp, acc, op1);
+ else
+ {
+ tree rhs = fold_convert (TREE_TYPE (acc),
+ fold_build2 (code,
+ TREE_TYPE (op1),
+ fold_convert (TREE_TYPE (op1), acc),
+ op1));
+ rhs = force_gimple_operand_gsi (&gsi, rhs,
+ false, NULL, true, GSI_CONTINUE_LINKING);
+ stmt = gimple_build_assign (NULL_TREE, rhs);
+ }
+
result = make_ssa_name (tmp, stmt);
gimple_assign_set_lhs (stmt, result);
update_stmt (stmt);
! gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
return result;
}
*************** static tree
*** 599,607 ****
update_accumulator_with_ops (enum tree_code code, tree acc, tree op1,
gimple_stmt_iterator gsi)
{
! gimple stmt = gimple_build_assign_with_ops (code, SSA_NAME_VAR (acc), acc,
! op1);
! tree var = make_ssa_name (SSA_NAME_VAR (acc), stmt);
gimple_assign_set_lhs (stmt, var);
update_stmt (stmt);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
--- 613,634 ----
update_accumulator_with_ops (enum tree_code code, tree acc, tree op1,
gimple_stmt_iterator gsi)
{
! gimple stmt;
! tree var;
! if (types_compatible_p (TREE_TYPE (acc), TREE_TYPE (op1)))
! stmt = gimple_build_assign_with_ops (code, SSA_NAME_VAR (acc), acc, op1);
! else
! {
! tree rhs = fold_convert (TREE_TYPE (acc),
! fold_build2 (code,
! TREE_TYPE (op1),
! fold_convert (TREE_TYPE (op1), acc),
! op1));
! rhs = force_gimple_operand_gsi (&gsi, rhs,
! false, NULL, false, GSI_CONTINUE_LINKING);
! stmt = gimple_build_assign (NULL_TREE, rhs);
! }
! make_ssa_name (SSA_NAME_VAR (acc), stmt);
gimple_assign_set_lhs (stmt, var);
update_stmt (stmt);
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
*************** adjust_accumulator_values (gimple_stmt_i
*** 631,637 ****
var = m_acc;
else
var = adjust_return_value_with_ops (MULT_EXPR, "acc_tmp", m_acc,
! a, gsi, GSI_NEW_STMT);
}
else
var = a;
--- 658,664 ----
var = m_acc;
else
var = adjust_return_value_with_ops (MULT_EXPR, "acc_tmp", m_acc,
! a, gsi);
}
else
var = a;
*************** adjust_return_value (basic_block bb, tre
*** 667,676 ****
if (m)
retval = adjust_return_value_with_ops (MULT_EXPR, "mul_tmp", m_acc, retval,
! gsi, GSI_SAME_STMT);
if (a)
retval = adjust_return_value_with_ops (PLUS_EXPR, "acc_tmp", a_acc, retval,
! gsi, GSI_SAME_STMT);
gimple_return_set_retval (ret_stmt, retval);
update_stmt (ret_stmt);
}
--- 694,703 ----
if (m)
retval = adjust_return_value_with_ops (MULT_EXPR, "mul_tmp", m_acc, retval,
! gsi);
if (a)
retval = adjust_return_value_with_ops (PLUS_EXPR, "acc_tmp", a_acc, retval,
! gsi);
gimple_return_set_retval (ret_stmt, retval);
update_stmt (ret_stmt);
}
Index: gcc/testsuite/gcc.c-torture/compile/pr42749.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr42749.c (revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr42749.c (revision 0)
***************
*** 0 ****
--- 1,5 ----
+ struct pdf_object { int val; };
+ int pdf_count_size_object (struct pdf_object * p_obj)
+ {
+ return pdf_count_size_object(p_obj) + 2 * sizeof(struct pdf_object);
+ }