gimple-match-head.c: Include vec-perm-indices.h.
authorRichard Biener <rguenther@suse.de>
Mon, 20 May 2019 10:33:54 +0000 (10:33 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 20 May 2019 10:33:54 +0000 (10:33 +0000)
2019-05-20  Richard Biener  <rguenther@suse.de>

* gimple-match-head.c: Include vec-perm-indices.h.
* generic-match-head.c: Likewise.
* fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h
is included.
* fold-const.c (fold_vec_perm): Export.
(fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR...
(match.pd): ...here.

From-SVN: r271404

gcc/ChangeLog
gcc/fold-const.c
gcc/fold-const.h
gcc/generic-match-head.c
gcc/gimple-match-head.c
gcc/match.pd

index 682d5f75e6c8fdc6fb145919e9cfeb90898f3beb..920ea6ffa6594feecd680c78dcccdb9d1e196e64 100644 (file)
@@ -1,3 +1,13 @@
+2019-05-20  Richard Biener  <rguenther@suse.de>
+
+       * gimple-match-head.c: Include vec-perm-indices.h.
+       * generic-match-head.c: Likewise.
+       * fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h
+       is included.
+       * fold-const.c (fold_vec_perm): Export.
+       (fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR...
+       (match.pd): ...here.
+
 2019-05-20  Jakub Jelinek  <jakub@redhat.com>
 
        * cfgloop.h (struct loop): Add simdlen member.
index c4257721cfee3e50cfb2d19d29c4f0dd721cdd9a..34448524050431cbbabde75093c37ed5693f9cec 100644 (file)
@@ -9015,7 +9015,7 @@ vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
    selector.  Return the folded VECTOR_CST or CONSTRUCTOR if successful,
    NULL_TREE otherwise.  */
 
-static tree
+tree
 fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel)
 {
   unsigned int i;
@@ -11763,7 +11763,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       return NULL_TREE;
 
     case VEC_PERM_EXPR:
-      if (TREE_CODE (arg2) == VECTOR_CST)
+      /* Perform constant folding of BIT_INSERT_EXPR.  */
+      if (TREE_CODE (arg2) == VECTOR_CST
+         && TREE_CODE (op0) == VECTOR_CST
+         && TREE_CODE (op1) == VECTOR_CST)
        {
          /* Build a vector of integers from the tree mask.  */
          vec_perm_builder builder;
@@ -11774,61 +11777,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
          bool single_arg = (op0 == op1);
          vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
-
-         /* Check for cases that fold to OP0 or OP1 in their original
-            element order.  */
-         if (sel.series_p (0, 1, 0, 1))
-           return op0;
-         if (sel.series_p (0, 1, nelts, 1))
-           return op1;
-
-         if (!single_arg)
-           {
-             if (sel.all_from_input_p (0))
-               op1 = op0;
-             else if (sel.all_from_input_p (1))
-               {
-                 op0 = op1;
-                 sel.rotate_inputs (1);
-               }
-           }
-
-         if ((TREE_CODE (op0) == VECTOR_CST
-              || TREE_CODE (op0) == CONSTRUCTOR)
-             && (TREE_CODE (op1) == VECTOR_CST
-                 || TREE_CODE (op1) == CONSTRUCTOR))
-           {
-             tree t = fold_vec_perm (type, op0, op1, sel);
-             if (t != NULL_TREE)
-               return t;
-           }
-
-         bool changed = (op0 == op1 && !single_arg);
-
-         /* Generate a canonical form of the selector.  */
-         if (arg2 == op2 && sel.encoding () != builder)
-           {
-             /* Some targets are deficient and fail to expand a single
-                argument permutation while still allowing an equivalent
-                2-argument version.  */
-             if (sel.ninputs () == 2
-                 || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
-               op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
-             else
-               {
-                 vec_perm_indices sel2 (builder, 2, nelts);
-                 if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
-                   op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel2);
-                 else
-                   /* Not directly supported with either encoding,
-                      so use the preferred form.  */
-                   op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
-               }
-             changed = true;
-           }
-
-         if (changed)
-           return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2);
+         return fold_vec_perm (type, op0, op1, sel);
        }
       return NULL_TREE;
 
index 049fee91876b0e7f7f846c3a466419121a866e2d..c4b7cbfbdba8805aa471b5e01e06949d87964066 100644 (file)
@@ -100,6 +100,9 @@ extern tree fold_bit_and_mask (tree, tree, enum tree_code,
                               tree, enum tree_code, tree, tree,
                               tree, enum tree_code, tree, tree, tree *);
 extern tree fold_read_from_constant_string (tree);
+#if GCC_VEC_PERN_INDICES_H
+extern tree fold_vec_perm (tree, tree, tree, const vec_perm_indices &);
+#endif
 extern bool wide_int_binop (wide_int &res, enum tree_code,
                            const wide_int &arg1, const wide_int &arg2,
                            signop, wi::overflow_type *);
index a46f375017b5ccd907dd3c2c5a7be64a96cb1f60..76fc99934816af0b1c6f303bb2fee0895b6ae842 100644 (file)
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "ssa.h"
 #include "cgraph.h"
+#include "vec-perm-indices.h"
 #include "fold-const.h"
 #include "stor-layout.h"
 #include "tree-dfa.h"
index bbbc0f2c28b15c941b53f4fb684b77bcd782cc35..f83f225617889c1cf8e6fe3f6f6f57d71f216f81 100644 (file)
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "ssa.h"
 #include "cgraph.h"
+#include "vec-perm-indices.h"
 #include "fold-const.h"
 #include "fold-const-call.h"
 #include "stor-layout.h"
index 29c94e01f7d6c973e96492b770a79b19d133a171..9ff52123cd9b93b171ec2b2297fa909c648e56ab 100644 (file)
@@ -5374,3 +5374,86 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       (bit_and:elt_type
        (BIT_FIELD_REF:elt_type @0 { size; } { pos; })
        { elt; })))))))
+
+(simplify
+ (vec_perm @0 @1 VECTOR_CST@2)
+ (with
+  {
+    tree op0 = @0, op1 = @1, op2 = @2;
+
+    /* Build a vector of integers from the tree mask.  */
+    vec_perm_builder builder;
+    if (!tree_to_vec_perm_builder (&builder, op2))
+      return NULL_TREE;
+
+    /* Create a vec_perm_indices for the integer vector.  */
+    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
+    bool single_arg = (op0 == op1);
+    vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
+  }
+  (if (sel.series_p (0, 1, 0, 1))
+   { op0; }
+   (if (sel.series_p (0, 1, nelts, 1))
+    { op1; }
+    (with
+     {
+       if (!single_arg)
+         {
+          if (sel.all_from_input_p (0))
+            op1 = op0;
+          else if (sel.all_from_input_p (1))
+            {
+              op0 = op1;
+              sel.rotate_inputs (1);
+            }
+         }
+       gassign *def;
+       tree cop0 = op0, cop1 = op1;
+       if (TREE_CODE (op0) == SSA_NAME
+           && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0)))
+          && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+        cop0 = gimple_assign_rhs1 (def);
+       if (TREE_CODE (op1) == SSA_NAME
+           && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op1)))
+          && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+        cop1 = gimple_assign_rhs1 (def);
+
+       tree t;
+    }
+    (if ((TREE_CODE (cop0) == VECTOR_CST
+         || TREE_CODE (cop0) == CONSTRUCTOR)
+        && (TREE_CODE (cop1) == VECTOR_CST
+            || TREE_CODE (cop1) == CONSTRUCTOR)
+        && (t = fold_vec_perm (type, cop0, cop1, sel)))
+     { t; }
+     (with
+      {
+       bool changed = (op0 == op1 && !single_arg);
+
+       /* Generate a canonical form of the selector.  */
+       if (sel.encoding () != builder)
+         {
+           /* Some targets are deficient and fail to expand a single
+              argument permutation while still allowing an equivalent
+              2-argument version.  */
+           tree oldop2 = op2;
+           if (sel.ninputs () == 2
+              || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
+             op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+           else
+             {
+               vec_perm_indices sel2 (builder, 2, nelts);
+               if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
+                 op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel2);
+               else
+                 /* Not directly supported with either encoding,
+                    so use the preferred form.  */
+                 op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+             }
+           /* Differences in the encoder do not necessarily mean
+              differences in the resulting vector.  */
+           changed = !operand_equal_p (op2, oldop2, 0);
+         }
+      }
+      (if (changed)
+       (vec_perm { op0; } { op1; } { op2; })))))))))