On Thu, 29 Oct 2015, Richard Biener wrote:

> 
> After
> 
> Index: gcc/gimple-fold.c
> ===================================================================
> --- gcc/gimple-fold.c   (revision 229518)
> +++ gcc/gimple-fold.c   (working copy)
> @@ -398,7 +398,10 @@ fold_gimple_assign (gimple_stmt_iterator
>          /* If we couldn't fold the RHS, hand over to the generic
>             fold routines.  */
>          if (result == NULL_TREE)
> -          result = fold (rhs);
> +         {
> +           result = fold (rhs);
> +           gcc_assert (result == rhs);
> +         }
>  
>          /* Strip away useless type conversions.  Both the NON_LVALUE_EXPR
>             that may have been added by fold, and "useless" type
> 
> passed bootstrap and regtest on x86_64-unknown-linux-gnu I am now
> testing the following.

The following is what I ended up applying.

Bootstrapped & tested on x86_64-unknown-linux-gnu.

Richard.

2015-10-30  Richard Biener  <rguent...@suse.de>

        * gimple-fold.c (fold_gimple_assign): Do not dispatch to
        fold () on single RHSs.  Allow CONSTRUCTORS with trailing
        zeros to be folded to VECTOR_CSTs.
        * tree.c (build_vector_from_ctor): Handle VECTOR_CST elements.
        * fold-const.c (fold): Use build_vector_from_ctor.

Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c   (revision 229520)
--- gcc/gimple-fold.c   (working copy)
*************** fold_gimple_assign (gimple_stmt_iterator
*** 355,362 ****
                    return val;
                  }
              }
- 
          }
        else if (TREE_CODE (rhs) == ADDR_EXPR)
          {
            tree ref = TREE_OPERAND (rhs, 0);
--- 355,362 ----
                    return val;
                  }
              }
          }
+ 
        else if (TREE_CODE (rhs) == ADDR_EXPR)
          {
            tree ref = TREE_OPERAND (rhs, 0);
*************** fold_gimple_assign (gimple_stmt_iterator
*** 371,391 ****
            else if (TREE_CODE (ref) == MEM_REF
                     && integer_zerop (TREE_OPERAND (ref, 1)))
              result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (ref, 0));
          }
  
        else if (TREE_CODE (rhs) == CONSTRUCTOR
!                && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
!                && (CONSTRUCTOR_NELTS (rhs)
!                    == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
          {
            /* Fold a constant vector CONSTRUCTOR to VECTOR_CST.  */
            unsigned i;
            tree val;
  
            FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
!             if (TREE_CODE (val) != INTEGER_CST
!                 && TREE_CODE (val) != REAL_CST
!                 && TREE_CODE (val) != FIXED_CST)
                return NULL_TREE;
  
            return build_vector_from_ctor (TREE_TYPE (rhs),
--- 371,399 ----
            else if (TREE_CODE (ref) == MEM_REF
                     && integer_zerop (TREE_OPERAND (ref, 1)))
              result = fold_convert (TREE_TYPE (rhs), TREE_OPERAND (ref, 0));
+ 
+           if (result)
+             {
+               /* Strip away useless type conversions.  Both the
+                  NON_LVALUE_EXPR that may have been added by fold, and
+                  "useless" type conversions that might now be apparent
+                  due to propagation.  */
+               STRIP_USELESS_TYPE_CONVERSION (result);
+ 
+               if (result != rhs && valid_gimple_rhs_p (result))
+                 return result;
+             }
          }
  
        else if (TREE_CODE (rhs) == CONSTRUCTOR
!                && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE)
          {
            /* Fold a constant vector CONSTRUCTOR to VECTOR_CST.  */
            unsigned i;
            tree val;
  
            FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
!             if (! CONSTANT_CLASS_P (val))
                return NULL_TREE;
  
            return build_vector_from_ctor (TREE_TYPE (rhs),
*************** fold_gimple_assign (gimple_stmt_iterator
*** 394,414 ****
  
        else if (DECL_P (rhs))
          return get_symbol_constant_value (rhs);
- 
-         /* If we couldn't fold the RHS, hand over to the generic
-            fold routines.  */
-         if (result == NULL_TREE)
-           result = fold (rhs);
- 
-         /* Strip away useless type conversions.  Both the NON_LVALUE_EXPR
-            that may have been added by fold, and "useless" type
-            conversions that might now be apparent due to propagation.  */
-         STRIP_USELESS_TYPE_CONVERSION (result);
- 
-         if (result != rhs && valid_gimple_rhs_p (result))
-         return result;
- 
-       return NULL_TREE;
        }
        break;
  
--- 402,407 ----
Index: gcc/tree.c
===================================================================
*** gcc/tree.c  (revision 229520)
--- gcc/tree.c  (working copy)
*************** tree
*** 1730,1742 ****
  build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
  {
    tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
!   unsigned HOST_WIDE_INT idx;
    tree value;
  
    FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
!     vec[idx] = value;
    for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
!     vec[idx] = build_zero_cst (TREE_TYPE (type));
  
    return build_vector (type, vec);
  }
--- 1730,1748 ----
  build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
  {
    tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
!   unsigned HOST_WIDE_INT idx, pos = 0;
    tree value;
  
    FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
!     {
!       if (TREE_CODE (value) == VECTOR_CST)
!       for (unsigned i = 0; i < VECTOR_CST_NELTS (value); ++i)
!         vec[pos++] = VECTOR_CST_ELT (value, i);
!       else
!       vec[pos++] = value;
!     }
    for (; idx < TYPE_VECTOR_SUBPARTS (type); ++idx)
!     vec[pos++] = build_zero_cst (TREE_TYPE (type));
  
    return build_vector (type, vec);
  }
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 229520)
--- gcc/fold-const.c    (working copy)
*************** fold (tree expr)
*** 11960,11985 ****
        if (TREE_CODE (type) != VECTOR_TYPE)
          return t;
  
!       tree *vec = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (type));
!       unsigned HOST_WIDE_INT idx, pos = 0;
!       tree value;
! 
!       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), idx, value)
!         {
!           if (!CONSTANT_CLASS_P (value))
!             return t;
!           if (TREE_CODE (value) == VECTOR_CST)
!             {
!               for (unsigned i = 0; i < VECTOR_CST_NELTS (value); ++i)
!                 vec[pos++] = VECTOR_CST_ELT (value, i);
!             }
!           else
!             vec[pos++] = value;
!         }
!       for (; pos < TYPE_VECTOR_SUBPARTS (type); ++pos)
!         vec[pos] = build_zero_cst (TREE_TYPE (type));
  
!       return build_vector (type, vec);
        }
  
      case CONST_DECL:
--- 11977,11989 ----
        if (TREE_CODE (type) != VECTOR_TYPE)
          return t;
  
!       unsigned i;
!       tree val;
!       FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, val)
!         if (! CONSTANT_CLASS_P (val))
!           return t;
  
!       return build_vector_from_ctor (type, CONSTRUCTOR_ELTS (t));
        }
  
      case CONST_DECL:

Reply via email to