This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Allow generate_element_init in tree-sra.c to fail
I fixed a few buglets and committed this version.
r~
* tree-sra.c (struct sra_walk_fns): Revert 2004-07-05 change.
(sra_walk_modify_expr, scan_init): Likewise.
(generate_element_zero): Check visited before scanning children.
(generate_element_init): Set visited on error.
(scalarize_init): Handle generate_element_init failure similar
to use_block_copy.
Index: tree-sra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v
retrieving revision 2.16
diff -c -p -d -r2.16 tree-sra.c
*** tree-sra.c 5 Jul 2004 16:14:51 -0000 2.16
--- tree-sra.c 6 Jul 2004 22:57:11 -0000
*************** struct sra_walk_fns
*** 569,577 ****
block_stmt_iterator *bsi);
/* Invoked when ELT is initialized from a constant. VALUE may be NULL,
! in which case it should be treated as an empty CONSTRUCTOR. Return
! false if we found a case we couldn't handle. */
! bool (*init) (struct sra_elt *elt, tree value, block_stmt_iterator *bsi);
/* Invoked when we have a copy between one scalarizable reference ELT
and one non-scalarizable reference OTHER. IS_OUTPUT is true if ELT
--- 569,576 ----
block_stmt_iterator *bsi);
/* Invoked when ELT is initialized from a constant. VALUE may be NULL,
! in which case it should be treated as an empty CONSTRUCTOR. */
! void (*init) (struct sra_elt *elt, tree value, block_stmt_iterator *bsi);
/* Invoked when we have a copy between one scalarizable reference ELT
and one non-scalarizable reference OTHER. IS_OUTPUT is true if ELT
*************** sra_walk_modify_expr (tree expr, block_s
*** 770,790 ****
{
/* If this is an assignment from a constant, or constructor, then
we have access to all of the elements individually. Invoke INIT. */
! if ((TREE_CODE (rhs) == COMPLEX_EXPR
! || TREE_CODE (rhs) == COMPLEX_CST
! || TREE_CODE (rhs) == CONSTRUCTOR)
! && fns->init (lhs_elt, rhs, bsi))
! ;
/* If this is an assignment from read-only memory, treat this as if
we'd been passed the constructor directly. Invoke INIT. */
else if (TREE_CODE (rhs) == VAR_DECL
&& TREE_STATIC (rhs)
&& TREE_READONLY (rhs)
! && targetm.binds_local_p (rhs)
! && DECL_INITIAL (rhs)
! && fns->init (lhs_elt, DECL_INITIAL (rhs), bsi))
! ;
/* If this is a copy from a non-scalarizable lvalue, invoke LDST.
The lvalue requirement prevents us from trying to directly scalarize
--- 769,786 ----
{
/* If this is an assignment from a constant, or constructor, then
we have access to all of the elements individually. Invoke INIT. */
! if (TREE_CODE (rhs) == COMPLEX_EXPR
! || TREE_CODE (rhs) == COMPLEX_CST
! || TREE_CODE (rhs) == CONSTRUCTOR)
! fns->init (lhs_elt, rhs, bsi);
/* If this is an assignment from read-only memory, treat this as if
we'd been passed the constructor directly. Invoke INIT. */
else if (TREE_CODE (rhs) == VAR_DECL
&& TREE_STATIC (rhs)
&& TREE_READONLY (rhs)
! && targetm.binds_local_p (rhs))
! fns->init (lhs_elt, DECL_INITIAL (rhs), bsi);
/* If this is a copy from a non-scalarizable lvalue, invoke LDST.
The lvalue requirement prevents us from trying to directly scalarize
*************** scan_copy (struct sra_elt *lhs_elt, stru
*** 934,945 ****
rhs_elt->n_copies += 1;
}
! static bool
scan_init (struct sra_elt *lhs_elt, tree rhs ATTRIBUTE_UNUSED,
block_stmt_iterator *bsi ATTRIBUTE_UNUSED)
{
lhs_elt->n_copies += 1;
- return true;
}
static void
--- 930,940 ----
rhs_elt->n_copies += 1;
}
! static void
scan_init (struct sra_elt *lhs_elt, tree rhs ATTRIBUTE_UNUSED,
block_stmt_iterator *bsi ATTRIBUTE_UNUSED)
{
lhs_elt->n_copies += 1;
}
static void
*************** generate_element_zero (struct sra_elt *e
*** 1490,1501 ****
{
struct sra_elt *c;
for (c = elt->children; c ; c = c->sibling)
generate_element_zero (c, list_p);
! if (elt->visited)
! elt->visited = false;
! else if (elt->replacement)
{
tree t;
--- 1485,1500 ----
{
struct sra_elt *c;
+ if (elt->visited)
+ {
+ elt->visited = false;
+ return;
+ }
+
for (c = elt->children; c ; c = c->sibling)
generate_element_zero (c, list_p);
! if (elt->replacement)
{
tree t;
*************** generate_element_init (struct sra_elt *e
*** 1567,1572 ****
--- 1566,1572 ----
break;
default:
+ elt->visited = true;
result = false;
}
*************** scalarize_copy (struct sra_elt *lhs_elt,
*** 1760,1768 ****
/* Scalarize an INIT. To recap, this is an assignment to a scalarizable
reference from some form of constructor: CONSTRUCTOR, COMPLEX_CST or
COMPLEX_EXPR. If RHS is NULL, it should be treated as an empty
! CONSTRUCTOR. Return false if we didn't handle this case. */
! static bool
scalarize_init (struct sra_elt *lhs_elt, tree rhs, block_stmt_iterator *bsi)
{
bool result = true;
--- 1760,1768 ----
/* Scalarize an INIT. To recap, this is an assignment to a scalarizable
reference from some form of constructor: CONSTRUCTOR, COMPLEX_CST or
COMPLEX_EXPR. If RHS is NULL, it should be treated as an empty
! CONSTRUCTOR. */
! static void
scalarize_init (struct sra_elt *lhs_elt, tree rhs, block_stmt_iterator *bsi)
{
bool result = true;
*************** scalarize_init (struct sra_elt *lhs_elt,
*** 1776,1803 ****
a zero value. Initialize the rest of the instantiated elements. */
generate_element_zero (lhs_elt, &list);
! /* If we didn't generate anything or couldn't handle this case return.
! Say which it was. */
! if (!result || list == NULL)
! return result;
! if (lhs_elt->use_block_copy)
{
/* Since LHS is not fully instantiated, we must leave the structure
assignment in place. Treating this case differently from a USE
exposes constants to later optimizations. */
! mark_all_v_defs (expr_first (list));
! sra_insert_after (bsi, list);
}
else
{
/* The LHS is fully instantiated. The list of initializations
replaces the original structure assignment. */
mark_all_v_defs (bsi_stmt (*bsi));
sra_replace (bsi, list);
}
-
- return true;
}
/* A subroutine of scalarize_ldst called via walk_tree. Set TREE_NO_TRAP
--- 1776,1816 ----
a zero value. Initialize the rest of the instantiated elements. */
generate_element_zero (lhs_elt, &list);
! if (!result)
! {
! /* If we failed to convert the entire initializer, then we must
! leave the structure assignment in place and must load values
! from the structure into the slots for which we did not find
! constants. The easiest way to do this is to generate a complete
! copy-out, and then follow that with the constant assignments
! that we were able to build. DCE will clean things up. */
! tree list0 = NULL;
! generate_copy_inout (lhs_elt, true, generate_element_ref (lhs_elt),
! &list0);
! append_to_statement_list (list, &list0);
! list = list0;
! }
! if (lhs_elt->use_block_copy || !result)
{
/* Since LHS is not fully instantiated, we must leave the structure
assignment in place. Treating this case differently from a USE
exposes constants to later optimizations. */
! if (list)
! {
! mark_all_v_defs (expr_first (list));
! sra_insert_after (bsi, list);
! }
}
else
{
/* The LHS is fully instantiated. The list of initializations
replaces the original structure assignment. */
+ if (!list)
+ abort ();
mark_all_v_defs (bsi_stmt (*bsi));
sra_replace (bsi, list);
}
}
/* A subroutine of scalarize_ldst called via walk_tree. Set TREE_NO_TRAP