From: Richard Guenther Date: Tue, 6 Sep 2011 13:17:50 +0000 (+0000) Subject: re PR tree-optimization/48317 (SCCVN does not handle vector constructors) X-Git-Tag: releases/gcc-4.7.0~3908 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5a7d7f9cf3bc2cacd798cae88a3de28bd1d7259d;p=thirdparty%2Fgcc.git re PR tree-optimization/48317 (SCCVN does not handle vector constructors) 2011-09-06 Richard Guenther 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb1fbec74973..0a59a05fd1d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2011-09-06 Richard Guenther + + 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 * config/arm/arm.c (arm_preferred_simd_mode): Check diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 79749668203c..d22fe495d15b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-09-06 Richard Guenther + + PR tree-optimization/48317 + * gcc.dg/tree-ssa/ssa-fre-31.c: New testcase. + 2011-09-06 Ira Rosen * lib/target-supports.exp (check_effective_target_vect_multiple_sizes): diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c new file mode 100644 index 000000000000..42257cca5ad4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c @@ -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" } } */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 6f3b03b3f98f..f69aec0dd4d0 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -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; diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index e0d4ca9561c9..aeb2e0831417 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -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; diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index bf99702e43ad..97d7f8f39213 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -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) **);