tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address): New function.

2010-07-08  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
	New function.
	(valueize_refs): Call it.

From-SVN: r161946
This commit is contained in:
Richard Guenther 2010-07-08 09:16:42 +00:00 committed by Richard Biener
parent e73cfe5d34
commit a03a9774c1
2 changed files with 87 additions and 0 deletions

View File

@ -1,3 +1,9 @@
2010-07-08 Richard Guenther <rguenther@suse.de>
* tree-ssa-sccvn.c (vn_reference_maybe_forwprop_address):
New function.
(valueize_refs): Call it.
2010-07-08 Richard Guenther <rguenther@suse.de>
PR rtl-optimization/44838

View File

@ -972,6 +972,82 @@ vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **ops,
}
}
/* Fold *& at position *I_P in a vn_reference_op_s vector *OPS. Updates
*I_P to point to the last element of the replacement. */
static void
vn_reference_maybe_forwprop_address (VEC (vn_reference_op_s, heap) **ops,
unsigned int *i_p)
{
unsigned int i = *i_p;
vn_reference_op_t op = VEC_index (vn_reference_op_s, *ops, i);
vn_reference_op_t mem_op = VEC_index (vn_reference_op_s, *ops, i - 1);
gimple def_stmt;
enum tree_code code;
double_int off;
def_stmt = SSA_NAME_DEF_STMT (op->op0);
if (!gimple_assign_single_p (def_stmt))
return;
code = gimple_assign_rhs_code (def_stmt);
if (code != ADDR_EXPR
&& code != POINTER_PLUS_EXPR)
return;
off = tree_to_double_int (mem_op->op0);
off = double_int_sext (off, TYPE_PRECISION (TREE_TYPE (mem_op->op0)));
/* The only thing we have to do is from &OBJ.foo.bar add the offset
from .foo.bar to the preceeding MEM_REF offset and replace the
address with &OBJ. */
if (code == ADDR_EXPR)
{
tree addr, addr_base;
HOST_WIDE_INT addr_offset;
addr = gimple_assign_rhs1 (def_stmt);
addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
&addr_offset);
if (!addr_base
|| TREE_CODE (addr_base) != MEM_REF)
return;
off = double_int_add (off, shwi_to_double_int (addr_offset));
off = double_int_add (off, mem_ref_offset (addr_base));
op->op0 = TREE_OPERAND (addr_base, 0);
}
else
{
tree ptr, ptroff;
ptr = gimple_assign_rhs1 (def_stmt);
ptroff = gimple_assign_rhs2 (def_stmt);
if (TREE_CODE (ptr) != SSA_NAME
|| TREE_CODE (ptroff) != INTEGER_CST)
return;
off = double_int_add (off, tree_to_double_int (ptroff));
op->op0 = TREE_OPERAND (ptr, 0);
}
mem_op->op0 = double_int_to_tree (TREE_TYPE (mem_op->op0), off);
if (host_integerp (mem_op->op0, 0))
mem_op->off = TREE_INT_CST_LOW (mem_op->op0);
else
mem_op->off = -1;
if (TREE_CODE (op->op0) == SSA_NAME)
{
op->op0 = SSA_VAL (op->op0);
if (TREE_CODE (op->op0) != SSA_NAME)
op->opcode = TREE_CODE (op->op0);
}
/* And recurse. */
if (TREE_CODE (op->op0) == SSA_NAME)
vn_reference_maybe_forwprop_address (ops, i_p);
else if (TREE_CODE (op->op0) == ADDR_EXPR)
vn_reference_fold_indirect (ops, i_p);
}
/* Optimize the reference REF to a constant if possible or return
NULL_TREE if not. */
@ -1075,6 +1151,11 @@ valueize_refs (VEC (vn_reference_op_s, heap) *orig)
&& VEC_index (vn_reference_op_s,
orig, i - 1)->opcode == MEM_REF)
vn_reference_fold_indirect (&orig, &i);
else if (i > 0
&& vro->opcode == SSA_NAME
&& VEC_index (vn_reference_op_s,
orig, i - 1)->opcode == MEM_REF)
vn_reference_maybe_forwprop_address (&orig, &i);
/* If it transforms a non-constant ARRAY_REF into a constant
one, adjust the constant offset. */
else if (vro->opcode == ARRAY_REF