We currently lack support for vector CONSTRUCTORs in value-numbering
(yes, and vector component selection as well, but that's a different 
story...).

The following implements this by treating vector CONSTRUCTOR as nary
ops.  With quite some infrastructure adjustments to support
(sort-of arbitrary) sized narys instead of a maximum number of 4
ops as it is now.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2011-09-06  Richard Guenther  <rguent...@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.

Index: trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
===================================================================
*** /dev/null   1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c    2011-09-06 
12:55:03.000000000 +0200
***************
*** 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" } } */
Index: trunk/gcc/tree-ssa-pre.c
===================================================================
*** trunk.orig/gcc/tree-ssa-pre.c       2011-09-06 12:28:12.000000000 +0200
--- trunk/gcc/tree-ssa-pre.c    2011-09-06 13:32:35.000000000 +0200
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1443,1462 ****
        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)));
  
!       for (i = 0; i < newnary.length; i++)
          {
!           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;
                leader = find_leader_in_sets (op_val_id, set1, set2);
                  result = phi_translate (leader, set1, set2, pred, phiblock);
                if (result && result != leader)
--- 1443,1460 ----
        unsigned int i;
        bool changed = false;
        vn_nary_op_t nary = PRE_EXPR_NARY (expr);
!       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++)
          {
!           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;
                leader = find_leader_in_sets (op_val_id, set1, set2);
                  result = phi_translate (leader, set1, set2, pred, phiblock);
                if (result && result != leader)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1464,1475 ****
                    tree name = get_representative_for (result);
                    if (!name)
                      return NULL;
!                   newnary.op[i] = name;
                  }
                else if (!result)
                  return NULL;
  
!               changed |= newnary.op[i] != nary->op[i];
              }
          }
        if (changed)
--- 1462,1473 ----
                    tree name = get_representative_for (result);
                    if (!name)
                      return NULL;
!                   newnary->op[i] = name;
                  }
                else if (!result)
                  return NULL;
  
!               changed |= newnary->op[i] != nary->op[i];
              }
          }
        if (changed)
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1477,1489 ****
            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],
                                                    &nary);
            if (result && is_gimple_min_invariant (result))
              return get_or_alloc_expr_for_constant (result);
--- 1475,1484 ----
            pre_expr constant;
            unsigned int new_val_id;
  
!           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);
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1507,1519 ****
                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],
                                                 result, new_val_id);
                PRE_EXPR_NARY (expr) = nary;
                constant = fully_constant_expression (expr);
--- 1502,1511 ----
                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],
                                                 result, new_val_id);
                PRE_EXPR_NARY (expr) = nary;
                constant = fully_constant_expression (expr);
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1708,1716 ****
  
                nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result),
                                                    TREE_TYPE (result),
!                                                   TREE_OPERAND (result, 0),
!                                                   NULL_TREE, NULL_TREE,
!                                                   NULL_TREE,
                                                    &nary);
                if (nresult && is_gimple_min_invariant (nresult))
                  return get_or_alloc_expr_for_constant (nresult);
--- 1700,1706 ----
  
                nresult = vn_nary_op_lookup_pieces (1, TREE_CODE (result),
                                                    TREE_TYPE (result),
!                                                   &TREE_OPERAND (result, 0),
                                                    &nary);
                if (nresult && is_gimple_min_invariant (nresult))
                  return get_or_alloc_expr_for_constant (nresult);
*************** phi_translate_1 (pre_expr expr, bitmap_s
*** 1734,1742 ****
                                           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,
                                                     new_val_id);
                    PRE_EXPR_NARY (expr) = nary;
                    constant = fully_constant_expression (expr);
--- 1724,1731 ----
                                           get_max_value_id() + 1);
                    nary = vn_nary_op_insert_pieces (1, TREE_CODE (result),
                                                     TREE_TYPE (result),
!                                                    &TREE_OPERAND (result, 0),
!                                                    NULL_TREE,
                                                     new_val_id);
                    PRE_EXPR_NARY (expr) = nary;
                    constant = fully_constant_expression (expr);
*************** create_expression_by_pieces (basic_block
*** 3087,3136 ****
      case NARY:
        {
        vn_nary_op_t nary = PRE_EXPR_NARY (expr);
!       switch (nary->length)
          {
!         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;
          }
        }
        break;
--- 3076,3124 ----
      case NARY:
        {
        vn_nary_op_t nary = PRE_EXPR_NARY (expr);
!       tree genop[4];
!       unsigned i;
!       for (i = 0; i < nary->length; ++i)
!         {
!           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;
*************** compute_avail (void)
*** 4053,4061 ****
                      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);
  
                      if (!nary)
                        continue;
--- 4041,4048 ----
                      vn_nary_op_lookup_pieces (gimple_num_ops (stmt) - 1,
                                                gimple_assign_rhs_code (stmt),
                                                gimple_expr_type (stmt),
!                                               gimple_assign_rhs1_ptr (stmt),
!                                               &nary);
  
                      if (!nary)
                        continue;
Index: trunk/gcc/tree-ssa-sccvn.c
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.c     2011-09-06 12:28:12.000000000 +0200
--- trunk/gcc/tree-ssa-sccvn.c  2011-09-06 13:50:39.000000000 +0200
*************** vn_nary_op_eq (const void *p1, const voi
*** 1923,1928 ****
--- 1923,1931 ----
    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;
*************** vn_nary_op_eq (const void *p1, const voi
*** 1938,1959 ****
  
  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)
  {
    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;
!     }
  }
  
  /* Initialize VNO from OP.  */
--- 1941,1952 ----
  
  static void
  init_vn_nary_op_from_pieces (vn_nary_op_t vno, unsigned int length,
!                            enum tree_code code, tree type, tree *ops)
  {
    vno->opcode = code;
    vno->length = length;
    vno->type = type;
!   memcpy (&vno->op[0], ops, sizeof (tree) * length);
  }
  
  /* Initialize VNO from OP.  */
*************** init_vn_nary_op_from_op (vn_nary_op_t vn
*** 1970,1975 ****
--- 1963,1988 ----
      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
*************** init_vn_nary_op_from_stmt (vn_nary_op_t
*** 1978,1991 ****
    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);
  }
  
  /* Compute the hashcode for VNO and look for it in the hash table;
--- 1991,2017 ----
    unsigned i;
  
    vno->opcode = gimple_assign_rhs_code (stmt);
    vno->type = gimple_expr_type (stmt);
!   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;
*************** vn_nary_op_lookup_1 (vn_nary_op_t vno, v
*** 2023,2034 ****
  
  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)
  {
!   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);
  }
  
  /* Lookup OP in the current hash table, and return the resulting value
--- 2049,2060 ----
  
  tree
  vn_nary_op_lookup_pieces (unsigned int length, enum tree_code code,
!                         tree type, tree *ops, vn_nary_op_t *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
*************** vn_nary_op_lookup_pieces (unsigned int l
*** 2040,2048 ****
  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);
  }
  
  /* Lookup the rhs of STMT in the current hash table, and return the resulting
--- 2066,2076 ----
  tree
  vn_nary_op_lookup (tree op, vn_nary_op_t *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
*************** vn_nary_op_lookup (tree op, vn_nary_op_t
*** 2053,2069 ****
  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);
  }
  
  /* Allocate a vn_nary_op_t with LENGTH operands on STACK.  */
--- 2081,2091 ----
  tree
  vn_nary_op_lookup_stmt (gimple stmt, vn_nary_op_t *vnresult)
  {
!   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.  */
*************** vn_nary_op_insert_into (vn_nary_op_t vno
*** 2114,2128 ****
  
  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)
  {
!   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);
    return vn_nary_op_insert_into (vno1, current_info->nary, true);
  }
  
--- 2136,2146 ----
  
  vn_nary_op_t
  vn_nary_op_insert_pieces (unsigned int length, enum tree_code code,
!                         tree type, tree *ops,
!                         tree result, unsigned int value_id)
  {
!   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);
  }
  
*************** vn_nary_op_insert (tree op, tree result)
*** 2147,2156 ****
  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);
    init_vn_nary_op_from_stmt (vno1, stmt);
    return vn_nary_op_insert_into (vno1, current_info->nary, true);
  }
--- 2165,2173 ----
  vn_nary_op_t
  vn_nary_op_insert_stmt (gimple stmt, tree result)
  {
!   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);
  }
*************** visit_use (tree use)
*** 3171,3184 ****
                        case tcc_declaration:
                          changed = visit_reference_op_load (lhs, rhs1, stmt);
                          break;
!                       case tcc_expression:
                          if (code == ADDR_EXPR)
                            {
                              changed = visit_nary_op (lhs, stmt);
                              break;
                            }
!                         /* Fallthrough.  */
!                       default:
                          changed = defs_to_varying (stmt);
                        }
                      break;
--- 3188,3204 ----
                        case tcc_declaration:
                          changed = visit_reference_op_load (lhs, rhs1, stmt);
                          break;
!                       default:
                          if (code == ADDR_EXPR)
                            {
                              changed = visit_nary_op (lhs, stmt);
                              break;
                            }
!                         else if (code == CONSTRUCTOR)
!                           {
!                             changed = visit_nary_op (lhs, stmt);
!                             break;
!                           }
                          changed = defs_to_varying (stmt);
                        }
                      break;
Index: trunk/gcc/tree-ssa-sccvn.h
===================================================================
*** trunk.orig/gcc/tree-ssa-sccvn.h     2011-02-07 15:57:24.000000000 +0100
--- trunk/gcc/tree-ssa-sccvn.h  2011-09-06 13:36:58.000000000 +0200
*************** typedef struct vn_nary_op_s
*** 42,51 ****
    hashval_t hashcode;
    tree result;
    tree type;
!   tree op[4];
  } *vn_nary_op_t;
  typedef const struct vn_nary_op_s *const_vn_nary_op_t;
  
  /* 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
--- 42,59 ----
    hashval_t hashcode;
    tree result;
    tree type;
!   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
*************** void free_scc_vn (void);
*** 176,188 ****
  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 *);
  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);
  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) **);
--- 184,194 ----
  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 *, 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, 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) **);

Reply via email to