Make more use of VECTOR_CST_ENCODED_ELT

Message ID 87mv2v98qj.fsf_-_@linaro.org
State New
Headers show
Series
  • Make more use of VECTOR_CST_ENCODED_ELT
Related show

Commit Message

Richard Sandiford Dec. 6, 2017, 3:28 p.m.
This patch makes various bits of code operate directly on the new
VECTOR_CST encoding, instead of using VECTOR_CST_ELT on all elements
of the vector.

Previous patches handled operations that produce a new VECTOR_CST,
while this patch handles things like predicates.  It also makes
print_node dump the encoding instead of the full vector that
the encoding represents.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also spot-checked on sparc64-linux-gnu.  OK to install?

Thanks,
Richard


2017-12-06  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* tree-vector-builder.h
	(tree_vector_builder::binary_encoded_nelts): Declare.
	* tree-vector-builder.c
	(tree_vector_builder::binary_encoded_nelts): New function.
	* fold-const.c (negate_expr_p): Likewise.
	(operand_equal_p, fold_checksum_tree): Likewise.
	* tree-loop-distribution.c (const_with_all_bytes_same): Likewise.
	* tree.c (integer_zerop, integer_onep, integer_all_onesp, real_zerop)
	(real_onep, real_minus_onep, add_expr, initializer_zerop): Likewise.
	(uniform_vector_p): Likewise.
	* varasm.c (const_hash_1, compare_constant): Likewise.
	* tree-ssa-ccp.c: Include tree-vector-builder.h.
	(valid_lattice_transition): Operate directly on the VECTOR_CST
	encoding.
	* ipa-icf.c: Include tree-vector-builder.h.
	(sem_variable::equals): Operate directly on the VECTOR_CST encoding.
	* print-tree.c (print_node): Print encoding of VECTOR_CSTs.

Comments

Richard Biener Dec. 7, 2017, 11:12 a.m. | #1
On Wed, Dec 6, 2017 at 4:28 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes various bits of code operate directly on the new

> VECTOR_CST encoding, instead of using VECTOR_CST_ELT on all elements

> of the vector.

>

> Previous patches handled operations that produce a new VECTOR_CST,

> while this patch handles things like predicates.  It also makes

> print_node dump the encoding instead of the full vector that

> the encoding represents.

>

> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.

> Also spot-checked on sparc64-linux-gnu.  OK to install?


Ok.

Richard.

> Thanks,

> Richard

>

>

> 2017-12-06  Richard Sandiford  <richard.sandiford@linaro.org>

>

> gcc/

>         * tree-vector-builder.h

>         (tree_vector_builder::binary_encoded_nelts): Declare.

>         * tree-vector-builder.c

>         (tree_vector_builder::binary_encoded_nelts): New function.

>         * fold-const.c (negate_expr_p): Likewise.

>         (operand_equal_p, fold_checksum_tree): Likewise.

>         * tree-loop-distribution.c (const_with_all_bytes_same): Likewise.

>         * tree.c (integer_zerop, integer_onep, integer_all_onesp, real_zerop)

>         (real_onep, real_minus_onep, add_expr, initializer_zerop): Likewise.

>         (uniform_vector_p): Likewise.

>         * varasm.c (const_hash_1, compare_constant): Likewise.

>         * tree-ssa-ccp.c: Include tree-vector-builder.h.

>         (valid_lattice_transition): Operate directly on the VECTOR_CST

>         encoding.

>         * ipa-icf.c: Include tree-vector-builder.h.

>         (sem_variable::equals): Operate directly on the VECTOR_CST encoding.

>         * print-tree.c (print_node): Print encoding of VECTOR_CSTs.

>

> Index: gcc/tree-vector-builder.h

> ===================================================================

> --- gcc/tree-vector-builder.h   2017-12-06 14:49:04.289693414 +0000

> +++ gcc/tree-vector-builder.h   2017-12-06 14:50:45.559564436 +0000

> @@ -40,6 +40,8 @@ #define GCC_TREE_VECTOR_BUILDER_H

>    bool new_unary_operation (tree, tree, bool);

>    bool new_binary_operation (tree, tree, tree, bool);

>

> +  static unsigned int binary_encoded_nelts (tree, tree);

> +

>  private:

>    bool equal_p (const_tree, const_tree) const;

>    bool allow_steps_p () const;

> Index: gcc/tree-vector-builder.c

> ===================================================================

> --- gcc/tree-vector-builder.c   2017-12-06 14:49:04.289693414 +0000

> +++ gcc/tree-vector-builder.c   2017-12-06 14:50:45.558564477 +0000

> @@ -96,6 +96,24 @@ tree_vector_builder::new_binary_operatio

>    return true;

>  }

>

> +/* Return the number of elements that the caller needs to operate on in

> +   order to handle a binary operation on VECTOR_CSTs T1 and T2.  This static

> +   function is used instead of new_binary_operation if the result of the

> +   operation is not a VECTOR_CST.  */

> +

> +unsigned int

> +tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)

> +{

> +  unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));

> +  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)));

> +  /* See new_binary_operation for details.  */

> +  unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),

> +                                                 VECTOR_CST_NPATTERNS (t2));

> +  unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),

> +                                       VECTOR_CST_NELTS_PER_PATTERN (t2));

> +  return MIN (npatterns * nelts_per_pattern, nelts);

> +}

> +

>  /* Return a vector element with the value BASE + FACTOR * STEP.  */

>

>  tree

> Index: gcc/fold-const.c

> ===================================================================

> --- gcc/fold-const.c    2017-12-06 14:49:00.386854068 +0000

> +++ gcc/fold-const.c    2017-12-06 14:50:45.557564518 +0000

> @@ -410,10 +410,10 @@ negate_expr_p (tree t)

>         if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))

>           return true;

>

> -       int count = VECTOR_CST_NELTS (t), i;

> -

> -       for (i = 0; i < count; i++)

> -         if (!negate_expr_p (VECTOR_CST_ELT (t, i)))

> +       /* Steps don't prevent negation.  */

> +       unsigned int count = vector_cst_encoded_nelts (t);

> +       for (unsigned int i = 0; i < count; ++i)

> +         if (!negate_expr_p (VECTOR_CST_ENCODED_ELT (t, i)))

>             return false;

>

>         return true;

> @@ -2981,17 +2981,19 @@ operand_equal_p (const_tree arg0, const_

>

>        case VECTOR_CST:

>         {

> -         unsigned i;

> +         if (VECTOR_CST_LOG2_NPATTERNS (arg0)

> +             != VECTOR_CST_LOG2_NPATTERNS (arg1))

> +           return 0;

>

> -         if (VECTOR_CST_NELTS (arg0) != VECTOR_CST_NELTS (arg1))

> +         if (VECTOR_CST_NELTS_PER_PATTERN (arg0)

> +             != VECTOR_CST_NELTS_PER_PATTERN (arg1))

>             return 0;

>

> -         for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)

> -           {

> -             if (!operand_equal_p (VECTOR_CST_ELT (arg0, i),

> -                                   VECTOR_CST_ELT (arg1, i), flags))

> -               return 0;

> -           }

> +         unsigned int count = vector_cst_encoded_nelts (arg0);

> +         for (unsigned int i = 0; i < count; ++i)

> +           if (!operand_equal_p (VECTOR_CST_ENCODED_ELT (arg0, i),

> +                                 VECTOR_CST_ENCODED_ELT (arg1, i), flags))

> +             return 0;

>           return 1;

>         }

>

> @@ -11992,8 +11994,9 @@ fold_checksum_tree (const_tree expr, str

>           fold_checksum_tree (TREE_IMAGPART (expr), ctx, ht);

>           break;

>         case VECTOR_CST:

> -         for (i = 0; i < (int) VECTOR_CST_NELTS (expr); ++i)

> -           fold_checksum_tree (VECTOR_CST_ELT (expr, i), ctx, ht);

> +         len = vector_cst_encoded_nelts (expr);

> +         for (i = 0; i < len; ++i)

> +           fold_checksum_tree (VECTOR_CST_ENCODED_ELT (expr, i), ctx, ht);

>           break;

>         default:

>           break;

> Index: gcc/tree-loop-distribution.c

> ===================================================================

> --- gcc/tree-loop-distribution.c        2017-11-29 11:06:34.810688336 +0000

> +++ gcc/tree-loop-distribution.c        2017-12-06 14:50:45.558564477 +0000

> @@ -944,13 +944,16 @@ const_with_all_bytes_same (tree val)

>             return 0;

>           break;

>         case VECTOR_CST:

> -         unsigned int j;

> -         for (j = 0; j < VECTOR_CST_NELTS (val); ++j)

> -           if (const_with_all_bytes_same (VECTOR_CST_ELT (val, j)))

> -             break;

> -         if (j == VECTOR_CST_NELTS (val))

> -           return 0;

> -         break;

> +         {

> +           unsigned int count = vector_cst_encoded_nelts (val);

> +           unsigned int j;

> +           for (j = 0; j < count; ++j)

> +             if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))

> +               break;

> +           if (j == count)

> +             return 0;

> +           break;

> +         }

>         default:

>           break;

>         }

> Index: gcc/tree.c

> ===================================================================

> --- gcc/tree.c  2017-12-06 14:49:10.295445836 +0000

> +++ gcc/tree.c  2017-12-06 14:50:45.560564396 +0000

> @@ -2338,13 +2338,9 @@ integer_zerop (const_tree expr)

>        return (integer_zerop (TREE_REALPART (expr))

>               && integer_zerop (TREE_IMAGPART (expr)));

>      case VECTOR_CST:

> -      {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -         if (!integer_zerop (VECTOR_CST_ELT (expr, i)))

> -           return false;

> -       return true;

> -      }

> +      return (VECTOR_CST_NPATTERNS (expr) == 1

> +             && VECTOR_CST_DUPLICATE_P (expr)

> +             && integer_zerop (VECTOR_CST_ENCODED_ELT (expr, 0)));

>      default:

>        return false;

>      }

> @@ -2364,13 +2360,9 @@ integer_onep (const_tree expr)

>        return (integer_onep (TREE_REALPART (expr))

>               && integer_zerop (TREE_IMAGPART (expr)));

>      case VECTOR_CST:

> -      {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -         if (!integer_onep (VECTOR_CST_ELT (expr, i)))

> -           return false;

> -       return true;

> -      }

> +      return (VECTOR_CST_NPATTERNS (expr) == 1

> +             && VECTOR_CST_DUPLICATE_P (expr)

> +             && integer_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));

>      default:

>        return false;

>      }

> @@ -2401,13 +2393,9 @@ integer_all_onesp (const_tree expr)

>      return 1;

>

>    else if (TREE_CODE (expr) == VECTOR_CST)

> -    {

> -      unsigned i;

> -      for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -       if (!integer_all_onesp (VECTOR_CST_ELT (expr, i)))

> -         return 0;

> -      return 1;

> -    }

> +    return (VECTOR_CST_NPATTERNS (expr) == 1

> +           && VECTOR_CST_DUPLICATE_P (expr)

> +           && integer_all_onesp (VECTOR_CST_ENCODED_ELT (expr, 0)));

>

>    else if (TREE_CODE (expr) != INTEGER_CST)

>      return 0;

> @@ -2630,9 +2618,11 @@ real_zerop (const_tree expr)

>              && real_zerop (TREE_IMAGPART (expr));

>      case VECTOR_CST:

>        {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -         if (!real_zerop (VECTOR_CST_ELT (expr, i)))

> +       /* Don't simply check for a duplicate because the predicate

> +          accepts both +0.0 and -0.0.  */

> +       unsigned count = vector_cst_encoded_nelts (expr);

> +       for (unsigned int i = 0; i < count; ++i)

> +         if (!real_zerop (VECTOR_CST_ENCODED_ELT (expr, i)))

>             return false;

>         return true;

>        }

> @@ -2657,13 +2647,9 @@ real_onep (const_tree expr)

>        return real_onep (TREE_REALPART (expr))

>              && real_zerop (TREE_IMAGPART (expr));

>      case VECTOR_CST:

> -      {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -         if (!real_onep (VECTOR_CST_ELT (expr, i)))

> -           return false;

> -       return true;

> -      }

> +      return (VECTOR_CST_NPATTERNS (expr) == 1

> +             && VECTOR_CST_DUPLICATE_P (expr)

> +             && real_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));

>      default:

>        return false;

>      }

> @@ -2684,13 +2670,9 @@ real_minus_onep (const_tree expr)

>        return real_minus_onep (TREE_REALPART (expr))

>              && real_zerop (TREE_IMAGPART (expr));

>      case VECTOR_CST:

> -      {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)

> -         if (!real_minus_onep (VECTOR_CST_ELT (expr, i)))

> -           return false;

> -       return true;

> -      }

> +      return (VECTOR_CST_NPATTERNS (expr) == 1

> +             && VECTOR_CST_DUPLICATE_P (expr)

> +             && real_minus_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));

>      default:

>        return false;

>      }

> @@ -7102,9 +7084,11 @@ add_expr (const_tree t, inchash::hash &h

>        return;

>      case VECTOR_CST:

>        {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (t); ++i)

> -         inchash::add_expr (VECTOR_CST_ELT (t, i), hstate, flags);

> +       hstate.add_int (VECTOR_CST_NPATTERNS (t));

> +       hstate.add_int (VECTOR_CST_NELTS_PER_PATTERN (t));

> +       unsigned int count = vector_cst_encoded_nelts (t);

> +       for (unsigned int i = 0; i < count; ++i)

> +         inchash::add_expr (VECTOR_CST_ENCODED_ELT (t, i), hstate, flags);

>         return;

>        }

>      case SSA_NAME:

> @@ -10431,13 +10415,9 @@ initializer_zerop (const_tree init)

>             && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));

>

>      case VECTOR_CST:

> -      {

> -       unsigned i;

> -       for (i = 0; i < VECTOR_CST_NELTS (init); ++i)

> -         if (!initializer_zerop (VECTOR_CST_ELT (init, i)))

> -           return false;

> -       return true;

> -      }

> +      return (VECTOR_CST_NPATTERNS (init) == 1

> +             && VECTOR_CST_DUPLICATE_P (init)

> +             && initializer_zerop (VECTOR_CST_ENCODED_ELT (init, 0)));

>

>      case CONSTRUCTOR:

>        {

> @@ -10486,12 +10466,9 @@ uniform_vector_p (const_tree vec)

>

>    if (TREE_CODE (vec) == VECTOR_CST)

>      {

> -      first = VECTOR_CST_ELT (vec, 0);

> -      for (i = 1; i < VECTOR_CST_NELTS (vec); ++i)

> -       if (!operand_equal_p (first, VECTOR_CST_ELT (vec, i), 0))

> -         return NULL_TREE;

> -

> -      return first;

> +      if (VECTOR_CST_NPATTERNS (vec) == 1 && VECTOR_CST_DUPLICATE_P (vec))

> +       return VECTOR_CST_ENCODED_ELT (vec, 0);

> +      return NULL_TREE;

>      }

>

>    else if (TREE_CODE (vec) == CONSTRUCTOR)

> Index: gcc/varasm.c

> ===================================================================

> --- gcc/varasm.c        2017-12-05 14:24:56.163946903 +0000

> +++ gcc/varasm.c        2017-12-06 14:50:45.560564396 +0000

> @@ -3007,13 +3007,11 @@ const_hash_1 (const tree exp)

>

>      case VECTOR_CST:

>        {

> -       unsigned i;

> -

> -       hi = 7 + VECTOR_CST_NELTS (exp);

> -

> -       for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)

> -         hi = hi * 563 + const_hash_1 (VECTOR_CST_ELT (exp, i));

> -

> +       hi = 7 + VECTOR_CST_NPATTERNS (exp);

> +       hi = hi * 563 + VECTOR_CST_NELTS_PER_PATTERN (exp);

> +       unsigned int count = vector_cst_encoded_nelts (exp);

> +       for (unsigned int i = 0; i < count; ++i)

> +         hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i));

>         return hi;

>        }

>

> @@ -3151,14 +3149,18 @@ compare_constant (const tree t1, const t

>

>      case VECTOR_CST:

>        {

> -       unsigned i;

> +       if (VECTOR_CST_NPATTERNS (t1)

> +           != VECTOR_CST_NPATTERNS (t2))

> +         return 0;

>

> -        if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))

> +       if (VECTOR_CST_NELTS_PER_PATTERN (t1)

> +           != VECTOR_CST_NELTS_PER_PATTERN (t2))

>           return 0;

>

> -       for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)

> -         if (!compare_constant (VECTOR_CST_ELT (t1, i),

> -                                VECTOR_CST_ELT (t2, i)))

> +       unsigned int count = vector_cst_encoded_nelts (t1);

> +       for (unsigned int i = 0; i < count; ++i)

> +         if (!compare_constant (VECTOR_CST_ENCODED_ELT (t1, i),

> +                                VECTOR_CST_ENCODED_ELT (t2, i)))

>             return 0;

>

>         return 1;

> Index: gcc/tree-ssa-ccp.c

> ===================================================================

> --- gcc/tree-ssa-ccp.c  2017-12-05 14:24:55.073967105 +0000

> +++ gcc/tree-ssa-ccp.c  2017-12-06 14:50:45.558564477 +0000

> @@ -147,6 +147,7 @@ Free Software Foundation; either version

>  #include "diagnostic-core.h"

>  #include "stringpool.h"

>  #include "attribs.h"

> +#include "tree-vector-builder.h"

>

>  /* Possible lattice values.  */

>  typedef enum

> @@ -465,11 +466,14 @@ valid_lattice_transition (ccp_prop_value

>    else if (VECTOR_FLOAT_TYPE_P (type)

>            && !HONOR_NANS (type))

>      {

> -      for (unsigned i = 0; i < VECTOR_CST_NELTS (old_val.value); ++i)

> +      unsigned int count

> +       = tree_vector_builder::binary_encoded_nelts (old_val.value,

> +                                                    new_val.value);

> +      for (unsigned int i = 0; i < count; ++i)

>         if (!REAL_VALUE_ISNAN

> -              (TREE_REAL_CST (VECTOR_CST_ELT (old_val.value, i)))

> -           && !operand_equal_p (VECTOR_CST_ELT (old_val.value, i),

> -                                VECTOR_CST_ELT (new_val.value, i), 0))

> +              (TREE_REAL_CST (VECTOR_CST_ENCODED_ELT (old_val.value, i)))

> +           && !operand_equal_p (VECTOR_CST_ENCODED_ELT (old_val.value, i),

> +                                VECTOR_CST_ENCODED_ELT (new_val.value, i), 0))

>           return false;

>        return true;

>      }

> Index: gcc/ipa-icf.c

> ===================================================================

> --- gcc/ipa-icf.c       2017-11-29 11:06:34.810688336 +0000

> +++ gcc/ipa-icf.c       2017-12-06 14:50:45.557564518 +0000

> @@ -83,6 +83,7 @@ #define INCLUDE_LIST

>  #include "ipa-icf.h"

>  #include "stor-layout.h"

>  #include "dbgcnt.h"

> +#include "tree-vector-builder.h"

>

>  using namespace ipa_icf_gimple;

>

> @@ -2024,17 +2025,17 @@ sem_variable::equals (tree t1, tree t2)

>                                                 &TREE_REAL_CST (t2)));

>      case VECTOR_CST:

>        {

> -       unsigned i;

> -

>          if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))

>            return return_false_with_msg ("VECTOR_CST nelts mismatch");

>

> -       for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)

> -         if (!sem_variable::equals (VECTOR_CST_ELT (t1, i),

> -                                    VECTOR_CST_ELT (t2, i)))

> -           return 0;

> +       unsigned int count

> +         = tree_vector_builder::binary_encoded_nelts (t1, t2);

> +       for (unsigned int i = 0; i < count; ++i)

> +         if (!sem_variable::equals (VECTOR_CST_ENCODED_ELT (t1, i),

> +                                    VECTOR_CST_ENCODED_ELT (t2, i)))

> +           return false;

>

> -       return 1;

> +       return true;

>        }

>      case ARRAY_REF:

>      case ARRAY_RANGE_REF:

> Index: gcc/print-tree.c

> ===================================================================

> --- gcc/print-tree.c    2017-11-29 11:06:34.810688336 +0000

> +++ gcc/print-tree.c    2017-12-06 14:50:45.558564477 +0000

> @@ -761,24 +761,18 @@ print_node (FILE *file, const char *pref

>

>         case VECTOR_CST:

>           {

> -           /* Big enough for 2 UINT_MAX plus the string below.  */

> +           /* Big enough for UINT_MAX plus the string below.  */

>             char buf[32];

> -           unsigned i;

>

> -           for (i = 0; i < VECTOR_CST_NELTS (node); ++i)

> +           fprintf (file, " npatterns:%u nelts-per-pattern:%u",

> +                    VECTOR_CST_NPATTERNS (node),

> +                    VECTOR_CST_NELTS_PER_PATTERN (node));

> +           unsigned int count = vector_cst_encoded_nelts (node);

> +           for (unsigned int i = 0; i < count; ++i)

>               {

> -               unsigned j;

> -               /* Coalesce the output of identical consecutive elements.  */

> -               for (j = i + 1; j < VECTOR_CST_NELTS (node); j++)

> -                 if (VECTOR_CST_ELT (node, j) != VECTOR_CST_ELT (node, i))

> -                   break;

> -               j--;

> -               if (i == j)

> -                 sprintf (buf, "elt:%u: ", i);

> -               else

> -                 sprintf (buf, "elt:%u...%u: ", i, j);

> -               print_node (file, buf, VECTOR_CST_ELT (node, i), indent + 4);

> -               i = j;

> +               sprintf (buf, "elt:%u: ", i);

> +               print_node (file, buf, VECTOR_CST_ENCODED_ELT (node, i),

> +                           indent + 4);

>               }

>           }

>           break;

Patch

Index: gcc/tree-vector-builder.h
===================================================================
--- gcc/tree-vector-builder.h	2017-12-06 14:49:04.289693414 +0000
+++ gcc/tree-vector-builder.h	2017-12-06 14:50:45.559564436 +0000
@@ -40,6 +40,8 @@  #define GCC_TREE_VECTOR_BUILDER_H
   bool new_unary_operation (tree, tree, bool);
   bool new_binary_operation (tree, tree, tree, bool);
 
+  static unsigned int binary_encoded_nelts (tree, tree);
+
 private:
   bool equal_p (const_tree, const_tree) const;
   bool allow_steps_p () const;
Index: gcc/tree-vector-builder.c
===================================================================
--- gcc/tree-vector-builder.c	2017-12-06 14:49:04.289693414 +0000
+++ gcc/tree-vector-builder.c	2017-12-06 14:50:45.558564477 +0000
@@ -96,6 +96,24 @@  tree_vector_builder::new_binary_operatio
   return true;
 }
 
+/* Return the number of elements that the caller needs to operate on in
+   order to handle a binary operation on VECTOR_CSTs T1 and T2.  This static
+   function is used instead of new_binary_operation if the result of the
+   operation is not a VECTOR_CST.  */
+
+unsigned int
+tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
+{
+  unsigned int nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));
+  gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2)));
+  /* See new_binary_operation for details.  */
+  unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
+						  VECTOR_CST_NPATTERNS (t2));
+  unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
+					VECTOR_CST_NELTS_PER_PATTERN (t2));
+  return MIN (npatterns * nelts_per_pattern, nelts);
+}
+
 /* Return a vector element with the value BASE + FACTOR * STEP.  */
 
 tree
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2017-12-06 14:49:00.386854068 +0000
+++ gcc/fold-const.c	2017-12-06 14:50:45.557564518 +0000
@@ -410,10 +410,10 @@  negate_expr_p (tree t)
 	if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))
 	  return true;
 
-	int count = VECTOR_CST_NELTS (t), i;
-
-	for (i = 0; i < count; i++)
-	  if (!negate_expr_p (VECTOR_CST_ELT (t, i)))
+	/* Steps don't prevent negation.  */
+	unsigned int count = vector_cst_encoded_nelts (t);
+	for (unsigned int i = 0; i < count; ++i)
+	  if (!negate_expr_p (VECTOR_CST_ENCODED_ELT (t, i)))
 	    return false;
 
 	return true;
@@ -2981,17 +2981,19 @@  operand_equal_p (const_tree arg0, const_
 
       case VECTOR_CST:
 	{
-	  unsigned i;
+	  if (VECTOR_CST_LOG2_NPATTERNS (arg0)
+	      != VECTOR_CST_LOG2_NPATTERNS (arg1))
+	    return 0;
 
-	  if (VECTOR_CST_NELTS (arg0) != VECTOR_CST_NELTS (arg1))
+	  if (VECTOR_CST_NELTS_PER_PATTERN (arg0)
+	      != VECTOR_CST_NELTS_PER_PATTERN (arg1))
 	    return 0;
 
-	  for (i = 0; i < VECTOR_CST_NELTS (arg0); ++i)
-	    {
-	      if (!operand_equal_p (VECTOR_CST_ELT (arg0, i),
-				    VECTOR_CST_ELT (arg1, i), flags))
-		return 0;
-	    }
+	  unsigned int count = vector_cst_encoded_nelts (arg0);
+	  for (unsigned int i = 0; i < count; ++i)
+	    if (!operand_equal_p (VECTOR_CST_ENCODED_ELT (arg0, i),
+				  VECTOR_CST_ENCODED_ELT (arg1, i), flags))
+	      return 0;
 	  return 1;
 	}
 
@@ -11992,8 +11994,9 @@  fold_checksum_tree (const_tree expr, str
 	  fold_checksum_tree (TREE_IMAGPART (expr), ctx, ht);
 	  break;
 	case VECTOR_CST:
-	  for (i = 0; i < (int) VECTOR_CST_NELTS (expr); ++i)
-	    fold_checksum_tree (VECTOR_CST_ELT (expr, i), ctx, ht);
+	  len = vector_cst_encoded_nelts (expr);
+	  for (i = 0; i < len; ++i)
+	    fold_checksum_tree (VECTOR_CST_ENCODED_ELT (expr, i), ctx, ht);
 	  break;
 	default:
 	  break;
Index: gcc/tree-loop-distribution.c
===================================================================
--- gcc/tree-loop-distribution.c	2017-11-29 11:06:34.810688336 +0000
+++ gcc/tree-loop-distribution.c	2017-12-06 14:50:45.558564477 +0000
@@ -944,13 +944,16 @@  const_with_all_bytes_same (tree val)
 	    return 0;
 	  break;
 	case VECTOR_CST:
-	  unsigned int j;
-	  for (j = 0; j < VECTOR_CST_NELTS (val); ++j)
-	    if (const_with_all_bytes_same (VECTOR_CST_ELT (val, j)))
-	      break;
-	  if (j == VECTOR_CST_NELTS (val))
-	    return 0;
-	  break;
+	  {
+	    unsigned int count = vector_cst_encoded_nelts (val);
+	    unsigned int j;
+	    for (j = 0; j < count; ++j)
+	      if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))
+		break;
+	    if (j == count)
+	      return 0;
+	    break;
+	  }
 	default:
 	  break;
 	}
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2017-12-06 14:49:10.295445836 +0000
+++ gcc/tree.c	2017-12-06 14:50:45.560564396 +0000
@@ -2338,13 +2338,9 @@  integer_zerop (const_tree expr)
       return (integer_zerop (TREE_REALPART (expr))
 	      && integer_zerop (TREE_IMAGPART (expr)));
     case VECTOR_CST:
-      {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	  if (!integer_zerop (VECTOR_CST_ELT (expr, i)))
-	    return false;
-	return true;
-      }
+      return (VECTOR_CST_NPATTERNS (expr) == 1
+	      && VECTOR_CST_DUPLICATE_P (expr)
+	      && integer_zerop (VECTOR_CST_ENCODED_ELT (expr, 0)));
     default:
       return false;
     }
@@ -2364,13 +2360,9 @@  integer_onep (const_tree expr)
       return (integer_onep (TREE_REALPART (expr))
 	      && integer_zerop (TREE_IMAGPART (expr)));
     case VECTOR_CST:
-      {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	  if (!integer_onep (VECTOR_CST_ELT (expr, i)))
-	    return false;
-	return true;
-      }
+      return (VECTOR_CST_NPATTERNS (expr) == 1
+	      && VECTOR_CST_DUPLICATE_P (expr)
+	      && integer_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
     default:
       return false;
     }
@@ -2401,13 +2393,9 @@  integer_all_onesp (const_tree expr)
     return 1;
 
   else if (TREE_CODE (expr) == VECTOR_CST)
-    {
-      unsigned i;
-      for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	if (!integer_all_onesp (VECTOR_CST_ELT (expr, i)))
-	  return 0;
-      return 1;
-    }
+    return (VECTOR_CST_NPATTERNS (expr) == 1
+	    && VECTOR_CST_DUPLICATE_P (expr)
+	    && integer_all_onesp (VECTOR_CST_ENCODED_ELT (expr, 0)));
 
   else if (TREE_CODE (expr) != INTEGER_CST)
     return 0;
@@ -2630,9 +2618,11 @@  real_zerop (const_tree expr)
 	     && real_zerop (TREE_IMAGPART (expr));
     case VECTOR_CST:
       {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	  if (!real_zerop (VECTOR_CST_ELT (expr, i)))
+	/* Don't simply check for a duplicate because the predicate
+	   accepts both +0.0 and -0.0.  */
+	unsigned count = vector_cst_encoded_nelts (expr);
+	for (unsigned int i = 0; i < count; ++i)
+	  if (!real_zerop (VECTOR_CST_ENCODED_ELT (expr, i)))
 	    return false;
 	return true;
       }
@@ -2657,13 +2647,9 @@  real_onep (const_tree expr)
       return real_onep (TREE_REALPART (expr))
 	     && real_zerop (TREE_IMAGPART (expr));
     case VECTOR_CST:
-      {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	  if (!real_onep (VECTOR_CST_ELT (expr, i)))
-	    return false;
-	return true;
-      }
+      return (VECTOR_CST_NPATTERNS (expr) == 1
+	      && VECTOR_CST_DUPLICATE_P (expr)
+	      && real_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
     default:
       return false;
     }
@@ -2684,13 +2670,9 @@  real_minus_onep (const_tree expr)
       return real_minus_onep (TREE_REALPART (expr))
 	     && real_zerop (TREE_IMAGPART (expr));
     case VECTOR_CST:
-      {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-	  if (!real_minus_onep (VECTOR_CST_ELT (expr, i)))
-	    return false;
-	return true;
-      }
+      return (VECTOR_CST_NPATTERNS (expr) == 1
+	      && VECTOR_CST_DUPLICATE_P (expr)
+	      && real_minus_onep (VECTOR_CST_ENCODED_ELT (expr, 0)));
     default:
       return false;
     }
@@ -7102,9 +7084,11 @@  add_expr (const_tree t, inchash::hash &h
       return;
     case VECTOR_CST:
       {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (t); ++i)
-	  inchash::add_expr (VECTOR_CST_ELT (t, i), hstate, flags);
+	hstate.add_int (VECTOR_CST_NPATTERNS (t));
+	hstate.add_int (VECTOR_CST_NELTS_PER_PATTERN (t));
+	unsigned int count = vector_cst_encoded_nelts (t);
+	for (unsigned int i = 0; i < count; ++i)
+	  inchash::add_expr (VECTOR_CST_ENCODED_ELT (t, i), hstate, flags);
 	return;
       }
     case SSA_NAME:
@@ -10431,13 +10415,9 @@  initializer_zerop (const_tree init)
 	    && ! REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (TREE_IMAGPART (init))));
 
     case VECTOR_CST:
-      {
-	unsigned i;
-	for (i = 0; i < VECTOR_CST_NELTS (init); ++i)
-	  if (!initializer_zerop (VECTOR_CST_ELT (init, i)))
-	    return false;
-	return true;
-      }
+      return (VECTOR_CST_NPATTERNS (init) == 1
+	      && VECTOR_CST_DUPLICATE_P (init)
+	      && initializer_zerop (VECTOR_CST_ENCODED_ELT (init, 0)));
 
     case CONSTRUCTOR:
       {
@@ -10486,12 +10466,9 @@  uniform_vector_p (const_tree vec)
 
   if (TREE_CODE (vec) == VECTOR_CST)
     {
-      first = VECTOR_CST_ELT (vec, 0);
-      for (i = 1; i < VECTOR_CST_NELTS (vec); ++i)
-	if (!operand_equal_p (first, VECTOR_CST_ELT (vec, i), 0))
-	  return NULL_TREE;
-
-      return first;
+      if (VECTOR_CST_NPATTERNS (vec) == 1 && VECTOR_CST_DUPLICATE_P (vec))
+	return VECTOR_CST_ENCODED_ELT (vec, 0);
+      return NULL_TREE;
     }
 
   else if (TREE_CODE (vec) == CONSTRUCTOR)
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2017-12-05 14:24:56.163946903 +0000
+++ gcc/varasm.c	2017-12-06 14:50:45.560564396 +0000
@@ -3007,13 +3007,11 @@  const_hash_1 (const tree exp)
 
     case VECTOR_CST:
       {
-	unsigned i;
-
-	hi = 7 + VECTOR_CST_NELTS (exp);
-
-	for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
-	  hi = hi * 563 + const_hash_1 (VECTOR_CST_ELT (exp, i));
-
+	hi = 7 + VECTOR_CST_NPATTERNS (exp);
+	hi = hi * 563 + VECTOR_CST_NELTS_PER_PATTERN (exp);
+	unsigned int count = vector_cst_encoded_nelts (exp);
+	for (unsigned int i = 0; i < count; ++i)
+	  hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i));
 	return hi;
       }
 
@@ -3151,14 +3149,18 @@  compare_constant (const tree t1, const t
 
     case VECTOR_CST:
       {
-	unsigned i;
+	if (VECTOR_CST_NPATTERNS (t1)
+	    != VECTOR_CST_NPATTERNS (t2))
+	  return 0;
 
-        if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))
+	if (VECTOR_CST_NELTS_PER_PATTERN (t1)
+	    != VECTOR_CST_NELTS_PER_PATTERN (t2))
 	  return 0;
 
-	for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
-	  if (!compare_constant (VECTOR_CST_ELT (t1, i),
-				 VECTOR_CST_ELT (t2, i)))
+	unsigned int count = vector_cst_encoded_nelts (t1);
+	for (unsigned int i = 0; i < count; ++i)
+	  if (!compare_constant (VECTOR_CST_ENCODED_ELT (t1, i),
+				 VECTOR_CST_ENCODED_ELT (t2, i)))
 	    return 0;
 
 	return 1;
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c	2017-12-05 14:24:55.073967105 +0000
+++ gcc/tree-ssa-ccp.c	2017-12-06 14:50:45.558564477 +0000
@@ -147,6 +147,7 @@  Free Software Foundation; either version
 #include "diagnostic-core.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "tree-vector-builder.h"
 
 /* Possible lattice values.  */
 typedef enum
@@ -465,11 +466,14 @@  valid_lattice_transition (ccp_prop_value
   else if (VECTOR_FLOAT_TYPE_P (type)
 	   && !HONOR_NANS (type))
     {
-      for (unsigned i = 0; i < VECTOR_CST_NELTS (old_val.value); ++i)
+      unsigned int count
+	= tree_vector_builder::binary_encoded_nelts (old_val.value,
+						     new_val.value);
+      for (unsigned int i = 0; i < count; ++i)
 	if (!REAL_VALUE_ISNAN
-	       (TREE_REAL_CST (VECTOR_CST_ELT (old_val.value, i)))
-	    && !operand_equal_p (VECTOR_CST_ELT (old_val.value, i),
-				 VECTOR_CST_ELT (new_val.value, i), 0))
+	       (TREE_REAL_CST (VECTOR_CST_ENCODED_ELT (old_val.value, i)))
+	    && !operand_equal_p (VECTOR_CST_ENCODED_ELT (old_val.value, i),
+				 VECTOR_CST_ENCODED_ELT (new_val.value, i), 0))
 	  return false;
       return true;
     }
Index: gcc/ipa-icf.c
===================================================================
--- gcc/ipa-icf.c	2017-11-29 11:06:34.810688336 +0000
+++ gcc/ipa-icf.c	2017-12-06 14:50:45.557564518 +0000
@@ -83,6 +83,7 @@  #define INCLUDE_LIST
 #include "ipa-icf.h"
 #include "stor-layout.h"
 #include "dbgcnt.h"
+#include "tree-vector-builder.h"
 
 using namespace ipa_icf_gimple;
 
@@ -2024,17 +2025,17 @@  sem_variable::equals (tree t1, tree t2)
 						&TREE_REAL_CST (t2)));
     case VECTOR_CST:
       {
-	unsigned i;
-
         if (VECTOR_CST_NELTS (t1) != VECTOR_CST_NELTS (t2))
           return return_false_with_msg ("VECTOR_CST nelts mismatch");
 
-	for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
-	  if (!sem_variable::equals (VECTOR_CST_ELT (t1, i),
-				     VECTOR_CST_ELT (t2, i)))
-	    return 0;
+	unsigned int count
+	  = tree_vector_builder::binary_encoded_nelts (t1, t2);
+	for (unsigned int i = 0; i < count; ++i)
+	  if (!sem_variable::equals (VECTOR_CST_ENCODED_ELT (t1, i),
+				     VECTOR_CST_ENCODED_ELT (t2, i)))
+	    return false;
 
-	return 1;
+	return true;
       }
     case ARRAY_REF:
     case ARRAY_RANGE_REF:
Index: gcc/print-tree.c
===================================================================
--- gcc/print-tree.c	2017-11-29 11:06:34.810688336 +0000
+++ gcc/print-tree.c	2017-12-06 14:50:45.558564477 +0000
@@ -761,24 +761,18 @@  print_node (FILE *file, const char *pref
 
 	case VECTOR_CST:
 	  {
-	    /* Big enough for 2 UINT_MAX plus the string below.  */
+	    /* Big enough for UINT_MAX plus the string below.  */
 	    char buf[32];
-	    unsigned i;
 
-	    for (i = 0; i < VECTOR_CST_NELTS (node); ++i)
+	    fprintf (file, " npatterns:%u nelts-per-pattern:%u",
+		     VECTOR_CST_NPATTERNS (node),
+		     VECTOR_CST_NELTS_PER_PATTERN (node));
+	    unsigned int count = vector_cst_encoded_nelts (node);
+	    for (unsigned int i = 0; i < count; ++i)
 	      {
-		unsigned j;
-		/* Coalesce the output of identical consecutive elements.  */
-		for (j = i + 1; j < VECTOR_CST_NELTS (node); j++)
-		  if (VECTOR_CST_ELT (node, j) != VECTOR_CST_ELT (node, i))
-		    break;
-		j--;
-		if (i == j)
-		  sprintf (buf, "elt:%u: ", i);
-		else
-		  sprintf (buf, "elt:%u...%u: ", i, j);
-		print_node (file, buf, VECTOR_CST_ELT (node, i), indent + 4);
-		i = j;
+		sprintf (buf, "elt:%u: ", i);
+		print_node (file, buf, VECTOR_CST_ENCODED_ELT (node, i),
+			    indent + 4);
 	      }
 	  }
 	  break;