This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Virtual operands in tree-tailcall
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 1 Jan 2004 23:58:41 +0100
- Subject: [tree-ssa] Virtual operands in tree-tailcall
Hello,
while playing with new loop invariant motion pass, I have noticed
a problem with the tail recursion elimination -- we just forget the
vdefs of the call. This causes problems in cases like
int n;
void bla (void)
{
int p = n;
n++;
if (!p)
bla ();
}
where the missing vdef enables us to hoist p = n assignment out of the
loop. This patch turns the vdefs into loop phi nodes, thus fixing the
problem.
Ok if it passes regtesting?
Zdenek
* tree-tailcall.c (eliminate_tail_call): Add phi nodes for the call
vdefs.
Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-tailcall.c,v
retrieving revision 1.1.2.12
diff -c -3 -p -r1.1.2.12 tree-tailcall.c
*** tree-tailcall.c 19 Dec 2003 07:01:36 -0000 1.1.2.12
--- tree-tailcall.c 1 Jan 2004 22:44:51 -0000
*************** static void
*** 249,259 ****
eliminate_tail_call (struct tailcall *t)
{
tree param, stmt, args;
! basic_block bb;
edge e;
tree phi;
stmt = bsi_stmt (t->call_bsi);
bb = t->call_block;
if (dump_file && (dump_flags & TDF_DETAILS))
--- 249,264 ----
eliminate_tail_call (struct tailcall *t)
{
tree param, stmt, args;
! basic_block bb, first;
edge e;
tree phi;
+ stmt_ann_t ann;
+ vdef_optype vdefs;
+ unsigned i;
stmt = bsi_stmt (t->call_bsi);
+ get_stmt_operands (stmt);
+ ann = stmt_ann (stmt);
bb = t->call_block;
if (dump_file && (dump_flags & TDF_DETAILS))
*************** eliminate_tail_call (struct tailcall *t)
*** 274,298 ****
}
bsi_remove (&t->call_bsi);
! e = redirect_edge_and_branch (t->call_block->succ,
! ENTRY_BLOCK_PTR->succ->dest);
if (!e)
abort ();
! /* We expect that each PHI node on first basic block represent an argument.
! Add proper entries. */
! for (phi = phi_nodes (ENTRY_BLOCK_PTR->succ->dest); phi;
! phi = TREE_CHAIN (phi))
{
! for (param = DECL_ARGUMENTS (current_function_decl),
! args = TREE_OPERAND (stmt, 1);
! param;
! param = TREE_CHAIN (param),
! args = TREE_CHAIN (args))
if (param == SSA_NAME_VAR (PHI_RESULT (phi)))
break;
! if (!param)
abort ();
add_phi_arg (&phi, TREE_VALUE (args), e);
}
}
--- 279,329 ----
}
bsi_remove (&t->call_bsi);
! first = ENTRY_BLOCK_PTR->succ->dest;
! e = redirect_edge_and_branch (t->call_block->succ, first);
if (!e)
abort ();
!
! /* Add phi node entries for arguments. */
! for (param = DECL_ARGUMENTS (current_function_decl),
! args = TREE_OPERAND (stmt, 1);
! param;
! param = TREE_CHAIN (param),
! args = TREE_CHAIN (args))
{
! for (phi = phi_nodes (first); phi; phi = TREE_CHAIN (phi))
if (param == SSA_NAME_VAR (PHI_RESULT (phi)))
break;
! if (!phi)
abort ();
add_phi_arg (&phi, TREE_VALUE (args), e);
+ }
+
+ /* Add phi nodes for the call clobbered variables. */
+ vdefs = VDEF_OPS (ann);
+ for (i = 0; i < NUM_VDEFS (vdefs); i++)
+ {
+ param = SSA_NAME_VAR (VDEF_RESULT (vdefs, i));
+ for (phi = phi_nodes (first); phi; phi = TREE_CHAIN (phi))
+ if (param == SSA_NAME_VAR (PHI_RESULT (phi)))
+ break;
+
+ if (!phi)
+ {
+ tree name = var_ann (param)->default_def;
+ tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
+
+ var_ann (param)->default_def = new_name;
+ phi = create_phi_node (name, first);
+ SSA_NAME_DEF_STMT (name) = phi;
+ add_phi_arg (&phi, new_name, ENTRY_BLOCK_PTR->succ);
+
+ /* For all calls the same set of variables should be clobbered. */
+ if (first->pred->pred_next->pred_next)
+ abort ();
+ }
+
+ add_phi_arg (&phi, VDEF_OP (vdefs, i), e);
}
}