re PR tree-optimization/48317 (SCCVN does not handle vector constructors)

2011-09-06  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/48317
	* tree-ssa-sccvn.h (struct vn_nary_op_s): Make op a true
	trailing array.
	(sizeof_vn_nary_op): New inline function.
	(vn_nary_op_lookup_pieces): Adjust.
	(vn_nary_op_insert_pieces): Likewise.
	* tree-ssa-sccvn.c (vn_nary_op_eq): Also compare the length.
	(init_vn_nary_op_from_pieces): Adjust signature.  Deal with
	any number of operands.
	(vn_nary_length_from_stmt): New function.
	(init_vn_nary_op_from_stmt): Adjust for CONSTRUCTOR handling.
	(vn_nary_op_lookup_pieces): Adjust signature and allocate properly
	sized temporary.
	(vn_nary_op_lookup): Likewise.
	(vn_nary_op_lookup_stmt): Likewise.
	(vn_nary_op_insert_into): Likewise.
	(vn_nary_op_insert_stmt): Likewise.
	(visit_use): Handle CONSTRUCTOR as nary.
	* tree-ssa-pre.c (phi_translate_1): Adjust.
	(create_expression_by_pieces): Likewise.
	(compute_avail): Likewise.

	* gcc.dg/tree-ssa/ssa-fre-31.c: New testcase.

From-SVN: r178595
This commit is contained in:
Richard Guenther 2011-09-06 13:17:50 +00:00 committed by Richard Biener
parent 0a03460680
commit 5a7d7f9cf3
6 changed files with 222 additions and 134 deletions

View File

@ -1,3 +1,27 @@
2011-09-06 Richard Guenther <rguenther@suse.de>
PR tree-optimization/48317
* tree-ssa-sccvn.h (struct vn_nary_op_s): Make op a true
trailing array.
(sizeof_vn_nary_op): New inline function.
(vn_nary_op_lookup_pieces): Adjust.
(vn_nary_op_insert_pieces): Likewise.
* tree-ssa-sccvn.c (vn_nary_op_eq): Also compare the length.
(init_vn_nary_op_from_pieces): Adjust signature. Deal with
any number of operands.
(vn_nary_length_from_stmt): New function.
(init_vn_nary_op_from_stmt): Adjust for CONSTRUCTOR handling.
(vn_nary_op_lookup_pieces): Adjust signature and allocate properly
sized temporary.
(vn_nary_op_lookup): Likewise.
(vn_nary_op_lookup_stmt): Likewise.
(vn_nary_op_insert_into): Likewise.
(vn_nary_op_insert_stmt): Likewise.
(visit_use): Handle CONSTRUCTOR as nary.
* tree-ssa-pre.c (phi_translate_1): Adjust.
(create_expression_by_pieces): Likewise.
(compute_avail): Likewise.
2011-09-06 Ira Rosen <ira.rosen@linaro.org>
* config/arm/arm.c (arm_preferred_simd_mode): Check

View File

@ -1,3 +1,8 @@
2011-09-06 Richard Guenther <rguenther@suse.de>
PR tree-optimization/48317
* gcc.dg/tree-ssa/ssa-fre-31.c: New testcase.
2011-09-06 Ira Rosen <ira.rosen@linaro.org>
* lib/target-supports.exp (check_effective_target_vect_multiple_sizes):

View File

@ -0,0 +1,46 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1-details" } */
typedef double d128 __attribute__((vector_size(16)));
typedef float f128 __attribute__((vector_size(16)));
typedef short s128 __attribute__((vector_size(16)));
typedef char c256 __attribute__((vector_size(32)));
d128 d;
f128 f;
s128 s;
c256 c;
void test1 (double x)
{
d = (d128){x + x, x + x};
d = (d128){x + x, x + x};
}
void test2 (float x)
{
f = (f128){x + x, x + x, x + x, x + x};
f = (f128){x + x, x + x, x + x, x + x};
}
void test3 (short x)
{
s = (s128){x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x};
s = (s128){x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x};
}
void test4 (unsigned char x)
{
c = (c256){x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x};
c = (c256){x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x,
x + x, x + x, x + x, x + x, x + x, x + x, x + x, x + x};
}
/* { dg-final { scan-tree-dump-times "Replaced \{" 4 "fre1" } } */
/* { dg-final { scan-tree-dump-times "Deleted redundant store" 4 "fre1" } } */
/* { dg-final { cleanup-tree-dump "fre1" } } */

View File

@ -1443,20 +1443,18 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
unsigned int i;
bool changed = false;
vn_nary_op_t nary = PRE_EXPR_NARY (expr);
struct vn_nary_op_s newnary;
/* The NARY structure is only guaranteed to have been
allocated to the nary->length operands. */
memcpy (&newnary, nary, (sizeof (struct vn_nary_op_s)
- sizeof (tree) * (4 - nary->length)));
vn_nary_op_t newnary = XALLOCAVAR (struct vn_nary_op_s,
sizeof_vn_nary_op (nary->length));
memcpy (newnary, nary, sizeof_vn_nary_op (nary->length));
for (i = 0; i < newnary.length; i++)
for (i = 0; i < newnary->length; i++)
{
if (TREE_CODE (newnary.op[i]) != SSA_NAME)
if (TREE_CODE (newnary->op[i]) != SSA_NAME)
continue;
else
{
pre_expr leader, result;
unsigned int op_val_id = VN_INFO (newnary.op[i])->value_id;
unsigned int op_val_id = VN_INFO (newnary->op[i])->value_id;
leader = find_leader_in_sets (op_val_id, set1, set2);
result = phi_translate (leader, set1, set2, pred, phiblock);
if (result && result != leader)
@ -1464,12 +1462,12 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
tree name = get_representative_for (result);
if (!name)
return NULL;
newnary.op[i] = name;
newnary->op[i] = name;
}
else if (!result)
return NULL;
changed |= newnary.op[i] != nary->op[i];
changed |= newnary->op[i] != nary->op[i];
}
}
if (changed)
@ -1477,13 +1475,10 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
pre_expr constant;
unsigned int new_val_id;
tree result = vn_nary_op_lookup_pieces (newnary.length,
newnary.opcode,
newnary.type,
newnary.op[0],
newnary.op[1],
newnary.op[2],
newnary.op[3],
tree result = vn_nary_op_lookup_pieces (newnary->length,
newnary->opcode,
newnary->type,
&newnary->op[0],
&nary);
if (result && is_gimple_min_invariant (result))
return get_or_alloc_expr_for_constant (result);
@ -1507,13 +1502,10 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
VEC_safe_grow_cleared (bitmap_set_t, heap,
value_expressions,
get_max_value_id() + 1);
nary = vn_nary_op_insert_pieces (newnary.length,
newnary.opcode,
newnary.type,
newnary.op[0],
newnary.op[1],
newnary.op[2],
newnary.op[3],
nary = vn_nary_op_insert_pieces (newnary->length,
newnary->opcode,
newnary->type,
&newnary->op[0],
result, new_val_id);
PRE_EXPR_NARY (expr) = nary;
constant = fully_constant_expression (expr);
@ -1708,9 +1700,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result),
TREE_TYPE (result),
TREE_OPERAND (result, 0),
NULL_TREE, NULL_TREE,
NULL_TREE,
&TREE_OPERAND (result, 0),
&nary);
if (nresult && is_gimple_min_invariant (nresult))
return get_or_alloc_expr_for_constant (nresult);
@ -1734,9 +1724,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
get_max_value_id() + 1);
nary = vn_nary_op_insert_pieces (1, TREE_CODE (result),
TREE_TYPE (result),
TREE_OPERAND (result, 0),
NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE,
&TREE_OPERAND (result, 0),
NULL_TREE,
new_val_id);
PRE_EXPR_NARY (expr) = nary;
constant = fully_constant_expression (expr);
@ -3087,50 +3076,49 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
case NARY:
{
vn_nary_op_t nary = PRE_EXPR_NARY (expr);
switch (nary->length)
tree genop[4];
unsigned i;
for (i = 0; i < nary->length; ++i)
{
case 2:
{
pre_expr op1 = get_or_alloc_expr_for (nary->op[0]);
pre_expr op2 = get_or_alloc_expr_for (nary->op[1]);
tree genop1 = find_or_generate_expression (block, op1,
stmts, domstmt);
tree genop2 = find_or_generate_expression (block, op2,
stmts, domstmt);
if (!genop1 || !genop2)
return NULL_TREE;
/* Ensure op2 is a ptrofftype for POINTER_PLUS_EXPR. It
may be a constant with the wrong type. */
if (nary->opcode == POINTER_PLUS_EXPR)
{
genop1 = fold_convert (nary->type, genop1);
genop2 = convert_to_ptrofftype (genop2);
}
else
{
genop1 = fold_convert (TREE_TYPE (nary->op[0]), genop1);
genop2 = fold_convert (TREE_TYPE (nary->op[1]), genop2);
}
folded = fold_build2 (nary->opcode, nary->type,
genop1, genop2);
}
break;
case 1:
{
pre_expr op1 = get_or_alloc_expr_for (nary->op[0]);
tree genop1 = find_or_generate_expression (block, op1,
stmts, domstmt);
if (!genop1)
return NULL_TREE;
genop1 = fold_convert (TREE_TYPE (nary->op[0]), genop1);
folded = fold_build1 (nary->opcode, nary->type,
genop1);
}
break;
default:
return NULL_TREE;
pre_expr op = get_or_alloc_expr_for (nary->op[i]);
genop[i] = find_or_generate_expression (block, op,
stmts, domstmt);
if (!genop[i])
return NULL_TREE;
/* Ensure genop[1] is a ptrofftype for POINTER_PLUS_EXPR. It
may be a constant with the wrong type. */
if (i == 1
&& nary->opcode == POINTER_PLUS_EXPR)
genop[i] = convert_to_ptrofftype (genop[i]);
else
genop[i] = fold_convert (TREE_TYPE (nary->op[i]), genop[i]);
}
if (nary->opcode == CONSTRUCTOR)
{
VEC(constructor_elt,gc) *elts = NULL;
for (i = 0; i < nary->length; ++i)
CONSTRUCTOR_APPEND_ELT (elts, NULL_TREE, genop[i]);
folded = build_constructor (nary->type, elts);
}
else
{
switch (nary->length)
{
case 1:
folded = fold_build1 (nary->opcode, nary->type,
genop[0]);
break;
case 2:
folded = fold_build2 (nary->opcode, nary->type,
genop[0], genop[1]);
break;
case 3:
folded = fold_build3 (nary->opcode, nary->type,
genop[0], genop[1], genop[3]);
break;
default:
gcc_unreachable ();
}
}
}
break;
@ -4053,9 +4041,8 @@ compute_avail (void)
vn_nary_op_lookup_pieces (gimple_num_ops (stmt) - 1,
gimple_assign_rhs_code (stmt),
gimple_expr_type (stmt),
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt),
NULL_TREE, NULL_TREE, &nary);
gimple_assign_rhs1_ptr (stmt),
&nary);
if (!nary)
continue;

View File

@ -1923,6 +1923,9 @@ vn_nary_op_eq (const void *p1, const void *p2)
if (vno1->hashcode != vno2->hashcode)
return false;
if (vno1->length != vno2->length)
return false;
if (vno1->opcode != vno2->opcode
|| !types_compatible_p (vno1->type, vno2->type))
return false;
@ -1938,22 +1941,12 @@ vn_nary_op_eq (const void *p1, const void *p2)
static void
init_vn_nary_op_from_pieces (vn_nary_op_t vno, unsigned int length,
enum tree_code code, tree type, tree op0,
tree op1, tree op2, tree op3)
enum tree_code code, tree type, tree *ops)
{
vno->opcode = code;
vno->length = length;
vno->type = type;
switch (length)
{
/* The fallthrus here are deliberate. */
case 4: vno->op[3] = op3;
case 3: vno->op[2] = op2;
case 2: vno->op[1] = op1;
case 1: vno->op[0] = op0;
default:
break;
}
memcpy (&vno->op[0], ops, sizeof (tree) * length);
}
/* Initialize VNO from OP. */
@ -1970,6 +1963,26 @@ init_vn_nary_op_from_op (vn_nary_op_t vno, tree op)
vno->op[i] = TREE_OPERAND (op, i);
}
/* Return the number of operands for a vn_nary ops structure from STMT. */
static unsigned int
vn_nary_length_from_stmt (gimple stmt)
{
switch (gimple_assign_rhs_code (stmt))
{
case REALPART_EXPR:
case IMAGPART_EXPR:
case VIEW_CONVERT_EXPR:
return 1;
case CONSTRUCTOR:
return CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
default:
return gimple_num_ops (stmt) - 1;
}
}
/* Initialize VNO from STMT. */
static void
@ -1978,14 +1991,27 @@ init_vn_nary_op_from_stmt (vn_nary_op_t vno, gimple stmt)
unsigned i;
vno->opcode = gimple_assign_rhs_code (stmt);
vno->length = gimple_num_ops (stmt) - 1;
vno->type = gimple_expr_type (stmt);
for (i = 0; i < vno->length; ++i)
vno->op[i] = gimple_op (stmt, i + 1);
if (vno->opcode == REALPART_EXPR
|| vno->opcode == IMAGPART_EXPR
|| vno->opcode == VIEW_CONVERT_EXPR)
vno->op[0] = TREE_OPERAND (vno->op[0], 0);
switch (vno->opcode)
{
case REALPART_EXPR:
case IMAGPART_EXPR:
case VIEW_CONVERT_EXPR:
vno->length = 1;
vno->op[0] = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
break;
case CONSTRUCTOR:
vno->length = CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt));
for (i = 0; i < vno->length; ++i)
vno->op[i] = CONSTRUCTOR_ELT (gimple_assign_rhs1 (stmt), i)->value;
break;
default:
vno->length = gimple_num_ops (stmt) - 1;
for (i = 0; i < vno->length; ++i)
vno->op[i] = gimple_op (stmt, i + 1);
}
}
/* Compute the hashcode for VNO and look for it in the hash table;
@ -2023,12 +2049,12 @@ vn_nary_op_lookup_1 (vn_nary_op_t vno, vn_nary_op_t *vnresult)
tree
vn_nary_op_lookup_pieces (unsigned int length, enum tree_code code,
tree type, tree op0, tree op1, tree op2,
tree op3, vn_nary_op_t *vnresult)
tree type, tree *ops, vn_nary_op_t *vnresult)
{
struct vn_nary_op_s vno1;
init_vn_nary_op_from_pieces (&vno1, length, code, type, op0, op1, op2, op3);
return vn_nary_op_lookup_1 (&vno1, vnresult);
vn_nary_op_t vno1 = XALLOCAVAR (struct vn_nary_op_s,
sizeof_vn_nary_op (length));
init_vn_nary_op_from_pieces (vno1, length, code, type, ops);
return vn_nary_op_lookup_1 (vno1, vnresult);
}
/* Lookup OP in the current hash table, and return the resulting value
@ -2040,9 +2066,11 @@ vn_nary_op_lookup_pieces (unsigned int length, enum tree_code code,
tree
vn_nary_op_lookup (tree op, vn_nary_op_t *vnresult)
{
struct vn_nary_op_s vno1;
init_vn_nary_op_from_op (&vno1, op);
return vn_nary_op_lookup_1 (&vno1, vnresult);
vn_nary_op_t vno1
= XALLOCAVAR (struct vn_nary_op_s,
sizeof_vn_nary_op (TREE_CODE_LENGTH (TREE_CODE (op))));
init_vn_nary_op_from_op (vno1, op);
return vn_nary_op_lookup_1 (vno1, vnresult);
}
/* Lookup the rhs of STMT in the current hash table, and return the resulting
@ -2053,17 +2081,11 @@ vn_nary_op_lookup (tree op, vn_nary_op_t *vnresult)
tree
vn_nary_op_lookup_stmt (gimple stmt, vn_nary_op_t *vnresult)
{
struct vn_nary_op_s vno1;
init_vn_nary_op_from_stmt (&vno1, stmt);
return vn_nary_op_lookup_1 (&vno1, vnresult);
}
/* Return the size of a vn_nary_op_t with LENGTH operands. */
static size_t
sizeof_vn_nary_op (unsigned int length)
{
return sizeof (struct vn_nary_op_s) - sizeof (tree) * (4 - length);
vn_nary_op_t vno1
= XALLOCAVAR (struct vn_nary_op_s,
sizeof_vn_nary_op (vn_nary_length_from_stmt (stmt)));
init_vn_nary_op_from_stmt (vno1, stmt);
return vn_nary_op_lookup_1 (vno1, vnresult);
}
/* Allocate a vn_nary_op_t with LENGTH operands on STACK. */
@ -2114,15 +2136,11 @@ vn_nary_op_insert_into (vn_nary_op_t vno, htab_t table, bool compute_hash)
vn_nary_op_t
vn_nary_op_insert_pieces (unsigned int length, enum tree_code code,
tree type, tree op0,
tree op1, tree op2, tree op3,
tree result,
unsigned int value_id)
tree type, tree *ops,
tree result, unsigned int value_id)
{
vn_nary_op_t vno1;
vno1 = alloc_vn_nary_op (length, result, value_id);
init_vn_nary_op_from_pieces (vno1, length, code, type, op0, op1, op2, op3);
vn_nary_op_t vno1 = alloc_vn_nary_op (length, result, value_id);
init_vn_nary_op_from_pieces (vno1, length, code, type, ops);
return vn_nary_op_insert_into (vno1, current_info->nary, true);
}
@ -2147,10 +2165,9 @@ vn_nary_op_insert (tree op, tree result)
vn_nary_op_t
vn_nary_op_insert_stmt (gimple stmt, tree result)
{
unsigned length = gimple_num_ops (stmt) - 1;
vn_nary_op_t vno1;
vno1 = alloc_vn_nary_op (length, result, VN_INFO (result)->value_id);
vn_nary_op_t vno1
= alloc_vn_nary_op (vn_nary_length_from_stmt (stmt),
result, VN_INFO (result)->value_id);
init_vn_nary_op_from_stmt (vno1, stmt);
return vn_nary_op_insert_into (vno1, current_info->nary, true);
}
@ -3171,14 +3188,17 @@ visit_use (tree use)
case tcc_declaration:
changed = visit_reference_op_load (lhs, rhs1, stmt);
break;
case tcc_expression:
default:
if (code == ADDR_EXPR)
{
changed = visit_nary_op (lhs, stmt);
break;
}
/* Fallthrough. */
default:
else if (code == CONSTRUCTOR)
{
changed = visit_nary_op (lhs, stmt);
break;
}
changed = defs_to_varying (stmt);
}
break;

View File

@ -42,10 +42,18 @@ typedef struct vn_nary_op_s
hashval_t hashcode;
tree result;
tree type;
tree op[4];
tree op[1];
} *vn_nary_op_t;
typedef const struct vn_nary_op_s *const_vn_nary_op_t;
/* Return the size of a vn_nary_op_t with LENGTH operands. */
static inline size_t
sizeof_vn_nary_op (unsigned int length)
{
return sizeof (struct vn_nary_op_s) + sizeof (tree) * (length - 1);
}
/* Phi nodes in the hashtable consist of their non-VN_TOP phi
arguments, and the basic block the phi is in. Result is the value
number of the operation, and hashcode is stored to avoid having to
@ -176,13 +184,11 @@ void free_scc_vn (void);
tree vn_nary_op_lookup (tree, vn_nary_op_t *);
tree vn_nary_op_lookup_stmt (gimple, vn_nary_op_t *);
tree vn_nary_op_lookup_pieces (unsigned int, enum tree_code,
tree, tree, tree, tree, tree,
vn_nary_op_t *);
tree, tree *, vn_nary_op_t *);
vn_nary_op_t vn_nary_op_insert (tree, tree);
vn_nary_op_t vn_nary_op_insert_stmt (gimple, tree);
vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
tree, tree, tree, tree,
tree, tree, unsigned int);
tree, tree *, tree, unsigned int);
void vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **,
unsigned int *);
void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);