2012-11-28 Marc Glisse <marc.glisse@inria.fr>
authorglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Nov 2012 10:11:27 +0000 (10:11 +0000)
committerglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Nov 2012 10:11:27 +0000 (10:11 +0000)
PR middle-end/55266
* fold-const.c (fold_ternary_loc) [BIT_FIELD_REF]: Handle
CONSTRUCTOR with vector elements.
* tree-ssa-propagate.c (valid_gimple_rhs_p): Handle CONSTRUCTOR
and BIT_FIELD_REF.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@193884 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/tree-ssa-propagate.c

index b1a4afb..a15b5ef 100644 (file)
@@ -1,3 +1,11 @@
+2012-11-28  Marc Glisse  <marc.glisse@inria.fr>
+
+       PR middle-end/55266
+       * fold-const.c (fold_ternary_loc) [BIT_FIELD_REF]: Handle
+       CONSTRUCTOR with vector elements.
+       * tree-ssa-propagate.c (valid_gimple_rhs_p): Handle CONSTRUCTOR
+       and BIT_FIELD_REF.
+
 2012-11-28  Richard Biener  <rguenther@suse.de>
 
        PR c/35634
index 98ef84f..e4693cd 100644 (file)
@@ -14081,52 +14081,62 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
            {
              idx = idx / width;
              n = n / width;
-             if (TREE_CODE (type) == VECTOR_TYPE)
+
+             if (TREE_CODE (arg0) == VECTOR_CST)
                {
-                 if (TREE_CODE (arg0) == VECTOR_CST)
-                   {
-                     tree *vals = XALLOCAVEC (tree, n);
-                     unsigned i;
-                     for (i = 0; i < n; ++i)
-                       vals[i] = VECTOR_CST_ELT (arg0, idx + i);
-                     return build_vector (type, vals);
-                   }
-                 else
-                   {
-                     vec<constructor_elt, va_gc> *vals;
-                     unsigned i;
-                     if (CONSTRUCTOR_NELTS (arg0) == 0)
-                       return build_constructor (type,
-                                             NULL);
-                     if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
-                                                                0)->value))
-                         != VECTOR_TYPE)
-                       {
-                         vec_alloc (vals, n);
-                         for (i = 0;
-                              i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
-                              ++i)
-                           CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
-                                                   CONSTRUCTOR_ELT
-                                                     (arg0, idx + i)->value);
-                         return build_constructor (type, vals);
-                       }
-                   }
+                 if (n == 1)
+                   return VECTOR_CST_ELT (arg0, idx);
+
+                 tree *vals = XALLOCAVEC (tree, n);
+                 for (unsigned i = 0; i < n; ++i)
+                   vals[i] = VECTOR_CST_ELT (arg0, idx + i);
+                 return build_vector (type, vals);
                }
-             else if (n == 1)
+
+             /* Constructor elements can be subvectors.  */
+             unsigned HOST_WIDE_INT k = 1;
+             if (CONSTRUCTOR_NELTS (arg0) != 0)
                {
-                 if (TREE_CODE (arg0) == VECTOR_CST)
-                   return VECTOR_CST_ELT (arg0, idx);
-                 else if (CONSTRUCTOR_NELTS (arg0) == 0)
-                   return build_zero_cst (type);
-                 else if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
-                                                                 0)->value))
-                          != VECTOR_TYPE)
+                 tree cons_elem = TREE_TYPE (CONSTRUCTOR_ELT (arg0, 0)->value);
+                 if (TREE_CODE (cons_elem) == VECTOR_TYPE)
+                   k = TYPE_VECTOR_SUBPARTS (cons_elem);
+               }
+
+             /* We keep an exact subset of the constructor elements.  */
+             if ((idx % k) == 0 && (n % k) == 0)
+               {
+                 if (CONSTRUCTOR_NELTS (arg0) == 0)
+                   return build_constructor (type, NULL);
+                 idx /= k;
+                 n /= k;
+                 if (n == 1)
                    {
                      if (idx < CONSTRUCTOR_NELTS (arg0))
                        return CONSTRUCTOR_ELT (arg0, idx)->value;
                      return build_zero_cst (type);
                    }
+
+                 vec<constructor_elt, va_gc> *vals;
+                 vec_alloc (vals, n);
+                 for (unsigned i = 0;
+                      i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
+                      ++i)
+                   CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
+                                           CONSTRUCTOR_ELT
+                                             (arg0, idx + i)->value);
+                 return build_constructor (type, vals);
+               }
+             /* The bitfield references a single constructor element.  */
+             else if (idx + n <= (idx / k + 1) * k)
+               {
+                 if (CONSTRUCTOR_NELTS (arg0) <= idx / k)
+                   return build_zero_cst (type);
+                 else if (n == k)
+                   return CONSTRUCTOR_ELT (arg0, idx / k)->value;
+                 else
+                   return fold_build3_loc (loc, code, type,
+                     CONSTRUCTOR_ELT (arg0, idx / k)->value, op1,
+                     build_int_cst (TREE_TYPE (op2), (idx % k) * width));
                }
            }
        }
index 2203b66..a959ea7 100644 (file)
@@ -611,10 +611,24 @@ valid_gimple_rhs_p (tree expr)
       return false;
 
     case tcc_exceptional:
+      if (code == CONSTRUCTOR)
+       {
+         unsigned i;
+         tree elt;
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, elt)
+           if (!is_gimple_val (elt))
+             return false;
+         return true;
+       }
       if (code != SSA_NAME)
         return false;
       break;
 
+    case tcc_reference:
+      if (code == BIT_FIELD_REF)
+       return is_gimple_val (TREE_OPERAND (expr, 0));
+      return false;
+
     default:
       return false;
     }